blob: 1435b15029751f6334079a8fbfc8dc6cb950c7f3 [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
Ewan D. Milne19c8ead2014-12-04 11:49:27 -050083#define TARGET_CHANGED_ASC 0x3f
84#define LUNS_CHANGED_ASCQ 0x0e
Douglas Gilbert22017ed2014-11-24 23:04:47 -050085#define INSUFF_RES_ASC 0x55
86#define INSUFF_RES_ASCQ 0x3
Douglas Gilbertcbf67842014-07-26 11:55:35 -040087#define POWER_ON_RESET_ASCQ 0x0
88#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */
89#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */
Douglas Gilbert22017ed2014-11-24 23:04:47 -050090#define CAPACITY_CHANGED_ASCQ 0x9
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#define SAVING_PARAMS_UNSUP 0x39
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050092#define TRANSPORT_PROBLEM 0x4b
Douglas Gilbertc65b1442006-06-06 00:11:24 -040093#define THRESHOLD_EXCEEDED 0x5d
94#define LOW_POWER_COND_ON 0x5e
Douglas Gilbert22017ed2014-11-24 23:04:47 -050095#define MISCOMPARE_VERIFY_ASC 0x1d
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050097/* Additional Sense Code Qualifier (ASCQ) */
98#define ACK_NAK_TO 0x3
99
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101/* Default values for driver parameters */
102#define DEF_NUM_HOST 1
103#define DEF_NUM_TGTS 1
104#define DEF_MAX_LUNS 1
105/* With these defaults, this driver will make 1 host with 1 target
106 * (id 0) containing 1 logical unit (lun 0). That is 1 device.
107 */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500108#define DEF_ATO 1
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400109#define DEF_DELAY 1 /* if > 0 unit is a jiffy */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110#define DEF_DEV_SIZE_MB 8
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500111#define DEF_DIF 0
112#define DEF_DIX 0
113#define DEF_D_SENSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#define DEF_EVERY_NTH 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500115#define DEF_FAKE_RW 0
116#define DEF_GUARD 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400117#define DEF_HOST_LOCK 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500118#define DEF_LBPU 0
119#define DEF_LBPWS 0
120#define DEF_LBPWS10 0
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600121#define DEF_LBPRZ 1
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500122#define DEF_LOWEST_ALIGNED 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400123#define DEF_NDELAY 0 /* if > 0 unit is a nanosecond */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500124#define DEF_NO_LUN_0 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125#define DEF_NUM_PARTS 0
126#define DEF_OPTS 0
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400127#define DEF_OPT_BLKS 64
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500128#define DEF_PHYSBLK_EXP 0
129#define DEF_PTYPE 0
Martin Pittd9867882012-09-06 12:04:33 +0200130#define DEF_REMOVABLE false
Douglas Gilberte46b0342014-08-05 12:21:53 +0200131#define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500132#define DEF_SECTOR_SIZE 512
133#define DEF_UNMAP_ALIGNMENT 0
134#define DEF_UNMAP_GRANULARITY 1
Martin K. Petersen60147592010-08-19 11:49:00 -0400135#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
136#define DEF_UNMAP_MAX_DESC 256
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500137#define DEF_VIRTUAL_GB 0
138#define DEF_VPD_USE_HOSTNO 1
139#define DEF_WRITESAME_LENGTH 0xFFFF
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500140#define DEF_STRICT 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400141#define DELAY_OVERRIDDEN -9999
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143/* bit mask values for scsi_debug_opts */
144#define SCSI_DEBUG_OPT_NOISE 1
145#define SCSI_DEBUG_OPT_MEDIUM_ERR 2
146#define SCSI_DEBUG_OPT_TIMEOUT 4
147#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500148#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500149#define SCSI_DEBUG_OPT_DIF_ERR 32
150#define SCSI_DEBUG_OPT_DIX_ERR 64
Martin K. Petersen18a4d0a2012-02-09 13:48:53 -0500151#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400152#define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100
153#define SCSI_DEBUG_OPT_Q_NOISE 0x200
154#define SCSI_DEBUG_OPT_ALL_TSF 0x400
155#define SCSI_DEBUG_OPT_RARE_TSF 0x800
156#define SCSI_DEBUG_OPT_N_WCE 0x1000
157#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000
158#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000
159#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160/* When "every_nth" > 0 then modulo "every_nth" commands:
161 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
162 * - a RECOVERED_ERROR is simulated on successful read and write
163 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500164 * - a TRANSPORT_ERROR is simulated on successful read and write
165 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 *
167 * When "every_nth" < 0 then after "- every_nth" commands:
168 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
169 * - a RECOVERED_ERROR is simulated on successful read and write
170 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500171 * - a TRANSPORT_ERROR is simulated on successful read and write
172 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 * This will continue until some other action occurs (e.g. the user
174 * writing a new value (other than -1 or 1) to every_nth via sysfs).
175 */
176
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400177/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
178 * priority order. In the subset implemented here lower numbers have higher
179 * priority. The UA numbers should be a sequence starting from 0 with
180 * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */
181#define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */
182#define SDEBUG_UA_BUS_RESET 1
183#define SDEBUG_UA_MODE_CHANGED 2
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500184#define SDEBUG_UA_CAPACITY_CHANGED 3
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500185#define SDEBUG_UA_LUNS_CHANGED 4
186#define SDEBUG_NUM_UAS 5
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400187
188/* for check_readiness() */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500189#define UAS_ONLY 1 /* check for UAs only */
190#define UAS_TUR 0 /* if no UAs then check if media access possible */
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400191
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
193 * sector on read commands: */
194#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -0500195#define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
198 * or "peripheral device" addressing (value 0) */
199#define SAM2_LUN_ADDRESS_METHOD 0
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400200#define SAM2_WLUN_REPORT_LUNS 0xc101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400202/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
203 * (for response) at one time. Can be reduced by max_queue option. Command
204 * responses are not queued when delay=0 and ndelay=0. The per-device
205 * DEF_CMD_PER_LUN can be changed via sysfs:
206 * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
207 * SCSI_DEBUG_CANQUEUE. */
208#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */
209#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
210#define DEF_CMD_PER_LUN 255
211
212#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
213#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
214#endif
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400215
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500216/* SCSI opcodes (first byte of cdb) mapped onto these indexes */
217enum sdeb_opcode_index {
218 SDEB_I_INVALID_OPCODE = 0,
219 SDEB_I_INQUIRY = 1,
220 SDEB_I_REPORT_LUNS = 2,
221 SDEB_I_REQUEST_SENSE = 3,
222 SDEB_I_TEST_UNIT_READY = 4,
223 SDEB_I_MODE_SENSE = 5, /* 6, 10 */
224 SDEB_I_MODE_SELECT = 6, /* 6, 10 */
225 SDEB_I_LOG_SENSE = 7,
226 SDEB_I_READ_CAPACITY = 8, /* 10; 16 is in SA_IN(16) */
227 SDEB_I_READ = 9, /* 6, 10, 12, 16 */
228 SDEB_I_WRITE = 10, /* 6, 10, 12, 16 */
229 SDEB_I_START_STOP = 11,
230 SDEB_I_SERV_ACT_IN = 12, /* 12, 16 */
231 SDEB_I_SERV_ACT_OUT = 13, /* 12, 16 */
232 SDEB_I_MAINT_IN = 14,
233 SDEB_I_MAINT_OUT = 15,
234 SDEB_I_VERIFY = 16, /* 10 only */
235 SDEB_I_VARIABLE_LEN = 17,
236 SDEB_I_RESERVE = 18, /* 6, 10 */
237 SDEB_I_RELEASE = 19, /* 6, 10 */
238 SDEB_I_ALLOW_REMOVAL = 20, /* PREVENT ALLOW MEDIUM REMOVAL */
239 SDEB_I_REZERO_UNIT = 21, /* REWIND in SSC */
240 SDEB_I_ATA_PT = 22, /* 12, 16 */
241 SDEB_I_SEND_DIAG = 23,
242 SDEB_I_UNMAP = 24,
243 SDEB_I_XDWRITEREAD = 25, /* 10 only */
244 SDEB_I_WRITE_BUFFER = 26,
245 SDEB_I_WRITE_SAME = 27, /* 10, 16 */
246 SDEB_I_SYNC_CACHE = 28, /* 10 only */
247 SDEB_I_COMP_WRITE = 29,
248 SDEB_I_LAST_ELEMENT = 30, /* keep this last */
249};
250
251static const unsigned char opcode_ind_arr[256] = {
252/* 0x0; 0x0->0x1f: 6 byte cdbs */
253 SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
254 0, 0, 0, 0,
255 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,
256 0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
257 SDEB_I_RELEASE,
258 0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,
259 SDEB_I_ALLOW_REMOVAL, 0,
260/* 0x20; 0x20->0x3f: 10 byte cdbs */
261 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0,
262 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY,
263 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0,
264 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0,
265/* 0x40; 0x40->0x5f: 10 byte cdbs */
266 0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0,
267 0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0,
268 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
269 SDEB_I_RELEASE,
270 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0,
271/* 0x60; 0x60->0x7d are reserved */
272 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
273 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
274 0, SDEB_I_VARIABLE_LEN,
275/* 0x80; 0x80->0x9f: 16 byte cdbs */
276 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
277 SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
278 0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
279 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN, SDEB_I_SERV_ACT_OUT,
280/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
281 SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
282 SDEB_I_MAINT_OUT, 0, 0, 0,
283 SDEB_I_READ, SDEB_I_SERV_ACT_OUT, SDEB_I_WRITE, SDEB_I_SERV_ACT_IN,
284 0, 0, 0, 0,
285 0, 0, 0, 0, 0, 0, 0, 0,
286 0, 0, 0, 0, 0, 0, 0, 0,
287/* 0xc0; 0xc0->0xff: vendor specific */
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
292};
293
294#define F_D_IN 1
295#define F_D_OUT 2
296#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */
297#define F_D_UNKN 8
298#define F_RL_WLUN_OK 0x10
299#define F_SKIP_UA 0x20
300#define F_DELAY_OVERR 0x40
301#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */
302#define F_SA_HIGH 0x100 /* as used by variable length cdbs */
303#define F_INV_OP 0x200
304#define F_FAKE_RW 0x400
305#define F_M_ACCESS 0x800 /* media access */
306
307#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
308#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
309#define FF_SA (F_SA_HIGH | F_SA_LOW)
310
311struct sdebug_dev_info;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500312static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
313static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
314static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
315static int resp_mode_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
316static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *);
317static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
318static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *);
319static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
320static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
321static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
322static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
323static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
324static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
325static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500326static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
327static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500328static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
329static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
330static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500331static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500332
333struct opcode_info_t {
334 u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
335 * for terminating element */
336 u8 opcode; /* if num_attached > 0, preferred */
337 u16 sa; /* service action */
338 u32 flags; /* OR-ed set of SDEB_F_* */
339 int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
340 const struct opcode_info_t *arrp; /* num_attached elements or NULL */
341 u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */
342 /* ignore cdb bytes after position 15 */
343};
344
345static const struct opcode_info_t msense_iarr[1] = {
346 {0, 0x1a, 0, F_D_IN, NULL, NULL,
347 {6, 0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
348};
349
350static const struct opcode_info_t mselect_iarr[1] = {
351 {0, 0x15, 0, F_D_OUT, NULL, NULL,
352 {6, 0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
353};
354
355static const struct opcode_info_t read_iarr[3] = {
356 {0, 0x28, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(10) */
357 {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
358 0, 0, 0, 0} },
359 {0, 0x8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL, /* READ(6) */
360 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
361 {0, 0xa8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(12) */
362 {12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
363 0xc7, 0, 0, 0, 0} },
364};
365
366static const struct opcode_info_t write_iarr[3] = {
367 {0, 0x2a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 10 */
368 {10, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
369 0, 0, 0, 0} },
370 {0, 0xa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 6 */
371 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
372 {0, 0xaa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 12 */
373 {12, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
374 0xc7, 0, 0, 0, 0} },
375};
376
377static const struct opcode_info_t sa_in_iarr[1] = {
378 {0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
379 {16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
380 0xff, 0xff, 0xff, 0, 0xc7} },
381};
382
383static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */
384 {0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_DIRECT_IO, resp_write_dt0,
385 NULL, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0xb, 0xfa,
386 0, 0xff, 0xff, 0xff, 0xff} }, /* WRITE(32) */
387};
388
389static const struct opcode_info_t maint_in_iarr[2] = {
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500390 {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500391 {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
392 0xc7, 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500393 {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500394 {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
395 0, 0} },
396};
397
398static const struct opcode_info_t write_same_iarr[1] = {
399 {0, 0x93, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_16, NULL,
400 {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
401 0xff, 0xff, 0xff, 0x1f, 0xc7} },
402};
403
404static const struct opcode_info_t reserve_iarr[1] = {
405 {0, 0x16, 0, F_D_OUT, NULL, NULL, /* RESERVE(6) */
406 {6, 0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
407};
408
409static const struct opcode_info_t release_iarr[1] = {
410 {0, 0x17, 0, F_D_OUT, NULL, NULL, /* RELEASE(6) */
411 {6, 0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
412};
413
414
415/* This array is accessed via SDEB_I_* values. Make sure all are mapped,
416 * plus the terminating elements for logic that scans this table such as
417 * REPORT SUPPORTED OPERATION CODES. */
418static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
419/* 0 */
420 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL,
421 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
422 {0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL,
423 {6, 0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
424 {0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL,
425 {12, 0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
426 0, 0} },
427 {0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL,
428 {6, 0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
429 {0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */
430 {6, 0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
431 {1, 0x5a, 0, F_D_IN, resp_mode_sense, msense_iarr,
432 {10, 0xf8, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
433 0} },
434 {1, 0x55, 0, F_D_OUT, resp_mode_select, mselect_iarr,
435 {10, 0xf1, 0, 0, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
436 {0, 0x4d, 0, F_D_IN, resp_log_sense, NULL,
437 {10, 0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0,
438 0, 0, 0} },
439 {0, 0x25, 0, F_D_IN, resp_readcap, NULL,
440 {10, 0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0,
441 0, 0} },
442 {3, 0x88, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, read_iarr,
443 {16, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
444 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* READ(16) */
445/* 10 */
446 {3, 0x8a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, write_iarr,
447 {16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
448 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* WRITE(16) */
449 {0, 0x1b, 0, 0, resp_start_stop, NULL, /* START STOP UNIT */
450 {6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
451 {1, 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_iarr,
452 {16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
453 0xff, 0xff, 0xff, 0x1, 0xc7} }, /* READ CAPACITY(16) */
454 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* SA OUT */
455 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
456 {2, 0xa3, 0xa, F_SA_LOW | F_D_IN, resp_report_tgtpgs, maint_in_iarr,
457 {12, 0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 0,
458 0} },
459 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */
460 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
461 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* VERIFY */
462 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
463 {1, 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_DIRECT_IO, resp_read_dt0,
464 vl_iarr, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0x9, 0xfe, 0,
465 0xff, 0xff, 0xff, 0xff} },/* VARIABLE LENGTH, READ(32) */
466 {1, 0x56, 0, F_D_OUT, NULL, reserve_iarr, /* RESERVE(10) */
467 {10, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
468 0} },
469 {1, 0x57, 0, F_D_OUT, NULL, release_iarr, /* RELEASE(10) */
470 {10, 0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
471 0} },
472/* 20 */
473 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ALLOW REMOVAL */
474 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
475 {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */
476 {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
477 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */
478 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
479 {0, 0x1d, F_D_OUT, 0, NULL, NULL, /* SEND DIAGNOSTIC */
480 {6, 0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
481 {0, 0x42, 0, F_D_OUT | FF_DIRECT_IO, resp_unmap, NULL, /* UNMAP */
482 {10, 0x1, 0, 0, 0, 0, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
483 {0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
484 NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
485 0, 0, 0, 0, 0, 0} },
486 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* WRITE_BUFFER */
487 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
488 {1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
489 write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
490 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
491 {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */
492 {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
493 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500494 {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500495 {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
496 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */
497
498/* 30 */
499 {0xff, 0, 0, 0, NULL, NULL, /* terminating element */
500 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
501};
502
Douglas Gilbert817fd662014-11-24 20:18:02 -0500503struct sdebug_scmd_extra_t {
504 bool inj_recovered;
505 bool inj_transport;
506 bool inj_dif;
507 bool inj_dix;
508 bool inj_short;
509};
510
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511static int scsi_debug_add_host = DEF_NUM_HOST;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500512static int scsi_debug_ato = DEF_ATO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513static int scsi_debug_delay = DEF_DELAY;
514static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500515static int scsi_debug_dif = DEF_DIF;
516static int scsi_debug_dix = DEF_DIX;
517static int scsi_debug_dsense = DEF_D_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518static int scsi_debug_every_nth = DEF_EVERY_NTH;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500519static int scsi_debug_fake_rw = DEF_FAKE_RW;
Akinobu Mita68aee7b2013-09-18 21:27:27 +0900520static unsigned int scsi_debug_guard = DEF_GUARD;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500521static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522static int scsi_debug_max_luns = DEF_MAX_LUNS;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400523static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400524static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */
525static int scsi_debug_ndelay = DEF_NDELAY;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400526static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500527static int scsi_debug_no_uld = 0;
528static int scsi_debug_num_parts = DEF_NUM_PARTS;
529static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400530static int scsi_debug_opt_blks = DEF_OPT_BLKS;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500531static int scsi_debug_opts = DEF_OPTS;
532static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
533static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
534static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
535static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
536static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
537static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
538static unsigned int scsi_debug_lbpu = DEF_LBPU;
539static unsigned int scsi_debug_lbpws = DEF_LBPWS;
540static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600541static unsigned int scsi_debug_lbprz = DEF_LBPRZ;
Martin K. Petersen60147592010-08-19 11:49:00 -0400542static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500543static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
544static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
545static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
546static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
Martin Pittd9867882012-09-06 12:04:33 +0200547static bool scsi_debug_removable = DEF_REMOVABLE;
Akinobu Mita0759c662014-02-26 22:57:04 +0900548static bool scsi_debug_clustering;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400549static bool scsi_debug_host_lock = DEF_HOST_LOCK;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500550static bool scsi_debug_strict = DEF_STRICT;
Douglas Gilbert817fd662014-11-24 20:18:02 -0500551static bool sdebug_any_injecting_opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400553static atomic_t sdebug_cmnd_count;
554static atomic_t sdebug_completions;
555static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
557#define DEV_READONLY(TGT) (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400559static unsigned int sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560static sector_t sdebug_capacity; /* in sectors */
561
562/* old BIOS stuff, kernel may get rid of them but some mode sense pages
563 may still need them */
564static int sdebug_heads; /* heads per disk */
565static int sdebug_cylinders_per; /* cylinders per surface */
566static int sdebug_sectors_per; /* sectors per cylinder */
567
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568#define SDEBUG_MAX_PARTS 4
569
Martin K. Petersen395cef02009-09-18 17:33:03 -0400570#define SCSI_DEBUG_MAX_CMD_LEN 32
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +0900571
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500572static unsigned int scsi_debug_lbp(void)
573{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400574 return ((0 == scsi_debug_fake_rw) &&
575 (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500576}
577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578struct sdebug_dev_info {
579 struct list_head dev_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 unsigned int channel;
581 unsigned int target;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200582 u64 lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400584 unsigned long uas_bm[1];
585 atomic_t num_in_q;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500586 char stopped; /* TODO: should be atomic */
587 bool used;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588};
589
590struct sdebug_host_info {
591 struct list_head host_list;
592 struct Scsi_Host *shost;
593 struct device dev;
594 struct list_head dev_info_list;
595};
596
597#define to_sdebug_host(d) \
598 container_of(d, struct sdebug_host_info, dev)
599
600static LIST_HEAD(sdebug_host_list);
601static DEFINE_SPINLOCK(sdebug_host_list_lock);
602
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400603
604struct sdebug_hrtimer { /* ... is derived from hrtimer */
605 struct hrtimer hrt; /* must be first element */
606 int qa_indx;
607};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609struct sdebug_queued_cmd {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400610 /* in_use flagged by a bit in queued_in_use_bm[] */
611 struct timer_list *cmnd_timerp;
612 struct tasklet_struct *tletp;
613 struct sdebug_hrtimer *sd_hrtp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 struct scsi_cmnd * a_cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615};
616static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400617static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620static unsigned char * fake_storep; /* ramdisk storage */
Akinobu Mitae18d8be2013-06-29 17:59:18 +0900621static struct sd_dif_tuple *dif_storep; /* protection info */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400622static void *map_storep; /* provisioning map */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
Martin K. Petersen44d92692009-10-15 14:45:27 -0400624static unsigned long map_size;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400625static int num_aborts;
626static int num_dev_resets;
627static int num_target_resets;
628static int num_bus_resets;
629static int num_host_resets;
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500630static int dix_writes;
631static int dix_reads;
632static int dif_errors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
634static DEFINE_SPINLOCK(queued_arr_lock);
635static DEFINE_RWLOCK(atomic_rw);
636
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400637static char sdebug_proc_name[] = MY_NAME;
638static const char *my_name = MY_NAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640static struct bus_type pseudo_lld_bus;
641
642static struct device_driver sdebug_driverfs_driver = {
643 .name = sdebug_proc_name,
644 .bus = &pseudo_lld_bus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645};
646
647static const int check_condition_result =
648 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
649
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500650static const int illegal_condition_result =
651 (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
652
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400653static const int device_qfull_result =
654 (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
655
656static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
657 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
658 0, 0, 0, 0};
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400659static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
660 0, 0, 0x2, 0x4b};
661static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
662 0, 0, 0x0, 0x0};
663
Akinobu Mita14faa942013-09-18 21:27:24 +0900664static void *fake_store(unsigned long long lba)
665{
666 lba = do_div(lba, sdebug_store_sectors);
667
668 return fake_storep + lba * scsi_debug_sector_size;
669}
670
671static struct sd_dif_tuple *dif_store(sector_t sector)
672{
673 sector = do_div(sector, sdebug_store_sectors);
674
675 return dif_storep + sector;
676}
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678static int sdebug_add_adapter(void);
679static void sdebug_remove_adapter(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900681static void sdebug_max_tgts_luns(void)
682{
683 struct sdebug_host_info *sdbg_host;
684 struct Scsi_Host *hpnt;
685
686 spin_lock(&sdebug_host_list_lock);
687 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
688 hpnt = sdbg_host->shost;
689 if ((hpnt->this_id >= 0) &&
690 (scsi_debug_num_tgts > hpnt->this_id))
691 hpnt->max_id = scsi_debug_num_tgts + 1;
692 else
693 hpnt->max_id = scsi_debug_num_tgts;
694 /* scsi_debug_max_luns; */
695 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
696 }
697 spin_unlock(&sdebug_host_list_lock);
698}
699
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500700enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
701
702/* Set in_bit to -1 to indicate no bit position of invalid field */
703static void
704mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
705 int in_byte, int in_bit)
706{
707 unsigned char *sbuff;
708 u8 sks[4];
709 int sl, asc;
710
711 sbuff = scp->sense_buffer;
712 if (!sbuff) {
713 sdev_printk(KERN_ERR, scp->device,
714 "%s: sense_buffer is NULL\n", __func__);
715 return;
716 }
717 asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
718 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
719 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
720 asc, 0);
721 memset(sks, 0, sizeof(sks));
722 sks[0] = 0x80;
723 if (c_d)
724 sks[0] |= 0x40;
725 if (in_bit >= 0) {
726 sks[0] |= 0x8;
727 sks[0] |= 0x7 & in_bit;
728 }
729 put_unaligned_be16(in_byte, sks + 1);
730 if (scsi_debug_dsense) {
731 sl = sbuff[7] + 8;
732 sbuff[7] = sl;
733 sbuff[sl] = 0x2;
734 sbuff[sl + 1] = 0x6;
735 memcpy(sbuff + sl + 4, sks, 3);
736 } else
737 memcpy(sbuff + 15, sks, 3);
738 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
739 sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq"
740 "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
741 my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
742}
743
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400744static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900745{
746 unsigned char *sbuff;
747
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400748 sbuff = scp->sense_buffer;
749 if (!sbuff) {
750 sdev_printk(KERN_ERR, scp->device,
751 "%s: sense_buffer is NULL\n", __func__);
752 return;
753 }
754 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900755
756 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
757
758 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400759 sdev_printk(KERN_INFO, scp->device,
760 "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
761 my_name, key, asc, asq);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900762}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500764static void
765mk_sense_invalid_opcode(struct scsi_cmnd *scp)
766{
767 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
768}
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
771{
772 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400773 if (0x1261 == cmd)
774 sdev_printk(KERN_INFO, dev,
775 "%s: BLKFLSBUF [0x1261]\n", __func__);
776 else if (0x5331 == cmd)
777 sdev_printk(KERN_INFO, dev,
778 "%s: CDROM_GET_CAPABILITY [0x5331]\n",
779 __func__);
780 else
781 sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
782 __func__, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 }
784 return -EINVAL;
785 /* return -ENOTTY; // correct return but upsets fdisk */
786}
787
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500788static void clear_luns_changed_on_target(struct sdebug_dev_info *devip)
789{
790 struct sdebug_host_info *sdhp;
791 struct sdebug_dev_info *dp;
792
793 spin_lock(&sdebug_host_list_lock);
794 list_for_each_entry(sdhp, &sdebug_host_list, host_list) {
795 list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) {
796 if ((devip->sdbg_host == dp->sdbg_host) &&
797 (devip->target == dp->target))
798 clear_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm);
799 }
800 }
801 spin_unlock(&sdebug_host_list_lock);
802}
803
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400804static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400805 struct sdebug_dev_info * devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400807 int k;
808 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
809
810 k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
811 if (k != SDEBUG_NUM_UAS) {
812 const char *cp = NULL;
813
814 switch (k) {
815 case SDEBUG_UA_POR:
816 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
817 UA_RESET_ASC, POWER_ON_RESET_ASCQ);
818 if (debug)
819 cp = "power on reset";
820 break;
821 case SDEBUG_UA_BUS_RESET:
822 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
823 UA_RESET_ASC, BUS_RESET_ASCQ);
824 if (debug)
825 cp = "bus reset";
826 break;
827 case SDEBUG_UA_MODE_CHANGED:
828 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
829 UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
830 if (debug)
831 cp = "mode parameters changed";
832 break;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500833 case SDEBUG_UA_CAPACITY_CHANGED:
834 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
835 UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
836 if (debug)
837 cp = "capacity data changed";
Ewan D. Milnef49accf2014-12-04 11:49:25 -0500838 break;
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500839 case SDEBUG_UA_LUNS_CHANGED:
840 /*
841 * SPC-3 behavior is to report a UNIT ATTENTION with
842 * ASC/ASCQ REPORTED LUNS DATA HAS CHANGED on every LUN
843 * on the target, until a REPORT LUNS command is
844 * received. SPC-4 behavior is to report it only once.
845 * NOTE: scsi_debug_scsi_level does not use the same
846 * values as struct scsi_device->scsi_level.
847 */
848 if (scsi_debug_scsi_level >= 6) /* SPC-4 and above */
849 clear_luns_changed_on_target(devip);
850 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
851 TARGET_CHANGED_ASC,
852 LUNS_CHANGED_ASCQ);
853 if (debug)
854 cp = "reported luns data has changed";
855 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400856 default:
857 pr_warn("%s: unexpected unit attention code=%d\n",
858 __func__, k);
859 if (debug)
860 cp = "unknown";
861 break;
862 }
863 clear_bit(k, devip->uas_bm);
864 if (debug)
865 sdev_printk(KERN_INFO, SCpnt->device,
866 "%s reports: Unit attention: %s\n",
867 my_name, cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return check_condition_result;
869 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400870 if ((UAS_TUR == uas_only) && devip->stopped) {
871 mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400872 0x2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400873 if (debug)
874 sdev_printk(KERN_INFO, SCpnt->device,
875 "%s reports: Not ready: %s\n", my_name,
876 "initializing command required");
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400877 return check_condition_result;
878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 return 0;
880}
881
882/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900883static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 int arr_len)
885{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900886 int act_len;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900887 struct scsi_data_buffer *sdb = scsi_in(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900889 if (!sdb->length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900891 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 return (DID_ERROR << 16);
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900893
894 act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
895 arr, arr_len);
Akinobu Mitaa4517512013-07-08 16:01:57 -0700896 sdb->resid = scsi_bufflen(scp) - act_len;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 return 0;
899}
900
901/* Returns number of bytes fetched into 'arr' or -1 if error. */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900902static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
903 int arr_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900905 if (!scsi_bufflen(scp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900907 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 return -1;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900909
910 return scsi_sg_copy_to_buffer(scp, arr, arr_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911}
912
913
914static const char * inq_vendor_id = "Linux ";
915static const char * inq_product_id = "scsi_debug ";
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400916static const char *inq_product_rev = "0184"; /* version less '.' */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400918/* Device identification VPD page. Returns number of bytes placed in arr */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200919static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
920 int target_dev_id, int dev_id_num,
921 const char * dev_id_str,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400922 int dev_id_str_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923{
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400924 int num, port_a;
925 char b[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400927 port_a = target_dev_id + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 /* T10 vendor identifier field format (faked) */
929 arr[0] = 0x2; /* ASCII */
930 arr[1] = 0x1;
931 arr[2] = 0x0;
932 memcpy(&arr[4], inq_vendor_id, 8);
933 memcpy(&arr[12], inq_product_id, 16);
934 memcpy(&arr[28], dev_id_str, dev_id_str_len);
935 num = 8 + 16 + dev_id_str_len;
936 arr[3] = num;
937 num += 4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400938 if (dev_id_num >= 0) {
939 /* NAA-5, Logical unit identifier (binary) */
940 arr[num++] = 0x1; /* binary (not necessarily sas) */
941 arr[num++] = 0x3; /* PIV=0, lu, naa */
942 arr[num++] = 0x0;
943 arr[num++] = 0x8;
944 arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */
945 arr[num++] = 0x33;
946 arr[num++] = 0x33;
947 arr[num++] = 0x30;
948 arr[num++] = (dev_id_num >> 24);
949 arr[num++] = (dev_id_num >> 16) & 0xff;
950 arr[num++] = (dev_id_num >> 8) & 0xff;
951 arr[num++] = dev_id_num & 0xff;
952 /* Target relative port number */
953 arr[num++] = 0x61; /* proto=sas, binary */
954 arr[num++] = 0x94; /* PIV=1, target port, rel port */
955 arr[num++] = 0x0; /* reserved */
956 arr[num++] = 0x4; /* length */
957 arr[num++] = 0x0; /* reserved */
958 arr[num++] = 0x0; /* reserved */
959 arr[num++] = 0x0;
960 arr[num++] = 0x1; /* relative port A */
961 }
962 /* NAA-5, Target port identifier */
963 arr[num++] = 0x61; /* proto=sas, binary */
964 arr[num++] = 0x93; /* piv=1, target port, naa */
965 arr[num++] = 0x0;
966 arr[num++] = 0x8;
967 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
968 arr[num++] = 0x22;
969 arr[num++] = 0x22;
970 arr[num++] = 0x20;
971 arr[num++] = (port_a >> 24);
972 arr[num++] = (port_a >> 16) & 0xff;
973 arr[num++] = (port_a >> 8) & 0xff;
974 arr[num++] = port_a & 0xff;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200975 /* NAA-5, Target port group identifier */
976 arr[num++] = 0x61; /* proto=sas, binary */
977 arr[num++] = 0x95; /* piv=1, target port group id */
978 arr[num++] = 0x0;
979 arr[num++] = 0x4;
980 arr[num++] = 0;
981 arr[num++] = 0;
982 arr[num++] = (port_group_id >> 8) & 0xff;
983 arr[num++] = port_group_id & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400984 /* NAA-5, Target device identifier */
985 arr[num++] = 0x61; /* proto=sas, binary */
986 arr[num++] = 0xa3; /* piv=1, target device, naa */
987 arr[num++] = 0x0;
988 arr[num++] = 0x8;
989 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
990 arr[num++] = 0x22;
991 arr[num++] = 0x22;
992 arr[num++] = 0x20;
993 arr[num++] = (target_dev_id >> 24);
994 arr[num++] = (target_dev_id >> 16) & 0xff;
995 arr[num++] = (target_dev_id >> 8) & 0xff;
996 arr[num++] = target_dev_id & 0xff;
997 /* SCSI name string: Target device identifier */
998 arr[num++] = 0x63; /* proto=sas, UTF-8 */
999 arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */
1000 arr[num++] = 0x0;
1001 arr[num++] = 24;
1002 memcpy(arr + num, "naa.52222220", 12);
1003 num += 12;
1004 snprintf(b, sizeof(b), "%08X", target_dev_id);
1005 memcpy(arr + num, b, 8);
1006 num += 8;
1007 memset(arr + num, 0, 4);
1008 num += 4;
1009 return num;
1010}
1011
1012
1013static unsigned char vpd84_data[] = {
1014/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
1015 0x22,0x22,0x22,0x0,0xbb,0x1,
1016 0x22,0x22,0x22,0x0,0xbb,0x2,
1017};
1018
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001019/* Software interface identification VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001020static int inquiry_evpd_84(unsigned char * arr)
1021{
1022 memcpy(arr, vpd84_data, sizeof(vpd84_data));
1023 return sizeof(vpd84_data);
1024}
1025
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001026/* Management network addresses VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001027static int inquiry_evpd_85(unsigned char * arr)
1028{
1029 int num = 0;
1030 const char * na1 = "https://www.kernel.org/config";
1031 const char * na2 = "http://www.kernel.org/log";
1032 int plen, olen;
1033
1034 arr[num++] = 0x1; /* lu, storage config */
1035 arr[num++] = 0x0; /* reserved */
1036 arr[num++] = 0x0;
1037 olen = strlen(na1);
1038 plen = olen + 1;
1039 if (plen % 4)
1040 plen = ((plen / 4) + 1) * 4;
1041 arr[num++] = plen; /* length, null termianted, padded */
1042 memcpy(arr + num, na1, olen);
1043 memset(arr + num + olen, 0, plen - olen);
1044 num += plen;
1045
1046 arr[num++] = 0x4; /* lu, logging */
1047 arr[num++] = 0x0; /* reserved */
1048 arr[num++] = 0x0;
1049 olen = strlen(na2);
1050 plen = olen + 1;
1051 if (plen % 4)
1052 plen = ((plen / 4) + 1) * 4;
1053 arr[num++] = plen; /* length, null terminated, padded */
1054 memcpy(arr + num, na2, olen);
1055 memset(arr + num + olen, 0, plen - olen);
1056 num += plen;
1057
1058 return num;
1059}
1060
1061/* SCSI ports VPD page */
1062static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
1063{
1064 int num = 0;
1065 int port_a, port_b;
1066
1067 port_a = target_dev_id + 1;
1068 port_b = port_a + 1;
1069 arr[num++] = 0x0; /* reserved */
1070 arr[num++] = 0x0; /* reserved */
1071 arr[num++] = 0x0;
1072 arr[num++] = 0x1; /* relative port 1 (primary) */
1073 memset(arr + num, 0, 6);
1074 num += 6;
1075 arr[num++] = 0x0;
1076 arr[num++] = 12; /* length tp descriptor */
1077 /* naa-5 target port identifier (A) */
1078 arr[num++] = 0x61; /* proto=sas, binary */
1079 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1080 arr[num++] = 0x0; /* reserved */
1081 arr[num++] = 0x8; /* length */
1082 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1083 arr[num++] = 0x22;
1084 arr[num++] = 0x22;
1085 arr[num++] = 0x20;
1086 arr[num++] = (port_a >> 24);
1087 arr[num++] = (port_a >> 16) & 0xff;
1088 arr[num++] = (port_a >> 8) & 0xff;
1089 arr[num++] = port_a & 0xff;
1090
1091 arr[num++] = 0x0; /* reserved */
1092 arr[num++] = 0x0; /* reserved */
1093 arr[num++] = 0x0;
1094 arr[num++] = 0x2; /* relative port 2 (secondary) */
1095 memset(arr + num, 0, 6);
1096 num += 6;
1097 arr[num++] = 0x0;
1098 arr[num++] = 12; /* length tp descriptor */
1099 /* naa-5 target port identifier (B) */
1100 arr[num++] = 0x61; /* proto=sas, binary */
1101 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1102 arr[num++] = 0x0; /* reserved */
1103 arr[num++] = 0x8; /* length */
1104 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1105 arr[num++] = 0x22;
1106 arr[num++] = 0x22;
1107 arr[num++] = 0x20;
1108 arr[num++] = (port_b >> 24);
1109 arr[num++] = (port_b >> 16) & 0xff;
1110 arr[num++] = (port_b >> 8) & 0xff;
1111 arr[num++] = port_b & 0xff;
1112
1113 return num;
1114}
1115
1116
1117static unsigned char vpd89_data[] = {
1118/* from 4th byte */ 0,0,0,0,
1119'l','i','n','u','x',' ',' ',' ',
1120'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ',
1121'1','2','3','4',
11220x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
11230xec,0,0,0,
11240x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0,
11250,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20,
11260x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33,
11270x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31,
11280x53,0x41,
11290x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
11300x20,0x20,
11310x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
11320x10,0x80,
11330,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0,
11340x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0,
11350x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0,
11360,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0,
11370x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40,
11380x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0,
11390,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,0,0,0,0,
11400,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11420,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11430x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42,
11440,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8,
11450xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe,
11460,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,0,
11470,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11490,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11500,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11510,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11520,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11530,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11540,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11550,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11560,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11570,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11580,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
1159};
1160
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001161/* ATA Information VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001162static int inquiry_evpd_89(unsigned char * arr)
1163{
1164 memcpy(arr, vpd89_data, sizeof(vpd89_data));
1165 return sizeof(vpd89_data);
1166}
1167
1168
1169static unsigned char vpdb0_data[] = {
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001170 /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
1171 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1172 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1173 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001174};
1175
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001176/* Block limits VPD page (SBC-3) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001177static int inquiry_evpd_b0(unsigned char * arr)
1178{
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001179 unsigned int gran;
1180
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001181 memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001182
1183 /* Optimal transfer length granularity */
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001184 gran = 1 << scsi_debug_physblk_exp;
1185 arr[2] = (gran >> 8) & 0xff;
1186 arr[3] = gran & 0xff;
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001187
1188 /* Maximum Transfer Length */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001189 if (sdebug_store_sectors > 0x400) {
1190 arr[4] = (sdebug_store_sectors >> 24) & 0xff;
1191 arr[5] = (sdebug_store_sectors >> 16) & 0xff;
1192 arr[6] = (sdebug_store_sectors >> 8) & 0xff;
1193 arr[7] = sdebug_store_sectors & 0xff;
1194 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001195
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001196 /* Optimal Transfer Length */
1197 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
1198
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001199 if (scsi_debug_lbpu) {
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001200 /* Maximum Unmap LBA Count */
Martin K. Petersen60147592010-08-19 11:49:00 -04001201 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001202
1203 /* Maximum Unmap Block Descriptor Count */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001204 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
1205 }
1206
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001207 /* Unmap Granularity Alignment */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001208 if (scsi_debug_unmap_alignment) {
1209 put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
1210 arr[28] |= 0x80; /* UGAVALID */
1211 }
1212
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001213 /* Optimal Unmap Granularity */
Martin K. Petersen60147592010-08-19 11:49:00 -04001214 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
1215
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001216 /* Maximum WRITE SAME Length */
1217 put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
1218
1219 return 0x3c; /* Mandatory page length for Logical Block Provisioning */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001220
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001221 return sizeof(vpdb0_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222}
1223
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001224/* Block device characteristics VPD page (SBC-3) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001225static int inquiry_evpd_b1(unsigned char *arr)
1226{
1227 memset(arr, 0, 0x3c);
1228 arr[0] = 0;
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001229 arr[1] = 1; /* non rotating medium (e.g. solid state) */
1230 arr[2] = 0;
1231 arr[3] = 5; /* less than 1.8" */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001232
1233 return 0x3c;
1234}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001236/* Logical block provisioning VPD page (SBC-3) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001237static int inquiry_evpd_b2(unsigned char *arr)
1238{
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001239 memset(arr, 0, 0x4);
Martin K. Petersen60147592010-08-19 11:49:00 -04001240 arr[0] = 0; /* threshold exponent */
1241
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001242 if (scsi_debug_lbpu)
Martin K. Petersen60147592010-08-19 11:49:00 -04001243 arr[1] = 1 << 7;
1244
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001245 if (scsi_debug_lbpws)
Martin K. Petersen60147592010-08-19 11:49:00 -04001246 arr[1] |= 1 << 6;
1247
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001248 if (scsi_debug_lbpws10)
1249 arr[1] |= 1 << 5;
1250
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001251 if (scsi_debug_lbprz)
1252 arr[1] |= 1 << 2;
1253
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001254 return 0x4;
Martin K. Petersen60147592010-08-19 11:49:00 -04001255}
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257#define SDEBUG_LONG_INQ_SZ 96
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001258#define SDEBUG_MAX_INQ_ARR_SZ 584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001260static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261{
1262 unsigned char pq_pdt;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001263 unsigned char * arr;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001264 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001265 int alloc_len, n, ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001266 bool have_wlun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
1268 alloc_len = (cmd[3] << 8) + cmd[4];
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001269 arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
1270 if (! arr)
1271 return DID_REQUEUE << 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001272 have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS);
1273 if (have_wlun)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001274 pq_pdt = 0x1e; /* present, wlun */
1275 else if (scsi_debug_no_lun_0 && (0 == devip->lun))
1276 pq_pdt = 0x7f; /* not present, no device type */
1277 else
1278 pq_pdt = (scsi_debug_ptype & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 arr[0] = pq_pdt;
1280 if (0x2 & cmd[1]) { /* CMDDT bit set */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001281 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001282 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 return check_condition_result;
1284 } else if (0x1 & cmd[1]) { /* EVPD bit set */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001285 int lu_id_num, port_group_id, target_dev_id, len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001286 char lu_id_str[6];
1287 int host_no = devip->sdbg_host->shost->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001289 port_group_id = (((host_no + 1) & 0x7f) << 8) +
1290 (devip->channel & 0x7f);
Douglas Gilbert23183912006-09-16 20:30:47 -04001291 if (0 == scsi_debug_vpd_use_hostno)
1292 host_no = 0;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001293 lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001294 (devip->target * 1000) + devip->lun);
1295 target_dev_id = ((host_no + 1) * 2000) +
1296 (devip->target * 1000) - 3;
1297 len = scnprintf(lu_id_str, 6, "%d", lu_id_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 if (0 == cmd[2]) { /* supported vital product data pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001299 arr[1] = cmd[2]; /*sanity */
1300 n = 4;
1301 arr[n++] = 0x0; /* this page */
1302 arr[n++] = 0x80; /* unit serial number */
1303 arr[n++] = 0x83; /* device identification */
1304 arr[n++] = 0x84; /* software interface ident. */
1305 arr[n++] = 0x85; /* management network addresses */
1306 arr[n++] = 0x86; /* extended inquiry */
1307 arr[n++] = 0x87; /* mode page policy */
1308 arr[n++] = 0x88; /* SCSI ports */
1309 arr[n++] = 0x89; /* ATA information */
1310 arr[n++] = 0xb0; /* Block limits (SBC) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001311 arr[n++] = 0xb1; /* Block characteristics (SBC) */
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001312 if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
1313 arr[n++] = 0xb2;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001314 arr[3] = n - 4; /* number of supported VPD pages */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 } else if (0x80 == cmd[2]) { /* unit serial number */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001316 arr[1] = cmd[2]; /*sanity */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 arr[3] = len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001318 memcpy(&arr[4], lu_id_str, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 } else if (0x83 == cmd[2]) { /* device identification */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001320 arr[1] = cmd[2]; /*sanity */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001321 arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
1322 target_dev_id, lu_id_num,
1323 lu_id_str, len);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001324 } else if (0x84 == cmd[2]) { /* Software interface ident. */
1325 arr[1] = cmd[2]; /*sanity */
1326 arr[3] = inquiry_evpd_84(&arr[4]);
1327 } else if (0x85 == cmd[2]) { /* Management network addresses */
1328 arr[1] = cmd[2]; /*sanity */
1329 arr[3] = inquiry_evpd_85(&arr[4]);
1330 } else if (0x86 == cmd[2]) { /* extended inquiry */
1331 arr[1] = cmd[2]; /*sanity */
1332 arr[3] = 0x3c; /* number of following entries */
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001333 if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
1334 arr[4] = 0x4; /* SPT: GRD_CHK:1 */
1335 else if (scsi_debug_dif)
1336 arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
1337 else
1338 arr[4] = 0x0; /* no protection stuff */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001339 arr[5] = 0x7; /* head of q, ordered + simple q's */
1340 } else if (0x87 == cmd[2]) { /* mode page policy */
1341 arr[1] = cmd[2]; /*sanity */
1342 arr[3] = 0x8; /* number of following entries */
1343 arr[4] = 0x2; /* disconnect-reconnect mp */
1344 arr[6] = 0x80; /* mlus, shared */
1345 arr[8] = 0x18; /* protocol specific lu */
1346 arr[10] = 0x82; /* mlus, per initiator port */
1347 } else if (0x88 == cmd[2]) { /* SCSI Ports */
1348 arr[1] = cmd[2]; /*sanity */
1349 arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
1350 } else if (0x89 == cmd[2]) { /* ATA information */
1351 arr[1] = cmd[2]; /*sanity */
1352 n = inquiry_evpd_89(&arr[4]);
1353 arr[2] = (n >> 8);
1354 arr[3] = (n & 0xff);
1355 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
1356 arr[1] = cmd[2]; /*sanity */
1357 arr[3] = inquiry_evpd_b0(&arr[4]);
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001358 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
1359 arr[1] = cmd[2]; /*sanity */
1360 arr[3] = inquiry_evpd_b1(&arr[4]);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001361 } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001362 arr[1] = cmd[2]; /*sanity */
1363 arr[3] = inquiry_evpd_b2(&arr[4]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001365 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001366 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 return check_condition_result;
1368 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001369 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001370 ret = fill_from_dev_buffer(scp, arr,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001371 min(len, SDEBUG_MAX_INQ_ARR_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001372 kfree(arr);
1373 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 }
1375 /* drops through here for a standard inquiry */
Martin Pittd9867882012-09-06 12:04:33 +02001376 arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 arr[2] = scsi_debug_scsi_level;
1378 arr[3] = 2; /* response_data_format==2 */
1379 arr[4] = SDEBUG_LONG_INQ_SZ - 5;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001380 arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001381 if (0 == scsi_debug_vpd_use_hostno)
1382 arr[5] = 0x10; /* claim: implicit TGPS */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001383 arr[6] = 0x10; /* claim: MultiP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001385 arr[7] = 0xa; /* claim: LINKED + CMDQUE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 memcpy(&arr[8], inq_vendor_id, 8);
1387 memcpy(&arr[16], inq_product_id, 16);
1388 memcpy(&arr[32], inq_product_rev, 4);
1389 /* version descriptors (2 bytes each) follow */
Douglas Gilberte46b0342014-08-05 12:21:53 +02001390 arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */
1391 arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001392 n = 62;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 if (scsi_debug_ptype == 0) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001394 arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 } else if (scsi_debug_ptype == 1) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001396 arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 }
Douglas Gilberte46b0342014-08-05 12:21:53 +02001398 arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001399 ret = fill_from_dev_buffer(scp, arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 min(alloc_len, SDEBUG_LONG_INQ_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001401 kfree(arr);
1402 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403}
1404
1405static int resp_requests(struct scsi_cmnd * scp,
1406 struct sdebug_dev_info * devip)
1407{
1408 unsigned char * sbuff;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001409 unsigned char *cmd = scp->cmnd;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001410 unsigned char arr[SCSI_SENSE_BUFFERSIZE];
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001411 bool dsense, want_dsense;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 int len = 18;
1413
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001414 memset(arr, 0, sizeof(arr));
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001415 dsense = !!(cmd[1] & 1);
1416 want_dsense = dsense || scsi_debug_dsense;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001417 sbuff = scp->sense_buffer;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001418 if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001419 if (dsense) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001420 arr[0] = 0x72;
1421 arr[1] = 0x0; /* NO_SENSE in sense_key */
1422 arr[2] = THRESHOLD_EXCEEDED;
1423 arr[3] = 0xff; /* TEST set and MRIE==6 */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001424 len = 8;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001425 } else {
1426 arr[0] = 0x70;
1427 arr[2] = 0x0; /* NO_SENSE in sense_key */
1428 arr[7] = 0xa; /* 18 byte sense buffer */
1429 arr[12] = THRESHOLD_EXCEEDED;
1430 arr[13] = 0xff; /* TEST set and MRIE==6 */
1431 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001432 } else {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001433 memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001434 if (arr[0] >= 0x70 && dsense == scsi_debug_dsense)
1435 ; /* have sense and formats match */
1436 else if (arr[0] <= 0x70) {
1437 if (dsense) {
1438 memset(arr, 0, 8);
1439 arr[0] = 0x72;
1440 len = 8;
1441 } else {
1442 memset(arr, 0, 18);
1443 arr[0] = 0x70;
1444 arr[7] = 0xa;
1445 }
1446 } else if (dsense) {
1447 memset(arr, 0, 8);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001448 arr[0] = 0x72;
1449 arr[1] = sbuff[2]; /* sense key */
1450 arr[2] = sbuff[12]; /* asc */
1451 arr[3] = sbuff[13]; /* ascq */
1452 len = 8;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001453 } else {
1454 memset(arr, 0, 18);
1455 arr[0] = 0x70;
1456 arr[2] = sbuff[1];
1457 arr[7] = 0xa;
1458 arr[12] = sbuff[1];
1459 arr[13] = sbuff[3];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001460 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001461
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001462 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001463 mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 return fill_from_dev_buffer(scp, arr, len);
1465}
1466
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001467static int resp_start_stop(struct scsi_cmnd * scp,
1468 struct sdebug_dev_info * devip)
1469{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001470 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001471 int power_cond, start;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001472
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001473 power_cond = (cmd[4] & 0xf0) >> 4;
1474 if (power_cond) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001475 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001476 return check_condition_result;
1477 }
1478 start = cmd[4] & 1;
1479 if (start == devip->stopped)
1480 devip->stopped = !start;
1481 return 0;
1482}
1483
FUJITA Tomonori28898872008-03-30 00:59:55 +09001484static sector_t get_sdebug_capacity(void)
1485{
1486 if (scsi_debug_virtual_gb > 0)
Douglas Gilbert5447ed62010-04-25 12:30:23 +02001487 return (sector_t)scsi_debug_virtual_gb *
1488 (1073741824 / scsi_debug_sector_size);
FUJITA Tomonori28898872008-03-30 00:59:55 +09001489 else
1490 return sdebug_store_sectors;
1491}
1492
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493#define SDEBUG_READCAP_ARR_SZ 8
1494static int resp_readcap(struct scsi_cmnd * scp,
1495 struct sdebug_dev_info * devip)
1496{
1497 unsigned char arr[SDEBUG_READCAP_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001498 unsigned int capac;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001500 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001501 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001503 if (sdebug_capacity < 0xffffffff) {
1504 capac = (unsigned int)sdebug_capacity - 1;
1505 arr[0] = (capac >> 24);
1506 arr[1] = (capac >> 16) & 0xff;
1507 arr[2] = (capac >> 8) & 0xff;
1508 arr[3] = capac & 0xff;
1509 } else {
1510 arr[0] = 0xff;
1511 arr[1] = 0xff;
1512 arr[2] = 0xff;
1513 arr[3] = 0xff;
1514 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001515 arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
1516 arr[7] = scsi_debug_sector_size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
1518}
1519
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001520#define SDEBUG_READCAP16_ARR_SZ 32
1521static int resp_readcap16(struct scsi_cmnd * scp,
1522 struct sdebug_dev_info * devip)
1523{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001524 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001525 unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
1526 unsigned long long capac;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001527 int k, alloc_len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001528
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001529 alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
1530 + cmd[13]);
1531 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001532 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001533 memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
1534 capac = sdebug_capacity - 1;
1535 for (k = 0; k < 8; ++k, capac >>= 8)
1536 arr[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001537 arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
1538 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
1539 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
1540 arr[11] = scsi_debug_sector_size & 0xff;
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001541 arr[13] = scsi_debug_physblk_exp & 0xf;
1542 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
Martin K. Petersen44d92692009-10-15 14:45:27 -04001543
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001544 if (scsi_debug_lbp()) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001545 arr[14] |= 0x80; /* LBPME */
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001546 if (scsi_debug_lbprz)
1547 arr[14] |= 0x40; /* LBPRZ */
1548 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001549
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001550 arr[15] = scsi_debug_lowest_aligned & 0xff;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001551
1552 if (scsi_debug_dif) {
1553 arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
1554 arr[12] |= 1; /* PROT_EN */
1555 }
1556
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001557 return fill_from_dev_buffer(scp, arr,
1558 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
1559}
1560
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001561#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
1562
1563static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1564 struct sdebug_dev_info * devip)
1565{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001566 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001567 unsigned char * arr;
1568 int host_no = devip->sdbg_host->shost->host_no;
1569 int n, ret, alen, rlen;
1570 int port_group_a, port_group_b, port_a, port_b;
1571
1572 alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
1573 + cmd[9]);
1574
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001575 arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
1576 if (! arr)
1577 return DID_REQUEUE << 16;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001578 /*
1579 * EVPD page 0x88 states we have two ports, one
1580 * real and a fake port with no device connected.
1581 * So we create two port groups with one port each
1582 * and set the group with port B to unavailable.
1583 */
1584 port_a = 0x1; /* relative port A */
1585 port_b = 0x2; /* relative port B */
1586 port_group_a = (((host_no + 1) & 0x7f) << 8) +
1587 (devip->channel & 0x7f);
1588 port_group_b = (((host_no + 1) & 0x7f) << 8) +
1589 (devip->channel & 0x7f) + 0x80;
1590
1591 /*
1592 * The asymmetric access state is cycled according to the host_id.
1593 */
1594 n = 4;
1595 if (0 == scsi_debug_vpd_use_hostno) {
1596 arr[n++] = host_no % 3; /* Asymm access state */
1597 arr[n++] = 0x0F; /* claim: all states are supported */
1598 } else {
1599 arr[n++] = 0x0; /* Active/Optimized path */
1600 arr[n++] = 0x01; /* claim: only support active/optimized paths */
1601 }
1602 arr[n++] = (port_group_a >> 8) & 0xff;
1603 arr[n++] = port_group_a & 0xff;
1604 arr[n++] = 0; /* Reserved */
1605 arr[n++] = 0; /* Status code */
1606 arr[n++] = 0; /* Vendor unique */
1607 arr[n++] = 0x1; /* One port per group */
1608 arr[n++] = 0; /* Reserved */
1609 arr[n++] = 0; /* Reserved */
1610 arr[n++] = (port_a >> 8) & 0xff;
1611 arr[n++] = port_a & 0xff;
1612 arr[n++] = 3; /* Port unavailable */
1613 arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
1614 arr[n++] = (port_group_b >> 8) & 0xff;
1615 arr[n++] = port_group_b & 0xff;
1616 arr[n++] = 0; /* Reserved */
1617 arr[n++] = 0; /* Status code */
1618 arr[n++] = 0; /* Vendor unique */
1619 arr[n++] = 0x1; /* One port per group */
1620 arr[n++] = 0; /* Reserved */
1621 arr[n++] = 0; /* Reserved */
1622 arr[n++] = (port_b >> 8) & 0xff;
1623 arr[n++] = port_b & 0xff;
1624
1625 rlen = n - 4;
1626 arr[0] = (rlen >> 24) & 0xff;
1627 arr[1] = (rlen >> 16) & 0xff;
1628 arr[2] = (rlen >> 8) & 0xff;
1629 arr[3] = rlen & 0xff;
1630
1631 /*
1632 * Return the smallest value of either
1633 * - The allocated length
1634 * - The constructed command length
1635 * - The maximum array size
1636 */
1637 rlen = min(alen,n);
1638 ret = fill_from_dev_buffer(scp, arr,
1639 min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
1640 kfree(arr);
1641 return ret;
1642}
1643
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001644static int
1645resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1646{
1647 bool rctd;
1648 u8 reporting_opts, req_opcode, sdeb_i, supp;
1649 u16 req_sa, u;
1650 u32 alloc_len, a_len;
1651 int k, offset, len, errsts, count, bump, na;
1652 const struct opcode_info_t *oip;
1653 const struct opcode_info_t *r_oip;
1654 u8 *arr;
1655 u8 *cmd = scp->cmnd;
1656
1657 rctd = !!(cmd[2] & 0x80);
1658 reporting_opts = cmd[2] & 0x7;
1659 req_opcode = cmd[3];
1660 req_sa = get_unaligned_be16(cmd + 4);
1661 alloc_len = get_unaligned_be32(cmd + 6);
1662 if (alloc_len < 4 && alloc_len > 0xffff) {
1663 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1664 return check_condition_result;
1665 }
1666 if (alloc_len > 8192)
1667 a_len = 8192;
1668 else
1669 a_len = alloc_len;
1670 arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_KERNEL);
1671 if (NULL == arr) {
1672 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
1673 INSUFF_RES_ASCQ);
1674 return check_condition_result;
1675 }
1676 switch (reporting_opts) {
1677 case 0: /* all commands */
1678 /* count number of commands */
1679 for (count = 0, oip = opcode_info_arr;
1680 oip->num_attached != 0xff; ++oip) {
1681 if (F_INV_OP & oip->flags)
1682 continue;
1683 count += (oip->num_attached + 1);
1684 }
1685 bump = rctd ? 20 : 8;
1686 put_unaligned_be32(count * bump, arr);
1687 for (offset = 4, oip = opcode_info_arr;
1688 oip->num_attached != 0xff && offset < a_len; ++oip) {
1689 if (F_INV_OP & oip->flags)
1690 continue;
1691 na = oip->num_attached;
1692 arr[offset] = oip->opcode;
1693 put_unaligned_be16(oip->sa, arr + offset + 2);
1694 if (rctd)
1695 arr[offset + 5] |= 0x2;
1696 if (FF_SA & oip->flags)
1697 arr[offset + 5] |= 0x1;
1698 put_unaligned_be16(oip->len_mask[0], arr + offset + 6);
1699 if (rctd)
1700 put_unaligned_be16(0xa, arr + offset + 8);
1701 r_oip = oip;
1702 for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {
1703 if (F_INV_OP & oip->flags)
1704 continue;
1705 offset += bump;
1706 arr[offset] = oip->opcode;
1707 put_unaligned_be16(oip->sa, arr + offset + 2);
1708 if (rctd)
1709 arr[offset + 5] |= 0x2;
1710 if (FF_SA & oip->flags)
1711 arr[offset + 5] |= 0x1;
1712 put_unaligned_be16(oip->len_mask[0],
1713 arr + offset + 6);
1714 if (rctd)
1715 put_unaligned_be16(0xa,
1716 arr + offset + 8);
1717 }
1718 oip = r_oip;
1719 offset += bump;
1720 }
1721 break;
1722 case 1: /* one command: opcode only */
1723 case 2: /* one command: opcode plus service action */
1724 case 3: /* one command: if sa==0 then opcode only else opcode+sa */
1725 sdeb_i = opcode_ind_arr[req_opcode];
1726 oip = &opcode_info_arr[sdeb_i];
1727 if (F_INV_OP & oip->flags) {
1728 supp = 1;
1729 offset = 4;
1730 } else {
1731 if (1 == reporting_opts) {
1732 if (FF_SA & oip->flags) {
1733 mk_sense_invalid_fld(scp, SDEB_IN_CDB,
1734 2, 2);
1735 kfree(arr);
1736 return check_condition_result;
1737 }
1738 req_sa = 0;
1739 } else if (2 == reporting_opts &&
1740 0 == (FF_SA & oip->flags)) {
1741 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
1742 kfree(arr); /* point at requested sa */
1743 return check_condition_result;
1744 }
1745 if (0 == (FF_SA & oip->flags) &&
1746 req_opcode == oip->opcode)
1747 supp = 3;
1748 else if (0 == (FF_SA & oip->flags)) {
1749 na = oip->num_attached;
1750 for (k = 0, oip = oip->arrp; k < na;
1751 ++k, ++oip) {
1752 if (req_opcode == oip->opcode)
1753 break;
1754 }
1755 supp = (k >= na) ? 1 : 3;
1756 } else if (req_sa != oip->sa) {
1757 na = oip->num_attached;
1758 for (k = 0, oip = oip->arrp; k < na;
1759 ++k, ++oip) {
1760 if (req_sa == oip->sa)
1761 break;
1762 }
1763 supp = (k >= na) ? 1 : 3;
1764 } else
1765 supp = 3;
1766 if (3 == supp) {
1767 u = oip->len_mask[0];
1768 put_unaligned_be16(u, arr + 2);
1769 arr[4] = oip->opcode;
1770 for (k = 1; k < u; ++k)
1771 arr[4 + k] = (k < 16) ?
1772 oip->len_mask[k] : 0xff;
1773 offset = 4 + u;
1774 } else
1775 offset = 4;
1776 }
1777 arr[1] = (rctd ? 0x80 : 0) | supp;
1778 if (rctd) {
1779 put_unaligned_be16(0xa, arr + offset);
1780 offset += 12;
1781 }
1782 break;
1783 default:
1784 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2);
1785 kfree(arr);
1786 return check_condition_result;
1787 }
1788 offset = (offset < a_len) ? offset : a_len;
1789 len = (offset < alloc_len) ? offset : alloc_len;
1790 errsts = fill_from_dev_buffer(scp, arr, len);
1791 kfree(arr);
1792 return errsts;
1793}
1794
1795static int
1796resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1797{
1798 bool repd;
1799 u32 alloc_len, len;
1800 u8 arr[16];
1801 u8 *cmd = scp->cmnd;
1802
1803 memset(arr, 0, sizeof(arr));
1804 repd = !!(cmd[2] & 0x80);
1805 alloc_len = get_unaligned_be32(cmd + 6);
1806 if (alloc_len < 4) {
1807 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1808 return check_condition_result;
1809 }
1810 arr[0] = 0xc8; /* ATS | ATSS | LURS */
1811 arr[1] = 0x1; /* ITNRS */
1812 if (repd) {
1813 arr[3] = 0xc;
1814 len = 16;
1815 } else
1816 len = 4;
1817
1818 len = (len < alloc_len) ? len : alloc_len;
1819 return fill_from_dev_buffer(scp, arr, len);
1820}
1821
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822/* <<Following mode page info copied from ST318451LW>> */
1823
1824static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
1825{ /* Read-Write Error Recovery page for mode_sense */
1826 unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1827 5, 0, 0xff, 0xff};
1828
1829 memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1830 if (1 == pcontrol)
1831 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1832 return sizeof(err_recov_pg);
1833}
1834
1835static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
1836{ /* Disconnect-Reconnect page for mode_sense */
1837 unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1838 0, 0, 0, 0, 0, 0, 0, 0};
1839
1840 memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1841 if (1 == pcontrol)
1842 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1843 return sizeof(disconnect_pg);
1844}
1845
1846static int resp_format_pg(unsigned char * p, int pcontrol, int target)
1847{ /* Format device page for mode_sense */
Martin K. Petersen597136a2008-06-05 00:12:59 -04001848 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1849 0, 0, 0, 0, 0, 0, 0, 0,
1850 0, 0, 0, 0, 0x40, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
Martin K. Petersen597136a2008-06-05 00:12:59 -04001852 memcpy(p, format_pg, sizeof(format_pg));
1853 p[10] = (sdebug_sectors_per >> 8) & 0xff;
1854 p[11] = sdebug_sectors_per & 0xff;
1855 p[12] = (scsi_debug_sector_size >> 8) & 0xff;
1856 p[13] = scsi_debug_sector_size & 0xff;
Martin Pittd9867882012-09-06 12:04:33 +02001857 if (scsi_debug_removable)
Martin K. Petersen597136a2008-06-05 00:12:59 -04001858 p[20] |= 0x20; /* should agree with INQUIRY */
1859 if (1 == pcontrol)
1860 memset(p + 2, 0, sizeof(format_pg) - 2);
1861 return sizeof(format_pg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862}
1863
1864static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
1865{ /* Caching page for mode_sense */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001866 unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
1867 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1868 unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1870
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001871 if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
1872 caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 memcpy(p, caching_pg, sizeof(caching_pg));
1874 if (1 == pcontrol)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001875 memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg));
1876 else if (2 == pcontrol)
1877 memcpy(p, d_caching_pg, sizeof(d_caching_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 return sizeof(caching_pg);
1879}
1880
1881static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
1882{ /* Control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001883 unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
1884 0, 0, 0, 0};
1885 unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 0, 0, 0x2, 0x4b};
1887
1888 if (scsi_debug_dsense)
1889 ctrl_m_pg[2] |= 0x4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001890 else
1891 ctrl_m_pg[2] &= ~0x4;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001892
1893 if (scsi_debug_ato)
1894 ctrl_m_pg[5] |= 0x80; /* ATO=1 */
1895
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1897 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001898 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
1899 else if (2 == pcontrol)
1900 memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 return sizeof(ctrl_m_pg);
1902}
1903
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001904
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
1906{ /* Informational Exceptions control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001907 unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0,
1908 0, 0, 0x0, 0x0};
1909 unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1910 0, 0, 0x0, 0x0};
1911
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1913 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001914 memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg));
1915 else if (2 == pcontrol)
1916 memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 return sizeof(iec_m_pg);
1918}
1919
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001920static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target)
1921{ /* SAS SSP mode page - short format for mode_sense */
1922 unsigned char sas_sf_m_pg[] = {0x19, 0x6,
1923 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0};
1924
1925 memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg));
1926 if (1 == pcontrol)
1927 memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2);
1928 return sizeof(sas_sf_m_pg);
1929}
1930
1931
1932static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
1933 int target_dev_id)
1934{ /* SAS phy control and discover mode page for mode_sense */
1935 unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
1936 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
1937 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1938 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1939 0x2, 0, 0, 0, 0, 0, 0, 0,
1940 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1941 0, 0, 0, 0, 0, 0, 0, 0,
1942 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
1943 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1944 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1945 0x3, 0, 0, 0, 0, 0, 0, 0,
1946 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1947 0, 0, 0, 0, 0, 0, 0, 0,
1948 };
1949 int port_a, port_b;
1950
1951 port_a = target_dev_id + 1;
1952 port_b = port_a + 1;
1953 memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
1954 p[20] = (port_a >> 24);
1955 p[21] = (port_a >> 16) & 0xff;
1956 p[22] = (port_a >> 8) & 0xff;
1957 p[23] = port_a & 0xff;
1958 p[48 + 20] = (port_b >> 24);
1959 p[48 + 21] = (port_b >> 16) & 0xff;
1960 p[48 + 22] = (port_b >> 8) & 0xff;
1961 p[48 + 23] = port_b & 0xff;
1962 if (1 == pcontrol)
1963 memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
1964 return sizeof(sas_pcd_m_pg);
1965}
1966
1967static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
1968{ /* SAS SSP shared protocol specific port mode subpage */
1969 unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0,
1970 0, 0, 0, 0, 0, 0, 0, 0,
1971 };
1972
1973 memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg));
1974 if (1 == pcontrol)
1975 memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4);
1976 return sizeof(sas_sha_m_pg);
1977}
1978
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979#define SDEBUG_MAX_MSENSE_SZ 256
1980
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001981static int
1982resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983{
Douglas Gilbert23183912006-09-16 20:30:47 -04001984 unsigned char dbd, llbaa;
1985 int pcontrol, pcode, subpcode, bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 unsigned char dev_spec;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001987 int k, alloc_len, msense_6, offset, len, target_dev_id;
1988 int target = scp->device->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 unsigned char * ap;
1990 unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001991 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Douglas Gilbert23183912006-09-16 20:30:47 -04001993 dbd = !!(cmd[1] & 0x8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 pcontrol = (cmd[2] & 0xc0) >> 6;
1995 pcode = cmd[2] & 0x3f;
1996 subpcode = cmd[3];
1997 msense_6 = (MODE_SENSE == cmd[0]);
Douglas Gilbert23183912006-09-16 20:30:47 -04001998 llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
1999 if ((0 == scsi_debug_ptype) && (0 == dbd))
2000 bd_len = llbaa ? 16 : 8;
2001 else
2002 bd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
2004 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
2005 if (0x3 == pcontrol) { /* Saving values not supported */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002006 mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 return check_condition_result;
2008 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002009 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
2010 (devip->target * 1000) - 3;
Douglas Gilbert23183912006-09-16 20:30:47 -04002011 /* set DPOFUA bit for disks */
2012 if (0 == scsi_debug_ptype)
2013 dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
2014 else
2015 dev_spec = 0x0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 if (msense_6) {
2017 arr[2] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04002018 arr[3] = bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 offset = 4;
2020 } else {
2021 arr[3] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04002022 if (16 == bd_len)
2023 arr[4] = 0x1; /* set LONGLBA bit */
2024 arr[7] = bd_len; /* assume 255 or less */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 offset = 8;
2026 }
2027 ap = arr + offset;
FUJITA Tomonori28898872008-03-30 00:59:55 +09002028 if ((bd_len > 0) && (!sdebug_capacity))
2029 sdebug_capacity = get_sdebug_capacity();
2030
Douglas Gilbert23183912006-09-16 20:30:47 -04002031 if (8 == bd_len) {
2032 if (sdebug_capacity > 0xfffffffe) {
2033 ap[0] = 0xff;
2034 ap[1] = 0xff;
2035 ap[2] = 0xff;
2036 ap[3] = 0xff;
2037 } else {
2038 ap[0] = (sdebug_capacity >> 24) & 0xff;
2039 ap[1] = (sdebug_capacity >> 16) & 0xff;
2040 ap[2] = (sdebug_capacity >> 8) & 0xff;
2041 ap[3] = sdebug_capacity & 0xff;
2042 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04002043 ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
2044 ap[7] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002045 offset += bd_len;
2046 ap = arr + offset;
2047 } else if (16 == bd_len) {
2048 unsigned long long capac = sdebug_capacity;
2049
2050 for (k = 0; k < 8; ++k, capac >>= 8)
2051 ap[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04002052 ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
2053 ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
2054 ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
2055 ap[15] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002056 offset += bd_len;
2057 ap = arr + offset;
2058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002060 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
2061 /* TODO: Control Extension page */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002062 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 return check_condition_result;
2064 }
2065 switch (pcode) {
2066 case 0x1: /* Read-Write error recovery page, direct access */
2067 len = resp_err_recov_pg(ap, pcontrol, target);
2068 offset += len;
2069 break;
2070 case 0x2: /* Disconnect-Reconnect page, all devices */
2071 len = resp_disconnect_pg(ap, pcontrol, target);
2072 offset += len;
2073 break;
2074 case 0x3: /* Format device page, direct access */
2075 len = resp_format_pg(ap, pcontrol, target);
2076 offset += len;
2077 break;
2078 case 0x8: /* Caching page, direct access */
2079 len = resp_caching_pg(ap, pcontrol, target);
2080 offset += len;
2081 break;
2082 case 0xa: /* Control Mode page, all devices */
2083 len = resp_ctrl_m_pg(ap, pcontrol, target);
2084 offset += len;
2085 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002086 case 0x19: /* if spc==1 then sas phy, control+discover */
2087 if ((subpcode > 0x2) && (subpcode < 0xff)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002088 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002089 return check_condition_result;
2090 }
2091 len = 0;
2092 if ((0x0 == subpcode) || (0xff == subpcode))
2093 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2094 if ((0x1 == subpcode) || (0xff == subpcode))
2095 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
2096 target_dev_id);
2097 if ((0x2 == subpcode) || (0xff == subpcode))
2098 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2099 offset += len;
2100 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 case 0x1c: /* Informational Exceptions Mode page, all devices */
2102 len = resp_iec_m_pg(ap, pcontrol, target);
2103 offset += len;
2104 break;
2105 case 0x3f: /* Read all Mode pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002106 if ((0 == subpcode) || (0xff == subpcode)) {
2107 len = resp_err_recov_pg(ap, pcontrol, target);
2108 len += resp_disconnect_pg(ap + len, pcontrol, target);
2109 len += resp_format_pg(ap + len, pcontrol, target);
2110 len += resp_caching_pg(ap + len, pcontrol, target);
2111 len += resp_ctrl_m_pg(ap + len, pcontrol, target);
2112 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2113 if (0xff == subpcode) {
2114 len += resp_sas_pcd_m_spg(ap + len, pcontrol,
2115 target, target_dev_id);
2116 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2117 }
2118 len += resp_iec_m_pg(ap + len, pcontrol, target);
2119 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002120 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002121 return check_condition_result;
2122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 offset += len;
2124 break;
2125 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002126 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 return check_condition_result;
2128 }
2129 if (msense_6)
2130 arr[0] = offset - 1;
2131 else {
2132 arr[0] = ((offset - 2) >> 8) & 0xff;
2133 arr[1] = (offset - 2) & 0xff;
2134 }
2135 return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
2136}
2137
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002138#define SDEBUG_MAX_MSELECT_SZ 512
2139
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002140static int
2141resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002142{
2143 int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002144 int param_len, res, mpage;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002145 unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002146 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002147 int mselect6 = (MODE_SELECT == cmd[0]);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002148
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002149 memset(arr, 0, sizeof(arr));
2150 pf = cmd[1] & 0x10;
2151 sp = cmd[1] & 0x1;
2152 param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
2153 if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002154 mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002155 return check_condition_result;
2156 }
2157 res = fetch_to_dev_buffer(scp, arr, param_len);
2158 if (-1 == res)
2159 return (DID_ERROR << 16);
2160 else if ((res < param_len) &&
2161 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002162 sdev_printk(KERN_INFO, scp->device,
2163 "%s: cdb indicated=%d, IO sent=%d bytes\n",
2164 __func__, param_len, res);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002165 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
2166 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
Douglas Gilbert23183912006-09-16 20:30:47 -04002167 if (md_len > 2) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002168 mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002169 return check_condition_result;
2170 }
2171 off = bd_len + (mselect6 ? 4 : 8);
2172 mpage = arr[off] & 0x3f;
2173 ps = !!(arr[off] & 0x80);
2174 if (ps) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002175 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002176 return check_condition_result;
2177 }
2178 spf = !!(arr[off] & 0x40);
2179 pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
2180 (arr[off + 1] + 2);
2181 if ((pg_len + off) > param_len) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002182 mk_sense_buffer(scp, ILLEGAL_REQUEST,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002183 PARAMETER_LIST_LENGTH_ERR, 0);
2184 return check_condition_result;
2185 }
2186 switch (mpage) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002187 case 0x8: /* Caching Mode page */
2188 if (caching_pg[1] == arr[off + 1]) {
2189 memcpy(caching_pg + 2, arr + off + 2,
2190 sizeof(caching_pg) - 2);
2191 goto set_mode_changed_ua;
2192 }
2193 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002194 case 0xa: /* Control Mode page */
2195 if (ctrl_m_pg[1] == arr[off + 1]) {
2196 memcpy(ctrl_m_pg + 2, arr + off + 2,
2197 sizeof(ctrl_m_pg) - 2);
2198 scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002199 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002200 }
2201 break;
2202 case 0x1c: /* Informational Exceptions Mode page */
2203 if (iec_m_pg[1] == arr[off + 1]) {
2204 memcpy(iec_m_pg + 2, arr + off + 2,
2205 sizeof(iec_m_pg) - 2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002206 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002207 }
2208 break;
2209 default:
2210 break;
2211 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002212 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 5);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002213 return check_condition_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002214set_mode_changed_ua:
2215 set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
2216 return 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002217}
2218
2219static int resp_temp_l_pg(unsigned char * arr)
2220{
2221 unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38,
2222 0x0, 0x1, 0x3, 0x2, 0x0, 65,
2223 };
2224
2225 memcpy(arr, temp_l_pg, sizeof(temp_l_pg));
2226 return sizeof(temp_l_pg);
2227}
2228
2229static int resp_ie_l_pg(unsigned char * arr)
2230{
2231 unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38,
2232 };
2233
2234 memcpy(arr, ie_l_pg, sizeof(ie_l_pg));
2235 if (iec_m_pg[2] & 0x4) { /* TEST bit set */
2236 arr[4] = THRESHOLD_EXCEEDED;
2237 arr[5] = 0xff;
2238 }
2239 return sizeof(ie_l_pg);
2240}
2241
2242#define SDEBUG_MAX_LSENSE_SZ 512
2243
2244static int resp_log_sense(struct scsi_cmnd * scp,
2245 struct sdebug_dev_info * devip)
2246{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002247 int ppc, sp, pcontrol, pcode, subpcode, alloc_len, len, n;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002248 unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002249 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002250
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002251 memset(arr, 0, sizeof(arr));
2252 ppc = cmd[1] & 0x2;
2253 sp = cmd[1] & 0x1;
2254 if (ppc || sp) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002255 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, ppc ? 1 : 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002256 return check_condition_result;
2257 }
2258 pcontrol = (cmd[2] & 0xc0) >> 6;
2259 pcode = cmd[2] & 0x3f;
Douglas Gilbert23183912006-09-16 20:30:47 -04002260 subpcode = cmd[3] & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002261 alloc_len = (cmd[7] << 8) + cmd[8];
2262 arr[0] = pcode;
Douglas Gilbert23183912006-09-16 20:30:47 -04002263 if (0 == subpcode) {
2264 switch (pcode) {
2265 case 0x0: /* Supported log pages log page */
2266 n = 4;
2267 arr[n++] = 0x0; /* this page */
2268 arr[n++] = 0xd; /* Temperature */
2269 arr[n++] = 0x2f; /* Informational exceptions */
2270 arr[3] = n - 4;
2271 break;
2272 case 0xd: /* Temperature log page */
2273 arr[3] = resp_temp_l_pg(arr + 4);
2274 break;
2275 case 0x2f: /* Informational exceptions log page */
2276 arr[3] = resp_ie_l_pg(arr + 4);
2277 break;
2278 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002279 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002280 return check_condition_result;
2281 }
2282 } else if (0xff == subpcode) {
2283 arr[0] |= 0x40;
2284 arr[1] = subpcode;
2285 switch (pcode) {
2286 case 0x0: /* Supported log pages and subpages log page */
2287 n = 4;
2288 arr[n++] = 0x0;
2289 arr[n++] = 0x0; /* 0,0 page */
2290 arr[n++] = 0x0;
2291 arr[n++] = 0xff; /* this page */
2292 arr[n++] = 0xd;
2293 arr[n++] = 0x0; /* Temperature */
2294 arr[n++] = 0x2f;
2295 arr[n++] = 0x0; /* Informational exceptions */
2296 arr[3] = n - 4;
2297 break;
2298 case 0xd: /* Temperature subpages */
2299 n = 4;
2300 arr[n++] = 0xd;
2301 arr[n++] = 0x0; /* Temperature */
2302 arr[3] = n - 4;
2303 break;
2304 case 0x2f: /* Informational exceptions subpages */
2305 n = 4;
2306 arr[n++] = 0x2f;
2307 arr[n++] = 0x0; /* Informational exceptions */
2308 arr[3] = n - 4;
2309 break;
2310 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002311 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002312 return check_condition_result;
2313 }
2314 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002315 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002316 return check_condition_result;
2317 }
2318 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
2319 return fill_from_dev_buffer(scp, arr,
2320 min(len, SDEBUG_MAX_INQ_ARR_SZ));
2321}
2322
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002323static int check_device_access_params(struct scsi_cmnd *scp,
FUJITA Tomonori19789102008-03-30 00:59:56 +09002324 unsigned long long lba, unsigned int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325{
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002326 if (lba + num > sdebug_capacity) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002327 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 return check_condition_result;
2329 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002330 /* transfer length excessive (tie in to block limits VPD page) */
2331 if (num > sdebug_store_sectors) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002332 /* needs work to find which cdb byte 'num' comes from */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002333 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002334 return check_condition_result;
2335 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002336 return 0;
2337}
2338
Akinobu Mitaa4517512013-07-08 16:01:57 -07002339/* Returns number of bytes copied or -1 if error. */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002340static int
2341do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002342{
2343 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002344 u64 block, rest = 0;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002345 struct scsi_data_buffer *sdb;
2346 enum dma_data_direction dir;
2347 size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
2348 off_t);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002349
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002350 if (do_write) {
Akinobu Mitaa4517512013-07-08 16:01:57 -07002351 sdb = scsi_out(scmd);
2352 dir = DMA_TO_DEVICE;
2353 func = sg_pcopy_to_buffer;
2354 } else {
2355 sdb = scsi_in(scmd);
2356 dir = DMA_FROM_DEVICE;
2357 func = sg_pcopy_from_buffer;
2358 }
2359
2360 if (!sdb->length)
2361 return 0;
2362 if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
2363 return -1;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002364
2365 block = do_div(lba, sdebug_store_sectors);
2366 if (block + num > sdebug_store_sectors)
2367 rest = block + num - sdebug_store_sectors;
2368
Akinobu Mitaa4517512013-07-08 16:01:57 -07002369 ret = func(sdb->table.sgl, sdb->table.nents,
2370 fake_storep + (block * scsi_debug_sector_size),
2371 (num - rest) * scsi_debug_sector_size, 0);
2372 if (ret != (num - rest) * scsi_debug_sector_size)
2373 return ret;
2374
2375 if (rest) {
2376 ret += func(sdb->table.sgl, sdb->table.nents,
2377 fake_storep, rest * scsi_debug_sector_size,
2378 (num - rest) * scsi_debug_sector_size);
2379 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002380
2381 return ret;
2382}
2383
Douglas Gilbert38d5c832014-11-24 21:27:12 -05002384/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
2385 * arr into fake_store(lba,num) and return true. If comparison fails then
2386 * return false. */
2387static bool
2388comp_write_worker(u64 lba, u32 num, const u8 *arr)
2389{
2390 bool res;
2391 u64 block, rest = 0;
2392 u32 store_blks = sdebug_store_sectors;
2393 u32 lb_size = scsi_debug_sector_size;
2394
2395 block = do_div(lba, store_blks);
2396 if (block + num > store_blks)
2397 rest = block + num - store_blks;
2398
2399 res = !memcmp(fake_storep + (block * lb_size), arr,
2400 (num - rest) * lb_size);
2401 if (!res)
2402 return res;
2403 if (rest)
2404 res = memcmp(fake_storep, arr + ((num - rest) * lb_size),
2405 rest * lb_size);
2406 if (!res)
2407 return res;
2408 arr += num * lb_size;
2409 memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size);
2410 if (rest)
2411 memcpy(fake_storep, arr + ((num - rest) * lb_size),
2412 rest * lb_size);
2413 return res;
2414}
2415
Akinobu Mita51d648a2013-09-18 21:27:28 +09002416static __be16 dif_compute_csum(const void *buf, int len)
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002417{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002418 __be16 csum;
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002419
Akinobu Mita51d648a2013-09-18 21:27:28 +09002420 if (scsi_debug_guard)
2421 csum = (__force __be16)ip_compute_csum(buf, len);
2422 else
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002423 csum = cpu_to_be16(crc_t10dif(buf, len));
Akinobu Mita51d648a2013-09-18 21:27:28 +09002424
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002425 return csum;
2426}
2427
2428static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
2429 sector_t sector, u32 ei_lba)
2430{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002431 __be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002432
2433 if (sdt->guard_tag != csum) {
2434 pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
2435 __func__,
2436 (unsigned long)sector,
2437 be16_to_cpu(sdt->guard_tag),
2438 be16_to_cpu(csum));
2439 return 0x01;
2440 }
2441 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
2442 be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
2443 pr_err("%s: REF check failed on sector %lu\n",
2444 __func__, (unsigned long)sector);
2445 return 0x03;
2446 }
2447 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2448 be32_to_cpu(sdt->ref_tag) != ei_lba) {
2449 pr_err("%s: REF check failed on sector %lu\n",
2450 __func__, (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002451 return 0x03;
2452 }
2453 return 0;
2454}
2455
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002456static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002457 unsigned int sectors, bool read)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002458{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002459 size_t resid;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002460 void *paddr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002461 const void *dif_store_end = dif_storep + sdebug_store_sectors;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002462 struct sg_mapping_iter miter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002463
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002464 /* Bytes of protection data to copy into sgl */
2465 resid = sectors * sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002466
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002467 sg_miter_start(&miter, scsi_prot_sglist(SCpnt),
2468 scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC |
2469 (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
2470
2471 while (sg_miter_next(&miter) && resid > 0) {
2472 size_t len = min(miter.length, resid);
Akinobu Mita14faa942013-09-18 21:27:24 +09002473 void *start = dif_store(sector);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002474 size_t rest = 0;
Akinobu Mita14faa942013-09-18 21:27:24 +09002475
2476 if (dif_store_end < start + len)
2477 rest = start + len - dif_store_end;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002478
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002479 paddr = miter.addr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002480
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002481 if (read)
2482 memcpy(paddr, start, len - rest);
2483 else
2484 memcpy(start, paddr, len - rest);
2485
2486 if (rest) {
2487 if (read)
2488 memcpy(paddr + len - rest, dif_storep, rest);
2489 else
2490 memcpy(dif_storep, paddr + len - rest, rest);
2491 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002492
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002493 sector += len / sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002494 resid -= len;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002495 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002496 sg_miter_stop(&miter);
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002497}
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002498
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002499static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
2500 unsigned int sectors, u32 ei_lba)
2501{
2502 unsigned int i;
2503 struct sd_dif_tuple *sdt;
2504 sector_t sector;
2505
Akinobu Mitac45eabec2014-02-26 22:56:58 +09002506 for (i = 0; i < sectors; i++, ei_lba++) {
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002507 int ret;
2508
2509 sector = start_sec + i;
2510 sdt = dif_store(sector);
2511
Akinobu Mita51d648a2013-09-18 21:27:28 +09002512 if (sdt->app_tag == cpu_to_be16(0xffff))
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002513 continue;
2514
2515 ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
2516 if (ret) {
2517 dif_errors++;
2518 return ret;
2519 }
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002520 }
2521
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002522 dif_copy_prot(SCpnt, start_sec, sectors, true);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002523 dix_reads++;
2524
2525 return 0;
2526}
2527
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002528static int
2529resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002530{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002531 u8 *cmd = scp->cmnd;
2532 u64 lba;
2533 u32 num;
2534 u32 ei_lba;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002535 unsigned long iflags;
2536 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002537 bool check_prot;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002538
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002539 switch (cmd[0]) {
2540 case READ_16:
2541 ei_lba = 0;
2542 lba = get_unaligned_be64(cmd + 2);
2543 num = get_unaligned_be32(cmd + 10);
2544 check_prot = true;
2545 break;
2546 case READ_10:
2547 ei_lba = 0;
2548 lba = get_unaligned_be32(cmd + 2);
2549 num = get_unaligned_be16(cmd + 7);
2550 check_prot = true;
2551 break;
2552 case READ_6:
2553 ei_lba = 0;
2554 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2555 (u32)(cmd[1] & 0x1f) << 16;
2556 num = (0 == cmd[4]) ? 256 : cmd[4];
2557 check_prot = true;
2558 break;
2559 case READ_12:
2560 ei_lba = 0;
2561 lba = get_unaligned_be32(cmd + 2);
2562 num = get_unaligned_be32(cmd + 6);
2563 check_prot = true;
2564 break;
2565 case XDWRITEREAD_10:
2566 ei_lba = 0;
2567 lba = get_unaligned_be32(cmd + 2);
2568 num = get_unaligned_be16(cmd + 7);
2569 check_prot = false;
2570 break;
2571 default: /* assume READ(32) */
2572 lba = get_unaligned_be64(cmd + 12);
2573 ei_lba = get_unaligned_be32(cmd + 20);
2574 num = get_unaligned_be32(cmd + 28);
2575 check_prot = false;
2576 break;
2577 }
2578 if (check_prot) {
2579 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2580 (cmd[1] & 0xe0)) {
2581 mk_sense_invalid_opcode(scp);
2582 return check_condition_result;
2583 }
2584 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2585 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2586 (cmd[1] & 0xe0) == 0)
2587 sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
2588 "to DIF device\n");
2589 }
2590 if (sdebug_any_injecting_opt) {
2591 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2592
2593 if (ep->inj_short)
2594 num /= 2;
2595 }
2596
2597 /* inline check_device_access_params() */
2598 if (lba + num > sdebug_capacity) {
2599 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2600 return check_condition_result;
2601 }
2602 /* transfer length excessive (tie in to block limits VPD page) */
2603 if (num > sdebug_store_sectors) {
2604 /* needs work to find which cdb byte 'num' comes from */
2605 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2606 return check_condition_result;
2607 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002608
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002610 (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002611 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
2612 /* claim unrecoverable read error */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002613 mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002614 /* set info field and valid bit for fixed descriptor */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002615 if (0x70 == (scp->sense_buffer[0] & 0x7f)) {
2616 scp->sense_buffer[0] |= 0x80; /* Valid bit */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002617 ret = (lba < OPT_MEDIUM_ERR_ADDR)
2618 ? OPT_MEDIUM_ERR_ADDR : (int)lba;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002619 put_unaligned_be32(ret, scp->sense_buffer + 3);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002620 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002621 scsi_set_resid(scp, scsi_bufflen(scp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 return check_condition_result;
2623 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002624
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002625 read_lock_irqsave(&atomic_rw, iflags);
2626
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002627 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002628 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2629 int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002630
2631 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002632 read_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002633 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002634 return illegal_condition_result;
2635 }
2636 }
2637
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002638 ret = do_device_access(scp, lba, num, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 read_unlock_irqrestore(&atomic_rw, iflags);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002640 if (ret == -1)
2641 return DID_ERROR << 16;
2642
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002643 scsi_in(scp)->resid = scsi_bufflen(scp) - ret;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002644
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002645 if (sdebug_any_injecting_opt) {
2646 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2647
2648 if (ep->inj_recovered) {
2649 mk_sense_buffer(scp, RECOVERED_ERROR,
2650 THRESHOLD_EXCEEDED, 0);
2651 return check_condition_result;
2652 } else if (ep->inj_transport) {
2653 mk_sense_buffer(scp, ABORTED_COMMAND,
2654 TRANSPORT_PROBLEM, ACK_NAK_TO);
2655 return check_condition_result;
2656 } else if (ep->inj_dif) {
2657 /* Logical block guard check failed */
2658 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2659 return illegal_condition_result;
2660 } else if (ep->inj_dix) {
2661 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2662 return illegal_condition_result;
2663 }
2664 }
Akinobu Mitaa4517512013-07-08 16:01:57 -07002665 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666}
2667
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002668void dump_sector(unsigned char *buf, int len)
2669{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002670 int i, j, n;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002671
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002672 pr_err(">>> Sector Dump <<<\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002673 for (i = 0 ; i < len ; i += 16) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002674 char b[128];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002675
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002676 for (j = 0, n = 0; j < 16; j++) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002677 unsigned char c = buf[i+j];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002678
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002679 if (c >= 0x20 && c < 0x7e)
2680 n += scnprintf(b + n, sizeof(b) - n,
2681 " %c ", buf[i+j]);
2682 else
2683 n += scnprintf(b + n, sizeof(b) - n,
2684 "%02x ", buf[i+j]);
2685 }
2686 pr_err("%04d: %s\n", i, b);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002687 }
2688}
2689
2690static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
Martin K. Petersen395cef02009-09-18 17:33:03 -04002691 unsigned int sectors, u32 ei_lba)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002692{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002693 int ret;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002694 struct sd_dif_tuple *sdt;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002695 void *daddr;
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002696 sector_t sector = start_sec;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002697 int ppage_offset;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002698 int dpage_offset;
2699 struct sg_mapping_iter diter;
2700 struct sg_mapping_iter piter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002701
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002702 BUG_ON(scsi_sg_count(SCpnt) == 0);
2703 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
2704
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002705 sg_miter_start(&piter, scsi_prot_sglist(SCpnt),
2706 scsi_prot_sg_count(SCpnt),
2707 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
2708 sg_miter_start(&diter, scsi_sglist(SCpnt), scsi_sg_count(SCpnt),
2709 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002710
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002711 /* For each protection page */
2712 while (sg_miter_next(&piter)) {
2713 dpage_offset = 0;
2714 if (WARN_ON(!sg_miter_next(&diter))) {
2715 ret = 0x01;
2716 goto out;
2717 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002718
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002719 for (ppage_offset = 0; ppage_offset < piter.length;
2720 ppage_offset += sizeof(struct sd_dif_tuple)) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002721 /* If we're at the end of the current
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002722 * data page advance to the next one
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002723 */
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002724 if (dpage_offset >= diter.length) {
2725 if (WARN_ON(!sg_miter_next(&diter))) {
2726 ret = 0x01;
2727 goto out;
2728 }
2729 dpage_offset = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002730 }
2731
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002732 sdt = piter.addr + ppage_offset;
2733 daddr = diter.addr + dpage_offset;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002734
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002735 ret = dif_verify(sdt, daddr, sector, ei_lba);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002736 if (ret) {
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002737 dump_sector(daddr, scsi_debug_sector_size);
Martin K. Petersen395cef02009-09-18 17:33:03 -04002738 goto out;
2739 }
2740
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002741 sector++;
Martin K. Petersen395cef02009-09-18 17:33:03 -04002742 ei_lba++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002743 dpage_offset += scsi_debug_sector_size;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002744 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002745 diter.consumed = dpage_offset;
2746 sg_miter_stop(&diter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002747 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002748 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002749
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002750 dif_copy_prot(SCpnt, start_sec, sectors, false);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002751 dix_writes++;
2752
2753 return 0;
2754
2755out:
2756 dif_errors++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002757 sg_miter_stop(&diter);
2758 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002759 return ret;
2760}
2761
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002762static unsigned long lba_to_map_index(sector_t lba)
2763{
2764 if (scsi_debug_unmap_alignment) {
2765 lba += scsi_debug_unmap_granularity -
2766 scsi_debug_unmap_alignment;
2767 }
2768 do_div(lba, scsi_debug_unmap_granularity);
2769
2770 return lba;
2771}
2772
2773static sector_t map_index_to_lba(unsigned long index)
2774{
Akinobu Mitaa027b5b2013-08-26 22:08:41 +09002775 sector_t lba = index * scsi_debug_unmap_granularity;
2776
2777 if (scsi_debug_unmap_alignment) {
2778 lba -= scsi_debug_unmap_granularity -
2779 scsi_debug_unmap_alignment;
2780 }
2781
2782 return lba;
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002783}
2784
Martin K. Petersen44d92692009-10-15 14:45:27 -04002785static unsigned int map_state(sector_t lba, unsigned int *num)
2786{
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002787 sector_t end;
2788 unsigned int mapped;
2789 unsigned long index;
2790 unsigned long next;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002791
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002792 index = lba_to_map_index(lba);
2793 mapped = test_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002794
2795 if (mapped)
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002796 next = find_next_zero_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002797 else
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002798 next = find_next_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002799
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002800 end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
Martin K. Petersen44d92692009-10-15 14:45:27 -04002801 *num = end - lba;
2802
2803 return mapped;
2804}
2805
2806static void map_region(sector_t lba, unsigned int len)
2807{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002808 sector_t end = lba + len;
2809
Martin K. Petersen44d92692009-10-15 14:45:27 -04002810 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002811 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002812
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002813 if (index < map_size)
2814 set_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002815
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002816 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002817 }
2818}
2819
2820static void unmap_region(sector_t lba, unsigned int len)
2821{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002822 sector_t end = lba + len;
2823
Martin K. Petersen44d92692009-10-15 14:45:27 -04002824 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002825 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002826
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002827 if (lba == map_index_to_lba(index) &&
2828 lba + scsi_debug_unmap_granularity <= end &&
2829 index < map_size) {
2830 clear_bit(index, map_storep);
2831 if (scsi_debug_lbprz) {
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002832 memset(fake_storep +
Akinobu Mitacc34a8e2013-04-16 22:11:57 +09002833 lba * scsi_debug_sector_size, 0,
2834 scsi_debug_sector_size *
2835 scsi_debug_unmap_granularity);
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002836 }
Akinobu Mitae9926b42013-06-29 17:59:17 +09002837 if (dif_storep) {
2838 memset(dif_storep + lba, 0xff,
2839 sizeof(*dif_storep) *
2840 scsi_debug_unmap_granularity);
2841 }
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002842 }
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002843 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002844 }
2845}
2846
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002847static int
2848resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002850 u8 *cmd = scp->cmnd;
2851 u64 lba;
2852 u32 num;
2853 u32 ei_lba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 unsigned long iflags;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002855 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002856 bool check_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002858 switch (cmd[0]) {
2859 case WRITE_16:
2860 ei_lba = 0;
2861 lba = get_unaligned_be64(cmd + 2);
2862 num = get_unaligned_be32(cmd + 10);
2863 check_prot = true;
2864 break;
2865 case WRITE_10:
2866 ei_lba = 0;
2867 lba = get_unaligned_be32(cmd + 2);
2868 num = get_unaligned_be16(cmd + 7);
2869 check_prot = true;
2870 break;
2871 case WRITE_6:
2872 ei_lba = 0;
2873 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2874 (u32)(cmd[1] & 0x1f) << 16;
2875 num = (0 == cmd[4]) ? 256 : cmd[4];
2876 check_prot = true;
2877 break;
2878 case WRITE_12:
2879 ei_lba = 0;
2880 lba = get_unaligned_be32(cmd + 2);
2881 num = get_unaligned_be32(cmd + 6);
2882 check_prot = true;
2883 break;
2884 case 0x53: /* XDWRITEREAD(10) */
2885 ei_lba = 0;
2886 lba = get_unaligned_be32(cmd + 2);
2887 num = get_unaligned_be16(cmd + 7);
2888 check_prot = false;
2889 break;
2890 default: /* assume WRITE(32) */
2891 lba = get_unaligned_be64(cmd + 12);
2892 ei_lba = get_unaligned_be32(cmd + 20);
2893 num = get_unaligned_be32(cmd + 28);
2894 check_prot = false;
2895 break;
2896 }
2897 if (check_prot) {
2898 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2899 (cmd[1] & 0xe0)) {
2900 mk_sense_invalid_opcode(scp);
2901 return check_condition_result;
2902 }
2903 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2904 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2905 (cmd[1] & 0xe0) == 0)
2906 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
2907 "to DIF device\n");
2908 }
2909
2910 /* inline check_device_access_params() */
2911 if (lba + num > sdebug_capacity) {
2912 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2913 return check_condition_result;
2914 }
2915 /* transfer length excessive (tie in to block limits VPD page) */
2916 if (num > sdebug_store_sectors) {
2917 /* needs work to find which cdb byte 'num' comes from */
2918 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2919 return check_condition_result;
2920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002922 write_lock_irqsave(&atomic_rw, iflags);
2923
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002924 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002925 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2926 int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002927
2928 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002929 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002930 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002931 return illegal_condition_result;
2932 }
2933 }
2934
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002935 ret = do_device_access(scp, lba, num, true);
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002936 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002937 map_region(lba, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 write_unlock_irqrestore(&atomic_rw, iflags);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002939 if (-1 == ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 return (DID_ERROR << 16);
Martin K. Petersen597136a2008-06-05 00:12:59 -04002941 else if ((ret < (num * scsi_debug_sector_size)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002943 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002944 "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
2945 my_name, num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002946
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002947 if (sdebug_any_injecting_opt) {
2948 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2949
2950 if (ep->inj_recovered) {
2951 mk_sense_buffer(scp, RECOVERED_ERROR,
2952 THRESHOLD_EXCEEDED, 0);
2953 return check_condition_result;
2954 } else if (ep->inj_dif) {
2955 /* Logical block guard check failed */
2956 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2957 return illegal_condition_result;
2958 } else if (ep->inj_dix) {
2959 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2960 return illegal_condition_result;
2961 }
2962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 return 0;
2964}
2965
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002966static int
2967resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
2968 bool unmap, bool ndob)
Martin K. Petersen44d92692009-10-15 14:45:27 -04002969{
2970 unsigned long iflags;
2971 unsigned long long i;
2972 int ret;
2973
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002974 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002975 if (ret)
2976 return ret;
2977
2978 write_lock_irqsave(&atomic_rw, iflags);
2979
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002980 if (unmap && scsi_debug_lbp()) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04002981 unmap_region(lba, num);
2982 goto out;
2983 }
2984
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002985 /* if ndob then zero 1 logical block, else fetch 1 logical block */
2986 if (ndob) {
2987 memset(fake_storep + (lba * scsi_debug_sector_size), 0,
2988 scsi_debug_sector_size);
2989 ret = 0;
2990 } else
2991 ret = fetch_to_dev_buffer(scp, fake_storep +
2992 (lba * scsi_debug_sector_size),
2993 scsi_debug_sector_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002994
2995 if (-1 == ret) {
2996 write_unlock_irqrestore(&atomic_rw, iflags);
2997 return (DID_ERROR << 16);
2998 } else if ((ret < (num * scsi_debug_sector_size)) &&
2999 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003000 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003001 "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
3002 my_name, "write same",
3003 num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003004
3005 /* Copy first sector to remaining blocks */
3006 for (i = 1 ; i < num ; i++)
3007 memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
3008 fake_storep + (lba * scsi_debug_sector_size),
3009 scsi_debug_sector_size);
3010
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09003011 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04003012 map_region(lba, num);
3013out:
3014 write_unlock_irqrestore(&atomic_rw, iflags);
3015
3016 return 0;
3017}
3018
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003019static int
3020resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3021{
3022 u8 *cmd = scp->cmnd;
3023 u32 lba;
3024 u16 num;
3025 u32 ei_lba = 0;
3026 bool unmap = false;
3027
3028 if (cmd[1] & 0x8) {
3029 if (scsi_debug_lbpws10 == 0) {
3030 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
3031 return check_condition_result;
3032 } else
3033 unmap = true;
3034 }
3035 lba = get_unaligned_be32(cmd + 2);
3036 num = get_unaligned_be16(cmd + 7);
3037 if (num > scsi_debug_write_same_length) {
3038 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
3039 return check_condition_result;
3040 }
3041 return resp_write_same(scp, lba, num, ei_lba, unmap, false);
3042}
3043
3044static int
3045resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3046{
3047 u8 *cmd = scp->cmnd;
3048 u64 lba;
3049 u32 num;
3050 u32 ei_lba = 0;
3051 bool unmap = false;
3052 bool ndob = false;
3053
3054 if (cmd[1] & 0x8) { /* UNMAP */
3055 if (scsi_debug_lbpws == 0) {
3056 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
3057 return check_condition_result;
3058 } else
3059 unmap = true;
3060 }
3061 if (cmd[1] & 0x1) /* NDOB (no data-out buffer, assumes zeroes) */
3062 ndob = true;
3063 lba = get_unaligned_be64(cmd + 2);
3064 num = get_unaligned_be32(cmd + 10);
3065 if (num > scsi_debug_write_same_length) {
3066 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
3067 return check_condition_result;
3068 }
3069 return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
3070}
3071
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003072static int
3073resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3074{
3075 u8 *cmd = scp->cmnd;
3076 u8 *arr;
3077 u8 *fake_storep_hold;
3078 u64 lba;
3079 u32 dnum;
3080 u32 lb_size = scsi_debug_sector_size;
3081 u8 num;
3082 unsigned long iflags;
3083 int ret;
Douglas Gilbertd467d312014-11-26 12:33:48 -05003084 int retval = 0;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003085
Douglas Gilbertd467d312014-11-26 12:33:48 -05003086 lba = get_unaligned_be64(cmd + 2);
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003087 num = cmd[13]; /* 1 to a maximum of 255 logical blocks */
3088 if (0 == num)
3089 return 0; /* degenerate case, not an error */
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003090 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3091 (cmd[1] & 0xe0)) {
3092 mk_sense_invalid_opcode(scp);
3093 return check_condition_result;
3094 }
3095 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3096 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3097 (cmd[1] & 0xe0) == 0)
3098 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
3099 "to DIF device\n");
3100
3101 /* inline check_device_access_params() */
3102 if (lba + num > sdebug_capacity) {
3103 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
3104 return check_condition_result;
3105 }
3106 /* transfer length excessive (tie in to block limits VPD page) */
3107 if (num > sdebug_store_sectors) {
3108 /* needs work to find which cdb byte 'num' comes from */
3109 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
3110 return check_condition_result;
3111 }
Douglas Gilbertd467d312014-11-26 12:33:48 -05003112 dnum = 2 * num;
3113 arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
3114 if (NULL == arr) {
3115 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3116 INSUFF_RES_ASCQ);
3117 return check_condition_result;
3118 }
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003119
3120 write_lock_irqsave(&atomic_rw, iflags);
3121
3122 /* trick do_device_access() to fetch both compare and write buffers
3123 * from data-in into arr. Safe (atomic) since write_lock held. */
3124 fake_storep_hold = fake_storep;
3125 fake_storep = arr;
3126 ret = do_device_access(scp, 0, dnum, true);
3127 fake_storep = fake_storep_hold;
3128 if (ret == -1) {
Douglas Gilbertd467d312014-11-26 12:33:48 -05003129 retval = DID_ERROR << 16;
3130 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003131 } else if ((ret < (dnum * lb_size)) &&
3132 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3133 sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
3134 "indicated=%u, IO sent=%d bytes\n", my_name,
3135 dnum * lb_size, ret);
3136 if (!comp_write_worker(lba, num, arr)) {
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003137 mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003138 retval = check_condition_result;
3139 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003140 }
3141 if (scsi_debug_lbp())
3142 map_region(lba, num);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003143cleanup:
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003144 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003145 kfree(arr);
3146 return retval;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003147}
3148
Martin K. Petersen44d92692009-10-15 14:45:27 -04003149struct unmap_block_desc {
3150 __be64 lba;
3151 __be32 blocks;
3152 __be32 __reserved;
3153};
3154
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003155static int
3156resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003157{
3158 unsigned char *buf;
3159 struct unmap_block_desc *desc;
3160 unsigned int i, payload_len, descriptors;
3161 int ret;
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003162 unsigned long iflags;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003163
Martin K. Petersen44d92692009-10-15 14:45:27 -04003164
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003165 if (!scsi_debug_lbp())
3166 return 0; /* fib and say its done */
3167 payload_len = get_unaligned_be16(scp->cmnd + 7);
3168 BUG_ON(scsi_bufflen(scp) != payload_len);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003169
3170 descriptors = (payload_len - 8) / 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003171 if (descriptors > scsi_debug_unmap_max_desc) {
3172 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003173 return check_condition_result;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003174 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003175
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003176 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
3177 if (!buf) {
3178 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3179 INSUFF_RES_ASCQ);
3180 return check_condition_result;
3181 }
3182
3183 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
Martin K. Petersen44d92692009-10-15 14:45:27 -04003184
3185 BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
3186 BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
3187
3188 desc = (void *)&buf[8];
3189
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003190 write_lock_irqsave(&atomic_rw, iflags);
3191
Martin K. Petersen44d92692009-10-15 14:45:27 -04003192 for (i = 0 ; i < descriptors ; i++) {
3193 unsigned long long lba = get_unaligned_be64(&desc[i].lba);
3194 unsigned int num = get_unaligned_be32(&desc[i].blocks);
3195
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003196 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003197 if (ret)
3198 goto out;
3199
3200 unmap_region(lba, num);
3201 }
3202
3203 ret = 0;
3204
3205out:
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003206 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003207 kfree(buf);
3208
3209 return ret;
3210}
3211
3212#define SDEBUG_GET_LBA_STATUS_LEN 32
3213
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003214static int
3215resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003216{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003217 u8 *cmd = scp->cmnd;
3218 u64 lba;
3219 u32 alloc_len, mapped, num;
3220 u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
Martin K. Petersen44d92692009-10-15 14:45:27 -04003221 int ret;
3222
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003223 lba = get_unaligned_be64(cmd + 2);
3224 alloc_len = get_unaligned_be32(cmd + 10);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003225
3226 if (alloc_len < 24)
3227 return 0;
3228
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003229 ret = check_device_access_params(scp, lba, 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003230 if (ret)
3231 return ret;
3232
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003233 if (scsi_debug_lbp())
3234 mapped = map_state(lba, &num);
3235 else {
3236 mapped = 1;
3237 /* following just in case virtual_gb changed */
3238 sdebug_capacity = get_sdebug_capacity();
3239 if (sdebug_capacity - lba <= 0xffffffff)
3240 num = sdebug_capacity - lba;
3241 else
3242 num = 0xffffffff;
3243 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003244
3245 memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003246 put_unaligned_be32(20, arr); /* Parameter Data Length */
3247 put_unaligned_be64(lba, arr + 8); /* LBA */
3248 put_unaligned_be32(num, arr + 16); /* Number of blocks */
3249 arr[20] = !mapped; /* prov_stat=0: mapped; 1: dealloc */
Martin K. Petersen44d92692009-10-15 14:45:27 -04003250
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003251 return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003252}
3253
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003254#define SDEBUG_RLUN_ARR_SZ 256
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
3256static int resp_report_luns(struct scsi_cmnd * scp,
3257 struct sdebug_dev_info * devip)
3258{
3259 unsigned int alloc_len;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003260 int lun_cnt, i, upper, num, n, want_wlun, shortish;
3261 u64 lun;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02003262 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 int select_report = (int)cmd[2];
3264 struct scsi_lun *one_lun;
3265 unsigned char arr[SDEBUG_RLUN_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003266 unsigned char * max_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05003268 clear_luns_changed_on_target(devip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003270 shortish = (alloc_len < 4);
3271 if (shortish || (select_report > 2)) {
3272 mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 return check_condition_result;
3274 }
3275 /* can produce response with up to 16k luns (lun 0 to lun 16383) */
3276 memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
3277 lun_cnt = scsi_debug_max_luns;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003278 if (1 == select_report)
3279 lun_cnt = 0;
3280 else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
3281 --lun_cnt;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003282 want_wlun = (select_report > 0) ? 1 : 0;
3283 num = lun_cnt + want_wlun;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003284 arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
3285 arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
3286 n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
3287 sizeof(struct scsi_lun)), num);
3288 if (n < num) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003289 want_wlun = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003290 lun_cnt = n;
3291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292 one_lun = (struct scsi_lun *) &arr[8];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003293 max_addr = arr + SDEBUG_RLUN_ARR_SZ;
3294 for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
3295 ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
3296 i++, lun++) {
3297 upper = (lun >> 8) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 if (upper)
3299 one_lun[i].scsi_lun[0] =
3300 (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003301 one_lun[i].scsi_lun[1] = lun & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003303 if (want_wlun) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003304 one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
3305 one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
3306 i++;
3307 }
3308 alloc_len = (unsigned char *)(one_lun + i) - arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309 return fill_from_dev_buffer(scp, arr,
3310 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
3311}
3312
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003313static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
3314 unsigned int num, struct sdebug_dev_info *devip)
3315{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003316 int j;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003317 unsigned char *kaddr, *buf;
3318 unsigned int offset;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003319 struct scsi_data_buffer *sdb = scsi_in(scp);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003320 struct sg_mapping_iter miter;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003321
3322 /* better not to use temporary buffer. */
3323 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003324 if (!buf) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003325 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3326 INSUFF_RES_ASCQ);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003327 return check_condition_result;
3328 }
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003329
FUJITA Tomonori21a61822008-03-09 13:44:30 +09003330 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003331
3332 offset = 0;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003333 sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents,
3334 SG_MITER_ATOMIC | SG_MITER_TO_SG);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003335
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003336 while (sg_miter_next(&miter)) {
3337 kaddr = miter.addr;
3338 for (j = 0; j < miter.length; j++)
3339 *(kaddr + j) ^= *(buf + offset + j);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003340
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003341 offset += miter.length;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003342 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003343 sg_miter_stop(&miter);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003344 kfree(buf);
3345
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003346 return 0;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003347}
3348
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003349static int
3350resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3351{
3352 u8 *cmd = scp->cmnd;
3353 u64 lba;
3354 u32 num;
3355 int errsts;
3356
3357 if (!scsi_bidi_cmnd(scp)) {
3358 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3359 INSUFF_RES_ASCQ);
3360 return check_condition_result;
3361 }
3362 errsts = resp_read_dt0(scp, devip);
3363 if (errsts)
3364 return errsts;
3365 if (!(cmd[1] & 0x4)) { /* DISABLE_WRITE is not set */
3366 errsts = resp_write_dt0(scp, devip);
3367 if (errsts)
3368 return errsts;
3369 }
3370 lba = get_unaligned_be32(cmd + 2);
3371 num = get_unaligned_be16(cmd + 7);
3372 return resp_xdwriteread(scp, lba, num, devip);
3373}
3374
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003375/* When timer or tasklet goes off this function is called. */
3376static void sdebug_q_cmd_complete(unsigned long indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003378 int qa_indx;
3379 int retiring = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003381 struct sdebug_queued_cmd *sqcp;
3382 struct scsi_cmnd *scp;
3383 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003385 atomic_inc(&sdebug_completions);
3386 qa_indx = indx;
3387 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
3388 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 return;
3390 }
3391 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003392 sqcp = &queued_arr[qa_indx];
3393 scp = sqcp->a_cmnd;
3394 if (NULL == scp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003396 pr_err("%s: scp is NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397 return;
3398 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003399 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3400 if (devip)
3401 atomic_dec(&devip->num_in_q);
3402 else
3403 pr_err("%s: devip=NULL\n", __func__);
3404 if (atomic_read(&retired_max_queue) > 0)
3405 retiring = 1;
3406
3407 sqcp->a_cmnd = NULL;
3408 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3409 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3410 pr_err("%s: Unexpected completion\n", __func__);
3411 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003413
3414 if (unlikely(retiring)) { /* user has reduced max_queue */
3415 int k, retval;
3416
3417 retval = atomic_read(&retired_max_queue);
3418 if (qa_indx >= retval) {
3419 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3420 pr_err("%s: index %d too large\n", __func__, retval);
3421 return;
3422 }
3423 k = find_last_bit(queued_in_use_bm, retval);
3424 if ((k < scsi_debug_max_queue) || (k == retval))
3425 atomic_set(&retired_max_queue, 0);
3426 else
3427 atomic_set(&retired_max_queue, k + 1);
3428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003430 scp->scsi_done(scp); /* callback to mid level */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431}
3432
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003433/* When high resolution timer goes off this function is called. */
3434static enum hrtimer_restart
3435sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
3436{
3437 int qa_indx;
3438 int retiring = 0;
3439 unsigned long iflags;
3440 struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
3441 struct sdebug_queued_cmd *sqcp;
3442 struct scsi_cmnd *scp;
3443 struct sdebug_dev_info *devip;
3444
3445 atomic_inc(&sdebug_completions);
3446 qa_indx = sd_hrtp->qa_indx;
3447 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
3448 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
3449 goto the_end;
3450 }
3451 spin_lock_irqsave(&queued_arr_lock, iflags);
3452 sqcp = &queued_arr[qa_indx];
3453 scp = sqcp->a_cmnd;
3454 if (NULL == scp) {
3455 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3456 pr_err("%s: scp is NULL\n", __func__);
3457 goto the_end;
3458 }
3459 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3460 if (devip)
3461 atomic_dec(&devip->num_in_q);
3462 else
3463 pr_err("%s: devip=NULL\n", __func__);
3464 if (atomic_read(&retired_max_queue) > 0)
3465 retiring = 1;
3466
3467 sqcp->a_cmnd = NULL;
3468 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3469 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3470 pr_err("%s: Unexpected completion\n", __func__);
3471 goto the_end;
3472 }
3473
3474 if (unlikely(retiring)) { /* user has reduced max_queue */
3475 int k, retval;
3476
3477 retval = atomic_read(&retired_max_queue);
3478 if (qa_indx >= retval) {
3479 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3480 pr_err("%s: index %d too large\n", __func__, retval);
3481 goto the_end;
3482 }
3483 k = find_last_bit(queued_in_use_bm, retval);
3484 if ((k < scsi_debug_max_queue) || (k == retval))
3485 atomic_set(&retired_max_queue, 0);
3486 else
3487 atomic_set(&retired_max_queue, k + 1);
3488 }
3489 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3490 scp->scsi_done(scp); /* callback to mid level */
3491the_end:
3492 return HRTIMER_NORESTART;
3493}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003495static struct sdebug_dev_info *
3496sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003497{
3498 struct sdebug_dev_info *devip;
3499
3500 devip = kzalloc(sizeof(*devip), flags);
3501 if (devip) {
3502 devip->sdbg_host = sdbg_host;
3503 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
3504 }
3505 return devip;
3506}
3507
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
3509{
3510 struct sdebug_host_info * sdbg_host;
3511 struct sdebug_dev_info * open_devip = NULL;
3512 struct sdebug_dev_info * devip =
3513 (struct sdebug_dev_info *)sdev->hostdata;
3514
3515 if (devip)
3516 return devip;
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003517 sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
3518 if (!sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003519 pr_err("%s: Host info NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 return NULL;
3521 }
3522 list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
3523 if ((devip->used) && (devip->channel == sdev->channel) &&
3524 (devip->target == sdev->id) &&
3525 (devip->lun == sdev->lun))
3526 return devip;
3527 else {
3528 if ((!devip->used) && (!open_devip))
3529 open_devip = devip;
3530 }
3531 }
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003532 if (!open_devip) { /* try and make a new one */
3533 open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
3534 if (!open_devip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07003536 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 return NULL;
3538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 }
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003540
3541 open_devip->channel = sdev->channel;
3542 open_devip->target = sdev->id;
3543 open_devip->lun = sdev->lun;
3544 open_devip->sdbg_host = sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003545 atomic_set(&open_devip->num_in_q, 0);
3546 set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003547 open_devip->used = true;
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003548 return open_devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549}
3550
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003551static int scsi_debug_slave_alloc(struct scsi_device *sdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003553 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003554 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003555 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
Nick Piggin75ad23b2008-04-29 14:48:33 +02003556 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003557 return 0;
3558}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003560static int scsi_debug_slave_configure(struct scsi_device *sdp)
3561{
3562 struct sdebug_dev_info *devip;
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +09003563
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003565 printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003566 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3567 if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
3568 sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
3569 devip = devInfoReg(sdp);
3570 if (NULL == devip)
3571 return 1; /* no resources, will be marked offline */
Christoph Hellwigc8b09f62014-11-03 20:15:14 +01003572 sdp->hostdata = devip;
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09003573 blk_queue_max_segment_size(sdp->request_queue, -1U);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003574 if (scsi_debug_no_uld)
3575 sdp->no_uld_attach = 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003576 return 0;
3577}
3578
3579static void scsi_debug_slave_destroy(struct scsi_device *sdp)
3580{
3581 struct sdebug_dev_info *devip =
3582 (struct sdebug_dev_info *)sdp->hostdata;
3583
3584 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003585 printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003586 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3587 if (devip) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003588 /* make this slot available for re-use */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003589 devip->used = false;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003590 sdp->hostdata = NULL;
3591 }
3592}
3593
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003594/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003595static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
3596{
3597 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003598 int k, qmax, r_qmax;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003599 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003600 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003601
3602 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003603 qmax = scsi_debug_max_queue;
3604 r_qmax = atomic_read(&retired_max_queue);
3605 if (r_qmax > qmax)
3606 qmax = r_qmax;
3607 for (k = 0; k < qmax; ++k) {
3608 if (test_bit(k, queued_in_use_bm)) {
3609 sqcp = &queued_arr[k];
3610 if (cmnd == sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003611 devip = (struct sdebug_dev_info *)
3612 cmnd->device->hostdata;
3613 if (devip)
3614 atomic_dec(&devip->num_in_q);
3615 sqcp->a_cmnd = NULL;
3616 spin_unlock_irqrestore(&queued_arr_lock,
3617 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003618 if (scsi_debug_ndelay > 0) {
3619 if (sqcp->sd_hrtp)
3620 hrtimer_cancel(
3621 &sqcp->sd_hrtp->hrt);
3622 } else if (scsi_debug_delay > 0) {
3623 if (sqcp->cmnd_timerp)
3624 del_timer_sync(
3625 sqcp->cmnd_timerp);
3626 } else if (scsi_debug_delay < 0) {
3627 if (sqcp->tletp)
3628 tasklet_kill(sqcp->tletp);
3629 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003630 clear_bit(k, queued_in_use_bm);
3631 return 1;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003632 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003633 }
3634 }
3635 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003636 return 0;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003637}
3638
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003639/* Deletes (stops) timers or tasklets of all queued commands */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003640static void stop_all_queued(void)
3641{
3642 unsigned long iflags;
3643 int k;
3644 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003645 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003646
3647 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003648 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3649 if (test_bit(k, queued_in_use_bm)) {
3650 sqcp = &queued_arr[k];
3651 if (sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003652 devip = (struct sdebug_dev_info *)
3653 sqcp->a_cmnd->device->hostdata;
3654 if (devip)
3655 atomic_dec(&devip->num_in_q);
3656 sqcp->a_cmnd = NULL;
3657 spin_unlock_irqrestore(&queued_arr_lock,
3658 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003659 if (scsi_debug_ndelay > 0) {
3660 if (sqcp->sd_hrtp)
3661 hrtimer_cancel(
3662 &sqcp->sd_hrtp->hrt);
3663 } else if (scsi_debug_delay > 0) {
3664 if (sqcp->cmnd_timerp)
3665 del_timer_sync(
3666 sqcp->cmnd_timerp);
3667 } else if (scsi_debug_delay < 0) {
3668 if (sqcp->tletp)
3669 tasklet_kill(sqcp->tletp);
3670 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003671 clear_bit(k, queued_in_use_bm);
3672 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003673 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003674 }
3675 }
3676 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677}
3678
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003679/* Free queued command memory on heap */
3680static void free_all_queued(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003682 unsigned long iflags;
3683 int k;
3684 struct sdebug_queued_cmd *sqcp;
3685
3686 spin_lock_irqsave(&queued_arr_lock, iflags);
3687 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3688 sqcp = &queued_arr[k];
3689 kfree(sqcp->cmnd_timerp);
3690 sqcp->cmnd_timerp = NULL;
3691 kfree(sqcp->tletp);
3692 sqcp->tletp = NULL;
3693 kfree(sqcp->sd_hrtp);
3694 sqcp->sd_hrtp = NULL;
3695 }
3696 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697}
3698
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003699static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003701 ++num_aborts;
3702 if (SCpnt) {
3703 if (SCpnt->device &&
3704 (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3705 sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
3706 __func__);
3707 stop_queued_cmnd(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003709 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710}
3711
3712static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
3713{
3714 struct sdebug_dev_info * devip;
3715
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 ++num_dev_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003717 if (SCpnt && SCpnt->device) {
3718 struct scsi_device *sdp = SCpnt->device;
3719
3720 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3721 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3722 devip = devInfoReg(sdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 if (devip)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003724 set_bit(SDEBUG_UA_POR, devip->uas_bm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 }
3726 return SUCCESS;
3727}
3728
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003729static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
3730{
3731 struct sdebug_host_info *sdbg_host;
3732 struct sdebug_dev_info *devip;
3733 struct scsi_device *sdp;
3734 struct Scsi_Host *hp;
3735 int k = 0;
3736
3737 ++num_target_resets;
3738 if (!SCpnt)
3739 goto lie;
3740 sdp = SCpnt->device;
3741 if (!sdp)
3742 goto lie;
3743 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3744 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3745 hp = sdp->host;
3746 if (!hp)
3747 goto lie;
3748 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
3749 if (sdbg_host) {
3750 list_for_each_entry(devip,
3751 &sdbg_host->dev_info_list,
3752 dev_list)
3753 if (devip->target == sdp->id) {
3754 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3755 ++k;
3756 }
3757 }
3758 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3759 sdev_printk(KERN_INFO, sdp,
3760 "%s: %d device(s) found in target\n", __func__, k);
3761lie:
3762 return SUCCESS;
3763}
3764
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
3766{
3767 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003768 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 struct scsi_device * sdp;
3770 struct Scsi_Host * hp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003771 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 ++num_bus_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003774 if (!(SCpnt && SCpnt->device))
3775 goto lie;
3776 sdp = SCpnt->device;
3777 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3778 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3779 hp = sdp->host;
3780 if (hp) {
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003781 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 if (sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003783 list_for_each_entry(devip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 &sdbg_host->dev_info_list,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003785 dev_list) {
3786 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3787 ++k;
3788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 }
3790 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003791 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3792 sdev_printk(KERN_INFO, sdp,
3793 "%s: %d device(s) found in host\n", __func__, k);
3794lie:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 return SUCCESS;
3796}
3797
3798static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
3799{
3800 struct sdebug_host_info * sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003801 struct sdebug_dev_info *devip;
3802 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 ++num_host_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003805 if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3806 sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 spin_lock(&sdebug_host_list_lock);
3808 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003809 list_for_each_entry(devip, &sdbg_host->dev_info_list,
3810 dev_list) {
3811 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3812 ++k;
3813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 }
3815 spin_unlock(&sdebug_host_list_lock);
3816 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003817 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3818 sdev_printk(KERN_INFO, SCpnt->device,
3819 "%s: %d device(s) found\n", __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 return SUCCESS;
3821}
3822
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003823static void __init sdebug_build_parts(unsigned char *ramp,
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003824 unsigned long store_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825{
3826 struct partition * pp;
3827 int starts[SDEBUG_MAX_PARTS + 2];
3828 int sectors_per_part, num_sectors, k;
3829 int heads_by_sects, start_sec, end_sec;
3830
3831 /* assume partition table already zeroed */
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003832 if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 return;
3834 if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
3835 scsi_debug_num_parts = SDEBUG_MAX_PARTS;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003836 pr_warn("%s: reducing partitions to %d\n", __func__,
3837 SDEBUG_MAX_PARTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003839 num_sectors = (int)sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 sectors_per_part = (num_sectors - sdebug_sectors_per)
3841 / scsi_debug_num_parts;
3842 heads_by_sects = sdebug_heads * sdebug_sectors_per;
3843 starts[0] = sdebug_sectors_per;
3844 for (k = 1; k < scsi_debug_num_parts; ++k)
3845 starts[k] = ((k * sectors_per_part) / heads_by_sects)
3846 * heads_by_sects;
3847 starts[scsi_debug_num_parts] = num_sectors;
3848 starts[scsi_debug_num_parts + 1] = 0;
3849
3850 ramp[510] = 0x55; /* magic partition markings */
3851 ramp[511] = 0xAA;
3852 pp = (struct partition *)(ramp + 0x1be);
3853 for (k = 0; starts[k + 1]; ++k, ++pp) {
3854 start_sec = starts[k];
3855 end_sec = starts[k + 1] - 1;
3856 pp->boot_ind = 0;
3857
3858 pp->cyl = start_sec / heads_by_sects;
3859 pp->head = (start_sec - (pp->cyl * heads_by_sects))
3860 / sdebug_sectors_per;
3861 pp->sector = (start_sec % sdebug_sectors_per) + 1;
3862
3863 pp->end_cyl = end_sec / heads_by_sects;
3864 pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
3865 / sdebug_sectors_per;
3866 pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
3867
Akinobu Mita150c3542013-08-26 22:08:40 +09003868 pp->start_sect = cpu_to_le32(start_sec);
3869 pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 pp->sys_ind = 0x83; /* plain Linux partition */
3871 }
3872}
3873
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003874static int
3875schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
3876 int scsi_result, int delta_jiff)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003878 unsigned long iflags;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003879 int k, num_in_q, qdepth, inject;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003880 struct sdebug_queued_cmd *sqcp = NULL;
3881 struct scsi_device *sdp = cmnd->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003883 if (NULL == cmnd || NULL == devip) {
3884 pr_warn("%s: called with NULL cmnd or devip pointer\n",
3885 __func__);
3886 /* no particularly good error to report back */
3887 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003889 if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3890 sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
3891 __func__, scsi_result);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003892 if (delta_jiff == 0)
3893 goto respond_in_thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003895 /* schedule the response at a later time if resources permit */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003896 spin_lock_irqsave(&queued_arr_lock, iflags);
3897 num_in_q = atomic_read(&devip->num_in_q);
3898 qdepth = cmnd->device->queue_depth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003899 inject = 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003900 if ((qdepth > 0) && (num_in_q >= qdepth)) {
3901 if (scsi_result) {
3902 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3903 goto respond_in_thread;
3904 } else
3905 scsi_result = device_qfull_result;
3906 } else if ((scsi_debug_every_nth != 0) &&
3907 (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) &&
3908 (scsi_result == 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003909 if ((num_in_q == (qdepth - 1)) &&
3910 (atomic_inc_return(&sdebug_a_tsf) >=
3911 abs(scsi_debug_every_nth))) {
3912 atomic_set(&sdebug_a_tsf, 0);
3913 inject = 1;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003914 scsi_result = device_qfull_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003916 }
3917
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003918 k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003919 if (k >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003921 if (scsi_result)
3922 goto respond_in_thread;
3923 else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
3924 scsi_result = device_qfull_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003925 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
3926 sdev_printk(KERN_INFO, sdp,
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003927 "%s: max_queue=%d exceeded, %s\n",
3928 __func__, scsi_debug_max_queue,
3929 (scsi_result ? "status: TASK SET FULL" :
3930 "report: host busy"));
3931 if (scsi_result)
3932 goto respond_in_thread;
3933 else
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003934 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003936 __set_bit(k, queued_in_use_bm);
3937 atomic_inc(&devip->num_in_q);
3938 sqcp = &queued_arr[k];
3939 sqcp->a_cmnd = cmnd;
3940 cmnd->result = scsi_result;
3941 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3942 if (delta_jiff > 0) {
3943 if (NULL == sqcp->cmnd_timerp) {
3944 sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
3945 GFP_ATOMIC);
3946 if (NULL == sqcp->cmnd_timerp)
3947 return SCSI_MLQUEUE_HOST_BUSY;
3948 init_timer(sqcp->cmnd_timerp);
3949 }
3950 sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
3951 sqcp->cmnd_timerp->data = k;
3952 sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
3953 add_timer(sqcp->cmnd_timerp);
3954 } else if (scsi_debug_ndelay > 0) {
3955 ktime_t kt = ktime_set(0, scsi_debug_ndelay);
3956 struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
3957
3958 if (NULL == sd_hp) {
3959 sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
3960 if (NULL == sd_hp)
3961 return SCSI_MLQUEUE_HOST_BUSY;
3962 sqcp->sd_hrtp = sd_hp;
3963 hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
3964 HRTIMER_MODE_REL);
3965 sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
3966 sd_hp->qa_indx = k;
3967 }
3968 hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
3969 } else { /* delay < 0 */
3970 if (NULL == sqcp->tletp) {
3971 sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
3972 GFP_ATOMIC);
3973 if (NULL == sqcp->tletp)
3974 return SCSI_MLQUEUE_HOST_BUSY;
3975 tasklet_init(sqcp->tletp,
3976 sdebug_q_cmd_complete, k);
3977 }
3978 if (-1 == delta_jiff)
3979 tasklet_hi_schedule(sqcp->tletp);
3980 else
3981 tasklet_schedule(sqcp->tletp);
3982 }
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003983 if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) &&
3984 (scsi_result == device_qfull_result))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003985 sdev_printk(KERN_INFO, sdp,
3986 "%s: num_in_q=%d +1, %s%s\n", __func__,
3987 num_in_q, (inject ? "<inject> " : ""),
3988 "status: TASK SET FULL");
3989 return 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003990
3991respond_in_thread: /* call back to mid-layer using invocation thread */
3992 cmnd->result = scsi_result;
3993 cmnd->scsi_done(cmnd);
3994 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003996
Douglas Gilbert23183912006-09-16 20:30:47 -04003997/* Note: The following macros create attribute files in the
3998 /sys/module/scsi_debug/parameters directory. Unfortunately this
3999 driver is unaware of a change and cannot trigger auxiliary actions
4000 as it can when the corresponding attribute in the
4001 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
4002 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004003module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004004module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
Akinobu Mita0759c662014-02-26 22:57:04 +09004005module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004006module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
4007module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004008module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
4009module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004010module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
4011module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004012module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004013module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004014module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004015module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
4016module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
4017module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004018module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004019module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004020module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004021module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004022module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004023module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004024module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004025module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
4026module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004027module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004028module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004029module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004030module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
Martin Pittd9867882012-09-06 12:04:33 +02004031module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004032module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004033module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004034module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004035module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
4036module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
4037module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
4038module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004039module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004040module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
4041 S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004042module_param_named(write_same_length, scsi_debug_write_same_length, int,
4043 S_IRUGO | S_IWUSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044
4045MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
4046MODULE_DESCRIPTION("SCSI debug adapter driver");
4047MODULE_LICENSE("GPL");
4048MODULE_VERSION(SCSI_DEBUG_VERSION);
4049
4050MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004051MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
Akinobu Mita0759c662014-02-26 22:57:04 +09004052MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004053MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004054MODULE_PARM_DESC(dev_size_mb, "size in MiB of ram shared by devs(def=8)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004055MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
4056MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004057MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
Randy Dunlapbeb87c32007-06-11 11:36:40 -07004058MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
Douglas Gilbert23183912006-09-16 20:30:47 -04004059MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004060MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004061MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004062MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
4063MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
4064MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004065MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004066MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004067MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004068MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
4069MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004070MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004071MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004073MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004074MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05004075MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004076MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
Martin Pittd9867882012-09-06 12:04:33 +02004078MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
Douglas Gilberte46b0342014-08-05 12:21:53 +02004079MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004080MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004081MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004082MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
4083MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
Martin K. Petersen60147592010-08-19 11:49:00 -04004084MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
4085MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004086MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004087MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
4088MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
4090static char sdebug_info[256];
4091
4092static const char * scsi_debug_info(struct Scsi_Host * shp)
4093{
4094 sprintf(sdebug_info, "scsi_debug, version %s [%s], "
4095 "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
4096 scsi_debug_version_date, scsi_debug_dev_size_mb,
4097 scsi_debug_opts);
4098 return sdebug_info;
4099}
4100
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004101/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
Al Viroc8ed5552013-03-31 01:46:06 -04004102static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103{
Al Viroc8ed5552013-03-31 01:46:06 -04004104 char arr[16];
4105 int opts;
4106 int minLen = length > 15 ? 15 : length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Al Viroc8ed5552013-03-31 01:46:06 -04004108 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
4109 return -EACCES;
4110 memcpy(arr, buffer, minLen);
4111 arr[minLen] = '\0';
4112 if (1 != sscanf(arr, "%d", &opts))
4113 return -EINVAL;
4114 scsi_debug_opts = opts;
4115 if (scsi_debug_every_nth != 0)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004116 atomic_set(&sdebug_cmnd_count, 0);
Al Viroc8ed5552013-03-31 01:46:06 -04004117 return length;
4118}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004120/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
4121 * same for each scsi_debug host (if more than one). Some of the counters
4122 * output are not atomics so might be inaccurate in a busy system. */
Al Viroc8ed5552013-03-31 01:46:06 -04004123static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
4124{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004125 int f, l;
4126 char b[32];
4127
4128 if (scsi_debug_every_nth > 0)
4129 snprintf(b, sizeof(b), " (curr:%d)",
4130 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
4131 atomic_read(&sdebug_a_tsf) :
4132 atomic_read(&sdebug_cmnd_count)));
4133 else
4134 b[0] = '\0';
4135
4136 seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
4137 "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
4138 "every_nth=%d%s\n"
4139 "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
4140 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
4141 "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
4142 "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
4143 "usec_in_jiffy=%lu\n",
4144 SCSI_DEBUG_VERSION, scsi_debug_version_date,
4145 scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
4146 scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
4147 scsi_debug_max_luns, atomic_read(&sdebug_completions),
4148 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
4149 sdebug_sectors_per, num_aborts, num_dev_resets,
4150 num_target_resets, num_bus_resets, num_host_resets,
4151 dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
4152
4153 f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
4154 if (f != scsi_debug_max_queue) {
4155 l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
4156 seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n",
4157 "queued_in_use_bm", f, l);
4158 }
Al Viroc8ed5552013-03-31 01:46:06 -04004159 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160}
4161
Akinobu Mita82069372013-10-14 22:48:04 +09004162static ssize_t delay_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163{
4164 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
4165}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004166/* Returns -EBUSY if delay is being changed and commands are queued */
Akinobu Mita82069372013-10-14 22:48:04 +09004167static ssize_t delay_store(struct device_driver *ddp, const char *buf,
4168 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004170 int delay, res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004172 if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
4173 res = count;
4174 if (scsi_debug_delay != delay) {
4175 unsigned long iflags;
4176 int k;
4177
4178 spin_lock_irqsave(&queued_arr_lock, iflags);
4179 k = find_first_bit(queued_in_use_bm,
4180 scsi_debug_max_queue);
4181 if (k != scsi_debug_max_queue)
4182 res = -EBUSY; /* have queued commands */
4183 else {
4184 scsi_debug_delay = delay;
4185 scsi_debug_ndelay = 0;
4186 }
4187 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004189 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 }
4191 return -EINVAL;
4192}
Akinobu Mita82069372013-10-14 22:48:04 +09004193static DRIVER_ATTR_RW(delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004195static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
4196{
4197 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
4198}
4199/* Returns -EBUSY if ndelay is being changed and commands are queued */
4200/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
4201static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
4202 size_t count)
4203{
4204 unsigned long iflags;
4205 int ndelay, res, k;
4206
4207 if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
4208 (ndelay >= 0) && (ndelay < 1000000000)) {
4209 res = count;
4210 if (scsi_debug_ndelay != ndelay) {
4211 spin_lock_irqsave(&queued_arr_lock, iflags);
4212 k = find_first_bit(queued_in_use_bm,
4213 scsi_debug_max_queue);
4214 if (k != scsi_debug_max_queue)
4215 res = -EBUSY; /* have queued commands */
4216 else {
4217 scsi_debug_ndelay = ndelay;
4218 scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
4219 : DEF_DELAY;
4220 }
4221 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4222 }
4223 return res;
4224 }
4225 return -EINVAL;
4226}
4227static DRIVER_ATTR_RW(ndelay);
4228
Akinobu Mita82069372013-10-14 22:48:04 +09004229static ssize_t opts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230{
4231 return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
4232}
4233
Akinobu Mita82069372013-10-14 22:48:04 +09004234static ssize_t opts_store(struct device_driver *ddp, const char *buf,
4235 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
4237 int opts;
4238 char work[20];
4239
4240 if (1 == sscanf(buf, "%10s", work)) {
Rasmus Villemoes48a96872014-10-13 15:54:44 -07004241 if (0 == strncasecmp(work,"0x", 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 if (1 == sscanf(&work[2], "%x", &opts))
4243 goto opts_done;
4244 } else {
4245 if (1 == sscanf(work, "%d", &opts))
4246 goto opts_done;
4247 }
4248 }
4249 return -EINVAL;
4250opts_done:
4251 scsi_debug_opts = opts;
Douglas Gilbert817fd662014-11-24 20:18:02 -05004252 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
4253 sdebug_any_injecting_opt = true;
4254 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
4255 sdebug_any_injecting_opt = true;
4256 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
4257 sdebug_any_injecting_opt = true;
4258 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
4259 sdebug_any_injecting_opt = true;
4260 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
4261 sdebug_any_injecting_opt = true;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004262 atomic_set(&sdebug_cmnd_count, 0);
4263 atomic_set(&sdebug_a_tsf, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 return count;
4265}
Akinobu Mita82069372013-10-14 22:48:04 +09004266static DRIVER_ATTR_RW(opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Akinobu Mita82069372013-10-14 22:48:04 +09004268static ssize_t ptype_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269{
4270 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
4271}
Akinobu Mita82069372013-10-14 22:48:04 +09004272static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
4273 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274{
4275 int n;
4276
4277 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4278 scsi_debug_ptype = n;
4279 return count;
4280 }
4281 return -EINVAL;
4282}
Akinobu Mita82069372013-10-14 22:48:04 +09004283static DRIVER_ATTR_RW(ptype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284
Akinobu Mita82069372013-10-14 22:48:04 +09004285static ssize_t dsense_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286{
4287 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
4288}
Akinobu Mita82069372013-10-14 22:48:04 +09004289static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
4290 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291{
4292 int n;
4293
4294 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4295 scsi_debug_dsense = n;
4296 return count;
4297 }
4298 return -EINVAL;
4299}
Akinobu Mita82069372013-10-14 22:48:04 +09004300static DRIVER_ATTR_RW(dsense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301
Akinobu Mita82069372013-10-14 22:48:04 +09004302static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004303{
4304 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
4305}
Akinobu Mita82069372013-10-14 22:48:04 +09004306static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
4307 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004308{
4309 int n;
4310
4311 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004312 n = (n > 0);
4313 scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
4314 if (scsi_debug_fake_rw != n) {
4315 if ((0 == n) && (NULL == fake_storep)) {
4316 unsigned long sz =
4317 (unsigned long)scsi_debug_dev_size_mb *
4318 1048576;
4319
4320 fake_storep = vmalloc(sz);
4321 if (NULL == fake_storep) {
4322 pr_err("%s: out of memory, 9\n",
4323 __func__);
4324 return -ENOMEM;
4325 }
4326 memset(fake_storep, 0, sz);
4327 }
4328 scsi_debug_fake_rw = n;
4329 }
Douglas Gilbert23183912006-09-16 20:30:47 -04004330 return count;
4331 }
4332 return -EINVAL;
4333}
Akinobu Mita82069372013-10-14 22:48:04 +09004334static DRIVER_ATTR_RW(fake_rw);
Douglas Gilbert23183912006-09-16 20:30:47 -04004335
Akinobu Mita82069372013-10-14 22:48:04 +09004336static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004337{
4338 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
4339}
Akinobu Mita82069372013-10-14 22:48:04 +09004340static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
4341 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004342{
4343 int n;
4344
4345 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4346 scsi_debug_no_lun_0 = n;
4347 return count;
4348 }
4349 return -EINVAL;
4350}
Akinobu Mita82069372013-10-14 22:48:04 +09004351static DRIVER_ATTR_RW(no_lun_0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004352
Akinobu Mita82069372013-10-14 22:48:04 +09004353static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354{
4355 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
4356}
Akinobu Mita82069372013-10-14 22:48:04 +09004357static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
4358 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359{
4360 int n;
4361
4362 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4363 scsi_debug_num_tgts = n;
4364 sdebug_max_tgts_luns();
4365 return count;
4366 }
4367 return -EINVAL;
4368}
Akinobu Mita82069372013-10-14 22:48:04 +09004369static DRIVER_ATTR_RW(num_tgts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370
Akinobu Mita82069372013-10-14 22:48:04 +09004371static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372{
4373 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
4374}
Akinobu Mita82069372013-10-14 22:48:04 +09004375static DRIVER_ATTR_RO(dev_size_mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
Akinobu Mita82069372013-10-14 22:48:04 +09004377static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378{
4379 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
4380}
Akinobu Mita82069372013-10-14 22:48:04 +09004381static DRIVER_ATTR_RO(num_parts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
Akinobu Mita82069372013-10-14 22:48:04 +09004383static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384{
4385 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
4386}
Akinobu Mita82069372013-10-14 22:48:04 +09004387static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
4388 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389{
4390 int nth;
4391
4392 if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
4393 scsi_debug_every_nth = nth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004394 atomic_set(&sdebug_cmnd_count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395 return count;
4396 }
4397 return -EINVAL;
4398}
Akinobu Mita82069372013-10-14 22:48:04 +09004399static DRIVER_ATTR_RW(every_nth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400
Akinobu Mita82069372013-10-14 22:48:04 +09004401static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402{
4403 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
4404}
Akinobu Mita82069372013-10-14 22:48:04 +09004405static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
4406 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407{
4408 int n;
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004409 bool changed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
4411 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004412 changed = (scsi_debug_max_luns != n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413 scsi_debug_max_luns = n;
4414 sdebug_max_tgts_luns();
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004415 if (changed && (scsi_debug_scsi_level >= 5)) { /* >= SPC-3 */
4416 struct sdebug_host_info *sdhp;
4417 struct sdebug_dev_info *dp;
4418
4419 spin_lock(&sdebug_host_list_lock);
4420 list_for_each_entry(sdhp, &sdebug_host_list,
4421 host_list) {
4422 list_for_each_entry(dp, &sdhp->dev_info_list,
4423 dev_list) {
4424 set_bit(SDEBUG_UA_LUNS_CHANGED,
4425 dp->uas_bm);
4426 }
4427 }
4428 spin_unlock(&sdebug_host_list_lock);
4429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 return count;
4431 }
4432 return -EINVAL;
4433}
Akinobu Mita82069372013-10-14 22:48:04 +09004434static DRIVER_ATTR_RW(max_luns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Akinobu Mita82069372013-10-14 22:48:04 +09004436static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004437{
4438 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
4439}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004440/* N.B. max_queue can be changed while there are queued commands. In flight
4441 * commands beyond the new max_queue will be completed. */
Akinobu Mita82069372013-10-14 22:48:04 +09004442static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
4443 size_t count)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004444{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004445 unsigned long iflags;
4446 int n, k;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004447
4448 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
4449 (n <= SCSI_DEBUG_CANQUEUE)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004450 spin_lock_irqsave(&queued_arr_lock, iflags);
4451 k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004452 scsi_debug_max_queue = n;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004453 if (SCSI_DEBUG_CANQUEUE == k)
4454 atomic_set(&retired_max_queue, 0);
4455 else if (k >= n)
4456 atomic_set(&retired_max_queue, k + 1);
4457 else
4458 atomic_set(&retired_max_queue, 0);
4459 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004460 return count;
4461 }
4462 return -EINVAL;
4463}
Akinobu Mita82069372013-10-14 22:48:04 +09004464static DRIVER_ATTR_RW(max_queue);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004465
Akinobu Mita82069372013-10-14 22:48:04 +09004466static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004467{
4468 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
4469}
Akinobu Mita82069372013-10-14 22:48:04 +09004470static DRIVER_ATTR_RO(no_uld);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004471
Akinobu Mita82069372013-10-14 22:48:04 +09004472static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473{
4474 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
4475}
Akinobu Mita82069372013-10-14 22:48:04 +09004476static DRIVER_ATTR_RO(scsi_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477
Akinobu Mita82069372013-10-14 22:48:04 +09004478static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004479{
4480 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
4481}
Akinobu Mita82069372013-10-14 22:48:04 +09004482static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
4483 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004484{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004485 int n;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004486 bool changed;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004487
4488 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004489 changed = (scsi_debug_virtual_gb != n);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004490 scsi_debug_virtual_gb = n;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004491 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004492 if (changed) {
4493 struct sdebug_host_info *sdhp;
4494 struct sdebug_dev_info *dp;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004495
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004496 spin_lock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004497 list_for_each_entry(sdhp, &sdebug_host_list,
4498 host_list) {
4499 list_for_each_entry(dp, &sdhp->dev_info_list,
4500 dev_list) {
4501 set_bit(SDEBUG_UA_CAPACITY_CHANGED,
4502 dp->uas_bm);
4503 }
4504 }
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004505 spin_unlock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004506 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004507 return count;
4508 }
4509 return -EINVAL;
4510}
Akinobu Mita82069372013-10-14 22:48:04 +09004511static DRIVER_ATTR_RW(virtual_gb);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004512
Akinobu Mita82069372013-10-14 22:48:04 +09004513static ssize_t add_host_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514{
4515 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
4516}
4517
Akinobu Mita82069372013-10-14 22:48:04 +09004518static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
4519 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520{
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004521 int delta_hosts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004523 if (sscanf(buf, "%d", &delta_hosts) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 if (delta_hosts > 0) {
4526 do {
4527 sdebug_add_adapter();
4528 } while (--delta_hosts);
4529 } else if (delta_hosts < 0) {
4530 do {
4531 sdebug_remove_adapter();
4532 } while (++delta_hosts);
4533 }
4534 return count;
4535}
Akinobu Mita82069372013-10-14 22:48:04 +09004536static DRIVER_ATTR_RW(add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537
Akinobu Mita82069372013-10-14 22:48:04 +09004538static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004539{
4540 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
4541}
Akinobu Mita82069372013-10-14 22:48:04 +09004542static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
4543 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004544{
4545 int n;
4546
4547 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4548 scsi_debug_vpd_use_hostno = n;
4549 return count;
4550 }
4551 return -EINVAL;
4552}
Akinobu Mita82069372013-10-14 22:48:04 +09004553static DRIVER_ATTR_RW(vpd_use_hostno);
Douglas Gilbert23183912006-09-16 20:30:47 -04004554
Akinobu Mita82069372013-10-14 22:48:04 +09004555static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
Martin K. Petersen597136a2008-06-05 00:12:59 -04004556{
4557 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
4558}
Akinobu Mita82069372013-10-14 22:48:04 +09004559static DRIVER_ATTR_RO(sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04004560
Akinobu Mita82069372013-10-14 22:48:04 +09004561static ssize_t dix_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004562{
4563 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
4564}
Akinobu Mita82069372013-10-14 22:48:04 +09004565static DRIVER_ATTR_RO(dix);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004566
Akinobu Mita82069372013-10-14 22:48:04 +09004567static ssize_t dif_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004568{
4569 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
4570}
Akinobu Mita82069372013-10-14 22:48:04 +09004571static DRIVER_ATTR_RO(dif);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004572
Akinobu Mita82069372013-10-14 22:48:04 +09004573static ssize_t guard_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004574{
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004575 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004576}
Akinobu Mita82069372013-10-14 22:48:04 +09004577static DRIVER_ATTR_RO(guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004578
Akinobu Mita82069372013-10-14 22:48:04 +09004579static ssize_t ato_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004580{
4581 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
4582}
Akinobu Mita82069372013-10-14 22:48:04 +09004583static DRIVER_ATTR_RO(ato);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004584
Akinobu Mita82069372013-10-14 22:48:04 +09004585static ssize_t map_show(struct device_driver *ddp, char *buf)
Martin K. Petersen44d92692009-10-15 14:45:27 -04004586{
4587 ssize_t count;
4588
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004589 if (!scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04004590 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
4591 sdebug_store_sectors);
4592
4593 count = bitmap_scnlistprintf(buf, PAGE_SIZE, map_storep, map_size);
4594
4595 buf[count++] = '\n';
4596 buf[count++] = 0;
4597
4598 return count;
4599}
Akinobu Mita82069372013-10-14 22:48:04 +09004600static DRIVER_ATTR_RO(map);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004601
Akinobu Mita82069372013-10-14 22:48:04 +09004602static ssize_t removable_show(struct device_driver *ddp, char *buf)
Martin Pittd9867882012-09-06 12:04:33 +02004603{
4604 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
4605}
Akinobu Mita82069372013-10-14 22:48:04 +09004606static ssize_t removable_store(struct device_driver *ddp, const char *buf,
4607 size_t count)
Martin Pittd9867882012-09-06 12:04:33 +02004608{
4609 int n;
4610
4611 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4612 scsi_debug_removable = (n > 0);
4613 return count;
4614 }
4615 return -EINVAL;
4616}
Akinobu Mita82069372013-10-14 22:48:04 +09004617static DRIVER_ATTR_RW(removable);
Martin Pittd9867882012-09-06 12:04:33 +02004618
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004619static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
4620{
4621 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
4622}
4623/* Returns -EBUSY if host_lock is being changed and commands are queued */
4624static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
4625 size_t count)
4626{
4627 int n, res;
4628
4629 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4630 bool new_host_lock = (n > 0);
4631
4632 res = count;
4633 if (new_host_lock != scsi_debug_host_lock) {
4634 unsigned long iflags;
4635 int k;
4636
4637 spin_lock_irqsave(&queued_arr_lock, iflags);
4638 k = find_first_bit(queued_in_use_bm,
4639 scsi_debug_max_queue);
4640 if (k != scsi_debug_max_queue)
4641 res = -EBUSY; /* have queued commands */
4642 else
4643 scsi_debug_host_lock = new_host_lock;
4644 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4645 }
4646 return res;
4647 }
4648 return -EINVAL;
4649}
4650static DRIVER_ATTR_RW(host_lock);
4651
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004652static ssize_t strict_show(struct device_driver *ddp, char *buf)
4653{
4654 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict);
4655}
4656static ssize_t strict_store(struct device_driver *ddp, const char *buf,
4657 size_t count)
4658{
4659 int n;
4660
4661 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4662 scsi_debug_strict = (n > 0);
4663 return count;
4664 }
4665 return -EINVAL;
4666}
4667static DRIVER_ATTR_RW(strict);
4668
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004669
Akinobu Mita82069372013-10-14 22:48:04 +09004670/* Note: The following array creates attribute files in the
Douglas Gilbert23183912006-09-16 20:30:47 -04004671 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
4672 files (over those found in the /sys/module/scsi_debug/parameters
4673 directory) is that auxiliary actions can be triggered when an attribute
4674 is changed. For example see: sdebug_add_host_store() above.
4675 */
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004676
Akinobu Mita82069372013-10-14 22:48:04 +09004677static struct attribute *sdebug_drv_attrs[] = {
4678 &driver_attr_delay.attr,
4679 &driver_attr_opts.attr,
4680 &driver_attr_ptype.attr,
4681 &driver_attr_dsense.attr,
4682 &driver_attr_fake_rw.attr,
4683 &driver_attr_no_lun_0.attr,
4684 &driver_attr_num_tgts.attr,
4685 &driver_attr_dev_size_mb.attr,
4686 &driver_attr_num_parts.attr,
4687 &driver_attr_every_nth.attr,
4688 &driver_attr_max_luns.attr,
4689 &driver_attr_max_queue.attr,
4690 &driver_attr_no_uld.attr,
4691 &driver_attr_scsi_level.attr,
4692 &driver_attr_virtual_gb.attr,
4693 &driver_attr_add_host.attr,
4694 &driver_attr_vpd_use_hostno.attr,
4695 &driver_attr_sector_size.attr,
4696 &driver_attr_dix.attr,
4697 &driver_attr_dif.attr,
4698 &driver_attr_guard.attr,
4699 &driver_attr_ato.attr,
4700 &driver_attr_map.attr,
4701 &driver_attr_removable.attr,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004702 &driver_attr_host_lock.attr,
4703 &driver_attr_ndelay.attr,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004704 &driver_attr_strict.attr,
Akinobu Mita82069372013-10-14 22:48:04 +09004705 NULL,
4706};
4707ATTRIBUTE_GROUPS(sdebug_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708
Akinobu Mita11ddcec2014-02-26 22:56:59 +09004709static struct device *pseudo_primary;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004710
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711static int __init scsi_debug_init(void)
4712{
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004713 unsigned long sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714 int host_to_add;
4715 int k;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004716 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004718 atomic_set(&sdebug_cmnd_count, 0);
4719 atomic_set(&sdebug_completions, 0);
4720 atomic_set(&retired_max_queue, 0);
4721
4722 if (scsi_debug_ndelay >= 1000000000) {
4723 pr_warn("%s: ndelay must be less than 1 second, ignored\n",
4724 __func__);
4725 scsi_debug_ndelay = 0;
4726 } else if (scsi_debug_ndelay > 0)
4727 scsi_debug_delay = DELAY_OVERRIDDEN;
4728
Martin K. Petersen597136a2008-06-05 00:12:59 -04004729 switch (scsi_debug_sector_size) {
4730 case 512:
4731 case 1024:
4732 case 2048:
4733 case 4096:
4734 break;
4735 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004736 pr_err("%s: invalid sector_size %d\n", __func__,
Martin K. Petersen597136a2008-06-05 00:12:59 -04004737 scsi_debug_sector_size);
4738 return -EINVAL;
4739 }
4740
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004741 switch (scsi_debug_dif) {
4742
4743 case SD_DIF_TYPE0_PROTECTION:
4744 case SD_DIF_TYPE1_PROTECTION:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004745 case SD_DIF_TYPE2_PROTECTION:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004746 case SD_DIF_TYPE3_PROTECTION:
4747 break;
4748
4749 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004750 pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004751 return -EINVAL;
4752 }
4753
4754 if (scsi_debug_guard > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004755 pr_err("%s: guard must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004756 return -EINVAL;
4757 }
4758
4759 if (scsi_debug_ato > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004760 pr_err("%s: ato must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004761 return -EINVAL;
4762 }
4763
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004764 if (scsi_debug_physblk_exp > 15) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004765 pr_err("%s: invalid physblk_exp %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004766 scsi_debug_physblk_exp);
4767 return -EINVAL;
4768 }
4769
4770 if (scsi_debug_lowest_aligned > 0x3fff) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004771 pr_err("%s: lowest_aligned too big: %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004772 scsi_debug_lowest_aligned);
4773 return -EINVAL;
4774 }
4775
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776 if (scsi_debug_dev_size_mb < 1)
4777 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004778 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
Martin K. Petersen597136a2008-06-05 00:12:59 -04004779 sdebug_store_sectors = sz / scsi_debug_sector_size;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004780 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781
4782 /* play around with geometry, don't waste too much on track 0 */
4783 sdebug_heads = 8;
4784 sdebug_sectors_per = 32;
4785 if (scsi_debug_dev_size_mb >= 16)
4786 sdebug_heads = 32;
4787 else if (scsi_debug_dev_size_mb >= 256)
4788 sdebug_heads = 64;
4789 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4790 (sdebug_sectors_per * sdebug_heads);
4791 if (sdebug_cylinders_per >= 1024) {
4792 /* other LLDs do this; implies >= 1GB ram disk ... */
4793 sdebug_heads = 255;
4794 sdebug_sectors_per = 63;
4795 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4796 (sdebug_sectors_per * sdebug_heads);
4797 }
4798
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004799 if (0 == scsi_debug_fake_rw) {
4800 fake_storep = vmalloc(sz);
4801 if (NULL == fake_storep) {
4802 pr_err("%s: out of memory, 1\n", __func__);
4803 return -ENOMEM;
4804 }
4805 memset(fake_storep, 0, sz);
4806 if (scsi_debug_num_parts > 0)
4807 sdebug_build_parts(fake_storep, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809
Akinobu Mita7cb69d02013-06-29 17:59:16 +09004810 if (scsi_debug_dix) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004811 int dif_size;
4812
4813 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
4814 dif_storep = vmalloc(dif_size);
4815
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004816 pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size,
4817 dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004818
4819 if (dif_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004820 pr_err("%s: out of mem. (DIX)\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004821 ret = -ENOMEM;
4822 goto free_vm;
4823 }
4824
4825 memset(dif_storep, 0xff, dif_size);
4826 }
4827
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004828 /* Logical Block Provisioning */
4829 if (scsi_debug_lbp()) {
Martin K. Petersen60147592010-08-19 11:49:00 -04004830 scsi_debug_unmap_max_blocks =
4831 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
4832
4833 scsi_debug_unmap_max_desc =
4834 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
4835
4836 scsi_debug_unmap_granularity =
4837 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
4838
4839 if (scsi_debug_unmap_alignment &&
Akinobu Mitaac170782013-04-16 22:11:56 +09004840 scsi_debug_unmap_granularity <=
4841 scsi_debug_unmap_alignment) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004842 pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n",
Martin K. Petersen44d92692009-10-15 14:45:27 -04004843 __func__);
4844 return -EINVAL;
4845 }
4846
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004847 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
4848 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
Martin K. Petersen44d92692009-10-15 14:45:27 -04004849
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004850 pr_info("%s: %lu provisioning blocks\n", __func__, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004851
4852 if (map_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004853 pr_err("%s: out of mem. (MAP)\n", __func__);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004854 ret = -ENOMEM;
4855 goto free_vm;
4856 }
4857
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004858 bitmap_zero(map_storep, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004859
4860 /* Map first 1KB for partition table */
4861 if (scsi_debug_num_parts)
4862 map_region(0, 2);
4863 }
4864
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004865 pseudo_primary = root_device_register("pseudo_0");
4866 if (IS_ERR(pseudo_primary)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004867 pr_warn("%s: root_device_register() error\n", __func__);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004868 ret = PTR_ERR(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004869 goto free_vm;
4870 }
4871 ret = bus_register(&pseudo_lld_bus);
4872 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004873 pr_warn("%s: bus_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004874 goto dev_unreg;
4875 }
4876 ret = driver_register(&sdebug_driverfs_driver);
4877 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004878 pr_warn("%s: driver_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004879 goto bus_unreg;
4880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004881
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882 host_to_add = scsi_debug_add_host;
4883 scsi_debug_add_host = 0;
4884
4885 for (k = 0; k < host_to_add; k++) {
4886 if (sdebug_add_adapter()) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004887 pr_err("%s: sdebug_add_adapter failed k=%d\n",
4888 __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889 break;
4890 }
4891 }
4892
4893 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004894 pr_info("%s: built %d host(s)\n", __func__,
4895 scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896 }
4897 return 0;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004898
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004899bus_unreg:
4900 bus_unregister(&pseudo_lld_bus);
4901dev_unreg:
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004902 root_device_unregister(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004903free_vm:
Martin K. Petersen44d92692009-10-15 14:45:27 -04004904 if (map_storep)
4905 vfree(map_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004906 if (dif_storep)
4907 vfree(dif_storep);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004908 vfree(fake_storep);
4909
4910 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004911}
4912
4913static void __exit scsi_debug_exit(void)
4914{
4915 int k = scsi_debug_add_host;
4916
4917 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004918 free_all_queued();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919 for (; k; k--)
4920 sdebug_remove_adapter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921 driver_unregister(&sdebug_driverfs_driver);
4922 bus_unregister(&pseudo_lld_bus);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004923 root_device_unregister(pseudo_primary);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004925 if (dif_storep)
4926 vfree(dif_storep);
4927
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928 vfree(fake_storep);
4929}
4930
4931device_initcall(scsi_debug_init);
4932module_exit(scsi_debug_exit);
4933
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934static void sdebug_release_adapter(struct device * dev)
4935{
4936 struct sdebug_host_info *sdbg_host;
4937
4938 sdbg_host = to_sdebug_host(dev);
4939 kfree(sdbg_host);
4940}
4941
4942static int sdebug_add_adapter(void)
4943{
4944 int k, devs_per_host;
4945 int error = 0;
4946 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004947 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004949 sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004950 if (NULL == sdbg_host) {
4951 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004952 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953 return -ENOMEM;
4954 }
4955
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956 INIT_LIST_HEAD(&sdbg_host->dev_info_list);
4957
4958 devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
4959 for (k = 0; k < devs_per_host; k++) {
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09004960 sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
4961 if (!sdbg_devinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004963 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964 error = -ENOMEM;
4965 goto clean;
4966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967 }
4968
4969 spin_lock(&sdebug_host_list_lock);
4970 list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
4971 spin_unlock(&sdebug_host_list_lock);
4972
4973 sdbg_host->dev.bus = &pseudo_lld_bus;
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004974 sdbg_host->dev.parent = pseudo_primary;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975 sdbg_host->dev.release = &sdebug_release_adapter;
Kay Sievers71610f52008-12-03 22:41:36 +01004976 dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977
4978 error = device_register(&sdbg_host->dev);
4979
4980 if (error)
4981 goto clean;
4982
4983 ++scsi_debug_add_host;
4984 return error;
4985
4986clean:
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004987 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
4988 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 list_del(&sdbg_devinfo->dev_list);
4990 kfree(sdbg_devinfo);
4991 }
4992
4993 kfree(sdbg_host);
4994 return error;
4995}
4996
4997static void sdebug_remove_adapter(void)
4998{
4999 struct sdebug_host_info * sdbg_host = NULL;
5000
5001 spin_lock(&sdebug_host_list_lock);
5002 if (!list_empty(&sdebug_host_list)) {
5003 sdbg_host = list_entry(sdebug_host_list.prev,
5004 struct sdebug_host_info, host_list);
5005 list_del(&sdbg_host->host_list);
5006 }
5007 spin_unlock(&sdebug_host_list_lock);
5008
5009 if (!sdbg_host)
5010 return;
5011
5012 device_unregister(&sdbg_host->dev);
5013 --scsi_debug_add_host;
5014}
5015
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005016static int
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01005017sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005018{
5019 int num_in_q = 0;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005020 unsigned long iflags;
5021 struct sdebug_dev_info *devip;
5022
5023 spin_lock_irqsave(&queued_arr_lock, iflags);
5024 devip = (struct sdebug_dev_info *)sdev->hostdata;
5025 if (NULL == devip) {
5026 spin_unlock_irqrestore(&queued_arr_lock, iflags);
5027 return -ENODEV;
5028 }
5029 num_in_q = atomic_read(&devip->num_in_q);
5030 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005031
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005032 if (qdepth < 1)
5033 qdepth = 1;
5034 /* allow to exceed max host queued_arr elements for testing */
5035 if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
5036 qdepth = SCSI_DEBUG_CANQUEUE + 10;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01005037 scsi_change_queue_depth(sdev, qdepth);
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005038
5039 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
5040 sdev_printk(KERN_INFO, sdev,
5041 "%s: qdepth=%d, num_in_q=%d\n",
5042 __func__, qdepth, num_in_q);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005043 }
5044 return sdev->queue_depth;
5045}
5046
5047static int
Douglas Gilbert817fd662014-11-24 20:18:02 -05005048check_inject(struct scsi_cmnd *scp)
5049{
5050 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
5051
5052 memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
5053
5054 if (atomic_inc_return(&sdebug_cmnd_count) >=
5055 abs(scsi_debug_every_nth)) {
5056 atomic_set(&sdebug_cmnd_count, 0);
5057 if (scsi_debug_every_nth < -1)
5058 scsi_debug_every_nth = -1;
5059 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
5060 return 1; /* ignore command causing timeout */
5061 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
5062 scsi_medium_access_command(scp))
5063 return 1; /* time out reads and writes */
5064 if (sdebug_any_injecting_opt) {
5065 int opts = scsi_debug_opts;
5066
5067 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5068 ep->inj_recovered = true;
5069 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5070 ep->inj_transport = true;
5071 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5072 ep->inj_dif = true;
5073 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5074 ep->inj_dix = true;
5075 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5076 ep->inj_short = true;
5077 }
5078 }
5079 return 0;
5080}
5081
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05005082static int
5083scsi_debug_queuecommand(struct scsi_cmnd *scp)
5084{
5085 u8 sdeb_i;
5086 struct scsi_device *sdp = scp->device;
5087 const struct opcode_info_t *oip;
5088 const struct opcode_info_t *r_oip;
5089 struct sdebug_dev_info *devip;
5090 u8 *cmd = scp->cmnd;
5091 int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
5092 int k, na;
5093 int errsts = 0;
5094 int errsts_no_connect = DID_NO_CONNECT << 16;
5095 u32 flags;
5096 u16 sa;
5097 u8 opcode = cmd[0];
5098 bool has_wlun_rl;
5099 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
5100
5101 scsi_set_resid(scp, 0);
5102 if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
5103 char b[120];
5104 int n, len, sb;
5105
5106 len = scp->cmd_len;
5107 sb = (int)sizeof(b);
5108 if (len > 32)
5109 strcpy(b, "too long, over 32 bytes");
5110 else {
5111 for (k = 0, n = 0; k < len && n < sb; ++k)
5112 n += scnprintf(b + n, sb - n, "%02x ",
5113 (u32)cmd[k]);
5114 }
5115 sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
5116 }
5117 has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS);
5118 if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
5119 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5120
5121 sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */
5122 oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */
5123 devip = (struct sdebug_dev_info *)sdp->hostdata;
5124 if (!devip) {
5125 devip = devInfoReg(sdp);
5126 if (NULL == devip)
5127 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5128 }
5129 na = oip->num_attached;
5130 r_pfp = oip->pfp;
5131 if (na) { /* multiple commands with this opcode */
5132 r_oip = oip;
5133 if (FF_SA & r_oip->flags) {
5134 if (F_SA_LOW & oip->flags)
5135 sa = 0x1f & cmd[1];
5136 else
5137 sa = get_unaligned_be16(cmd + 8);
5138 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5139 if (opcode == oip->opcode && sa == oip->sa)
5140 break;
5141 }
5142 } else { /* since no service action only check opcode */
5143 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5144 if (opcode == oip->opcode)
5145 break;
5146 }
5147 }
5148 if (k > na) {
5149 if (F_SA_LOW & r_oip->flags)
5150 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 4);
5151 else if (F_SA_HIGH & r_oip->flags)
5152 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, 7);
5153 else
5154 mk_sense_invalid_opcode(scp);
5155 goto check_cond;
5156 }
5157 } /* else (when na==0) we assume the oip is a match */
5158 flags = oip->flags;
5159 if (F_INV_OP & flags) {
5160 mk_sense_invalid_opcode(scp);
5161 goto check_cond;
5162 }
5163 if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
5164 if (debug)
5165 sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: "
5166 "0x%x not supported for wlun\n", opcode);
5167 mk_sense_invalid_opcode(scp);
5168 goto check_cond;
5169 }
5170 if (scsi_debug_strict) { /* check cdb against mask */
5171 u8 rem;
5172 int j;
5173
5174 for (k = 1; k < oip->len_mask[0] && k < 16; ++k) {
5175 rem = ~oip->len_mask[k] & cmd[k];
5176 if (rem) {
5177 for (j = 7; j >= 0; --j, rem <<= 1) {
5178 if (0x80 & rem)
5179 break;
5180 }
5181 mk_sense_invalid_fld(scp, SDEB_IN_CDB, k, j);
5182 goto check_cond;
5183 }
5184 }
5185 }
5186 if (!(F_SKIP_UA & flags) &&
5187 SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) {
5188 errsts = check_readiness(scp, UAS_ONLY, devip);
5189 if (errsts)
5190 goto check_cond;
5191 }
5192 if ((F_M_ACCESS & flags) && devip->stopped) {
5193 mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
5194 if (debug)
5195 sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
5196 "%s\n", my_name, "initializing command "
5197 "required");
5198 errsts = check_condition_result;
5199 goto fini;
5200 }
5201 if (scsi_debug_fake_rw && (F_FAKE_RW & flags))
5202 goto fini;
5203 if (scsi_debug_every_nth) {
5204 if (check_inject(scp))
5205 return 0; /* ignore command: make trouble */
5206 }
5207 if (oip->pfp) /* if this command has a resp_* function, call it */
5208 errsts = oip->pfp(scp, devip);
5209 else if (r_pfp) /* if leaf function ptr NULL, try the root's */
5210 errsts = r_pfp(scp, devip);
5211
5212fini:
5213 return schedule_resp(scp, devip, errsts,
5214 ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay));
5215check_cond:
5216 return schedule_resp(scp, devip, check_condition_result, 0);
5217}
5218
Douglas Gilbert38d5c832014-11-24 21:27:12 -05005219static int
5220sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
5221{
5222 if (scsi_debug_host_lock) {
5223 unsigned long iflags;
5224 int rc;
5225
5226 spin_lock_irqsave(shost->host_lock, iflags);
5227 rc = scsi_debug_queuecommand(cmd);
5228 spin_unlock_irqrestore(shost->host_lock, iflags);
5229 return rc;
5230 } else
5231 return scsi_debug_queuecommand(cmd);
5232}
5233
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005234static struct scsi_host_template sdebug_driver_template = {
Al Viroc8ed5552013-03-31 01:46:06 -04005235 .show_info = scsi_debug_show_info,
5236 .write_info = scsi_debug_write_info,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005237 .proc_name = sdebug_proc_name,
5238 .name = "SCSI DEBUG",
5239 .info = scsi_debug_info,
5240 .slave_alloc = scsi_debug_slave_alloc,
5241 .slave_configure = scsi_debug_slave_configure,
5242 .slave_destroy = scsi_debug_slave_destroy,
5243 .ioctl = scsi_debug_ioctl,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005244 .queuecommand = sdebug_queuecommand_lock_or_not,
5245 .change_queue_depth = sdebug_change_qdepth,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005246 .eh_abort_handler = scsi_debug_abort,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005247 .eh_device_reset_handler = scsi_debug_device_reset,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005248 .eh_target_reset_handler = scsi_debug_target_reset,
5249 .eh_bus_reset_handler = scsi_debug_bus_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005250 .eh_host_reset_handler = scsi_debug_host_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005251 .can_queue = SCSI_DEBUG_CANQUEUE,
5252 .this_id = 7,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005253 .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005254 .cmd_per_lun = DEF_CMD_PER_LUN,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005255 .max_sectors = -1U,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005256 .use_clustering = DISABLE_CLUSTERING,
5257 .module = THIS_MODULE,
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005258 .track_queue_depth = 1,
Douglas Gilbert817fd662014-11-24 20:18:02 -05005259 .cmd_size = sizeof(struct sdebug_scmd_extra_t),
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005260};
5261
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262static int sdebug_driver_probe(struct device * dev)
5263{
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005264 int error = 0;
Douglas Gilbert817fd662014-11-24 20:18:02 -05005265 int opts;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005266 struct sdebug_host_info *sdbg_host;
5267 struct Scsi_Host *hpnt;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005268 int host_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
5270 sdbg_host = to_sdebug_host(dev);
5271
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005272 sdebug_driver_template.can_queue = scsi_debug_max_queue;
Akinobu Mita0759c662014-02-26 22:57:04 +09005273 if (scsi_debug_clustering)
5274 sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005275 hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
5276 if (NULL == hpnt) {
Finn Thain17c9ff52014-10-03 11:43:31 +10005277 pr_err("%s: scsi_host_alloc failed\n", __func__);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005278 error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 return error;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
5282 sdbg_host->shost = hpnt;
5283 *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
5284 if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
5285 hpnt->max_id = scsi_debug_num_tgts + 1;
5286 else
5287 hpnt->max_id = scsi_debug_num_tgts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04005288 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005289
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005290 host_prot = 0;
5291
5292 switch (scsi_debug_dif) {
5293
5294 case SD_DIF_TYPE1_PROTECTION:
5295 host_prot = SHOST_DIF_TYPE1_PROTECTION;
5296 if (scsi_debug_dix)
5297 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
5298 break;
5299
5300 case SD_DIF_TYPE2_PROTECTION:
5301 host_prot = SHOST_DIF_TYPE2_PROTECTION;
5302 if (scsi_debug_dix)
5303 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
5304 break;
5305
5306 case SD_DIF_TYPE3_PROTECTION:
5307 host_prot = SHOST_DIF_TYPE3_PROTECTION;
5308 if (scsi_debug_dix)
5309 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
5310 break;
5311
5312 default:
5313 if (scsi_debug_dix)
5314 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
5315 break;
5316 }
5317
5318 scsi_host_set_prot(hpnt, host_prot);
5319
5320 printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n",
5321 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
5322 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
5323 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
5324 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
5325 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
5326 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
5327 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
5328
5329 if (scsi_debug_guard == 1)
5330 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
5331 else
5332 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
5333
Douglas Gilbert817fd662014-11-24 20:18:02 -05005334 opts = scsi_debug_opts;
5335 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5336 sdebug_any_injecting_opt = true;
5337 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5338 sdebug_any_injecting_opt = true;
5339 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5340 sdebug_any_injecting_opt = true;
5341 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5342 sdebug_any_injecting_opt = true;
5343 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5344 sdebug_any_injecting_opt = true;
5345
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346 error = scsi_add_host(hpnt, &sdbg_host->dev);
5347 if (error) {
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07005348 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349 error = -ENODEV;
5350 scsi_host_put(hpnt);
5351 } else
5352 scsi_scan_host(hpnt);
5353
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005354 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355}
5356
5357static int sdebug_driver_remove(struct device * dev)
5358{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005360 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361
5362 sdbg_host = to_sdebug_host(dev);
5363
5364 if (!sdbg_host) {
5365 printk(KERN_ERR "%s: Unable to locate host info\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07005366 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 return -ENODEV;
5368 }
5369
5370 scsi_remove_host(sdbg_host->shost);
5371
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005372 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
5373 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374 list_del(&sdbg_devinfo->dev_list);
5375 kfree(sdbg_devinfo);
5376 }
5377
5378 scsi_host_put(sdbg_host->shost);
5379 return 0;
5380}
5381
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005382static int pseudo_lld_bus_match(struct device *dev,
5383 struct device_driver *dev_driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005384{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005385 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386}
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005387
5388static struct bus_type pseudo_lld_bus = {
5389 .name = "pseudo",
5390 .match = pseudo_lld_bus_match,
5391 .probe = sdebug_driver_probe,
5392 .remove = sdebug_driver_remove,
Akinobu Mita82069372013-10-14 22:48:04 +09005393 .drv_groups = sdebug_drv_groups,
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005394};