11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 31da177e4SLinus Torvalds * Copyright (C) 1992 Eric Youngdale 41da177e4SLinus Torvalds * Simulate a host adapter with 2 disks attached. Do a lot of checking 51da177e4SLinus Torvalds * to make sure that we are not getting blocks mixed up, and PANIC if 61da177e4SLinus Torvalds * anything out of the ordinary is seen. 71da177e4SLinus Torvalds * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * This version is more generic, simulating a variable number of disk 1023183910SDouglas Gilbert * (or disk like devices) sharing a common amount of RAM. To be more 1123183910SDouglas Gilbert * realistic, the simulated devices have the transport attributes of 1223183910SDouglas Gilbert * SAS disks. 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * 1578d4e5a0SDouglas Gilbert * For documentation see http://sg.danny.cz/sg/sdebug26.html 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * D. Gilbert (dpg) work for Magneto-Optical device test [20010421] 181da177e4SLinus Torvalds * dpg: work for devfs large number of disks [20010809] 191da177e4SLinus Torvalds * forked for lk 2.5 series [20011216, 20020101] 201da177e4SLinus Torvalds * use vmalloc() more inquiry+mode_sense [20020302] 211da177e4SLinus Torvalds * add timers for delayed responses [20020721] 221da177e4SLinus Torvalds * Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031] 231da177e4SLinus Torvalds * Mike Anderson <andmike@us.ibm.com> sysfs work [20021118] 241da177e4SLinus Torvalds * dpg: change style of boot options to "scsi_debug.num_tgts=2" and 251da177e4SLinus Torvalds * module options to "modprobe scsi_debug num_tgts=2" [20021221] 261da177e4SLinus Torvalds */ 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <linux/module.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include <linux/kernel.h> 311da177e4SLinus Torvalds #include <linux/errno.h> 321da177e4SLinus Torvalds #include <linux/timer.h> 335a0e3ad6STejun Heo #include <linux/slab.h> 341da177e4SLinus Torvalds #include <linux/types.h> 351da177e4SLinus Torvalds #include <linux/string.h> 361da177e4SLinus Torvalds #include <linux/genhd.h> 371da177e4SLinus Torvalds #include <linux/fs.h> 381da177e4SLinus Torvalds #include <linux/init.h> 391da177e4SLinus Torvalds #include <linux/proc_fs.h> 401da177e4SLinus Torvalds #include <linux/vmalloc.h> 411da177e4SLinus Torvalds #include <linux/moduleparam.h> 42852e034dSJens Axboe #include <linux/scatterlist.h> 431da177e4SLinus Torvalds #include <linux/blkdev.h> 44c6a44287SMartin K. Petersen #include <linux/crc-t10dif.h> 45cbf67842SDouglas Gilbert #include <linux/spinlock.h> 46cbf67842SDouglas Gilbert #include <linux/interrupt.h> 47cbf67842SDouglas Gilbert #include <linux/atomic.h> 48cbf67842SDouglas Gilbert #include <linux/hrtimer.h> 49c6a44287SMartin K. Petersen 50c6a44287SMartin K. Petersen #include <net/checksum.h> 519ff26eefSFUJITA Tomonori 5244d92694SMartin K. Petersen #include <asm/unaligned.h> 5344d92694SMartin K. Petersen 549ff26eefSFUJITA Tomonori #include <scsi/scsi.h> 559ff26eefSFUJITA Tomonori #include <scsi/scsi_cmnd.h> 569ff26eefSFUJITA Tomonori #include <scsi/scsi_device.h> 571da177e4SLinus Torvalds #include <scsi/scsi_host.h> 581da177e4SLinus Torvalds #include <scsi/scsicam.h> 59a34c4e98SFUJITA Tomonori #include <scsi/scsi_eh.h> 60cbf67842SDouglas Gilbert #include <scsi/scsi_tcq.h> 61395cef03SMartin K. Petersen #include <scsi/scsi_dbg.h> 621da177e4SLinus Torvalds 63c6a44287SMartin K. Petersen #include "sd.h" 641da177e4SLinus Torvalds #include "scsi_logging.h" 651da177e4SLinus Torvalds 66cbf67842SDouglas Gilbert #define SCSI_DEBUG_VERSION "1.84" 67cbf67842SDouglas Gilbert static const char *scsi_debug_version_date = "20140706"; 68cbf67842SDouglas Gilbert 69cbf67842SDouglas Gilbert #define MY_NAME "scsi_debug" 701da177e4SLinus Torvalds 716f3cbf55SDouglas Gilbert /* Additional Sense Code (ASC) */ 72c65b1445SDouglas Gilbert #define NO_ADDITIONAL_SENSE 0x0 73c65b1445SDouglas Gilbert #define LOGICAL_UNIT_NOT_READY 0x4 74c5af0db9SAkinobu Mita #define LOGICAL_UNIT_COMMUNICATION_FAILURE 0x8 751da177e4SLinus Torvalds #define UNRECOVERED_READ_ERR 0x11 76c65b1445SDouglas Gilbert #define PARAMETER_LIST_LENGTH_ERR 0x1a 771da177e4SLinus Torvalds #define INVALID_OPCODE 0x20 781da177e4SLinus Torvalds #define ADDR_OUT_OF_RANGE 0x21 79395cef03SMartin K. Petersen #define INVALID_COMMAND_OPCODE 0x20 801da177e4SLinus Torvalds #define INVALID_FIELD_IN_CDB 0x24 81c65b1445SDouglas Gilbert #define INVALID_FIELD_IN_PARAM_LIST 0x26 82cbf67842SDouglas Gilbert #define UA_RESET_ASC 0x29 83cbf67842SDouglas Gilbert #define UA_CHANGED_ASC 0x2a 84cbf67842SDouglas Gilbert #define POWER_ON_RESET_ASCQ 0x0 85cbf67842SDouglas Gilbert #define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */ 86cbf67842SDouglas Gilbert #define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */ 871da177e4SLinus Torvalds #define SAVING_PARAMS_UNSUP 0x39 886f3cbf55SDouglas Gilbert #define TRANSPORT_PROBLEM 0x4b 89c65b1445SDouglas Gilbert #define THRESHOLD_EXCEEDED 0x5d 90c65b1445SDouglas Gilbert #define LOW_POWER_COND_ON 0x5e 911da177e4SLinus Torvalds 926f3cbf55SDouglas Gilbert /* Additional Sense Code Qualifier (ASCQ) */ 936f3cbf55SDouglas Gilbert #define ACK_NAK_TO 0x3 946f3cbf55SDouglas Gilbert 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /* Default values for driver parameters */ 971da177e4SLinus Torvalds #define DEF_NUM_HOST 1 981da177e4SLinus Torvalds #define DEF_NUM_TGTS 1 991da177e4SLinus Torvalds #define DEF_MAX_LUNS 1 1001da177e4SLinus Torvalds /* With these defaults, this driver will make 1 host with 1 target 1011da177e4SLinus Torvalds * (id 0) containing 1 logical unit (lun 0). That is 1 device. 1021da177e4SLinus Torvalds */ 1035b94e232SMartin K. Petersen #define DEF_ATO 1 104cbf67842SDouglas Gilbert #define DEF_DELAY 1 /* if > 0 unit is a jiffy */ 1051da177e4SLinus Torvalds #define DEF_DEV_SIZE_MB 8 1065b94e232SMartin K. Petersen #define DEF_DIF 0 1075b94e232SMartin K. Petersen #define DEF_DIX 0 1085b94e232SMartin K. Petersen #define DEF_D_SENSE 0 1091da177e4SLinus Torvalds #define DEF_EVERY_NTH 0 1105b94e232SMartin K. Petersen #define DEF_FAKE_RW 0 1115b94e232SMartin K. Petersen #define DEF_GUARD 0 112cbf67842SDouglas Gilbert #define DEF_HOST_LOCK 0 1135b94e232SMartin K. Petersen #define DEF_LBPU 0 1145b94e232SMartin K. Petersen #define DEF_LBPWS 0 1155b94e232SMartin K. Petersen #define DEF_LBPWS10 0 116be1dd78dSEric Sandeen #define DEF_LBPRZ 1 1175b94e232SMartin K. Petersen #define DEF_LOWEST_ALIGNED 0 118cbf67842SDouglas Gilbert #define DEF_NDELAY 0 /* if > 0 unit is a nanosecond */ 1195b94e232SMartin K. Petersen #define DEF_NO_LUN_0 0 1201da177e4SLinus Torvalds #define DEF_NUM_PARTS 0 1211da177e4SLinus Torvalds #define DEF_OPTS 0 122e308b3d1SMartin K. Petersen #define DEF_OPT_BLKS 64 1235b94e232SMartin K. Petersen #define DEF_PHYSBLK_EXP 0 1245b94e232SMartin K. Petersen #define DEF_PTYPE 0 125d986788bSMartin Pitt #define DEF_REMOVABLE false 126e46b0344SDouglas Gilbert #define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */ 1275b94e232SMartin K. Petersen #define DEF_SECTOR_SIZE 512 128cbf67842SDouglas Gilbert #define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ 1295b94e232SMartin K. Petersen #define DEF_UNMAP_ALIGNMENT 0 1305b94e232SMartin K. Petersen #define DEF_UNMAP_GRANULARITY 1 1316014759cSMartin K. Petersen #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF 1326014759cSMartin K. Petersen #define DEF_UNMAP_MAX_DESC 256 1335b94e232SMartin K. Petersen #define DEF_VIRTUAL_GB 0 1345b94e232SMartin K. Petersen #define DEF_VPD_USE_HOSTNO 1 1355b94e232SMartin K. Petersen #define DEF_WRITESAME_LENGTH 0xFFFF 136cbf67842SDouglas Gilbert #define DELAY_OVERRIDDEN -9999 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds /* bit mask values for scsi_debug_opts */ 1391da177e4SLinus Torvalds #define SCSI_DEBUG_OPT_NOISE 1 1401da177e4SLinus Torvalds #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 1411da177e4SLinus Torvalds #define SCSI_DEBUG_OPT_TIMEOUT 4 1421da177e4SLinus Torvalds #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 1436f3cbf55SDouglas Gilbert #define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 144c6a44287SMartin K. Petersen #define SCSI_DEBUG_OPT_DIF_ERR 32 145c6a44287SMartin K. Petersen #define SCSI_DEBUG_OPT_DIX_ERR 64 14618a4d0a2SMartin K. Petersen #define SCSI_DEBUG_OPT_MAC_TIMEOUT 128 147cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100 148cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_Q_NOISE 0x200 149cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_ALL_TSF 0x400 150cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_RARE_TSF 0x800 151cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_N_WCE 0x1000 152cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_RESET_NOISE 0x2000 153cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000 154cbf67842SDouglas Gilbert #define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000) 1551da177e4SLinus Torvalds /* When "every_nth" > 0 then modulo "every_nth" commands: 1561da177e4SLinus Torvalds * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set 1571da177e4SLinus Torvalds * - a RECOVERED_ERROR is simulated on successful read and write 1581da177e4SLinus Torvalds * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. 1596f3cbf55SDouglas Gilbert * - a TRANSPORT_ERROR is simulated on successful read and write 1606f3cbf55SDouglas Gilbert * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. 1611da177e4SLinus Torvalds * 1621da177e4SLinus Torvalds * When "every_nth" < 0 then after "- every_nth" commands: 1631da177e4SLinus Torvalds * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set 1641da177e4SLinus Torvalds * - a RECOVERED_ERROR is simulated on successful read and write 1651da177e4SLinus Torvalds * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. 1666f3cbf55SDouglas Gilbert * - a TRANSPORT_ERROR is simulated on successful read and write 1676f3cbf55SDouglas Gilbert * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. 1681da177e4SLinus Torvalds * This will continue until some other action occurs (e.g. the user 1691da177e4SLinus Torvalds * writing a new value (other than -1 or 1) to every_nth via sysfs). 1701da177e4SLinus Torvalds */ 1711da177e4SLinus Torvalds 172cbf67842SDouglas Gilbert /* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in 173cbf67842SDouglas Gilbert * priority order. In the subset implemented here lower numbers have higher 174cbf67842SDouglas Gilbert * priority. The UA numbers should be a sequence starting from 0 with 175cbf67842SDouglas Gilbert * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */ 176cbf67842SDouglas Gilbert #define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */ 177cbf67842SDouglas Gilbert #define SDEBUG_UA_BUS_RESET 1 178cbf67842SDouglas Gilbert #define SDEBUG_UA_MODE_CHANGED 2 179cbf67842SDouglas Gilbert #define SDEBUG_NUM_UAS 3 180cbf67842SDouglas Gilbert 181cbf67842SDouglas Gilbert /* for check_readiness() */ 182cbf67842SDouglas Gilbert #define UAS_ONLY 1 183cbf67842SDouglas Gilbert #define UAS_TUR 0 184cbf67842SDouglas Gilbert 1851da177e4SLinus Torvalds /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this 1861da177e4SLinus Torvalds * sector on read commands: */ 1871da177e4SLinus Torvalds #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ 18832f7ef73SDouglas Gilbert #define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */ 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1) 1911da177e4SLinus Torvalds * or "peripheral device" addressing (value 0) */ 1921da177e4SLinus Torvalds #define SAM2_LUN_ADDRESS_METHOD 0 193c65b1445SDouglas Gilbert #define SAM2_WLUN_REPORT_LUNS 0xc101 1941da177e4SLinus Torvalds 195cbf67842SDouglas Gilbert /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued 196cbf67842SDouglas Gilbert * (for response) at one time. Can be reduced by max_queue option. Command 197cbf67842SDouglas Gilbert * responses are not queued when delay=0 and ndelay=0. The per-device 198cbf67842SDouglas Gilbert * DEF_CMD_PER_LUN can be changed via sysfs: 199cbf67842SDouglas Gilbert * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed 200cbf67842SDouglas Gilbert * SCSI_DEBUG_CANQUEUE. */ 201cbf67842SDouglas Gilbert #define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */ 202cbf67842SDouglas Gilbert #define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG) 203cbf67842SDouglas Gilbert #define DEF_CMD_PER_LUN 255 204cbf67842SDouglas Gilbert 205cbf67842SDouglas Gilbert #if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE 206cbf67842SDouglas Gilbert #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" 207cbf67842SDouglas Gilbert #endif 20878d4e5a0SDouglas Gilbert 2091da177e4SLinus Torvalds static int scsi_debug_add_host = DEF_NUM_HOST; 2105b94e232SMartin K. Petersen static int scsi_debug_ato = DEF_ATO; 2111da177e4SLinus Torvalds static int scsi_debug_delay = DEF_DELAY; 2121da177e4SLinus Torvalds static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; 2135b94e232SMartin K. Petersen static int scsi_debug_dif = DEF_DIF; 2145b94e232SMartin K. Petersen static int scsi_debug_dix = DEF_DIX; 2155b94e232SMartin K. Petersen static int scsi_debug_dsense = DEF_D_SENSE; 2161da177e4SLinus Torvalds static int scsi_debug_every_nth = DEF_EVERY_NTH; 2175b94e232SMartin K. Petersen static int scsi_debug_fake_rw = DEF_FAKE_RW; 21868aee7baSAkinobu Mita static unsigned int scsi_debug_guard = DEF_GUARD; 2195b94e232SMartin K. Petersen static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; 2201da177e4SLinus Torvalds static int scsi_debug_max_luns = DEF_MAX_LUNS; 22178d4e5a0SDouglas Gilbert static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; 222cbf67842SDouglas Gilbert static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ 223cbf67842SDouglas Gilbert static int scsi_debug_ndelay = DEF_NDELAY; 224c65b1445SDouglas Gilbert static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; 2255b94e232SMartin K. Petersen static int scsi_debug_no_uld = 0; 2265b94e232SMartin K. Petersen static int scsi_debug_num_parts = DEF_NUM_PARTS; 2275b94e232SMartin K. Petersen static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */ 228e308b3d1SMartin K. Petersen static int scsi_debug_opt_blks = DEF_OPT_BLKS; 2295b94e232SMartin K. Petersen static int scsi_debug_opts = DEF_OPTS; 2305b94e232SMartin K. Petersen static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP; 2315b94e232SMartin K. Petersen static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */ 2325b94e232SMartin K. Petersen static int scsi_debug_scsi_level = DEF_SCSI_LEVEL; 2335b94e232SMartin K. Petersen static int scsi_debug_sector_size = DEF_SECTOR_SIZE; 2345b94e232SMartin K. Petersen static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; 2355b94e232SMartin K. Petersen static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; 2365b94e232SMartin K. Petersen static unsigned int scsi_debug_lbpu = DEF_LBPU; 2375b94e232SMartin K. Petersen static unsigned int scsi_debug_lbpws = DEF_LBPWS; 2385b94e232SMartin K. Petersen static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10; 239be1dd78dSEric Sandeen static unsigned int scsi_debug_lbprz = DEF_LBPRZ; 2406014759cSMartin K. Petersen static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT; 2415b94e232SMartin K. Petersen static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY; 2425b94e232SMartin K. Petersen static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS; 2435b94e232SMartin K. Petersen static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC; 2445b94e232SMartin K. Petersen static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; 245d986788bSMartin Pitt static bool scsi_debug_removable = DEF_REMOVABLE; 2460759c666SAkinobu Mita static bool scsi_debug_clustering; 247cbf67842SDouglas Gilbert static bool scsi_debug_host_lock = DEF_HOST_LOCK; 2481da177e4SLinus Torvalds 249cbf67842SDouglas Gilbert static atomic_t sdebug_cmnd_count; 250cbf67842SDouglas Gilbert static atomic_t sdebug_completions; 251cbf67842SDouglas Gilbert static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */ 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds #define DEV_READONLY(TGT) (0) 2541da177e4SLinus Torvalds 255c65b1445SDouglas Gilbert static unsigned int sdebug_store_sectors; 2561da177e4SLinus Torvalds static sector_t sdebug_capacity; /* in sectors */ 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds /* old BIOS stuff, kernel may get rid of them but some mode sense pages 2591da177e4SLinus Torvalds may still need them */ 2601da177e4SLinus Torvalds static int sdebug_heads; /* heads per disk */ 2611da177e4SLinus Torvalds static int sdebug_cylinders_per; /* cylinders per surface */ 2621da177e4SLinus Torvalds static int sdebug_sectors_per; /* sectors per cylinder */ 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds #define SDEBUG_MAX_PARTS 4 2651da177e4SLinus Torvalds 266395cef03SMartin K. Petersen #define SCSI_DEBUG_MAX_CMD_LEN 32 2679e603ca0SFUJITA Tomonori 2685b94e232SMartin K. Petersen static unsigned int scsi_debug_lbp(void) 2695b94e232SMartin K. Petersen { 270cbf67842SDouglas Gilbert return ((0 == scsi_debug_fake_rw) && 271cbf67842SDouglas Gilbert (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10)); 2725b94e232SMartin K. Petersen } 2735b94e232SMartin K. Petersen 2741da177e4SLinus Torvalds struct sdebug_dev_info { 2751da177e4SLinus Torvalds struct list_head dev_list; 2761da177e4SLinus Torvalds unsigned int channel; 2771da177e4SLinus Torvalds unsigned int target; 2789cb78c16SHannes Reinecke u64 lun; 2791da177e4SLinus Torvalds struct sdebug_host_info *sdbg_host; 2809cb78c16SHannes Reinecke u64 wlun; 281cbf67842SDouglas Gilbert unsigned long uas_bm[1]; 282cbf67842SDouglas Gilbert atomic_t num_in_q; 283c65b1445SDouglas Gilbert char stopped; 2841da177e4SLinus Torvalds char used; 2851da177e4SLinus Torvalds }; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds struct sdebug_host_info { 2881da177e4SLinus Torvalds struct list_head host_list; 2891da177e4SLinus Torvalds struct Scsi_Host *shost; 2901da177e4SLinus Torvalds struct device dev; 2911da177e4SLinus Torvalds struct list_head dev_info_list; 2921da177e4SLinus Torvalds }; 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds #define to_sdebug_host(d) \ 2951da177e4SLinus Torvalds container_of(d, struct sdebug_host_info, dev) 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds static LIST_HEAD(sdebug_host_list); 2981da177e4SLinus Torvalds static DEFINE_SPINLOCK(sdebug_host_list_lock); 2991da177e4SLinus Torvalds 300cbf67842SDouglas Gilbert 301cbf67842SDouglas Gilbert struct sdebug_hrtimer { /* ... is derived from hrtimer */ 302cbf67842SDouglas Gilbert struct hrtimer hrt; /* must be first element */ 303cbf67842SDouglas Gilbert int qa_indx; 304cbf67842SDouglas Gilbert }; 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds struct sdebug_queued_cmd { 307cbf67842SDouglas Gilbert /* in_use flagged by a bit in queued_in_use_bm[] */ 308cbf67842SDouglas Gilbert struct timer_list *cmnd_timerp; 309cbf67842SDouglas Gilbert struct tasklet_struct *tletp; 310cbf67842SDouglas Gilbert struct sdebug_hrtimer *sd_hrtp; 3111da177e4SLinus Torvalds struct scsi_cmnd * a_cmnd; 3121da177e4SLinus Torvalds }; 3131da177e4SLinus Torvalds static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; 314cbf67842SDouglas Gilbert static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS]; 315cbf67842SDouglas Gilbert 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds static unsigned char * fake_storep; /* ramdisk storage */ 318e18d8beaSAkinobu Mita static struct sd_dif_tuple *dif_storep; /* protection info */ 31944d92694SMartin K. Petersen static void *map_storep; /* provisioning map */ 3201da177e4SLinus Torvalds 32144d92694SMartin K. Petersen static unsigned long map_size; 322cbf67842SDouglas Gilbert static int num_aborts; 323cbf67842SDouglas Gilbert static int num_dev_resets; 324cbf67842SDouglas Gilbert static int num_target_resets; 325cbf67842SDouglas Gilbert static int num_bus_resets; 326cbf67842SDouglas Gilbert static int num_host_resets; 327c6a44287SMartin K. Petersen static int dix_writes; 328c6a44287SMartin K. Petersen static int dix_reads; 329c6a44287SMartin K. Petersen static int dif_errors; 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds static DEFINE_SPINLOCK(queued_arr_lock); 3321da177e4SLinus Torvalds static DEFINE_RWLOCK(atomic_rw); 3331da177e4SLinus Torvalds 334cbf67842SDouglas Gilbert static char sdebug_proc_name[] = MY_NAME; 335cbf67842SDouglas Gilbert static const char *my_name = MY_NAME; 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds static struct bus_type pseudo_lld_bus; 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds static struct device_driver sdebug_driverfs_driver = { 3401da177e4SLinus Torvalds .name = sdebug_proc_name, 3411da177e4SLinus Torvalds .bus = &pseudo_lld_bus, 3421da177e4SLinus Torvalds }; 3431da177e4SLinus Torvalds 3441da177e4SLinus Torvalds static const int check_condition_result = 3451da177e4SLinus Torvalds (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 3461da177e4SLinus Torvalds 347c6a44287SMartin K. Petersen static const int illegal_condition_result = 348c6a44287SMartin K. Petersen (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION; 349c6a44287SMartin K. Petersen 350cbf67842SDouglas Gilbert static const int device_qfull_result = 351cbf67842SDouglas Gilbert (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; 352cbf67842SDouglas Gilbert 353cbf67842SDouglas Gilbert static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 354cbf67842SDouglas Gilbert 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 355cbf67842SDouglas Gilbert 0, 0, 0, 0}; 356c65b1445SDouglas Gilbert static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 357c65b1445SDouglas Gilbert 0, 0, 0x2, 0x4b}; 358c65b1445SDouglas Gilbert static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 359c65b1445SDouglas Gilbert 0, 0, 0x0, 0x0}; 360c65b1445SDouglas Gilbert 36114faa944SAkinobu Mita static void *fake_store(unsigned long long lba) 36214faa944SAkinobu Mita { 36314faa944SAkinobu Mita lba = do_div(lba, sdebug_store_sectors); 36414faa944SAkinobu Mita 36514faa944SAkinobu Mita return fake_storep + lba * scsi_debug_sector_size; 36614faa944SAkinobu Mita } 36714faa944SAkinobu Mita 36814faa944SAkinobu Mita static struct sd_dif_tuple *dif_store(sector_t sector) 36914faa944SAkinobu Mita { 37014faa944SAkinobu Mita sector = do_div(sector, sdebug_store_sectors); 37114faa944SAkinobu Mita 37214faa944SAkinobu Mita return dif_storep + sector; 37314faa944SAkinobu Mita } 37414faa944SAkinobu Mita 3751da177e4SLinus Torvalds static int sdebug_add_adapter(void); 3761da177e4SLinus Torvalds static void sdebug_remove_adapter(void); 3771da177e4SLinus Torvalds 3788dea0d02SFUJITA Tomonori static void sdebug_max_tgts_luns(void) 3798dea0d02SFUJITA Tomonori { 3808dea0d02SFUJITA Tomonori struct sdebug_host_info *sdbg_host; 3818dea0d02SFUJITA Tomonori struct Scsi_Host *hpnt; 3828dea0d02SFUJITA Tomonori 3838dea0d02SFUJITA Tomonori spin_lock(&sdebug_host_list_lock); 3848dea0d02SFUJITA Tomonori list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { 3858dea0d02SFUJITA Tomonori hpnt = sdbg_host->shost; 3868dea0d02SFUJITA Tomonori if ((hpnt->this_id >= 0) && 3878dea0d02SFUJITA Tomonori (scsi_debug_num_tgts > hpnt->this_id)) 3888dea0d02SFUJITA Tomonori hpnt->max_id = scsi_debug_num_tgts + 1; 3898dea0d02SFUJITA Tomonori else 3908dea0d02SFUJITA Tomonori hpnt->max_id = scsi_debug_num_tgts; 3918dea0d02SFUJITA Tomonori /* scsi_debug_max_luns; */ 3928dea0d02SFUJITA Tomonori hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; 3938dea0d02SFUJITA Tomonori } 3948dea0d02SFUJITA Tomonori spin_unlock(&sdebug_host_list_lock); 3958dea0d02SFUJITA Tomonori } 3968dea0d02SFUJITA Tomonori 397cbf67842SDouglas Gilbert static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) 3988dea0d02SFUJITA Tomonori { 3998dea0d02SFUJITA Tomonori unsigned char *sbuff; 4008dea0d02SFUJITA Tomonori 401cbf67842SDouglas Gilbert sbuff = scp->sense_buffer; 402cbf67842SDouglas Gilbert if (!sbuff) { 403cbf67842SDouglas Gilbert sdev_printk(KERN_ERR, scp->device, 404cbf67842SDouglas Gilbert "%s: sense_buffer is NULL\n", __func__); 405cbf67842SDouglas Gilbert return; 406cbf67842SDouglas Gilbert } 407cbf67842SDouglas Gilbert memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE); 4088dea0d02SFUJITA Tomonori 4098dea0d02SFUJITA Tomonori scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); 4108dea0d02SFUJITA Tomonori 4118dea0d02SFUJITA Tomonori if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 412cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, scp->device, 413cbf67842SDouglas Gilbert "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n", 414cbf67842SDouglas Gilbert my_name, key, asc, asq); 4158dea0d02SFUJITA Tomonori } 4161da177e4SLinus Torvalds 4173de9f944SFUJITA Tomonori static void get_data_transfer_info(unsigned char *cmd, 418395cef03SMartin K. Petersen unsigned long long *lba, unsigned int *num, 419395cef03SMartin K. Petersen u32 *ei_lba) 4203de9f944SFUJITA Tomonori { 421395cef03SMartin K. Petersen *ei_lba = 0; 422395cef03SMartin K. Petersen 4233de9f944SFUJITA Tomonori switch (*cmd) { 424395cef03SMartin K. Petersen case VARIABLE_LENGTH_CMD: 425395cef03SMartin K. Petersen *lba = (u64)cmd[19] | (u64)cmd[18] << 8 | 426395cef03SMartin K. Petersen (u64)cmd[17] << 16 | (u64)cmd[16] << 24 | 427395cef03SMartin K. Petersen (u64)cmd[15] << 32 | (u64)cmd[14] << 40 | 428395cef03SMartin K. Petersen (u64)cmd[13] << 48 | (u64)cmd[12] << 56; 429395cef03SMartin K. Petersen 430395cef03SMartin K. Petersen *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 | 431395cef03SMartin K. Petersen (u32)cmd[21] << 16 | (u32)cmd[20] << 24; 432395cef03SMartin K. Petersen 433395cef03SMartin K. Petersen *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 | 434395cef03SMartin K. Petersen (u32)cmd[28] << 24; 435395cef03SMartin K. Petersen break; 436395cef03SMartin K. Petersen 43744d92694SMartin K. Petersen case WRITE_SAME_16: 4383de9f944SFUJITA Tomonori case WRITE_16: 4393de9f944SFUJITA Tomonori case READ_16: 440d5cdc989SFUJITA Tomonori *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | 441d5cdc989SFUJITA Tomonori (u64)cmd[7] << 16 | (u64)cmd[6] << 24 | 442d5cdc989SFUJITA Tomonori (u64)cmd[5] << 32 | (u64)cmd[4] << 40 | 443d5cdc989SFUJITA Tomonori (u64)cmd[3] << 48 | (u64)cmd[2] << 56; 444d5cdc989SFUJITA Tomonori 445d5cdc989SFUJITA Tomonori *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 | 446d5cdc989SFUJITA Tomonori (u32)cmd[10] << 24; 4473de9f944SFUJITA Tomonori break; 4483de9f944SFUJITA Tomonori case WRITE_12: 4493de9f944SFUJITA Tomonori case READ_12: 450d5cdc989SFUJITA Tomonori *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | 451d5cdc989SFUJITA Tomonori (u32)cmd[2] << 24; 452d5cdc989SFUJITA Tomonori 453d5cdc989SFUJITA Tomonori *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 | 454d5cdc989SFUJITA Tomonori (u32)cmd[6] << 24; 4553de9f944SFUJITA Tomonori break; 45644d92694SMartin K. Petersen case WRITE_SAME: 4573de9f944SFUJITA Tomonori case WRITE_10: 4583de9f944SFUJITA Tomonori case READ_10: 459c639d14eSFUJITA Tomonori case XDWRITEREAD_10: 460d5cdc989SFUJITA Tomonori *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | 461d5cdc989SFUJITA Tomonori (u32)cmd[2] << 24; 462d5cdc989SFUJITA Tomonori 463d5cdc989SFUJITA Tomonori *num = (u32)cmd[8] | (u32)cmd[7] << 8; 4643de9f944SFUJITA Tomonori break; 4653de9f944SFUJITA Tomonori case WRITE_6: 4663de9f944SFUJITA Tomonori case READ_6: 467d5cdc989SFUJITA Tomonori *lba = (u32)cmd[3] | (u32)cmd[2] << 8 | 468d5cdc989SFUJITA Tomonori (u32)(cmd[1] & 0x1f) << 16; 4693de9f944SFUJITA Tomonori *num = (0 == cmd[4]) ? 256 : cmd[4]; 4703de9f944SFUJITA Tomonori break; 4713de9f944SFUJITA Tomonori default: 4723de9f944SFUJITA Tomonori break; 4733de9f944SFUJITA Tomonori } 4743de9f944SFUJITA Tomonori } 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) 4771da177e4SLinus Torvalds { 4781da177e4SLinus Torvalds if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { 479cbf67842SDouglas Gilbert if (0x1261 == cmd) 480cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, dev, 481cbf67842SDouglas Gilbert "%s: BLKFLSBUF [0x1261]\n", __func__); 482cbf67842SDouglas Gilbert else if (0x5331 == cmd) 483cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, dev, 484cbf67842SDouglas Gilbert "%s: CDROM_GET_CAPABILITY [0x5331]\n", 485cbf67842SDouglas Gilbert __func__); 486cbf67842SDouglas Gilbert else 487cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n", 488cbf67842SDouglas Gilbert __func__, cmd); 4891da177e4SLinus Torvalds } 4901da177e4SLinus Torvalds return -EINVAL; 4911da177e4SLinus Torvalds /* return -ENOTTY; // correct return but upsets fdisk */ 4921da177e4SLinus Torvalds } 4931da177e4SLinus Torvalds 494cbf67842SDouglas Gilbert static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, 495c65b1445SDouglas Gilbert struct sdebug_dev_info * devip) 4961da177e4SLinus Torvalds { 497cbf67842SDouglas Gilbert int k; 498cbf67842SDouglas Gilbert bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts); 499cbf67842SDouglas Gilbert 500cbf67842SDouglas Gilbert k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS); 501cbf67842SDouglas Gilbert if (k != SDEBUG_NUM_UAS) { 502cbf67842SDouglas Gilbert const char *cp = NULL; 503cbf67842SDouglas Gilbert 504cbf67842SDouglas Gilbert switch (k) { 505cbf67842SDouglas Gilbert case SDEBUG_UA_POR: 506cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, UNIT_ATTENTION, 507cbf67842SDouglas Gilbert UA_RESET_ASC, POWER_ON_RESET_ASCQ); 508cbf67842SDouglas Gilbert if (debug) 509cbf67842SDouglas Gilbert cp = "power on reset"; 510cbf67842SDouglas Gilbert break; 511cbf67842SDouglas Gilbert case SDEBUG_UA_BUS_RESET: 512cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, UNIT_ATTENTION, 513cbf67842SDouglas Gilbert UA_RESET_ASC, BUS_RESET_ASCQ); 514cbf67842SDouglas Gilbert if (debug) 515cbf67842SDouglas Gilbert cp = "bus reset"; 516cbf67842SDouglas Gilbert break; 517cbf67842SDouglas Gilbert case SDEBUG_UA_MODE_CHANGED: 518cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, UNIT_ATTENTION, 519cbf67842SDouglas Gilbert UA_CHANGED_ASC, MODE_CHANGED_ASCQ); 520cbf67842SDouglas Gilbert if (debug) 521cbf67842SDouglas Gilbert cp = "mode parameters changed"; 522cbf67842SDouglas Gilbert break; 523cbf67842SDouglas Gilbert default: 524cbf67842SDouglas Gilbert pr_warn("%s: unexpected unit attention code=%d\n", 525cbf67842SDouglas Gilbert __func__, k); 526cbf67842SDouglas Gilbert if (debug) 527cbf67842SDouglas Gilbert cp = "unknown"; 528cbf67842SDouglas Gilbert break; 529cbf67842SDouglas Gilbert } 530cbf67842SDouglas Gilbert clear_bit(k, devip->uas_bm); 531cbf67842SDouglas Gilbert if (debug) 532cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, 533cbf67842SDouglas Gilbert "%s reports: Unit attention: %s\n", 534cbf67842SDouglas Gilbert my_name, cp); 5351da177e4SLinus Torvalds return check_condition_result; 5361da177e4SLinus Torvalds } 537cbf67842SDouglas Gilbert if ((UAS_TUR == uas_only) && devip->stopped) { 538cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY, 539c65b1445SDouglas Gilbert 0x2); 540cbf67842SDouglas Gilbert if (debug) 541cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, 542cbf67842SDouglas Gilbert "%s reports: Not ready: %s\n", my_name, 543cbf67842SDouglas Gilbert "initializing command required"); 544c65b1445SDouglas Gilbert return check_condition_result; 545c65b1445SDouglas Gilbert } 5461da177e4SLinus Torvalds return 0; 5471da177e4SLinus Torvalds } 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds /* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */ 5501da177e4SLinus Torvalds static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, 5511da177e4SLinus Torvalds int arr_len) 5521da177e4SLinus Torvalds { 55321a61829SFUJITA Tomonori int act_len; 554072d0bb3SFUJITA Tomonori struct scsi_data_buffer *sdb = scsi_in(scp); 5551da177e4SLinus Torvalds 556072d0bb3SFUJITA Tomonori if (!sdb->length) 5571da177e4SLinus Torvalds return 0; 558072d0bb3SFUJITA Tomonori if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) 5591da177e4SLinus Torvalds return (DID_ERROR << 16); 56021a61829SFUJITA Tomonori 56121a61829SFUJITA Tomonori act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, 56221a61829SFUJITA Tomonori arr, arr_len); 56321a61829SFUJITA Tomonori sdb->resid = scsi_bufflen(scp) - act_len; 56421a61829SFUJITA Tomonori 5651da177e4SLinus Torvalds return 0; 5661da177e4SLinus Torvalds } 5671da177e4SLinus Torvalds 5681da177e4SLinus Torvalds /* Returns number of bytes fetched into 'arr' or -1 if error. */ 5691da177e4SLinus Torvalds static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, 57021a61829SFUJITA Tomonori int arr_len) 5711da177e4SLinus Torvalds { 57221a61829SFUJITA Tomonori if (!scsi_bufflen(scp)) 5731da177e4SLinus Torvalds return 0; 574072d0bb3SFUJITA Tomonori if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE)) 5751da177e4SLinus Torvalds return -1; 57621a61829SFUJITA Tomonori 57721a61829SFUJITA Tomonori return scsi_sg_copy_to_buffer(scp, arr, arr_len); 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds static const char * inq_vendor_id = "Linux "; 5821da177e4SLinus Torvalds static const char * inq_product_id = "scsi_debug "; 583cbf67842SDouglas Gilbert static const char *inq_product_rev = "0184"; /* version less '.' */ 5841da177e4SLinus Torvalds 585cbf67842SDouglas Gilbert /* Device identification VPD page. Returns number of bytes placed in arr */ 5865a09e398SHannes Reinecke static int inquiry_evpd_83(unsigned char * arr, int port_group_id, 5875a09e398SHannes Reinecke int target_dev_id, int dev_id_num, 5885a09e398SHannes Reinecke const char * dev_id_str, 589c65b1445SDouglas Gilbert int dev_id_str_len) 5901da177e4SLinus Torvalds { 591c65b1445SDouglas Gilbert int num, port_a; 592c65b1445SDouglas Gilbert char b[32]; 5931da177e4SLinus Torvalds 594c65b1445SDouglas Gilbert port_a = target_dev_id + 1; 5951da177e4SLinus Torvalds /* T10 vendor identifier field format (faked) */ 5961da177e4SLinus Torvalds arr[0] = 0x2; /* ASCII */ 5971da177e4SLinus Torvalds arr[1] = 0x1; 5981da177e4SLinus Torvalds arr[2] = 0x0; 5991da177e4SLinus Torvalds memcpy(&arr[4], inq_vendor_id, 8); 6001da177e4SLinus Torvalds memcpy(&arr[12], inq_product_id, 16); 6011da177e4SLinus Torvalds memcpy(&arr[28], dev_id_str, dev_id_str_len); 6021da177e4SLinus Torvalds num = 8 + 16 + dev_id_str_len; 6031da177e4SLinus Torvalds arr[3] = num; 6041da177e4SLinus Torvalds num += 4; 605c65b1445SDouglas Gilbert if (dev_id_num >= 0) { 606c65b1445SDouglas Gilbert /* NAA-5, Logical unit identifier (binary) */ 607c65b1445SDouglas Gilbert arr[num++] = 0x1; /* binary (not necessarily sas) */ 608c65b1445SDouglas Gilbert arr[num++] = 0x3; /* PIV=0, lu, naa */ 609c65b1445SDouglas Gilbert arr[num++] = 0x0; 610c65b1445SDouglas Gilbert arr[num++] = 0x8; 611c65b1445SDouglas Gilbert arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */ 612c65b1445SDouglas Gilbert arr[num++] = 0x33; 613c65b1445SDouglas Gilbert arr[num++] = 0x33; 614c65b1445SDouglas Gilbert arr[num++] = 0x30; 615c65b1445SDouglas Gilbert arr[num++] = (dev_id_num >> 24); 616c65b1445SDouglas Gilbert arr[num++] = (dev_id_num >> 16) & 0xff; 617c65b1445SDouglas Gilbert arr[num++] = (dev_id_num >> 8) & 0xff; 618c65b1445SDouglas Gilbert arr[num++] = dev_id_num & 0xff; 619c65b1445SDouglas Gilbert /* Target relative port number */ 620c65b1445SDouglas Gilbert arr[num++] = 0x61; /* proto=sas, binary */ 621c65b1445SDouglas Gilbert arr[num++] = 0x94; /* PIV=1, target port, rel port */ 622c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 623c65b1445SDouglas Gilbert arr[num++] = 0x4; /* length */ 624c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 625c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 626c65b1445SDouglas Gilbert arr[num++] = 0x0; 627c65b1445SDouglas Gilbert arr[num++] = 0x1; /* relative port A */ 628c65b1445SDouglas Gilbert } 629c65b1445SDouglas Gilbert /* NAA-5, Target port identifier */ 630c65b1445SDouglas Gilbert arr[num++] = 0x61; /* proto=sas, binary */ 631c65b1445SDouglas Gilbert arr[num++] = 0x93; /* piv=1, target port, naa */ 632c65b1445SDouglas Gilbert arr[num++] = 0x0; 633c65b1445SDouglas Gilbert arr[num++] = 0x8; 634c65b1445SDouglas Gilbert arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */ 635c65b1445SDouglas Gilbert arr[num++] = 0x22; 636c65b1445SDouglas Gilbert arr[num++] = 0x22; 637c65b1445SDouglas Gilbert arr[num++] = 0x20; 638c65b1445SDouglas Gilbert arr[num++] = (port_a >> 24); 639c65b1445SDouglas Gilbert arr[num++] = (port_a >> 16) & 0xff; 640c65b1445SDouglas Gilbert arr[num++] = (port_a >> 8) & 0xff; 641c65b1445SDouglas Gilbert arr[num++] = port_a & 0xff; 6425a09e398SHannes Reinecke /* NAA-5, Target port group identifier */ 6435a09e398SHannes Reinecke arr[num++] = 0x61; /* proto=sas, binary */ 6445a09e398SHannes Reinecke arr[num++] = 0x95; /* piv=1, target port group id */ 6455a09e398SHannes Reinecke arr[num++] = 0x0; 6465a09e398SHannes Reinecke arr[num++] = 0x4; 6475a09e398SHannes Reinecke arr[num++] = 0; 6485a09e398SHannes Reinecke arr[num++] = 0; 6495a09e398SHannes Reinecke arr[num++] = (port_group_id >> 8) & 0xff; 6505a09e398SHannes Reinecke arr[num++] = port_group_id & 0xff; 651c65b1445SDouglas Gilbert /* NAA-5, Target device identifier */ 652c65b1445SDouglas Gilbert arr[num++] = 0x61; /* proto=sas, binary */ 653c65b1445SDouglas Gilbert arr[num++] = 0xa3; /* piv=1, target device, naa */ 654c65b1445SDouglas Gilbert arr[num++] = 0x0; 655c65b1445SDouglas Gilbert arr[num++] = 0x8; 656c65b1445SDouglas Gilbert arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */ 657c65b1445SDouglas Gilbert arr[num++] = 0x22; 658c65b1445SDouglas Gilbert arr[num++] = 0x22; 659c65b1445SDouglas Gilbert arr[num++] = 0x20; 660c65b1445SDouglas Gilbert arr[num++] = (target_dev_id >> 24); 661c65b1445SDouglas Gilbert arr[num++] = (target_dev_id >> 16) & 0xff; 662c65b1445SDouglas Gilbert arr[num++] = (target_dev_id >> 8) & 0xff; 663c65b1445SDouglas Gilbert arr[num++] = target_dev_id & 0xff; 664c65b1445SDouglas Gilbert /* SCSI name string: Target device identifier */ 665c65b1445SDouglas Gilbert arr[num++] = 0x63; /* proto=sas, UTF-8 */ 666c65b1445SDouglas Gilbert arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */ 667c65b1445SDouglas Gilbert arr[num++] = 0x0; 668c65b1445SDouglas Gilbert arr[num++] = 24; 669c65b1445SDouglas Gilbert memcpy(arr + num, "naa.52222220", 12); 670c65b1445SDouglas Gilbert num += 12; 671c65b1445SDouglas Gilbert snprintf(b, sizeof(b), "%08X", target_dev_id); 672c65b1445SDouglas Gilbert memcpy(arr + num, b, 8); 673c65b1445SDouglas Gilbert num += 8; 674c65b1445SDouglas Gilbert memset(arr + num, 0, 4); 675c65b1445SDouglas Gilbert num += 4; 676c65b1445SDouglas Gilbert return num; 677c65b1445SDouglas Gilbert } 678c65b1445SDouglas Gilbert 679c65b1445SDouglas Gilbert 680c65b1445SDouglas Gilbert static unsigned char vpd84_data[] = { 681c65b1445SDouglas Gilbert /* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0, 682c65b1445SDouglas Gilbert 0x22,0x22,0x22,0x0,0xbb,0x1, 683c65b1445SDouglas Gilbert 0x22,0x22,0x22,0x0,0xbb,0x2, 684c65b1445SDouglas Gilbert }; 685c65b1445SDouglas Gilbert 686cbf67842SDouglas Gilbert /* Software interface identification VPD page */ 687c65b1445SDouglas Gilbert static int inquiry_evpd_84(unsigned char * arr) 688c65b1445SDouglas Gilbert { 689c65b1445SDouglas Gilbert memcpy(arr, vpd84_data, sizeof(vpd84_data)); 690c65b1445SDouglas Gilbert return sizeof(vpd84_data); 691c65b1445SDouglas Gilbert } 692c65b1445SDouglas Gilbert 693cbf67842SDouglas Gilbert /* Management network addresses VPD page */ 694c65b1445SDouglas Gilbert static int inquiry_evpd_85(unsigned char * arr) 695c65b1445SDouglas Gilbert { 696c65b1445SDouglas Gilbert int num = 0; 697c65b1445SDouglas Gilbert const char * na1 = "https://www.kernel.org/config"; 698c65b1445SDouglas Gilbert const char * na2 = "http://www.kernel.org/log"; 699c65b1445SDouglas Gilbert int plen, olen; 700c65b1445SDouglas Gilbert 701c65b1445SDouglas Gilbert arr[num++] = 0x1; /* lu, storage config */ 702c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 703c65b1445SDouglas Gilbert arr[num++] = 0x0; 704c65b1445SDouglas Gilbert olen = strlen(na1); 705c65b1445SDouglas Gilbert plen = olen + 1; 706c65b1445SDouglas Gilbert if (plen % 4) 707c65b1445SDouglas Gilbert plen = ((plen / 4) + 1) * 4; 708c65b1445SDouglas Gilbert arr[num++] = plen; /* length, null termianted, padded */ 709c65b1445SDouglas Gilbert memcpy(arr + num, na1, olen); 710c65b1445SDouglas Gilbert memset(arr + num + olen, 0, plen - olen); 711c65b1445SDouglas Gilbert num += plen; 712c65b1445SDouglas Gilbert 713c65b1445SDouglas Gilbert arr[num++] = 0x4; /* lu, logging */ 714c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 715c65b1445SDouglas Gilbert arr[num++] = 0x0; 716c65b1445SDouglas Gilbert olen = strlen(na2); 717c65b1445SDouglas Gilbert plen = olen + 1; 718c65b1445SDouglas Gilbert if (plen % 4) 719c65b1445SDouglas Gilbert plen = ((plen / 4) + 1) * 4; 720c65b1445SDouglas Gilbert arr[num++] = plen; /* length, null terminated, padded */ 721c65b1445SDouglas Gilbert memcpy(arr + num, na2, olen); 722c65b1445SDouglas Gilbert memset(arr + num + olen, 0, plen - olen); 723c65b1445SDouglas Gilbert num += plen; 724c65b1445SDouglas Gilbert 725c65b1445SDouglas Gilbert return num; 726c65b1445SDouglas Gilbert } 727c65b1445SDouglas Gilbert 728c65b1445SDouglas Gilbert /* SCSI ports VPD page */ 729c65b1445SDouglas Gilbert static int inquiry_evpd_88(unsigned char * arr, int target_dev_id) 730c65b1445SDouglas Gilbert { 731c65b1445SDouglas Gilbert int num = 0; 732c65b1445SDouglas Gilbert int port_a, port_b; 733c65b1445SDouglas Gilbert 734c65b1445SDouglas Gilbert port_a = target_dev_id + 1; 735c65b1445SDouglas Gilbert port_b = port_a + 1; 736c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 737c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 738c65b1445SDouglas Gilbert arr[num++] = 0x0; 739c65b1445SDouglas Gilbert arr[num++] = 0x1; /* relative port 1 (primary) */ 740c65b1445SDouglas Gilbert memset(arr + num, 0, 6); 741c65b1445SDouglas Gilbert num += 6; 742c65b1445SDouglas Gilbert arr[num++] = 0x0; 743c65b1445SDouglas Gilbert arr[num++] = 12; /* length tp descriptor */ 744c65b1445SDouglas Gilbert /* naa-5 target port identifier (A) */ 745c65b1445SDouglas Gilbert arr[num++] = 0x61; /* proto=sas, binary */ 746c65b1445SDouglas Gilbert arr[num++] = 0x93; /* PIV=1, target port, NAA */ 747c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 748c65b1445SDouglas Gilbert arr[num++] = 0x8; /* length */ 749c65b1445SDouglas Gilbert arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */ 750c65b1445SDouglas Gilbert arr[num++] = 0x22; 751c65b1445SDouglas Gilbert arr[num++] = 0x22; 752c65b1445SDouglas Gilbert arr[num++] = 0x20; 753c65b1445SDouglas Gilbert arr[num++] = (port_a >> 24); 754c65b1445SDouglas Gilbert arr[num++] = (port_a >> 16) & 0xff; 755c65b1445SDouglas Gilbert arr[num++] = (port_a >> 8) & 0xff; 756c65b1445SDouglas Gilbert arr[num++] = port_a & 0xff; 757c65b1445SDouglas Gilbert 758c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 759c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 760c65b1445SDouglas Gilbert arr[num++] = 0x0; 761c65b1445SDouglas Gilbert arr[num++] = 0x2; /* relative port 2 (secondary) */ 762c65b1445SDouglas Gilbert memset(arr + num, 0, 6); 763c65b1445SDouglas Gilbert num += 6; 764c65b1445SDouglas Gilbert arr[num++] = 0x0; 765c65b1445SDouglas Gilbert arr[num++] = 12; /* length tp descriptor */ 766c65b1445SDouglas Gilbert /* naa-5 target port identifier (B) */ 767c65b1445SDouglas Gilbert arr[num++] = 0x61; /* proto=sas, binary */ 768c65b1445SDouglas Gilbert arr[num++] = 0x93; /* PIV=1, target port, NAA */ 769c65b1445SDouglas Gilbert arr[num++] = 0x0; /* reserved */ 770c65b1445SDouglas Gilbert arr[num++] = 0x8; /* length */ 771c65b1445SDouglas Gilbert arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */ 772c65b1445SDouglas Gilbert arr[num++] = 0x22; 773c65b1445SDouglas Gilbert arr[num++] = 0x22; 774c65b1445SDouglas Gilbert arr[num++] = 0x20; 775c65b1445SDouglas Gilbert arr[num++] = (port_b >> 24); 776c65b1445SDouglas Gilbert arr[num++] = (port_b >> 16) & 0xff; 777c65b1445SDouglas Gilbert arr[num++] = (port_b >> 8) & 0xff; 778c65b1445SDouglas Gilbert arr[num++] = port_b & 0xff; 779c65b1445SDouglas Gilbert 780c65b1445SDouglas Gilbert return num; 781c65b1445SDouglas Gilbert } 782c65b1445SDouglas Gilbert 783c65b1445SDouglas Gilbert 784c65b1445SDouglas Gilbert static unsigned char vpd89_data[] = { 785c65b1445SDouglas Gilbert /* from 4th byte */ 0,0,0,0, 786c65b1445SDouglas Gilbert 'l','i','n','u','x',' ',' ',' ', 787c65b1445SDouglas Gilbert 'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ', 788c65b1445SDouglas Gilbert '1','2','3','4', 789c65b1445SDouglas Gilbert 0x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 790c65b1445SDouglas Gilbert 0xec,0,0,0, 791c65b1445SDouglas Gilbert 0x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0, 792c65b1445SDouglas Gilbert 0,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20, 793c65b1445SDouglas Gilbert 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33, 794c65b1445SDouglas Gilbert 0x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31, 795c65b1445SDouglas Gilbert 0x53,0x41, 796c65b1445SDouglas Gilbert 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 797c65b1445SDouglas Gilbert 0x20,0x20, 798c65b1445SDouglas Gilbert 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 799c65b1445SDouglas Gilbert 0x10,0x80, 800c65b1445SDouglas Gilbert 0,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0, 801c65b1445SDouglas Gilbert 0x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0, 802c65b1445SDouglas Gilbert 0x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0, 803c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0, 804c65b1445SDouglas Gilbert 0x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40, 805c65b1445SDouglas Gilbert 0x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0, 806c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,0,0,0,0, 807c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 808c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 809c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 810c65b1445SDouglas Gilbert 0x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42, 811c65b1445SDouglas Gilbert 0,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8, 812c65b1445SDouglas Gilbert 0xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe, 813c65b1445SDouglas Gilbert 0,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,0, 814c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 815c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 816c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 817c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 818c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 819c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 820c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 821c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 822c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 823c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 824c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 825c65b1445SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51, 826c65b1445SDouglas Gilbert }; 827c65b1445SDouglas Gilbert 828cbf67842SDouglas Gilbert /* ATA Information VPD page */ 829c65b1445SDouglas Gilbert static int inquiry_evpd_89(unsigned char * arr) 830c65b1445SDouglas Gilbert { 831c65b1445SDouglas Gilbert memcpy(arr, vpd89_data, sizeof(vpd89_data)); 832c65b1445SDouglas Gilbert return sizeof(vpd89_data); 833c65b1445SDouglas Gilbert } 834c65b1445SDouglas Gilbert 835c65b1445SDouglas Gilbert 836c65b1445SDouglas Gilbert static unsigned char vpdb0_data[] = { 8371e49f785SDouglas Gilbert /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64, 8381e49f785SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 8391e49f785SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 8401e49f785SDouglas Gilbert 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 841c65b1445SDouglas Gilbert }; 842c65b1445SDouglas Gilbert 843cbf67842SDouglas Gilbert /* Block limits VPD page (SBC-3) */ 844c65b1445SDouglas Gilbert static int inquiry_evpd_b0(unsigned char * arr) 845c65b1445SDouglas Gilbert { 846ea61fca5SMartin K. Petersen unsigned int gran; 847ea61fca5SMartin K. Petersen 848c65b1445SDouglas Gilbert memcpy(arr, vpdb0_data, sizeof(vpdb0_data)); 849e308b3d1SMartin K. Petersen 850e308b3d1SMartin K. Petersen /* Optimal transfer length granularity */ 851ea61fca5SMartin K. Petersen gran = 1 << scsi_debug_physblk_exp; 852ea61fca5SMartin K. Petersen arr[2] = (gran >> 8) & 0xff; 853ea61fca5SMartin K. Petersen arr[3] = gran & 0xff; 854e308b3d1SMartin K. Petersen 855e308b3d1SMartin K. Petersen /* Maximum Transfer Length */ 856c65b1445SDouglas Gilbert if (sdebug_store_sectors > 0x400) { 857c65b1445SDouglas Gilbert arr[4] = (sdebug_store_sectors >> 24) & 0xff; 858c65b1445SDouglas Gilbert arr[5] = (sdebug_store_sectors >> 16) & 0xff; 859c65b1445SDouglas Gilbert arr[6] = (sdebug_store_sectors >> 8) & 0xff; 860c65b1445SDouglas Gilbert arr[7] = sdebug_store_sectors & 0xff; 861c65b1445SDouglas Gilbert } 86244d92694SMartin K. Petersen 863e308b3d1SMartin K. Petersen /* Optimal Transfer Length */ 864e308b3d1SMartin K. Petersen put_unaligned_be32(scsi_debug_opt_blks, &arr[8]); 865e308b3d1SMartin K. Petersen 8665b94e232SMartin K. Petersen if (scsi_debug_lbpu) { 867e308b3d1SMartin K. Petersen /* Maximum Unmap LBA Count */ 8686014759cSMartin K. Petersen put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]); 869e308b3d1SMartin K. Petersen 870e308b3d1SMartin K. Petersen /* Maximum Unmap Block Descriptor Count */ 87144d92694SMartin K. Petersen put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]); 87244d92694SMartin K. Petersen } 87344d92694SMartin K. Petersen 874e308b3d1SMartin K. Petersen /* Unmap Granularity Alignment */ 87544d92694SMartin K. Petersen if (scsi_debug_unmap_alignment) { 87644d92694SMartin K. Petersen put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]); 87744d92694SMartin K. Petersen arr[28] |= 0x80; /* UGAVALID */ 87844d92694SMartin K. Petersen } 87944d92694SMartin K. Petersen 880e308b3d1SMartin K. Petersen /* Optimal Unmap Granularity */ 88144d92694SMartin K. Petersen put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]); 8826014759cSMartin K. Petersen 8835b94e232SMartin K. Petersen /* Maximum WRITE SAME Length */ 8845b94e232SMartin K. Petersen put_unaligned_be64(scsi_debug_write_same_length, &arr[32]); 8855b94e232SMartin K. Petersen 8865b94e232SMartin K. Petersen return 0x3c; /* Mandatory page length for Logical Block Provisioning */ 88744d92694SMartin K. Petersen 888c65b1445SDouglas Gilbert return sizeof(vpdb0_data); 8891da177e4SLinus Torvalds } 8901da177e4SLinus Torvalds 8911e49f785SDouglas Gilbert /* Block device characteristics VPD page (SBC-3) */ 892eac6e8e4SMatthew Wilcox static int inquiry_evpd_b1(unsigned char *arr) 893eac6e8e4SMatthew Wilcox { 894eac6e8e4SMatthew Wilcox memset(arr, 0, 0x3c); 895eac6e8e4SMatthew Wilcox arr[0] = 0; 8961e49f785SDouglas Gilbert arr[1] = 1; /* non rotating medium (e.g. solid state) */ 8971e49f785SDouglas Gilbert arr[2] = 0; 8981e49f785SDouglas Gilbert arr[3] = 5; /* less than 1.8" */ 899eac6e8e4SMatthew Wilcox 900eac6e8e4SMatthew Wilcox return 0x3c; 901eac6e8e4SMatthew Wilcox } 9021da177e4SLinus Torvalds 903be1dd78dSEric Sandeen /* Logical block provisioning VPD page (SBC-3) */ 9046014759cSMartin K. Petersen static int inquiry_evpd_b2(unsigned char *arr) 9056014759cSMartin K. Petersen { 9063f0bc3b3SMartin K. Petersen memset(arr, 0, 0x4); 9076014759cSMartin K. Petersen arr[0] = 0; /* threshold exponent */ 9086014759cSMartin K. Petersen 9095b94e232SMartin K. Petersen if (scsi_debug_lbpu) 9106014759cSMartin K. Petersen arr[1] = 1 << 7; 9116014759cSMartin K. Petersen 9125b94e232SMartin K. Petersen if (scsi_debug_lbpws) 9136014759cSMartin K. Petersen arr[1] |= 1 << 6; 9146014759cSMartin K. Petersen 9155b94e232SMartin K. Petersen if (scsi_debug_lbpws10) 9165b94e232SMartin K. Petersen arr[1] |= 1 << 5; 9175b94e232SMartin K. Petersen 918be1dd78dSEric Sandeen if (scsi_debug_lbprz) 919be1dd78dSEric Sandeen arr[1] |= 1 << 2; 920be1dd78dSEric Sandeen 9213f0bc3b3SMartin K. Petersen return 0x4; 9226014759cSMartin K. Petersen } 9236014759cSMartin K. Petersen 9241da177e4SLinus Torvalds #define SDEBUG_LONG_INQ_SZ 96 925c65b1445SDouglas Gilbert #define SDEBUG_MAX_INQ_ARR_SZ 584 9261da177e4SLinus Torvalds 9271da177e4SLinus Torvalds static int resp_inquiry(struct scsi_cmnd *scp, int target, 9281da177e4SLinus Torvalds struct sdebug_dev_info * devip) 9291da177e4SLinus Torvalds { 9301da177e4SLinus Torvalds unsigned char pq_pdt; 9315a09e398SHannes Reinecke unsigned char * arr; 93201123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 9335a09e398SHannes Reinecke int alloc_len, n, ret; 9341da177e4SLinus Torvalds 9351da177e4SLinus Torvalds alloc_len = (cmd[3] << 8) + cmd[4]; 9366f3cbf55SDouglas Gilbert arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); 9376f3cbf55SDouglas Gilbert if (! arr) 9386f3cbf55SDouglas Gilbert return DID_REQUEUE << 16; 939c65b1445SDouglas Gilbert if (devip->wlun) 940c65b1445SDouglas Gilbert pq_pdt = 0x1e; /* present, wlun */ 941c65b1445SDouglas Gilbert else if (scsi_debug_no_lun_0 && (0 == devip->lun)) 942c65b1445SDouglas Gilbert pq_pdt = 0x7f; /* not present, no device type */ 943c65b1445SDouglas Gilbert else 9441da177e4SLinus Torvalds pq_pdt = (scsi_debug_ptype & 0x1f); 9451da177e4SLinus Torvalds arr[0] = pq_pdt; 9461da177e4SLinus Torvalds if (0x2 & cmd[1]) { /* CMDDT bit set */ 947cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 9481da177e4SLinus Torvalds 0); 9495a09e398SHannes Reinecke kfree(arr); 9501da177e4SLinus Torvalds return check_condition_result; 9511da177e4SLinus Torvalds } else if (0x1 & cmd[1]) { /* EVPD bit set */ 9525a09e398SHannes Reinecke int lu_id_num, port_group_id, target_dev_id, len; 953c65b1445SDouglas Gilbert char lu_id_str[6]; 954c65b1445SDouglas Gilbert int host_no = devip->sdbg_host->shost->host_no; 9551da177e4SLinus Torvalds 9565a09e398SHannes Reinecke port_group_id = (((host_no + 1) & 0x7f) << 8) + 9575a09e398SHannes Reinecke (devip->channel & 0x7f); 95823183910SDouglas Gilbert if (0 == scsi_debug_vpd_use_hostno) 95923183910SDouglas Gilbert host_no = 0; 960c65b1445SDouglas Gilbert lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) + 961c65b1445SDouglas Gilbert (devip->target * 1000) + devip->lun); 962c65b1445SDouglas Gilbert target_dev_id = ((host_no + 1) * 2000) + 963c65b1445SDouglas Gilbert (devip->target * 1000) - 3; 964c65b1445SDouglas Gilbert len = scnprintf(lu_id_str, 6, "%d", lu_id_num); 9651da177e4SLinus Torvalds if (0 == cmd[2]) { /* supported vital product data pages */ 966c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 967c65b1445SDouglas Gilbert n = 4; 968c65b1445SDouglas Gilbert arr[n++] = 0x0; /* this page */ 969c65b1445SDouglas Gilbert arr[n++] = 0x80; /* unit serial number */ 970c65b1445SDouglas Gilbert arr[n++] = 0x83; /* device identification */ 971c65b1445SDouglas Gilbert arr[n++] = 0x84; /* software interface ident. */ 972c65b1445SDouglas Gilbert arr[n++] = 0x85; /* management network addresses */ 973c65b1445SDouglas Gilbert arr[n++] = 0x86; /* extended inquiry */ 974c65b1445SDouglas Gilbert arr[n++] = 0x87; /* mode page policy */ 975c65b1445SDouglas Gilbert arr[n++] = 0x88; /* SCSI ports */ 976c65b1445SDouglas Gilbert arr[n++] = 0x89; /* ATA information */ 977c65b1445SDouglas Gilbert arr[n++] = 0xb0; /* Block limits (SBC) */ 978eac6e8e4SMatthew Wilcox arr[n++] = 0xb1; /* Block characteristics (SBC) */ 9795b94e232SMartin K. Petersen if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */ 9805b94e232SMartin K. Petersen arr[n++] = 0xb2; 981c65b1445SDouglas Gilbert arr[3] = n - 4; /* number of supported VPD pages */ 9821da177e4SLinus Torvalds } else if (0x80 == cmd[2]) { /* unit serial number */ 983c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 9841da177e4SLinus Torvalds arr[3] = len; 985c65b1445SDouglas Gilbert memcpy(&arr[4], lu_id_str, len); 9861da177e4SLinus Torvalds } else if (0x83 == cmd[2]) { /* device identification */ 987c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 9885a09e398SHannes Reinecke arr[3] = inquiry_evpd_83(&arr[4], port_group_id, 9895a09e398SHannes Reinecke target_dev_id, lu_id_num, 9905a09e398SHannes Reinecke lu_id_str, len); 991c65b1445SDouglas Gilbert } else if (0x84 == cmd[2]) { /* Software interface ident. */ 992c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 993c65b1445SDouglas Gilbert arr[3] = inquiry_evpd_84(&arr[4]); 994c65b1445SDouglas Gilbert } else if (0x85 == cmd[2]) { /* Management network addresses */ 995c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 996c65b1445SDouglas Gilbert arr[3] = inquiry_evpd_85(&arr[4]); 997c65b1445SDouglas Gilbert } else if (0x86 == cmd[2]) { /* extended inquiry */ 998c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 999c65b1445SDouglas Gilbert arr[3] = 0x3c; /* number of following entries */ 1000c6a44287SMartin K. Petersen if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) 1001c6a44287SMartin K. Petersen arr[4] = 0x4; /* SPT: GRD_CHK:1 */ 1002c6a44287SMartin K. Petersen else if (scsi_debug_dif) 1003c6a44287SMartin K. Petersen arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ 1004c6a44287SMartin K. Petersen else 1005c65b1445SDouglas Gilbert arr[4] = 0x0; /* no protection stuff */ 1006c65b1445SDouglas Gilbert arr[5] = 0x7; /* head of q, ordered + simple q's */ 1007c65b1445SDouglas Gilbert } else if (0x87 == cmd[2]) { /* mode page policy */ 1008c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 1009c65b1445SDouglas Gilbert arr[3] = 0x8; /* number of following entries */ 1010c65b1445SDouglas Gilbert arr[4] = 0x2; /* disconnect-reconnect mp */ 1011c65b1445SDouglas Gilbert arr[6] = 0x80; /* mlus, shared */ 1012c65b1445SDouglas Gilbert arr[8] = 0x18; /* protocol specific lu */ 1013c65b1445SDouglas Gilbert arr[10] = 0x82; /* mlus, per initiator port */ 1014c65b1445SDouglas Gilbert } else if (0x88 == cmd[2]) { /* SCSI Ports */ 1015c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 1016c65b1445SDouglas Gilbert arr[3] = inquiry_evpd_88(&arr[4], target_dev_id); 1017c65b1445SDouglas Gilbert } else if (0x89 == cmd[2]) { /* ATA information */ 1018c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 1019c65b1445SDouglas Gilbert n = inquiry_evpd_89(&arr[4]); 1020c65b1445SDouglas Gilbert arr[2] = (n >> 8); 1021c65b1445SDouglas Gilbert arr[3] = (n & 0xff); 1022c65b1445SDouglas Gilbert } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */ 1023c65b1445SDouglas Gilbert arr[1] = cmd[2]; /*sanity */ 1024c65b1445SDouglas Gilbert arr[3] = inquiry_evpd_b0(&arr[4]); 1025eac6e8e4SMatthew Wilcox } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */ 1026eac6e8e4SMatthew Wilcox arr[1] = cmd[2]; /*sanity */ 1027eac6e8e4SMatthew Wilcox arr[3] = inquiry_evpd_b1(&arr[4]); 10285b94e232SMartin K. Petersen } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */ 10296014759cSMartin K. Petersen arr[1] = cmd[2]; /*sanity */ 10306014759cSMartin K. Petersen arr[3] = inquiry_evpd_b2(&arr[4]); 10311da177e4SLinus Torvalds } else { 10321da177e4SLinus Torvalds /* Illegal request, invalid field in cdb */ 1033cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 10341da177e4SLinus Torvalds INVALID_FIELD_IN_CDB, 0); 10355a09e398SHannes Reinecke kfree(arr); 10361da177e4SLinus Torvalds return check_condition_result; 10371da177e4SLinus Torvalds } 1038c65b1445SDouglas Gilbert len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); 10395a09e398SHannes Reinecke ret = fill_from_dev_buffer(scp, arr, 1040c65b1445SDouglas Gilbert min(len, SDEBUG_MAX_INQ_ARR_SZ)); 10415a09e398SHannes Reinecke kfree(arr); 10425a09e398SHannes Reinecke return ret; 10431da177e4SLinus Torvalds } 10441da177e4SLinus Torvalds /* drops through here for a standard inquiry */ 1045d986788bSMartin Pitt arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */ 10461da177e4SLinus Torvalds arr[2] = scsi_debug_scsi_level; 10471da177e4SLinus Torvalds arr[3] = 2; /* response_data_format==2 */ 10481da177e4SLinus Torvalds arr[4] = SDEBUG_LONG_INQ_SZ - 5; 1049c6a44287SMartin K. Petersen arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */ 10505a09e398SHannes Reinecke if (0 == scsi_debug_vpd_use_hostno) 10515a09e398SHannes Reinecke arr[5] = 0x10; /* claim: implicit TGPS */ 1052c65b1445SDouglas Gilbert arr[6] = 0x10; /* claim: MultiP */ 10531da177e4SLinus Torvalds /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */ 1054c65b1445SDouglas Gilbert arr[7] = 0xa; /* claim: LINKED + CMDQUE */ 10551da177e4SLinus Torvalds memcpy(&arr[8], inq_vendor_id, 8); 10561da177e4SLinus Torvalds memcpy(&arr[16], inq_product_id, 16); 10571da177e4SLinus Torvalds memcpy(&arr[32], inq_product_rev, 4); 10581da177e4SLinus Torvalds /* version descriptors (2 bytes each) follow */ 1059e46b0344SDouglas Gilbert arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */ 1060e46b0344SDouglas Gilbert arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */ 1061c65b1445SDouglas Gilbert n = 62; 10621da177e4SLinus Torvalds if (scsi_debug_ptype == 0) { 1063e46b0344SDouglas Gilbert arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */ 10641da177e4SLinus Torvalds } else if (scsi_debug_ptype == 1) { 1065e46b0344SDouglas Gilbert arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */ 10661da177e4SLinus Torvalds } 1067e46b0344SDouglas Gilbert arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */ 10685a09e398SHannes Reinecke ret = fill_from_dev_buffer(scp, arr, 10691da177e4SLinus Torvalds min(alloc_len, SDEBUG_LONG_INQ_SZ)); 10705a09e398SHannes Reinecke kfree(arr); 10715a09e398SHannes Reinecke return ret; 10721da177e4SLinus Torvalds } 10731da177e4SLinus Torvalds 10741da177e4SLinus Torvalds static int resp_requests(struct scsi_cmnd * scp, 10751da177e4SLinus Torvalds struct sdebug_dev_info * devip) 10761da177e4SLinus Torvalds { 10771da177e4SLinus Torvalds unsigned char * sbuff; 107801123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 1079cbf67842SDouglas Gilbert unsigned char arr[SCSI_SENSE_BUFFERSIZE]; 1080c65b1445SDouglas Gilbert int want_dsense; 10811da177e4SLinus Torvalds int len = 18; 10821da177e4SLinus Torvalds 1083c65b1445SDouglas Gilbert memset(arr, 0, sizeof(arr)); 1084c65b1445SDouglas Gilbert want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense; 1085cbf67842SDouglas Gilbert sbuff = scp->sense_buffer; 1086c65b1445SDouglas Gilbert if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { 1087c65b1445SDouglas Gilbert if (want_dsense) { 1088c65b1445SDouglas Gilbert arr[0] = 0x72; 1089c65b1445SDouglas Gilbert arr[1] = 0x0; /* NO_SENSE in sense_key */ 1090c65b1445SDouglas Gilbert arr[2] = THRESHOLD_EXCEEDED; 1091c65b1445SDouglas Gilbert arr[3] = 0xff; /* TEST set and MRIE==6 */ 1092c65b1445SDouglas Gilbert } else { 1093c65b1445SDouglas Gilbert arr[0] = 0x70; 1094c65b1445SDouglas Gilbert arr[2] = 0x0; /* NO_SENSE in sense_key */ 1095c65b1445SDouglas Gilbert arr[7] = 0xa; /* 18 byte sense buffer */ 1096c65b1445SDouglas Gilbert arr[12] = THRESHOLD_EXCEEDED; 1097c65b1445SDouglas Gilbert arr[13] = 0xff; /* TEST set and MRIE==6 */ 1098c65b1445SDouglas Gilbert } 1099c65b1445SDouglas Gilbert } else { 1100cbf67842SDouglas Gilbert memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); 11011da177e4SLinus Torvalds if ((cmd[1] & 1) && (! scsi_debug_dsense)) { 11021da177e4SLinus Torvalds /* DESC bit set and sense_buff in fixed format */ 1103c65b1445SDouglas Gilbert memset(arr, 0, sizeof(arr)); 11041da177e4SLinus Torvalds arr[0] = 0x72; 11051da177e4SLinus Torvalds arr[1] = sbuff[2]; /* sense key */ 11061da177e4SLinus Torvalds arr[2] = sbuff[12]; /* asc */ 11071da177e4SLinus Torvalds arr[3] = sbuff[13]; /* ascq */ 11081da177e4SLinus Torvalds len = 8; 1109c65b1445SDouglas Gilbert } 1110c65b1445SDouglas Gilbert } 1111cbf67842SDouglas Gilbert mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0); 11121da177e4SLinus Torvalds return fill_from_dev_buffer(scp, arr, len); 11131da177e4SLinus Torvalds } 11141da177e4SLinus Torvalds 1115c65b1445SDouglas Gilbert static int resp_start_stop(struct scsi_cmnd * scp, 1116c65b1445SDouglas Gilbert struct sdebug_dev_info * devip) 1117c65b1445SDouglas Gilbert { 111801123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 1119c65b1445SDouglas Gilbert int power_cond, errsts, start; 1120c65b1445SDouglas Gilbert 1121cbf67842SDouglas Gilbert errsts = check_readiness(scp, UAS_ONLY, devip); 1122cbf67842SDouglas Gilbert if (errsts) 1123c65b1445SDouglas Gilbert return errsts; 1124c65b1445SDouglas Gilbert power_cond = (cmd[4] & 0xf0) >> 4; 1125c65b1445SDouglas Gilbert if (power_cond) { 1126cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 1127c65b1445SDouglas Gilbert 0); 1128c65b1445SDouglas Gilbert return check_condition_result; 1129c65b1445SDouglas Gilbert } 1130c65b1445SDouglas Gilbert start = cmd[4] & 1; 1131c65b1445SDouglas Gilbert if (start == devip->stopped) 1132c65b1445SDouglas Gilbert devip->stopped = !start; 1133c65b1445SDouglas Gilbert return 0; 1134c65b1445SDouglas Gilbert } 1135c65b1445SDouglas Gilbert 113628898873SFUJITA Tomonori static sector_t get_sdebug_capacity(void) 113728898873SFUJITA Tomonori { 113828898873SFUJITA Tomonori if (scsi_debug_virtual_gb > 0) 11395447ed6cSDouglas Gilbert return (sector_t)scsi_debug_virtual_gb * 11405447ed6cSDouglas Gilbert (1073741824 / scsi_debug_sector_size); 114128898873SFUJITA Tomonori else 114228898873SFUJITA Tomonori return sdebug_store_sectors; 114328898873SFUJITA Tomonori } 114428898873SFUJITA Tomonori 11451da177e4SLinus Torvalds #define SDEBUG_READCAP_ARR_SZ 8 11461da177e4SLinus Torvalds static int resp_readcap(struct scsi_cmnd * scp, 11471da177e4SLinus Torvalds struct sdebug_dev_info * devip) 11481da177e4SLinus Torvalds { 11491da177e4SLinus Torvalds unsigned char arr[SDEBUG_READCAP_ARR_SZ]; 1150c65b1445SDouglas Gilbert unsigned int capac; 11511da177e4SLinus Torvalds int errsts; 11521da177e4SLinus Torvalds 1153cbf67842SDouglas Gilbert errsts = check_readiness(scp, UAS_ONLY, devip); 1154cbf67842SDouglas Gilbert if (errsts) 11551da177e4SLinus Torvalds return errsts; 1156c65b1445SDouglas Gilbert /* following just in case virtual_gb changed */ 115728898873SFUJITA Tomonori sdebug_capacity = get_sdebug_capacity(); 11581da177e4SLinus Torvalds memset(arr, 0, SDEBUG_READCAP_ARR_SZ); 1159c65b1445SDouglas Gilbert if (sdebug_capacity < 0xffffffff) { 1160c65b1445SDouglas Gilbert capac = (unsigned int)sdebug_capacity - 1; 11611da177e4SLinus Torvalds arr[0] = (capac >> 24); 11621da177e4SLinus Torvalds arr[1] = (capac >> 16) & 0xff; 11631da177e4SLinus Torvalds arr[2] = (capac >> 8) & 0xff; 11641da177e4SLinus Torvalds arr[3] = capac & 0xff; 1165c65b1445SDouglas Gilbert } else { 1166c65b1445SDouglas Gilbert arr[0] = 0xff; 1167c65b1445SDouglas Gilbert arr[1] = 0xff; 1168c65b1445SDouglas Gilbert arr[2] = 0xff; 1169c65b1445SDouglas Gilbert arr[3] = 0xff; 1170c65b1445SDouglas Gilbert } 1171597136abSMartin K. Petersen arr[6] = (scsi_debug_sector_size >> 8) & 0xff; 1172597136abSMartin K. Petersen arr[7] = scsi_debug_sector_size & 0xff; 11731da177e4SLinus Torvalds return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ); 11741da177e4SLinus Torvalds } 11751da177e4SLinus Torvalds 1176c65b1445SDouglas Gilbert #define SDEBUG_READCAP16_ARR_SZ 32 1177c65b1445SDouglas Gilbert static int resp_readcap16(struct scsi_cmnd * scp, 1178c65b1445SDouglas Gilbert struct sdebug_dev_info * devip) 1179c65b1445SDouglas Gilbert { 118001123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 1181c65b1445SDouglas Gilbert unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; 1182c65b1445SDouglas Gilbert unsigned long long capac; 1183c65b1445SDouglas Gilbert int errsts, k, alloc_len; 1184c65b1445SDouglas Gilbert 1185cbf67842SDouglas Gilbert errsts = check_readiness(scp, UAS_ONLY, devip); 1186cbf67842SDouglas Gilbert if (errsts) 1187c65b1445SDouglas Gilbert return errsts; 1188c65b1445SDouglas Gilbert alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) 1189c65b1445SDouglas Gilbert + cmd[13]); 1190c65b1445SDouglas Gilbert /* following just in case virtual_gb changed */ 119128898873SFUJITA Tomonori sdebug_capacity = get_sdebug_capacity(); 1192c65b1445SDouglas Gilbert memset(arr, 0, SDEBUG_READCAP16_ARR_SZ); 1193c65b1445SDouglas Gilbert capac = sdebug_capacity - 1; 1194c65b1445SDouglas Gilbert for (k = 0; k < 8; ++k, capac >>= 8) 1195c65b1445SDouglas Gilbert arr[7 - k] = capac & 0xff; 1196597136abSMartin K. Petersen arr[8] = (scsi_debug_sector_size >> 24) & 0xff; 1197597136abSMartin K. Petersen arr[9] = (scsi_debug_sector_size >> 16) & 0xff; 1198597136abSMartin K. Petersen arr[10] = (scsi_debug_sector_size >> 8) & 0xff; 1199597136abSMartin K. Petersen arr[11] = scsi_debug_sector_size & 0xff; 1200ea61fca5SMartin K. Petersen arr[13] = scsi_debug_physblk_exp & 0xf; 1201ea61fca5SMartin K. Petersen arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f; 120244d92694SMartin K. Petersen 1203be1dd78dSEric Sandeen if (scsi_debug_lbp()) { 12045b94e232SMartin K. Petersen arr[14] |= 0x80; /* LBPME */ 1205be1dd78dSEric Sandeen if (scsi_debug_lbprz) 1206be1dd78dSEric Sandeen arr[14] |= 0x40; /* LBPRZ */ 1207be1dd78dSEric Sandeen } 120844d92694SMartin K. Petersen 1209ea61fca5SMartin K. Petersen arr[15] = scsi_debug_lowest_aligned & 0xff; 1210c6a44287SMartin K. Petersen 1211c6a44287SMartin K. Petersen if (scsi_debug_dif) { 1212c6a44287SMartin K. Petersen arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */ 1213c6a44287SMartin K. Petersen arr[12] |= 1; /* PROT_EN */ 1214c6a44287SMartin K. Petersen } 1215c6a44287SMartin K. Petersen 1216c65b1445SDouglas Gilbert return fill_from_dev_buffer(scp, arr, 1217c65b1445SDouglas Gilbert min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); 1218c65b1445SDouglas Gilbert } 1219c65b1445SDouglas Gilbert 12205a09e398SHannes Reinecke #define SDEBUG_MAX_TGTPGS_ARR_SZ 1412 12215a09e398SHannes Reinecke 12225a09e398SHannes Reinecke static int resp_report_tgtpgs(struct scsi_cmnd * scp, 12235a09e398SHannes Reinecke struct sdebug_dev_info * devip) 12245a09e398SHannes Reinecke { 122501123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 12265a09e398SHannes Reinecke unsigned char * arr; 12275a09e398SHannes Reinecke int host_no = devip->sdbg_host->shost->host_no; 12285a09e398SHannes Reinecke int n, ret, alen, rlen; 12295a09e398SHannes Reinecke int port_group_a, port_group_b, port_a, port_b; 12305a09e398SHannes Reinecke 12315a09e398SHannes Reinecke alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) 12325a09e398SHannes Reinecke + cmd[9]); 12335a09e398SHannes Reinecke 12346f3cbf55SDouglas Gilbert arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); 12356f3cbf55SDouglas Gilbert if (! arr) 12366f3cbf55SDouglas Gilbert return DID_REQUEUE << 16; 12375a09e398SHannes Reinecke /* 12385a09e398SHannes Reinecke * EVPD page 0x88 states we have two ports, one 12395a09e398SHannes Reinecke * real and a fake port with no device connected. 12405a09e398SHannes Reinecke * So we create two port groups with one port each 12415a09e398SHannes Reinecke * and set the group with port B to unavailable. 12425a09e398SHannes Reinecke */ 12435a09e398SHannes Reinecke port_a = 0x1; /* relative port A */ 12445a09e398SHannes Reinecke port_b = 0x2; /* relative port B */ 12455a09e398SHannes Reinecke port_group_a = (((host_no + 1) & 0x7f) << 8) + 12465a09e398SHannes Reinecke (devip->channel & 0x7f); 12475a09e398SHannes Reinecke port_group_b = (((host_no + 1) & 0x7f) << 8) + 12485a09e398SHannes Reinecke (devip->channel & 0x7f) + 0x80; 12495a09e398SHannes Reinecke 12505a09e398SHannes Reinecke /* 12515a09e398SHannes Reinecke * The asymmetric access state is cycled according to the host_id. 12525a09e398SHannes Reinecke */ 12535a09e398SHannes Reinecke n = 4; 12545a09e398SHannes Reinecke if (0 == scsi_debug_vpd_use_hostno) { 12555a09e398SHannes Reinecke arr[n++] = host_no % 3; /* Asymm access state */ 12565a09e398SHannes Reinecke arr[n++] = 0x0F; /* claim: all states are supported */ 12575a09e398SHannes Reinecke } else { 12585a09e398SHannes Reinecke arr[n++] = 0x0; /* Active/Optimized path */ 12595a09e398SHannes Reinecke arr[n++] = 0x01; /* claim: only support active/optimized paths */ 12605a09e398SHannes Reinecke } 12615a09e398SHannes Reinecke arr[n++] = (port_group_a >> 8) & 0xff; 12625a09e398SHannes Reinecke arr[n++] = port_group_a & 0xff; 12635a09e398SHannes Reinecke arr[n++] = 0; /* Reserved */ 12645a09e398SHannes Reinecke arr[n++] = 0; /* Status code */ 12655a09e398SHannes Reinecke arr[n++] = 0; /* Vendor unique */ 12665a09e398SHannes Reinecke arr[n++] = 0x1; /* One port per group */ 12675a09e398SHannes Reinecke arr[n++] = 0; /* Reserved */ 12685a09e398SHannes Reinecke arr[n++] = 0; /* Reserved */ 12695a09e398SHannes Reinecke arr[n++] = (port_a >> 8) & 0xff; 12705a09e398SHannes Reinecke arr[n++] = port_a & 0xff; 12715a09e398SHannes Reinecke arr[n++] = 3; /* Port unavailable */ 12725a09e398SHannes Reinecke arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */ 12735a09e398SHannes Reinecke arr[n++] = (port_group_b >> 8) & 0xff; 12745a09e398SHannes Reinecke arr[n++] = port_group_b & 0xff; 12755a09e398SHannes Reinecke arr[n++] = 0; /* Reserved */ 12765a09e398SHannes Reinecke arr[n++] = 0; /* Status code */ 12775a09e398SHannes Reinecke arr[n++] = 0; /* Vendor unique */ 12785a09e398SHannes Reinecke arr[n++] = 0x1; /* One port per group */ 12795a09e398SHannes Reinecke arr[n++] = 0; /* Reserved */ 12805a09e398SHannes Reinecke arr[n++] = 0; /* Reserved */ 12815a09e398SHannes Reinecke arr[n++] = (port_b >> 8) & 0xff; 12825a09e398SHannes Reinecke arr[n++] = port_b & 0xff; 12835a09e398SHannes Reinecke 12845a09e398SHannes Reinecke rlen = n - 4; 12855a09e398SHannes Reinecke arr[0] = (rlen >> 24) & 0xff; 12865a09e398SHannes Reinecke arr[1] = (rlen >> 16) & 0xff; 12875a09e398SHannes Reinecke arr[2] = (rlen >> 8) & 0xff; 12885a09e398SHannes Reinecke arr[3] = rlen & 0xff; 12895a09e398SHannes Reinecke 12905a09e398SHannes Reinecke /* 12915a09e398SHannes Reinecke * Return the smallest value of either 12925a09e398SHannes Reinecke * - The allocated length 12935a09e398SHannes Reinecke * - The constructed command length 12945a09e398SHannes Reinecke * - The maximum array size 12955a09e398SHannes Reinecke */ 12965a09e398SHannes Reinecke rlen = min(alen,n); 12975a09e398SHannes Reinecke ret = fill_from_dev_buffer(scp, arr, 12985a09e398SHannes Reinecke min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); 12995a09e398SHannes Reinecke kfree(arr); 13005a09e398SHannes Reinecke return ret; 13015a09e398SHannes Reinecke } 13025a09e398SHannes Reinecke 13031da177e4SLinus Torvalds /* <<Following mode page info copied from ST318451LW>> */ 13041da177e4SLinus Torvalds 13051da177e4SLinus Torvalds static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) 13061da177e4SLinus Torvalds { /* Read-Write Error Recovery page for mode_sense */ 13071da177e4SLinus Torvalds unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0, 13081da177e4SLinus Torvalds 5, 0, 0xff, 0xff}; 13091da177e4SLinus Torvalds 13101da177e4SLinus Torvalds memcpy(p, err_recov_pg, sizeof(err_recov_pg)); 13111da177e4SLinus Torvalds if (1 == pcontrol) 13121da177e4SLinus Torvalds memset(p + 2, 0, sizeof(err_recov_pg) - 2); 13131da177e4SLinus Torvalds return sizeof(err_recov_pg); 13141da177e4SLinus Torvalds } 13151da177e4SLinus Torvalds 13161da177e4SLinus Torvalds static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target) 13171da177e4SLinus Torvalds { /* Disconnect-Reconnect page for mode_sense */ 13181da177e4SLinus Torvalds unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0, 13191da177e4SLinus Torvalds 0, 0, 0, 0, 0, 0, 0, 0}; 13201da177e4SLinus Torvalds 13211da177e4SLinus Torvalds memcpy(p, disconnect_pg, sizeof(disconnect_pg)); 13221da177e4SLinus Torvalds if (1 == pcontrol) 13231da177e4SLinus Torvalds memset(p + 2, 0, sizeof(disconnect_pg) - 2); 13241da177e4SLinus Torvalds return sizeof(disconnect_pg); 13251da177e4SLinus Torvalds } 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds static int resp_format_pg(unsigned char * p, int pcontrol, int target) 13281da177e4SLinus Torvalds { /* Format device page for mode_sense */ 13291da177e4SLinus Torvalds unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0, 13301da177e4SLinus Torvalds 0, 0, 0, 0, 0, 0, 0, 0, 13311da177e4SLinus Torvalds 0, 0, 0, 0, 0x40, 0, 0, 0}; 13321da177e4SLinus Torvalds 13331da177e4SLinus Torvalds memcpy(p, format_pg, sizeof(format_pg)); 13341da177e4SLinus Torvalds p[10] = (sdebug_sectors_per >> 8) & 0xff; 13351da177e4SLinus Torvalds p[11] = sdebug_sectors_per & 0xff; 1336597136abSMartin K. Petersen p[12] = (scsi_debug_sector_size >> 8) & 0xff; 1337597136abSMartin K. Petersen p[13] = scsi_debug_sector_size & 0xff; 1338d986788bSMartin Pitt if (scsi_debug_removable) 13391da177e4SLinus Torvalds p[20] |= 0x20; /* should agree with INQUIRY */ 13401da177e4SLinus Torvalds if (1 == pcontrol) 13411da177e4SLinus Torvalds memset(p + 2, 0, sizeof(format_pg) - 2); 13421da177e4SLinus Torvalds return sizeof(format_pg); 13431da177e4SLinus Torvalds } 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds static int resp_caching_pg(unsigned char * p, int pcontrol, int target) 13461da177e4SLinus Torvalds { /* Caching page for mode_sense */ 1347cbf67842SDouglas Gilbert unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0, 1348cbf67842SDouglas Gilbert 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 1349cbf67842SDouglas Gilbert unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 13501da177e4SLinus Torvalds 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}; 13511da177e4SLinus Torvalds 1352cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts) 1353cbf67842SDouglas Gilbert caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */ 13541da177e4SLinus Torvalds memcpy(p, caching_pg, sizeof(caching_pg)); 13551da177e4SLinus Torvalds if (1 == pcontrol) 1356cbf67842SDouglas Gilbert memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg)); 1357cbf67842SDouglas Gilbert else if (2 == pcontrol) 1358cbf67842SDouglas Gilbert memcpy(p, d_caching_pg, sizeof(d_caching_pg)); 13591da177e4SLinus Torvalds return sizeof(caching_pg); 13601da177e4SLinus Torvalds } 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) 13631da177e4SLinus Torvalds { /* Control mode page for mode_sense */ 1364c65b1445SDouglas Gilbert unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0, 1365c65b1445SDouglas Gilbert 0, 0, 0, 0}; 1366c65b1445SDouglas Gilbert unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 13671da177e4SLinus Torvalds 0, 0, 0x2, 0x4b}; 13681da177e4SLinus Torvalds 13691da177e4SLinus Torvalds if (scsi_debug_dsense) 13701da177e4SLinus Torvalds ctrl_m_pg[2] |= 0x4; 1371c65b1445SDouglas Gilbert else 1372c65b1445SDouglas Gilbert ctrl_m_pg[2] &= ~0x4; 1373c6a44287SMartin K. Petersen 1374c6a44287SMartin K. Petersen if (scsi_debug_ato) 1375c6a44287SMartin K. Petersen ctrl_m_pg[5] |= 0x80; /* ATO=1 */ 1376c6a44287SMartin K. Petersen 13771da177e4SLinus Torvalds memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg)); 13781da177e4SLinus Torvalds if (1 == pcontrol) 1379c65b1445SDouglas Gilbert memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg)); 1380c65b1445SDouglas Gilbert else if (2 == pcontrol) 1381c65b1445SDouglas Gilbert memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg)); 13821da177e4SLinus Torvalds return sizeof(ctrl_m_pg); 13831da177e4SLinus Torvalds } 13841da177e4SLinus Torvalds 1385c65b1445SDouglas Gilbert 13861da177e4SLinus Torvalds static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target) 13871da177e4SLinus Torvalds { /* Informational Exceptions control mode page for mode_sense */ 1388c65b1445SDouglas Gilbert unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0, 13891da177e4SLinus Torvalds 0, 0, 0x0, 0x0}; 1390c65b1445SDouglas Gilbert unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, 1391c65b1445SDouglas Gilbert 0, 0, 0x0, 0x0}; 1392c65b1445SDouglas Gilbert 13931da177e4SLinus Torvalds memcpy(p, iec_m_pg, sizeof(iec_m_pg)); 13941da177e4SLinus Torvalds if (1 == pcontrol) 1395c65b1445SDouglas Gilbert memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg)); 1396c65b1445SDouglas Gilbert else if (2 == pcontrol) 1397c65b1445SDouglas Gilbert memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg)); 13981da177e4SLinus Torvalds return sizeof(iec_m_pg); 13991da177e4SLinus Torvalds } 14001da177e4SLinus Torvalds 1401c65b1445SDouglas Gilbert static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target) 1402c65b1445SDouglas Gilbert { /* SAS SSP mode page - short format for mode_sense */ 1403c65b1445SDouglas Gilbert unsigned char sas_sf_m_pg[] = {0x19, 0x6, 1404c65b1445SDouglas Gilbert 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0}; 1405c65b1445SDouglas Gilbert 1406c65b1445SDouglas Gilbert memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg)); 1407c65b1445SDouglas Gilbert if (1 == pcontrol) 1408c65b1445SDouglas Gilbert memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2); 1409c65b1445SDouglas Gilbert return sizeof(sas_sf_m_pg); 1410c65b1445SDouglas Gilbert } 1411c65b1445SDouglas Gilbert 1412c65b1445SDouglas Gilbert 1413c65b1445SDouglas Gilbert static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target, 1414c65b1445SDouglas Gilbert int target_dev_id) 1415c65b1445SDouglas Gilbert { /* SAS phy control and discover mode page for mode_sense */ 1416c65b1445SDouglas Gilbert unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2, 1417c65b1445SDouglas Gilbert 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0, 1418c65b1445SDouglas Gilbert 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0, 1419c65b1445SDouglas Gilbert 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1, 1420c65b1445SDouglas Gilbert 0x2, 0, 0, 0, 0, 0, 0, 0, 1421c65b1445SDouglas Gilbert 0x88, 0x99, 0, 0, 0, 0, 0, 0, 1422c65b1445SDouglas Gilbert 0, 0, 0, 0, 0, 0, 0, 0, 1423c65b1445SDouglas Gilbert 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0, 1424c65b1445SDouglas Gilbert 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0, 1425c65b1445SDouglas Gilbert 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1, 1426c65b1445SDouglas Gilbert 0x3, 0, 0, 0, 0, 0, 0, 0, 1427c65b1445SDouglas Gilbert 0x88, 0x99, 0, 0, 0, 0, 0, 0, 1428c65b1445SDouglas Gilbert 0, 0, 0, 0, 0, 0, 0, 0, 1429c65b1445SDouglas Gilbert }; 1430c65b1445SDouglas Gilbert int port_a, port_b; 1431c65b1445SDouglas Gilbert 1432c65b1445SDouglas Gilbert port_a = target_dev_id + 1; 1433c65b1445SDouglas Gilbert port_b = port_a + 1; 1434c65b1445SDouglas Gilbert memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg)); 1435c65b1445SDouglas Gilbert p[20] = (port_a >> 24); 1436c65b1445SDouglas Gilbert p[21] = (port_a >> 16) & 0xff; 1437c65b1445SDouglas Gilbert p[22] = (port_a >> 8) & 0xff; 1438c65b1445SDouglas Gilbert p[23] = port_a & 0xff; 1439c65b1445SDouglas Gilbert p[48 + 20] = (port_b >> 24); 1440c65b1445SDouglas Gilbert p[48 + 21] = (port_b >> 16) & 0xff; 1441c65b1445SDouglas Gilbert p[48 + 22] = (port_b >> 8) & 0xff; 1442c65b1445SDouglas Gilbert p[48 + 23] = port_b & 0xff; 1443c65b1445SDouglas Gilbert if (1 == pcontrol) 1444c65b1445SDouglas Gilbert memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4); 1445c65b1445SDouglas Gilbert return sizeof(sas_pcd_m_pg); 1446c65b1445SDouglas Gilbert } 1447c65b1445SDouglas Gilbert 1448c65b1445SDouglas Gilbert static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol) 1449c65b1445SDouglas Gilbert { /* SAS SSP shared protocol specific port mode subpage */ 1450c65b1445SDouglas Gilbert unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0, 1451c65b1445SDouglas Gilbert 0, 0, 0, 0, 0, 0, 0, 0, 1452c65b1445SDouglas Gilbert }; 1453c65b1445SDouglas Gilbert 1454c65b1445SDouglas Gilbert memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg)); 1455c65b1445SDouglas Gilbert if (1 == pcontrol) 1456c65b1445SDouglas Gilbert memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4); 1457c65b1445SDouglas Gilbert return sizeof(sas_sha_m_pg); 1458c65b1445SDouglas Gilbert } 1459c65b1445SDouglas Gilbert 14601da177e4SLinus Torvalds #define SDEBUG_MAX_MSENSE_SZ 256 14611da177e4SLinus Torvalds 14621da177e4SLinus Torvalds static int resp_mode_sense(struct scsi_cmnd * scp, int target, 14631da177e4SLinus Torvalds struct sdebug_dev_info * devip) 14641da177e4SLinus Torvalds { 146523183910SDouglas Gilbert unsigned char dbd, llbaa; 146623183910SDouglas Gilbert int pcontrol, pcode, subpcode, bd_len; 14671da177e4SLinus Torvalds unsigned char dev_spec; 146823183910SDouglas Gilbert int k, alloc_len, msense_6, offset, len, errsts, target_dev_id; 14691da177e4SLinus Torvalds unsigned char * ap; 14701da177e4SLinus Torvalds unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; 147101123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 14721da177e4SLinus Torvalds 1473cbf67842SDouglas Gilbert errsts = check_readiness(scp, UAS_ONLY, devip); 1474cbf67842SDouglas Gilbert if (errsts) 14751da177e4SLinus Torvalds return errsts; 147623183910SDouglas Gilbert dbd = !!(cmd[1] & 0x8); 14771da177e4SLinus Torvalds pcontrol = (cmd[2] & 0xc0) >> 6; 14781da177e4SLinus Torvalds pcode = cmd[2] & 0x3f; 14791da177e4SLinus Torvalds subpcode = cmd[3]; 14801da177e4SLinus Torvalds msense_6 = (MODE_SENSE == cmd[0]); 148123183910SDouglas Gilbert llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10); 148223183910SDouglas Gilbert if ((0 == scsi_debug_ptype) && (0 == dbd)) 148323183910SDouglas Gilbert bd_len = llbaa ? 16 : 8; 148423183910SDouglas Gilbert else 148523183910SDouglas Gilbert bd_len = 0; 14861da177e4SLinus Torvalds alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]); 14871da177e4SLinus Torvalds memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); 14881da177e4SLinus Torvalds if (0x3 == pcontrol) { /* Saving values not supported */ 1489cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0); 14901da177e4SLinus Torvalds return check_condition_result; 14911da177e4SLinus Torvalds } 1492c65b1445SDouglas Gilbert target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + 1493c65b1445SDouglas Gilbert (devip->target * 1000) - 3; 149423183910SDouglas Gilbert /* set DPOFUA bit for disks */ 149523183910SDouglas Gilbert if (0 == scsi_debug_ptype) 149623183910SDouglas Gilbert dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10; 149723183910SDouglas Gilbert else 149823183910SDouglas Gilbert dev_spec = 0x0; 14991da177e4SLinus Torvalds if (msense_6) { 15001da177e4SLinus Torvalds arr[2] = dev_spec; 150123183910SDouglas Gilbert arr[3] = bd_len; 15021da177e4SLinus Torvalds offset = 4; 15031da177e4SLinus Torvalds } else { 15041da177e4SLinus Torvalds arr[3] = dev_spec; 150523183910SDouglas Gilbert if (16 == bd_len) 150623183910SDouglas Gilbert arr[4] = 0x1; /* set LONGLBA bit */ 150723183910SDouglas Gilbert arr[7] = bd_len; /* assume 255 or less */ 15081da177e4SLinus Torvalds offset = 8; 15091da177e4SLinus Torvalds } 15101da177e4SLinus Torvalds ap = arr + offset; 151128898873SFUJITA Tomonori if ((bd_len > 0) && (!sdebug_capacity)) 151228898873SFUJITA Tomonori sdebug_capacity = get_sdebug_capacity(); 151328898873SFUJITA Tomonori 151423183910SDouglas Gilbert if (8 == bd_len) { 151523183910SDouglas Gilbert if (sdebug_capacity > 0xfffffffe) { 151623183910SDouglas Gilbert ap[0] = 0xff; 151723183910SDouglas Gilbert ap[1] = 0xff; 151823183910SDouglas Gilbert ap[2] = 0xff; 151923183910SDouglas Gilbert ap[3] = 0xff; 152023183910SDouglas Gilbert } else { 152123183910SDouglas Gilbert ap[0] = (sdebug_capacity >> 24) & 0xff; 152223183910SDouglas Gilbert ap[1] = (sdebug_capacity >> 16) & 0xff; 152323183910SDouglas Gilbert ap[2] = (sdebug_capacity >> 8) & 0xff; 152423183910SDouglas Gilbert ap[3] = sdebug_capacity & 0xff; 152523183910SDouglas Gilbert } 1526597136abSMartin K. Petersen ap[6] = (scsi_debug_sector_size >> 8) & 0xff; 1527597136abSMartin K. Petersen ap[7] = scsi_debug_sector_size & 0xff; 152823183910SDouglas Gilbert offset += bd_len; 152923183910SDouglas Gilbert ap = arr + offset; 153023183910SDouglas Gilbert } else if (16 == bd_len) { 153123183910SDouglas Gilbert unsigned long long capac = sdebug_capacity; 153223183910SDouglas Gilbert 153323183910SDouglas Gilbert for (k = 0; k < 8; ++k, capac >>= 8) 153423183910SDouglas Gilbert ap[7 - k] = capac & 0xff; 1535597136abSMartin K. Petersen ap[12] = (scsi_debug_sector_size >> 24) & 0xff; 1536597136abSMartin K. Petersen ap[13] = (scsi_debug_sector_size >> 16) & 0xff; 1537597136abSMartin K. Petersen ap[14] = (scsi_debug_sector_size >> 8) & 0xff; 1538597136abSMartin K. Petersen ap[15] = scsi_debug_sector_size & 0xff; 153923183910SDouglas Gilbert offset += bd_len; 154023183910SDouglas Gilbert ap = arr + offset; 154123183910SDouglas Gilbert } 15421da177e4SLinus Torvalds 1543c65b1445SDouglas Gilbert if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) { 1544c65b1445SDouglas Gilbert /* TODO: Control Extension page */ 1545cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 15461da177e4SLinus Torvalds 0); 15471da177e4SLinus Torvalds return check_condition_result; 15481da177e4SLinus Torvalds } 15491da177e4SLinus Torvalds switch (pcode) { 15501da177e4SLinus Torvalds case 0x1: /* Read-Write error recovery page, direct access */ 15511da177e4SLinus Torvalds len = resp_err_recov_pg(ap, pcontrol, target); 15521da177e4SLinus Torvalds offset += len; 15531da177e4SLinus Torvalds break; 15541da177e4SLinus Torvalds case 0x2: /* Disconnect-Reconnect page, all devices */ 15551da177e4SLinus Torvalds len = resp_disconnect_pg(ap, pcontrol, target); 15561da177e4SLinus Torvalds offset += len; 15571da177e4SLinus Torvalds break; 15581da177e4SLinus Torvalds case 0x3: /* Format device page, direct access */ 15591da177e4SLinus Torvalds len = resp_format_pg(ap, pcontrol, target); 15601da177e4SLinus Torvalds offset += len; 15611da177e4SLinus Torvalds break; 15621da177e4SLinus Torvalds case 0x8: /* Caching page, direct access */ 15631da177e4SLinus Torvalds len = resp_caching_pg(ap, pcontrol, target); 15641da177e4SLinus Torvalds offset += len; 15651da177e4SLinus Torvalds break; 15661da177e4SLinus Torvalds case 0xa: /* Control Mode page, all devices */ 15671da177e4SLinus Torvalds len = resp_ctrl_m_pg(ap, pcontrol, target); 15681da177e4SLinus Torvalds offset += len; 15691da177e4SLinus Torvalds break; 1570c65b1445SDouglas Gilbert case 0x19: /* if spc==1 then sas phy, control+discover */ 1571c65b1445SDouglas Gilbert if ((subpcode > 0x2) && (subpcode < 0xff)) { 1572cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1573c65b1445SDouglas Gilbert INVALID_FIELD_IN_CDB, 0); 1574c65b1445SDouglas Gilbert return check_condition_result; 1575c65b1445SDouglas Gilbert } 1576c65b1445SDouglas Gilbert len = 0; 1577c65b1445SDouglas Gilbert if ((0x0 == subpcode) || (0xff == subpcode)) 1578c65b1445SDouglas Gilbert len += resp_sas_sf_m_pg(ap + len, pcontrol, target); 1579c65b1445SDouglas Gilbert if ((0x1 == subpcode) || (0xff == subpcode)) 1580c65b1445SDouglas Gilbert len += resp_sas_pcd_m_spg(ap + len, pcontrol, target, 1581c65b1445SDouglas Gilbert target_dev_id); 1582c65b1445SDouglas Gilbert if ((0x2 == subpcode) || (0xff == subpcode)) 1583c65b1445SDouglas Gilbert len += resp_sas_sha_m_spg(ap + len, pcontrol); 1584c65b1445SDouglas Gilbert offset += len; 1585c65b1445SDouglas Gilbert break; 15861da177e4SLinus Torvalds case 0x1c: /* Informational Exceptions Mode page, all devices */ 15871da177e4SLinus Torvalds len = resp_iec_m_pg(ap, pcontrol, target); 15881da177e4SLinus Torvalds offset += len; 15891da177e4SLinus Torvalds break; 15901da177e4SLinus Torvalds case 0x3f: /* Read all Mode pages */ 1591c65b1445SDouglas Gilbert if ((0 == subpcode) || (0xff == subpcode)) { 15921da177e4SLinus Torvalds len = resp_err_recov_pg(ap, pcontrol, target); 15931da177e4SLinus Torvalds len += resp_disconnect_pg(ap + len, pcontrol, target); 15941da177e4SLinus Torvalds len += resp_format_pg(ap + len, pcontrol, target); 15951da177e4SLinus Torvalds len += resp_caching_pg(ap + len, pcontrol, target); 15961da177e4SLinus Torvalds len += resp_ctrl_m_pg(ap + len, pcontrol, target); 1597c65b1445SDouglas Gilbert len += resp_sas_sf_m_pg(ap + len, pcontrol, target); 1598c65b1445SDouglas Gilbert if (0xff == subpcode) { 1599c65b1445SDouglas Gilbert len += resp_sas_pcd_m_spg(ap + len, pcontrol, 1600c65b1445SDouglas Gilbert target, target_dev_id); 1601c65b1445SDouglas Gilbert len += resp_sas_sha_m_spg(ap + len, pcontrol); 1602c65b1445SDouglas Gilbert } 16031da177e4SLinus Torvalds len += resp_iec_m_pg(ap + len, pcontrol, target); 1604c65b1445SDouglas Gilbert } else { 1605cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1606c65b1445SDouglas Gilbert INVALID_FIELD_IN_CDB, 0); 1607c65b1445SDouglas Gilbert return check_condition_result; 1608c65b1445SDouglas Gilbert } 16091da177e4SLinus Torvalds offset += len; 16101da177e4SLinus Torvalds break; 16111da177e4SLinus Torvalds default: 1612cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 16131da177e4SLinus Torvalds 0); 16141da177e4SLinus Torvalds return check_condition_result; 16151da177e4SLinus Torvalds } 16161da177e4SLinus Torvalds if (msense_6) 16171da177e4SLinus Torvalds arr[0] = offset - 1; 16181da177e4SLinus Torvalds else { 16191da177e4SLinus Torvalds arr[0] = ((offset - 2) >> 8) & 0xff; 16201da177e4SLinus Torvalds arr[1] = (offset - 2) & 0xff; 16211da177e4SLinus Torvalds } 16221da177e4SLinus Torvalds return fill_from_dev_buffer(scp, arr, min(alloc_len, offset)); 16231da177e4SLinus Torvalds } 16241da177e4SLinus Torvalds 1625c65b1445SDouglas Gilbert #define SDEBUG_MAX_MSELECT_SZ 512 1626c65b1445SDouglas Gilbert 1627c65b1445SDouglas Gilbert static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, 1628c65b1445SDouglas Gilbert struct sdebug_dev_info * devip) 1629c65b1445SDouglas Gilbert { 1630c65b1445SDouglas Gilbert int pf, sp, ps, md_len, bd_len, off, spf, pg_len; 1631c65b1445SDouglas Gilbert int param_len, res, errsts, mpage; 1632c65b1445SDouglas Gilbert unsigned char arr[SDEBUG_MAX_MSELECT_SZ]; 163301123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 1634c65b1445SDouglas Gilbert 1635cbf67842SDouglas Gilbert errsts = check_readiness(scp, UAS_ONLY, devip); 1636cbf67842SDouglas Gilbert if (errsts) 1637c65b1445SDouglas Gilbert return errsts; 1638c65b1445SDouglas Gilbert memset(arr, 0, sizeof(arr)); 1639c65b1445SDouglas Gilbert pf = cmd[1] & 0x10; 1640c65b1445SDouglas Gilbert sp = cmd[1] & 0x1; 1641c65b1445SDouglas Gilbert param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]); 1642c65b1445SDouglas Gilbert if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) { 1643cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1644c65b1445SDouglas Gilbert INVALID_FIELD_IN_CDB, 0); 1645c65b1445SDouglas Gilbert return check_condition_result; 1646c65b1445SDouglas Gilbert } 1647c65b1445SDouglas Gilbert res = fetch_to_dev_buffer(scp, arr, param_len); 1648c65b1445SDouglas Gilbert if (-1 == res) 1649c65b1445SDouglas Gilbert return (DID_ERROR << 16); 1650c65b1445SDouglas Gilbert else if ((res < param_len) && 1651c65b1445SDouglas Gilbert (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) 1652cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, scp->device, 1653cbf67842SDouglas Gilbert "%s: cdb indicated=%d, IO sent=%d bytes\n", 1654cbf67842SDouglas Gilbert __func__, param_len, res); 1655c65b1445SDouglas Gilbert md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2); 1656c65b1445SDouglas Gilbert bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]); 165723183910SDouglas Gilbert if (md_len > 2) { 1658cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1659c65b1445SDouglas Gilbert INVALID_FIELD_IN_PARAM_LIST, 0); 1660c65b1445SDouglas Gilbert return check_condition_result; 1661c65b1445SDouglas Gilbert } 1662c65b1445SDouglas Gilbert off = bd_len + (mselect6 ? 4 : 8); 1663c65b1445SDouglas Gilbert mpage = arr[off] & 0x3f; 1664c65b1445SDouglas Gilbert ps = !!(arr[off] & 0x80); 1665c65b1445SDouglas Gilbert if (ps) { 1666cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1667c65b1445SDouglas Gilbert INVALID_FIELD_IN_PARAM_LIST, 0); 1668c65b1445SDouglas Gilbert return check_condition_result; 1669c65b1445SDouglas Gilbert } 1670c65b1445SDouglas Gilbert spf = !!(arr[off] & 0x40); 1671c65b1445SDouglas Gilbert pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) : 1672c65b1445SDouglas Gilbert (arr[off + 1] + 2); 1673c65b1445SDouglas Gilbert if ((pg_len + off) > param_len) { 1674cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1675c65b1445SDouglas Gilbert PARAMETER_LIST_LENGTH_ERR, 0); 1676c65b1445SDouglas Gilbert return check_condition_result; 1677c65b1445SDouglas Gilbert } 1678c65b1445SDouglas Gilbert switch (mpage) { 1679cbf67842SDouglas Gilbert case 0x8: /* Caching Mode page */ 1680cbf67842SDouglas Gilbert if (caching_pg[1] == arr[off + 1]) { 1681cbf67842SDouglas Gilbert memcpy(caching_pg + 2, arr + off + 2, 1682cbf67842SDouglas Gilbert sizeof(caching_pg) - 2); 1683cbf67842SDouglas Gilbert goto set_mode_changed_ua; 1684cbf67842SDouglas Gilbert } 1685cbf67842SDouglas Gilbert break; 1686c65b1445SDouglas Gilbert case 0xa: /* Control Mode page */ 1687c65b1445SDouglas Gilbert if (ctrl_m_pg[1] == arr[off + 1]) { 1688c65b1445SDouglas Gilbert memcpy(ctrl_m_pg + 2, arr + off + 2, 1689c65b1445SDouglas Gilbert sizeof(ctrl_m_pg) - 2); 1690c65b1445SDouglas Gilbert scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4); 1691cbf67842SDouglas Gilbert goto set_mode_changed_ua; 1692c65b1445SDouglas Gilbert } 1693c65b1445SDouglas Gilbert break; 1694c65b1445SDouglas Gilbert case 0x1c: /* Informational Exceptions Mode page */ 1695c65b1445SDouglas Gilbert if (iec_m_pg[1] == arr[off + 1]) { 1696c65b1445SDouglas Gilbert memcpy(iec_m_pg + 2, arr + off + 2, 1697c65b1445SDouglas Gilbert sizeof(iec_m_pg) - 2); 1698cbf67842SDouglas Gilbert goto set_mode_changed_ua; 1699c65b1445SDouglas Gilbert } 1700c65b1445SDouglas Gilbert break; 1701c65b1445SDouglas Gilbert default: 1702c65b1445SDouglas Gilbert break; 1703c65b1445SDouglas Gilbert } 1704cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1705c65b1445SDouglas Gilbert INVALID_FIELD_IN_PARAM_LIST, 0); 1706c65b1445SDouglas Gilbert return check_condition_result; 1707cbf67842SDouglas Gilbert set_mode_changed_ua: 1708cbf67842SDouglas Gilbert set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm); 1709cbf67842SDouglas Gilbert return 0; 1710c65b1445SDouglas Gilbert } 1711c65b1445SDouglas Gilbert 1712c65b1445SDouglas Gilbert static int resp_temp_l_pg(unsigned char * arr) 1713c65b1445SDouglas Gilbert { 1714c65b1445SDouglas Gilbert unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38, 1715c65b1445SDouglas Gilbert 0x0, 0x1, 0x3, 0x2, 0x0, 65, 1716c65b1445SDouglas Gilbert }; 1717c65b1445SDouglas Gilbert 1718c65b1445SDouglas Gilbert memcpy(arr, temp_l_pg, sizeof(temp_l_pg)); 1719c65b1445SDouglas Gilbert return sizeof(temp_l_pg); 1720c65b1445SDouglas Gilbert } 1721c65b1445SDouglas Gilbert 1722c65b1445SDouglas Gilbert static int resp_ie_l_pg(unsigned char * arr) 1723c65b1445SDouglas Gilbert { 1724c65b1445SDouglas Gilbert unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38, 1725c65b1445SDouglas Gilbert }; 1726c65b1445SDouglas Gilbert 1727c65b1445SDouglas Gilbert memcpy(arr, ie_l_pg, sizeof(ie_l_pg)); 1728c65b1445SDouglas Gilbert if (iec_m_pg[2] & 0x4) { /* TEST bit set */ 1729c65b1445SDouglas Gilbert arr[4] = THRESHOLD_EXCEEDED; 1730c65b1445SDouglas Gilbert arr[5] = 0xff; 1731c65b1445SDouglas Gilbert } 1732c65b1445SDouglas Gilbert return sizeof(ie_l_pg); 1733c65b1445SDouglas Gilbert } 1734c65b1445SDouglas Gilbert 1735c65b1445SDouglas Gilbert #define SDEBUG_MAX_LSENSE_SZ 512 1736c65b1445SDouglas Gilbert 1737c65b1445SDouglas Gilbert static int resp_log_sense(struct scsi_cmnd * scp, 1738c65b1445SDouglas Gilbert struct sdebug_dev_info * devip) 1739c65b1445SDouglas Gilbert { 174023183910SDouglas Gilbert int ppc, sp, pcontrol, pcode, subpcode, alloc_len, errsts, len, n; 1741c65b1445SDouglas Gilbert unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; 174201123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 1743c65b1445SDouglas Gilbert 1744cbf67842SDouglas Gilbert errsts = check_readiness(scp, UAS_ONLY, devip); 1745cbf67842SDouglas Gilbert if (errsts) 1746c65b1445SDouglas Gilbert return errsts; 1747c65b1445SDouglas Gilbert memset(arr, 0, sizeof(arr)); 1748c65b1445SDouglas Gilbert ppc = cmd[1] & 0x2; 1749c65b1445SDouglas Gilbert sp = cmd[1] & 0x1; 1750c65b1445SDouglas Gilbert if (ppc || sp) { 1751cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1752c65b1445SDouglas Gilbert INVALID_FIELD_IN_CDB, 0); 1753c65b1445SDouglas Gilbert return check_condition_result; 1754c65b1445SDouglas Gilbert } 1755c65b1445SDouglas Gilbert pcontrol = (cmd[2] & 0xc0) >> 6; 1756c65b1445SDouglas Gilbert pcode = cmd[2] & 0x3f; 175723183910SDouglas Gilbert subpcode = cmd[3] & 0xff; 1758c65b1445SDouglas Gilbert alloc_len = (cmd[7] << 8) + cmd[8]; 1759c65b1445SDouglas Gilbert arr[0] = pcode; 176023183910SDouglas Gilbert if (0 == subpcode) { 1761c65b1445SDouglas Gilbert switch (pcode) { 1762c65b1445SDouglas Gilbert case 0x0: /* Supported log pages log page */ 1763c65b1445SDouglas Gilbert n = 4; 1764c65b1445SDouglas Gilbert arr[n++] = 0x0; /* this page */ 1765c65b1445SDouglas Gilbert arr[n++] = 0xd; /* Temperature */ 1766c65b1445SDouglas Gilbert arr[n++] = 0x2f; /* Informational exceptions */ 1767c65b1445SDouglas Gilbert arr[3] = n - 4; 1768c65b1445SDouglas Gilbert break; 1769c65b1445SDouglas Gilbert case 0xd: /* Temperature log page */ 1770c65b1445SDouglas Gilbert arr[3] = resp_temp_l_pg(arr + 4); 1771c65b1445SDouglas Gilbert break; 1772c65b1445SDouglas Gilbert case 0x2f: /* Informational exceptions log page */ 1773c65b1445SDouglas Gilbert arr[3] = resp_ie_l_pg(arr + 4); 1774c65b1445SDouglas Gilbert break; 1775c65b1445SDouglas Gilbert default: 1776cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 1777c65b1445SDouglas Gilbert INVALID_FIELD_IN_CDB, 0); 1778c65b1445SDouglas Gilbert return check_condition_result; 1779c65b1445SDouglas Gilbert } 178023183910SDouglas Gilbert } else if (0xff == subpcode) { 178123183910SDouglas Gilbert arr[0] |= 0x40; 178223183910SDouglas Gilbert arr[1] = subpcode; 178323183910SDouglas Gilbert switch (pcode) { 178423183910SDouglas Gilbert case 0x0: /* Supported log pages and subpages log page */ 178523183910SDouglas Gilbert n = 4; 178623183910SDouglas Gilbert arr[n++] = 0x0; 178723183910SDouglas Gilbert arr[n++] = 0x0; /* 0,0 page */ 178823183910SDouglas Gilbert arr[n++] = 0x0; 178923183910SDouglas Gilbert arr[n++] = 0xff; /* this page */ 179023183910SDouglas Gilbert arr[n++] = 0xd; 179123183910SDouglas Gilbert arr[n++] = 0x0; /* Temperature */ 179223183910SDouglas Gilbert arr[n++] = 0x2f; 179323183910SDouglas Gilbert arr[n++] = 0x0; /* Informational exceptions */ 179423183910SDouglas Gilbert arr[3] = n - 4; 179523183910SDouglas Gilbert break; 179623183910SDouglas Gilbert case 0xd: /* Temperature subpages */ 179723183910SDouglas Gilbert n = 4; 179823183910SDouglas Gilbert arr[n++] = 0xd; 179923183910SDouglas Gilbert arr[n++] = 0x0; /* Temperature */ 180023183910SDouglas Gilbert arr[3] = n - 4; 180123183910SDouglas Gilbert break; 180223183910SDouglas Gilbert case 0x2f: /* Informational exceptions subpages */ 180323183910SDouglas Gilbert n = 4; 180423183910SDouglas Gilbert arr[n++] = 0x2f; 180523183910SDouglas Gilbert arr[n++] = 0x0; /* Informational exceptions */ 180623183910SDouglas Gilbert arr[3] = n - 4; 180723183910SDouglas Gilbert break; 180823183910SDouglas Gilbert default: 1809cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 181023183910SDouglas Gilbert INVALID_FIELD_IN_CDB, 0); 181123183910SDouglas Gilbert return check_condition_result; 181223183910SDouglas Gilbert } 181323183910SDouglas Gilbert } else { 1814cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, 181523183910SDouglas Gilbert INVALID_FIELD_IN_CDB, 0); 181623183910SDouglas Gilbert return check_condition_result; 181723183910SDouglas Gilbert } 1818c65b1445SDouglas Gilbert len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); 1819c65b1445SDouglas Gilbert return fill_from_dev_buffer(scp, arr, 1820c65b1445SDouglas Gilbert min(len, SDEBUG_MAX_INQ_ARR_SZ)); 1821c65b1445SDouglas Gilbert } 1822c65b1445SDouglas Gilbert 1823cbf67842SDouglas Gilbert static int check_device_access_params(struct scsi_cmnd *scp, 182419789100SFUJITA Tomonori unsigned long long lba, unsigned int num) 18251da177e4SLinus Torvalds { 1826c65b1445SDouglas Gilbert if (lba + num > sdebug_capacity) { 1827cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0); 18281da177e4SLinus Torvalds return check_condition_result; 18291da177e4SLinus Torvalds } 1830c65b1445SDouglas Gilbert /* transfer length excessive (tie in to block limits VPD page) */ 1831c65b1445SDouglas Gilbert if (num > sdebug_store_sectors) { 1832cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); 1833c65b1445SDouglas Gilbert return check_condition_result; 1834c65b1445SDouglas Gilbert } 183519789100SFUJITA Tomonori return 0; 183619789100SFUJITA Tomonori } 183719789100SFUJITA Tomonori 1838a4517511SAkinobu Mita /* Returns number of bytes copied or -1 if error. */ 183919789100SFUJITA Tomonori static int do_device_access(struct scsi_cmnd *scmd, 184019789100SFUJITA Tomonori unsigned long long lba, unsigned int num, int write) 184119789100SFUJITA Tomonori { 184219789100SFUJITA Tomonori int ret; 1843a361cc00SDarrick J. Wong unsigned long long block, rest = 0; 1844a4517511SAkinobu Mita struct scsi_data_buffer *sdb; 1845a4517511SAkinobu Mita enum dma_data_direction dir; 1846a4517511SAkinobu Mita size_t (*func)(struct scatterlist *, unsigned int, void *, size_t, 1847a4517511SAkinobu Mita off_t); 184819789100SFUJITA Tomonori 1849a4517511SAkinobu Mita if (write) { 1850a4517511SAkinobu Mita sdb = scsi_out(scmd); 1851a4517511SAkinobu Mita dir = DMA_TO_DEVICE; 1852a4517511SAkinobu Mita func = sg_pcopy_to_buffer; 1853a4517511SAkinobu Mita } else { 1854a4517511SAkinobu Mita sdb = scsi_in(scmd); 1855a4517511SAkinobu Mita dir = DMA_FROM_DEVICE; 1856a4517511SAkinobu Mita func = sg_pcopy_from_buffer; 1857a4517511SAkinobu Mita } 1858a4517511SAkinobu Mita 1859a4517511SAkinobu Mita if (!sdb->length) 1860a4517511SAkinobu Mita return 0; 1861a4517511SAkinobu Mita if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir)) 1862a4517511SAkinobu Mita return -1; 186319789100SFUJITA Tomonori 186419789100SFUJITA Tomonori block = do_div(lba, sdebug_store_sectors); 186519789100SFUJITA Tomonori if (block + num > sdebug_store_sectors) 186619789100SFUJITA Tomonori rest = block + num - sdebug_store_sectors; 186719789100SFUJITA Tomonori 1868a4517511SAkinobu Mita ret = func(sdb->table.sgl, sdb->table.nents, 1869a4517511SAkinobu Mita fake_storep + (block * scsi_debug_sector_size), 1870a4517511SAkinobu Mita (num - rest) * scsi_debug_sector_size, 0); 1871a4517511SAkinobu Mita if (ret != (num - rest) * scsi_debug_sector_size) 1872a4517511SAkinobu Mita return ret; 1873a4517511SAkinobu Mita 1874a4517511SAkinobu Mita if (rest) { 1875a4517511SAkinobu Mita ret += func(sdb->table.sgl, sdb->table.nents, 1876a4517511SAkinobu Mita fake_storep, rest * scsi_debug_sector_size, 1877597136abSMartin K. Petersen (num - rest) * scsi_debug_sector_size); 1878a4517511SAkinobu Mita } 187919789100SFUJITA Tomonori 188019789100SFUJITA Tomonori return ret; 188119789100SFUJITA Tomonori } 188219789100SFUJITA Tomonori 188351d648afSAkinobu Mita static __be16 dif_compute_csum(const void *buf, int len) 1884beb40ea4SAkinobu Mita { 188551d648afSAkinobu Mita __be16 csum; 1886beb40ea4SAkinobu Mita 188751d648afSAkinobu Mita if (scsi_debug_guard) 188851d648afSAkinobu Mita csum = (__force __be16)ip_compute_csum(buf, len); 188951d648afSAkinobu Mita else 1890beb40ea4SAkinobu Mita csum = cpu_to_be16(crc_t10dif(buf, len)); 189151d648afSAkinobu Mita 1892beb40ea4SAkinobu Mita return csum; 1893beb40ea4SAkinobu Mita } 1894beb40ea4SAkinobu Mita 1895beb40ea4SAkinobu Mita static int dif_verify(struct sd_dif_tuple *sdt, const void *data, 1896beb40ea4SAkinobu Mita sector_t sector, u32 ei_lba) 1897beb40ea4SAkinobu Mita { 189851d648afSAkinobu Mita __be16 csum = dif_compute_csum(data, scsi_debug_sector_size); 1899beb40ea4SAkinobu Mita 1900beb40ea4SAkinobu Mita if (sdt->guard_tag != csum) { 1901beb40ea4SAkinobu Mita pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", 1902beb40ea4SAkinobu Mita __func__, 1903beb40ea4SAkinobu Mita (unsigned long)sector, 1904beb40ea4SAkinobu Mita be16_to_cpu(sdt->guard_tag), 1905beb40ea4SAkinobu Mita be16_to_cpu(csum)); 1906beb40ea4SAkinobu Mita return 0x01; 1907beb40ea4SAkinobu Mita } 1908beb40ea4SAkinobu Mita if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && 1909beb40ea4SAkinobu Mita be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { 1910beb40ea4SAkinobu Mita pr_err("%s: REF check failed on sector %lu\n", 1911beb40ea4SAkinobu Mita __func__, (unsigned long)sector); 1912beb40ea4SAkinobu Mita return 0x03; 1913beb40ea4SAkinobu Mita } 1914beb40ea4SAkinobu Mita if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && 1915beb40ea4SAkinobu Mita be32_to_cpu(sdt->ref_tag) != ei_lba) { 1916beb40ea4SAkinobu Mita pr_err("%s: REF check failed on sector %lu\n", 1917beb40ea4SAkinobu Mita __func__, (unsigned long)sector); 1918beb40ea4SAkinobu Mita return 0x03; 1919beb40ea4SAkinobu Mita } 1920beb40ea4SAkinobu Mita return 0; 1921beb40ea4SAkinobu Mita } 1922beb40ea4SAkinobu Mita 1923bb8c063cSAkinobu Mita static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector, 192465f72f2aSAkinobu Mita unsigned int sectors, bool read) 1925c6a44287SMartin K. Petersen { 1926be4e11beSAkinobu Mita size_t resid; 1927c6a44287SMartin K. Petersen void *paddr; 192814faa944SAkinobu Mita const void *dif_store_end = dif_storep + sdebug_store_sectors; 1929be4e11beSAkinobu Mita struct sg_mapping_iter miter; 1930c6a44287SMartin K. Petersen 1931e18d8beaSAkinobu Mita /* Bytes of protection data to copy into sgl */ 1932e18d8beaSAkinobu Mita resid = sectors * sizeof(*dif_storep); 1933c6a44287SMartin K. Petersen 1934be4e11beSAkinobu Mita sg_miter_start(&miter, scsi_prot_sglist(SCpnt), 1935be4e11beSAkinobu Mita scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC | 1936be4e11beSAkinobu Mita (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG)); 1937be4e11beSAkinobu Mita 1938be4e11beSAkinobu Mita while (sg_miter_next(&miter) && resid > 0) { 1939be4e11beSAkinobu Mita size_t len = min(miter.length, resid); 194014faa944SAkinobu Mita void *start = dif_store(sector); 1941be4e11beSAkinobu Mita size_t rest = 0; 194214faa944SAkinobu Mita 194314faa944SAkinobu Mita if (dif_store_end < start + len) 194414faa944SAkinobu Mita rest = start + len - dif_store_end; 1945c6a44287SMartin K. Petersen 1946be4e11beSAkinobu Mita paddr = miter.addr; 194714faa944SAkinobu Mita 194865f72f2aSAkinobu Mita if (read) 194965f72f2aSAkinobu Mita memcpy(paddr, start, len - rest); 195065f72f2aSAkinobu Mita else 195165f72f2aSAkinobu Mita memcpy(start, paddr, len - rest); 195265f72f2aSAkinobu Mita 195365f72f2aSAkinobu Mita if (rest) { 195465f72f2aSAkinobu Mita if (read) 195514faa944SAkinobu Mita memcpy(paddr + len - rest, dif_storep, rest); 195665f72f2aSAkinobu Mita else 195765f72f2aSAkinobu Mita memcpy(dif_storep, paddr + len - rest, rest); 195865f72f2aSAkinobu Mita } 1959c6a44287SMartin K. Petersen 1960e18d8beaSAkinobu Mita sector += len / sizeof(*dif_storep); 1961c6a44287SMartin K. Petersen resid -= len; 1962c6a44287SMartin K. Petersen } 1963be4e11beSAkinobu Mita sg_miter_stop(&miter); 1964bb8c063cSAkinobu Mita } 1965c6a44287SMartin K. Petersen 1966bb8c063cSAkinobu Mita static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, 1967bb8c063cSAkinobu Mita unsigned int sectors, u32 ei_lba) 1968bb8c063cSAkinobu Mita { 1969bb8c063cSAkinobu Mita unsigned int i; 1970bb8c063cSAkinobu Mita struct sd_dif_tuple *sdt; 1971bb8c063cSAkinobu Mita sector_t sector; 1972bb8c063cSAkinobu Mita 1973c45eabecSAkinobu Mita for (i = 0; i < sectors; i++, ei_lba++) { 1974bb8c063cSAkinobu Mita int ret; 1975bb8c063cSAkinobu Mita 1976bb8c063cSAkinobu Mita sector = start_sec + i; 1977bb8c063cSAkinobu Mita sdt = dif_store(sector); 1978bb8c063cSAkinobu Mita 197951d648afSAkinobu Mita if (sdt->app_tag == cpu_to_be16(0xffff)) 1980bb8c063cSAkinobu Mita continue; 1981bb8c063cSAkinobu Mita 1982bb8c063cSAkinobu Mita ret = dif_verify(sdt, fake_store(sector), sector, ei_lba); 1983bb8c063cSAkinobu Mita if (ret) { 1984bb8c063cSAkinobu Mita dif_errors++; 1985bb8c063cSAkinobu Mita return ret; 1986bb8c063cSAkinobu Mita } 1987bb8c063cSAkinobu Mita } 1988bb8c063cSAkinobu Mita 198965f72f2aSAkinobu Mita dif_copy_prot(SCpnt, start_sec, sectors, true); 1990c6a44287SMartin K. Petersen dix_reads++; 1991c6a44287SMartin K. Petersen 1992c6a44287SMartin K. Petersen return 0; 1993c6a44287SMartin K. Petersen } 1994c6a44287SMartin K. Petersen 199519789100SFUJITA Tomonori static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, 1996cbf67842SDouglas Gilbert unsigned int num, u32 ei_lba) 199719789100SFUJITA Tomonori { 199819789100SFUJITA Tomonori unsigned long iflags; 199919789100SFUJITA Tomonori int ret; 200019789100SFUJITA Tomonori 2001cbf67842SDouglas Gilbert ret = check_device_access_params(SCpnt, lba, num); 200219789100SFUJITA Tomonori if (ret) 200319789100SFUJITA Tomonori return ret; 200419789100SFUJITA Tomonori 20051da177e4SLinus Torvalds if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && 200632f7ef73SDouglas Gilbert (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && 2007c65b1445SDouglas Gilbert ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { 2008c65b1445SDouglas Gilbert /* claim unrecoverable read error */ 2009cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); 2010c65b1445SDouglas Gilbert /* set info field and valid bit for fixed descriptor */ 2011cbf67842SDouglas Gilbert if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) { 2012cbf67842SDouglas Gilbert SCpnt->sense_buffer[0] |= 0x80; /* Valid bit */ 201332f7ef73SDouglas Gilbert ret = (lba < OPT_MEDIUM_ERR_ADDR) 201432f7ef73SDouglas Gilbert ? OPT_MEDIUM_ERR_ADDR : (int)lba; 2015cbf67842SDouglas Gilbert SCpnt->sense_buffer[3] = (ret >> 24) & 0xff; 2016cbf67842SDouglas Gilbert SCpnt->sense_buffer[4] = (ret >> 16) & 0xff; 2017cbf67842SDouglas Gilbert SCpnt->sense_buffer[5] = (ret >> 8) & 0xff; 2018cbf67842SDouglas Gilbert SCpnt->sense_buffer[6] = ret & 0xff; 2019c65b1445SDouglas Gilbert } 2020a87e3a67SDouglas Gilbert scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); 20211da177e4SLinus Torvalds return check_condition_result; 20221da177e4SLinus Torvalds } 2023c6a44287SMartin K. Petersen 20246c78cc06SAkinobu Mita read_lock_irqsave(&atomic_rw, iflags); 20256c78cc06SAkinobu Mita 2026c6a44287SMartin K. Petersen /* DIX + T10 DIF */ 2027c6a44287SMartin K. Petersen if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { 2028395cef03SMartin K. Petersen int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba); 2029c6a44287SMartin K. Petersen 2030c6a44287SMartin K. Petersen if (prot_ret) { 20316c78cc06SAkinobu Mita read_unlock_irqrestore(&atomic_rw, iflags); 2032cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret); 2033c6a44287SMartin K. Petersen return illegal_condition_result; 2034c6a44287SMartin K. Petersen } 2035c6a44287SMartin K. Petersen } 2036c6a44287SMartin K. Petersen 2037cbf67842SDouglas Gilbert ret = do_device_access(SCpnt, lba, num, 0); 20381da177e4SLinus Torvalds read_unlock_irqrestore(&atomic_rw, iflags); 2039a4517511SAkinobu Mita if (ret == -1) 2040a4517511SAkinobu Mita return DID_ERROR << 16; 2041a4517511SAkinobu Mita 2042a4517511SAkinobu Mita scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret; 2043a4517511SAkinobu Mita 2044a4517511SAkinobu Mita return 0; 20451da177e4SLinus Torvalds } 20461da177e4SLinus Torvalds 2047c6a44287SMartin K. Petersen void dump_sector(unsigned char *buf, int len) 2048c6a44287SMartin K. Petersen { 2049cbf67842SDouglas Gilbert int i, j, n; 2050c6a44287SMartin K. Petersen 2051cbf67842SDouglas Gilbert pr_err(">>> Sector Dump <<<\n"); 2052c6a44287SMartin K. Petersen for (i = 0 ; i < len ; i += 16) { 2053cbf67842SDouglas Gilbert char b[128]; 2054c6a44287SMartin K. Petersen 2055cbf67842SDouglas Gilbert for (j = 0, n = 0; j < 16; j++) { 2056c6a44287SMartin K. Petersen unsigned char c = buf[i+j]; 2057c6a44287SMartin K. Petersen 2058cbf67842SDouglas Gilbert if (c >= 0x20 && c < 0x7e) 2059cbf67842SDouglas Gilbert n += scnprintf(b + n, sizeof(b) - n, 2060cbf67842SDouglas Gilbert " %c ", buf[i+j]); 2061cbf67842SDouglas Gilbert else 2062cbf67842SDouglas Gilbert n += scnprintf(b + n, sizeof(b) - n, 2063cbf67842SDouglas Gilbert "%02x ", buf[i+j]); 2064cbf67842SDouglas Gilbert } 2065cbf67842SDouglas Gilbert pr_err("%04d: %s\n", i, b); 2066c6a44287SMartin K. Petersen } 2067c6a44287SMartin K. Petersen } 2068c6a44287SMartin K. Petersen 2069c6a44287SMartin K. Petersen static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, 2070395cef03SMartin K. Petersen unsigned int sectors, u32 ei_lba) 2071c6a44287SMartin K. Petersen { 2072be4e11beSAkinobu Mita int ret; 2073c6a44287SMartin K. Petersen struct sd_dif_tuple *sdt; 2074be4e11beSAkinobu Mita void *daddr; 207565f72f2aSAkinobu Mita sector_t sector = start_sec; 2076c6a44287SMartin K. Petersen int ppage_offset; 2077be4e11beSAkinobu Mita int dpage_offset; 2078be4e11beSAkinobu Mita struct sg_mapping_iter diter; 2079be4e11beSAkinobu Mita struct sg_mapping_iter piter; 2080c6a44287SMartin K. Petersen 2081c6a44287SMartin K. Petersen BUG_ON(scsi_sg_count(SCpnt) == 0); 2082c6a44287SMartin K. Petersen BUG_ON(scsi_prot_sg_count(SCpnt) == 0); 2083c6a44287SMartin K. Petersen 2084be4e11beSAkinobu Mita sg_miter_start(&piter, scsi_prot_sglist(SCpnt), 2085be4e11beSAkinobu Mita scsi_prot_sg_count(SCpnt), 2086be4e11beSAkinobu Mita SG_MITER_ATOMIC | SG_MITER_FROM_SG); 2087be4e11beSAkinobu Mita sg_miter_start(&diter, scsi_sglist(SCpnt), scsi_sg_count(SCpnt), 2088be4e11beSAkinobu Mita SG_MITER_ATOMIC | SG_MITER_FROM_SG); 2089c6a44287SMartin K. Petersen 2090be4e11beSAkinobu Mita /* For each protection page */ 2091be4e11beSAkinobu Mita while (sg_miter_next(&piter)) { 2092be4e11beSAkinobu Mita dpage_offset = 0; 2093be4e11beSAkinobu Mita if (WARN_ON(!sg_miter_next(&diter))) { 2094be4e11beSAkinobu Mita ret = 0x01; 2095be4e11beSAkinobu Mita goto out; 2096c6a44287SMartin K. Petersen } 2097c6a44287SMartin K. Petersen 2098be4e11beSAkinobu Mita for (ppage_offset = 0; ppage_offset < piter.length; 2099be4e11beSAkinobu Mita ppage_offset += sizeof(struct sd_dif_tuple)) { 2100be4e11beSAkinobu Mita /* If we're at the end of the current 2101be4e11beSAkinobu Mita * data page advance to the next one 2102be4e11beSAkinobu Mita */ 2103be4e11beSAkinobu Mita if (dpage_offset >= diter.length) { 2104be4e11beSAkinobu Mita if (WARN_ON(!sg_miter_next(&diter))) { 2105be4e11beSAkinobu Mita ret = 0x01; 2106be4e11beSAkinobu Mita goto out; 2107be4e11beSAkinobu Mita } 2108be4e11beSAkinobu Mita dpage_offset = 0; 2109be4e11beSAkinobu Mita } 2110c6a44287SMartin K. Petersen 2111be4e11beSAkinobu Mita sdt = piter.addr + ppage_offset; 2112be4e11beSAkinobu Mita daddr = diter.addr + dpage_offset; 2113be4e11beSAkinobu Mita 2114be4e11beSAkinobu Mita ret = dif_verify(sdt, daddr, sector, ei_lba); 2115beb40ea4SAkinobu Mita if (ret) { 2116be4e11beSAkinobu Mita dump_sector(daddr, scsi_debug_sector_size); 2117395cef03SMartin K. Petersen goto out; 2118395cef03SMartin K. Petersen } 2119395cef03SMartin K. Petersen 2120c6a44287SMartin K. Petersen sector++; 2121395cef03SMartin K. Petersen ei_lba++; 2122be4e11beSAkinobu Mita dpage_offset += scsi_debug_sector_size; 2123c6a44287SMartin K. Petersen } 2124be4e11beSAkinobu Mita diter.consumed = dpage_offset; 2125be4e11beSAkinobu Mita sg_miter_stop(&diter); 2126c6a44287SMartin K. Petersen } 2127be4e11beSAkinobu Mita sg_miter_stop(&piter); 2128c6a44287SMartin K. Petersen 212965f72f2aSAkinobu Mita dif_copy_prot(SCpnt, start_sec, sectors, false); 2130c6a44287SMartin K. Petersen dix_writes++; 2131c6a44287SMartin K. Petersen 2132c6a44287SMartin K. Petersen return 0; 2133c6a44287SMartin K. Petersen 2134c6a44287SMartin K. Petersen out: 2135c6a44287SMartin K. Petersen dif_errors++; 2136be4e11beSAkinobu Mita sg_miter_stop(&diter); 2137be4e11beSAkinobu Mita sg_miter_stop(&piter); 2138c6a44287SMartin K. Petersen return ret; 2139c6a44287SMartin K. Petersen } 2140c6a44287SMartin K. Petersen 2141b90ebc3dSAkinobu Mita static unsigned long lba_to_map_index(sector_t lba) 2142b90ebc3dSAkinobu Mita { 2143b90ebc3dSAkinobu Mita if (scsi_debug_unmap_alignment) { 2144b90ebc3dSAkinobu Mita lba += scsi_debug_unmap_granularity - 2145b90ebc3dSAkinobu Mita scsi_debug_unmap_alignment; 2146b90ebc3dSAkinobu Mita } 2147b90ebc3dSAkinobu Mita do_div(lba, scsi_debug_unmap_granularity); 2148b90ebc3dSAkinobu Mita 2149b90ebc3dSAkinobu Mita return lba; 2150b90ebc3dSAkinobu Mita } 2151b90ebc3dSAkinobu Mita 2152b90ebc3dSAkinobu Mita static sector_t map_index_to_lba(unsigned long index) 2153b90ebc3dSAkinobu Mita { 2154a027b5b9SAkinobu Mita sector_t lba = index * scsi_debug_unmap_granularity; 2155a027b5b9SAkinobu Mita 2156a027b5b9SAkinobu Mita if (scsi_debug_unmap_alignment) { 2157a027b5b9SAkinobu Mita lba -= scsi_debug_unmap_granularity - 2158b90ebc3dSAkinobu Mita scsi_debug_unmap_alignment; 2159b90ebc3dSAkinobu Mita } 2160b90ebc3dSAkinobu Mita 2161a027b5b9SAkinobu Mita return lba; 2162a027b5b9SAkinobu Mita } 2163a027b5b9SAkinobu Mita 216444d92694SMartin K. Petersen static unsigned int map_state(sector_t lba, unsigned int *num) 216544d92694SMartin K. Petersen { 2166b90ebc3dSAkinobu Mita sector_t end; 2167b90ebc3dSAkinobu Mita unsigned int mapped; 2168b90ebc3dSAkinobu Mita unsigned long index; 2169b90ebc3dSAkinobu Mita unsigned long next; 217044d92694SMartin K. Petersen 2171b90ebc3dSAkinobu Mita index = lba_to_map_index(lba); 2172b90ebc3dSAkinobu Mita mapped = test_bit(index, map_storep); 217344d92694SMartin K. Petersen 217444d92694SMartin K. Petersen if (mapped) 2175b90ebc3dSAkinobu Mita next = find_next_zero_bit(map_storep, map_size, index); 217644d92694SMartin K. Petersen else 2177b90ebc3dSAkinobu Mita next = find_next_bit(map_storep, map_size, index); 217844d92694SMartin K. Petersen 2179b90ebc3dSAkinobu Mita end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next)); 218044d92694SMartin K. Petersen *num = end - lba; 218144d92694SMartin K. Petersen 218244d92694SMartin K. Petersen return mapped; 218344d92694SMartin K. Petersen } 218444d92694SMartin K. Petersen 218544d92694SMartin K. Petersen static void map_region(sector_t lba, unsigned int len) 218644d92694SMartin K. Petersen { 218744d92694SMartin K. Petersen sector_t end = lba + len; 218844d92694SMartin K. Petersen 218944d92694SMartin K. Petersen while (lba < end) { 2190b90ebc3dSAkinobu Mita unsigned long index = lba_to_map_index(lba); 219144d92694SMartin K. Petersen 2192b90ebc3dSAkinobu Mita if (index < map_size) 2193b90ebc3dSAkinobu Mita set_bit(index, map_storep); 219444d92694SMartin K. Petersen 2195b90ebc3dSAkinobu Mita lba = map_index_to_lba(index + 1); 219644d92694SMartin K. Petersen } 219744d92694SMartin K. Petersen } 219844d92694SMartin K. Petersen 219944d92694SMartin K. Petersen static void unmap_region(sector_t lba, unsigned int len) 220044d92694SMartin K. Petersen { 220144d92694SMartin K. Petersen sector_t end = lba + len; 220244d92694SMartin K. Petersen 220344d92694SMartin K. Petersen while (lba < end) { 2204b90ebc3dSAkinobu Mita unsigned long index = lba_to_map_index(lba); 220544d92694SMartin K. Petersen 2206b90ebc3dSAkinobu Mita if (lba == map_index_to_lba(index) && 2207b90ebc3dSAkinobu Mita lba + scsi_debug_unmap_granularity <= end && 2208b90ebc3dSAkinobu Mita index < map_size) { 2209b90ebc3dSAkinobu Mita clear_bit(index, map_storep); 2210b90ebc3dSAkinobu Mita if (scsi_debug_lbprz) { 2211be1dd78dSEric Sandeen memset(fake_storep + 2212cc34a8e6SAkinobu Mita lba * scsi_debug_sector_size, 0, 2213cc34a8e6SAkinobu Mita scsi_debug_sector_size * 2214cc34a8e6SAkinobu Mita scsi_debug_unmap_granularity); 2215be1dd78dSEric Sandeen } 2216e9926b43SAkinobu Mita if (dif_storep) { 2217e9926b43SAkinobu Mita memset(dif_storep + lba, 0xff, 2218e9926b43SAkinobu Mita sizeof(*dif_storep) * 2219e9926b43SAkinobu Mita scsi_debug_unmap_granularity); 2220e9926b43SAkinobu Mita } 2221b90ebc3dSAkinobu Mita } 2222b90ebc3dSAkinobu Mita lba = map_index_to_lba(index + 1); 222344d92694SMartin K. Petersen } 222444d92694SMartin K. Petersen } 222544d92694SMartin K. Petersen 2226c65b1445SDouglas Gilbert static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, 2227cbf67842SDouglas Gilbert unsigned int num, u32 ei_lba) 22281da177e4SLinus Torvalds { 22291da177e4SLinus Torvalds unsigned long iflags; 223019789100SFUJITA Tomonori int ret; 22311da177e4SLinus Torvalds 2232cbf67842SDouglas Gilbert ret = check_device_access_params(SCpnt, lba, num); 223319789100SFUJITA Tomonori if (ret) 223419789100SFUJITA Tomonori return ret; 22351da177e4SLinus Torvalds 22366c78cc06SAkinobu Mita write_lock_irqsave(&atomic_rw, iflags); 22376c78cc06SAkinobu Mita 2238c6a44287SMartin K. Petersen /* DIX + T10 DIF */ 2239c6a44287SMartin K. Petersen if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { 2240395cef03SMartin K. Petersen int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba); 2241c6a44287SMartin K. Petersen 2242c6a44287SMartin K. Petersen if (prot_ret) { 22436c78cc06SAkinobu Mita write_unlock_irqrestore(&atomic_rw, iflags); 2244cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 2245cbf67842SDouglas Gilbert prot_ret); 2246c6a44287SMartin K. Petersen return illegal_condition_result; 2247c6a44287SMartin K. Petersen } 2248c6a44287SMartin K. Petersen } 2249c6a44287SMartin K. Petersen 2250cbf67842SDouglas Gilbert ret = do_device_access(SCpnt, lba, num, 1); 22519ed8d3dcSAkinobu Mita if (scsi_debug_lbp()) 225244d92694SMartin K. Petersen map_region(lba, num); 22531da177e4SLinus Torvalds write_unlock_irqrestore(&atomic_rw, iflags); 225419789100SFUJITA Tomonori if (-1 == ret) 22551da177e4SLinus Torvalds return (DID_ERROR << 16); 2256597136abSMartin K. Petersen else if ((ret < (num * scsi_debug_sector_size)) && 22571da177e4SLinus Torvalds (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) 2258cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, 2259cbf67842SDouglas Gilbert "%s: write: cdb indicated=%u, IO sent=%d bytes\n", 2260cbf67842SDouglas Gilbert my_name, num * scsi_debug_sector_size, ret); 226144d92694SMartin K. Petersen 22621da177e4SLinus Torvalds return 0; 22631da177e4SLinus Torvalds } 22641da177e4SLinus Torvalds 226544d92694SMartin K. Petersen static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, 2266cbf67842SDouglas Gilbert unsigned int num, u32 ei_lba, unsigned int unmap) 226744d92694SMartin K. Petersen { 226844d92694SMartin K. Petersen unsigned long iflags; 226944d92694SMartin K. Petersen unsigned long long i; 227044d92694SMartin K. Petersen int ret; 227144d92694SMartin K. Petersen 2272cbf67842SDouglas Gilbert ret = check_device_access_params(scmd, lba, num); 227344d92694SMartin K. Petersen if (ret) 227444d92694SMartin K. Petersen return ret; 227544d92694SMartin K. Petersen 22765b94e232SMartin K. Petersen if (num > scsi_debug_write_same_length) { 2277cbf67842SDouglas Gilbert mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 22785b94e232SMartin K. Petersen 0); 22795b94e232SMartin K. Petersen return check_condition_result; 22805b94e232SMartin K. Petersen } 22815b94e232SMartin K. Petersen 228244d92694SMartin K. Petersen write_lock_irqsave(&atomic_rw, iflags); 228344d92694SMartin K. Petersen 22849ed8d3dcSAkinobu Mita if (unmap && scsi_debug_lbp()) { 228544d92694SMartin K. Petersen unmap_region(lba, num); 228644d92694SMartin K. Petersen goto out; 228744d92694SMartin K. Petersen } 228844d92694SMartin K. Petersen 228944d92694SMartin K. Petersen /* Else fetch one logical block */ 229044d92694SMartin K. Petersen ret = fetch_to_dev_buffer(scmd, 229144d92694SMartin K. Petersen fake_storep + (lba * scsi_debug_sector_size), 229244d92694SMartin K. Petersen scsi_debug_sector_size); 229344d92694SMartin K. Petersen 229444d92694SMartin K. Petersen if (-1 == ret) { 229544d92694SMartin K. Petersen write_unlock_irqrestore(&atomic_rw, iflags); 229644d92694SMartin K. Petersen return (DID_ERROR << 16); 229744d92694SMartin K. Petersen } else if ((ret < (num * scsi_debug_sector_size)) && 229844d92694SMartin K. Petersen (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) 2299cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, scmd->device, 2300cbf67842SDouglas Gilbert "%s: %s: cdb indicated=%u, IO sent=%d bytes\n", 2301cbf67842SDouglas Gilbert my_name, "write same", 2302cbf67842SDouglas Gilbert num * scsi_debug_sector_size, ret); 230344d92694SMartin K. Petersen 230444d92694SMartin K. Petersen /* Copy first sector to remaining blocks */ 230544d92694SMartin K. Petersen for (i = 1 ; i < num ; i++) 230644d92694SMartin K. Petersen memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size), 230744d92694SMartin K. Petersen fake_storep + (lba * scsi_debug_sector_size), 230844d92694SMartin K. Petersen scsi_debug_sector_size); 230944d92694SMartin K. Petersen 23109ed8d3dcSAkinobu Mita if (scsi_debug_lbp()) 231144d92694SMartin K. Petersen map_region(lba, num); 231244d92694SMartin K. Petersen out: 231344d92694SMartin K. Petersen write_unlock_irqrestore(&atomic_rw, iflags); 231444d92694SMartin K. Petersen 231544d92694SMartin K. Petersen return 0; 231644d92694SMartin K. Petersen } 231744d92694SMartin K. Petersen 231844d92694SMartin K. Petersen struct unmap_block_desc { 231944d92694SMartin K. Petersen __be64 lba; 232044d92694SMartin K. Petersen __be32 blocks; 232144d92694SMartin K. Petersen __be32 __reserved; 232244d92694SMartin K. Petersen }; 232344d92694SMartin K. Petersen 232444d92694SMartin K. Petersen static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) 232544d92694SMartin K. Petersen { 232644d92694SMartin K. Petersen unsigned char *buf; 232744d92694SMartin K. Petersen struct unmap_block_desc *desc; 232844d92694SMartin K. Petersen unsigned int i, payload_len, descriptors; 232944d92694SMartin K. Petersen int ret; 23306c78cc06SAkinobu Mita unsigned long iflags; 233144d92694SMartin K. Petersen 2332cbf67842SDouglas Gilbert ret = check_readiness(scmd, UAS_ONLY, devip); 233344d92694SMartin K. Petersen if (ret) 233444d92694SMartin K. Petersen return ret; 233544d92694SMartin K. Petersen 233644d92694SMartin K. Petersen payload_len = get_unaligned_be16(&scmd->cmnd[7]); 233744d92694SMartin K. Petersen BUG_ON(scsi_bufflen(scmd) != payload_len); 233844d92694SMartin K. Petersen 233944d92694SMartin K. Petersen descriptors = (payload_len - 8) / 16; 234044d92694SMartin K. Petersen 234144d92694SMartin K. Petersen buf = kmalloc(scsi_bufflen(scmd), GFP_ATOMIC); 234244d92694SMartin K. Petersen if (!buf) 234344d92694SMartin K. Petersen return check_condition_result; 234444d92694SMartin K. Petersen 234544d92694SMartin K. Petersen scsi_sg_copy_to_buffer(scmd, buf, scsi_bufflen(scmd)); 234644d92694SMartin K. Petersen 234744d92694SMartin K. Petersen BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2); 234844d92694SMartin K. Petersen BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16); 234944d92694SMartin K. Petersen 235044d92694SMartin K. Petersen desc = (void *)&buf[8]; 235144d92694SMartin K. Petersen 23526c78cc06SAkinobu Mita write_lock_irqsave(&atomic_rw, iflags); 23536c78cc06SAkinobu Mita 235444d92694SMartin K. Petersen for (i = 0 ; i < descriptors ; i++) { 235544d92694SMartin K. Petersen unsigned long long lba = get_unaligned_be64(&desc[i].lba); 235644d92694SMartin K. Petersen unsigned int num = get_unaligned_be32(&desc[i].blocks); 235744d92694SMartin K. Petersen 2358cbf67842SDouglas Gilbert ret = check_device_access_params(scmd, lba, num); 235944d92694SMartin K. Petersen if (ret) 236044d92694SMartin K. Petersen goto out; 236144d92694SMartin K. Petersen 236244d92694SMartin K. Petersen unmap_region(lba, num); 236344d92694SMartin K. Petersen } 236444d92694SMartin K. Petersen 236544d92694SMartin K. Petersen ret = 0; 236644d92694SMartin K. Petersen 236744d92694SMartin K. Petersen out: 23686c78cc06SAkinobu Mita write_unlock_irqrestore(&atomic_rw, iflags); 236944d92694SMartin K. Petersen kfree(buf); 237044d92694SMartin K. Petersen 237144d92694SMartin K. Petersen return ret; 237244d92694SMartin K. Petersen } 237344d92694SMartin K. Petersen 237444d92694SMartin K. Petersen #define SDEBUG_GET_LBA_STATUS_LEN 32 237544d92694SMartin K. Petersen 237644d92694SMartin K. Petersen static int resp_get_lba_status(struct scsi_cmnd * scmd, 237744d92694SMartin K. Petersen struct sdebug_dev_info * devip) 237844d92694SMartin K. Petersen { 237944d92694SMartin K. Petersen unsigned long long lba; 238044d92694SMartin K. Petersen unsigned int alloc_len, mapped, num; 238144d92694SMartin K. Petersen unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN]; 238244d92694SMartin K. Petersen int ret; 238344d92694SMartin K. Petersen 2384cbf67842SDouglas Gilbert ret = check_readiness(scmd, UAS_ONLY, devip); 238544d92694SMartin K. Petersen if (ret) 238644d92694SMartin K. Petersen return ret; 238744d92694SMartin K. Petersen 238844d92694SMartin K. Petersen lba = get_unaligned_be64(&scmd->cmnd[2]); 238944d92694SMartin K. Petersen alloc_len = get_unaligned_be32(&scmd->cmnd[10]); 239044d92694SMartin K. Petersen 239144d92694SMartin K. Petersen if (alloc_len < 24) 239244d92694SMartin K. Petersen return 0; 239344d92694SMartin K. Petersen 2394cbf67842SDouglas Gilbert ret = check_device_access_params(scmd, lba, 1); 239544d92694SMartin K. Petersen if (ret) 239644d92694SMartin K. Petersen return ret; 239744d92694SMartin K. Petersen 239844d92694SMartin K. Petersen mapped = map_state(lba, &num); 239944d92694SMartin K. Petersen 240044d92694SMartin K. Petersen memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN); 2401de13e965SDouglas Gilbert put_unaligned_be32(20, &arr[0]); /* Parameter Data Length */ 240244d92694SMartin K. Petersen put_unaligned_be64(lba, &arr[8]); /* LBA */ 240344d92694SMartin K. Petersen put_unaligned_be32(num, &arr[16]); /* Number of blocks */ 240444d92694SMartin K. Petersen arr[20] = !mapped; /* mapped = 0, unmapped = 1 */ 240544d92694SMartin K. Petersen 240644d92694SMartin K. Petersen return fill_from_dev_buffer(scmd, arr, SDEBUG_GET_LBA_STATUS_LEN); 240744d92694SMartin K. Petersen } 240844d92694SMartin K. Petersen 2409c65b1445SDouglas Gilbert #define SDEBUG_RLUN_ARR_SZ 256 24101da177e4SLinus Torvalds 24111da177e4SLinus Torvalds static int resp_report_luns(struct scsi_cmnd * scp, 24121da177e4SLinus Torvalds struct sdebug_dev_info * devip) 24131da177e4SLinus Torvalds { 24141da177e4SLinus Torvalds unsigned int alloc_len; 24159cb78c16SHannes Reinecke int lun_cnt, i, upper, num, n; 24169cb78c16SHannes Reinecke u64 wlun, lun; 241701123ef4SDouglas Gilbert unsigned char *cmd = scp->cmnd; 24181da177e4SLinus Torvalds int select_report = (int)cmd[2]; 24191da177e4SLinus Torvalds struct scsi_lun *one_lun; 24201da177e4SLinus Torvalds unsigned char arr[SDEBUG_RLUN_ARR_SZ]; 2421c65b1445SDouglas Gilbert unsigned char * max_addr; 24221da177e4SLinus Torvalds 24231da177e4SLinus Torvalds alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); 2424c65b1445SDouglas Gilbert if ((alloc_len < 4) || (select_report > 2)) { 2425cbf67842SDouglas Gilbert mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 24261da177e4SLinus Torvalds 0); 24271da177e4SLinus Torvalds return check_condition_result; 24281da177e4SLinus Torvalds } 24291da177e4SLinus Torvalds /* can produce response with up to 16k luns (lun 0 to lun 16383) */ 24301da177e4SLinus Torvalds memset(arr, 0, SDEBUG_RLUN_ARR_SZ); 24311da177e4SLinus Torvalds lun_cnt = scsi_debug_max_luns; 2432c65b1445SDouglas Gilbert if (1 == select_report) 2433c65b1445SDouglas Gilbert lun_cnt = 0; 2434c65b1445SDouglas Gilbert else if (scsi_debug_no_lun_0 && (lun_cnt > 0)) 2435c65b1445SDouglas Gilbert --lun_cnt; 2436c65b1445SDouglas Gilbert wlun = (select_report > 0) ? 1 : 0; 2437c65b1445SDouglas Gilbert num = lun_cnt + wlun; 2438c65b1445SDouglas Gilbert arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff; 2439c65b1445SDouglas Gilbert arr[3] = (sizeof(struct scsi_lun) * num) & 0xff; 2440c65b1445SDouglas Gilbert n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) / 2441c65b1445SDouglas Gilbert sizeof(struct scsi_lun)), num); 2442c65b1445SDouglas Gilbert if (n < num) { 2443c65b1445SDouglas Gilbert wlun = 0; 2444c65b1445SDouglas Gilbert lun_cnt = n; 2445c65b1445SDouglas Gilbert } 24461da177e4SLinus Torvalds one_lun = (struct scsi_lun *) &arr[8]; 2447c65b1445SDouglas Gilbert max_addr = arr + SDEBUG_RLUN_ARR_SZ; 2448c65b1445SDouglas Gilbert for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0); 2449c65b1445SDouglas Gilbert ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr)); 2450c65b1445SDouglas Gilbert i++, lun++) { 2451c65b1445SDouglas Gilbert upper = (lun >> 8) & 0x3f; 24521da177e4SLinus Torvalds if (upper) 24531da177e4SLinus Torvalds one_lun[i].scsi_lun[0] = 24541da177e4SLinus Torvalds (upper | (SAM2_LUN_ADDRESS_METHOD << 6)); 2455c65b1445SDouglas Gilbert one_lun[i].scsi_lun[1] = lun & 0xff; 24561da177e4SLinus Torvalds } 2457c65b1445SDouglas Gilbert if (wlun) { 2458c65b1445SDouglas Gilbert one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff; 2459c65b1445SDouglas Gilbert one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff; 2460c65b1445SDouglas Gilbert i++; 2461c65b1445SDouglas Gilbert } 2462c65b1445SDouglas Gilbert alloc_len = (unsigned char *)(one_lun + i) - arr; 24631da177e4SLinus Torvalds return fill_from_dev_buffer(scp, arr, 24641da177e4SLinus Torvalds min((int)alloc_len, SDEBUG_RLUN_ARR_SZ)); 24651da177e4SLinus Torvalds } 24661da177e4SLinus Torvalds 2467c639d14eSFUJITA Tomonori static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, 2468c639d14eSFUJITA Tomonori unsigned int num, struct sdebug_dev_info *devip) 2469c639d14eSFUJITA Tomonori { 2470be4e11beSAkinobu Mita int j; 2471c639d14eSFUJITA Tomonori unsigned char *kaddr, *buf; 2472c639d14eSFUJITA Tomonori unsigned int offset; 2473c639d14eSFUJITA Tomonori struct scsi_data_buffer *sdb = scsi_in(scp); 2474be4e11beSAkinobu Mita struct sg_mapping_iter miter; 2475c639d14eSFUJITA Tomonori 2476c639d14eSFUJITA Tomonori /* better not to use temporary buffer. */ 2477c639d14eSFUJITA Tomonori buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); 2478c5af0db9SAkinobu Mita if (!buf) { 2479cbf67842SDouglas Gilbert mk_sense_buffer(scp, NOT_READY, 2480c5af0db9SAkinobu Mita LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); 2481c5af0db9SAkinobu Mita return check_condition_result; 2482c5af0db9SAkinobu Mita } 2483c639d14eSFUJITA Tomonori 248421a61829SFUJITA Tomonori scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp)); 2485c639d14eSFUJITA Tomonori 2486c639d14eSFUJITA Tomonori offset = 0; 2487be4e11beSAkinobu Mita sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents, 2488be4e11beSAkinobu Mita SG_MITER_ATOMIC | SG_MITER_TO_SG); 2489c639d14eSFUJITA Tomonori 2490be4e11beSAkinobu Mita while (sg_miter_next(&miter)) { 2491be4e11beSAkinobu Mita kaddr = miter.addr; 2492be4e11beSAkinobu Mita for (j = 0; j < miter.length; j++) 2493be4e11beSAkinobu Mita *(kaddr + j) ^= *(buf + offset + j); 2494c639d14eSFUJITA Tomonori 2495be4e11beSAkinobu Mita offset += miter.length; 2496c639d14eSFUJITA Tomonori } 2497be4e11beSAkinobu Mita sg_miter_stop(&miter); 2498c639d14eSFUJITA Tomonori kfree(buf); 2499c639d14eSFUJITA Tomonori 2500be4e11beSAkinobu Mita return 0; 2501c639d14eSFUJITA Tomonori } 2502c639d14eSFUJITA Tomonori 2503cbf67842SDouglas Gilbert /* When timer or tasklet goes off this function is called. */ 2504cbf67842SDouglas Gilbert static void sdebug_q_cmd_complete(unsigned long indx) 25051da177e4SLinus Torvalds { 2506cbf67842SDouglas Gilbert int qa_indx; 2507cbf67842SDouglas Gilbert int retiring = 0; 25081da177e4SLinus Torvalds unsigned long iflags; 2509cbf67842SDouglas Gilbert struct sdebug_queued_cmd *sqcp; 2510cbf67842SDouglas Gilbert struct scsi_cmnd *scp; 2511cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 25121da177e4SLinus Torvalds 2513cbf67842SDouglas Gilbert atomic_inc(&sdebug_completions); 2514cbf67842SDouglas Gilbert qa_indx = indx; 2515cbf67842SDouglas Gilbert if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { 2516cbf67842SDouglas Gilbert pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); 25171da177e4SLinus Torvalds return; 25181da177e4SLinus Torvalds } 25191da177e4SLinus Torvalds spin_lock_irqsave(&queued_arr_lock, iflags); 2520cbf67842SDouglas Gilbert sqcp = &queued_arr[qa_indx]; 2521cbf67842SDouglas Gilbert scp = sqcp->a_cmnd; 2522cbf67842SDouglas Gilbert if (NULL == scp) { 25231da177e4SLinus Torvalds spin_unlock_irqrestore(&queued_arr_lock, iflags); 2524cbf67842SDouglas Gilbert pr_err("%s: scp is NULL\n", __func__); 25251da177e4SLinus Torvalds return; 25261da177e4SLinus Torvalds } 2527cbf67842SDouglas Gilbert devip = (struct sdebug_dev_info *)scp->device->hostdata; 2528cbf67842SDouglas Gilbert if (devip) 2529cbf67842SDouglas Gilbert atomic_dec(&devip->num_in_q); 2530cbf67842SDouglas Gilbert else 2531cbf67842SDouglas Gilbert pr_err("%s: devip=NULL\n", __func__); 2532cbf67842SDouglas Gilbert if (atomic_read(&retired_max_queue) > 0) 2533cbf67842SDouglas Gilbert retiring = 1; 2534cbf67842SDouglas Gilbert 2535cbf67842SDouglas Gilbert sqcp->a_cmnd = NULL; 2536cbf67842SDouglas Gilbert if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { 25371da177e4SLinus Torvalds spin_unlock_irqrestore(&queued_arr_lock, iflags); 2538cbf67842SDouglas Gilbert pr_err("%s: Unexpected completion\n", __func__); 2539cbf67842SDouglas Gilbert return; 25401da177e4SLinus Torvalds } 25411da177e4SLinus Torvalds 2542cbf67842SDouglas Gilbert if (unlikely(retiring)) { /* user has reduced max_queue */ 2543cbf67842SDouglas Gilbert int k, retval; 2544cbf67842SDouglas Gilbert 2545cbf67842SDouglas Gilbert retval = atomic_read(&retired_max_queue); 2546cbf67842SDouglas Gilbert if (qa_indx >= retval) { 2547cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 2548cbf67842SDouglas Gilbert pr_err("%s: index %d too large\n", __func__, retval); 2549cbf67842SDouglas Gilbert return; 2550cbf67842SDouglas Gilbert } 2551cbf67842SDouglas Gilbert k = find_last_bit(queued_in_use_bm, retval); 2552cbf67842SDouglas Gilbert if ((k < scsi_debug_max_queue) || (k == retval)) 2553cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, 0); 2554cbf67842SDouglas Gilbert else 2555cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, k + 1); 2556cbf67842SDouglas Gilbert } 2557cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 2558cbf67842SDouglas Gilbert scp->scsi_done(scp); /* callback to mid level */ 2559cbf67842SDouglas Gilbert } 2560cbf67842SDouglas Gilbert 2561cbf67842SDouglas Gilbert /* When high resolution timer goes off this function is called. */ 2562cbf67842SDouglas Gilbert static enum hrtimer_restart 2563cbf67842SDouglas Gilbert sdebug_q_cmd_hrt_complete(struct hrtimer *timer) 2564cbf67842SDouglas Gilbert { 2565cbf67842SDouglas Gilbert int qa_indx; 2566cbf67842SDouglas Gilbert int retiring = 0; 2567cbf67842SDouglas Gilbert unsigned long iflags; 2568cbf67842SDouglas Gilbert struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer; 2569cbf67842SDouglas Gilbert struct sdebug_queued_cmd *sqcp; 2570cbf67842SDouglas Gilbert struct scsi_cmnd *scp; 2571cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 2572cbf67842SDouglas Gilbert 2573cbf67842SDouglas Gilbert atomic_inc(&sdebug_completions); 2574cbf67842SDouglas Gilbert qa_indx = sd_hrtp->qa_indx; 2575cbf67842SDouglas Gilbert if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { 2576cbf67842SDouglas Gilbert pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); 2577cbf67842SDouglas Gilbert goto the_end; 2578cbf67842SDouglas Gilbert } 2579cbf67842SDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 2580cbf67842SDouglas Gilbert sqcp = &queued_arr[qa_indx]; 2581cbf67842SDouglas Gilbert scp = sqcp->a_cmnd; 2582cbf67842SDouglas Gilbert if (NULL == scp) { 2583cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 2584cbf67842SDouglas Gilbert pr_err("%s: scp is NULL\n", __func__); 2585cbf67842SDouglas Gilbert goto the_end; 2586cbf67842SDouglas Gilbert } 2587cbf67842SDouglas Gilbert devip = (struct sdebug_dev_info *)scp->device->hostdata; 2588cbf67842SDouglas Gilbert if (devip) 2589cbf67842SDouglas Gilbert atomic_dec(&devip->num_in_q); 2590cbf67842SDouglas Gilbert else 2591cbf67842SDouglas Gilbert pr_err("%s: devip=NULL\n", __func__); 2592cbf67842SDouglas Gilbert if (atomic_read(&retired_max_queue) > 0) 2593cbf67842SDouglas Gilbert retiring = 1; 2594cbf67842SDouglas Gilbert 2595cbf67842SDouglas Gilbert sqcp->a_cmnd = NULL; 2596cbf67842SDouglas Gilbert if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { 2597cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 2598cbf67842SDouglas Gilbert pr_err("%s: Unexpected completion\n", __func__); 2599cbf67842SDouglas Gilbert goto the_end; 2600cbf67842SDouglas Gilbert } 2601cbf67842SDouglas Gilbert 2602cbf67842SDouglas Gilbert if (unlikely(retiring)) { /* user has reduced max_queue */ 2603cbf67842SDouglas Gilbert int k, retval; 2604cbf67842SDouglas Gilbert 2605cbf67842SDouglas Gilbert retval = atomic_read(&retired_max_queue); 2606cbf67842SDouglas Gilbert if (qa_indx >= retval) { 2607cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 2608cbf67842SDouglas Gilbert pr_err("%s: index %d too large\n", __func__, retval); 2609cbf67842SDouglas Gilbert goto the_end; 2610cbf67842SDouglas Gilbert } 2611cbf67842SDouglas Gilbert k = find_last_bit(queued_in_use_bm, retval); 2612cbf67842SDouglas Gilbert if ((k < scsi_debug_max_queue) || (k == retval)) 2613cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, 0); 2614cbf67842SDouglas Gilbert else 2615cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, k + 1); 2616cbf67842SDouglas Gilbert } 2617cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 2618cbf67842SDouglas Gilbert scp->scsi_done(scp); /* callback to mid level */ 2619cbf67842SDouglas Gilbert the_end: 2620cbf67842SDouglas Gilbert return HRTIMER_NORESTART; 2621cbf67842SDouglas Gilbert } 26221da177e4SLinus Torvalds 26238dea0d02SFUJITA Tomonori static struct sdebug_dev_info * 26248dea0d02SFUJITA Tomonori sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags) 26255cb2fc06SFUJITA Tomonori { 26265cb2fc06SFUJITA Tomonori struct sdebug_dev_info *devip; 26275cb2fc06SFUJITA Tomonori 26285cb2fc06SFUJITA Tomonori devip = kzalloc(sizeof(*devip), flags); 26295cb2fc06SFUJITA Tomonori if (devip) { 26305cb2fc06SFUJITA Tomonori devip->sdbg_host = sdbg_host; 26315cb2fc06SFUJITA Tomonori list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list); 26325cb2fc06SFUJITA Tomonori } 26335cb2fc06SFUJITA Tomonori return devip; 26345cb2fc06SFUJITA Tomonori } 26355cb2fc06SFUJITA Tomonori 26361da177e4SLinus Torvalds static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) 26371da177e4SLinus Torvalds { 26381da177e4SLinus Torvalds struct sdebug_host_info * sdbg_host; 26391da177e4SLinus Torvalds struct sdebug_dev_info * open_devip = NULL; 26401da177e4SLinus Torvalds struct sdebug_dev_info * devip = 26411da177e4SLinus Torvalds (struct sdebug_dev_info *)sdev->hostdata; 26421da177e4SLinus Torvalds 26431da177e4SLinus Torvalds if (devip) 26441da177e4SLinus Torvalds return devip; 2645d1e4c9c5SFUJITA Tomonori sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); 26461da177e4SLinus Torvalds if (!sdbg_host) { 2647cbf67842SDouglas Gilbert pr_err("%s: Host info NULL\n", __func__); 26481da177e4SLinus Torvalds return NULL; 26491da177e4SLinus Torvalds } 26501da177e4SLinus Torvalds list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { 26511da177e4SLinus Torvalds if ((devip->used) && (devip->channel == sdev->channel) && 26521da177e4SLinus Torvalds (devip->target == sdev->id) && 26531da177e4SLinus Torvalds (devip->lun == sdev->lun)) 26541da177e4SLinus Torvalds return devip; 26551da177e4SLinus Torvalds else { 26561da177e4SLinus Torvalds if ((!devip->used) && (!open_devip)) 26571da177e4SLinus Torvalds open_devip = devip; 26581da177e4SLinus Torvalds } 26591da177e4SLinus Torvalds } 26605cb2fc06SFUJITA Tomonori if (!open_devip) { /* try and make a new one */ 26615cb2fc06SFUJITA Tomonori open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC); 26625cb2fc06SFUJITA Tomonori if (!open_devip) { 26631da177e4SLinus Torvalds printk(KERN_ERR "%s: out of memory at line %d\n", 2664cadbd4a5SHarvey Harrison __func__, __LINE__); 26651da177e4SLinus Torvalds return NULL; 26661da177e4SLinus Torvalds } 26671da177e4SLinus Torvalds } 2668a75869d1SFUJITA Tomonori 26691da177e4SLinus Torvalds open_devip->channel = sdev->channel; 26701da177e4SLinus Torvalds open_devip->target = sdev->id; 26711da177e4SLinus Torvalds open_devip->lun = sdev->lun; 26721da177e4SLinus Torvalds open_devip->sdbg_host = sdbg_host; 2673cbf67842SDouglas Gilbert atomic_set(&open_devip->num_in_q, 0); 2674cbf67842SDouglas Gilbert set_bit(SDEBUG_UA_POR, open_devip->uas_bm); 26751da177e4SLinus Torvalds open_devip->used = 1; 2676c65b1445SDouglas Gilbert if (sdev->lun == SAM2_WLUN_REPORT_LUNS) 2677c65b1445SDouglas Gilbert open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff; 2678a75869d1SFUJITA Tomonori 26791da177e4SLinus Torvalds return open_devip; 26801da177e4SLinus Torvalds } 26811da177e4SLinus Torvalds 26828dea0d02SFUJITA Tomonori static int scsi_debug_slave_alloc(struct scsi_device *sdp) 26831da177e4SLinus Torvalds { 26848dea0d02SFUJITA Tomonori if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 26859cb78c16SHannes Reinecke printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n", 26868dea0d02SFUJITA Tomonori sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); 268775ad23bcSNick Piggin queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue); 26888dea0d02SFUJITA Tomonori return 0; 26898dea0d02SFUJITA Tomonori } 26901da177e4SLinus Torvalds 26918dea0d02SFUJITA Tomonori static int scsi_debug_slave_configure(struct scsi_device *sdp) 26928dea0d02SFUJITA Tomonori { 26938dea0d02SFUJITA Tomonori struct sdebug_dev_info *devip; 2694a34c4e98SFUJITA Tomonori 26951da177e4SLinus Torvalds if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 26969cb78c16SHannes Reinecke printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n", 26978dea0d02SFUJITA Tomonori sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); 26988dea0d02SFUJITA Tomonori if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) 26998dea0d02SFUJITA Tomonori sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; 27008dea0d02SFUJITA Tomonori devip = devInfoReg(sdp); 27018dea0d02SFUJITA Tomonori if (NULL == devip) 27028dea0d02SFUJITA Tomonori return 1; /* no resources, will be marked offline */ 2703c8b09f6fSChristoph Hellwig sdp->hostdata = devip; 27046bb5e6e7SAkinobu Mita blk_queue_max_segment_size(sdp->request_queue, -1U); 270578d4e5a0SDouglas Gilbert if (scsi_debug_no_uld) 270678d4e5a0SDouglas Gilbert sdp->no_uld_attach = 1; 27078dea0d02SFUJITA Tomonori return 0; 27088dea0d02SFUJITA Tomonori } 27098dea0d02SFUJITA Tomonori 27108dea0d02SFUJITA Tomonori static void scsi_debug_slave_destroy(struct scsi_device *sdp) 27118dea0d02SFUJITA Tomonori { 27128dea0d02SFUJITA Tomonori struct sdebug_dev_info *devip = 27138dea0d02SFUJITA Tomonori (struct sdebug_dev_info *)sdp->hostdata; 27148dea0d02SFUJITA Tomonori 27158dea0d02SFUJITA Tomonori if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 27169cb78c16SHannes Reinecke printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n", 27178dea0d02SFUJITA Tomonori sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); 27188dea0d02SFUJITA Tomonori if (devip) { 271925985edcSLucas De Marchi /* make this slot available for re-use */ 27208dea0d02SFUJITA Tomonori devip->used = 0; 27218dea0d02SFUJITA Tomonori sdp->hostdata = NULL; 27228dea0d02SFUJITA Tomonori } 27238dea0d02SFUJITA Tomonori } 27248dea0d02SFUJITA Tomonori 2725cbf67842SDouglas Gilbert /* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */ 27268dea0d02SFUJITA Tomonori static int stop_queued_cmnd(struct scsi_cmnd *cmnd) 27278dea0d02SFUJITA Tomonori { 27288dea0d02SFUJITA Tomonori unsigned long iflags; 2729cbf67842SDouglas Gilbert int k, qmax, r_qmax; 27308dea0d02SFUJITA Tomonori struct sdebug_queued_cmd *sqcp; 2731cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 27328dea0d02SFUJITA Tomonori 27338dea0d02SFUJITA Tomonori spin_lock_irqsave(&queued_arr_lock, iflags); 2734cbf67842SDouglas Gilbert qmax = scsi_debug_max_queue; 2735cbf67842SDouglas Gilbert r_qmax = atomic_read(&retired_max_queue); 2736cbf67842SDouglas Gilbert if (r_qmax > qmax) 2737cbf67842SDouglas Gilbert qmax = r_qmax; 2738cbf67842SDouglas Gilbert for (k = 0; k < qmax; ++k) { 2739cbf67842SDouglas Gilbert if (test_bit(k, queued_in_use_bm)) { 27408dea0d02SFUJITA Tomonori sqcp = &queued_arr[k]; 2741cbf67842SDouglas Gilbert if (cmnd == sqcp->a_cmnd) { 2742db525fceSDouglas Gilbert devip = (struct sdebug_dev_info *) 2743db525fceSDouglas Gilbert cmnd->device->hostdata; 2744db525fceSDouglas Gilbert if (devip) 2745db525fceSDouglas Gilbert atomic_dec(&devip->num_in_q); 2746db525fceSDouglas Gilbert sqcp->a_cmnd = NULL; 2747db525fceSDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, 2748db525fceSDouglas Gilbert iflags); 2749cbf67842SDouglas Gilbert if (scsi_debug_ndelay > 0) { 2750cbf67842SDouglas Gilbert if (sqcp->sd_hrtp) 2751cbf67842SDouglas Gilbert hrtimer_cancel( 2752cbf67842SDouglas Gilbert &sqcp->sd_hrtp->hrt); 2753cbf67842SDouglas Gilbert } else if (scsi_debug_delay > 0) { 2754cbf67842SDouglas Gilbert if (sqcp->cmnd_timerp) 2755cbf67842SDouglas Gilbert del_timer_sync( 2756cbf67842SDouglas Gilbert sqcp->cmnd_timerp); 2757cbf67842SDouglas Gilbert } else if (scsi_debug_delay < 0) { 2758cbf67842SDouglas Gilbert if (sqcp->tletp) 2759cbf67842SDouglas Gilbert tasklet_kill(sqcp->tletp); 2760cbf67842SDouglas Gilbert } 2761db525fceSDouglas Gilbert clear_bit(k, queued_in_use_bm); 2762db525fceSDouglas Gilbert return 1; 27638dea0d02SFUJITA Tomonori } 27648dea0d02SFUJITA Tomonori } 2765cbf67842SDouglas Gilbert } 27668dea0d02SFUJITA Tomonori spin_unlock_irqrestore(&queued_arr_lock, iflags); 2767db525fceSDouglas Gilbert return 0; 27688dea0d02SFUJITA Tomonori } 27698dea0d02SFUJITA Tomonori 2770cbf67842SDouglas Gilbert /* Deletes (stops) timers or tasklets of all queued commands */ 27718dea0d02SFUJITA Tomonori static void stop_all_queued(void) 27728dea0d02SFUJITA Tomonori { 27738dea0d02SFUJITA Tomonori unsigned long iflags; 27748dea0d02SFUJITA Tomonori int k; 27758dea0d02SFUJITA Tomonori struct sdebug_queued_cmd *sqcp; 2776cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 27778dea0d02SFUJITA Tomonori 27788dea0d02SFUJITA Tomonori spin_lock_irqsave(&queued_arr_lock, iflags); 2779cbf67842SDouglas Gilbert for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { 2780cbf67842SDouglas Gilbert if (test_bit(k, queued_in_use_bm)) { 27818dea0d02SFUJITA Tomonori sqcp = &queued_arr[k]; 2782cbf67842SDouglas Gilbert if (sqcp->a_cmnd) { 2783db525fceSDouglas Gilbert devip = (struct sdebug_dev_info *) 2784db525fceSDouglas Gilbert sqcp->a_cmnd->device->hostdata; 2785db525fceSDouglas Gilbert if (devip) 2786db525fceSDouglas Gilbert atomic_dec(&devip->num_in_q); 2787db525fceSDouglas Gilbert sqcp->a_cmnd = NULL; 2788db525fceSDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, 2789db525fceSDouglas Gilbert iflags); 2790cbf67842SDouglas Gilbert if (scsi_debug_ndelay > 0) { 2791cbf67842SDouglas Gilbert if (sqcp->sd_hrtp) 2792cbf67842SDouglas Gilbert hrtimer_cancel( 2793cbf67842SDouglas Gilbert &sqcp->sd_hrtp->hrt); 2794cbf67842SDouglas Gilbert } else if (scsi_debug_delay > 0) { 2795cbf67842SDouglas Gilbert if (sqcp->cmnd_timerp) 2796cbf67842SDouglas Gilbert del_timer_sync( 2797cbf67842SDouglas Gilbert sqcp->cmnd_timerp); 2798cbf67842SDouglas Gilbert } else if (scsi_debug_delay < 0) { 2799cbf67842SDouglas Gilbert if (sqcp->tletp) 2800cbf67842SDouglas Gilbert tasklet_kill(sqcp->tletp); 2801cbf67842SDouglas Gilbert } 2802db525fceSDouglas Gilbert clear_bit(k, queued_in_use_bm); 2803db525fceSDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 28048dea0d02SFUJITA Tomonori } 28058dea0d02SFUJITA Tomonori } 2806cbf67842SDouglas Gilbert } 2807cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 2808cbf67842SDouglas Gilbert } 2809cbf67842SDouglas Gilbert 2810cbf67842SDouglas Gilbert /* Free queued command memory on heap */ 2811cbf67842SDouglas Gilbert static void free_all_queued(void) 2812cbf67842SDouglas Gilbert { 2813cbf67842SDouglas Gilbert unsigned long iflags; 2814cbf67842SDouglas Gilbert int k; 2815cbf67842SDouglas Gilbert struct sdebug_queued_cmd *sqcp; 2816cbf67842SDouglas Gilbert 2817cbf67842SDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 2818cbf67842SDouglas Gilbert for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { 2819cbf67842SDouglas Gilbert sqcp = &queued_arr[k]; 2820cbf67842SDouglas Gilbert kfree(sqcp->cmnd_timerp); 2821cbf67842SDouglas Gilbert sqcp->cmnd_timerp = NULL; 2822cbf67842SDouglas Gilbert kfree(sqcp->tletp); 2823cbf67842SDouglas Gilbert sqcp->tletp = NULL; 2824cbf67842SDouglas Gilbert kfree(sqcp->sd_hrtp); 2825cbf67842SDouglas Gilbert sqcp->sd_hrtp = NULL; 2826cbf67842SDouglas Gilbert } 28278dea0d02SFUJITA Tomonori spin_unlock_irqrestore(&queued_arr_lock, iflags); 28281da177e4SLinus Torvalds } 28291da177e4SLinus Torvalds 28301da177e4SLinus Torvalds static int scsi_debug_abort(struct scsi_cmnd *SCpnt) 28311da177e4SLinus Torvalds { 28321da177e4SLinus Torvalds ++num_aborts; 2833cbf67842SDouglas Gilbert if (SCpnt) { 2834cbf67842SDouglas Gilbert if (SCpnt->device && 2835cbf67842SDouglas Gilbert (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) 2836cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, "%s\n", 2837cbf67842SDouglas Gilbert __func__); 28381da177e4SLinus Torvalds stop_queued_cmnd(SCpnt); 2839cbf67842SDouglas Gilbert } 28401da177e4SLinus Torvalds return SUCCESS; 28411da177e4SLinus Torvalds } 28421da177e4SLinus Torvalds 28431da177e4SLinus Torvalds static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) 28441da177e4SLinus Torvalds { 28451da177e4SLinus Torvalds struct sdebug_dev_info * devip; 28461da177e4SLinus Torvalds 28471da177e4SLinus Torvalds ++num_dev_resets; 2848cbf67842SDouglas Gilbert if (SCpnt && SCpnt->device) { 2849cbf67842SDouglas Gilbert struct scsi_device *sdp = SCpnt->device; 2850cbf67842SDouglas Gilbert 2851cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) 2852cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, "%s\n", __func__); 2853cbf67842SDouglas Gilbert devip = devInfoReg(sdp); 28541da177e4SLinus Torvalds if (devip) 2855cbf67842SDouglas Gilbert set_bit(SDEBUG_UA_POR, devip->uas_bm); 28561da177e4SLinus Torvalds } 28571da177e4SLinus Torvalds return SUCCESS; 28581da177e4SLinus Torvalds } 28591da177e4SLinus Torvalds 2860cbf67842SDouglas Gilbert static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt) 2861cbf67842SDouglas Gilbert { 2862cbf67842SDouglas Gilbert struct sdebug_host_info *sdbg_host; 2863cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 2864cbf67842SDouglas Gilbert struct scsi_device *sdp; 2865cbf67842SDouglas Gilbert struct Scsi_Host *hp; 2866cbf67842SDouglas Gilbert int k = 0; 2867cbf67842SDouglas Gilbert 2868cbf67842SDouglas Gilbert ++num_target_resets; 2869cbf67842SDouglas Gilbert if (!SCpnt) 2870cbf67842SDouglas Gilbert goto lie; 2871cbf67842SDouglas Gilbert sdp = SCpnt->device; 2872cbf67842SDouglas Gilbert if (!sdp) 2873cbf67842SDouglas Gilbert goto lie; 2874cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) 2875cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, "%s\n", __func__); 2876cbf67842SDouglas Gilbert hp = sdp->host; 2877cbf67842SDouglas Gilbert if (!hp) 2878cbf67842SDouglas Gilbert goto lie; 2879cbf67842SDouglas Gilbert sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); 2880cbf67842SDouglas Gilbert if (sdbg_host) { 2881cbf67842SDouglas Gilbert list_for_each_entry(devip, 2882cbf67842SDouglas Gilbert &sdbg_host->dev_info_list, 2883cbf67842SDouglas Gilbert dev_list) 2884cbf67842SDouglas Gilbert if (devip->target == sdp->id) { 2885cbf67842SDouglas Gilbert set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); 2886cbf67842SDouglas Gilbert ++k; 2887cbf67842SDouglas Gilbert } 2888cbf67842SDouglas Gilbert } 2889cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) 2890cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, 2891cbf67842SDouglas Gilbert "%s: %d device(s) found in target\n", __func__, k); 2892cbf67842SDouglas Gilbert lie: 2893cbf67842SDouglas Gilbert return SUCCESS; 2894cbf67842SDouglas Gilbert } 2895cbf67842SDouglas Gilbert 28961da177e4SLinus Torvalds static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) 28971da177e4SLinus Torvalds { 28981da177e4SLinus Torvalds struct sdebug_host_info *sdbg_host; 2899cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 29001da177e4SLinus Torvalds struct scsi_device * sdp; 29011da177e4SLinus Torvalds struct Scsi_Host * hp; 2902cbf67842SDouglas Gilbert int k = 0; 29031da177e4SLinus Torvalds 29041da177e4SLinus Torvalds ++num_bus_resets; 2905cbf67842SDouglas Gilbert if (!(SCpnt && SCpnt->device)) 2906cbf67842SDouglas Gilbert goto lie; 2907cbf67842SDouglas Gilbert sdp = SCpnt->device; 2908cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) 2909cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, "%s\n", __func__); 2910cbf67842SDouglas Gilbert hp = sdp->host; 2911cbf67842SDouglas Gilbert if (hp) { 2912d1e4c9c5SFUJITA Tomonori sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); 29131da177e4SLinus Torvalds if (sdbg_host) { 2914cbf67842SDouglas Gilbert list_for_each_entry(devip, 29151da177e4SLinus Torvalds &sdbg_host->dev_info_list, 2916cbf67842SDouglas Gilbert dev_list) { 2917cbf67842SDouglas Gilbert set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); 2918cbf67842SDouglas Gilbert ++k; 29191da177e4SLinus Torvalds } 29201da177e4SLinus Torvalds } 2921cbf67842SDouglas Gilbert } 2922cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) 2923cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, 2924cbf67842SDouglas Gilbert "%s: %d device(s) found in host\n", __func__, k); 2925cbf67842SDouglas Gilbert lie: 29261da177e4SLinus Torvalds return SUCCESS; 29271da177e4SLinus Torvalds } 29281da177e4SLinus Torvalds 29291da177e4SLinus Torvalds static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) 29301da177e4SLinus Torvalds { 29311da177e4SLinus Torvalds struct sdebug_host_info * sdbg_host; 2932cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 2933cbf67842SDouglas Gilbert int k = 0; 29341da177e4SLinus Torvalds 29351da177e4SLinus Torvalds ++num_host_resets; 2936cbf67842SDouglas Gilbert if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) 2937cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__); 29381da177e4SLinus Torvalds spin_lock(&sdebug_host_list_lock); 29391da177e4SLinus Torvalds list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { 2940cbf67842SDouglas Gilbert list_for_each_entry(devip, &sdbg_host->dev_info_list, 2941cbf67842SDouglas Gilbert dev_list) { 2942cbf67842SDouglas Gilbert set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); 2943cbf67842SDouglas Gilbert ++k; 2944cbf67842SDouglas Gilbert } 29451da177e4SLinus Torvalds } 29461da177e4SLinus Torvalds spin_unlock(&sdebug_host_list_lock); 29471da177e4SLinus Torvalds stop_all_queued(); 2948cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) 2949cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, 2950cbf67842SDouglas Gilbert "%s: %d device(s) found\n", __func__, k); 29511da177e4SLinus Torvalds return SUCCESS; 29521da177e4SLinus Torvalds } 29531da177e4SLinus Torvalds 2954f58b0efbSFUJITA Tomonori static void __init sdebug_build_parts(unsigned char *ramp, 29555f2578e5SFUJITA Tomonori unsigned long store_size) 29561da177e4SLinus Torvalds { 29571da177e4SLinus Torvalds struct partition * pp; 29581da177e4SLinus Torvalds int starts[SDEBUG_MAX_PARTS + 2]; 29591da177e4SLinus Torvalds int sectors_per_part, num_sectors, k; 29601da177e4SLinus Torvalds int heads_by_sects, start_sec, end_sec; 29611da177e4SLinus Torvalds 29621da177e4SLinus Torvalds /* assume partition table already zeroed */ 2963f58b0efbSFUJITA Tomonori if ((scsi_debug_num_parts < 1) || (store_size < 1048576)) 29641da177e4SLinus Torvalds return; 29651da177e4SLinus Torvalds if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { 29661da177e4SLinus Torvalds scsi_debug_num_parts = SDEBUG_MAX_PARTS; 2967cbf67842SDouglas Gilbert pr_warn("%s: reducing partitions to %d\n", __func__, 2968cbf67842SDouglas Gilbert SDEBUG_MAX_PARTS); 29691da177e4SLinus Torvalds } 2970c65b1445SDouglas Gilbert num_sectors = (int)sdebug_store_sectors; 29711da177e4SLinus Torvalds sectors_per_part = (num_sectors - sdebug_sectors_per) 29721da177e4SLinus Torvalds / scsi_debug_num_parts; 29731da177e4SLinus Torvalds heads_by_sects = sdebug_heads * sdebug_sectors_per; 29741da177e4SLinus Torvalds starts[0] = sdebug_sectors_per; 29751da177e4SLinus Torvalds for (k = 1; k < scsi_debug_num_parts; ++k) 29761da177e4SLinus Torvalds starts[k] = ((k * sectors_per_part) / heads_by_sects) 29771da177e4SLinus Torvalds * heads_by_sects; 29781da177e4SLinus Torvalds starts[scsi_debug_num_parts] = num_sectors; 29791da177e4SLinus Torvalds starts[scsi_debug_num_parts + 1] = 0; 29801da177e4SLinus Torvalds 29811da177e4SLinus Torvalds ramp[510] = 0x55; /* magic partition markings */ 29821da177e4SLinus Torvalds ramp[511] = 0xAA; 29831da177e4SLinus Torvalds pp = (struct partition *)(ramp + 0x1be); 29841da177e4SLinus Torvalds for (k = 0; starts[k + 1]; ++k, ++pp) { 29851da177e4SLinus Torvalds start_sec = starts[k]; 29861da177e4SLinus Torvalds end_sec = starts[k + 1] - 1; 29871da177e4SLinus Torvalds pp->boot_ind = 0; 29881da177e4SLinus Torvalds 29891da177e4SLinus Torvalds pp->cyl = start_sec / heads_by_sects; 29901da177e4SLinus Torvalds pp->head = (start_sec - (pp->cyl * heads_by_sects)) 29911da177e4SLinus Torvalds / sdebug_sectors_per; 29921da177e4SLinus Torvalds pp->sector = (start_sec % sdebug_sectors_per) + 1; 29931da177e4SLinus Torvalds 29941da177e4SLinus Torvalds pp->end_cyl = end_sec / heads_by_sects; 29951da177e4SLinus Torvalds pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects)) 29961da177e4SLinus Torvalds / sdebug_sectors_per; 29971da177e4SLinus Torvalds pp->end_sector = (end_sec % sdebug_sectors_per) + 1; 29981da177e4SLinus Torvalds 2999150c3544SAkinobu Mita pp->start_sect = cpu_to_le32(start_sec); 3000150c3544SAkinobu Mita pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1); 30011da177e4SLinus Torvalds pp->sys_ind = 0x83; /* plain Linux partition */ 30021da177e4SLinus Torvalds } 30031da177e4SLinus Torvalds } 30041da177e4SLinus Torvalds 3005cbf67842SDouglas Gilbert static int 3006cbf67842SDouglas Gilbert schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, 3007cbf67842SDouglas Gilbert int scsi_result, int delta_jiff) 30081da177e4SLinus Torvalds { 3009cbf67842SDouglas Gilbert unsigned long iflags; 3010cd62b7daSDouglas Gilbert int k, num_in_q, qdepth, inject; 3011cbf67842SDouglas Gilbert struct sdebug_queued_cmd *sqcp = NULL; 30121da177e4SLinus Torvalds struct scsi_device *sdp = cmnd->device; 30131da177e4SLinus Torvalds 3014cbf67842SDouglas Gilbert if (NULL == cmnd || NULL == devip) { 3015cbf67842SDouglas Gilbert pr_warn("%s: called with NULL cmnd or devip pointer\n", 3016cbf67842SDouglas Gilbert __func__); 3017cbf67842SDouglas Gilbert /* no particularly good error to report back */ 3018cbf67842SDouglas Gilbert return SCSI_MLQUEUE_HOST_BUSY; 30191da177e4SLinus Torvalds } 3020cbf67842SDouglas Gilbert if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) 3021cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", 3022cbf67842SDouglas Gilbert __func__, scsi_result); 3023cd62b7daSDouglas Gilbert if (delta_jiff == 0) 3024cd62b7daSDouglas Gilbert goto respond_in_thread; 30251da177e4SLinus Torvalds 3026cd62b7daSDouglas Gilbert /* schedule the response at a later time if resources permit */ 30271da177e4SLinus Torvalds spin_lock_irqsave(&queued_arr_lock, iflags); 3028cbf67842SDouglas Gilbert num_in_q = atomic_read(&devip->num_in_q); 3029cbf67842SDouglas Gilbert qdepth = cmnd->device->queue_depth; 3030cbf67842SDouglas Gilbert inject = 0; 3031cd62b7daSDouglas Gilbert if ((qdepth > 0) && (num_in_q >= qdepth)) { 3032cd62b7daSDouglas Gilbert if (scsi_result) { 3033cd62b7daSDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 3034cd62b7daSDouglas Gilbert goto respond_in_thread; 3035cd62b7daSDouglas Gilbert } else 3036cd62b7daSDouglas Gilbert scsi_result = device_qfull_result; 3037cd62b7daSDouglas Gilbert } else if ((scsi_debug_every_nth != 0) && 3038cd62b7daSDouglas Gilbert (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) && 3039cd62b7daSDouglas Gilbert (scsi_result == 0)) { 3040cbf67842SDouglas Gilbert if ((num_in_q == (qdepth - 1)) && 3041cbf67842SDouglas Gilbert (atomic_inc_return(&sdebug_a_tsf) >= 3042cbf67842SDouglas Gilbert abs(scsi_debug_every_nth))) { 3043cbf67842SDouglas Gilbert atomic_set(&sdebug_a_tsf, 0); 3044cbf67842SDouglas Gilbert inject = 1; 3045cd62b7daSDouglas Gilbert scsi_result = device_qfull_result; 30461da177e4SLinus Torvalds } 3047cbf67842SDouglas Gilbert } 3048cbf67842SDouglas Gilbert 3049cd62b7daSDouglas Gilbert k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue); 305078d4e5a0SDouglas Gilbert if (k >= scsi_debug_max_queue) { 30511da177e4SLinus Torvalds spin_unlock_irqrestore(&queued_arr_lock, iflags); 3052cd62b7daSDouglas Gilbert if (scsi_result) 3053cd62b7daSDouglas Gilbert goto respond_in_thread; 3054cd62b7daSDouglas Gilbert else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts) 3055cd62b7daSDouglas Gilbert scsi_result = device_qfull_result; 3056cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) 3057cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, 3058cd62b7daSDouglas Gilbert "%s: max_queue=%d exceeded, %s\n", 3059cd62b7daSDouglas Gilbert __func__, scsi_debug_max_queue, 3060cd62b7daSDouglas Gilbert (scsi_result ? "status: TASK SET FULL" : 3061cbf67842SDouglas Gilbert "report: host busy")); 3062cd62b7daSDouglas Gilbert if (scsi_result) 3063cd62b7daSDouglas Gilbert goto respond_in_thread; 3064cd62b7daSDouglas Gilbert else 3065cbf67842SDouglas Gilbert return SCSI_MLQUEUE_HOST_BUSY; 30661da177e4SLinus Torvalds } 3067cbf67842SDouglas Gilbert __set_bit(k, queued_in_use_bm); 3068cbf67842SDouglas Gilbert atomic_inc(&devip->num_in_q); 3069cbf67842SDouglas Gilbert sqcp = &queued_arr[k]; 30701da177e4SLinus Torvalds sqcp->a_cmnd = cmnd; 3071cbf67842SDouglas Gilbert cmnd->result = scsi_result; 30721da177e4SLinus Torvalds spin_unlock_irqrestore(&queued_arr_lock, iflags); 3073cbf67842SDouglas Gilbert if (delta_jiff > 0) { 3074cbf67842SDouglas Gilbert if (NULL == sqcp->cmnd_timerp) { 3075cbf67842SDouglas Gilbert sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list), 3076cbf67842SDouglas Gilbert GFP_ATOMIC); 3077cbf67842SDouglas Gilbert if (NULL == sqcp->cmnd_timerp) 3078cbf67842SDouglas Gilbert return SCSI_MLQUEUE_HOST_BUSY; 3079cbf67842SDouglas Gilbert init_timer(sqcp->cmnd_timerp); 3080cbf67842SDouglas Gilbert } 3081cbf67842SDouglas Gilbert sqcp->cmnd_timerp->function = sdebug_q_cmd_complete; 3082cbf67842SDouglas Gilbert sqcp->cmnd_timerp->data = k; 3083cbf67842SDouglas Gilbert sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff; 3084cbf67842SDouglas Gilbert add_timer(sqcp->cmnd_timerp); 3085cbf67842SDouglas Gilbert } else if (scsi_debug_ndelay > 0) { 3086cbf67842SDouglas Gilbert ktime_t kt = ktime_set(0, scsi_debug_ndelay); 3087cbf67842SDouglas Gilbert struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp; 3088cbf67842SDouglas Gilbert 3089cbf67842SDouglas Gilbert if (NULL == sd_hp) { 3090cbf67842SDouglas Gilbert sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC); 3091cbf67842SDouglas Gilbert if (NULL == sd_hp) 3092cbf67842SDouglas Gilbert return SCSI_MLQUEUE_HOST_BUSY; 3093cbf67842SDouglas Gilbert sqcp->sd_hrtp = sd_hp; 3094cbf67842SDouglas Gilbert hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC, 3095cbf67842SDouglas Gilbert HRTIMER_MODE_REL); 3096cbf67842SDouglas Gilbert sd_hp->hrt.function = sdebug_q_cmd_hrt_complete; 3097cbf67842SDouglas Gilbert sd_hp->qa_indx = k; 3098cbf67842SDouglas Gilbert } 3099cbf67842SDouglas Gilbert hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL); 3100cbf67842SDouglas Gilbert } else { /* delay < 0 */ 3101cbf67842SDouglas Gilbert if (NULL == sqcp->tletp) { 3102cbf67842SDouglas Gilbert sqcp->tletp = kmalloc(sizeof(*sqcp->tletp), 3103cbf67842SDouglas Gilbert GFP_ATOMIC); 3104cbf67842SDouglas Gilbert if (NULL == sqcp->tletp) 3105cbf67842SDouglas Gilbert return SCSI_MLQUEUE_HOST_BUSY; 3106cbf67842SDouglas Gilbert tasklet_init(sqcp->tletp, 3107cbf67842SDouglas Gilbert sdebug_q_cmd_complete, k); 3108cbf67842SDouglas Gilbert } 3109cbf67842SDouglas Gilbert if (-1 == delta_jiff) 3110cbf67842SDouglas Gilbert tasklet_hi_schedule(sqcp->tletp); 3111cbf67842SDouglas Gilbert else 3112cbf67842SDouglas Gilbert tasklet_schedule(sqcp->tletp); 3113cbf67842SDouglas Gilbert } 3114cd62b7daSDouglas Gilbert if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) && 3115cd62b7daSDouglas Gilbert (scsi_result == device_qfull_result)) 3116cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdp, 3117cbf67842SDouglas Gilbert "%s: num_in_q=%d +1, %s%s\n", __func__, 3118cbf67842SDouglas Gilbert num_in_q, (inject ? "<inject> " : ""), 3119cbf67842SDouglas Gilbert "status: TASK SET FULL"); 31201da177e4SLinus Torvalds return 0; 3121cd62b7daSDouglas Gilbert 3122cd62b7daSDouglas Gilbert respond_in_thread: /* call back to mid-layer using invocation thread */ 3123cd62b7daSDouglas Gilbert cmnd->result = scsi_result; 3124cd62b7daSDouglas Gilbert cmnd->scsi_done(cmnd); 3125cd62b7daSDouglas Gilbert return 0; 31261da177e4SLinus Torvalds } 3127cbf67842SDouglas Gilbert 312823183910SDouglas Gilbert /* Note: The following macros create attribute files in the 312923183910SDouglas Gilbert /sys/module/scsi_debug/parameters directory. Unfortunately this 313023183910SDouglas Gilbert driver is unaware of a change and cannot trigger auxiliary actions 313123183910SDouglas Gilbert as it can when the corresponding attribute in the 313223183910SDouglas Gilbert /sys/bus/pseudo/drivers/scsi_debug directory is changed. 313323183910SDouglas Gilbert */ 3134c65b1445SDouglas Gilbert module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR); 31355b94e232SMartin K. Petersen module_param_named(ato, scsi_debug_ato, int, S_IRUGO); 31360759c666SAkinobu Mita module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR); 3137c65b1445SDouglas Gilbert module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR); 3138c65b1445SDouglas Gilbert module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO); 31395b94e232SMartin K. Petersen module_param_named(dif, scsi_debug_dif, int, S_IRUGO); 31405b94e232SMartin K. Petersen module_param_named(dix, scsi_debug_dix, int, S_IRUGO); 3141c65b1445SDouglas Gilbert module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); 3142c65b1445SDouglas Gilbert module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); 314323183910SDouglas Gilbert module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR); 314468aee7baSAkinobu Mita module_param_named(guard, scsi_debug_guard, uint, S_IRUGO); 3145cbf67842SDouglas Gilbert module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR); 31465b94e232SMartin K. Petersen module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO); 31475b94e232SMartin K. Petersen module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO); 31485b94e232SMartin K. Petersen module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO); 3149be1dd78dSEric Sandeen module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO); 31505b94e232SMartin K. Petersen module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO); 3151c65b1445SDouglas Gilbert module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR); 315278d4e5a0SDouglas Gilbert module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR); 3153cbf67842SDouglas Gilbert module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR); 3154c65b1445SDouglas Gilbert module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR); 315578d4e5a0SDouglas Gilbert module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO); 3156c65b1445SDouglas Gilbert module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO); 3157c65b1445SDouglas Gilbert module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR); 31585b94e232SMartin K. Petersen module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO); 3159c65b1445SDouglas Gilbert module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR); 31605b94e232SMartin K. Petersen module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO); 3161c65b1445SDouglas Gilbert module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR); 3162d986788bSMartin Pitt module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR); 3163c65b1445SDouglas Gilbert module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO); 31645b94e232SMartin K. Petersen module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); 31655b94e232SMartin K. Petersen module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO); 31665b94e232SMartin K. Petersen module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO); 31675b94e232SMartin K. Petersen module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO); 31685b94e232SMartin K. Petersen module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO); 3169c65b1445SDouglas Gilbert module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); 317023183910SDouglas Gilbert module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, 317123183910SDouglas Gilbert S_IRUGO | S_IWUSR); 31725b94e232SMartin K. Petersen module_param_named(write_same_length, scsi_debug_write_same_length, int, 31735b94e232SMartin K. Petersen S_IRUGO | S_IWUSR); 31741da177e4SLinus Torvalds 31751da177e4SLinus Torvalds MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 31761da177e4SLinus Torvalds MODULE_DESCRIPTION("SCSI debug adapter driver"); 31771da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 31781da177e4SLinus Torvalds MODULE_VERSION(SCSI_DEBUG_VERSION); 31791da177e4SLinus Torvalds 31801da177e4SLinus Torvalds MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); 31815b94e232SMartin K. Petersen MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); 31820759c666SAkinobu Mita MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)"); 3183cbf67842SDouglas Gilbert MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny"); 3184c65b1445SDouglas Gilbert MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)"); 31855b94e232SMartin K. Petersen MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); 31865b94e232SMartin K. Petersen MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); 3187c65b1445SDouglas Gilbert MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)"); 3188beb87c33SRandy Dunlap MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)"); 318923183910SDouglas Gilbert MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)"); 31905b94e232SMartin K. Petersen MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); 3191cbf67842SDouglas Gilbert MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)"); 31925b94e232SMartin K. Petersen MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)"); 31935b94e232SMartin K. Petersen MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)"); 31945b94e232SMartin K. Petersen MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)"); 3195be1dd78dSEric Sandeen MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)"); 31965b94e232SMartin K. Petersen MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); 3197c65b1445SDouglas Gilbert MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); 3198cbf67842SDouglas Gilbert MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))"); 3199cbf67842SDouglas Gilbert MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)"); 3200c65b1445SDouglas Gilbert MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); 320178d4e5a0SDouglas Gilbert MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))"); 32021da177e4SLinus Torvalds MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); 3203c65b1445SDouglas Gilbert MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)"); 32045b94e232SMartin K. Petersen MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)"); 32056f3cbf55SDouglas Gilbert MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)"); 32065b94e232SMartin K. Petersen MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)"); 32071da177e4SLinus Torvalds MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); 3208d986788bSMartin Pitt MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); 3209e46b0344SDouglas Gilbert MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])"); 3210ea61fca5SMartin K. Petersen MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); 32115b94e232SMartin K. Petersen MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); 32125b94e232SMartin K. Petersen MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); 32136014759cSMartin K. Petersen MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)"); 32146014759cSMartin K. Petersen MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)"); 32155b94e232SMartin K. Petersen MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); 32165b94e232SMartin K. Petersen MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); 32175b94e232SMartin K. Petersen MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)"); 32181da177e4SLinus Torvalds 32191da177e4SLinus Torvalds static char sdebug_info[256]; 32201da177e4SLinus Torvalds 32211da177e4SLinus Torvalds static const char * scsi_debug_info(struct Scsi_Host * shp) 32221da177e4SLinus Torvalds { 32231da177e4SLinus Torvalds sprintf(sdebug_info, "scsi_debug, version %s [%s], " 32241da177e4SLinus Torvalds "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION, 32251da177e4SLinus Torvalds scsi_debug_version_date, scsi_debug_dev_size_mb, 32261da177e4SLinus Torvalds scsi_debug_opts); 32271da177e4SLinus Torvalds return sdebug_info; 32281da177e4SLinus Torvalds } 32291da177e4SLinus Torvalds 3230cbf67842SDouglas Gilbert /* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */ 3231c8ed555aSAl Viro static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length) 32321da177e4SLinus Torvalds { 32331da177e4SLinus Torvalds char arr[16]; 3234c8ed555aSAl Viro int opts; 32351da177e4SLinus Torvalds int minLen = length > 15 ? 15 : length; 32361da177e4SLinus Torvalds 32371da177e4SLinus Torvalds if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 32381da177e4SLinus Torvalds return -EACCES; 32391da177e4SLinus Torvalds memcpy(arr, buffer, minLen); 32401da177e4SLinus Torvalds arr[minLen] = '\0'; 3241c8ed555aSAl Viro if (1 != sscanf(arr, "%d", &opts)) 32421da177e4SLinus Torvalds return -EINVAL; 3243c8ed555aSAl Viro scsi_debug_opts = opts; 32441da177e4SLinus Torvalds if (scsi_debug_every_nth != 0) 3245cbf67842SDouglas Gilbert atomic_set(&sdebug_cmnd_count, 0); 32461da177e4SLinus Torvalds return length; 32471da177e4SLinus Torvalds } 3248c8ed555aSAl Viro 3249cbf67842SDouglas Gilbert /* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the 3250cbf67842SDouglas Gilbert * same for each scsi_debug host (if more than one). Some of the counters 3251cbf67842SDouglas Gilbert * output are not atomics so might be inaccurate in a busy system. */ 3252c8ed555aSAl Viro static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) 3253c8ed555aSAl Viro { 3254cbf67842SDouglas Gilbert int f, l; 3255cbf67842SDouglas Gilbert char b[32]; 3256cbf67842SDouglas Gilbert 3257cbf67842SDouglas Gilbert if (scsi_debug_every_nth > 0) 3258cbf67842SDouglas Gilbert snprintf(b, sizeof(b), " (curr:%d)", 3259cbf67842SDouglas Gilbert ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ? 3260cbf67842SDouglas Gilbert atomic_read(&sdebug_a_tsf) : 3261cbf67842SDouglas Gilbert atomic_read(&sdebug_cmnd_count))); 3262cbf67842SDouglas Gilbert else 3263cbf67842SDouglas Gilbert b[0] = '\0'; 3264cbf67842SDouglas Gilbert 3265cbf67842SDouglas Gilbert seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n" 32661da177e4SLinus Torvalds "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, " 3267cbf67842SDouglas Gilbert "every_nth=%d%s\n" 3268cbf67842SDouglas Gilbert "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n" 32691da177e4SLinus Torvalds "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" 3270cbf67842SDouglas Gilbert "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, " 3271cbf67842SDouglas Gilbert "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d " 3272cbf67842SDouglas Gilbert "usec_in_jiffy=%lu\n", 3273cbf67842SDouglas Gilbert SCSI_DEBUG_VERSION, scsi_debug_version_date, 3274cbf67842SDouglas Gilbert scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts, 3275cbf67842SDouglas Gilbert scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay, 3276cbf67842SDouglas Gilbert scsi_debug_max_luns, atomic_read(&sdebug_completions), 3277597136abSMartin K. Petersen scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, 3278cbf67842SDouglas Gilbert sdebug_sectors_per, num_aborts, num_dev_resets, 3279cbf67842SDouglas Gilbert num_target_resets, num_bus_resets, num_host_resets, 3280cbf67842SDouglas Gilbert dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000); 3281cbf67842SDouglas Gilbert 3282cbf67842SDouglas Gilbert f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue); 3283cbf67842SDouglas Gilbert if (f != scsi_debug_max_queue) { 3284cbf67842SDouglas Gilbert l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue); 3285cbf67842SDouglas Gilbert seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n", 3286cbf67842SDouglas Gilbert "queued_in_use_bm", f, l); 3287cbf67842SDouglas Gilbert } 3288c8ed555aSAl Viro return 0; 32891da177e4SLinus Torvalds } 32901da177e4SLinus Torvalds 329182069379SAkinobu Mita static ssize_t delay_show(struct device_driver *ddp, char *buf) 32921da177e4SLinus Torvalds { 32931da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); 32941da177e4SLinus Torvalds } 3295cbf67842SDouglas Gilbert /* Returns -EBUSY if delay is being changed and commands are queued */ 329682069379SAkinobu Mita static ssize_t delay_store(struct device_driver *ddp, const char *buf, 329782069379SAkinobu Mita size_t count) 32981da177e4SLinus Torvalds { 3299cbf67842SDouglas Gilbert int delay, res; 33001da177e4SLinus Torvalds 3301cbf67842SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) { 3302cbf67842SDouglas Gilbert res = count; 3303cbf67842SDouglas Gilbert if (scsi_debug_delay != delay) { 3304cbf67842SDouglas Gilbert unsigned long iflags; 3305cbf67842SDouglas Gilbert int k; 3306cbf67842SDouglas Gilbert 3307cbf67842SDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 3308cbf67842SDouglas Gilbert k = find_first_bit(queued_in_use_bm, 3309cbf67842SDouglas Gilbert scsi_debug_max_queue); 3310cbf67842SDouglas Gilbert if (k != scsi_debug_max_queue) 3311cbf67842SDouglas Gilbert res = -EBUSY; /* have queued commands */ 3312cbf67842SDouglas Gilbert else { 33131da177e4SLinus Torvalds scsi_debug_delay = delay; 3314cbf67842SDouglas Gilbert scsi_debug_ndelay = 0; 33151da177e4SLinus Torvalds } 3316cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 3317cbf67842SDouglas Gilbert } 3318cbf67842SDouglas Gilbert return res; 33191da177e4SLinus Torvalds } 33201da177e4SLinus Torvalds return -EINVAL; 33211da177e4SLinus Torvalds } 332282069379SAkinobu Mita static DRIVER_ATTR_RW(delay); 33231da177e4SLinus Torvalds 3324cbf67842SDouglas Gilbert static ssize_t ndelay_show(struct device_driver *ddp, char *buf) 3325cbf67842SDouglas Gilbert { 3326cbf67842SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay); 3327cbf67842SDouglas Gilbert } 3328cbf67842SDouglas Gilbert /* Returns -EBUSY if ndelay is being changed and commands are queued */ 3329cbf67842SDouglas Gilbert /* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */ 3330cbf67842SDouglas Gilbert static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, 3331cbf67842SDouglas Gilbert size_t count) 3332cbf67842SDouglas Gilbert { 3333cbf67842SDouglas Gilbert unsigned long iflags; 3334cbf67842SDouglas Gilbert int ndelay, res, k; 3335cbf67842SDouglas Gilbert 3336cbf67842SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) && 3337cbf67842SDouglas Gilbert (ndelay >= 0) && (ndelay < 1000000000)) { 3338cbf67842SDouglas Gilbert res = count; 3339cbf67842SDouglas Gilbert if (scsi_debug_ndelay != ndelay) { 3340cbf67842SDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 3341cbf67842SDouglas Gilbert k = find_first_bit(queued_in_use_bm, 3342cbf67842SDouglas Gilbert scsi_debug_max_queue); 3343cbf67842SDouglas Gilbert if (k != scsi_debug_max_queue) 3344cbf67842SDouglas Gilbert res = -EBUSY; /* have queued commands */ 3345cbf67842SDouglas Gilbert else { 3346cbf67842SDouglas Gilbert scsi_debug_ndelay = ndelay; 3347cbf67842SDouglas Gilbert scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN 3348cbf67842SDouglas Gilbert : DEF_DELAY; 3349cbf67842SDouglas Gilbert } 3350cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 3351cbf67842SDouglas Gilbert } 3352cbf67842SDouglas Gilbert return res; 3353cbf67842SDouglas Gilbert } 3354cbf67842SDouglas Gilbert return -EINVAL; 3355cbf67842SDouglas Gilbert } 3356cbf67842SDouglas Gilbert static DRIVER_ATTR_RW(ndelay); 3357cbf67842SDouglas Gilbert 335882069379SAkinobu Mita static ssize_t opts_show(struct device_driver *ddp, char *buf) 33591da177e4SLinus Torvalds { 33601da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); 33611da177e4SLinus Torvalds } 33621da177e4SLinus Torvalds 336382069379SAkinobu Mita static ssize_t opts_store(struct device_driver *ddp, const char *buf, 336482069379SAkinobu Mita size_t count) 33651da177e4SLinus Torvalds { 33661da177e4SLinus Torvalds int opts; 33671da177e4SLinus Torvalds char work[20]; 33681da177e4SLinus Torvalds 33691da177e4SLinus Torvalds if (1 == sscanf(buf, "%10s", work)) { 337048a96876SRasmus Villemoes if (0 == strncasecmp(work,"0x", 2)) { 33711da177e4SLinus Torvalds if (1 == sscanf(&work[2], "%x", &opts)) 33721da177e4SLinus Torvalds goto opts_done; 33731da177e4SLinus Torvalds } else { 33741da177e4SLinus Torvalds if (1 == sscanf(work, "%d", &opts)) 33751da177e4SLinus Torvalds goto opts_done; 33761da177e4SLinus Torvalds } 33771da177e4SLinus Torvalds } 33781da177e4SLinus Torvalds return -EINVAL; 33791da177e4SLinus Torvalds opts_done: 33801da177e4SLinus Torvalds scsi_debug_opts = opts; 3381cbf67842SDouglas Gilbert atomic_set(&sdebug_cmnd_count, 0); 3382cbf67842SDouglas Gilbert atomic_set(&sdebug_a_tsf, 0); 33831da177e4SLinus Torvalds return count; 33841da177e4SLinus Torvalds } 338582069379SAkinobu Mita static DRIVER_ATTR_RW(opts); 33861da177e4SLinus Torvalds 338782069379SAkinobu Mita static ssize_t ptype_show(struct device_driver *ddp, char *buf) 33881da177e4SLinus Torvalds { 33891da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype); 33901da177e4SLinus Torvalds } 339182069379SAkinobu Mita static ssize_t ptype_store(struct device_driver *ddp, const char *buf, 339282069379SAkinobu Mita size_t count) 33931da177e4SLinus Torvalds { 33941da177e4SLinus Torvalds int n; 33951da177e4SLinus Torvalds 33961da177e4SLinus Torvalds if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 33971da177e4SLinus Torvalds scsi_debug_ptype = n; 33981da177e4SLinus Torvalds return count; 33991da177e4SLinus Torvalds } 34001da177e4SLinus Torvalds return -EINVAL; 34011da177e4SLinus Torvalds } 340282069379SAkinobu Mita static DRIVER_ATTR_RW(ptype); 34031da177e4SLinus Torvalds 340482069379SAkinobu Mita static ssize_t dsense_show(struct device_driver *ddp, char *buf) 34051da177e4SLinus Torvalds { 34061da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense); 34071da177e4SLinus Torvalds } 340882069379SAkinobu Mita static ssize_t dsense_store(struct device_driver *ddp, const char *buf, 340982069379SAkinobu Mita size_t count) 34101da177e4SLinus Torvalds { 34111da177e4SLinus Torvalds int n; 34121da177e4SLinus Torvalds 34131da177e4SLinus Torvalds if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 34141da177e4SLinus Torvalds scsi_debug_dsense = n; 34151da177e4SLinus Torvalds return count; 34161da177e4SLinus Torvalds } 34171da177e4SLinus Torvalds return -EINVAL; 34181da177e4SLinus Torvalds } 341982069379SAkinobu Mita static DRIVER_ATTR_RW(dsense); 34201da177e4SLinus Torvalds 342182069379SAkinobu Mita static ssize_t fake_rw_show(struct device_driver *ddp, char *buf) 342223183910SDouglas Gilbert { 342323183910SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw); 342423183910SDouglas Gilbert } 342582069379SAkinobu Mita static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, 342682069379SAkinobu Mita size_t count) 342723183910SDouglas Gilbert { 342823183910SDouglas Gilbert int n; 342923183910SDouglas Gilbert 343023183910SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 3431cbf67842SDouglas Gilbert n = (n > 0); 3432cbf67842SDouglas Gilbert scsi_debug_fake_rw = (scsi_debug_fake_rw > 0); 3433cbf67842SDouglas Gilbert if (scsi_debug_fake_rw != n) { 3434cbf67842SDouglas Gilbert if ((0 == n) && (NULL == fake_storep)) { 3435cbf67842SDouglas Gilbert unsigned long sz = 3436cbf67842SDouglas Gilbert (unsigned long)scsi_debug_dev_size_mb * 3437cbf67842SDouglas Gilbert 1048576; 3438cbf67842SDouglas Gilbert 3439cbf67842SDouglas Gilbert fake_storep = vmalloc(sz); 3440cbf67842SDouglas Gilbert if (NULL == fake_storep) { 3441cbf67842SDouglas Gilbert pr_err("%s: out of memory, 9\n", 3442cbf67842SDouglas Gilbert __func__); 3443cbf67842SDouglas Gilbert return -ENOMEM; 3444cbf67842SDouglas Gilbert } 3445cbf67842SDouglas Gilbert memset(fake_storep, 0, sz); 3446cbf67842SDouglas Gilbert } 344723183910SDouglas Gilbert scsi_debug_fake_rw = n; 3448cbf67842SDouglas Gilbert } 344923183910SDouglas Gilbert return count; 345023183910SDouglas Gilbert } 345123183910SDouglas Gilbert return -EINVAL; 345223183910SDouglas Gilbert } 345382069379SAkinobu Mita static DRIVER_ATTR_RW(fake_rw); 345423183910SDouglas Gilbert 345582069379SAkinobu Mita static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf) 3456c65b1445SDouglas Gilbert { 3457c65b1445SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0); 3458c65b1445SDouglas Gilbert } 345982069379SAkinobu Mita static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf, 346082069379SAkinobu Mita size_t count) 3461c65b1445SDouglas Gilbert { 3462c65b1445SDouglas Gilbert int n; 3463c65b1445SDouglas Gilbert 3464c65b1445SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 3465c65b1445SDouglas Gilbert scsi_debug_no_lun_0 = n; 3466c65b1445SDouglas Gilbert return count; 3467c65b1445SDouglas Gilbert } 3468c65b1445SDouglas Gilbert return -EINVAL; 3469c65b1445SDouglas Gilbert } 347082069379SAkinobu Mita static DRIVER_ATTR_RW(no_lun_0); 3471c65b1445SDouglas Gilbert 347282069379SAkinobu Mita static ssize_t num_tgts_show(struct device_driver *ddp, char *buf) 34731da177e4SLinus Torvalds { 34741da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts); 34751da177e4SLinus Torvalds } 347682069379SAkinobu Mita static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf, 347782069379SAkinobu Mita size_t count) 34781da177e4SLinus Torvalds { 34791da177e4SLinus Torvalds int n; 34801da177e4SLinus Torvalds 34811da177e4SLinus Torvalds if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 34821da177e4SLinus Torvalds scsi_debug_num_tgts = n; 34831da177e4SLinus Torvalds sdebug_max_tgts_luns(); 34841da177e4SLinus Torvalds return count; 34851da177e4SLinus Torvalds } 34861da177e4SLinus Torvalds return -EINVAL; 34871da177e4SLinus Torvalds } 348882069379SAkinobu Mita static DRIVER_ATTR_RW(num_tgts); 34891da177e4SLinus Torvalds 349082069379SAkinobu Mita static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf) 34911da177e4SLinus Torvalds { 34921da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); 34931da177e4SLinus Torvalds } 349482069379SAkinobu Mita static DRIVER_ATTR_RO(dev_size_mb); 34951da177e4SLinus Torvalds 349682069379SAkinobu Mita static ssize_t num_parts_show(struct device_driver *ddp, char *buf) 34971da177e4SLinus Torvalds { 34981da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts); 34991da177e4SLinus Torvalds } 350082069379SAkinobu Mita static DRIVER_ATTR_RO(num_parts); 35011da177e4SLinus Torvalds 350282069379SAkinobu Mita static ssize_t every_nth_show(struct device_driver *ddp, char *buf) 35031da177e4SLinus Torvalds { 35041da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth); 35051da177e4SLinus Torvalds } 350682069379SAkinobu Mita static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, 350782069379SAkinobu Mita size_t count) 35081da177e4SLinus Torvalds { 35091da177e4SLinus Torvalds int nth; 35101da177e4SLinus Torvalds 35111da177e4SLinus Torvalds if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) { 35121da177e4SLinus Torvalds scsi_debug_every_nth = nth; 3513cbf67842SDouglas Gilbert atomic_set(&sdebug_cmnd_count, 0); 35141da177e4SLinus Torvalds return count; 35151da177e4SLinus Torvalds } 35161da177e4SLinus Torvalds return -EINVAL; 35171da177e4SLinus Torvalds } 351882069379SAkinobu Mita static DRIVER_ATTR_RW(every_nth); 35191da177e4SLinus Torvalds 352082069379SAkinobu Mita static ssize_t max_luns_show(struct device_driver *ddp, char *buf) 35211da177e4SLinus Torvalds { 35221da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); 35231da177e4SLinus Torvalds } 352482069379SAkinobu Mita static ssize_t max_luns_store(struct device_driver *ddp, const char *buf, 352582069379SAkinobu Mita size_t count) 35261da177e4SLinus Torvalds { 35271da177e4SLinus Torvalds int n; 35281da177e4SLinus Torvalds 35291da177e4SLinus Torvalds if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 35301da177e4SLinus Torvalds scsi_debug_max_luns = n; 35311da177e4SLinus Torvalds sdebug_max_tgts_luns(); 35321da177e4SLinus Torvalds return count; 35331da177e4SLinus Torvalds } 35341da177e4SLinus Torvalds return -EINVAL; 35351da177e4SLinus Torvalds } 353682069379SAkinobu Mita static DRIVER_ATTR_RW(max_luns); 35371da177e4SLinus Torvalds 353882069379SAkinobu Mita static ssize_t max_queue_show(struct device_driver *ddp, char *buf) 353978d4e5a0SDouglas Gilbert { 354078d4e5a0SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue); 354178d4e5a0SDouglas Gilbert } 3542cbf67842SDouglas Gilbert /* N.B. max_queue can be changed while there are queued commands. In flight 3543cbf67842SDouglas Gilbert * commands beyond the new max_queue will be completed. */ 354482069379SAkinobu Mita static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, 354582069379SAkinobu Mita size_t count) 354678d4e5a0SDouglas Gilbert { 3547cbf67842SDouglas Gilbert unsigned long iflags; 3548cbf67842SDouglas Gilbert int n, k; 354978d4e5a0SDouglas Gilbert 355078d4e5a0SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && 355178d4e5a0SDouglas Gilbert (n <= SCSI_DEBUG_CANQUEUE)) { 3552cbf67842SDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 3553cbf67842SDouglas Gilbert k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE); 355478d4e5a0SDouglas Gilbert scsi_debug_max_queue = n; 3555cbf67842SDouglas Gilbert if (SCSI_DEBUG_CANQUEUE == k) 3556cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, 0); 3557cbf67842SDouglas Gilbert else if (k >= n) 3558cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, k + 1); 3559cbf67842SDouglas Gilbert else 3560cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, 0); 3561cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 356278d4e5a0SDouglas Gilbert return count; 356378d4e5a0SDouglas Gilbert } 356478d4e5a0SDouglas Gilbert return -EINVAL; 356578d4e5a0SDouglas Gilbert } 356682069379SAkinobu Mita static DRIVER_ATTR_RW(max_queue); 356778d4e5a0SDouglas Gilbert 356882069379SAkinobu Mita static ssize_t no_uld_show(struct device_driver *ddp, char *buf) 356978d4e5a0SDouglas Gilbert { 357078d4e5a0SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld); 357178d4e5a0SDouglas Gilbert } 357282069379SAkinobu Mita static DRIVER_ATTR_RO(no_uld); 357378d4e5a0SDouglas Gilbert 357482069379SAkinobu Mita static ssize_t scsi_level_show(struct device_driver *ddp, char *buf) 35751da177e4SLinus Torvalds { 35761da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); 35771da177e4SLinus Torvalds } 357882069379SAkinobu Mita static DRIVER_ATTR_RO(scsi_level); 35791da177e4SLinus Torvalds 358082069379SAkinobu Mita static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf) 3581c65b1445SDouglas Gilbert { 3582c65b1445SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb); 3583c65b1445SDouglas Gilbert } 358482069379SAkinobu Mita static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf, 358582069379SAkinobu Mita size_t count) 3586c65b1445SDouglas Gilbert { 3587c65b1445SDouglas Gilbert int n; 3588c65b1445SDouglas Gilbert 3589c65b1445SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 3590c65b1445SDouglas Gilbert scsi_debug_virtual_gb = n; 359128898873SFUJITA Tomonori 359228898873SFUJITA Tomonori sdebug_capacity = get_sdebug_capacity(); 359328898873SFUJITA Tomonori 3594c65b1445SDouglas Gilbert return count; 3595c65b1445SDouglas Gilbert } 3596c65b1445SDouglas Gilbert return -EINVAL; 3597c65b1445SDouglas Gilbert } 359882069379SAkinobu Mita static DRIVER_ATTR_RW(virtual_gb); 3599c65b1445SDouglas Gilbert 360082069379SAkinobu Mita static ssize_t add_host_show(struct device_driver *ddp, char *buf) 36011da177e4SLinus Torvalds { 36021da177e4SLinus Torvalds return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); 36031da177e4SLinus Torvalds } 36041da177e4SLinus Torvalds 360582069379SAkinobu Mita static ssize_t add_host_store(struct device_driver *ddp, const char *buf, 360682069379SAkinobu Mita size_t count) 36071da177e4SLinus Torvalds { 36081da177e4SLinus Torvalds int delta_hosts; 36091da177e4SLinus Torvalds 3610f3df41cfSFUJITA Tomonori if (sscanf(buf, "%d", &delta_hosts) != 1) 36111da177e4SLinus Torvalds return -EINVAL; 36121da177e4SLinus Torvalds if (delta_hosts > 0) { 36131da177e4SLinus Torvalds do { 36141da177e4SLinus Torvalds sdebug_add_adapter(); 36151da177e4SLinus Torvalds } while (--delta_hosts); 36161da177e4SLinus Torvalds } else if (delta_hosts < 0) { 36171da177e4SLinus Torvalds do { 36181da177e4SLinus Torvalds sdebug_remove_adapter(); 36191da177e4SLinus Torvalds } while (++delta_hosts); 36201da177e4SLinus Torvalds } 36211da177e4SLinus Torvalds return count; 36221da177e4SLinus Torvalds } 362382069379SAkinobu Mita static DRIVER_ATTR_RW(add_host); 36241da177e4SLinus Torvalds 362582069379SAkinobu Mita static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf) 362623183910SDouglas Gilbert { 362723183910SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno); 362823183910SDouglas Gilbert } 362982069379SAkinobu Mita static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf, 363082069379SAkinobu Mita size_t count) 363123183910SDouglas Gilbert { 363223183910SDouglas Gilbert int n; 363323183910SDouglas Gilbert 363423183910SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 363523183910SDouglas Gilbert scsi_debug_vpd_use_hostno = n; 363623183910SDouglas Gilbert return count; 363723183910SDouglas Gilbert } 363823183910SDouglas Gilbert return -EINVAL; 363923183910SDouglas Gilbert } 364082069379SAkinobu Mita static DRIVER_ATTR_RW(vpd_use_hostno); 364123183910SDouglas Gilbert 364282069379SAkinobu Mita static ssize_t sector_size_show(struct device_driver *ddp, char *buf) 3643597136abSMartin K. Petersen { 3644597136abSMartin K. Petersen return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size); 3645597136abSMartin K. Petersen } 364682069379SAkinobu Mita static DRIVER_ATTR_RO(sector_size); 3647597136abSMartin K. Petersen 364882069379SAkinobu Mita static ssize_t dix_show(struct device_driver *ddp, char *buf) 3649c6a44287SMartin K. Petersen { 3650c6a44287SMartin K. Petersen return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix); 3651c6a44287SMartin K. Petersen } 365282069379SAkinobu Mita static DRIVER_ATTR_RO(dix); 3653c6a44287SMartin K. Petersen 365482069379SAkinobu Mita static ssize_t dif_show(struct device_driver *ddp, char *buf) 3655c6a44287SMartin K. Petersen { 3656c6a44287SMartin K. Petersen return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif); 3657c6a44287SMartin K. Petersen } 365882069379SAkinobu Mita static DRIVER_ATTR_RO(dif); 3659c6a44287SMartin K. Petersen 366082069379SAkinobu Mita static ssize_t guard_show(struct device_driver *ddp, char *buf) 3661c6a44287SMartin K. Petersen { 366268aee7baSAkinobu Mita return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard); 3663c6a44287SMartin K. Petersen } 366482069379SAkinobu Mita static DRIVER_ATTR_RO(guard); 3665c6a44287SMartin K. Petersen 366682069379SAkinobu Mita static ssize_t ato_show(struct device_driver *ddp, char *buf) 3667c6a44287SMartin K. Petersen { 3668c6a44287SMartin K. Petersen return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato); 3669c6a44287SMartin K. Petersen } 367082069379SAkinobu Mita static DRIVER_ATTR_RO(ato); 3671c6a44287SMartin K. Petersen 367282069379SAkinobu Mita static ssize_t map_show(struct device_driver *ddp, char *buf) 367344d92694SMartin K. Petersen { 367444d92694SMartin K. Petersen ssize_t count; 367544d92694SMartin K. Petersen 36765b94e232SMartin K. Petersen if (!scsi_debug_lbp()) 367744d92694SMartin K. Petersen return scnprintf(buf, PAGE_SIZE, "0-%u\n", 367844d92694SMartin K. Petersen sdebug_store_sectors); 367944d92694SMartin K. Petersen 368044d92694SMartin K. Petersen count = bitmap_scnlistprintf(buf, PAGE_SIZE, map_storep, map_size); 368144d92694SMartin K. Petersen 368244d92694SMartin K. Petersen buf[count++] = '\n'; 368344d92694SMartin K. Petersen buf[count++] = 0; 368444d92694SMartin K. Petersen 368544d92694SMartin K. Petersen return count; 368644d92694SMartin K. Petersen } 368782069379SAkinobu Mita static DRIVER_ATTR_RO(map); 368844d92694SMartin K. Petersen 368982069379SAkinobu Mita static ssize_t removable_show(struct device_driver *ddp, char *buf) 3690d986788bSMartin Pitt { 3691d986788bSMartin Pitt return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0); 3692d986788bSMartin Pitt } 369382069379SAkinobu Mita static ssize_t removable_store(struct device_driver *ddp, const char *buf, 369482069379SAkinobu Mita size_t count) 3695d986788bSMartin Pitt { 3696d986788bSMartin Pitt int n; 3697d986788bSMartin Pitt 3698d986788bSMartin Pitt if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 3699d986788bSMartin Pitt scsi_debug_removable = (n > 0); 3700d986788bSMartin Pitt return count; 3701d986788bSMartin Pitt } 3702d986788bSMartin Pitt return -EINVAL; 3703d986788bSMartin Pitt } 370482069379SAkinobu Mita static DRIVER_ATTR_RW(removable); 3705d986788bSMartin Pitt 3706cbf67842SDouglas Gilbert static ssize_t host_lock_show(struct device_driver *ddp, char *buf) 3707cbf67842SDouglas Gilbert { 3708cbf67842SDouglas Gilbert return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock); 3709cbf67842SDouglas Gilbert } 3710cbf67842SDouglas Gilbert /* Returns -EBUSY if host_lock is being changed and commands are queued */ 3711cbf67842SDouglas Gilbert static ssize_t host_lock_store(struct device_driver *ddp, const char *buf, 3712cbf67842SDouglas Gilbert size_t count) 3713cbf67842SDouglas Gilbert { 3714cbf67842SDouglas Gilbert int n, res; 3715cbf67842SDouglas Gilbert 3716cbf67842SDouglas Gilbert if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { 3717cbf67842SDouglas Gilbert bool new_host_lock = (n > 0); 3718cbf67842SDouglas Gilbert 3719cbf67842SDouglas Gilbert res = count; 3720cbf67842SDouglas Gilbert if (new_host_lock != scsi_debug_host_lock) { 3721cbf67842SDouglas Gilbert unsigned long iflags; 3722cbf67842SDouglas Gilbert int k; 3723cbf67842SDouglas Gilbert 3724cbf67842SDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 3725cbf67842SDouglas Gilbert k = find_first_bit(queued_in_use_bm, 3726cbf67842SDouglas Gilbert scsi_debug_max_queue); 3727cbf67842SDouglas Gilbert if (k != scsi_debug_max_queue) 3728cbf67842SDouglas Gilbert res = -EBUSY; /* have queued commands */ 3729cbf67842SDouglas Gilbert else 3730cbf67842SDouglas Gilbert scsi_debug_host_lock = new_host_lock; 3731cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 3732cbf67842SDouglas Gilbert } 3733cbf67842SDouglas Gilbert return res; 3734cbf67842SDouglas Gilbert } 3735cbf67842SDouglas Gilbert return -EINVAL; 3736cbf67842SDouglas Gilbert } 3737cbf67842SDouglas Gilbert static DRIVER_ATTR_RW(host_lock); 3738cbf67842SDouglas Gilbert 3739cbf67842SDouglas Gilbert 374082069379SAkinobu Mita /* Note: The following array creates attribute files in the 374123183910SDouglas Gilbert /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these 374223183910SDouglas Gilbert files (over those found in the /sys/module/scsi_debug/parameters 374323183910SDouglas Gilbert directory) is that auxiliary actions can be triggered when an attribute 374423183910SDouglas Gilbert is changed. For example see: sdebug_add_host_store() above. 374523183910SDouglas Gilbert */ 37466ecaff7fSRandy Dunlap 374782069379SAkinobu Mita static struct attribute *sdebug_drv_attrs[] = { 374882069379SAkinobu Mita &driver_attr_delay.attr, 374982069379SAkinobu Mita &driver_attr_opts.attr, 375082069379SAkinobu Mita &driver_attr_ptype.attr, 375182069379SAkinobu Mita &driver_attr_dsense.attr, 375282069379SAkinobu Mita &driver_attr_fake_rw.attr, 375382069379SAkinobu Mita &driver_attr_no_lun_0.attr, 375482069379SAkinobu Mita &driver_attr_num_tgts.attr, 375582069379SAkinobu Mita &driver_attr_dev_size_mb.attr, 375682069379SAkinobu Mita &driver_attr_num_parts.attr, 375782069379SAkinobu Mita &driver_attr_every_nth.attr, 375882069379SAkinobu Mita &driver_attr_max_luns.attr, 375982069379SAkinobu Mita &driver_attr_max_queue.attr, 376082069379SAkinobu Mita &driver_attr_no_uld.attr, 376182069379SAkinobu Mita &driver_attr_scsi_level.attr, 376282069379SAkinobu Mita &driver_attr_virtual_gb.attr, 376382069379SAkinobu Mita &driver_attr_add_host.attr, 376482069379SAkinobu Mita &driver_attr_vpd_use_hostno.attr, 376582069379SAkinobu Mita &driver_attr_sector_size.attr, 376682069379SAkinobu Mita &driver_attr_dix.attr, 376782069379SAkinobu Mita &driver_attr_dif.attr, 376882069379SAkinobu Mita &driver_attr_guard.attr, 376982069379SAkinobu Mita &driver_attr_ato.attr, 377082069379SAkinobu Mita &driver_attr_map.attr, 377182069379SAkinobu Mita &driver_attr_removable.attr, 3772cbf67842SDouglas Gilbert &driver_attr_host_lock.attr, 3773cbf67842SDouglas Gilbert &driver_attr_ndelay.attr, 377482069379SAkinobu Mita NULL, 377582069379SAkinobu Mita }; 377682069379SAkinobu Mita ATTRIBUTE_GROUPS(sdebug_drv); 37771da177e4SLinus Torvalds 377811ddcecaSAkinobu Mita static struct device *pseudo_primary; 37798dea0d02SFUJITA Tomonori 37801da177e4SLinus Torvalds static int __init scsi_debug_init(void) 37811da177e4SLinus Torvalds { 37825f2578e5SFUJITA Tomonori unsigned long sz; 37831da177e4SLinus Torvalds int host_to_add; 37841da177e4SLinus Torvalds int k; 37856ecaff7fSRandy Dunlap int ret; 37861da177e4SLinus Torvalds 3787cbf67842SDouglas Gilbert atomic_set(&sdebug_cmnd_count, 0); 3788cbf67842SDouglas Gilbert atomic_set(&sdebug_completions, 0); 3789cbf67842SDouglas Gilbert atomic_set(&retired_max_queue, 0); 3790cbf67842SDouglas Gilbert 3791cbf67842SDouglas Gilbert if (scsi_debug_ndelay >= 1000000000) { 3792cbf67842SDouglas Gilbert pr_warn("%s: ndelay must be less than 1 second, ignored\n", 3793cbf67842SDouglas Gilbert __func__); 3794cbf67842SDouglas Gilbert scsi_debug_ndelay = 0; 3795cbf67842SDouglas Gilbert } else if (scsi_debug_ndelay > 0) 3796cbf67842SDouglas Gilbert scsi_debug_delay = DELAY_OVERRIDDEN; 3797cbf67842SDouglas Gilbert 3798597136abSMartin K. Petersen switch (scsi_debug_sector_size) { 3799597136abSMartin K. Petersen case 512: 3800597136abSMartin K. Petersen case 1024: 3801597136abSMartin K. Petersen case 2048: 3802597136abSMartin K. Petersen case 4096: 3803597136abSMartin K. Petersen break; 3804597136abSMartin K. Petersen default: 3805cbf67842SDouglas Gilbert pr_err("%s: invalid sector_size %d\n", __func__, 3806597136abSMartin K. Petersen scsi_debug_sector_size); 3807597136abSMartin K. Petersen return -EINVAL; 3808597136abSMartin K. Petersen } 3809597136abSMartin K. Petersen 3810c6a44287SMartin K. Petersen switch (scsi_debug_dif) { 3811c6a44287SMartin K. Petersen 3812c6a44287SMartin K. Petersen case SD_DIF_TYPE0_PROTECTION: 3813c6a44287SMartin K. Petersen case SD_DIF_TYPE1_PROTECTION: 3814395cef03SMartin K. Petersen case SD_DIF_TYPE2_PROTECTION: 3815c6a44287SMartin K. Petersen case SD_DIF_TYPE3_PROTECTION: 3816c6a44287SMartin K. Petersen break; 3817c6a44287SMartin K. Petersen 3818c6a44287SMartin K. Petersen default: 3819cbf67842SDouglas Gilbert pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__); 3820c6a44287SMartin K. Petersen return -EINVAL; 3821c6a44287SMartin K. Petersen } 3822c6a44287SMartin K. Petersen 3823c6a44287SMartin K. Petersen if (scsi_debug_guard > 1) { 3824cbf67842SDouglas Gilbert pr_err("%s: guard must be 0 or 1\n", __func__); 3825c6a44287SMartin K. Petersen return -EINVAL; 3826c6a44287SMartin K. Petersen } 3827c6a44287SMartin K. Petersen 3828c6a44287SMartin K. Petersen if (scsi_debug_ato > 1) { 3829cbf67842SDouglas Gilbert pr_err("%s: ato must be 0 or 1\n", __func__); 3830c6a44287SMartin K. Petersen return -EINVAL; 3831c6a44287SMartin K. Petersen } 3832c6a44287SMartin K. Petersen 3833ea61fca5SMartin K. Petersen if (scsi_debug_physblk_exp > 15) { 3834cbf67842SDouglas Gilbert pr_err("%s: invalid physblk_exp %u\n", __func__, 3835ea61fca5SMartin K. Petersen scsi_debug_physblk_exp); 3836ea61fca5SMartin K. Petersen return -EINVAL; 3837ea61fca5SMartin K. Petersen } 3838ea61fca5SMartin K. Petersen 3839ea61fca5SMartin K. Petersen if (scsi_debug_lowest_aligned > 0x3fff) { 3840cbf67842SDouglas Gilbert pr_err("%s: lowest_aligned too big: %u\n", __func__, 3841ea61fca5SMartin K. Petersen scsi_debug_lowest_aligned); 3842ea61fca5SMartin K. Petersen return -EINVAL; 3843ea61fca5SMartin K. Petersen } 3844ea61fca5SMartin K. Petersen 38451da177e4SLinus Torvalds if (scsi_debug_dev_size_mb < 1) 38461da177e4SLinus Torvalds scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ 38475f2578e5SFUJITA Tomonori sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; 3848597136abSMartin K. Petersen sdebug_store_sectors = sz / scsi_debug_sector_size; 384928898873SFUJITA Tomonori sdebug_capacity = get_sdebug_capacity(); 38501da177e4SLinus Torvalds 38511da177e4SLinus Torvalds /* play around with geometry, don't waste too much on track 0 */ 38521da177e4SLinus Torvalds sdebug_heads = 8; 38531da177e4SLinus Torvalds sdebug_sectors_per = 32; 38541da177e4SLinus Torvalds if (scsi_debug_dev_size_mb >= 16) 38551da177e4SLinus Torvalds sdebug_heads = 32; 38561da177e4SLinus Torvalds else if (scsi_debug_dev_size_mb >= 256) 38571da177e4SLinus Torvalds sdebug_heads = 64; 38581da177e4SLinus Torvalds sdebug_cylinders_per = (unsigned long)sdebug_capacity / 38591da177e4SLinus Torvalds (sdebug_sectors_per * sdebug_heads); 38601da177e4SLinus Torvalds if (sdebug_cylinders_per >= 1024) { 38611da177e4SLinus Torvalds /* other LLDs do this; implies >= 1GB ram disk ... */ 38621da177e4SLinus Torvalds sdebug_heads = 255; 38631da177e4SLinus Torvalds sdebug_sectors_per = 63; 38641da177e4SLinus Torvalds sdebug_cylinders_per = (unsigned long)sdebug_capacity / 38651da177e4SLinus Torvalds (sdebug_sectors_per * sdebug_heads); 38661da177e4SLinus Torvalds } 38671da177e4SLinus Torvalds 3868cbf67842SDouglas Gilbert if (0 == scsi_debug_fake_rw) { 38691da177e4SLinus Torvalds fake_storep = vmalloc(sz); 38701da177e4SLinus Torvalds if (NULL == fake_storep) { 3871cbf67842SDouglas Gilbert pr_err("%s: out of memory, 1\n", __func__); 38721da177e4SLinus Torvalds return -ENOMEM; 38731da177e4SLinus Torvalds } 38741da177e4SLinus Torvalds memset(fake_storep, 0, sz); 38751da177e4SLinus Torvalds if (scsi_debug_num_parts > 0) 3876f58b0efbSFUJITA Tomonori sdebug_build_parts(fake_storep, sz); 3877cbf67842SDouglas Gilbert } 38781da177e4SLinus Torvalds 38797cb69d03SAkinobu Mita if (scsi_debug_dix) { 3880c6a44287SMartin K. Petersen int dif_size; 3881c6a44287SMartin K. Petersen 3882c6a44287SMartin K. Petersen dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); 3883c6a44287SMartin K. Petersen dif_storep = vmalloc(dif_size); 3884c6a44287SMartin K. Petersen 3885cbf67842SDouglas Gilbert pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size, 3886cbf67842SDouglas Gilbert dif_storep); 3887c6a44287SMartin K. Petersen 3888c6a44287SMartin K. Petersen if (dif_storep == NULL) { 3889cbf67842SDouglas Gilbert pr_err("%s: out of mem. (DIX)\n", __func__); 3890c6a44287SMartin K. Petersen ret = -ENOMEM; 3891c6a44287SMartin K. Petersen goto free_vm; 3892c6a44287SMartin K. Petersen } 3893c6a44287SMartin K. Petersen 3894c6a44287SMartin K. Petersen memset(dif_storep, 0xff, dif_size); 3895c6a44287SMartin K. Petersen } 3896c6a44287SMartin K. Petersen 38975b94e232SMartin K. Petersen /* Logical Block Provisioning */ 38985b94e232SMartin K. Petersen if (scsi_debug_lbp()) { 38996014759cSMartin K. Petersen scsi_debug_unmap_max_blocks = 39006014759cSMartin K. Petersen clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU); 39016014759cSMartin K. Petersen 39026014759cSMartin K. Petersen scsi_debug_unmap_max_desc = 39036014759cSMartin K. Petersen clamp(scsi_debug_unmap_max_desc, 0U, 256U); 39046014759cSMartin K. Petersen 39056014759cSMartin K. Petersen scsi_debug_unmap_granularity = 39066014759cSMartin K. Petersen clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU); 39076014759cSMartin K. Petersen 39086014759cSMartin K. Petersen if (scsi_debug_unmap_alignment && 3909ac17078aSAkinobu Mita scsi_debug_unmap_granularity <= 3910ac17078aSAkinobu Mita scsi_debug_unmap_alignment) { 3911cbf67842SDouglas Gilbert pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n", 391244d92694SMartin K. Petersen __func__); 391344d92694SMartin K. Petersen return -EINVAL; 391444d92694SMartin K. Petersen } 391544d92694SMartin K. Petersen 3916b90ebc3dSAkinobu Mita map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; 3917b90ebc3dSAkinobu Mita map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long)); 391844d92694SMartin K. Petersen 3919cbf67842SDouglas Gilbert pr_info("%s: %lu provisioning blocks\n", __func__, map_size); 392044d92694SMartin K. Petersen 392144d92694SMartin K. Petersen if (map_storep == NULL) { 3922cbf67842SDouglas Gilbert pr_err("%s: out of mem. (MAP)\n", __func__); 392344d92694SMartin K. Petersen ret = -ENOMEM; 392444d92694SMartin K. Petersen goto free_vm; 392544d92694SMartin K. Petersen } 392644d92694SMartin K. Petersen 3927b90ebc3dSAkinobu Mita bitmap_zero(map_storep, map_size); 392844d92694SMartin K. Petersen 392944d92694SMartin K. Petersen /* Map first 1KB for partition table */ 393044d92694SMartin K. Petersen if (scsi_debug_num_parts) 393144d92694SMartin K. Petersen map_region(0, 2); 393244d92694SMartin K. Petersen } 393344d92694SMartin K. Petersen 39349b906779SNicholas Bellinger pseudo_primary = root_device_register("pseudo_0"); 39359b906779SNicholas Bellinger if (IS_ERR(pseudo_primary)) { 3936cbf67842SDouglas Gilbert pr_warn("%s: root_device_register() error\n", __func__); 39379b906779SNicholas Bellinger ret = PTR_ERR(pseudo_primary); 39386ecaff7fSRandy Dunlap goto free_vm; 39396ecaff7fSRandy Dunlap } 39406ecaff7fSRandy Dunlap ret = bus_register(&pseudo_lld_bus); 39416ecaff7fSRandy Dunlap if (ret < 0) { 3942cbf67842SDouglas Gilbert pr_warn("%s: bus_register error: %d\n", __func__, ret); 39436ecaff7fSRandy Dunlap goto dev_unreg; 39446ecaff7fSRandy Dunlap } 39456ecaff7fSRandy Dunlap ret = driver_register(&sdebug_driverfs_driver); 39466ecaff7fSRandy Dunlap if (ret < 0) { 3947cbf67842SDouglas Gilbert pr_warn("%s: driver_register error: %d\n", __func__, ret); 39486ecaff7fSRandy Dunlap goto bus_unreg; 39496ecaff7fSRandy Dunlap } 39501da177e4SLinus Torvalds 39511da177e4SLinus Torvalds host_to_add = scsi_debug_add_host; 39521da177e4SLinus Torvalds scsi_debug_add_host = 0; 39531da177e4SLinus Torvalds 39541da177e4SLinus Torvalds for (k = 0; k < host_to_add; k++) { 39551da177e4SLinus Torvalds if (sdebug_add_adapter()) { 3956cbf67842SDouglas Gilbert pr_err("%s: sdebug_add_adapter failed k=%d\n", 3957cbf67842SDouglas Gilbert __func__, k); 39581da177e4SLinus Torvalds break; 39591da177e4SLinus Torvalds } 39601da177e4SLinus Torvalds } 39611da177e4SLinus Torvalds 39621da177e4SLinus Torvalds if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { 3963cbf67842SDouglas Gilbert pr_info("%s: built %d host(s)\n", __func__, 39641da177e4SLinus Torvalds scsi_debug_add_host); 39651da177e4SLinus Torvalds } 39661da177e4SLinus Torvalds return 0; 39676ecaff7fSRandy Dunlap 39686ecaff7fSRandy Dunlap bus_unreg: 39696ecaff7fSRandy Dunlap bus_unregister(&pseudo_lld_bus); 39706ecaff7fSRandy Dunlap dev_unreg: 39719b906779SNicholas Bellinger root_device_unregister(pseudo_primary); 39726ecaff7fSRandy Dunlap free_vm: 397344d92694SMartin K. Petersen if (map_storep) 397444d92694SMartin K. Petersen vfree(map_storep); 3975c6a44287SMartin K. Petersen if (dif_storep) 3976c6a44287SMartin K. Petersen vfree(dif_storep); 39776ecaff7fSRandy Dunlap vfree(fake_storep); 39786ecaff7fSRandy Dunlap 39796ecaff7fSRandy Dunlap return ret; 39801da177e4SLinus Torvalds } 39811da177e4SLinus Torvalds 39821da177e4SLinus Torvalds static void __exit scsi_debug_exit(void) 39831da177e4SLinus Torvalds { 39841da177e4SLinus Torvalds int k = scsi_debug_add_host; 39851da177e4SLinus Torvalds 39861da177e4SLinus Torvalds stop_all_queued(); 3987cbf67842SDouglas Gilbert free_all_queued(); 39881da177e4SLinus Torvalds for (; k; k--) 39891da177e4SLinus Torvalds sdebug_remove_adapter(); 39901da177e4SLinus Torvalds driver_unregister(&sdebug_driverfs_driver); 39911da177e4SLinus Torvalds bus_unregister(&pseudo_lld_bus); 39929b906779SNicholas Bellinger root_device_unregister(pseudo_primary); 39931da177e4SLinus Torvalds 3994c6a44287SMartin K. Petersen if (dif_storep) 3995c6a44287SMartin K. Petersen vfree(dif_storep); 3996c6a44287SMartin K. Petersen 39971da177e4SLinus Torvalds vfree(fake_storep); 39981da177e4SLinus Torvalds } 39991da177e4SLinus Torvalds 40001da177e4SLinus Torvalds device_initcall(scsi_debug_init); 40011da177e4SLinus Torvalds module_exit(scsi_debug_exit); 40021da177e4SLinus Torvalds 40031da177e4SLinus Torvalds static void sdebug_release_adapter(struct device * dev) 40041da177e4SLinus Torvalds { 40051da177e4SLinus Torvalds struct sdebug_host_info *sdbg_host; 40061da177e4SLinus Torvalds 40071da177e4SLinus Torvalds sdbg_host = to_sdebug_host(dev); 40081da177e4SLinus Torvalds kfree(sdbg_host); 40091da177e4SLinus Torvalds } 40101da177e4SLinus Torvalds 40111da177e4SLinus Torvalds static int sdebug_add_adapter(void) 40121da177e4SLinus Torvalds { 40131da177e4SLinus Torvalds int k, devs_per_host; 40141da177e4SLinus Torvalds int error = 0; 40151da177e4SLinus Torvalds struct sdebug_host_info *sdbg_host; 40168b40228fSFUJITA Tomonori struct sdebug_dev_info *sdbg_devinfo, *tmp; 40171da177e4SLinus Torvalds 401824669f75SJes Sorensen sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); 40191da177e4SLinus Torvalds if (NULL == sdbg_host) { 40201da177e4SLinus Torvalds printk(KERN_ERR "%s: out of memory at line %d\n", 4021cadbd4a5SHarvey Harrison __func__, __LINE__); 40221da177e4SLinus Torvalds return -ENOMEM; 40231da177e4SLinus Torvalds } 40241da177e4SLinus Torvalds 40251da177e4SLinus Torvalds INIT_LIST_HEAD(&sdbg_host->dev_info_list); 40261da177e4SLinus Torvalds 40271da177e4SLinus Torvalds devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns; 40281da177e4SLinus Torvalds for (k = 0; k < devs_per_host; k++) { 40295cb2fc06SFUJITA Tomonori sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL); 40305cb2fc06SFUJITA Tomonori if (!sdbg_devinfo) { 40311da177e4SLinus Torvalds printk(KERN_ERR "%s: out of memory at line %d\n", 4032cadbd4a5SHarvey Harrison __func__, __LINE__); 40331da177e4SLinus Torvalds error = -ENOMEM; 40341da177e4SLinus Torvalds goto clean; 40351da177e4SLinus Torvalds } 40361da177e4SLinus Torvalds } 40371da177e4SLinus Torvalds 40381da177e4SLinus Torvalds spin_lock(&sdebug_host_list_lock); 40391da177e4SLinus Torvalds list_add_tail(&sdbg_host->host_list, &sdebug_host_list); 40401da177e4SLinus Torvalds spin_unlock(&sdebug_host_list_lock); 40411da177e4SLinus Torvalds 40421da177e4SLinus Torvalds sdbg_host->dev.bus = &pseudo_lld_bus; 40439b906779SNicholas Bellinger sdbg_host->dev.parent = pseudo_primary; 40441da177e4SLinus Torvalds sdbg_host->dev.release = &sdebug_release_adapter; 404571610f55SKay Sievers dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host); 40461da177e4SLinus Torvalds 40471da177e4SLinus Torvalds error = device_register(&sdbg_host->dev); 40481da177e4SLinus Torvalds 40491da177e4SLinus Torvalds if (error) 40501da177e4SLinus Torvalds goto clean; 40511da177e4SLinus Torvalds 40521da177e4SLinus Torvalds ++scsi_debug_add_host; 40531da177e4SLinus Torvalds return error; 40541da177e4SLinus Torvalds 40551da177e4SLinus Torvalds clean: 40568b40228fSFUJITA Tomonori list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list, 40578b40228fSFUJITA Tomonori dev_list) { 40581da177e4SLinus Torvalds list_del(&sdbg_devinfo->dev_list); 40591da177e4SLinus Torvalds kfree(sdbg_devinfo); 40601da177e4SLinus Torvalds } 40611da177e4SLinus Torvalds 40621da177e4SLinus Torvalds kfree(sdbg_host); 40631da177e4SLinus Torvalds return error; 40641da177e4SLinus Torvalds } 40651da177e4SLinus Torvalds 40661da177e4SLinus Torvalds static void sdebug_remove_adapter(void) 40671da177e4SLinus Torvalds { 40681da177e4SLinus Torvalds struct sdebug_host_info * sdbg_host = NULL; 40691da177e4SLinus Torvalds 40701da177e4SLinus Torvalds spin_lock(&sdebug_host_list_lock); 40711da177e4SLinus Torvalds if (!list_empty(&sdebug_host_list)) { 40721da177e4SLinus Torvalds sdbg_host = list_entry(sdebug_host_list.prev, 40731da177e4SLinus Torvalds struct sdebug_host_info, host_list); 40741da177e4SLinus Torvalds list_del(&sdbg_host->host_list); 40751da177e4SLinus Torvalds } 40761da177e4SLinus Torvalds spin_unlock(&sdebug_host_list_lock); 40771da177e4SLinus Torvalds 40781da177e4SLinus Torvalds if (!sdbg_host) 40791da177e4SLinus Torvalds return; 40801da177e4SLinus Torvalds 40811da177e4SLinus Torvalds device_unregister(&sdbg_host->dev); 40821da177e4SLinus Torvalds --scsi_debug_add_host; 40831da177e4SLinus Torvalds } 40841da177e4SLinus Torvalds 4085cbf67842SDouglas Gilbert static int 4086cbf67842SDouglas Gilbert scsi_debug_queuecommand(struct scsi_cmnd *SCpnt) 4087639db475SFUJITA Tomonori { 408801123ef4SDouglas Gilbert unsigned char *cmd = SCpnt->cmnd; 4089639db475SFUJITA Tomonori int len, k; 4090639db475SFUJITA Tomonori unsigned int num; 4091639db475SFUJITA Tomonori unsigned long long lba; 4092395cef03SMartin K. Petersen u32 ei_lba; 4093639db475SFUJITA Tomonori int errsts = 0; 4094639db475SFUJITA Tomonori int target = SCpnt->device->id; 4095639db475SFUJITA Tomonori struct sdebug_dev_info *devip = NULL; 4096639db475SFUJITA Tomonori int inj_recovered = 0; 4097639db475SFUJITA Tomonori int inj_transport = 0; 4098c6a44287SMartin K. Petersen int inj_dif = 0; 4099c6a44287SMartin K. Petersen int inj_dix = 0; 4100b57d7c01SChristoph Hellwig int inj_short = 0; 4101639db475SFUJITA Tomonori int delay_override = 0; 410244d92694SMartin K. Petersen int unmap = 0; 4103639db475SFUJITA Tomonori 4104639db475SFUJITA Tomonori scsi_set_resid(SCpnt, 0); 4105cbf67842SDouglas Gilbert if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && 410601123ef4SDouglas Gilbert !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) { 4107cbf67842SDouglas Gilbert char b[120]; 4108cbf67842SDouglas Gilbert int n; 4109639db475SFUJITA Tomonori 4110cbf67842SDouglas Gilbert len = SCpnt->cmd_len; 4111cbf67842SDouglas Gilbert if (len > 32) 4112cbf67842SDouglas Gilbert strcpy(b, "too long, over 32 bytes"); 4113cbf67842SDouglas Gilbert else { 4114cbf67842SDouglas Gilbert for (k = 0, n = 0; k < len; ++k) 4115cbf67842SDouglas Gilbert n += scnprintf(b + n, sizeof(b) - n, "%02x ", 4116cbf67842SDouglas Gilbert (unsigned int)cmd[k]); 4117cbf67842SDouglas Gilbert } 4118cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name, 4119cbf67842SDouglas Gilbert b); 4120639db475SFUJITA Tomonori } 4121639db475SFUJITA Tomonori 4122639db475SFUJITA Tomonori if ((SCpnt->device->lun >= scsi_debug_max_luns) && 4123639db475SFUJITA Tomonori (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) 4124cbf67842SDouglas Gilbert return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); 4125639db475SFUJITA Tomonori devip = devInfoReg(SCpnt->device); 4126639db475SFUJITA Tomonori if (NULL == devip) 4127cbf67842SDouglas Gilbert return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); 4128639db475SFUJITA Tomonori 4129639db475SFUJITA Tomonori if ((scsi_debug_every_nth != 0) && 4130cbf67842SDouglas Gilbert (atomic_inc_return(&sdebug_cmnd_count) >= 4131cbf67842SDouglas Gilbert abs(scsi_debug_every_nth))) { 4132cbf67842SDouglas Gilbert atomic_set(&sdebug_cmnd_count, 0); 4133639db475SFUJITA Tomonori if (scsi_debug_every_nth < -1) 4134639db475SFUJITA Tomonori scsi_debug_every_nth = -1; 4135639db475SFUJITA Tomonori if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) 4136639db475SFUJITA Tomonori return 0; /* ignore command causing timeout */ 413718a4d0a2SMartin K. Petersen else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts && 413818a4d0a2SMartin K. Petersen scsi_medium_access_command(SCpnt)) 413918a4d0a2SMartin K. Petersen return 0; /* time out reads and writes */ 4140639db475SFUJITA Tomonori else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) 4141639db475SFUJITA Tomonori inj_recovered = 1; /* to reads and writes below */ 4142639db475SFUJITA Tomonori else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) 4143639db475SFUJITA Tomonori inj_transport = 1; /* to reads and writes below */ 4144c6a44287SMartin K. Petersen else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts) 4145c6a44287SMartin K. Petersen inj_dif = 1; /* to reads and writes below */ 4146c6a44287SMartin K. Petersen else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts) 4147c6a44287SMartin K. Petersen inj_dix = 1; /* to reads and writes below */ 4148b57d7c01SChristoph Hellwig else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & scsi_debug_opts) 4149b57d7c01SChristoph Hellwig inj_short = 1; 4150639db475SFUJITA Tomonori } 4151639db475SFUJITA Tomonori 4152639db475SFUJITA Tomonori if (devip->wlun) { 4153639db475SFUJITA Tomonori switch (*cmd) { 4154639db475SFUJITA Tomonori case INQUIRY: 4155639db475SFUJITA Tomonori case REQUEST_SENSE: 4156639db475SFUJITA Tomonori case TEST_UNIT_READY: 4157639db475SFUJITA Tomonori case REPORT_LUNS: 4158639db475SFUJITA Tomonori break; /* only allowable wlun commands */ 4159639db475SFUJITA Tomonori default: 4160639db475SFUJITA Tomonori if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 4161639db475SFUJITA Tomonori printk(KERN_INFO "scsi_debug: Opcode: 0x%x " 4162639db475SFUJITA Tomonori "not supported for wlun\n", *cmd); 4163cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4164639db475SFUJITA Tomonori INVALID_OPCODE, 0); 4165639db475SFUJITA Tomonori errsts = check_condition_result; 4166cbf67842SDouglas Gilbert return schedule_resp(SCpnt, devip, errsts, 0); 4167639db475SFUJITA Tomonori } 4168639db475SFUJITA Tomonori } 4169639db475SFUJITA Tomonori 4170639db475SFUJITA Tomonori switch (*cmd) { 4171639db475SFUJITA Tomonori case INQUIRY: /* mandatory, ignore unit attention */ 4172639db475SFUJITA Tomonori delay_override = 1; 4173639db475SFUJITA Tomonori errsts = resp_inquiry(SCpnt, target, devip); 4174639db475SFUJITA Tomonori break; 4175639db475SFUJITA Tomonori case REQUEST_SENSE: /* mandatory, ignore unit attention */ 4176639db475SFUJITA Tomonori delay_override = 1; 4177639db475SFUJITA Tomonori errsts = resp_requests(SCpnt, devip); 4178639db475SFUJITA Tomonori break; 4179639db475SFUJITA Tomonori case REZERO_UNIT: /* actually this is REWIND for SSC */ 4180639db475SFUJITA Tomonori case START_STOP: 4181639db475SFUJITA Tomonori errsts = resp_start_stop(SCpnt, devip); 4182639db475SFUJITA Tomonori break; 4183639db475SFUJITA Tomonori case ALLOW_MEDIUM_REMOVAL: 4184cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4185639db475SFUJITA Tomonori if (errsts) 4186639db475SFUJITA Tomonori break; 4187639db475SFUJITA Tomonori if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 4188639db475SFUJITA Tomonori printk(KERN_INFO "scsi_debug: Medium removal %s\n", 4189639db475SFUJITA Tomonori cmd[4] ? "inhibited" : "enabled"); 4190639db475SFUJITA Tomonori break; 4191639db475SFUJITA Tomonori case SEND_DIAGNOSTIC: /* mandatory */ 4192cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4193639db475SFUJITA Tomonori break; 4194639db475SFUJITA Tomonori case TEST_UNIT_READY: /* mandatory */ 4195cbf67842SDouglas Gilbert /* delay_override = 1; */ 4196cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 4197639db475SFUJITA Tomonori break; 4198639db475SFUJITA Tomonori case RESERVE: 4199cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4200639db475SFUJITA Tomonori break; 4201639db475SFUJITA Tomonori case RESERVE_10: 4202cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4203639db475SFUJITA Tomonori break; 4204639db475SFUJITA Tomonori case RELEASE: 4205cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4206639db475SFUJITA Tomonori break; 4207639db475SFUJITA Tomonori case RELEASE_10: 4208cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4209639db475SFUJITA Tomonori break; 4210639db475SFUJITA Tomonori case READ_CAPACITY: 4211639db475SFUJITA Tomonori errsts = resp_readcap(SCpnt, devip); 4212639db475SFUJITA Tomonori break; 4213639db475SFUJITA Tomonori case SERVICE_ACTION_IN: 421444d92694SMartin K. Petersen if (cmd[1] == SAI_READ_CAPACITY_16) 421544d92694SMartin K. Petersen errsts = resp_readcap16(SCpnt, devip); 421644d92694SMartin K. Petersen else if (cmd[1] == SAI_GET_LBA_STATUS) { 421744d92694SMartin K. Petersen 42185b94e232SMartin K. Petersen if (scsi_debug_lbp() == 0) { 4219cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 422044d92694SMartin K. Petersen INVALID_COMMAND_OPCODE, 0); 422144d92694SMartin K. Petersen errsts = check_condition_result; 422244d92694SMartin K. Petersen } else 422344d92694SMartin K. Petersen errsts = resp_get_lba_status(SCpnt, devip); 422444d92694SMartin K. Petersen } else { 4225cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4226639db475SFUJITA Tomonori INVALID_OPCODE, 0); 4227639db475SFUJITA Tomonori errsts = check_condition_result; 4228639db475SFUJITA Tomonori } 4229639db475SFUJITA Tomonori break; 4230639db475SFUJITA Tomonori case MAINTENANCE_IN: 4231639db475SFUJITA Tomonori if (MI_REPORT_TARGET_PGS != cmd[1]) { 4232cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4233639db475SFUJITA Tomonori INVALID_OPCODE, 0); 4234639db475SFUJITA Tomonori errsts = check_condition_result; 4235639db475SFUJITA Tomonori break; 4236639db475SFUJITA Tomonori } 4237639db475SFUJITA Tomonori errsts = resp_report_tgtpgs(SCpnt, devip); 4238639db475SFUJITA Tomonori break; 4239639db475SFUJITA Tomonori case READ_16: 4240639db475SFUJITA Tomonori case READ_12: 4241639db475SFUJITA Tomonori case READ_10: 4242395cef03SMartin K. Petersen /* READ{10,12,16} and DIF Type 2 are natural enemies */ 4243395cef03SMartin K. Petersen if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && 4244395cef03SMartin K. Petersen cmd[1] & 0xe0) { 4245cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4246395cef03SMartin K. Petersen INVALID_COMMAND_OPCODE, 0); 4247395cef03SMartin K. Petersen errsts = check_condition_result; 4248395cef03SMartin K. Petersen break; 4249395cef03SMartin K. Petersen } 4250395cef03SMartin K. Petersen 4251395cef03SMartin K. Petersen if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || 4252395cef03SMartin K. Petersen scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && 4253395cef03SMartin K. Petersen (cmd[1] & 0xe0) == 0) 4254395cef03SMartin K. Petersen printk(KERN_ERR "Unprotected RD/WR to DIF device\n"); 4255395cef03SMartin K. Petersen 4256395cef03SMartin K. Petersen /* fall through */ 4257639db475SFUJITA Tomonori case READ_6: 4258395cef03SMartin K. Petersen read: 4259cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 4260639db475SFUJITA Tomonori if (errsts) 4261639db475SFUJITA Tomonori break; 4262639db475SFUJITA Tomonori if (scsi_debug_fake_rw) 4263639db475SFUJITA Tomonori break; 4264395cef03SMartin K. Petersen get_data_transfer_info(cmd, &lba, &num, &ei_lba); 4265b57d7c01SChristoph Hellwig 4266b57d7c01SChristoph Hellwig if (inj_short) 4267b57d7c01SChristoph Hellwig num /= 2; 4268b57d7c01SChristoph Hellwig 4269cbf67842SDouglas Gilbert errsts = resp_read(SCpnt, lba, num, ei_lba); 4270639db475SFUJITA Tomonori if (inj_recovered && (0 == errsts)) { 4271cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, RECOVERED_ERROR, 4272639db475SFUJITA Tomonori THRESHOLD_EXCEEDED, 0); 4273639db475SFUJITA Tomonori errsts = check_condition_result; 4274639db475SFUJITA Tomonori } else if (inj_transport && (0 == errsts)) { 4275cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ABORTED_COMMAND, 4276639db475SFUJITA Tomonori TRANSPORT_PROBLEM, ACK_NAK_TO); 4277639db475SFUJITA Tomonori errsts = check_condition_result; 4278c6a44287SMartin K. Petersen } else if (inj_dif && (0 == errsts)) { 4279cbf67842SDouglas Gilbert /* Logical block guard check failed */ 4280cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); 4281c6a44287SMartin K. Petersen errsts = illegal_condition_result; 4282c6a44287SMartin K. Petersen } else if (inj_dix && (0 == errsts)) { 4283cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); 4284c6a44287SMartin K. Petersen errsts = illegal_condition_result; 4285639db475SFUJITA Tomonori } 4286639db475SFUJITA Tomonori break; 4287639db475SFUJITA Tomonori case REPORT_LUNS: /* mandatory, ignore unit attention */ 4288639db475SFUJITA Tomonori delay_override = 1; 4289639db475SFUJITA Tomonori errsts = resp_report_luns(SCpnt, devip); 4290639db475SFUJITA Tomonori break; 4291639db475SFUJITA Tomonori case VERIFY: /* 10 byte SBC-2 command */ 4292cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 4293639db475SFUJITA Tomonori break; 4294639db475SFUJITA Tomonori case WRITE_16: 4295639db475SFUJITA Tomonori case WRITE_12: 4296639db475SFUJITA Tomonori case WRITE_10: 4297395cef03SMartin K. Petersen /* WRITE{10,12,16} and DIF Type 2 are natural enemies */ 4298395cef03SMartin K. Petersen if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && 4299395cef03SMartin K. Petersen cmd[1] & 0xe0) { 4300cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4301395cef03SMartin K. Petersen INVALID_COMMAND_OPCODE, 0); 4302395cef03SMartin K. Petersen errsts = check_condition_result; 4303395cef03SMartin K. Petersen break; 4304395cef03SMartin K. Petersen } 4305395cef03SMartin K. Petersen 4306395cef03SMartin K. Petersen if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || 4307395cef03SMartin K. Petersen scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && 4308395cef03SMartin K. Petersen (cmd[1] & 0xe0) == 0) 4309395cef03SMartin K. Petersen printk(KERN_ERR "Unprotected RD/WR to DIF device\n"); 4310395cef03SMartin K. Petersen 4311395cef03SMartin K. Petersen /* fall through */ 4312639db475SFUJITA Tomonori case WRITE_6: 4313395cef03SMartin K. Petersen write: 4314cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 4315639db475SFUJITA Tomonori if (errsts) 4316639db475SFUJITA Tomonori break; 4317639db475SFUJITA Tomonori if (scsi_debug_fake_rw) 4318639db475SFUJITA Tomonori break; 4319395cef03SMartin K. Petersen get_data_transfer_info(cmd, &lba, &num, &ei_lba); 4320cbf67842SDouglas Gilbert errsts = resp_write(SCpnt, lba, num, ei_lba); 4321639db475SFUJITA Tomonori if (inj_recovered && (0 == errsts)) { 4322cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, RECOVERED_ERROR, 4323639db475SFUJITA Tomonori THRESHOLD_EXCEEDED, 0); 4324639db475SFUJITA Tomonori errsts = check_condition_result; 4325c6a44287SMartin K. Petersen } else if (inj_dif && (0 == errsts)) { 4326cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); 4327c6a44287SMartin K. Petersen errsts = illegal_condition_result; 4328c6a44287SMartin K. Petersen } else if (inj_dix && (0 == errsts)) { 4329cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); 4330c6a44287SMartin K. Petersen errsts = illegal_condition_result; 4331639db475SFUJITA Tomonori } 4332639db475SFUJITA Tomonori break; 433344d92694SMartin K. Petersen case WRITE_SAME_16: 43345b94e232SMartin K. Petersen case WRITE_SAME: 43356014759cSMartin K. Petersen if (cmd[1] & 0x8) { 43365b94e232SMartin K. Petersen if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) || 43375b94e232SMartin K. Petersen (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) { 4338cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 43396014759cSMartin K. Petersen INVALID_FIELD_IN_CDB, 0); 43406014759cSMartin K. Petersen errsts = check_condition_result; 43416014759cSMartin K. Petersen } else 434244d92694SMartin K. Petersen unmap = 1; 43436014759cSMartin K. Petersen } 43446014759cSMartin K. Petersen if (errsts) 43456014759cSMartin K. Petersen break; 4346cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 434744d92694SMartin K. Petersen if (errsts) 434844d92694SMartin K. Petersen break; 4349cbf67842SDouglas Gilbert if (scsi_debug_fake_rw) 4350cbf67842SDouglas Gilbert break; 435144d92694SMartin K. Petersen get_data_transfer_info(cmd, &lba, &num, &ei_lba); 4352cbf67842SDouglas Gilbert errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap); 435344d92694SMartin K. Petersen break; 435444d92694SMartin K. Petersen case UNMAP: 4355cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 435644d92694SMartin K. Petersen if (errsts) 435744d92694SMartin K. Petersen break; 4358cbf67842SDouglas Gilbert if (scsi_debug_fake_rw) 4359cbf67842SDouglas Gilbert break; 436044d92694SMartin K. Petersen 43615b94e232SMartin K. Petersen if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) { 4362cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 436344d92694SMartin K. Petersen INVALID_COMMAND_OPCODE, 0); 436444d92694SMartin K. Petersen errsts = check_condition_result; 436544d92694SMartin K. Petersen } else 436644d92694SMartin K. Petersen errsts = resp_unmap(SCpnt, devip); 436744d92694SMartin K. Petersen break; 4368639db475SFUJITA Tomonori case MODE_SENSE: 4369639db475SFUJITA Tomonori case MODE_SENSE_10: 4370639db475SFUJITA Tomonori errsts = resp_mode_sense(SCpnt, target, devip); 4371639db475SFUJITA Tomonori break; 4372639db475SFUJITA Tomonori case MODE_SELECT: 4373639db475SFUJITA Tomonori errsts = resp_mode_select(SCpnt, 1, devip); 4374639db475SFUJITA Tomonori break; 4375639db475SFUJITA Tomonori case MODE_SELECT_10: 4376639db475SFUJITA Tomonori errsts = resp_mode_select(SCpnt, 0, devip); 4377639db475SFUJITA Tomonori break; 4378639db475SFUJITA Tomonori case LOG_SENSE: 4379639db475SFUJITA Tomonori errsts = resp_log_sense(SCpnt, devip); 4380639db475SFUJITA Tomonori break; 4381639db475SFUJITA Tomonori case SYNCHRONIZE_CACHE: 4382639db475SFUJITA Tomonori delay_override = 1; 4383cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 4384639db475SFUJITA Tomonori break; 4385639db475SFUJITA Tomonori case WRITE_BUFFER: 4386cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4387639db475SFUJITA Tomonori break; 4388639db475SFUJITA Tomonori case XDWRITEREAD_10: 4389639db475SFUJITA Tomonori if (!scsi_bidi_cmnd(SCpnt)) { 4390cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4391639db475SFUJITA Tomonori INVALID_FIELD_IN_CDB, 0); 4392639db475SFUJITA Tomonori errsts = check_condition_result; 4393639db475SFUJITA Tomonori break; 4394639db475SFUJITA Tomonori } 4395639db475SFUJITA Tomonori 4396cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_TUR, devip); 4397639db475SFUJITA Tomonori if (errsts) 4398639db475SFUJITA Tomonori break; 4399639db475SFUJITA Tomonori if (scsi_debug_fake_rw) 4400639db475SFUJITA Tomonori break; 4401395cef03SMartin K. Petersen get_data_transfer_info(cmd, &lba, &num, &ei_lba); 4402cbf67842SDouglas Gilbert errsts = resp_read(SCpnt, lba, num, ei_lba); 4403639db475SFUJITA Tomonori if (errsts) 4404639db475SFUJITA Tomonori break; 4405cbf67842SDouglas Gilbert errsts = resp_write(SCpnt, lba, num, ei_lba); 4406639db475SFUJITA Tomonori if (errsts) 4407639db475SFUJITA Tomonori break; 4408639db475SFUJITA Tomonori errsts = resp_xdwriteread(SCpnt, lba, num, devip); 4409639db475SFUJITA Tomonori break; 4410395cef03SMartin K. Petersen case VARIABLE_LENGTH_CMD: 4411395cef03SMartin K. Petersen if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) { 4412395cef03SMartin K. Petersen 4413395cef03SMartin K. Petersen if ((cmd[10] & 0xe0) == 0) 4414395cef03SMartin K. Petersen printk(KERN_ERR 4415395cef03SMartin K. Petersen "Unprotected RD/WR to DIF device\n"); 4416395cef03SMartin K. Petersen 4417395cef03SMartin K. Petersen if (cmd[9] == READ_32) { 4418395cef03SMartin K. Petersen BUG_ON(SCpnt->cmd_len < 32); 4419395cef03SMartin K. Petersen goto read; 4420395cef03SMartin K. Petersen } 4421395cef03SMartin K. Petersen 4422395cef03SMartin K. Petersen if (cmd[9] == WRITE_32) { 4423395cef03SMartin K. Petersen BUG_ON(SCpnt->cmd_len < 32); 4424395cef03SMartin K. Petersen goto write; 4425395cef03SMartin K. Petersen } 4426395cef03SMartin K. Petersen } 4427395cef03SMartin K. Petersen 4428cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4429395cef03SMartin K. Petersen INVALID_FIELD_IN_CDB, 0); 4430395cef03SMartin K. Petersen errsts = check_condition_result; 4431395cef03SMartin K. Petersen break; 4432cbf67842SDouglas Gilbert case 0x85: 4433cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 4434cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, 4435cbf67842SDouglas Gilbert "%s: ATA PASS-THROUGH(16) not supported\n", my_name); 4436cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 4437cbf67842SDouglas Gilbert INVALID_OPCODE, 0); 4438cbf67842SDouglas Gilbert errsts = check_condition_result; 4439cbf67842SDouglas Gilbert break; 4440639db475SFUJITA Tomonori default: 4441639db475SFUJITA Tomonori if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 4442cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, SCpnt->device, 4443cbf67842SDouglas Gilbert "%s: Opcode: 0x%x not supported\n", 4444cbf67842SDouglas Gilbert my_name, *cmd); 4445cbf67842SDouglas Gilbert errsts = check_readiness(SCpnt, UAS_ONLY, devip); 4446639db475SFUJITA Tomonori if (errsts) 4447639db475SFUJITA Tomonori break; /* Unit attention takes precedence */ 4448cbf67842SDouglas Gilbert mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); 4449639db475SFUJITA Tomonori errsts = check_condition_result; 4450639db475SFUJITA Tomonori break; 4451639db475SFUJITA Tomonori } 4452cbf67842SDouglas Gilbert return schedule_resp(SCpnt, devip, errsts, 4453639db475SFUJITA Tomonori (delay_override ? 0 : scsi_debug_delay)); 4454639db475SFUJITA Tomonori } 4455639db475SFUJITA Tomonori 4456cbf67842SDouglas Gilbert static int 4457cbf67842SDouglas Gilbert sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd) 4458cbf67842SDouglas Gilbert { 4459cbf67842SDouglas Gilbert if (scsi_debug_host_lock) { 4460cbf67842SDouglas Gilbert unsigned long iflags; 4461cbf67842SDouglas Gilbert int rc; 4462cbf67842SDouglas Gilbert 4463cbf67842SDouglas Gilbert spin_lock_irqsave(shost->host_lock, iflags); 4464cbf67842SDouglas Gilbert rc = scsi_debug_queuecommand(cmd); 4465cbf67842SDouglas Gilbert spin_unlock_irqrestore(shost->host_lock, iflags); 4466cbf67842SDouglas Gilbert return rc; 4467cbf67842SDouglas Gilbert } else 4468cbf67842SDouglas Gilbert return scsi_debug_queuecommand(cmd); 4469cbf67842SDouglas Gilbert } 4470cbf67842SDouglas Gilbert 4471cbf67842SDouglas Gilbert static int 4472cbf67842SDouglas Gilbert sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason) 4473cbf67842SDouglas Gilbert { 4474cbf67842SDouglas Gilbert int num_in_q = 0; 4475cbf67842SDouglas Gilbert unsigned long iflags; 4476cbf67842SDouglas Gilbert struct sdebug_dev_info *devip; 4477cbf67842SDouglas Gilbert 4478cbf67842SDouglas Gilbert spin_lock_irqsave(&queued_arr_lock, iflags); 4479cbf67842SDouglas Gilbert devip = (struct sdebug_dev_info *)sdev->hostdata; 4480cbf67842SDouglas Gilbert if (NULL == devip) { 4481cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 4482cbf67842SDouglas Gilbert return -ENODEV; 4483cbf67842SDouglas Gilbert } 4484cbf67842SDouglas Gilbert num_in_q = atomic_read(&devip->num_in_q); 4485cbf67842SDouglas Gilbert spin_unlock_irqrestore(&queued_arr_lock, iflags); 4486c40ecc12SChristoph Hellwig 4487cbf67842SDouglas Gilbert if (qdepth < 1) 4488cbf67842SDouglas Gilbert qdepth = 1; 4489cbf67842SDouglas Gilbert /* allow to exceed max host queued_arr elements for testing */ 4490cbf67842SDouglas Gilbert if (qdepth > SCSI_DEBUG_CANQUEUE + 10) 4491cbf67842SDouglas Gilbert qdepth = SCSI_DEBUG_CANQUEUE + 10; 4492c8b09f6fSChristoph Hellwig scsi_adjust_queue_depth(sdev, qdepth); 4493cbf67842SDouglas Gilbert 4494c40ecc12SChristoph Hellwig if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { 4495cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdev, 4496c40ecc12SChristoph Hellwig "%s: qdepth=%d, num_in_q=%d\n", 4497c40ecc12SChristoph Hellwig __func__, qdepth, num_in_q); 4498cbf67842SDouglas Gilbert } 4499cbf67842SDouglas Gilbert return sdev->queue_depth; 4500cbf67842SDouglas Gilbert } 4501cbf67842SDouglas Gilbert 4502cbf67842SDouglas Gilbert static int 4503cbf67842SDouglas Gilbert sdebug_change_qtype(struct scsi_device *sdev, int qtype) 4504cbf67842SDouglas Gilbert { 4505a62182f3SChristoph Hellwig qtype = scsi_change_queue_type(sdev, qtype); 4506cbf67842SDouglas Gilbert if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { 4507cbf67842SDouglas Gilbert const char *cp; 4508cbf67842SDouglas Gilbert 4509cbf67842SDouglas Gilbert switch (qtype) { 4510cbf67842SDouglas Gilbert case 0: 4511cbf67842SDouglas Gilbert cp = "untagged"; 4512cbf67842SDouglas Gilbert break; 4513cbf67842SDouglas Gilbert case MSG_SIMPLE_TAG: 4514cbf67842SDouglas Gilbert cp = "simple tags"; 4515cbf67842SDouglas Gilbert break; 4516cbf67842SDouglas Gilbert case MSG_ORDERED_TAG: 4517cbf67842SDouglas Gilbert cp = "ordered tags"; 4518cbf67842SDouglas Gilbert break; 4519cbf67842SDouglas Gilbert default: 4520cbf67842SDouglas Gilbert cp = "unknown"; 4521cbf67842SDouglas Gilbert break; 4522cbf67842SDouglas Gilbert } 4523cbf67842SDouglas Gilbert sdev_printk(KERN_INFO, sdev, "%s: to %s\n", __func__, cp); 4524cbf67842SDouglas Gilbert } 4525cbf67842SDouglas Gilbert return qtype; 4526cbf67842SDouglas Gilbert } 4527f281233dSJeff Garzik 45289e603ca0SFUJITA Tomonori static struct scsi_host_template sdebug_driver_template = { 4529c8ed555aSAl Viro .show_info = scsi_debug_show_info, 4530c8ed555aSAl Viro .write_info = scsi_debug_write_info, 45319e603ca0SFUJITA Tomonori .proc_name = sdebug_proc_name, 45329e603ca0SFUJITA Tomonori .name = "SCSI DEBUG", 45339e603ca0SFUJITA Tomonori .info = scsi_debug_info, 45349e603ca0SFUJITA Tomonori .slave_alloc = scsi_debug_slave_alloc, 45359e603ca0SFUJITA Tomonori .slave_configure = scsi_debug_slave_configure, 45369e603ca0SFUJITA Tomonori .slave_destroy = scsi_debug_slave_destroy, 45379e603ca0SFUJITA Tomonori .ioctl = scsi_debug_ioctl, 4538cbf67842SDouglas Gilbert .queuecommand = sdebug_queuecommand_lock_or_not, 4539cbf67842SDouglas Gilbert .change_queue_depth = sdebug_change_qdepth, 4540cbf67842SDouglas Gilbert .change_queue_type = sdebug_change_qtype, 45419e603ca0SFUJITA Tomonori .eh_abort_handler = scsi_debug_abort, 45429e603ca0SFUJITA Tomonori .eh_device_reset_handler = scsi_debug_device_reset, 4543cbf67842SDouglas Gilbert .eh_target_reset_handler = scsi_debug_target_reset, 4544cbf67842SDouglas Gilbert .eh_bus_reset_handler = scsi_debug_bus_reset, 45459e603ca0SFUJITA Tomonori .eh_host_reset_handler = scsi_debug_host_reset, 45469e603ca0SFUJITA Tomonori .can_queue = SCSI_DEBUG_CANQUEUE, 45479e603ca0SFUJITA Tomonori .this_id = 7, 45486bb5e6e7SAkinobu Mita .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, 4549cbf67842SDouglas Gilbert .cmd_per_lun = DEF_CMD_PER_LUN, 45506bb5e6e7SAkinobu Mita .max_sectors = -1U, 45519e603ca0SFUJITA Tomonori .use_clustering = DISABLE_CLUSTERING, 45529e603ca0SFUJITA Tomonori .module = THIS_MODULE, 4553c40ecc12SChristoph Hellwig .track_queue_depth = 1, 45549e603ca0SFUJITA Tomonori }; 45559e603ca0SFUJITA Tomonori 45561da177e4SLinus Torvalds static int sdebug_driver_probe(struct device * dev) 45571da177e4SLinus Torvalds { 45581da177e4SLinus Torvalds int error = 0; 45591da177e4SLinus Torvalds struct sdebug_host_info *sdbg_host; 45601da177e4SLinus Torvalds struct Scsi_Host *hpnt; 4561c6a44287SMartin K. Petersen int host_prot; 45621da177e4SLinus Torvalds 45631da177e4SLinus Torvalds sdbg_host = to_sdebug_host(dev); 45641da177e4SLinus Torvalds 456578d4e5a0SDouglas Gilbert sdebug_driver_template.can_queue = scsi_debug_max_queue; 45660759c666SAkinobu Mita if (scsi_debug_clustering) 45670759c666SAkinobu Mita sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; 45681da177e4SLinus Torvalds hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); 45691da177e4SLinus Torvalds if (NULL == hpnt) { 457017c9ff52SFinn Thain pr_err("%s: scsi_host_alloc failed\n", __func__); 45711da177e4SLinus Torvalds error = -ENODEV; 45721da177e4SLinus Torvalds return error; 45731da177e4SLinus Torvalds } 45741da177e4SLinus Torvalds 45751da177e4SLinus Torvalds sdbg_host->shost = hpnt; 45761da177e4SLinus Torvalds *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; 45771da177e4SLinus Torvalds if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id)) 45781da177e4SLinus Torvalds hpnt->max_id = scsi_debug_num_tgts + 1; 45791da177e4SLinus Torvalds else 45801da177e4SLinus Torvalds hpnt->max_id = scsi_debug_num_tgts; 4581c65b1445SDouglas Gilbert hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */ 45821da177e4SLinus Torvalds 4583c6a44287SMartin K. Petersen host_prot = 0; 4584c6a44287SMartin K. Petersen 4585c6a44287SMartin K. Petersen switch (scsi_debug_dif) { 4586c6a44287SMartin K. Petersen 4587c6a44287SMartin K. Petersen case SD_DIF_TYPE1_PROTECTION: 4588c6a44287SMartin K. Petersen host_prot = SHOST_DIF_TYPE1_PROTECTION; 4589c6a44287SMartin K. Petersen if (scsi_debug_dix) 4590c6a44287SMartin K. Petersen host_prot |= SHOST_DIX_TYPE1_PROTECTION; 4591c6a44287SMartin K. Petersen break; 4592c6a44287SMartin K. Petersen 4593c6a44287SMartin K. Petersen case SD_DIF_TYPE2_PROTECTION: 4594c6a44287SMartin K. Petersen host_prot = SHOST_DIF_TYPE2_PROTECTION; 4595c6a44287SMartin K. Petersen if (scsi_debug_dix) 4596c6a44287SMartin K. Petersen host_prot |= SHOST_DIX_TYPE2_PROTECTION; 4597c6a44287SMartin K. Petersen break; 4598c6a44287SMartin K. Petersen 4599c6a44287SMartin K. Petersen case SD_DIF_TYPE3_PROTECTION: 4600c6a44287SMartin K. Petersen host_prot = SHOST_DIF_TYPE3_PROTECTION; 4601c6a44287SMartin K. Petersen if (scsi_debug_dix) 4602c6a44287SMartin K. Petersen host_prot |= SHOST_DIX_TYPE3_PROTECTION; 4603c6a44287SMartin K. Petersen break; 4604c6a44287SMartin K. Petersen 4605c6a44287SMartin K. Petersen default: 4606c6a44287SMartin K. Petersen if (scsi_debug_dix) 4607c6a44287SMartin K. Petersen host_prot |= SHOST_DIX_TYPE0_PROTECTION; 4608c6a44287SMartin K. Petersen break; 4609c6a44287SMartin K. Petersen } 4610c6a44287SMartin K. Petersen 4611c6a44287SMartin K. Petersen scsi_host_set_prot(hpnt, host_prot); 4612c6a44287SMartin K. Petersen 4613c6a44287SMartin K. Petersen printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n", 4614c6a44287SMartin K. Petersen (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", 4615c6a44287SMartin K. Petersen (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", 4616c6a44287SMartin K. Petersen (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", 4617c6a44287SMartin K. Petersen (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "", 4618c6a44287SMartin K. Petersen (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "", 4619c6a44287SMartin K. Petersen (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "", 4620c6a44287SMartin K. Petersen (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : ""); 4621c6a44287SMartin K. Petersen 4622c6a44287SMartin K. Petersen if (scsi_debug_guard == 1) 4623c6a44287SMartin K. Petersen scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP); 4624c6a44287SMartin K. Petersen else 4625c6a44287SMartin K. Petersen scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); 4626c6a44287SMartin K. Petersen 46271da177e4SLinus Torvalds error = scsi_add_host(hpnt, &sdbg_host->dev); 46281da177e4SLinus Torvalds if (error) { 4629cadbd4a5SHarvey Harrison printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); 46301da177e4SLinus Torvalds error = -ENODEV; 46311da177e4SLinus Torvalds scsi_host_put(hpnt); 46321da177e4SLinus Torvalds } else 46331da177e4SLinus Torvalds scsi_scan_host(hpnt); 46341da177e4SLinus Torvalds 46351da177e4SLinus Torvalds return error; 46361da177e4SLinus Torvalds } 46371da177e4SLinus Torvalds 46381da177e4SLinus Torvalds static int sdebug_driver_remove(struct device * dev) 46391da177e4SLinus Torvalds { 46401da177e4SLinus Torvalds struct sdebug_host_info *sdbg_host; 46418b40228fSFUJITA Tomonori struct sdebug_dev_info *sdbg_devinfo, *tmp; 46421da177e4SLinus Torvalds 46431da177e4SLinus Torvalds sdbg_host = to_sdebug_host(dev); 46441da177e4SLinus Torvalds 46451da177e4SLinus Torvalds if (!sdbg_host) { 46461da177e4SLinus Torvalds printk(KERN_ERR "%s: Unable to locate host info\n", 4647cadbd4a5SHarvey Harrison __func__); 46481da177e4SLinus Torvalds return -ENODEV; 46491da177e4SLinus Torvalds } 46501da177e4SLinus Torvalds 46511da177e4SLinus Torvalds scsi_remove_host(sdbg_host->shost); 46521da177e4SLinus Torvalds 46538b40228fSFUJITA Tomonori list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list, 46548b40228fSFUJITA Tomonori dev_list) { 46551da177e4SLinus Torvalds list_del(&sdbg_devinfo->dev_list); 46561da177e4SLinus Torvalds kfree(sdbg_devinfo); 46571da177e4SLinus Torvalds } 46581da177e4SLinus Torvalds 46591da177e4SLinus Torvalds scsi_host_put(sdbg_host->shost); 46601da177e4SLinus Torvalds return 0; 46611da177e4SLinus Torvalds } 46621da177e4SLinus Torvalds 46638dea0d02SFUJITA Tomonori static int pseudo_lld_bus_match(struct device *dev, 46648dea0d02SFUJITA Tomonori struct device_driver *dev_driver) 46651da177e4SLinus Torvalds { 46668dea0d02SFUJITA Tomonori return 1; 46678dea0d02SFUJITA Tomonori } 46681da177e4SLinus Torvalds 46698dea0d02SFUJITA Tomonori static struct bus_type pseudo_lld_bus = { 46708dea0d02SFUJITA Tomonori .name = "pseudo", 46718dea0d02SFUJITA Tomonori .match = pseudo_lld_bus_match, 46728dea0d02SFUJITA Tomonori .probe = sdebug_driver_probe, 46738dea0d02SFUJITA Tomonori .remove = sdebug_driver_remove, 467482069379SAkinobu Mita .drv_groups = sdebug_drv_groups, 46758dea0d02SFUJITA Tomonori }; 4676