blob: ee99aca92bca2c31e704186da4ba669e2c738834 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#define UNRECOVERED_READ_ERR 0x11
Douglas Gilbertc65b1442006-06-06 00:11:24 -040075#define PARAMETER_LIST_LENGTH_ERR 0x1a
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#define INVALID_OPCODE 0x20
Martin K. Petersen395cef02009-09-18 17:33:03 -040077#define INVALID_COMMAND_OPCODE 0x20
Douglas Gilbert22017ed2014-11-24 23:04:47 -050078#define LBA_OUT_OF_RANGE 0x21
Linus Torvalds1da177e2005-04-16 15:20:36 -070079#define INVALID_FIELD_IN_CDB 0x24
Douglas Gilbertc65b1442006-06-06 00:11:24 -040080#define INVALID_FIELD_IN_PARAM_LIST 0x26
Douglas Gilbertcbf67842014-07-26 11:55:35 -040081#define UA_RESET_ASC 0x29
82#define UA_CHANGED_ASC 0x2a
Douglas Gilbert22017ed2014-11-24 23:04:47 -050083#define INSUFF_RES_ASC 0x55
84#define INSUFF_RES_ASCQ 0x3
Douglas Gilbertcbf67842014-07-26 11:55:35 -040085#define POWER_ON_RESET_ASCQ 0x0
86#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */
87#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */
Douglas Gilbert22017ed2014-11-24 23:04:47 -050088#define CAPACITY_CHANGED_ASCQ 0x9
Linus Torvalds1da177e2005-04-16 15:20:36 -070089#define SAVING_PARAMS_UNSUP 0x39
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050090#define TRANSPORT_PROBLEM 0x4b
Douglas Gilbertc65b1442006-06-06 00:11:24 -040091#define THRESHOLD_EXCEEDED 0x5d
92#define LOW_POWER_COND_ON 0x5e
Douglas Gilbert22017ed2014-11-24 23:04:47 -050093#define MISCOMPARE_VERIFY_ASC 0x1d
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050095/* Additional Sense Code Qualifier (ASCQ) */
96#define ACK_NAK_TO 0x3
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
99/* Default values for driver parameters */
100#define DEF_NUM_HOST 1
101#define DEF_NUM_TGTS 1
102#define DEF_MAX_LUNS 1
103/* With these defaults, this driver will make 1 host with 1 target
104 * (id 0) containing 1 logical unit (lun 0). That is 1 device.
105 */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500106#define DEF_ATO 1
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400107#define DEF_DELAY 1 /* if > 0 unit is a jiffy */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108#define DEF_DEV_SIZE_MB 8
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500109#define DEF_DIF 0
110#define DEF_DIX 0
111#define DEF_D_SENSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#define DEF_EVERY_NTH 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500113#define DEF_FAKE_RW 0
114#define DEF_GUARD 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400115#define DEF_HOST_LOCK 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500116#define DEF_LBPU 0
117#define DEF_LBPWS 0
118#define DEF_LBPWS10 0
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600119#define DEF_LBPRZ 1
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500120#define DEF_LOWEST_ALIGNED 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400121#define DEF_NDELAY 0 /* if > 0 unit is a nanosecond */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500122#define DEF_NO_LUN_0 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123#define DEF_NUM_PARTS 0
124#define DEF_OPTS 0
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400125#define DEF_OPT_BLKS 64
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500126#define DEF_PHYSBLK_EXP 0
127#define DEF_PTYPE 0
Martin Pittd9867882012-09-06 12:04:33 +0200128#define DEF_REMOVABLE false
Douglas Gilberte46b0342014-08-05 12:21:53 +0200129#define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500130#define DEF_SECTOR_SIZE 512
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400131#define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500132#define DEF_UNMAP_ALIGNMENT 0
133#define DEF_UNMAP_GRANULARITY 1
Martin K. Petersen60147592010-08-19 11:49:00 -0400134#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
135#define DEF_UNMAP_MAX_DESC 256
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500136#define DEF_VIRTUAL_GB 0
137#define DEF_VPD_USE_HOSTNO 1
138#define DEF_WRITESAME_LENGTH 0xFFFF
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400139#define DELAY_OVERRIDDEN -9999
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141/* bit mask values for scsi_debug_opts */
142#define SCSI_DEBUG_OPT_NOISE 1
143#define SCSI_DEBUG_OPT_MEDIUM_ERR 2
144#define SCSI_DEBUG_OPT_TIMEOUT 4
145#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500146#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500147#define SCSI_DEBUG_OPT_DIF_ERR 32
148#define SCSI_DEBUG_OPT_DIX_ERR 64
Martin K. Petersen18a4d0a2012-02-09 13:48:53 -0500149#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400150#define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100
151#define SCSI_DEBUG_OPT_Q_NOISE 0x200
152#define SCSI_DEBUG_OPT_ALL_TSF 0x400
153#define SCSI_DEBUG_OPT_RARE_TSF 0x800
154#define SCSI_DEBUG_OPT_N_WCE 0x1000
155#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000
156#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000
157#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158/* When "every_nth" > 0 then modulo "every_nth" commands:
159 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
160 * - a RECOVERED_ERROR is simulated on successful read and write
161 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500162 * - a TRANSPORT_ERROR is simulated on successful read and write
163 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 *
165 * When "every_nth" < 0 then after "- every_nth" commands:
166 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
167 * - a RECOVERED_ERROR is simulated on successful read and write
168 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500169 * - a TRANSPORT_ERROR is simulated on successful read and write
170 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 * This will continue until some other action occurs (e.g. the user
172 * writing a new value (other than -1 or 1) to every_nth via sysfs).
173 */
174
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400175/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
176 * priority order. In the subset implemented here lower numbers have higher
177 * priority. The UA numbers should be a sequence starting from 0 with
178 * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */
179#define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */
180#define SDEBUG_UA_BUS_RESET 1
181#define SDEBUG_UA_MODE_CHANGED 2
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500182#define SDEBUG_UA_CAPACITY_CHANGED 3
183#define SDEBUG_NUM_UAS 4
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400184
185/* for check_readiness() */
186#define UAS_ONLY 1
187#define UAS_TUR 0
188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
190 * sector on read commands: */
191#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -0500192#define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
195 * or "peripheral device" addressing (value 0) */
196#define SAM2_LUN_ADDRESS_METHOD 0
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400197#define SAM2_WLUN_REPORT_LUNS 0xc101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400199/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
200 * (for response) at one time. Can be reduced by max_queue option. Command
201 * responses are not queued when delay=0 and ndelay=0. The per-device
202 * DEF_CMD_PER_LUN can be changed via sysfs:
203 * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
204 * SCSI_DEBUG_CANQUEUE. */
205#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */
206#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
207#define DEF_CMD_PER_LUN 255
208
209#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
210#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
211#endif
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400212
Douglas Gilbert817fd662014-11-24 20:18:02 -0500213struct sdebug_scmd_extra_t {
214 bool inj_recovered;
215 bool inj_transport;
216 bool inj_dif;
217 bool inj_dix;
218 bool inj_short;
219};
220
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221static int scsi_debug_add_host = DEF_NUM_HOST;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500222static int scsi_debug_ato = DEF_ATO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223static int scsi_debug_delay = DEF_DELAY;
224static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500225static int scsi_debug_dif = DEF_DIF;
226static int scsi_debug_dix = DEF_DIX;
227static int scsi_debug_dsense = DEF_D_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228static int scsi_debug_every_nth = DEF_EVERY_NTH;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500229static int scsi_debug_fake_rw = DEF_FAKE_RW;
Akinobu Mita68aee7b2013-09-18 21:27:27 +0900230static unsigned int scsi_debug_guard = DEF_GUARD;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500231static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232static int scsi_debug_max_luns = DEF_MAX_LUNS;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400233static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400234static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */
235static int scsi_debug_ndelay = DEF_NDELAY;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400236static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500237static int scsi_debug_no_uld = 0;
238static int scsi_debug_num_parts = DEF_NUM_PARTS;
239static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400240static int scsi_debug_opt_blks = DEF_OPT_BLKS;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500241static int scsi_debug_opts = DEF_OPTS;
242static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
243static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
244static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
245static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
246static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
247static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
248static unsigned int scsi_debug_lbpu = DEF_LBPU;
249static unsigned int scsi_debug_lbpws = DEF_LBPWS;
250static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600251static unsigned int scsi_debug_lbprz = DEF_LBPRZ;
Martin K. Petersen60147592010-08-19 11:49:00 -0400252static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500253static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
254static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
255static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
256static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
Martin Pittd9867882012-09-06 12:04:33 +0200257static bool scsi_debug_removable = DEF_REMOVABLE;
Akinobu Mita0759c662014-02-26 22:57:04 +0900258static bool scsi_debug_clustering;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400259static bool scsi_debug_host_lock = DEF_HOST_LOCK;
Douglas Gilbert817fd662014-11-24 20:18:02 -0500260static bool sdebug_any_injecting_opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400262static atomic_t sdebug_cmnd_count;
263static atomic_t sdebug_completions;
264static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266#define DEV_READONLY(TGT) (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400268static unsigned int sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269static sector_t sdebug_capacity; /* in sectors */
270
271/* old BIOS stuff, kernel may get rid of them but some mode sense pages
272 may still need them */
273static int sdebug_heads; /* heads per disk */
274static int sdebug_cylinders_per; /* cylinders per surface */
275static int sdebug_sectors_per; /* sectors per cylinder */
276
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277#define SDEBUG_MAX_PARTS 4
278
Martin K. Petersen395cef02009-09-18 17:33:03 -0400279#define SCSI_DEBUG_MAX_CMD_LEN 32
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +0900280
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500281static unsigned int scsi_debug_lbp(void)
282{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400283 return ((0 == scsi_debug_fake_rw) &&
284 (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500285}
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287struct sdebug_dev_info {
288 struct list_head dev_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 unsigned int channel;
290 unsigned int target;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200291 u64 lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 struct sdebug_host_info *sdbg_host;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200293 u64 wlun;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400294 unsigned long uas_bm[1];
295 atomic_t num_in_q;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400296 char stopped;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 char used;
298};
299
300struct sdebug_host_info {
301 struct list_head host_list;
302 struct Scsi_Host *shost;
303 struct device dev;
304 struct list_head dev_info_list;
305};
306
307#define to_sdebug_host(d) \
308 container_of(d, struct sdebug_host_info, dev)
309
310static LIST_HEAD(sdebug_host_list);
311static DEFINE_SPINLOCK(sdebug_host_list_lock);
312
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400313
314struct sdebug_hrtimer { /* ... is derived from hrtimer */
315 struct hrtimer hrt; /* must be first element */
316 int qa_indx;
317};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
319struct sdebug_queued_cmd {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400320 /* in_use flagged by a bit in queued_in_use_bm[] */
321 struct timer_list *cmnd_timerp;
322 struct tasklet_struct *tletp;
323 struct sdebug_hrtimer *sd_hrtp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 struct scsi_cmnd * a_cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325};
326static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400327static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330static unsigned char * fake_storep; /* ramdisk storage */
Akinobu Mitae18d8be2013-06-29 17:59:18 +0900331static struct sd_dif_tuple *dif_storep; /* protection info */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400332static void *map_storep; /* provisioning map */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Martin K. Petersen44d92692009-10-15 14:45:27 -0400334static unsigned long map_size;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400335static int num_aborts;
336static int num_dev_resets;
337static int num_target_resets;
338static int num_bus_resets;
339static int num_host_resets;
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500340static int dix_writes;
341static int dix_reads;
342static int dif_errors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
344static DEFINE_SPINLOCK(queued_arr_lock);
345static DEFINE_RWLOCK(atomic_rw);
346
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400347static char sdebug_proc_name[] = MY_NAME;
348static const char *my_name = MY_NAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350static struct bus_type pseudo_lld_bus;
351
352static struct device_driver sdebug_driverfs_driver = {
353 .name = sdebug_proc_name,
354 .bus = &pseudo_lld_bus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355};
356
357static const int check_condition_result =
358 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
359
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500360static const int illegal_condition_result =
361 (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
362
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400363static const int device_qfull_result =
364 (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
365
366static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
367 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
368 0, 0, 0, 0};
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400369static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
370 0, 0, 0x2, 0x4b};
371static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
372 0, 0, 0x0, 0x0};
373
Akinobu Mita14faa942013-09-18 21:27:24 +0900374static void *fake_store(unsigned long long lba)
375{
376 lba = do_div(lba, sdebug_store_sectors);
377
378 return fake_storep + lba * scsi_debug_sector_size;
379}
380
381static struct sd_dif_tuple *dif_store(sector_t sector)
382{
383 sector = do_div(sector, sdebug_store_sectors);
384
385 return dif_storep + sector;
386}
387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388static int sdebug_add_adapter(void);
389static void sdebug_remove_adapter(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900391static void sdebug_max_tgts_luns(void)
392{
393 struct sdebug_host_info *sdbg_host;
394 struct Scsi_Host *hpnt;
395
396 spin_lock(&sdebug_host_list_lock);
397 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
398 hpnt = sdbg_host->shost;
399 if ((hpnt->this_id >= 0) &&
400 (scsi_debug_num_tgts > hpnt->this_id))
401 hpnt->max_id = scsi_debug_num_tgts + 1;
402 else
403 hpnt->max_id = scsi_debug_num_tgts;
404 /* scsi_debug_max_luns; */
405 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
406 }
407 spin_unlock(&sdebug_host_list_lock);
408}
409
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500410enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
411
412/* Set in_bit to -1 to indicate no bit position of invalid field */
413static void
414mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
415 int in_byte, int in_bit)
416{
417 unsigned char *sbuff;
418 u8 sks[4];
419 int sl, asc;
420
421 sbuff = scp->sense_buffer;
422 if (!sbuff) {
423 sdev_printk(KERN_ERR, scp->device,
424 "%s: sense_buffer is NULL\n", __func__);
425 return;
426 }
427 asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
428 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
429 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
430 asc, 0);
431 memset(sks, 0, sizeof(sks));
432 sks[0] = 0x80;
433 if (c_d)
434 sks[0] |= 0x40;
435 if (in_bit >= 0) {
436 sks[0] |= 0x8;
437 sks[0] |= 0x7 & in_bit;
438 }
439 put_unaligned_be16(in_byte, sks + 1);
440 if (scsi_debug_dsense) {
441 sl = sbuff[7] + 8;
442 sbuff[7] = sl;
443 sbuff[sl] = 0x2;
444 sbuff[sl + 1] = 0x6;
445 memcpy(sbuff + sl + 4, sks, 3);
446 } else
447 memcpy(sbuff + 15, sks, 3);
448 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
449 sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq"
450 "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
451 my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
452}
453
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400454static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900455{
456 unsigned char *sbuff;
457
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400458 sbuff = scp->sense_buffer;
459 if (!sbuff) {
460 sdev_printk(KERN_ERR, scp->device,
461 "%s: sense_buffer is NULL\n", __func__);
462 return;
463 }
464 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900465
466 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
467
468 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400469 sdev_printk(KERN_INFO, scp->device,
470 "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
471 my_name, key, asc, asq);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900472}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500474static void
475mk_sense_invalid_opcode(struct scsi_cmnd *scp)
476{
477 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
478}
479
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900480static void get_data_transfer_info(unsigned char *cmd,
Martin K. Petersen395cef02009-09-18 17:33:03 -0400481 unsigned long long *lba, unsigned int *num,
482 u32 *ei_lba)
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900483{
Martin K. Petersen395cef02009-09-18 17:33:03 -0400484 *ei_lba = 0;
485
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900486 switch (*cmd) {
Martin K. Petersen395cef02009-09-18 17:33:03 -0400487 case VARIABLE_LENGTH_CMD:
488 *lba = (u64)cmd[19] | (u64)cmd[18] << 8 |
489 (u64)cmd[17] << 16 | (u64)cmd[16] << 24 |
490 (u64)cmd[15] << 32 | (u64)cmd[14] << 40 |
491 (u64)cmd[13] << 48 | (u64)cmd[12] << 56;
492
493 *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 |
494 (u32)cmd[21] << 16 | (u32)cmd[20] << 24;
495
496 *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 |
497 (u32)cmd[28] << 24;
498 break;
499
Martin K. Petersen44d92692009-10-15 14:45:27 -0400500 case WRITE_SAME_16:
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900501 case WRITE_16:
502 case READ_16:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900503 *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
504 (u64)cmd[7] << 16 | (u64)cmd[6] << 24 |
505 (u64)cmd[5] << 32 | (u64)cmd[4] << 40 |
506 (u64)cmd[3] << 48 | (u64)cmd[2] << 56;
507
508 *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 |
509 (u32)cmd[10] << 24;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900510 break;
511 case WRITE_12:
512 case READ_12:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900513 *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
514 (u32)cmd[2] << 24;
515
516 *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
517 (u32)cmd[6] << 24;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900518 break;
Martin K. Petersen44d92692009-10-15 14:45:27 -0400519 case WRITE_SAME:
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900520 case WRITE_10:
521 case READ_10:
FUJITA Tomonoric639d142008-01-23 01:32:01 +0900522 case XDWRITEREAD_10:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900523 *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
524 (u32)cmd[2] << 24;
525
526 *num = (u32)cmd[8] | (u32)cmd[7] << 8;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900527 break;
528 case WRITE_6:
529 case READ_6:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900530 *lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
531 (u32)(cmd[1] & 0x1f) << 16;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900532 *num = (0 == cmd[4]) ? 256 : cmd[4];
533 break;
534 default:
535 break;
536 }
537}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
540{
541 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400542 if (0x1261 == cmd)
543 sdev_printk(KERN_INFO, dev,
544 "%s: BLKFLSBUF [0x1261]\n", __func__);
545 else if (0x5331 == cmd)
546 sdev_printk(KERN_INFO, dev,
547 "%s: CDROM_GET_CAPABILITY [0x5331]\n",
548 __func__);
549 else
550 sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
551 __func__, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 }
553 return -EINVAL;
554 /* return -ENOTTY; // correct return but upsets fdisk */
555}
556
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400557static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400558 struct sdebug_dev_info * devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400560 int k;
561 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
562
563 k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
564 if (k != SDEBUG_NUM_UAS) {
565 const char *cp = NULL;
566
567 switch (k) {
568 case SDEBUG_UA_POR:
569 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
570 UA_RESET_ASC, POWER_ON_RESET_ASCQ);
571 if (debug)
572 cp = "power on reset";
573 break;
574 case SDEBUG_UA_BUS_RESET:
575 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
576 UA_RESET_ASC, BUS_RESET_ASCQ);
577 if (debug)
578 cp = "bus reset";
579 break;
580 case SDEBUG_UA_MODE_CHANGED:
581 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
582 UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
583 if (debug)
584 cp = "mode parameters changed";
585 break;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500586 case SDEBUG_UA_CAPACITY_CHANGED:
587 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
588 UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
589 if (debug)
590 cp = "capacity data changed";
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400591 default:
592 pr_warn("%s: unexpected unit attention code=%d\n",
593 __func__, k);
594 if (debug)
595 cp = "unknown";
596 break;
597 }
598 clear_bit(k, devip->uas_bm);
599 if (debug)
600 sdev_printk(KERN_INFO, SCpnt->device,
601 "%s reports: Unit attention: %s\n",
602 my_name, cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 return check_condition_result;
604 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400605 if ((UAS_TUR == uas_only) && devip->stopped) {
606 mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400607 0x2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400608 if (debug)
609 sdev_printk(KERN_INFO, SCpnt->device,
610 "%s reports: Not ready: %s\n", my_name,
611 "initializing command required");
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400612 return check_condition_result;
613 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 return 0;
615}
616
617/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900618static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 int arr_len)
620{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900621 int act_len;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900622 struct scsi_data_buffer *sdb = scsi_in(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900624 if (!sdb->length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900626 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 return (DID_ERROR << 16);
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900628
629 act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
630 arr, arr_len);
Akinobu Mitaa4517512013-07-08 16:01:57 -0700631 sdb->resid = scsi_bufflen(scp) - act_len;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 return 0;
634}
635
636/* Returns number of bytes fetched into 'arr' or -1 if error. */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900637static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
638 int arr_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900640 if (!scsi_bufflen(scp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900642 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 return -1;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900644
645 return scsi_sg_copy_to_buffer(scp, arr, arr_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646}
647
648
649static const char * inq_vendor_id = "Linux ";
650static const char * inq_product_id = "scsi_debug ";
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400651static const char *inq_product_rev = "0184"; /* version less '.' */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400653/* Device identification VPD page. Returns number of bytes placed in arr */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200654static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
655 int target_dev_id, int dev_id_num,
656 const char * dev_id_str,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400657 int dev_id_str_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400659 int num, port_a;
660 char b[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400662 port_a = target_dev_id + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 /* T10 vendor identifier field format (faked) */
664 arr[0] = 0x2; /* ASCII */
665 arr[1] = 0x1;
666 arr[2] = 0x0;
667 memcpy(&arr[4], inq_vendor_id, 8);
668 memcpy(&arr[12], inq_product_id, 16);
669 memcpy(&arr[28], dev_id_str, dev_id_str_len);
670 num = 8 + 16 + dev_id_str_len;
671 arr[3] = num;
672 num += 4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400673 if (dev_id_num >= 0) {
674 /* NAA-5, Logical unit identifier (binary) */
675 arr[num++] = 0x1; /* binary (not necessarily sas) */
676 arr[num++] = 0x3; /* PIV=0, lu, naa */
677 arr[num++] = 0x0;
678 arr[num++] = 0x8;
679 arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */
680 arr[num++] = 0x33;
681 arr[num++] = 0x33;
682 arr[num++] = 0x30;
683 arr[num++] = (dev_id_num >> 24);
684 arr[num++] = (dev_id_num >> 16) & 0xff;
685 arr[num++] = (dev_id_num >> 8) & 0xff;
686 arr[num++] = dev_id_num & 0xff;
687 /* Target relative port number */
688 arr[num++] = 0x61; /* proto=sas, binary */
689 arr[num++] = 0x94; /* PIV=1, target port, rel port */
690 arr[num++] = 0x0; /* reserved */
691 arr[num++] = 0x4; /* length */
692 arr[num++] = 0x0; /* reserved */
693 arr[num++] = 0x0; /* reserved */
694 arr[num++] = 0x0;
695 arr[num++] = 0x1; /* relative port A */
696 }
697 /* NAA-5, Target port identifier */
698 arr[num++] = 0x61; /* proto=sas, binary */
699 arr[num++] = 0x93; /* piv=1, target port, naa */
700 arr[num++] = 0x0;
701 arr[num++] = 0x8;
702 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
703 arr[num++] = 0x22;
704 arr[num++] = 0x22;
705 arr[num++] = 0x20;
706 arr[num++] = (port_a >> 24);
707 arr[num++] = (port_a >> 16) & 0xff;
708 arr[num++] = (port_a >> 8) & 0xff;
709 arr[num++] = port_a & 0xff;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200710 /* NAA-5, Target port group identifier */
711 arr[num++] = 0x61; /* proto=sas, binary */
712 arr[num++] = 0x95; /* piv=1, target port group id */
713 arr[num++] = 0x0;
714 arr[num++] = 0x4;
715 arr[num++] = 0;
716 arr[num++] = 0;
717 arr[num++] = (port_group_id >> 8) & 0xff;
718 arr[num++] = port_group_id & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400719 /* NAA-5, Target device identifier */
720 arr[num++] = 0x61; /* proto=sas, binary */
721 arr[num++] = 0xa3; /* piv=1, target device, naa */
722 arr[num++] = 0x0;
723 arr[num++] = 0x8;
724 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
725 arr[num++] = 0x22;
726 arr[num++] = 0x22;
727 arr[num++] = 0x20;
728 arr[num++] = (target_dev_id >> 24);
729 arr[num++] = (target_dev_id >> 16) & 0xff;
730 arr[num++] = (target_dev_id >> 8) & 0xff;
731 arr[num++] = target_dev_id & 0xff;
732 /* SCSI name string: Target device identifier */
733 arr[num++] = 0x63; /* proto=sas, UTF-8 */
734 arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */
735 arr[num++] = 0x0;
736 arr[num++] = 24;
737 memcpy(arr + num, "naa.52222220", 12);
738 num += 12;
739 snprintf(b, sizeof(b), "%08X", target_dev_id);
740 memcpy(arr + num, b, 8);
741 num += 8;
742 memset(arr + num, 0, 4);
743 num += 4;
744 return num;
745}
746
747
748static unsigned char vpd84_data[] = {
749/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
750 0x22,0x22,0x22,0x0,0xbb,0x1,
751 0x22,0x22,0x22,0x0,0xbb,0x2,
752};
753
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400754/* Software interface identification VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400755static int inquiry_evpd_84(unsigned char * arr)
756{
757 memcpy(arr, vpd84_data, sizeof(vpd84_data));
758 return sizeof(vpd84_data);
759}
760
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400761/* Management network addresses VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400762static int inquiry_evpd_85(unsigned char * arr)
763{
764 int num = 0;
765 const char * na1 = "https://www.kernel.org/config";
766 const char * na2 = "http://www.kernel.org/log";
767 int plen, olen;
768
769 arr[num++] = 0x1; /* lu, storage config */
770 arr[num++] = 0x0; /* reserved */
771 arr[num++] = 0x0;
772 olen = strlen(na1);
773 plen = olen + 1;
774 if (plen % 4)
775 plen = ((plen / 4) + 1) * 4;
776 arr[num++] = plen; /* length, null termianted, padded */
777 memcpy(arr + num, na1, olen);
778 memset(arr + num + olen, 0, plen - olen);
779 num += plen;
780
781 arr[num++] = 0x4; /* lu, logging */
782 arr[num++] = 0x0; /* reserved */
783 arr[num++] = 0x0;
784 olen = strlen(na2);
785 plen = olen + 1;
786 if (plen % 4)
787 plen = ((plen / 4) + 1) * 4;
788 arr[num++] = plen; /* length, null terminated, padded */
789 memcpy(arr + num, na2, olen);
790 memset(arr + num + olen, 0, plen - olen);
791 num += plen;
792
793 return num;
794}
795
796/* SCSI ports VPD page */
797static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
798{
799 int num = 0;
800 int port_a, port_b;
801
802 port_a = target_dev_id + 1;
803 port_b = port_a + 1;
804 arr[num++] = 0x0; /* reserved */
805 arr[num++] = 0x0; /* reserved */
806 arr[num++] = 0x0;
807 arr[num++] = 0x1; /* relative port 1 (primary) */
808 memset(arr + num, 0, 6);
809 num += 6;
810 arr[num++] = 0x0;
811 arr[num++] = 12; /* length tp descriptor */
812 /* naa-5 target port identifier (A) */
813 arr[num++] = 0x61; /* proto=sas, binary */
814 arr[num++] = 0x93; /* PIV=1, target port, NAA */
815 arr[num++] = 0x0; /* reserved */
816 arr[num++] = 0x8; /* length */
817 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
818 arr[num++] = 0x22;
819 arr[num++] = 0x22;
820 arr[num++] = 0x20;
821 arr[num++] = (port_a >> 24);
822 arr[num++] = (port_a >> 16) & 0xff;
823 arr[num++] = (port_a >> 8) & 0xff;
824 arr[num++] = port_a & 0xff;
825
826 arr[num++] = 0x0; /* reserved */
827 arr[num++] = 0x0; /* reserved */
828 arr[num++] = 0x0;
829 arr[num++] = 0x2; /* relative port 2 (secondary) */
830 memset(arr + num, 0, 6);
831 num += 6;
832 arr[num++] = 0x0;
833 arr[num++] = 12; /* length tp descriptor */
834 /* naa-5 target port identifier (B) */
835 arr[num++] = 0x61; /* proto=sas, binary */
836 arr[num++] = 0x93; /* PIV=1, target port, NAA */
837 arr[num++] = 0x0; /* reserved */
838 arr[num++] = 0x8; /* length */
839 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
840 arr[num++] = 0x22;
841 arr[num++] = 0x22;
842 arr[num++] = 0x20;
843 arr[num++] = (port_b >> 24);
844 arr[num++] = (port_b >> 16) & 0xff;
845 arr[num++] = (port_b >> 8) & 0xff;
846 arr[num++] = port_b & 0xff;
847
848 return num;
849}
850
851
852static unsigned char vpd89_data[] = {
853/* from 4th byte */ 0,0,0,0,
854'l','i','n','u','x',' ',' ',' ',
855'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ',
856'1','2','3','4',
8570x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
8580xec,0,0,0,
8590x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0,
8600,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20,
8610x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33,
8620x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31,
8630x53,0x41,
8640x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
8650x20,0x20,
8660x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
8670x10,0x80,
8680,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0,
8690x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0,
8700x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0,
8710,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0,
8720x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40,
8730x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0,
8740,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,0,0,0,0,
8750,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8760,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8770,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8780x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42,
8790,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8,
8800xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe,
8810,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,0,
8820,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8830,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8840,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8850,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8860,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8870,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8880,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8890,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8900,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8910,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8920,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8930,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
894};
895
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400896/* ATA Information VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400897static int inquiry_evpd_89(unsigned char * arr)
898{
899 memcpy(arr, vpd89_data, sizeof(vpd89_data));
900 return sizeof(vpd89_data);
901}
902
903
904static unsigned char vpdb0_data[] = {
Douglas Gilbert1e49f782009-10-29 01:48:31 -0400905 /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
906 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
907 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
908 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400909};
910
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400911/* Block limits VPD page (SBC-3) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400912static int inquiry_evpd_b0(unsigned char * arr)
913{
Martin K. Petersenea61fca2009-05-15 00:40:33 -0400914 unsigned int gran;
915
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400916 memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400917
918 /* Optimal transfer length granularity */
Martin K. Petersenea61fca2009-05-15 00:40:33 -0400919 gran = 1 << scsi_debug_physblk_exp;
920 arr[2] = (gran >> 8) & 0xff;
921 arr[3] = gran & 0xff;
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400922
923 /* Maximum Transfer Length */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400924 if (sdebug_store_sectors > 0x400) {
925 arr[4] = (sdebug_store_sectors >> 24) & 0xff;
926 arr[5] = (sdebug_store_sectors >> 16) & 0xff;
927 arr[6] = (sdebug_store_sectors >> 8) & 0xff;
928 arr[7] = sdebug_store_sectors & 0xff;
929 }
Martin K. Petersen44d92692009-10-15 14:45:27 -0400930
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400931 /* Optimal Transfer Length */
932 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
933
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500934 if (scsi_debug_lbpu) {
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400935 /* Maximum Unmap LBA Count */
Martin K. Petersen60147592010-08-19 11:49:00 -0400936 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400937
938 /* Maximum Unmap Block Descriptor Count */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400939 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
940 }
941
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400942 /* Unmap Granularity Alignment */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400943 if (scsi_debug_unmap_alignment) {
944 put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
945 arr[28] |= 0x80; /* UGAVALID */
946 }
947
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400948 /* Optimal Unmap Granularity */
Martin K. Petersen60147592010-08-19 11:49:00 -0400949 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
950
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500951 /* Maximum WRITE SAME Length */
952 put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
953
954 return 0x3c; /* Mandatory page length for Logical Block Provisioning */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400955
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400956 return sizeof(vpdb0_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957}
958
Douglas Gilbert1e49f782009-10-29 01:48:31 -0400959/* Block device characteristics VPD page (SBC-3) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -0600960static int inquiry_evpd_b1(unsigned char *arr)
961{
962 memset(arr, 0, 0x3c);
963 arr[0] = 0;
Douglas Gilbert1e49f782009-10-29 01:48:31 -0400964 arr[1] = 1; /* non rotating medium (e.g. solid state) */
965 arr[2] = 0;
966 arr[3] = 5; /* less than 1.8" */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -0600967
968 return 0x3c;
969}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600971/* Logical block provisioning VPD page (SBC-3) */
Martin K. Petersen60147592010-08-19 11:49:00 -0400972static int inquiry_evpd_b2(unsigned char *arr)
973{
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -0500974 memset(arr, 0, 0x4);
Martin K. Petersen60147592010-08-19 11:49:00 -0400975 arr[0] = 0; /* threshold exponent */
976
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500977 if (scsi_debug_lbpu)
Martin K. Petersen60147592010-08-19 11:49:00 -0400978 arr[1] = 1 << 7;
979
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500980 if (scsi_debug_lbpws)
Martin K. Petersen60147592010-08-19 11:49:00 -0400981 arr[1] |= 1 << 6;
982
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500983 if (scsi_debug_lbpws10)
984 arr[1] |= 1 << 5;
985
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600986 if (scsi_debug_lbprz)
987 arr[1] |= 1 << 2;
988
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -0500989 return 0x4;
Martin K. Petersen60147592010-08-19 11:49:00 -0400990}
991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992#define SDEBUG_LONG_INQ_SZ 96
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400993#define SDEBUG_MAX_INQ_ARR_SZ 584
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400995static int resp_inquiry(struct scsi_cmnd *scp, int target,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 struct sdebug_dev_info * devip)
997{
998 unsigned char pq_pdt;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200999 unsigned char * arr;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001000 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001001 int alloc_len, n, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
1003 alloc_len = (cmd[3] << 8) + cmd[4];
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001004 arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
1005 if (! arr)
1006 return DID_REQUEUE << 16;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001007 if (devip->wlun)
1008 pq_pdt = 0x1e; /* present, wlun */
1009 else if (scsi_debug_no_lun_0 && (0 == devip->lun))
1010 pq_pdt = 0x7f; /* not present, no device type */
1011 else
1012 pq_pdt = (scsi_debug_ptype & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 arr[0] = pq_pdt;
1014 if (0x2 & cmd[1]) { /* CMDDT bit set */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001015 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001016 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 return check_condition_result;
1018 } else if (0x1 & cmd[1]) { /* EVPD bit set */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001019 int lu_id_num, port_group_id, target_dev_id, len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001020 char lu_id_str[6];
1021 int host_no = devip->sdbg_host->shost->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001023 port_group_id = (((host_no + 1) & 0x7f) << 8) +
1024 (devip->channel & 0x7f);
Douglas Gilbert23183912006-09-16 20:30:47 -04001025 if (0 == scsi_debug_vpd_use_hostno)
1026 host_no = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001027 lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) +
1028 (devip->target * 1000) + devip->lun);
1029 target_dev_id = ((host_no + 1) * 2000) +
1030 (devip->target * 1000) - 3;
1031 len = scnprintf(lu_id_str, 6, "%d", lu_id_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 if (0 == cmd[2]) { /* supported vital product data pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001033 arr[1] = cmd[2]; /*sanity */
1034 n = 4;
1035 arr[n++] = 0x0; /* this page */
1036 arr[n++] = 0x80; /* unit serial number */
1037 arr[n++] = 0x83; /* device identification */
1038 arr[n++] = 0x84; /* software interface ident. */
1039 arr[n++] = 0x85; /* management network addresses */
1040 arr[n++] = 0x86; /* extended inquiry */
1041 arr[n++] = 0x87; /* mode page policy */
1042 arr[n++] = 0x88; /* SCSI ports */
1043 arr[n++] = 0x89; /* ATA information */
1044 arr[n++] = 0xb0; /* Block limits (SBC) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001045 arr[n++] = 0xb1; /* Block characteristics (SBC) */
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001046 if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
1047 arr[n++] = 0xb2;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001048 arr[3] = n - 4; /* number of supported VPD pages */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 } else if (0x80 == cmd[2]) { /* unit serial number */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001050 arr[1] = cmd[2]; /*sanity */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 arr[3] = len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001052 memcpy(&arr[4], lu_id_str, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 } else if (0x83 == cmd[2]) { /* device identification */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001054 arr[1] = cmd[2]; /*sanity */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001055 arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
1056 target_dev_id, lu_id_num,
1057 lu_id_str, len);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001058 } else if (0x84 == cmd[2]) { /* Software interface ident. */
1059 arr[1] = cmd[2]; /*sanity */
1060 arr[3] = inquiry_evpd_84(&arr[4]);
1061 } else if (0x85 == cmd[2]) { /* Management network addresses */
1062 arr[1] = cmd[2]; /*sanity */
1063 arr[3] = inquiry_evpd_85(&arr[4]);
1064 } else if (0x86 == cmd[2]) { /* extended inquiry */
1065 arr[1] = cmd[2]; /*sanity */
1066 arr[3] = 0x3c; /* number of following entries */
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001067 if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
1068 arr[4] = 0x4; /* SPT: GRD_CHK:1 */
1069 else if (scsi_debug_dif)
1070 arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
1071 else
1072 arr[4] = 0x0; /* no protection stuff */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001073 arr[5] = 0x7; /* head of q, ordered + simple q's */
1074 } else if (0x87 == cmd[2]) { /* mode page policy */
1075 arr[1] = cmd[2]; /*sanity */
1076 arr[3] = 0x8; /* number of following entries */
1077 arr[4] = 0x2; /* disconnect-reconnect mp */
1078 arr[6] = 0x80; /* mlus, shared */
1079 arr[8] = 0x18; /* protocol specific lu */
1080 arr[10] = 0x82; /* mlus, per initiator port */
1081 } else if (0x88 == cmd[2]) { /* SCSI Ports */
1082 arr[1] = cmd[2]; /*sanity */
1083 arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
1084 } else if (0x89 == cmd[2]) { /* ATA information */
1085 arr[1] = cmd[2]; /*sanity */
1086 n = inquiry_evpd_89(&arr[4]);
1087 arr[2] = (n >> 8);
1088 arr[3] = (n & 0xff);
1089 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
1090 arr[1] = cmd[2]; /*sanity */
1091 arr[3] = inquiry_evpd_b0(&arr[4]);
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001092 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
1093 arr[1] = cmd[2]; /*sanity */
1094 arr[3] = inquiry_evpd_b1(&arr[4]);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001095 } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001096 arr[1] = cmd[2]; /*sanity */
1097 arr[3] = inquiry_evpd_b2(&arr[4]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001099 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001100 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 return check_condition_result;
1102 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001103 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001104 ret = fill_from_dev_buffer(scp, arr,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001105 min(len, SDEBUG_MAX_INQ_ARR_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001106 kfree(arr);
1107 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 }
1109 /* drops through here for a standard inquiry */
Martin Pittd9867882012-09-06 12:04:33 +02001110 arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 arr[2] = scsi_debug_scsi_level;
1112 arr[3] = 2; /* response_data_format==2 */
1113 arr[4] = SDEBUG_LONG_INQ_SZ - 5;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001114 arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001115 if (0 == scsi_debug_vpd_use_hostno)
1116 arr[5] = 0x10; /* claim: implicit TGPS */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001117 arr[6] = 0x10; /* claim: MultiP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001119 arr[7] = 0xa; /* claim: LINKED + CMDQUE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 memcpy(&arr[8], inq_vendor_id, 8);
1121 memcpy(&arr[16], inq_product_id, 16);
1122 memcpy(&arr[32], inq_product_rev, 4);
1123 /* version descriptors (2 bytes each) follow */
Douglas Gilberte46b0342014-08-05 12:21:53 +02001124 arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */
1125 arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001126 n = 62;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 if (scsi_debug_ptype == 0) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001128 arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 } else if (scsi_debug_ptype == 1) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001130 arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 }
Douglas Gilberte46b0342014-08-05 12:21:53 +02001132 arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001133 ret = fill_from_dev_buffer(scp, arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 min(alloc_len, SDEBUG_LONG_INQ_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001135 kfree(arr);
1136 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137}
1138
1139static int resp_requests(struct scsi_cmnd * scp,
1140 struct sdebug_dev_info * devip)
1141{
1142 unsigned char * sbuff;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001143 unsigned char *cmd = scp->cmnd;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001144 unsigned char arr[SCSI_SENSE_BUFFERSIZE];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001145 int want_dsense;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 int len = 18;
1147
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001148 memset(arr, 0, sizeof(arr));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001149 want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001150 sbuff = scp->sense_buffer;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001151 if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
1152 if (want_dsense) {
1153 arr[0] = 0x72;
1154 arr[1] = 0x0; /* NO_SENSE in sense_key */
1155 arr[2] = THRESHOLD_EXCEEDED;
1156 arr[3] = 0xff; /* TEST set and MRIE==6 */
1157 } else {
1158 arr[0] = 0x70;
1159 arr[2] = 0x0; /* NO_SENSE in sense_key */
1160 arr[7] = 0xa; /* 18 byte sense buffer */
1161 arr[12] = THRESHOLD_EXCEEDED;
1162 arr[13] = 0xff; /* TEST set and MRIE==6 */
1163 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001164 } else {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001165 memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001166 if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
1167 /* DESC bit set and sense_buff in fixed format */
1168 memset(arr, 0, sizeof(arr));
1169 arr[0] = 0x72;
1170 arr[1] = sbuff[2]; /* sense key */
1171 arr[2] = sbuff[12]; /* asc */
1172 arr[3] = sbuff[13]; /* ascq */
1173 len = 8;
1174 }
1175 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001176 mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 return fill_from_dev_buffer(scp, arr, len);
1178}
1179
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001180static int resp_start_stop(struct scsi_cmnd * scp,
1181 struct sdebug_dev_info * devip)
1182{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001183 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001184 int power_cond, errsts, start;
1185
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001186 errsts = check_readiness(scp, UAS_ONLY, devip);
1187 if (errsts)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001188 return errsts;
1189 power_cond = (cmd[4] & 0xf0) >> 4;
1190 if (power_cond) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001191 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001192 return check_condition_result;
1193 }
1194 start = cmd[4] & 1;
1195 if (start == devip->stopped)
1196 devip->stopped = !start;
1197 return 0;
1198}
1199
FUJITA Tomonori28898872008-03-30 00:59:55 +09001200static sector_t get_sdebug_capacity(void)
1201{
1202 if (scsi_debug_virtual_gb > 0)
Douglas Gilbert5447ed62010-04-25 12:30:23 +02001203 return (sector_t)scsi_debug_virtual_gb *
1204 (1073741824 / scsi_debug_sector_size);
FUJITA Tomonori28898872008-03-30 00:59:55 +09001205 else
1206 return sdebug_store_sectors;
1207}
1208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209#define SDEBUG_READCAP_ARR_SZ 8
1210static int resp_readcap(struct scsi_cmnd * scp,
1211 struct sdebug_dev_info * devip)
1212{
1213 unsigned char arr[SDEBUG_READCAP_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001214 unsigned int capac;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 int errsts;
1216
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001217 errsts = check_readiness(scp, UAS_ONLY, devip);
1218 if (errsts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 return errsts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001220 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001221 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001223 if (sdebug_capacity < 0xffffffff) {
1224 capac = (unsigned int)sdebug_capacity - 1;
1225 arr[0] = (capac >> 24);
1226 arr[1] = (capac >> 16) & 0xff;
1227 arr[2] = (capac >> 8) & 0xff;
1228 arr[3] = capac & 0xff;
1229 } else {
1230 arr[0] = 0xff;
1231 arr[1] = 0xff;
1232 arr[2] = 0xff;
1233 arr[3] = 0xff;
1234 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001235 arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
1236 arr[7] = scsi_debug_sector_size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
1238}
1239
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001240#define SDEBUG_READCAP16_ARR_SZ 32
1241static int resp_readcap16(struct scsi_cmnd * scp,
1242 struct sdebug_dev_info * devip)
1243{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001244 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001245 unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
1246 unsigned long long capac;
1247 int errsts, k, alloc_len;
1248
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001249 errsts = check_readiness(scp, UAS_ONLY, devip);
1250 if (errsts)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001251 return errsts;
1252 alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
1253 + cmd[13]);
1254 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001255 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001256 memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
1257 capac = sdebug_capacity - 1;
1258 for (k = 0; k < 8; ++k, capac >>= 8)
1259 arr[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001260 arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
1261 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
1262 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
1263 arr[11] = scsi_debug_sector_size & 0xff;
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001264 arr[13] = scsi_debug_physblk_exp & 0xf;
1265 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
Martin K. Petersen44d92692009-10-15 14:45:27 -04001266
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001267 if (scsi_debug_lbp()) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001268 arr[14] |= 0x80; /* LBPME */
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001269 if (scsi_debug_lbprz)
1270 arr[14] |= 0x40; /* LBPRZ */
1271 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001272
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001273 arr[15] = scsi_debug_lowest_aligned & 0xff;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001274
1275 if (scsi_debug_dif) {
1276 arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
1277 arr[12] |= 1; /* PROT_EN */
1278 }
1279
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001280 return fill_from_dev_buffer(scp, arr,
1281 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
1282}
1283
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001284#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
1285
1286static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1287 struct sdebug_dev_info * devip)
1288{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001289 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001290 unsigned char * arr;
1291 int host_no = devip->sdbg_host->shost->host_no;
1292 int n, ret, alen, rlen;
1293 int port_group_a, port_group_b, port_a, port_b;
1294
1295 alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
1296 + cmd[9]);
1297
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001298 arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
1299 if (! arr)
1300 return DID_REQUEUE << 16;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001301 /*
1302 * EVPD page 0x88 states we have two ports, one
1303 * real and a fake port with no device connected.
1304 * So we create two port groups with one port each
1305 * and set the group with port B to unavailable.
1306 */
1307 port_a = 0x1; /* relative port A */
1308 port_b = 0x2; /* relative port B */
1309 port_group_a = (((host_no + 1) & 0x7f) << 8) +
1310 (devip->channel & 0x7f);
1311 port_group_b = (((host_no + 1) & 0x7f) << 8) +
1312 (devip->channel & 0x7f) + 0x80;
1313
1314 /*
1315 * The asymmetric access state is cycled according to the host_id.
1316 */
1317 n = 4;
1318 if (0 == scsi_debug_vpd_use_hostno) {
1319 arr[n++] = host_no % 3; /* Asymm access state */
1320 arr[n++] = 0x0F; /* claim: all states are supported */
1321 } else {
1322 arr[n++] = 0x0; /* Active/Optimized path */
1323 arr[n++] = 0x01; /* claim: only support active/optimized paths */
1324 }
1325 arr[n++] = (port_group_a >> 8) & 0xff;
1326 arr[n++] = port_group_a & 0xff;
1327 arr[n++] = 0; /* Reserved */
1328 arr[n++] = 0; /* Status code */
1329 arr[n++] = 0; /* Vendor unique */
1330 arr[n++] = 0x1; /* One port per group */
1331 arr[n++] = 0; /* Reserved */
1332 arr[n++] = 0; /* Reserved */
1333 arr[n++] = (port_a >> 8) & 0xff;
1334 arr[n++] = port_a & 0xff;
1335 arr[n++] = 3; /* Port unavailable */
1336 arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
1337 arr[n++] = (port_group_b >> 8) & 0xff;
1338 arr[n++] = port_group_b & 0xff;
1339 arr[n++] = 0; /* Reserved */
1340 arr[n++] = 0; /* Status code */
1341 arr[n++] = 0; /* Vendor unique */
1342 arr[n++] = 0x1; /* One port per group */
1343 arr[n++] = 0; /* Reserved */
1344 arr[n++] = 0; /* Reserved */
1345 arr[n++] = (port_b >> 8) & 0xff;
1346 arr[n++] = port_b & 0xff;
1347
1348 rlen = n - 4;
1349 arr[0] = (rlen >> 24) & 0xff;
1350 arr[1] = (rlen >> 16) & 0xff;
1351 arr[2] = (rlen >> 8) & 0xff;
1352 arr[3] = rlen & 0xff;
1353
1354 /*
1355 * Return the smallest value of either
1356 * - The allocated length
1357 * - The constructed command length
1358 * - The maximum array size
1359 */
1360 rlen = min(alen,n);
1361 ret = fill_from_dev_buffer(scp, arr,
1362 min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
1363 kfree(arr);
1364 return ret;
1365}
1366
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367/* <<Following mode page info copied from ST318451LW>> */
1368
1369static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
1370{ /* Read-Write Error Recovery page for mode_sense */
1371 unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1372 5, 0, 0xff, 0xff};
1373
1374 memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1375 if (1 == pcontrol)
1376 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1377 return sizeof(err_recov_pg);
1378}
1379
1380static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
1381{ /* Disconnect-Reconnect page for mode_sense */
1382 unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1383 0, 0, 0, 0, 0, 0, 0, 0};
1384
1385 memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1386 if (1 == pcontrol)
1387 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1388 return sizeof(disconnect_pg);
1389}
1390
1391static int resp_format_pg(unsigned char * p, int pcontrol, int target)
1392{ /* Format device page for mode_sense */
Martin K. Petersen597136a2008-06-05 00:12:59 -04001393 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1394 0, 0, 0, 0, 0, 0, 0, 0,
1395 0, 0, 0, 0, 0x40, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Martin K. Petersen597136a2008-06-05 00:12:59 -04001397 memcpy(p, format_pg, sizeof(format_pg));
1398 p[10] = (sdebug_sectors_per >> 8) & 0xff;
1399 p[11] = sdebug_sectors_per & 0xff;
1400 p[12] = (scsi_debug_sector_size >> 8) & 0xff;
1401 p[13] = scsi_debug_sector_size & 0xff;
Martin Pittd9867882012-09-06 12:04:33 +02001402 if (scsi_debug_removable)
Martin K. Petersen597136a2008-06-05 00:12:59 -04001403 p[20] |= 0x20; /* should agree with INQUIRY */
1404 if (1 == pcontrol)
1405 memset(p + 2, 0, sizeof(format_pg) - 2);
1406 return sizeof(format_pg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407}
1408
1409static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
1410{ /* Caching page for mode_sense */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001411 unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
1412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1413 unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1415
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001416 if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
1417 caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 memcpy(p, caching_pg, sizeof(caching_pg));
1419 if (1 == pcontrol)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001420 memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg));
1421 else if (2 == pcontrol)
1422 memcpy(p, d_caching_pg, sizeof(d_caching_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 return sizeof(caching_pg);
1424}
1425
1426static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
1427{ /* Control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001428 unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
1429 0, 0, 0, 0};
1430 unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 0, 0, 0x2, 0x4b};
1432
1433 if (scsi_debug_dsense)
1434 ctrl_m_pg[2] |= 0x4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001435 else
1436 ctrl_m_pg[2] &= ~0x4;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001437
1438 if (scsi_debug_ato)
1439 ctrl_m_pg[5] |= 0x80; /* ATO=1 */
1440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1442 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001443 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
1444 else if (2 == pcontrol)
1445 memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 return sizeof(ctrl_m_pg);
1447}
1448
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001449
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
1451{ /* Informational Exceptions control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001452 unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0,
1453 0, 0, 0x0, 0x0};
1454 unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1455 0, 0, 0x0, 0x0};
1456
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1458 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001459 memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg));
1460 else if (2 == pcontrol)
1461 memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 return sizeof(iec_m_pg);
1463}
1464
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001465static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target)
1466{ /* SAS SSP mode page - short format for mode_sense */
1467 unsigned char sas_sf_m_pg[] = {0x19, 0x6,
1468 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0};
1469
1470 memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg));
1471 if (1 == pcontrol)
1472 memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2);
1473 return sizeof(sas_sf_m_pg);
1474}
1475
1476
1477static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
1478 int target_dev_id)
1479{ /* SAS phy control and discover mode page for mode_sense */
1480 unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
1481 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
1482 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1483 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1484 0x2, 0, 0, 0, 0, 0, 0, 0,
1485 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1486 0, 0, 0, 0, 0, 0, 0, 0,
1487 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
1488 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1489 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1490 0x3, 0, 0, 0, 0, 0, 0, 0,
1491 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1492 0, 0, 0, 0, 0, 0, 0, 0,
1493 };
1494 int port_a, port_b;
1495
1496 port_a = target_dev_id + 1;
1497 port_b = port_a + 1;
1498 memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
1499 p[20] = (port_a >> 24);
1500 p[21] = (port_a >> 16) & 0xff;
1501 p[22] = (port_a >> 8) & 0xff;
1502 p[23] = port_a & 0xff;
1503 p[48 + 20] = (port_b >> 24);
1504 p[48 + 21] = (port_b >> 16) & 0xff;
1505 p[48 + 22] = (port_b >> 8) & 0xff;
1506 p[48 + 23] = port_b & 0xff;
1507 if (1 == pcontrol)
1508 memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
1509 return sizeof(sas_pcd_m_pg);
1510}
1511
1512static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
1513{ /* SAS SSP shared protocol specific port mode subpage */
1514 unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0,
1515 0, 0, 0, 0, 0, 0, 0, 0,
1516 };
1517
1518 memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg));
1519 if (1 == pcontrol)
1520 memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4);
1521 return sizeof(sas_sha_m_pg);
1522}
1523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524#define SDEBUG_MAX_MSENSE_SZ 256
1525
1526static int resp_mode_sense(struct scsi_cmnd * scp, int target,
1527 struct sdebug_dev_info * devip)
1528{
Douglas Gilbert23183912006-09-16 20:30:47 -04001529 unsigned char dbd, llbaa;
1530 int pcontrol, pcode, subpcode, bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 unsigned char dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001532 int k, alloc_len, msense_6, offset, len, errsts, target_dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 unsigned char * ap;
1534 unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001535 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001537 errsts = check_readiness(scp, UAS_ONLY, devip);
1538 if (errsts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 return errsts;
Douglas Gilbert23183912006-09-16 20:30:47 -04001540 dbd = !!(cmd[1] & 0x8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 pcontrol = (cmd[2] & 0xc0) >> 6;
1542 pcode = cmd[2] & 0x3f;
1543 subpcode = cmd[3];
1544 msense_6 = (MODE_SENSE == cmd[0]);
Douglas Gilbert23183912006-09-16 20:30:47 -04001545 llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
1546 if ((0 == scsi_debug_ptype) && (0 == dbd))
1547 bd_len = llbaa ? 16 : 8;
1548 else
1549 bd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
1551 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
1552 if (0x3 == pcontrol) { /* Saving values not supported */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001553 mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 return check_condition_result;
1555 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001556 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
1557 (devip->target * 1000) - 3;
Douglas Gilbert23183912006-09-16 20:30:47 -04001558 /* set DPOFUA bit for disks */
1559 if (0 == scsi_debug_ptype)
1560 dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
1561 else
1562 dev_spec = 0x0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 if (msense_6) {
1564 arr[2] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001565 arr[3] = bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 offset = 4;
1567 } else {
1568 arr[3] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001569 if (16 == bd_len)
1570 arr[4] = 0x1; /* set LONGLBA bit */
1571 arr[7] = bd_len; /* assume 255 or less */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 offset = 8;
1573 }
1574 ap = arr + offset;
FUJITA Tomonori28898872008-03-30 00:59:55 +09001575 if ((bd_len > 0) && (!sdebug_capacity))
1576 sdebug_capacity = get_sdebug_capacity();
1577
Douglas Gilbert23183912006-09-16 20:30:47 -04001578 if (8 == bd_len) {
1579 if (sdebug_capacity > 0xfffffffe) {
1580 ap[0] = 0xff;
1581 ap[1] = 0xff;
1582 ap[2] = 0xff;
1583 ap[3] = 0xff;
1584 } else {
1585 ap[0] = (sdebug_capacity >> 24) & 0xff;
1586 ap[1] = (sdebug_capacity >> 16) & 0xff;
1587 ap[2] = (sdebug_capacity >> 8) & 0xff;
1588 ap[3] = sdebug_capacity & 0xff;
1589 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001590 ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
1591 ap[7] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04001592 offset += bd_len;
1593 ap = arr + offset;
1594 } else if (16 == bd_len) {
1595 unsigned long long capac = sdebug_capacity;
1596
1597 for (k = 0; k < 8; ++k, capac >>= 8)
1598 ap[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001599 ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
1600 ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
1601 ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
1602 ap[15] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04001603 offset += bd_len;
1604 ap = arr + offset;
1605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001607 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
1608 /* TODO: Control Extension page */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001609 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 return check_condition_result;
1611 }
1612 switch (pcode) {
1613 case 0x1: /* Read-Write error recovery page, direct access */
1614 len = resp_err_recov_pg(ap, pcontrol, target);
1615 offset += len;
1616 break;
1617 case 0x2: /* Disconnect-Reconnect page, all devices */
1618 len = resp_disconnect_pg(ap, pcontrol, target);
1619 offset += len;
1620 break;
1621 case 0x3: /* Format device page, direct access */
1622 len = resp_format_pg(ap, pcontrol, target);
1623 offset += len;
1624 break;
1625 case 0x8: /* Caching page, direct access */
1626 len = resp_caching_pg(ap, pcontrol, target);
1627 offset += len;
1628 break;
1629 case 0xa: /* Control Mode page, all devices */
1630 len = resp_ctrl_m_pg(ap, pcontrol, target);
1631 offset += len;
1632 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001633 case 0x19: /* if spc==1 then sas phy, control+discover */
1634 if ((subpcode > 0x2) && (subpcode < 0xff)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001635 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001636 return check_condition_result;
1637 }
1638 len = 0;
1639 if ((0x0 == subpcode) || (0xff == subpcode))
1640 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
1641 if ((0x1 == subpcode) || (0xff == subpcode))
1642 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
1643 target_dev_id);
1644 if ((0x2 == subpcode) || (0xff == subpcode))
1645 len += resp_sas_sha_m_spg(ap + len, pcontrol);
1646 offset += len;
1647 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 case 0x1c: /* Informational Exceptions Mode page, all devices */
1649 len = resp_iec_m_pg(ap, pcontrol, target);
1650 offset += len;
1651 break;
1652 case 0x3f: /* Read all Mode pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001653 if ((0 == subpcode) || (0xff == subpcode)) {
1654 len = resp_err_recov_pg(ap, pcontrol, target);
1655 len += resp_disconnect_pg(ap + len, pcontrol, target);
1656 len += resp_format_pg(ap + len, pcontrol, target);
1657 len += resp_caching_pg(ap + len, pcontrol, target);
1658 len += resp_ctrl_m_pg(ap + len, pcontrol, target);
1659 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
1660 if (0xff == subpcode) {
1661 len += resp_sas_pcd_m_spg(ap + len, pcontrol,
1662 target, target_dev_id);
1663 len += resp_sas_sha_m_spg(ap + len, pcontrol);
1664 }
1665 len += resp_iec_m_pg(ap + len, pcontrol, target);
1666 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001667 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001668 return check_condition_result;
1669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 offset += len;
1671 break;
1672 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001673 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 return check_condition_result;
1675 }
1676 if (msense_6)
1677 arr[0] = offset - 1;
1678 else {
1679 arr[0] = ((offset - 2) >> 8) & 0xff;
1680 arr[1] = (offset - 2) & 0xff;
1681 }
1682 return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
1683}
1684
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001685#define SDEBUG_MAX_MSELECT_SZ 512
1686
1687static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
1688 struct sdebug_dev_info * devip)
1689{
1690 int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
1691 int param_len, res, errsts, mpage;
1692 unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001693 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001694
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001695 errsts = check_readiness(scp, UAS_ONLY, devip);
1696 if (errsts)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001697 return errsts;
1698 memset(arr, 0, sizeof(arr));
1699 pf = cmd[1] & 0x10;
1700 sp = cmd[1] & 0x1;
1701 param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
1702 if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001703 mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001704 return check_condition_result;
1705 }
1706 res = fetch_to_dev_buffer(scp, arr, param_len);
1707 if (-1 == res)
1708 return (DID_ERROR << 16);
1709 else if ((res < param_len) &&
1710 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001711 sdev_printk(KERN_INFO, scp->device,
1712 "%s: cdb indicated=%d, IO sent=%d bytes\n",
1713 __func__, param_len, res);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001714 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
1715 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
Douglas Gilbert23183912006-09-16 20:30:47 -04001716 if (md_len > 2) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001717 mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001718 return check_condition_result;
1719 }
1720 off = bd_len + (mselect6 ? 4 : 8);
1721 mpage = arr[off] & 0x3f;
1722 ps = !!(arr[off] & 0x80);
1723 if (ps) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001724 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001725 return check_condition_result;
1726 }
1727 spf = !!(arr[off] & 0x40);
1728 pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
1729 (arr[off + 1] + 2);
1730 if ((pg_len + off) > param_len) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001731 mk_sense_buffer(scp, ILLEGAL_REQUEST,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001732 PARAMETER_LIST_LENGTH_ERR, 0);
1733 return check_condition_result;
1734 }
1735 switch (mpage) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001736 case 0x8: /* Caching Mode page */
1737 if (caching_pg[1] == arr[off + 1]) {
1738 memcpy(caching_pg + 2, arr + off + 2,
1739 sizeof(caching_pg) - 2);
1740 goto set_mode_changed_ua;
1741 }
1742 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001743 case 0xa: /* Control Mode page */
1744 if (ctrl_m_pg[1] == arr[off + 1]) {
1745 memcpy(ctrl_m_pg + 2, arr + off + 2,
1746 sizeof(ctrl_m_pg) - 2);
1747 scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001748 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001749 }
1750 break;
1751 case 0x1c: /* Informational Exceptions Mode page */
1752 if (iec_m_pg[1] == arr[off + 1]) {
1753 memcpy(iec_m_pg + 2, arr + off + 2,
1754 sizeof(iec_m_pg) - 2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001755 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001756 }
1757 break;
1758 default:
1759 break;
1760 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001761 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 5);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001762 return check_condition_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001763set_mode_changed_ua:
1764 set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
1765 return 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001766}
1767
1768static int resp_temp_l_pg(unsigned char * arr)
1769{
1770 unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38,
1771 0x0, 0x1, 0x3, 0x2, 0x0, 65,
1772 };
1773
1774 memcpy(arr, temp_l_pg, sizeof(temp_l_pg));
1775 return sizeof(temp_l_pg);
1776}
1777
1778static int resp_ie_l_pg(unsigned char * arr)
1779{
1780 unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38,
1781 };
1782
1783 memcpy(arr, ie_l_pg, sizeof(ie_l_pg));
1784 if (iec_m_pg[2] & 0x4) { /* TEST bit set */
1785 arr[4] = THRESHOLD_EXCEEDED;
1786 arr[5] = 0xff;
1787 }
1788 return sizeof(ie_l_pg);
1789}
1790
1791#define SDEBUG_MAX_LSENSE_SZ 512
1792
1793static int resp_log_sense(struct scsi_cmnd * scp,
1794 struct sdebug_dev_info * devip)
1795{
Douglas Gilbert23183912006-09-16 20:30:47 -04001796 int ppc, sp, pcontrol, pcode, subpcode, alloc_len, errsts, len, n;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001797 unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001798 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001799
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001800 errsts = check_readiness(scp, UAS_ONLY, devip);
1801 if (errsts)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001802 return errsts;
1803 memset(arr, 0, sizeof(arr));
1804 ppc = cmd[1] & 0x2;
1805 sp = cmd[1] & 0x1;
1806 if (ppc || sp) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001807 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, ppc ? 1 : 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001808 return check_condition_result;
1809 }
1810 pcontrol = (cmd[2] & 0xc0) >> 6;
1811 pcode = cmd[2] & 0x3f;
Douglas Gilbert23183912006-09-16 20:30:47 -04001812 subpcode = cmd[3] & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001813 alloc_len = (cmd[7] << 8) + cmd[8];
1814 arr[0] = pcode;
Douglas Gilbert23183912006-09-16 20:30:47 -04001815 if (0 == subpcode) {
1816 switch (pcode) {
1817 case 0x0: /* Supported log pages log page */
1818 n = 4;
1819 arr[n++] = 0x0; /* this page */
1820 arr[n++] = 0xd; /* Temperature */
1821 arr[n++] = 0x2f; /* Informational exceptions */
1822 arr[3] = n - 4;
1823 break;
1824 case 0xd: /* Temperature log page */
1825 arr[3] = resp_temp_l_pg(arr + 4);
1826 break;
1827 case 0x2f: /* Informational exceptions log page */
1828 arr[3] = resp_ie_l_pg(arr + 4);
1829 break;
1830 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001831 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04001832 return check_condition_result;
1833 }
1834 } else if (0xff == subpcode) {
1835 arr[0] |= 0x40;
1836 arr[1] = subpcode;
1837 switch (pcode) {
1838 case 0x0: /* Supported log pages and subpages log page */
1839 n = 4;
1840 arr[n++] = 0x0;
1841 arr[n++] = 0x0; /* 0,0 page */
1842 arr[n++] = 0x0;
1843 arr[n++] = 0xff; /* this page */
1844 arr[n++] = 0xd;
1845 arr[n++] = 0x0; /* Temperature */
1846 arr[n++] = 0x2f;
1847 arr[n++] = 0x0; /* Informational exceptions */
1848 arr[3] = n - 4;
1849 break;
1850 case 0xd: /* Temperature subpages */
1851 n = 4;
1852 arr[n++] = 0xd;
1853 arr[n++] = 0x0; /* Temperature */
1854 arr[3] = n - 4;
1855 break;
1856 case 0x2f: /* Informational exceptions subpages */
1857 n = 4;
1858 arr[n++] = 0x2f;
1859 arr[n++] = 0x0; /* Informational exceptions */
1860 arr[3] = n - 4;
1861 break;
1862 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001863 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04001864 return check_condition_result;
1865 }
1866 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001867 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001868 return check_condition_result;
1869 }
1870 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
1871 return fill_from_dev_buffer(scp, arr,
1872 min(len, SDEBUG_MAX_INQ_ARR_SZ));
1873}
1874
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001875static int check_device_access_params(struct scsi_cmnd *scp,
FUJITA Tomonori19789102008-03-30 00:59:56 +09001876 unsigned long long lba, unsigned int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877{
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001878 if (lba + num > sdebug_capacity) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001879 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 return check_condition_result;
1881 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001882 /* transfer length excessive (tie in to block limits VPD page) */
1883 if (num > sdebug_store_sectors) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001884 /* needs work to find which cdb byte 'num' comes from */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001885 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001886 return check_condition_result;
1887 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09001888 return 0;
1889}
1890
Akinobu Mitaa4517512013-07-08 16:01:57 -07001891/* Returns number of bytes copied or -1 if error. */
FUJITA Tomonori19789102008-03-30 00:59:56 +09001892static int do_device_access(struct scsi_cmnd *scmd,
FUJITA Tomonori19789102008-03-30 00:59:56 +09001893 unsigned long long lba, unsigned int num, int write)
1894{
1895 int ret;
Darrick J. Wonga361cc02011-01-31 18:47:54 -08001896 unsigned long long block, rest = 0;
Akinobu Mitaa4517512013-07-08 16:01:57 -07001897 struct scsi_data_buffer *sdb;
1898 enum dma_data_direction dir;
1899 size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
1900 off_t);
FUJITA Tomonori19789102008-03-30 00:59:56 +09001901
Akinobu Mitaa4517512013-07-08 16:01:57 -07001902 if (write) {
1903 sdb = scsi_out(scmd);
1904 dir = DMA_TO_DEVICE;
1905 func = sg_pcopy_to_buffer;
1906 } else {
1907 sdb = scsi_in(scmd);
1908 dir = DMA_FROM_DEVICE;
1909 func = sg_pcopy_from_buffer;
1910 }
1911
1912 if (!sdb->length)
1913 return 0;
1914 if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
1915 return -1;
FUJITA Tomonori19789102008-03-30 00:59:56 +09001916
1917 block = do_div(lba, sdebug_store_sectors);
1918 if (block + num > sdebug_store_sectors)
1919 rest = block + num - sdebug_store_sectors;
1920
Akinobu Mitaa4517512013-07-08 16:01:57 -07001921 ret = func(sdb->table.sgl, sdb->table.nents,
1922 fake_storep + (block * scsi_debug_sector_size),
1923 (num - rest) * scsi_debug_sector_size, 0);
1924 if (ret != (num - rest) * scsi_debug_sector_size)
1925 return ret;
1926
1927 if (rest) {
1928 ret += func(sdb->table.sgl, sdb->table.nents,
1929 fake_storep, rest * scsi_debug_sector_size,
1930 (num - rest) * scsi_debug_sector_size);
1931 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09001932
1933 return ret;
1934}
1935
Akinobu Mita51d648a2013-09-18 21:27:28 +09001936static __be16 dif_compute_csum(const void *buf, int len)
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001937{
Akinobu Mita51d648a2013-09-18 21:27:28 +09001938 __be16 csum;
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001939
Akinobu Mita51d648a2013-09-18 21:27:28 +09001940 if (scsi_debug_guard)
1941 csum = (__force __be16)ip_compute_csum(buf, len);
1942 else
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001943 csum = cpu_to_be16(crc_t10dif(buf, len));
Akinobu Mita51d648a2013-09-18 21:27:28 +09001944
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001945 return csum;
1946}
1947
1948static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
1949 sector_t sector, u32 ei_lba)
1950{
Akinobu Mita51d648a2013-09-18 21:27:28 +09001951 __be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001952
1953 if (sdt->guard_tag != csum) {
1954 pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
1955 __func__,
1956 (unsigned long)sector,
1957 be16_to_cpu(sdt->guard_tag),
1958 be16_to_cpu(csum));
1959 return 0x01;
1960 }
1961 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
1962 be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
1963 pr_err("%s: REF check failed on sector %lu\n",
1964 __func__, (unsigned long)sector);
1965 return 0x03;
1966 }
1967 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
1968 be32_to_cpu(sdt->ref_tag) != ei_lba) {
1969 pr_err("%s: REF check failed on sector %lu\n",
1970 __func__, (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001971 return 0x03;
1972 }
1973 return 0;
1974}
1975
Akinobu Mitabb8c0632013-09-18 21:27:25 +09001976static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09001977 unsigned int sectors, bool read)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001978{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001979 size_t resid;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001980 void *paddr;
Akinobu Mita14faa942013-09-18 21:27:24 +09001981 const void *dif_store_end = dif_storep + sdebug_store_sectors;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001982 struct sg_mapping_iter miter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001983
Akinobu Mitae18d8be2013-06-29 17:59:18 +09001984 /* Bytes of protection data to copy into sgl */
1985 resid = sectors * sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001986
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001987 sg_miter_start(&miter, scsi_prot_sglist(SCpnt),
1988 scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC |
1989 (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
1990
1991 while (sg_miter_next(&miter) && resid > 0) {
1992 size_t len = min(miter.length, resid);
Akinobu Mita14faa942013-09-18 21:27:24 +09001993 void *start = dif_store(sector);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001994 size_t rest = 0;
Akinobu Mita14faa942013-09-18 21:27:24 +09001995
1996 if (dif_store_end < start + len)
1997 rest = start + len - dif_store_end;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001998
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001999 paddr = miter.addr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002000
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002001 if (read)
2002 memcpy(paddr, start, len - rest);
2003 else
2004 memcpy(start, paddr, len - rest);
2005
2006 if (rest) {
2007 if (read)
2008 memcpy(paddr + len - rest, dif_storep, rest);
2009 else
2010 memcpy(dif_storep, paddr + len - rest, rest);
2011 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002012
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002013 sector += len / sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002014 resid -= len;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002015 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002016 sg_miter_stop(&miter);
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002017}
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002018
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002019static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
2020 unsigned int sectors, u32 ei_lba)
2021{
2022 unsigned int i;
2023 struct sd_dif_tuple *sdt;
2024 sector_t sector;
2025
Akinobu Mitac45eabec2014-02-26 22:56:58 +09002026 for (i = 0; i < sectors; i++, ei_lba++) {
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002027 int ret;
2028
2029 sector = start_sec + i;
2030 sdt = dif_store(sector);
2031
Akinobu Mita51d648a2013-09-18 21:27:28 +09002032 if (sdt->app_tag == cpu_to_be16(0xffff))
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002033 continue;
2034
2035 ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
2036 if (ret) {
2037 dif_errors++;
2038 return ret;
2039 }
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002040 }
2041
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002042 dif_copy_prot(SCpnt, start_sec, sectors, true);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002043 dix_reads++;
2044
2045 return 0;
2046}
2047
FUJITA Tomonori19789102008-03-30 00:59:56 +09002048static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002049 unsigned int num, u32 ei_lba)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002050{
2051 unsigned long iflags;
2052 int ret;
2053
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002054 ret = check_device_access_params(SCpnt, lba, num);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002055 if (ret)
2056 return ret;
2057
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002059 (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002060 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
2061 /* claim unrecoverable read error */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002062 mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002063 /* set info field and valid bit for fixed descriptor */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002064 if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) {
2065 SCpnt->sense_buffer[0] |= 0x80; /* Valid bit */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002066 ret = (lba < OPT_MEDIUM_ERR_ADDR)
2067 ? OPT_MEDIUM_ERR_ADDR : (int)lba;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002068 SCpnt->sense_buffer[3] = (ret >> 24) & 0xff;
2069 SCpnt->sense_buffer[4] = (ret >> 16) & 0xff;
2070 SCpnt->sense_buffer[5] = (ret >> 8) & 0xff;
2071 SCpnt->sense_buffer[6] = ret & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002072 }
Douglas Gilberta87e3a62010-12-17 19:16:06 -05002073 scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 return check_condition_result;
2075 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002076
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002077 read_lock_irqsave(&atomic_rw, iflags);
2078
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002079 /* DIX + T10 DIF */
2080 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
Martin K. Petersen395cef02009-09-18 17:33:03 -04002081 int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002082
2083 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002084 read_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002085 mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002086 return illegal_condition_result;
2087 }
2088 }
2089
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002090 ret = do_device_access(SCpnt, lba, num, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 read_unlock_irqrestore(&atomic_rw, iflags);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002092 if (ret == -1)
2093 return DID_ERROR << 16;
2094
2095 scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret;
2096
2097 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098}
2099
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002100void dump_sector(unsigned char *buf, int len)
2101{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002102 int i, j, n;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002103
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002104 pr_err(">>> Sector Dump <<<\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002105 for (i = 0 ; i < len ; i += 16) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002106 char b[128];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002107
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002108 for (j = 0, n = 0; j < 16; j++) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002109 unsigned char c = buf[i+j];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002110
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002111 if (c >= 0x20 && c < 0x7e)
2112 n += scnprintf(b + n, sizeof(b) - n,
2113 " %c ", buf[i+j]);
2114 else
2115 n += scnprintf(b + n, sizeof(b) - n,
2116 "%02x ", buf[i+j]);
2117 }
2118 pr_err("%04d: %s\n", i, b);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002119 }
2120}
2121
2122static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
Martin K. Petersen395cef02009-09-18 17:33:03 -04002123 unsigned int sectors, u32 ei_lba)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002124{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002125 int ret;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002126 struct sd_dif_tuple *sdt;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002127 void *daddr;
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002128 sector_t sector = start_sec;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002129 int ppage_offset;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002130 int dpage_offset;
2131 struct sg_mapping_iter diter;
2132 struct sg_mapping_iter piter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002133
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002134 BUG_ON(scsi_sg_count(SCpnt) == 0);
2135 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
2136
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002137 sg_miter_start(&piter, scsi_prot_sglist(SCpnt),
2138 scsi_prot_sg_count(SCpnt),
2139 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
2140 sg_miter_start(&diter, scsi_sglist(SCpnt), scsi_sg_count(SCpnt),
2141 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002142
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002143 /* For each protection page */
2144 while (sg_miter_next(&piter)) {
2145 dpage_offset = 0;
2146 if (WARN_ON(!sg_miter_next(&diter))) {
2147 ret = 0x01;
2148 goto out;
2149 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002150
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002151 for (ppage_offset = 0; ppage_offset < piter.length;
2152 ppage_offset += sizeof(struct sd_dif_tuple)) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002153 /* If we're at the end of the current
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002154 * data page advance to the next one
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002155 */
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002156 if (dpage_offset >= diter.length) {
2157 if (WARN_ON(!sg_miter_next(&diter))) {
2158 ret = 0x01;
2159 goto out;
2160 }
2161 dpage_offset = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002162 }
2163
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002164 sdt = piter.addr + ppage_offset;
2165 daddr = diter.addr + dpage_offset;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002166
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002167 ret = dif_verify(sdt, daddr, sector, ei_lba);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002168 if (ret) {
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002169 dump_sector(daddr, scsi_debug_sector_size);
Martin K. Petersen395cef02009-09-18 17:33:03 -04002170 goto out;
2171 }
2172
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002173 sector++;
Martin K. Petersen395cef02009-09-18 17:33:03 -04002174 ei_lba++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002175 dpage_offset += scsi_debug_sector_size;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002176 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002177 diter.consumed = dpage_offset;
2178 sg_miter_stop(&diter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002179 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002180 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002181
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002182 dif_copy_prot(SCpnt, start_sec, sectors, false);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002183 dix_writes++;
2184
2185 return 0;
2186
2187out:
2188 dif_errors++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002189 sg_miter_stop(&diter);
2190 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002191 return ret;
2192}
2193
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002194static unsigned long lba_to_map_index(sector_t lba)
2195{
2196 if (scsi_debug_unmap_alignment) {
2197 lba += scsi_debug_unmap_granularity -
2198 scsi_debug_unmap_alignment;
2199 }
2200 do_div(lba, scsi_debug_unmap_granularity);
2201
2202 return lba;
2203}
2204
2205static sector_t map_index_to_lba(unsigned long index)
2206{
Akinobu Mitaa027b5b2013-08-26 22:08:41 +09002207 sector_t lba = index * scsi_debug_unmap_granularity;
2208
2209 if (scsi_debug_unmap_alignment) {
2210 lba -= scsi_debug_unmap_granularity -
2211 scsi_debug_unmap_alignment;
2212 }
2213
2214 return lba;
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002215}
2216
Martin K. Petersen44d92692009-10-15 14:45:27 -04002217static unsigned int map_state(sector_t lba, unsigned int *num)
2218{
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002219 sector_t end;
2220 unsigned int mapped;
2221 unsigned long index;
2222 unsigned long next;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002223
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002224 index = lba_to_map_index(lba);
2225 mapped = test_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002226
2227 if (mapped)
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002228 next = find_next_zero_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002229 else
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002230 next = find_next_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002231
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002232 end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
Martin K. Petersen44d92692009-10-15 14:45:27 -04002233 *num = end - lba;
2234
2235 return mapped;
2236}
2237
2238static void map_region(sector_t lba, unsigned int len)
2239{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002240 sector_t end = lba + len;
2241
Martin K. Petersen44d92692009-10-15 14:45:27 -04002242 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002243 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002244
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002245 if (index < map_size)
2246 set_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002247
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002248 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002249 }
2250}
2251
2252static void unmap_region(sector_t lba, unsigned int len)
2253{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002254 sector_t end = lba + len;
2255
Martin K. Petersen44d92692009-10-15 14:45:27 -04002256 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002257 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002258
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002259 if (lba == map_index_to_lba(index) &&
2260 lba + scsi_debug_unmap_granularity <= end &&
2261 index < map_size) {
2262 clear_bit(index, map_storep);
2263 if (scsi_debug_lbprz) {
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002264 memset(fake_storep +
Akinobu Mitacc34a8e2013-04-16 22:11:57 +09002265 lba * scsi_debug_sector_size, 0,
2266 scsi_debug_sector_size *
2267 scsi_debug_unmap_granularity);
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002268 }
Akinobu Mitae9926b42013-06-29 17:59:17 +09002269 if (dif_storep) {
2270 memset(dif_storep + lba, 0xff,
2271 sizeof(*dif_storep) *
2272 scsi_debug_unmap_granularity);
2273 }
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002274 }
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002275 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002276 }
2277}
2278
FUJITA Tomonori19789102008-03-30 00:59:56 +09002279static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002280 unsigned int num, u32 ei_lba)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281{
2282 unsigned long iflags;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002283 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002285 ret = check_device_access_params(SCpnt, lba, num);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002286 if (ret)
2287 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002289 write_lock_irqsave(&atomic_rw, iflags);
2290
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002291 /* DIX + T10 DIF */
2292 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
Martin K. Petersen395cef02009-09-18 17:33:03 -04002293 int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002294
2295 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002296 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002297 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10,
2298 prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002299 return illegal_condition_result;
2300 }
2301 }
2302
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002303 ret = do_device_access(SCpnt, lba, num, 1);
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002304 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002305 map_region(lba, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 write_unlock_irqrestore(&atomic_rw, iflags);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002307 if (-1 == ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 return (DID_ERROR << 16);
Martin K. Petersen597136a2008-06-05 00:12:59 -04002309 else if ((ret < (num * scsi_debug_sector_size)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002311 sdev_printk(KERN_INFO, SCpnt->device,
2312 "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
2313 my_name, num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002314
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 return 0;
2316}
2317
Martin K. Petersen44d92692009-10-15 14:45:27 -04002318static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002319 unsigned int num, u32 ei_lba, unsigned int unmap)
Martin K. Petersen44d92692009-10-15 14:45:27 -04002320{
2321 unsigned long iflags;
2322 unsigned long long i;
2323 int ret;
2324
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002325 ret = check_device_access_params(scmd, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002326 if (ret)
2327 return ret;
2328
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002329 if (num > scsi_debug_write_same_length) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002330 mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002331 0);
2332 return check_condition_result;
2333 }
2334
Martin K. Petersen44d92692009-10-15 14:45:27 -04002335 write_lock_irqsave(&atomic_rw, iflags);
2336
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002337 if (unmap && scsi_debug_lbp()) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04002338 unmap_region(lba, num);
2339 goto out;
2340 }
2341
2342 /* Else fetch one logical block */
2343 ret = fetch_to_dev_buffer(scmd,
2344 fake_storep + (lba * scsi_debug_sector_size),
2345 scsi_debug_sector_size);
2346
2347 if (-1 == ret) {
2348 write_unlock_irqrestore(&atomic_rw, iflags);
2349 return (DID_ERROR << 16);
2350 } else if ((ret < (num * scsi_debug_sector_size)) &&
2351 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002352 sdev_printk(KERN_INFO, scmd->device,
2353 "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
2354 my_name, "write same",
2355 num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002356
2357 /* Copy first sector to remaining blocks */
2358 for (i = 1 ; i < num ; i++)
2359 memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
2360 fake_storep + (lba * scsi_debug_sector_size),
2361 scsi_debug_sector_size);
2362
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002363 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002364 map_region(lba, num);
2365out:
2366 write_unlock_irqrestore(&atomic_rw, iflags);
2367
2368 return 0;
2369}
2370
2371struct unmap_block_desc {
2372 __be64 lba;
2373 __be32 blocks;
2374 __be32 __reserved;
2375};
2376
2377static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
2378{
2379 unsigned char *buf;
2380 struct unmap_block_desc *desc;
2381 unsigned int i, payload_len, descriptors;
2382 int ret;
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002383 unsigned long iflags;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002384
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002385 ret = check_readiness(scmd, UAS_ONLY, devip);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002386 if (ret)
2387 return ret;
2388
2389 payload_len = get_unaligned_be16(&scmd->cmnd[7]);
2390 BUG_ON(scsi_bufflen(scmd) != payload_len);
2391
2392 descriptors = (payload_len - 8) / 16;
2393
2394 buf = kmalloc(scsi_bufflen(scmd), GFP_ATOMIC);
2395 if (!buf)
2396 return check_condition_result;
2397
2398 scsi_sg_copy_to_buffer(scmd, buf, scsi_bufflen(scmd));
2399
2400 BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
2401 BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
2402
2403 desc = (void *)&buf[8];
2404
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002405 write_lock_irqsave(&atomic_rw, iflags);
2406
Martin K. Petersen44d92692009-10-15 14:45:27 -04002407 for (i = 0 ; i < descriptors ; i++) {
2408 unsigned long long lba = get_unaligned_be64(&desc[i].lba);
2409 unsigned int num = get_unaligned_be32(&desc[i].blocks);
2410
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002411 ret = check_device_access_params(scmd, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002412 if (ret)
2413 goto out;
2414
2415 unmap_region(lba, num);
2416 }
2417
2418 ret = 0;
2419
2420out:
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002421 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002422 kfree(buf);
2423
2424 return ret;
2425}
2426
2427#define SDEBUG_GET_LBA_STATUS_LEN 32
2428
2429static int resp_get_lba_status(struct scsi_cmnd * scmd,
2430 struct sdebug_dev_info * devip)
2431{
2432 unsigned long long lba;
2433 unsigned int alloc_len, mapped, num;
2434 unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN];
2435 int ret;
2436
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002437 ret = check_readiness(scmd, UAS_ONLY, devip);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002438 if (ret)
2439 return ret;
2440
2441 lba = get_unaligned_be64(&scmd->cmnd[2]);
2442 alloc_len = get_unaligned_be32(&scmd->cmnd[10]);
2443
2444 if (alloc_len < 24)
2445 return 0;
2446
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002447 ret = check_device_access_params(scmd, lba, 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002448 if (ret)
2449 return ret;
2450
2451 mapped = map_state(lba, &num);
2452
2453 memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
Douglas Gilbertde13e962012-01-19 19:30:00 -05002454 put_unaligned_be32(20, &arr[0]); /* Parameter Data Length */
Martin K. Petersen44d92692009-10-15 14:45:27 -04002455 put_unaligned_be64(lba, &arr[8]); /* LBA */
2456 put_unaligned_be32(num, &arr[16]); /* Number of blocks */
2457 arr[20] = !mapped; /* mapped = 0, unmapped = 1 */
2458
2459 return fill_from_dev_buffer(scmd, arr, SDEBUG_GET_LBA_STATUS_LEN);
2460}
2461
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002462#define SDEBUG_RLUN_ARR_SZ 256
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463
2464static int resp_report_luns(struct scsi_cmnd * scp,
2465 struct sdebug_dev_info * devip)
2466{
2467 unsigned int alloc_len;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002468 int lun_cnt, i, upper, num, n, want_wlun, shortish;
2469 u64 lun;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002470 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 int select_report = (int)cmd[2];
2472 struct scsi_lun *one_lun;
2473 unsigned char arr[SDEBUG_RLUN_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002474 unsigned char * max_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
2476 alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002477 shortish = (alloc_len < 4);
2478 if (shortish || (select_report > 2)) {
2479 mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 return check_condition_result;
2481 }
2482 /* can produce response with up to 16k luns (lun 0 to lun 16383) */
2483 memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
2484 lun_cnt = scsi_debug_max_luns;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002485 if (1 == select_report)
2486 lun_cnt = 0;
2487 else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
2488 --lun_cnt;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002489 want_wlun = (select_report > 0) ? 1 : 0;
2490 num = lun_cnt + want_wlun;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002491 arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
2492 arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
2493 n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
2494 sizeof(struct scsi_lun)), num);
2495 if (n < num) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002496 want_wlun = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002497 lun_cnt = n;
2498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 one_lun = (struct scsi_lun *) &arr[8];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002500 max_addr = arr + SDEBUG_RLUN_ARR_SZ;
2501 for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
2502 ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
2503 i++, lun++) {
2504 upper = (lun >> 8) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 if (upper)
2506 one_lun[i].scsi_lun[0] =
2507 (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002508 one_lun[i].scsi_lun[1] = lun & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002510 if (want_wlun) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002511 one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
2512 one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
2513 i++;
2514 }
2515 alloc_len = (unsigned char *)(one_lun + i) - arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 return fill_from_dev_buffer(scp, arr,
2517 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
2518}
2519
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002520static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
2521 unsigned int num, struct sdebug_dev_info *devip)
2522{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002523 int j;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002524 unsigned char *kaddr, *buf;
2525 unsigned int offset;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002526 struct scsi_data_buffer *sdb = scsi_in(scp);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002527 struct sg_mapping_iter miter;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002528
2529 /* better not to use temporary buffer. */
2530 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09002531 if (!buf) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002532 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
2533 INSUFF_RES_ASCQ);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09002534 return check_condition_result;
2535 }
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002536
FUJITA Tomonori21a61822008-03-09 13:44:30 +09002537 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002538
2539 offset = 0;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002540 sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents,
2541 SG_MITER_ATOMIC | SG_MITER_TO_SG);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002542
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002543 while (sg_miter_next(&miter)) {
2544 kaddr = miter.addr;
2545 for (j = 0; j < miter.length; j++)
2546 *(kaddr + j) ^= *(buf + offset + j);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002547
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002548 offset += miter.length;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002549 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002550 sg_miter_stop(&miter);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002551 kfree(buf);
2552
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002553 return 0;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002554}
2555
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002556/* When timer or tasklet goes off this function is called. */
2557static void sdebug_q_cmd_complete(unsigned long indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002559 int qa_indx;
2560 int retiring = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002562 struct sdebug_queued_cmd *sqcp;
2563 struct scsi_cmnd *scp;
2564 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002566 atomic_inc(&sdebug_completions);
2567 qa_indx = indx;
2568 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
2569 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 return;
2571 }
2572 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002573 sqcp = &queued_arr[qa_indx];
2574 scp = sqcp->a_cmnd;
2575 if (NULL == scp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002577 pr_err("%s: scp is NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 return;
2579 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002580 devip = (struct sdebug_dev_info *)scp->device->hostdata;
2581 if (devip)
2582 atomic_dec(&devip->num_in_q);
2583 else
2584 pr_err("%s: devip=NULL\n", __func__);
2585 if (atomic_read(&retired_max_queue) > 0)
2586 retiring = 1;
2587
2588 sqcp->a_cmnd = NULL;
2589 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
2590 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2591 pr_err("%s: Unexpected completion\n", __func__);
2592 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002594
2595 if (unlikely(retiring)) { /* user has reduced max_queue */
2596 int k, retval;
2597
2598 retval = atomic_read(&retired_max_queue);
2599 if (qa_indx >= retval) {
2600 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2601 pr_err("%s: index %d too large\n", __func__, retval);
2602 return;
2603 }
2604 k = find_last_bit(queued_in_use_bm, retval);
2605 if ((k < scsi_debug_max_queue) || (k == retval))
2606 atomic_set(&retired_max_queue, 0);
2607 else
2608 atomic_set(&retired_max_queue, k + 1);
2609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002611 scp->scsi_done(scp); /* callback to mid level */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612}
2613
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002614/* When high resolution timer goes off this function is called. */
2615static enum hrtimer_restart
2616sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
2617{
2618 int qa_indx;
2619 int retiring = 0;
2620 unsigned long iflags;
2621 struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
2622 struct sdebug_queued_cmd *sqcp;
2623 struct scsi_cmnd *scp;
2624 struct sdebug_dev_info *devip;
2625
2626 atomic_inc(&sdebug_completions);
2627 qa_indx = sd_hrtp->qa_indx;
2628 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
2629 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
2630 goto the_end;
2631 }
2632 spin_lock_irqsave(&queued_arr_lock, iflags);
2633 sqcp = &queued_arr[qa_indx];
2634 scp = sqcp->a_cmnd;
2635 if (NULL == scp) {
2636 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2637 pr_err("%s: scp is NULL\n", __func__);
2638 goto the_end;
2639 }
2640 devip = (struct sdebug_dev_info *)scp->device->hostdata;
2641 if (devip)
2642 atomic_dec(&devip->num_in_q);
2643 else
2644 pr_err("%s: devip=NULL\n", __func__);
2645 if (atomic_read(&retired_max_queue) > 0)
2646 retiring = 1;
2647
2648 sqcp->a_cmnd = NULL;
2649 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
2650 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2651 pr_err("%s: Unexpected completion\n", __func__);
2652 goto the_end;
2653 }
2654
2655 if (unlikely(retiring)) { /* user has reduced max_queue */
2656 int k, retval;
2657
2658 retval = atomic_read(&retired_max_queue);
2659 if (qa_indx >= retval) {
2660 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2661 pr_err("%s: index %d too large\n", __func__, retval);
2662 goto the_end;
2663 }
2664 k = find_last_bit(queued_in_use_bm, retval);
2665 if ((k < scsi_debug_max_queue) || (k == retval))
2666 atomic_set(&retired_max_queue, 0);
2667 else
2668 atomic_set(&retired_max_queue, k + 1);
2669 }
2670 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2671 scp->scsi_done(scp); /* callback to mid level */
2672the_end:
2673 return HRTIMER_NORESTART;
2674}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002676static struct sdebug_dev_info *
2677sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09002678{
2679 struct sdebug_dev_info *devip;
2680
2681 devip = kzalloc(sizeof(*devip), flags);
2682 if (devip) {
2683 devip->sdbg_host = sdbg_host;
2684 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
2685 }
2686 return devip;
2687}
2688
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
2690{
2691 struct sdebug_host_info * sdbg_host;
2692 struct sdebug_dev_info * open_devip = NULL;
2693 struct sdebug_dev_info * devip =
2694 (struct sdebug_dev_info *)sdev->hostdata;
2695
2696 if (devip)
2697 return devip;
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09002698 sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
2699 if (!sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002700 pr_err("%s: Host info NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 return NULL;
2702 }
2703 list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
2704 if ((devip->used) && (devip->channel == sdev->channel) &&
2705 (devip->target == sdev->id) &&
2706 (devip->lun == sdev->lun))
2707 return devip;
2708 else {
2709 if ((!devip->used) && (!open_devip))
2710 open_devip = devip;
2711 }
2712 }
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09002713 if (!open_devip) { /* try and make a new one */
2714 open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
2715 if (!open_devip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002717 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 return NULL;
2719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 }
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09002721
2722 open_devip->channel = sdev->channel;
2723 open_devip->target = sdev->id;
2724 open_devip->lun = sdev->lun;
2725 open_devip->sdbg_host = sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002726 atomic_set(&open_devip->num_in_q, 0);
2727 set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09002728 open_devip->used = 1;
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09002729 if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
2730 open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
2731
2732 return open_devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733}
2734
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002735static int scsi_debug_slave_alloc(struct scsi_device *sdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002737 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002738 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002739 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
Nick Piggin75ad23b2008-04-29 14:48:33 +02002740 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002741 return 0;
2742}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002744static int scsi_debug_slave_configure(struct scsi_device *sdp)
2745{
2746 struct sdebug_dev_info *devip;
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +09002747
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002749 printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002750 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
2751 if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
2752 sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
2753 devip = devInfoReg(sdp);
2754 if (NULL == devip)
2755 return 1; /* no resources, will be marked offline */
Christoph Hellwigc8b09f62014-11-03 20:15:14 +01002756 sdp->hostdata = devip;
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09002757 blk_queue_max_segment_size(sdp->request_queue, -1U);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002758 if (scsi_debug_no_uld)
2759 sdp->no_uld_attach = 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002760 return 0;
2761}
2762
2763static void scsi_debug_slave_destroy(struct scsi_device *sdp)
2764{
2765 struct sdebug_dev_info *devip =
2766 (struct sdebug_dev_info *)sdp->hostdata;
2767
2768 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002769 printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002770 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
2771 if (devip) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002772 /* make this slot available for re-use */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002773 devip->used = 0;
2774 sdp->hostdata = NULL;
2775 }
2776}
2777
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002778/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002779static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
2780{
2781 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002782 int k, qmax, r_qmax;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002783 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002784 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002785
2786 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002787 qmax = scsi_debug_max_queue;
2788 r_qmax = atomic_read(&retired_max_queue);
2789 if (r_qmax > qmax)
2790 qmax = r_qmax;
2791 for (k = 0; k < qmax; ++k) {
2792 if (test_bit(k, queued_in_use_bm)) {
2793 sqcp = &queued_arr[k];
2794 if (cmnd == sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04002795 devip = (struct sdebug_dev_info *)
2796 cmnd->device->hostdata;
2797 if (devip)
2798 atomic_dec(&devip->num_in_q);
2799 sqcp->a_cmnd = NULL;
2800 spin_unlock_irqrestore(&queued_arr_lock,
2801 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002802 if (scsi_debug_ndelay > 0) {
2803 if (sqcp->sd_hrtp)
2804 hrtimer_cancel(
2805 &sqcp->sd_hrtp->hrt);
2806 } else if (scsi_debug_delay > 0) {
2807 if (sqcp->cmnd_timerp)
2808 del_timer_sync(
2809 sqcp->cmnd_timerp);
2810 } else if (scsi_debug_delay < 0) {
2811 if (sqcp->tletp)
2812 tasklet_kill(sqcp->tletp);
2813 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04002814 clear_bit(k, queued_in_use_bm);
2815 return 1;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002816 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002817 }
2818 }
2819 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04002820 return 0;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002821}
2822
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002823/* Deletes (stops) timers or tasklets of all queued commands */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002824static void stop_all_queued(void)
2825{
2826 unsigned long iflags;
2827 int k;
2828 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002829 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002830
2831 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002832 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
2833 if (test_bit(k, queued_in_use_bm)) {
2834 sqcp = &queued_arr[k];
2835 if (sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04002836 devip = (struct sdebug_dev_info *)
2837 sqcp->a_cmnd->device->hostdata;
2838 if (devip)
2839 atomic_dec(&devip->num_in_q);
2840 sqcp->a_cmnd = NULL;
2841 spin_unlock_irqrestore(&queued_arr_lock,
2842 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002843 if (scsi_debug_ndelay > 0) {
2844 if (sqcp->sd_hrtp)
2845 hrtimer_cancel(
2846 &sqcp->sd_hrtp->hrt);
2847 } else if (scsi_debug_delay > 0) {
2848 if (sqcp->cmnd_timerp)
2849 del_timer_sync(
2850 sqcp->cmnd_timerp);
2851 } else if (scsi_debug_delay < 0) {
2852 if (sqcp->tletp)
2853 tasklet_kill(sqcp->tletp);
2854 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04002855 clear_bit(k, queued_in_use_bm);
2856 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002857 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002858 }
2859 }
2860 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861}
2862
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002863/* Free queued command memory on heap */
2864static void free_all_queued(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002866 unsigned long iflags;
2867 int k;
2868 struct sdebug_queued_cmd *sqcp;
2869
2870 spin_lock_irqsave(&queued_arr_lock, iflags);
2871 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
2872 sqcp = &queued_arr[k];
2873 kfree(sqcp->cmnd_timerp);
2874 sqcp->cmnd_timerp = NULL;
2875 kfree(sqcp->tletp);
2876 sqcp->tletp = NULL;
2877 kfree(sqcp->sd_hrtp);
2878 sqcp->sd_hrtp = NULL;
2879 }
2880 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881}
2882
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002883static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002885 ++num_aborts;
2886 if (SCpnt) {
2887 if (SCpnt->device &&
2888 (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
2889 sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
2890 __func__);
2891 stop_queued_cmnd(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002893 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894}
2895
2896static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
2897{
2898 struct sdebug_dev_info * devip;
2899
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 ++num_dev_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002901 if (SCpnt && SCpnt->device) {
2902 struct scsi_device *sdp = SCpnt->device;
2903
2904 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
2905 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
2906 devip = devInfoReg(sdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 if (devip)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002908 set_bit(SDEBUG_UA_POR, devip->uas_bm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 }
2910 return SUCCESS;
2911}
2912
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002913static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
2914{
2915 struct sdebug_host_info *sdbg_host;
2916 struct sdebug_dev_info *devip;
2917 struct scsi_device *sdp;
2918 struct Scsi_Host *hp;
2919 int k = 0;
2920
2921 ++num_target_resets;
2922 if (!SCpnt)
2923 goto lie;
2924 sdp = SCpnt->device;
2925 if (!sdp)
2926 goto lie;
2927 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
2928 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
2929 hp = sdp->host;
2930 if (!hp)
2931 goto lie;
2932 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
2933 if (sdbg_host) {
2934 list_for_each_entry(devip,
2935 &sdbg_host->dev_info_list,
2936 dev_list)
2937 if (devip->target == sdp->id) {
2938 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
2939 ++k;
2940 }
2941 }
2942 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
2943 sdev_printk(KERN_INFO, sdp,
2944 "%s: %d device(s) found in target\n", __func__, k);
2945lie:
2946 return SUCCESS;
2947}
2948
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
2950{
2951 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002952 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 struct scsi_device * sdp;
2954 struct Scsi_Host * hp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002955 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 ++num_bus_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002958 if (!(SCpnt && SCpnt->device))
2959 goto lie;
2960 sdp = SCpnt->device;
2961 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
2962 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
2963 hp = sdp->host;
2964 if (hp) {
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09002965 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966 if (sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002967 list_for_each_entry(devip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 &sdbg_host->dev_info_list,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002969 dev_list) {
2970 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
2971 ++k;
2972 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 }
2974 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002975 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
2976 sdev_printk(KERN_INFO, sdp,
2977 "%s: %d device(s) found in host\n", __func__, k);
2978lie:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 return SUCCESS;
2980}
2981
2982static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
2983{
2984 struct sdebug_host_info * sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002985 struct sdebug_dev_info *devip;
2986 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 ++num_host_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002989 if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
2990 sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 spin_lock(&sdebug_host_list_lock);
2992 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002993 list_for_each_entry(devip, &sdbg_host->dev_info_list,
2994 dev_list) {
2995 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
2996 ++k;
2997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 }
2999 spin_unlock(&sdebug_host_list_lock);
3000 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003001 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3002 sdev_printk(KERN_INFO, SCpnt->device,
3003 "%s: %d device(s) found\n", __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 return SUCCESS;
3005}
3006
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003007static void __init sdebug_build_parts(unsigned char *ramp,
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003008 unsigned long store_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009{
3010 struct partition * pp;
3011 int starts[SDEBUG_MAX_PARTS + 2];
3012 int sectors_per_part, num_sectors, k;
3013 int heads_by_sects, start_sec, end_sec;
3014
3015 /* assume partition table already zeroed */
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003016 if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 return;
3018 if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
3019 scsi_debug_num_parts = SDEBUG_MAX_PARTS;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003020 pr_warn("%s: reducing partitions to %d\n", __func__,
3021 SDEBUG_MAX_PARTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003023 num_sectors = (int)sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 sectors_per_part = (num_sectors - sdebug_sectors_per)
3025 / scsi_debug_num_parts;
3026 heads_by_sects = sdebug_heads * sdebug_sectors_per;
3027 starts[0] = sdebug_sectors_per;
3028 for (k = 1; k < scsi_debug_num_parts; ++k)
3029 starts[k] = ((k * sectors_per_part) / heads_by_sects)
3030 * heads_by_sects;
3031 starts[scsi_debug_num_parts] = num_sectors;
3032 starts[scsi_debug_num_parts + 1] = 0;
3033
3034 ramp[510] = 0x55; /* magic partition markings */
3035 ramp[511] = 0xAA;
3036 pp = (struct partition *)(ramp + 0x1be);
3037 for (k = 0; starts[k + 1]; ++k, ++pp) {
3038 start_sec = starts[k];
3039 end_sec = starts[k + 1] - 1;
3040 pp->boot_ind = 0;
3041
3042 pp->cyl = start_sec / heads_by_sects;
3043 pp->head = (start_sec - (pp->cyl * heads_by_sects))
3044 / sdebug_sectors_per;
3045 pp->sector = (start_sec % sdebug_sectors_per) + 1;
3046
3047 pp->end_cyl = end_sec / heads_by_sects;
3048 pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
3049 / sdebug_sectors_per;
3050 pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
3051
Akinobu Mita150c3542013-08-26 22:08:40 +09003052 pp->start_sect = cpu_to_le32(start_sec);
3053 pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 pp->sys_ind = 0x83; /* plain Linux partition */
3055 }
3056}
3057
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003058static int
3059schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
3060 int scsi_result, int delta_jiff)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003062 unsigned long iflags;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003063 int k, num_in_q, qdepth, inject;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003064 struct sdebug_queued_cmd *sqcp = NULL;
3065 struct scsi_device *sdp = cmnd->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003067 if (NULL == cmnd || NULL == devip) {
3068 pr_warn("%s: called with NULL cmnd or devip pointer\n",
3069 __func__);
3070 /* no particularly good error to report back */
3071 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003073 if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3074 sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
3075 __func__, scsi_result);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003076 if (delta_jiff == 0)
3077 goto respond_in_thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003079 /* schedule the response at a later time if resources permit */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003080 spin_lock_irqsave(&queued_arr_lock, iflags);
3081 num_in_q = atomic_read(&devip->num_in_q);
3082 qdepth = cmnd->device->queue_depth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003083 inject = 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003084 if ((qdepth > 0) && (num_in_q >= qdepth)) {
3085 if (scsi_result) {
3086 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3087 goto respond_in_thread;
3088 } else
3089 scsi_result = device_qfull_result;
3090 } else if ((scsi_debug_every_nth != 0) &&
3091 (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) &&
3092 (scsi_result == 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003093 if ((num_in_q == (qdepth - 1)) &&
3094 (atomic_inc_return(&sdebug_a_tsf) >=
3095 abs(scsi_debug_every_nth))) {
3096 atomic_set(&sdebug_a_tsf, 0);
3097 inject = 1;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003098 scsi_result = device_qfull_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003100 }
3101
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003102 k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003103 if (k >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003105 if (scsi_result)
3106 goto respond_in_thread;
3107 else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
3108 scsi_result = device_qfull_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003109 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
3110 sdev_printk(KERN_INFO, sdp,
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003111 "%s: max_queue=%d exceeded, %s\n",
3112 __func__, scsi_debug_max_queue,
3113 (scsi_result ? "status: TASK SET FULL" :
3114 "report: host busy"));
3115 if (scsi_result)
3116 goto respond_in_thread;
3117 else
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003118 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003120 __set_bit(k, queued_in_use_bm);
3121 atomic_inc(&devip->num_in_q);
3122 sqcp = &queued_arr[k];
3123 sqcp->a_cmnd = cmnd;
3124 cmnd->result = scsi_result;
3125 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3126 if (delta_jiff > 0) {
3127 if (NULL == sqcp->cmnd_timerp) {
3128 sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
3129 GFP_ATOMIC);
3130 if (NULL == sqcp->cmnd_timerp)
3131 return SCSI_MLQUEUE_HOST_BUSY;
3132 init_timer(sqcp->cmnd_timerp);
3133 }
3134 sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
3135 sqcp->cmnd_timerp->data = k;
3136 sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
3137 add_timer(sqcp->cmnd_timerp);
3138 } else if (scsi_debug_ndelay > 0) {
3139 ktime_t kt = ktime_set(0, scsi_debug_ndelay);
3140 struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
3141
3142 if (NULL == sd_hp) {
3143 sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
3144 if (NULL == sd_hp)
3145 return SCSI_MLQUEUE_HOST_BUSY;
3146 sqcp->sd_hrtp = sd_hp;
3147 hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
3148 HRTIMER_MODE_REL);
3149 sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
3150 sd_hp->qa_indx = k;
3151 }
3152 hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
3153 } else { /* delay < 0 */
3154 if (NULL == sqcp->tletp) {
3155 sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
3156 GFP_ATOMIC);
3157 if (NULL == sqcp->tletp)
3158 return SCSI_MLQUEUE_HOST_BUSY;
3159 tasklet_init(sqcp->tletp,
3160 sdebug_q_cmd_complete, k);
3161 }
3162 if (-1 == delta_jiff)
3163 tasklet_hi_schedule(sqcp->tletp);
3164 else
3165 tasklet_schedule(sqcp->tletp);
3166 }
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003167 if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) &&
3168 (scsi_result == device_qfull_result))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003169 sdev_printk(KERN_INFO, sdp,
3170 "%s: num_in_q=%d +1, %s%s\n", __func__,
3171 num_in_q, (inject ? "<inject> " : ""),
3172 "status: TASK SET FULL");
3173 return 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003174
3175respond_in_thread: /* call back to mid-layer using invocation thread */
3176 cmnd->result = scsi_result;
3177 cmnd->scsi_done(cmnd);
3178 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003180
Douglas Gilbert23183912006-09-16 20:30:47 -04003181/* Note: The following macros create attribute files in the
3182 /sys/module/scsi_debug/parameters directory. Unfortunately this
3183 driver is unaware of a change and cannot trigger auxiliary actions
3184 as it can when the corresponding attribute in the
3185 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
3186 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003187module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003188module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
Akinobu Mita0759c662014-02-26 22:57:04 +09003189module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003190module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
3191module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003192module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
3193module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003194module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
3195module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04003196module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
Akinobu Mita68aee7b2013-09-18 21:27:27 +09003197module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003198module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003199module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
3200module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
3201module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
Eric Sandeenbe1dd782012-03-08 00:03:59 -06003202module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003203module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003204module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003205module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003206module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003207module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003208module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003209module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
3210module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003211module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003212module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003213module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003214module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
Martin Pittd9867882012-09-06 12:04:33 +02003215module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003216module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003217module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
3218module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
3219module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
3220module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
3221module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003222module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04003223module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
3224 S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003225module_param_named(write_same_length, scsi_debug_write_same_length, int,
3226 S_IRUGO | S_IWUSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227
3228MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
3229MODULE_DESCRIPTION("SCSI debug adapter driver");
3230MODULE_LICENSE("GPL");
3231MODULE_VERSION(SCSI_DEBUG_VERSION);
3232
3233MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003234MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
Akinobu Mita0759c662014-02-26 22:57:04 +09003235MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003236MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003237MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003238MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
3239MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003240MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
Randy Dunlapbeb87c32007-06-11 11:36:40 -07003241MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
Douglas Gilbert23183912006-09-16 20:30:47 -04003242MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003243MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003244MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003245MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
3246MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
3247MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
Eric Sandeenbe1dd782012-03-08 00:03:59 -06003248MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003249MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003250MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003251MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
3252MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003253MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003254MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003256MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003257MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05003258MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003259MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
Martin Pittd9867882012-09-06 12:04:33 +02003261MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
Douglas Gilberte46b0342014-08-05 12:21:53 +02003262MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
Martin K. Petersenea61fca2009-05-15 00:40:33 -04003263MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003264MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
3265MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
Martin K. Petersen60147592010-08-19 11:49:00 -04003266MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
3267MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003268MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
3269MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
3270MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271
3272static char sdebug_info[256];
3273
3274static const char * scsi_debug_info(struct Scsi_Host * shp)
3275{
3276 sprintf(sdebug_info, "scsi_debug, version %s [%s], "
3277 "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
3278 scsi_debug_version_date, scsi_debug_dev_size_mb,
3279 scsi_debug_opts);
3280 return sdebug_info;
3281}
3282
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003283/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
Al Viroc8ed5552013-03-31 01:46:06 -04003284static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285{
Al Viroc8ed5552013-03-31 01:46:06 -04003286 char arr[16];
3287 int opts;
3288 int minLen = length > 15 ? 15 : length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289
Al Viroc8ed5552013-03-31 01:46:06 -04003290 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
3291 return -EACCES;
3292 memcpy(arr, buffer, minLen);
3293 arr[minLen] = '\0';
3294 if (1 != sscanf(arr, "%d", &opts))
3295 return -EINVAL;
3296 scsi_debug_opts = opts;
3297 if (scsi_debug_every_nth != 0)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003298 atomic_set(&sdebug_cmnd_count, 0);
Al Viroc8ed5552013-03-31 01:46:06 -04003299 return length;
3300}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003302/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
3303 * same for each scsi_debug host (if more than one). Some of the counters
3304 * output are not atomics so might be inaccurate in a busy system. */
Al Viroc8ed5552013-03-31 01:46:06 -04003305static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
3306{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003307 int f, l;
3308 char b[32];
3309
3310 if (scsi_debug_every_nth > 0)
3311 snprintf(b, sizeof(b), " (curr:%d)",
3312 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
3313 atomic_read(&sdebug_a_tsf) :
3314 atomic_read(&sdebug_cmnd_count)));
3315 else
3316 b[0] = '\0';
3317
3318 seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
3319 "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
3320 "every_nth=%d%s\n"
3321 "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
3322 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
3323 "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
3324 "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
3325 "usec_in_jiffy=%lu\n",
3326 SCSI_DEBUG_VERSION, scsi_debug_version_date,
3327 scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
3328 scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
3329 scsi_debug_max_luns, atomic_read(&sdebug_completions),
3330 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
3331 sdebug_sectors_per, num_aborts, num_dev_resets,
3332 num_target_resets, num_bus_resets, num_host_resets,
3333 dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
3334
3335 f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
3336 if (f != scsi_debug_max_queue) {
3337 l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
3338 seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n",
3339 "queued_in_use_bm", f, l);
3340 }
Al Viroc8ed5552013-03-31 01:46:06 -04003341 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342}
3343
Akinobu Mita82069372013-10-14 22:48:04 +09003344static ssize_t delay_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345{
3346 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
3347}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003348/* Returns -EBUSY if delay is being changed and commands are queued */
Akinobu Mita82069372013-10-14 22:48:04 +09003349static ssize_t delay_store(struct device_driver *ddp, const char *buf,
3350 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003352 int delay, res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003354 if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
3355 res = count;
3356 if (scsi_debug_delay != delay) {
3357 unsigned long iflags;
3358 int k;
3359
3360 spin_lock_irqsave(&queued_arr_lock, iflags);
3361 k = find_first_bit(queued_in_use_bm,
3362 scsi_debug_max_queue);
3363 if (k != scsi_debug_max_queue)
3364 res = -EBUSY; /* have queued commands */
3365 else {
3366 scsi_debug_delay = delay;
3367 scsi_debug_ndelay = 0;
3368 }
3369 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003371 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 }
3373 return -EINVAL;
3374}
Akinobu Mita82069372013-10-14 22:48:04 +09003375static DRIVER_ATTR_RW(delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003377static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
3378{
3379 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
3380}
3381/* Returns -EBUSY if ndelay is being changed and commands are queued */
3382/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
3383static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
3384 size_t count)
3385{
3386 unsigned long iflags;
3387 int ndelay, res, k;
3388
3389 if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
3390 (ndelay >= 0) && (ndelay < 1000000000)) {
3391 res = count;
3392 if (scsi_debug_ndelay != ndelay) {
3393 spin_lock_irqsave(&queued_arr_lock, iflags);
3394 k = find_first_bit(queued_in_use_bm,
3395 scsi_debug_max_queue);
3396 if (k != scsi_debug_max_queue)
3397 res = -EBUSY; /* have queued commands */
3398 else {
3399 scsi_debug_ndelay = ndelay;
3400 scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
3401 : DEF_DELAY;
3402 }
3403 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3404 }
3405 return res;
3406 }
3407 return -EINVAL;
3408}
3409static DRIVER_ATTR_RW(ndelay);
3410
Akinobu Mita82069372013-10-14 22:48:04 +09003411static ssize_t opts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412{
3413 return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
3414}
3415
Akinobu Mita82069372013-10-14 22:48:04 +09003416static ssize_t opts_store(struct device_driver *ddp, const char *buf,
3417 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418{
3419 int opts;
3420 char work[20];
3421
3422 if (1 == sscanf(buf, "%10s", work)) {
Rasmus Villemoes48a96872014-10-13 15:54:44 -07003423 if (0 == strncasecmp(work,"0x", 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 if (1 == sscanf(&work[2], "%x", &opts))
3425 goto opts_done;
3426 } else {
3427 if (1 == sscanf(work, "%d", &opts))
3428 goto opts_done;
3429 }
3430 }
3431 return -EINVAL;
3432opts_done:
3433 scsi_debug_opts = opts;
Douglas Gilbert817fd662014-11-24 20:18:02 -05003434 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
3435 sdebug_any_injecting_opt = true;
3436 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
3437 sdebug_any_injecting_opt = true;
3438 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
3439 sdebug_any_injecting_opt = true;
3440 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
3441 sdebug_any_injecting_opt = true;
3442 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
3443 sdebug_any_injecting_opt = true;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003444 atomic_set(&sdebug_cmnd_count, 0);
3445 atomic_set(&sdebug_a_tsf, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 return count;
3447}
Akinobu Mita82069372013-10-14 22:48:04 +09003448static DRIVER_ATTR_RW(opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449
Akinobu Mita82069372013-10-14 22:48:04 +09003450static ssize_t ptype_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451{
3452 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
3453}
Akinobu Mita82069372013-10-14 22:48:04 +09003454static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
3455 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456{
3457 int n;
3458
3459 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3460 scsi_debug_ptype = n;
3461 return count;
3462 }
3463 return -EINVAL;
3464}
Akinobu Mita82069372013-10-14 22:48:04 +09003465static DRIVER_ATTR_RW(ptype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466
Akinobu Mita82069372013-10-14 22:48:04 +09003467static ssize_t dsense_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468{
3469 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
3470}
Akinobu Mita82069372013-10-14 22:48:04 +09003471static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
3472 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473{
3474 int n;
3475
3476 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3477 scsi_debug_dsense = n;
3478 return count;
3479 }
3480 return -EINVAL;
3481}
Akinobu Mita82069372013-10-14 22:48:04 +09003482static DRIVER_ATTR_RW(dsense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483
Akinobu Mita82069372013-10-14 22:48:04 +09003484static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04003485{
3486 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
3487}
Akinobu Mita82069372013-10-14 22:48:04 +09003488static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
3489 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04003490{
3491 int n;
3492
3493 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003494 n = (n > 0);
3495 scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
3496 if (scsi_debug_fake_rw != n) {
3497 if ((0 == n) && (NULL == fake_storep)) {
3498 unsigned long sz =
3499 (unsigned long)scsi_debug_dev_size_mb *
3500 1048576;
3501
3502 fake_storep = vmalloc(sz);
3503 if (NULL == fake_storep) {
3504 pr_err("%s: out of memory, 9\n",
3505 __func__);
3506 return -ENOMEM;
3507 }
3508 memset(fake_storep, 0, sz);
3509 }
3510 scsi_debug_fake_rw = n;
3511 }
Douglas Gilbert23183912006-09-16 20:30:47 -04003512 return count;
3513 }
3514 return -EINVAL;
3515}
Akinobu Mita82069372013-10-14 22:48:04 +09003516static DRIVER_ATTR_RW(fake_rw);
Douglas Gilbert23183912006-09-16 20:30:47 -04003517
Akinobu Mita82069372013-10-14 22:48:04 +09003518static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003519{
3520 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
3521}
Akinobu Mita82069372013-10-14 22:48:04 +09003522static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
3523 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003524{
3525 int n;
3526
3527 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3528 scsi_debug_no_lun_0 = n;
3529 return count;
3530 }
3531 return -EINVAL;
3532}
Akinobu Mita82069372013-10-14 22:48:04 +09003533static DRIVER_ATTR_RW(no_lun_0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003534
Akinobu Mita82069372013-10-14 22:48:04 +09003535static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536{
3537 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
3538}
Akinobu Mita82069372013-10-14 22:48:04 +09003539static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
3540 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541{
3542 int n;
3543
3544 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3545 scsi_debug_num_tgts = n;
3546 sdebug_max_tgts_luns();
3547 return count;
3548 }
3549 return -EINVAL;
3550}
Akinobu Mita82069372013-10-14 22:48:04 +09003551static DRIVER_ATTR_RW(num_tgts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552
Akinobu Mita82069372013-10-14 22:48:04 +09003553static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554{
3555 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
3556}
Akinobu Mita82069372013-10-14 22:48:04 +09003557static DRIVER_ATTR_RO(dev_size_mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558
Akinobu Mita82069372013-10-14 22:48:04 +09003559static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560{
3561 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
3562}
Akinobu Mita82069372013-10-14 22:48:04 +09003563static DRIVER_ATTR_RO(num_parts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564
Akinobu Mita82069372013-10-14 22:48:04 +09003565static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566{
3567 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
3568}
Akinobu Mita82069372013-10-14 22:48:04 +09003569static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
3570 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571{
3572 int nth;
3573
3574 if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
3575 scsi_debug_every_nth = nth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003576 atomic_set(&sdebug_cmnd_count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 return count;
3578 }
3579 return -EINVAL;
3580}
Akinobu Mita82069372013-10-14 22:48:04 +09003581static DRIVER_ATTR_RW(every_nth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
Akinobu Mita82069372013-10-14 22:48:04 +09003583static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584{
3585 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
3586}
Akinobu Mita82069372013-10-14 22:48:04 +09003587static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
3588 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589{
3590 int n;
3591
3592 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3593 scsi_debug_max_luns = n;
3594 sdebug_max_tgts_luns();
3595 return count;
3596 }
3597 return -EINVAL;
3598}
Akinobu Mita82069372013-10-14 22:48:04 +09003599static DRIVER_ATTR_RW(max_luns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600
Akinobu Mita82069372013-10-14 22:48:04 +09003601static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003602{
3603 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
3604}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003605/* N.B. max_queue can be changed while there are queued commands. In flight
3606 * commands beyond the new max_queue will be completed. */
Akinobu Mita82069372013-10-14 22:48:04 +09003607static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
3608 size_t count)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003609{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003610 unsigned long iflags;
3611 int n, k;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003612
3613 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
3614 (n <= SCSI_DEBUG_CANQUEUE)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003615 spin_lock_irqsave(&queued_arr_lock, iflags);
3616 k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003617 scsi_debug_max_queue = n;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003618 if (SCSI_DEBUG_CANQUEUE == k)
3619 atomic_set(&retired_max_queue, 0);
3620 else if (k >= n)
3621 atomic_set(&retired_max_queue, k + 1);
3622 else
3623 atomic_set(&retired_max_queue, 0);
3624 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003625 return count;
3626 }
3627 return -EINVAL;
3628}
Akinobu Mita82069372013-10-14 22:48:04 +09003629static DRIVER_ATTR_RW(max_queue);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003630
Akinobu Mita82069372013-10-14 22:48:04 +09003631static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003632{
3633 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
3634}
Akinobu Mita82069372013-10-14 22:48:04 +09003635static DRIVER_ATTR_RO(no_uld);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003636
Akinobu Mita82069372013-10-14 22:48:04 +09003637static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638{
3639 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
3640}
Akinobu Mita82069372013-10-14 22:48:04 +09003641static DRIVER_ATTR_RO(scsi_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642
Akinobu Mita82069372013-10-14 22:48:04 +09003643static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003644{
3645 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
3646}
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05003647
Akinobu Mita82069372013-10-14 22:48:04 +09003648static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
3649 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003650{
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05003651 int n;
3652 bool changed;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003653
3654 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05003655 changed = (scsi_debug_virtual_gb != n);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003656 scsi_debug_virtual_gb = n;
FUJITA Tomonori28898872008-03-30 00:59:55 +09003657 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05003658 if (changed) {
3659 struct sdebug_host_info *sdhp;
3660 struct sdebug_dev_info *dp;
FUJITA Tomonori28898872008-03-30 00:59:55 +09003661
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05003662 list_for_each_entry(sdhp, &sdebug_host_list,
3663 host_list) {
3664 list_for_each_entry(dp, &sdhp->dev_info_list,
3665 dev_list) {
3666 set_bit(SDEBUG_UA_CAPACITY_CHANGED,
3667 dp->uas_bm);
3668 }
3669 }
3670 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003671 return count;
3672 }
3673 return -EINVAL;
3674}
Akinobu Mita82069372013-10-14 22:48:04 +09003675static DRIVER_ATTR_RW(virtual_gb);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003676
Akinobu Mita82069372013-10-14 22:48:04 +09003677static ssize_t add_host_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678{
3679 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
3680}
3681
Akinobu Mita82069372013-10-14 22:48:04 +09003682static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
3683 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684{
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09003685 int delta_hosts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09003687 if (sscanf(buf, "%d", &delta_hosts) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 if (delta_hosts > 0) {
3690 do {
3691 sdebug_add_adapter();
3692 } while (--delta_hosts);
3693 } else if (delta_hosts < 0) {
3694 do {
3695 sdebug_remove_adapter();
3696 } while (++delta_hosts);
3697 }
3698 return count;
3699}
Akinobu Mita82069372013-10-14 22:48:04 +09003700static DRIVER_ATTR_RW(add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701
Akinobu Mita82069372013-10-14 22:48:04 +09003702static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04003703{
3704 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
3705}
Akinobu Mita82069372013-10-14 22:48:04 +09003706static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
3707 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04003708{
3709 int n;
3710
3711 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3712 scsi_debug_vpd_use_hostno = n;
3713 return count;
3714 }
3715 return -EINVAL;
3716}
Akinobu Mita82069372013-10-14 22:48:04 +09003717static DRIVER_ATTR_RW(vpd_use_hostno);
Douglas Gilbert23183912006-09-16 20:30:47 -04003718
Akinobu Mita82069372013-10-14 22:48:04 +09003719static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
Martin K. Petersen597136a2008-06-05 00:12:59 -04003720{
3721 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
3722}
Akinobu Mita82069372013-10-14 22:48:04 +09003723static DRIVER_ATTR_RO(sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04003724
Akinobu Mita82069372013-10-14 22:48:04 +09003725static ssize_t dix_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003726{
3727 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
3728}
Akinobu Mita82069372013-10-14 22:48:04 +09003729static DRIVER_ATTR_RO(dix);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003730
Akinobu Mita82069372013-10-14 22:48:04 +09003731static ssize_t dif_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003732{
3733 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
3734}
Akinobu Mita82069372013-10-14 22:48:04 +09003735static DRIVER_ATTR_RO(dif);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003736
Akinobu Mita82069372013-10-14 22:48:04 +09003737static ssize_t guard_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003738{
Akinobu Mita68aee7b2013-09-18 21:27:27 +09003739 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003740}
Akinobu Mita82069372013-10-14 22:48:04 +09003741static DRIVER_ATTR_RO(guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003742
Akinobu Mita82069372013-10-14 22:48:04 +09003743static ssize_t ato_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003744{
3745 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
3746}
Akinobu Mita82069372013-10-14 22:48:04 +09003747static DRIVER_ATTR_RO(ato);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003748
Akinobu Mita82069372013-10-14 22:48:04 +09003749static ssize_t map_show(struct device_driver *ddp, char *buf)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003750{
3751 ssize_t count;
3752
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003753 if (!scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04003754 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
3755 sdebug_store_sectors);
3756
3757 count = bitmap_scnlistprintf(buf, PAGE_SIZE, map_storep, map_size);
3758
3759 buf[count++] = '\n';
3760 buf[count++] = 0;
3761
3762 return count;
3763}
Akinobu Mita82069372013-10-14 22:48:04 +09003764static DRIVER_ATTR_RO(map);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003765
Akinobu Mita82069372013-10-14 22:48:04 +09003766static ssize_t removable_show(struct device_driver *ddp, char *buf)
Martin Pittd9867882012-09-06 12:04:33 +02003767{
3768 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
3769}
Akinobu Mita82069372013-10-14 22:48:04 +09003770static ssize_t removable_store(struct device_driver *ddp, const char *buf,
3771 size_t count)
Martin Pittd9867882012-09-06 12:04:33 +02003772{
3773 int n;
3774
3775 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3776 scsi_debug_removable = (n > 0);
3777 return count;
3778 }
3779 return -EINVAL;
3780}
Akinobu Mita82069372013-10-14 22:48:04 +09003781static DRIVER_ATTR_RW(removable);
Martin Pittd9867882012-09-06 12:04:33 +02003782
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003783static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
3784{
3785 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
3786}
3787/* Returns -EBUSY if host_lock is being changed and commands are queued */
3788static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
3789 size_t count)
3790{
3791 int n, res;
3792
3793 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3794 bool new_host_lock = (n > 0);
3795
3796 res = count;
3797 if (new_host_lock != scsi_debug_host_lock) {
3798 unsigned long iflags;
3799 int k;
3800
3801 spin_lock_irqsave(&queued_arr_lock, iflags);
3802 k = find_first_bit(queued_in_use_bm,
3803 scsi_debug_max_queue);
3804 if (k != scsi_debug_max_queue)
3805 res = -EBUSY; /* have queued commands */
3806 else
3807 scsi_debug_host_lock = new_host_lock;
3808 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3809 }
3810 return res;
3811 }
3812 return -EINVAL;
3813}
3814static DRIVER_ATTR_RW(host_lock);
3815
3816
Akinobu Mita82069372013-10-14 22:48:04 +09003817/* Note: The following array creates attribute files in the
Douglas Gilbert23183912006-09-16 20:30:47 -04003818 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
3819 files (over those found in the /sys/module/scsi_debug/parameters
3820 directory) is that auxiliary actions can be triggered when an attribute
3821 is changed. For example see: sdebug_add_host_store() above.
3822 */
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003823
Akinobu Mita82069372013-10-14 22:48:04 +09003824static struct attribute *sdebug_drv_attrs[] = {
3825 &driver_attr_delay.attr,
3826 &driver_attr_opts.attr,
3827 &driver_attr_ptype.attr,
3828 &driver_attr_dsense.attr,
3829 &driver_attr_fake_rw.attr,
3830 &driver_attr_no_lun_0.attr,
3831 &driver_attr_num_tgts.attr,
3832 &driver_attr_dev_size_mb.attr,
3833 &driver_attr_num_parts.attr,
3834 &driver_attr_every_nth.attr,
3835 &driver_attr_max_luns.attr,
3836 &driver_attr_max_queue.attr,
3837 &driver_attr_no_uld.attr,
3838 &driver_attr_scsi_level.attr,
3839 &driver_attr_virtual_gb.attr,
3840 &driver_attr_add_host.attr,
3841 &driver_attr_vpd_use_hostno.attr,
3842 &driver_attr_sector_size.attr,
3843 &driver_attr_dix.attr,
3844 &driver_attr_dif.attr,
3845 &driver_attr_guard.attr,
3846 &driver_attr_ato.attr,
3847 &driver_attr_map.attr,
3848 &driver_attr_removable.attr,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003849 &driver_attr_host_lock.attr,
3850 &driver_attr_ndelay.attr,
Akinobu Mita82069372013-10-14 22:48:04 +09003851 NULL,
3852};
3853ATTRIBUTE_GROUPS(sdebug_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854
Akinobu Mita11ddcec2014-02-26 22:56:59 +09003855static struct device *pseudo_primary;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003856
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857static int __init scsi_debug_init(void)
3858{
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003859 unsigned long sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 int host_to_add;
3861 int k;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003862 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003864 atomic_set(&sdebug_cmnd_count, 0);
3865 atomic_set(&sdebug_completions, 0);
3866 atomic_set(&retired_max_queue, 0);
3867
3868 if (scsi_debug_ndelay >= 1000000000) {
3869 pr_warn("%s: ndelay must be less than 1 second, ignored\n",
3870 __func__);
3871 scsi_debug_ndelay = 0;
3872 } else if (scsi_debug_ndelay > 0)
3873 scsi_debug_delay = DELAY_OVERRIDDEN;
3874
Martin K. Petersen597136a2008-06-05 00:12:59 -04003875 switch (scsi_debug_sector_size) {
3876 case 512:
3877 case 1024:
3878 case 2048:
3879 case 4096:
3880 break;
3881 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003882 pr_err("%s: invalid sector_size %d\n", __func__,
Martin K. Petersen597136a2008-06-05 00:12:59 -04003883 scsi_debug_sector_size);
3884 return -EINVAL;
3885 }
3886
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003887 switch (scsi_debug_dif) {
3888
3889 case SD_DIF_TYPE0_PROTECTION:
3890 case SD_DIF_TYPE1_PROTECTION:
Martin K. Petersen395cef02009-09-18 17:33:03 -04003891 case SD_DIF_TYPE2_PROTECTION:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003892 case SD_DIF_TYPE3_PROTECTION:
3893 break;
3894
3895 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003896 pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003897 return -EINVAL;
3898 }
3899
3900 if (scsi_debug_guard > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003901 pr_err("%s: guard must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003902 return -EINVAL;
3903 }
3904
3905 if (scsi_debug_ato > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003906 pr_err("%s: ato must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003907 return -EINVAL;
3908 }
3909
Martin K. Petersenea61fca2009-05-15 00:40:33 -04003910 if (scsi_debug_physblk_exp > 15) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003911 pr_err("%s: invalid physblk_exp %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04003912 scsi_debug_physblk_exp);
3913 return -EINVAL;
3914 }
3915
3916 if (scsi_debug_lowest_aligned > 0x3fff) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003917 pr_err("%s: lowest_aligned too big: %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04003918 scsi_debug_lowest_aligned);
3919 return -EINVAL;
3920 }
3921
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 if (scsi_debug_dev_size_mb < 1)
3923 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003924 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
Martin K. Petersen597136a2008-06-05 00:12:59 -04003925 sdebug_store_sectors = sz / scsi_debug_sector_size;
FUJITA Tomonori28898872008-03-30 00:59:55 +09003926 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927
3928 /* play around with geometry, don't waste too much on track 0 */
3929 sdebug_heads = 8;
3930 sdebug_sectors_per = 32;
3931 if (scsi_debug_dev_size_mb >= 16)
3932 sdebug_heads = 32;
3933 else if (scsi_debug_dev_size_mb >= 256)
3934 sdebug_heads = 64;
3935 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
3936 (sdebug_sectors_per * sdebug_heads);
3937 if (sdebug_cylinders_per >= 1024) {
3938 /* other LLDs do this; implies >= 1GB ram disk ... */
3939 sdebug_heads = 255;
3940 sdebug_sectors_per = 63;
3941 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
3942 (sdebug_sectors_per * sdebug_heads);
3943 }
3944
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003945 if (0 == scsi_debug_fake_rw) {
3946 fake_storep = vmalloc(sz);
3947 if (NULL == fake_storep) {
3948 pr_err("%s: out of memory, 1\n", __func__);
3949 return -ENOMEM;
3950 }
3951 memset(fake_storep, 0, sz);
3952 if (scsi_debug_num_parts > 0)
3953 sdebug_build_parts(fake_storep, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955
Akinobu Mita7cb69d02013-06-29 17:59:16 +09003956 if (scsi_debug_dix) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003957 int dif_size;
3958
3959 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
3960 dif_storep = vmalloc(dif_size);
3961
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003962 pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size,
3963 dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003964
3965 if (dif_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003966 pr_err("%s: out of mem. (DIX)\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003967 ret = -ENOMEM;
3968 goto free_vm;
3969 }
3970
3971 memset(dif_storep, 0xff, dif_size);
3972 }
3973
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003974 /* Logical Block Provisioning */
3975 if (scsi_debug_lbp()) {
Martin K. Petersen60147592010-08-19 11:49:00 -04003976 scsi_debug_unmap_max_blocks =
3977 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
3978
3979 scsi_debug_unmap_max_desc =
3980 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
3981
3982 scsi_debug_unmap_granularity =
3983 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
3984
3985 if (scsi_debug_unmap_alignment &&
Akinobu Mitaac170782013-04-16 22:11:56 +09003986 scsi_debug_unmap_granularity <=
3987 scsi_debug_unmap_alignment) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003988 pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n",
Martin K. Petersen44d92692009-10-15 14:45:27 -04003989 __func__);
3990 return -EINVAL;
3991 }
3992
Akinobu Mitab90ebc32013-04-16 22:11:58 +09003993 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
3994 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
Martin K. Petersen44d92692009-10-15 14:45:27 -04003995
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003996 pr_info("%s: %lu provisioning blocks\n", __func__, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003997
3998 if (map_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003999 pr_err("%s: out of mem. (MAP)\n", __func__);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004000 ret = -ENOMEM;
4001 goto free_vm;
4002 }
4003
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004004 bitmap_zero(map_storep, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004005
4006 /* Map first 1KB for partition table */
4007 if (scsi_debug_num_parts)
4008 map_region(0, 2);
4009 }
4010
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004011 pseudo_primary = root_device_register("pseudo_0");
4012 if (IS_ERR(pseudo_primary)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004013 pr_warn("%s: root_device_register() error\n", __func__);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004014 ret = PTR_ERR(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004015 goto free_vm;
4016 }
4017 ret = bus_register(&pseudo_lld_bus);
4018 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004019 pr_warn("%s: bus_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004020 goto dev_unreg;
4021 }
4022 ret = driver_register(&sdebug_driverfs_driver);
4023 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004024 pr_warn("%s: driver_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004025 goto bus_unreg;
4026 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 host_to_add = scsi_debug_add_host;
4029 scsi_debug_add_host = 0;
4030
4031 for (k = 0; k < host_to_add; k++) {
4032 if (sdebug_add_adapter()) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004033 pr_err("%s: sdebug_add_adapter failed k=%d\n",
4034 __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 break;
4036 }
4037 }
4038
4039 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004040 pr_info("%s: built %d host(s)\n", __func__,
4041 scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 }
4043 return 0;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004044
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004045bus_unreg:
4046 bus_unregister(&pseudo_lld_bus);
4047dev_unreg:
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004048 root_device_unregister(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004049free_vm:
Martin K. Petersen44d92692009-10-15 14:45:27 -04004050 if (map_storep)
4051 vfree(map_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004052 if (dif_storep)
4053 vfree(dif_storep);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004054 vfree(fake_storep);
4055
4056 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057}
4058
4059static void __exit scsi_debug_exit(void)
4060{
4061 int k = scsi_debug_add_host;
4062
4063 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004064 free_all_queued();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 for (; k; k--)
4066 sdebug_remove_adapter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 driver_unregister(&sdebug_driverfs_driver);
4068 bus_unregister(&pseudo_lld_bus);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004069 root_device_unregister(pseudo_primary);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004071 if (dif_storep)
4072 vfree(dif_storep);
4073
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 vfree(fake_storep);
4075}
4076
4077device_initcall(scsi_debug_init);
4078module_exit(scsi_debug_exit);
4079
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080static void sdebug_release_adapter(struct device * dev)
4081{
4082 struct sdebug_host_info *sdbg_host;
4083
4084 sdbg_host = to_sdebug_host(dev);
4085 kfree(sdbg_host);
4086}
4087
4088static int sdebug_add_adapter(void)
4089{
4090 int k, devs_per_host;
4091 int error = 0;
4092 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004093 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004095 sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 if (NULL == sdbg_host) {
4097 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004098 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 return -ENOMEM;
4100 }
4101
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 INIT_LIST_HEAD(&sdbg_host->dev_info_list);
4103
4104 devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
4105 for (k = 0; k < devs_per_host; k++) {
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09004106 sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
4107 if (!sdbg_devinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004109 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 error = -ENOMEM;
4111 goto clean;
4112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 }
4114
4115 spin_lock(&sdebug_host_list_lock);
4116 list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
4117 spin_unlock(&sdebug_host_list_lock);
4118
4119 sdbg_host->dev.bus = &pseudo_lld_bus;
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004120 sdbg_host->dev.parent = pseudo_primary;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 sdbg_host->dev.release = &sdebug_release_adapter;
Kay Sievers71610f52008-12-03 22:41:36 +01004122 dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
4124 error = device_register(&sdbg_host->dev);
4125
4126 if (error)
4127 goto clean;
4128
4129 ++scsi_debug_add_host;
4130 return error;
4131
4132clean:
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004133 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
4134 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 list_del(&sdbg_devinfo->dev_list);
4136 kfree(sdbg_devinfo);
4137 }
4138
4139 kfree(sdbg_host);
4140 return error;
4141}
4142
4143static void sdebug_remove_adapter(void)
4144{
4145 struct sdebug_host_info * sdbg_host = NULL;
4146
4147 spin_lock(&sdebug_host_list_lock);
4148 if (!list_empty(&sdebug_host_list)) {
4149 sdbg_host = list_entry(sdebug_host_list.prev,
4150 struct sdebug_host_info, host_list);
4151 list_del(&sdbg_host->host_list);
4152 }
4153 spin_unlock(&sdebug_host_list_lock);
4154
4155 if (!sdbg_host)
4156 return;
4157
4158 device_unregister(&sdbg_host->dev);
4159 --scsi_debug_add_host;
4160}
4161
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004162static int
4163scsi_debug_queuecommand(struct scsi_cmnd *SCpnt)
FUJITA Tomonori639db472008-03-20 11:09:19 +09004164{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02004165 unsigned char *cmd = SCpnt->cmnd;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004166 int len, k;
4167 unsigned int num;
4168 unsigned long long lba;
Martin K. Petersen395cef02009-09-18 17:33:03 -04004169 u32 ei_lba;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004170 int errsts = 0;
4171 int target = SCpnt->device->id;
4172 struct sdebug_dev_info *devip = NULL;
4173 int inj_recovered = 0;
4174 int inj_transport = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004175 int inj_dif = 0;
4176 int inj_dix = 0;
Christoph Hellwigb57d7c02014-05-01 16:51:51 +02004177 int inj_short = 0;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004178 int delay_override = 0;
Martin K. Petersen44d92692009-10-15 14:45:27 -04004179 int unmap = 0;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004180
4181 scsi_set_resid(SCpnt, 0);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004182 if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) &&
Douglas Gilbert01123ef2014-08-05 12:20:02 +02004183 !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004184 char b[120];
4185 int n;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004186
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004187 len = SCpnt->cmd_len;
4188 if (len > 32)
4189 strcpy(b, "too long, over 32 bytes");
4190 else {
4191 for (k = 0, n = 0; k < len; ++k)
4192 n += scnprintf(b + n, sizeof(b) - n, "%02x ",
4193 (unsigned int)cmd[k]);
4194 }
4195 sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name,
4196 b);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004197 }
4198
4199 if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
4200 (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004201 return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004202 devip = devInfoReg(SCpnt->device);
4203 if (NULL == devip)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004204 return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004205
4206 if ((scsi_debug_every_nth != 0) &&
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004207 (atomic_inc_return(&sdebug_cmnd_count) >=
4208 abs(scsi_debug_every_nth))) {
4209 atomic_set(&sdebug_cmnd_count, 0);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004210 if (scsi_debug_every_nth < -1)
4211 scsi_debug_every_nth = -1;
4212 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
4213 return 0; /* ignore command causing timeout */
Martin K. Petersen18a4d0a2012-02-09 13:48:53 -05004214 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
4215 scsi_medium_access_command(SCpnt))
4216 return 0; /* time out reads and writes */
FUJITA Tomonori639db472008-03-20 11:09:19 +09004217 else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
4218 inj_recovered = 1; /* to reads and writes below */
4219 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
4220 inj_transport = 1; /* to reads and writes below */
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004221 else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts)
4222 inj_dif = 1; /* to reads and writes below */
4223 else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts)
4224 inj_dix = 1; /* to reads and writes below */
Christoph Hellwigb57d7c02014-05-01 16:51:51 +02004225 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & scsi_debug_opts)
4226 inj_short = 1;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004227 }
4228
4229 if (devip->wlun) {
4230 switch (*cmd) {
4231 case INQUIRY:
4232 case REQUEST_SENSE:
4233 case TEST_UNIT_READY:
4234 case REPORT_LUNS:
4235 break; /* only allowable wlun commands */
4236 default:
4237 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
4238 printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
4239 "not supported for wlun\n", *cmd);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004240 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004241 INVALID_OPCODE, 0);
4242 errsts = check_condition_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004243 return schedule_resp(SCpnt, devip, errsts, 0);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004244 }
4245 }
4246
4247 switch (*cmd) {
4248 case INQUIRY: /* mandatory, ignore unit attention */
4249 delay_override = 1;
4250 errsts = resp_inquiry(SCpnt, target, devip);
4251 break;
4252 case REQUEST_SENSE: /* mandatory, ignore unit attention */
4253 delay_override = 1;
4254 errsts = resp_requests(SCpnt, devip);
4255 break;
4256 case REZERO_UNIT: /* actually this is REWIND for SSC */
4257 case START_STOP:
4258 errsts = resp_start_stop(SCpnt, devip);
4259 break;
4260 case ALLOW_MEDIUM_REMOVAL:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004261 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004262 if (errsts)
4263 break;
4264 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
4265 printk(KERN_INFO "scsi_debug: Medium removal %s\n",
4266 cmd[4] ? "inhibited" : "enabled");
4267 break;
4268 case SEND_DIAGNOSTIC: /* mandatory */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004269 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004270 break;
4271 case TEST_UNIT_READY: /* mandatory */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004272 /* delay_override = 1; */
4273 errsts = check_readiness(SCpnt, UAS_TUR, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004274 break;
4275 case RESERVE:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004276 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004277 break;
4278 case RESERVE_10:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004279 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004280 break;
4281 case RELEASE:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004282 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004283 break;
4284 case RELEASE_10:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004285 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004286 break;
4287 case READ_CAPACITY:
4288 errsts = resp_readcap(SCpnt, devip);
4289 break;
4290 case SERVICE_ACTION_IN:
Martin K. Petersen44d92692009-10-15 14:45:27 -04004291 if (cmd[1] == SAI_READ_CAPACITY_16)
4292 errsts = resp_readcap16(SCpnt, devip);
4293 else if (cmd[1] == SAI_GET_LBA_STATUS) {
4294
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004295 if (scsi_debug_lbp() == 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004296 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
Martin K. Petersen44d92692009-10-15 14:45:27 -04004297 INVALID_COMMAND_OPCODE, 0);
4298 errsts = check_condition_result;
4299 } else
4300 errsts = resp_get_lba_status(SCpnt, devip);
4301 } else {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004302 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004303 INVALID_OPCODE, 0);
4304 errsts = check_condition_result;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004305 }
FUJITA Tomonori639db472008-03-20 11:09:19 +09004306 break;
4307 case MAINTENANCE_IN:
4308 if (MI_REPORT_TARGET_PGS != cmd[1]) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004309 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004310 INVALID_OPCODE, 0);
4311 errsts = check_condition_result;
4312 break;
4313 }
4314 errsts = resp_report_tgtpgs(SCpnt, devip);
4315 break;
4316 case READ_16:
4317 case READ_12:
4318 case READ_10:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004319 /* READ{10,12,16} and DIF Type 2 are natural enemies */
4320 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
4321 cmd[1] & 0xe0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004322 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
Martin K. Petersen395cef02009-09-18 17:33:03 -04004323 INVALID_COMMAND_OPCODE, 0);
4324 errsts = check_condition_result;
4325 break;
4326 }
4327
4328 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
4329 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
4330 (cmd[1] & 0xe0) == 0)
4331 printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
4332
4333 /* fall through */
FUJITA Tomonori639db472008-03-20 11:09:19 +09004334 case READ_6:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004335read:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004336 errsts = check_readiness(SCpnt, UAS_TUR, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004337 if (errsts)
4338 break;
4339 if (scsi_debug_fake_rw)
4340 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04004341 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
Christoph Hellwigb57d7c02014-05-01 16:51:51 +02004342
4343 if (inj_short)
4344 num /= 2;
4345
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004346 errsts = resp_read(SCpnt, lba, num, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004347 if (inj_recovered && (0 == errsts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004348 mk_sense_buffer(SCpnt, RECOVERED_ERROR,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004349 THRESHOLD_EXCEEDED, 0);
4350 errsts = check_condition_result;
4351 } else if (inj_transport && (0 == errsts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004352 mk_sense_buffer(SCpnt, ABORTED_COMMAND,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004353 TRANSPORT_PROBLEM, ACK_NAK_TO);
4354 errsts = check_condition_result;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004355 } else if (inj_dif && (0 == errsts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004356 /* Logical block guard check failed */
4357 mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004358 errsts = illegal_condition_result;
4359 } else if (inj_dix && (0 == errsts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004360 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004361 errsts = illegal_condition_result;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004362 }
4363 break;
4364 case REPORT_LUNS: /* mandatory, ignore unit attention */
4365 delay_override = 1;
4366 errsts = resp_report_luns(SCpnt, devip);
4367 break;
4368 case VERIFY: /* 10 byte SBC-2 command */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004369 errsts = check_readiness(SCpnt, UAS_TUR, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004370 break;
4371 case WRITE_16:
4372 case WRITE_12:
4373 case WRITE_10:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004374 /* WRITE{10,12,16} and DIF Type 2 are natural enemies */
4375 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
4376 cmd[1] & 0xe0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004377 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
Martin K. Petersen395cef02009-09-18 17:33:03 -04004378 INVALID_COMMAND_OPCODE, 0);
4379 errsts = check_condition_result;
4380 break;
4381 }
4382
4383 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
4384 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
4385 (cmd[1] & 0xe0) == 0)
4386 printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
4387
4388 /* fall through */
FUJITA Tomonori639db472008-03-20 11:09:19 +09004389 case WRITE_6:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004390write:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004391 errsts = check_readiness(SCpnt, UAS_TUR, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004392 if (errsts)
4393 break;
4394 if (scsi_debug_fake_rw)
4395 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04004396 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004397 errsts = resp_write(SCpnt, lba, num, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004398 if (inj_recovered && (0 == errsts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004399 mk_sense_buffer(SCpnt, RECOVERED_ERROR,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004400 THRESHOLD_EXCEEDED, 0);
4401 errsts = check_condition_result;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004402 } else if (inj_dif && (0 == errsts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004403 mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004404 errsts = illegal_condition_result;
4405 } else if (inj_dix && (0 == errsts)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004406 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004407 errsts = illegal_condition_result;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004408 }
4409 break;
Martin K. Petersen44d92692009-10-15 14:45:27 -04004410 case WRITE_SAME_16:
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004411 case WRITE_SAME:
Martin K. Petersen60147592010-08-19 11:49:00 -04004412 if (cmd[1] & 0x8) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004413 if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) ||
4414 (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004415 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
Martin K. Petersen60147592010-08-19 11:49:00 -04004416 INVALID_FIELD_IN_CDB, 0);
4417 errsts = check_condition_result;
4418 } else
4419 unmap = 1;
4420 }
4421 if (errsts)
4422 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004423 errsts = check_readiness(SCpnt, UAS_TUR, devip);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004424 if (errsts)
4425 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004426 if (scsi_debug_fake_rw)
4427 break;
Martin K. Petersen44d92692009-10-15 14:45:27 -04004428 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004429 errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004430 break;
4431 case UNMAP:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004432 errsts = check_readiness(SCpnt, UAS_TUR, devip);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004433 if (errsts)
4434 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004435 if (scsi_debug_fake_rw)
4436 break;
Martin K. Petersen44d92692009-10-15 14:45:27 -04004437
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004438 if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004439 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
Martin K. Petersen44d92692009-10-15 14:45:27 -04004440 INVALID_COMMAND_OPCODE, 0);
4441 errsts = check_condition_result;
4442 } else
4443 errsts = resp_unmap(SCpnt, devip);
4444 break;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004445 case MODE_SENSE:
4446 case MODE_SENSE_10:
4447 errsts = resp_mode_sense(SCpnt, target, devip);
4448 break;
4449 case MODE_SELECT:
4450 errsts = resp_mode_select(SCpnt, 1, devip);
4451 break;
4452 case MODE_SELECT_10:
4453 errsts = resp_mode_select(SCpnt, 0, devip);
4454 break;
4455 case LOG_SENSE:
4456 errsts = resp_log_sense(SCpnt, devip);
4457 break;
4458 case SYNCHRONIZE_CACHE:
4459 delay_override = 1;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004460 errsts = check_readiness(SCpnt, UAS_TUR, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004461 break;
4462 case WRITE_BUFFER:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004463 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004464 break;
4465 case XDWRITEREAD_10:
4466 if (!scsi_bidi_cmnd(SCpnt)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004467 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004468 INVALID_FIELD_IN_CDB, 0);
4469 errsts = check_condition_result;
4470 break;
4471 }
4472
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004473 errsts = check_readiness(SCpnt, UAS_TUR, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004474 if (errsts)
4475 break;
4476 if (scsi_debug_fake_rw)
4477 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04004478 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004479 errsts = resp_read(SCpnt, lba, num, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004480 if (errsts)
4481 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004482 errsts = resp_write(SCpnt, lba, num, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004483 if (errsts)
4484 break;
4485 errsts = resp_xdwriteread(SCpnt, lba, num, devip);
4486 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04004487 case VARIABLE_LENGTH_CMD:
4488 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) {
4489
4490 if ((cmd[10] & 0xe0) == 0)
4491 printk(KERN_ERR
4492 "Unprotected RD/WR to DIF device\n");
4493
4494 if (cmd[9] == READ_32) {
4495 BUG_ON(SCpnt->cmd_len < 32);
4496 goto read;
4497 }
4498
4499 if (cmd[9] == WRITE_32) {
4500 BUG_ON(SCpnt->cmd_len < 32);
4501 goto write;
4502 }
4503 }
4504
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004505 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
Martin K. Petersen395cef02009-09-18 17:33:03 -04004506 INVALID_FIELD_IN_CDB, 0);
4507 errsts = check_condition_result;
4508 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004509 case 0x85:
4510 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
4511 sdev_printk(KERN_INFO, SCpnt->device,
4512 "%s: ATA PASS-THROUGH(16) not supported\n", my_name);
4513 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
4514 INVALID_OPCODE, 0);
4515 errsts = check_condition_result;
4516 break;
FUJITA Tomonori639db472008-03-20 11:09:19 +09004517 default:
4518 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004519 sdev_printk(KERN_INFO, SCpnt->device,
4520 "%s: Opcode: 0x%x not supported\n",
4521 my_name, *cmd);
4522 errsts = check_readiness(SCpnt, UAS_ONLY, devip);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004523 if (errsts)
4524 break; /* Unit attention takes precedence */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004525 mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
FUJITA Tomonori639db472008-03-20 11:09:19 +09004526 errsts = check_condition_result;
4527 break;
4528 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004529 return schedule_resp(SCpnt, devip, errsts,
FUJITA Tomonori639db472008-03-20 11:09:19 +09004530 (delay_override ? 0 : scsi_debug_delay));
4531}
4532
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004533static int
4534sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
4535{
4536 if (scsi_debug_host_lock) {
4537 unsigned long iflags;
4538 int rc;
4539
4540 spin_lock_irqsave(shost->host_lock, iflags);
4541 rc = scsi_debug_queuecommand(cmd);
4542 spin_unlock_irqrestore(shost->host_lock, iflags);
4543 return rc;
4544 } else
4545 return scsi_debug_queuecommand(cmd);
4546}
4547
4548static int
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01004549sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004550{
4551 int num_in_q = 0;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004552 unsigned long iflags;
4553 struct sdebug_dev_info *devip;
4554
4555 spin_lock_irqsave(&queued_arr_lock, iflags);
4556 devip = (struct sdebug_dev_info *)sdev->hostdata;
4557 if (NULL == devip) {
4558 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4559 return -ENODEV;
4560 }
4561 num_in_q = atomic_read(&devip->num_in_q);
4562 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004563
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01004564 if (qdepth < 1)
4565 qdepth = 1;
4566 /* allow to exceed max host queued_arr elements for testing */
4567 if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
4568 qdepth = SCSI_DEBUG_CANQUEUE + 10;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01004569 scsi_change_queue_depth(sdev, qdepth);
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01004570
4571 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
4572 sdev_printk(KERN_INFO, sdev,
4573 "%s: qdepth=%d, num_in_q=%d\n",
4574 __func__, qdepth, num_in_q);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004575 }
4576 return sdev->queue_depth;
4577}
4578
4579static int
4580sdebug_change_qtype(struct scsi_device *sdev, int qtype)
4581{
Christoph Hellwiga62182f2014-10-02 14:39:55 +02004582 qtype = scsi_change_queue_type(sdev, qtype);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004583 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
4584 const char *cp;
4585
4586 switch (qtype) {
4587 case 0:
4588 cp = "untagged";
4589 break;
4590 case MSG_SIMPLE_TAG:
4591 cp = "simple tags";
4592 break;
4593 case MSG_ORDERED_TAG:
4594 cp = "ordered tags";
4595 break;
4596 default:
4597 cp = "unknown";
4598 break;
4599 }
4600 sdev_printk(KERN_INFO, sdev, "%s: to %s\n", __func__, cp);
4601 }
4602 return qtype;
4603}
Jeff Garzikf2812332010-11-16 02:10:29 -05004604
Douglas Gilbert817fd662014-11-24 20:18:02 -05004605static int
4606check_inject(struct scsi_cmnd *scp)
4607{
4608 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
4609
4610 memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
4611
4612 if (atomic_inc_return(&sdebug_cmnd_count) >=
4613 abs(scsi_debug_every_nth)) {
4614 atomic_set(&sdebug_cmnd_count, 0);
4615 if (scsi_debug_every_nth < -1)
4616 scsi_debug_every_nth = -1;
4617 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
4618 return 1; /* ignore command causing timeout */
4619 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
4620 scsi_medium_access_command(scp))
4621 return 1; /* time out reads and writes */
4622 if (sdebug_any_injecting_opt) {
4623 int opts = scsi_debug_opts;
4624
4625 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
4626 ep->inj_recovered = true;
4627 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
4628 ep->inj_transport = true;
4629 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
4630 ep->inj_dif = true;
4631 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
4632 ep->inj_dix = true;
4633 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
4634 ep->inj_short = true;
4635 }
4636 }
4637 return 0;
4638}
4639
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004640static struct scsi_host_template sdebug_driver_template = {
Al Viroc8ed5552013-03-31 01:46:06 -04004641 .show_info = scsi_debug_show_info,
4642 .write_info = scsi_debug_write_info,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004643 .proc_name = sdebug_proc_name,
4644 .name = "SCSI DEBUG",
4645 .info = scsi_debug_info,
4646 .slave_alloc = scsi_debug_slave_alloc,
4647 .slave_configure = scsi_debug_slave_configure,
4648 .slave_destroy = scsi_debug_slave_destroy,
4649 .ioctl = scsi_debug_ioctl,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004650 .queuecommand = sdebug_queuecommand_lock_or_not,
4651 .change_queue_depth = sdebug_change_qdepth,
4652 .change_queue_type = sdebug_change_qtype,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004653 .eh_abort_handler = scsi_debug_abort,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004654 .eh_device_reset_handler = scsi_debug_device_reset,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004655 .eh_target_reset_handler = scsi_debug_target_reset,
4656 .eh_bus_reset_handler = scsi_debug_bus_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004657 .eh_host_reset_handler = scsi_debug_host_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004658 .can_queue = SCSI_DEBUG_CANQUEUE,
4659 .this_id = 7,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09004660 .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004661 .cmd_per_lun = DEF_CMD_PER_LUN,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09004662 .max_sectors = -1U,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004663 .use_clustering = DISABLE_CLUSTERING,
4664 .module = THIS_MODULE,
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01004665 .track_queue_depth = 1,
Douglas Gilbert817fd662014-11-24 20:18:02 -05004666 .cmd_size = sizeof(struct sdebug_scmd_extra_t),
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09004667};
4668
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669static int sdebug_driver_probe(struct device * dev)
4670{
Douglas Gilbert22017ed2014-11-24 23:04:47 -05004671 int error = 0;
Douglas Gilbert817fd662014-11-24 20:18:02 -05004672 int opts;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05004673 struct sdebug_host_info *sdbg_host;
4674 struct Scsi_Host *hpnt;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004675 int host_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676
4677 sdbg_host = to_sdebug_host(dev);
4678
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004679 sdebug_driver_template.can_queue = scsi_debug_max_queue;
Akinobu Mita0759c662014-02-26 22:57:04 +09004680 if (scsi_debug_clustering)
4681 sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004682 hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
4683 if (NULL == hpnt) {
Finn Thain17c9ff52014-10-03 11:43:31 +10004684 pr_err("%s: scsi_host_alloc failed\n", __func__);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004685 error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686 return error;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004687 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688
4689 sdbg_host->shost = hpnt;
4690 *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
4691 if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
4692 hpnt->max_id = scsi_debug_num_tgts + 1;
4693 else
4694 hpnt->max_id = scsi_debug_num_tgts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004695 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004697 host_prot = 0;
4698
4699 switch (scsi_debug_dif) {
4700
4701 case SD_DIF_TYPE1_PROTECTION:
4702 host_prot = SHOST_DIF_TYPE1_PROTECTION;
4703 if (scsi_debug_dix)
4704 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
4705 break;
4706
4707 case SD_DIF_TYPE2_PROTECTION:
4708 host_prot = SHOST_DIF_TYPE2_PROTECTION;
4709 if (scsi_debug_dix)
4710 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
4711 break;
4712
4713 case SD_DIF_TYPE3_PROTECTION:
4714 host_prot = SHOST_DIF_TYPE3_PROTECTION;
4715 if (scsi_debug_dix)
4716 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
4717 break;
4718
4719 default:
4720 if (scsi_debug_dix)
4721 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
4722 break;
4723 }
4724
4725 scsi_host_set_prot(hpnt, host_prot);
4726
4727 printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n",
4728 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
4729 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
4730 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
4731 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
4732 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
4733 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
4734 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
4735
4736 if (scsi_debug_guard == 1)
4737 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
4738 else
4739 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
4740
Douglas Gilbert817fd662014-11-24 20:18:02 -05004741 opts = scsi_debug_opts;
4742 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
4743 sdebug_any_injecting_opt = true;
4744 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
4745 sdebug_any_injecting_opt = true;
4746 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
4747 sdebug_any_injecting_opt = true;
4748 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
4749 sdebug_any_injecting_opt = true;
4750 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
4751 sdebug_any_injecting_opt = true;
4752
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753 error = scsi_add_host(hpnt, &sdbg_host->dev);
4754 if (error) {
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004755 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756 error = -ENODEV;
4757 scsi_host_put(hpnt);
4758 } else
4759 scsi_scan_host(hpnt);
4760
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004761 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762}
4763
4764static int sdebug_driver_remove(struct device * dev)
4765{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004767 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768
4769 sdbg_host = to_sdebug_host(dev);
4770
4771 if (!sdbg_host) {
4772 printk(KERN_ERR "%s: Unable to locate host info\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004773 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774 return -ENODEV;
4775 }
4776
4777 scsi_remove_host(sdbg_host->shost);
4778
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004779 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
4780 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781 list_del(&sdbg_devinfo->dev_list);
4782 kfree(sdbg_devinfo);
4783 }
4784
4785 scsi_host_put(sdbg_host->shost);
4786 return 0;
4787}
4788
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004789static int pseudo_lld_bus_match(struct device *dev,
4790 struct device_driver *dev_driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004791{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004792 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793}
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004794
4795static struct bus_type pseudo_lld_bus = {
4796 .name = "pseudo",
4797 .match = pseudo_lld_bus_match,
4798 .probe = sdebug_driver_probe,
4799 .remove = sdebug_driver_remove,
Akinobu Mita82069372013-10-14 22:48:04 +09004800 .drv_groups = sdebug_drv_groups,
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004801};