diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 1981 |
1 files changed, 1305 insertions, 676 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 238e06f13b8a..7b8b51bc29b4 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -63,8 +63,8 @@ | |||
63 | #include "sd.h" | 63 | #include "sd.h" |
64 | #include "scsi_logging.h" | 64 | #include "scsi_logging.h" |
65 | 65 | ||
66 | #define SCSI_DEBUG_VERSION "1.84" | 66 | #define SCSI_DEBUG_VERSION "1.85" |
67 | static const char *scsi_debug_version_date = "20140706"; | 67 | static const char *scsi_debug_version_date = "20141022"; |
68 | 68 | ||
69 | #define MY_NAME "scsi_debug" | 69 | #define MY_NAME "scsi_debug" |
70 | 70 | ||
@@ -75,19 +75,22 @@ static const char *scsi_debug_version_date = "20140706"; | |||
75 | #define UNRECOVERED_READ_ERR 0x11 | 75 | #define UNRECOVERED_READ_ERR 0x11 |
76 | #define PARAMETER_LIST_LENGTH_ERR 0x1a | 76 | #define PARAMETER_LIST_LENGTH_ERR 0x1a |
77 | #define INVALID_OPCODE 0x20 | 77 | #define INVALID_OPCODE 0x20 |
78 | #define ADDR_OUT_OF_RANGE 0x21 | 78 | #define LBA_OUT_OF_RANGE 0x21 |
79 | #define INVALID_COMMAND_OPCODE 0x20 | ||
80 | #define INVALID_FIELD_IN_CDB 0x24 | 79 | #define INVALID_FIELD_IN_CDB 0x24 |
81 | #define INVALID_FIELD_IN_PARAM_LIST 0x26 | 80 | #define INVALID_FIELD_IN_PARAM_LIST 0x26 |
82 | #define UA_RESET_ASC 0x29 | 81 | #define UA_RESET_ASC 0x29 |
83 | #define UA_CHANGED_ASC 0x2a | 82 | #define UA_CHANGED_ASC 0x2a |
83 | #define INSUFF_RES_ASC 0x55 | ||
84 | #define INSUFF_RES_ASCQ 0x3 | ||
84 | #define POWER_ON_RESET_ASCQ 0x0 | 85 | #define POWER_ON_RESET_ASCQ 0x0 |
85 | #define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */ | 86 | #define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */ |
86 | #define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */ | 87 | #define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */ |
88 | #define CAPACITY_CHANGED_ASCQ 0x9 | ||
87 | #define SAVING_PARAMS_UNSUP 0x39 | 89 | #define SAVING_PARAMS_UNSUP 0x39 |
88 | #define TRANSPORT_PROBLEM 0x4b | 90 | #define TRANSPORT_PROBLEM 0x4b |
89 | #define THRESHOLD_EXCEEDED 0x5d | 91 | #define THRESHOLD_EXCEEDED 0x5d |
90 | #define LOW_POWER_COND_ON 0x5e | 92 | #define LOW_POWER_COND_ON 0x5e |
93 | #define MISCOMPARE_VERIFY_ASC 0x1d | ||
91 | 94 | ||
92 | /* Additional Sense Code Qualifier (ASCQ) */ | 95 | /* Additional Sense Code Qualifier (ASCQ) */ |
93 | #define ACK_NAK_TO 0x3 | 96 | #define ACK_NAK_TO 0x3 |
@@ -125,7 +128,6 @@ static const char *scsi_debug_version_date = "20140706"; | |||
125 | #define DEF_REMOVABLE false | 128 | #define DEF_REMOVABLE false |
126 | #define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */ | 129 | #define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */ |
127 | #define DEF_SECTOR_SIZE 512 | 130 | #define DEF_SECTOR_SIZE 512 |
128 | #define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ | ||
129 | #define DEF_UNMAP_ALIGNMENT 0 | 131 | #define DEF_UNMAP_ALIGNMENT 0 |
130 | #define DEF_UNMAP_GRANULARITY 1 | 132 | #define DEF_UNMAP_GRANULARITY 1 |
131 | #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF | 133 | #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF |
@@ -133,6 +135,7 @@ static const char *scsi_debug_version_date = "20140706"; | |||
133 | #define DEF_VIRTUAL_GB 0 | 135 | #define DEF_VIRTUAL_GB 0 |
134 | #define DEF_VPD_USE_HOSTNO 1 | 136 | #define DEF_VPD_USE_HOSTNO 1 |
135 | #define DEF_WRITESAME_LENGTH 0xFFFF | 137 | #define DEF_WRITESAME_LENGTH 0xFFFF |
138 | #define DEF_STRICT 0 | ||
136 | #define DELAY_OVERRIDDEN -9999 | 139 | #define DELAY_OVERRIDDEN -9999 |
137 | 140 | ||
138 | /* bit mask values for scsi_debug_opts */ | 141 | /* bit mask values for scsi_debug_opts */ |
@@ -176,11 +179,12 @@ static const char *scsi_debug_version_date = "20140706"; | |||
176 | #define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */ | 179 | #define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */ |
177 | #define SDEBUG_UA_BUS_RESET 1 | 180 | #define SDEBUG_UA_BUS_RESET 1 |
178 | #define SDEBUG_UA_MODE_CHANGED 2 | 181 | #define SDEBUG_UA_MODE_CHANGED 2 |
179 | #define SDEBUG_NUM_UAS 3 | 182 | #define SDEBUG_UA_CAPACITY_CHANGED 3 |
183 | #define SDEBUG_NUM_UAS 4 | ||
180 | 184 | ||
181 | /* for check_readiness() */ | 185 | /* for check_readiness() */ |
182 | #define UAS_ONLY 1 | 186 | #define UAS_ONLY 1 /* check for UAs only */ |
183 | #define UAS_TUR 0 | 187 | #define UAS_TUR 0 /* if no UAs then check if media access possible */ |
184 | 188 | ||
185 | /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this | 189 | /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this |
186 | * sector on read commands: */ | 190 | * sector on read commands: */ |
@@ -206,6 +210,301 @@ static const char *scsi_debug_version_date = "20140706"; | |||
206 | #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" | 210 | #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" |
207 | #endif | 211 | #endif |
208 | 212 | ||
213 | /* SCSI opcodes (first byte of cdb) mapped onto these indexes */ | ||
214 | enum sdeb_opcode_index { | ||
215 | SDEB_I_INVALID_OPCODE = 0, | ||
216 | SDEB_I_INQUIRY = 1, | ||
217 | SDEB_I_REPORT_LUNS = 2, | ||
218 | SDEB_I_REQUEST_SENSE = 3, | ||
219 | SDEB_I_TEST_UNIT_READY = 4, | ||
220 | SDEB_I_MODE_SENSE = 5, /* 6, 10 */ | ||
221 | SDEB_I_MODE_SELECT = 6, /* 6, 10 */ | ||
222 | SDEB_I_LOG_SENSE = 7, | ||
223 | SDEB_I_READ_CAPACITY = 8, /* 10; 16 is in SA_IN(16) */ | ||
224 | SDEB_I_READ = 9, /* 6, 10, 12, 16 */ | ||
225 | SDEB_I_WRITE = 10, /* 6, 10, 12, 16 */ | ||
226 | SDEB_I_START_STOP = 11, | ||
227 | SDEB_I_SERV_ACT_IN = 12, /* 12, 16 */ | ||
228 | SDEB_I_SERV_ACT_OUT = 13, /* 12, 16 */ | ||
229 | SDEB_I_MAINT_IN = 14, | ||
230 | SDEB_I_MAINT_OUT = 15, | ||
231 | SDEB_I_VERIFY = 16, /* 10 only */ | ||
232 | SDEB_I_VARIABLE_LEN = 17, | ||
233 | SDEB_I_RESERVE = 18, /* 6, 10 */ | ||
234 | SDEB_I_RELEASE = 19, /* 6, 10 */ | ||
235 | SDEB_I_ALLOW_REMOVAL = 20, /* PREVENT ALLOW MEDIUM REMOVAL */ | ||
236 | SDEB_I_REZERO_UNIT = 21, /* REWIND in SSC */ | ||
237 | SDEB_I_ATA_PT = 22, /* 12, 16 */ | ||
238 | SDEB_I_SEND_DIAG = 23, | ||
239 | SDEB_I_UNMAP = 24, | ||
240 | SDEB_I_XDWRITEREAD = 25, /* 10 only */ | ||
241 | SDEB_I_WRITE_BUFFER = 26, | ||
242 | SDEB_I_WRITE_SAME = 27, /* 10, 16 */ | ||
243 | SDEB_I_SYNC_CACHE = 28, /* 10 only */ | ||
244 | SDEB_I_COMP_WRITE = 29, | ||
245 | SDEB_I_LAST_ELEMENT = 30, /* keep this last */ | ||
246 | }; | ||
247 | |||
248 | static const unsigned char opcode_ind_arr[256] = { | ||
249 | /* 0x0; 0x0->0x1f: 6 byte cdbs */ | ||
250 | SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE, | ||
251 | 0, 0, 0, 0, | ||
252 | SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0, | ||
253 | 0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE, | ||
254 | SDEB_I_RELEASE, | ||
255 | 0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG, | ||
256 | SDEB_I_ALLOW_REMOVAL, 0, | ||
257 | /* 0x20; 0x20->0x3f: 10 byte cdbs */ | ||
258 | 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0, | ||
259 | SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY, | ||
260 | 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0, | ||
261 | 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0, | ||
262 | /* 0x40; 0x40->0x5f: 10 byte cdbs */ | ||
263 | 0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0, | ||
264 | 0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0, | ||
265 | 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE, | ||
266 | SDEB_I_RELEASE, | ||
267 | 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0, | ||
268 | /* 0x60; 0x60->0x7d are reserved */ | ||
269 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
270 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
271 | 0, SDEB_I_VARIABLE_LEN, | ||
272 | /* 0x80; 0x80->0x9f: 16 byte cdbs */ | ||
273 | 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0, | ||
274 | SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0, | ||
275 | 0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0, | ||
276 | 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN, SDEB_I_SERV_ACT_OUT, | ||
277 | /* 0xa0; 0xa0->0xbf: 12 byte cdbs */ | ||
278 | SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN, | ||
279 | SDEB_I_MAINT_OUT, 0, 0, 0, | ||
280 | SDEB_I_READ, SDEB_I_SERV_ACT_OUT, SDEB_I_WRITE, SDEB_I_SERV_ACT_IN, | ||
281 | 0, 0, 0, 0, | ||
282 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
283 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
284 | /* 0xc0; 0xc0->0xff: vendor specific */ | ||
285 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
286 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
287 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
288 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
289 | }; | ||
290 | |||
291 | #define F_D_IN 1 | ||
292 | #define F_D_OUT 2 | ||
293 | #define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */ | ||
294 | #define F_D_UNKN 8 | ||
295 | #define F_RL_WLUN_OK 0x10 | ||
296 | #define F_SKIP_UA 0x20 | ||
297 | #define F_DELAY_OVERR 0x40 | ||
298 | #define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */ | ||
299 | #define F_SA_HIGH 0x100 /* as used by variable length cdbs */ | ||
300 | #define F_INV_OP 0x200 | ||
301 | #define F_FAKE_RW 0x400 | ||
302 | #define F_M_ACCESS 0x800 /* media access */ | ||
303 | |||
304 | #define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR) | ||
305 | #define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW) | ||
306 | #define FF_SA (F_SA_HIGH | F_SA_LOW) | ||
307 | |||
308 | struct sdebug_dev_info; | ||
309 | static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
310 | static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
311 | static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
312 | static int resp_mode_sense(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
313 | static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
314 | static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
315 | static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
316 | static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
317 | static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
318 | static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
319 | static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
320 | static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
321 | static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
322 | static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
323 | static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
324 | static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
325 | static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
326 | static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
327 | static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
328 | static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
329 | |||
330 | struct opcode_info_t { | ||
331 | u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff | ||
332 | * for terminating element */ | ||
333 | u8 opcode; /* if num_attached > 0, preferred */ | ||
334 | u16 sa; /* service action */ | ||
335 | u32 flags; /* OR-ed set of SDEB_F_* */ | ||
336 | int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *); | ||
337 | const struct opcode_info_t *arrp; /* num_attached elements or NULL */ | ||
338 | u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */ | ||
339 | /* ignore cdb bytes after position 15 */ | ||
340 | }; | ||
341 | |||
342 | static const struct opcode_info_t msense_iarr[1] = { | ||
343 | {0, 0x1a, 0, F_D_IN, NULL, NULL, | ||
344 | {6, 0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
345 | }; | ||
346 | |||
347 | static const struct opcode_info_t mselect_iarr[1] = { | ||
348 | {0, 0x15, 0, F_D_OUT, NULL, NULL, | ||
349 | {6, 0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
350 | }; | ||
351 | |||
352 | static const struct opcode_info_t read_iarr[3] = { | ||
353 | {0, 0x28, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(10) */ | ||
354 | {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0, | ||
355 | 0, 0, 0, 0} }, | ||
356 | {0, 0x8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL, /* READ(6) */ | ||
357 | {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
358 | {0, 0xa8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(12) */ | ||
359 | {12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, | ||
360 | 0xc7, 0, 0, 0, 0} }, | ||
361 | }; | ||
362 | |||
363 | static const struct opcode_info_t write_iarr[3] = { | ||
364 | {0, 0x2a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 10 */ | ||
365 | {10, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0, | ||
366 | 0, 0, 0, 0} }, | ||
367 | {0, 0xa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 6 */ | ||
368 | {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
369 | {0, 0xaa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 12 */ | ||
370 | {12, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, | ||
371 | 0xc7, 0, 0, 0, 0} }, | ||
372 | }; | ||
373 | |||
374 | static const struct opcode_info_t sa_in_iarr[1] = { | ||
375 | {0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL, | ||
376 | {16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
377 | 0xff, 0xff, 0xff, 0, 0xc7} }, | ||
378 | }; | ||
379 | |||
380 | static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */ | ||
381 | {0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_DIRECT_IO, resp_write_dt0, | ||
382 | NULL, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0xb, 0xfa, | ||
383 | 0, 0xff, 0xff, 0xff, 0xff} }, /* WRITE(32) */ | ||
384 | }; | ||
385 | |||
386 | static const struct opcode_info_t maint_in_iarr[2] = { | ||
387 | {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL, | ||
388 | {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, | ||
389 | 0xc7, 0, 0, 0, 0} }, | ||
390 | {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL, | ||
391 | {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, | ||
392 | 0, 0} }, | ||
393 | }; | ||
394 | |||
395 | static const struct opcode_info_t write_same_iarr[1] = { | ||
396 | {0, 0x93, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_16, NULL, | ||
397 | {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
398 | 0xff, 0xff, 0xff, 0x1f, 0xc7} }, | ||
399 | }; | ||
400 | |||
401 | static const struct opcode_info_t reserve_iarr[1] = { | ||
402 | {0, 0x16, 0, F_D_OUT, NULL, NULL, /* RESERVE(6) */ | ||
403 | {6, 0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
404 | }; | ||
405 | |||
406 | static const struct opcode_info_t release_iarr[1] = { | ||
407 | {0, 0x17, 0, F_D_OUT, NULL, NULL, /* RELEASE(6) */ | ||
408 | {6, 0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
409 | }; | ||
410 | |||
411 | |||
412 | /* This array is accessed via SDEB_I_* values. Make sure all are mapped, | ||
413 | * plus the terminating elements for logic that scans this table such as | ||
414 | * REPORT SUPPORTED OPERATION CODES. */ | ||
415 | static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = { | ||
416 | /* 0 */ | ||
417 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, | ||
418 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
419 | {0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL, | ||
420 | {6, 0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
421 | {0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL, | ||
422 | {12, 0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, | ||
423 | 0, 0} }, | ||
424 | {0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL, | ||
425 | {6, 0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
426 | {0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */ | ||
427 | {6, 0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
428 | {1, 0x5a, 0, F_D_IN, resp_mode_sense, msense_iarr, | ||
429 | {10, 0xf8, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, | ||
430 | 0} }, | ||
431 | {1, 0x55, 0, F_D_OUT, resp_mode_select, mselect_iarr, | ||
432 | {10, 0xf1, 0, 0, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, | ||
433 | {0, 0x4d, 0, F_D_IN, resp_log_sense, NULL, | ||
434 | {10, 0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, | ||
435 | 0, 0, 0} }, | ||
436 | {0, 0x25, 0, F_D_IN, resp_readcap, NULL, | ||
437 | {10, 0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0, | ||
438 | 0, 0} }, | ||
439 | {3, 0x88, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, read_iarr, | ||
440 | {16, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
441 | 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* READ(16) */ | ||
442 | /* 10 */ | ||
443 | {3, 0x8a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, write_iarr, | ||
444 | {16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
445 | 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* WRITE(16) */ | ||
446 | {0, 0x1b, 0, 0, resp_start_stop, NULL, /* START STOP UNIT */ | ||
447 | {6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
448 | {1, 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_iarr, | ||
449 | {16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
450 | 0xff, 0xff, 0xff, 0x1, 0xc7} }, /* READ CAPACITY(16) */ | ||
451 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* SA OUT */ | ||
452 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
453 | {2, 0xa3, 0xa, F_SA_LOW | F_D_IN, resp_report_tgtpgs, maint_in_iarr, | ||
454 | {12, 0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 0, | ||
455 | 0} }, | ||
456 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */ | ||
457 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
458 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* VERIFY */ | ||
459 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
460 | {1, 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_DIRECT_IO, resp_read_dt0, | ||
461 | vl_iarr, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0x9, 0xfe, 0, | ||
462 | 0xff, 0xff, 0xff, 0xff} },/* VARIABLE LENGTH, READ(32) */ | ||
463 | {1, 0x56, 0, F_D_OUT, NULL, reserve_iarr, /* RESERVE(10) */ | ||
464 | {10, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, | ||
465 | 0} }, | ||
466 | {1, 0x57, 0, F_D_OUT, NULL, release_iarr, /* RELEASE(10) */ | ||
467 | {10, 0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, | ||
468 | 0} }, | ||
469 | /* 20 */ | ||
470 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ALLOW REMOVAL */ | ||
471 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
472 | {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */ | ||
473 | {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
474 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */ | ||
475 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
476 | {0, 0x1d, F_D_OUT, 0, NULL, NULL, /* SEND DIAGNOSTIC */ | ||
477 | {6, 0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
478 | {0, 0x42, 0, F_D_OUT | FF_DIRECT_IO, resp_unmap, NULL, /* UNMAP */ | ||
479 | {10, 0x1, 0, 0, 0, 0, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, | ||
480 | {0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10, | ||
481 | NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, | ||
482 | 0, 0, 0, 0, 0, 0} }, | ||
483 | {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* WRITE_BUFFER */ | ||
484 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
485 | {1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10, | ||
486 | write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, | ||
487 | 0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, | ||
488 | {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */ | ||
489 | {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0, | ||
490 | 0, 0, 0, 0} }, | ||
491 | {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL, | ||
492 | {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, | ||
493 | 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */ | ||
494 | |||
495 | /* 30 */ | ||
496 | {0xff, 0, 0, 0, NULL, NULL, /* terminating element */ | ||
497 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, | ||
498 | }; | ||
499 | |||
500 | struct sdebug_scmd_extra_t { | ||
501 | bool inj_recovered; | ||
502 | bool inj_transport; | ||
503 | bool inj_dif; | ||
504 | bool inj_dix; | ||
505 | bool inj_short; | ||
506 | }; | ||
507 | |||
209 | static int scsi_debug_add_host = DEF_NUM_HOST; | 508 | static int scsi_debug_add_host = DEF_NUM_HOST; |
210 | static int scsi_debug_ato = DEF_ATO; | 509 | static int scsi_debug_ato = DEF_ATO; |
211 | static int scsi_debug_delay = DEF_DELAY; | 510 | static int scsi_debug_delay = DEF_DELAY; |
@@ -245,6 +544,8 @@ static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; | |||
245 | static bool scsi_debug_removable = DEF_REMOVABLE; | 544 | static bool scsi_debug_removable = DEF_REMOVABLE; |
246 | static bool scsi_debug_clustering; | 545 | static bool scsi_debug_clustering; |
247 | static bool scsi_debug_host_lock = DEF_HOST_LOCK; | 546 | static bool scsi_debug_host_lock = DEF_HOST_LOCK; |
547 | static bool scsi_debug_strict = DEF_STRICT; | ||
548 | static bool sdebug_any_injecting_opt; | ||
248 | 549 | ||
249 | static atomic_t sdebug_cmnd_count; | 550 | static atomic_t sdebug_cmnd_count; |
250 | static atomic_t sdebug_completions; | 551 | static atomic_t sdebug_completions; |
@@ -277,11 +578,10 @@ struct sdebug_dev_info { | |||
277 | unsigned int target; | 578 | unsigned int target; |
278 | u64 lun; | 579 | u64 lun; |
279 | struct sdebug_host_info *sdbg_host; | 580 | struct sdebug_host_info *sdbg_host; |
280 | u64 wlun; | ||
281 | unsigned long uas_bm[1]; | 581 | unsigned long uas_bm[1]; |
282 | atomic_t num_in_q; | 582 | atomic_t num_in_q; |
283 | char stopped; | 583 | char stopped; /* TODO: should be atomic */ |
284 | char used; | 584 | bool used; |
285 | }; | 585 | }; |
286 | 586 | ||
287 | struct sdebug_host_info { | 587 | struct sdebug_host_info { |
@@ -394,6 +694,50 @@ static void sdebug_max_tgts_luns(void) | |||
394 | spin_unlock(&sdebug_host_list_lock); | 694 | spin_unlock(&sdebug_host_list_lock); |
395 | } | 695 | } |
396 | 696 | ||
697 | enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1}; | ||
698 | |||
699 | /* Set in_bit to -1 to indicate no bit position of invalid field */ | ||
700 | static void | ||
701 | mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d, | ||
702 | int in_byte, int in_bit) | ||
703 | { | ||
704 | unsigned char *sbuff; | ||
705 | u8 sks[4]; | ||
706 | int sl, asc; | ||
707 | |||
708 | sbuff = scp->sense_buffer; | ||
709 | if (!sbuff) { | ||
710 | sdev_printk(KERN_ERR, scp->device, | ||
711 | "%s: sense_buffer is NULL\n", __func__); | ||
712 | return; | ||
713 | } | ||
714 | asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST; | ||
715 | memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE); | ||
716 | scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST, | ||
717 | asc, 0); | ||
718 | memset(sks, 0, sizeof(sks)); | ||
719 | sks[0] = 0x80; | ||
720 | if (c_d) | ||
721 | sks[0] |= 0x40; | ||
722 | if (in_bit >= 0) { | ||
723 | sks[0] |= 0x8; | ||
724 | sks[0] |= 0x7 & in_bit; | ||
725 | } | ||
726 | put_unaligned_be16(in_byte, sks + 1); | ||
727 | if (scsi_debug_dsense) { | ||
728 | sl = sbuff[7] + 8; | ||
729 | sbuff[7] = sl; | ||
730 | sbuff[sl] = 0x2; | ||
731 | sbuff[sl + 1] = 0x6; | ||
732 | memcpy(sbuff + sl + 4, sks, 3); | ||
733 | } else | ||
734 | memcpy(sbuff + 15, sks, 3); | ||
735 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
736 | sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq" | ||
737 | "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n", | ||
738 | my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit); | ||
739 | } | ||
740 | |||
397 | static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) | 741 | static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) |
398 | { | 742 | { |
399 | unsigned char *sbuff; | 743 | unsigned char *sbuff; |
@@ -414,63 +758,10 @@ static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) | |||
414 | my_name, key, asc, asq); | 758 | my_name, key, asc, asq); |
415 | } | 759 | } |
416 | 760 | ||
417 | static void get_data_transfer_info(unsigned char *cmd, | 761 | static void |
418 | unsigned long long *lba, unsigned int *num, | 762 | mk_sense_invalid_opcode(struct scsi_cmnd *scp) |
419 | u32 *ei_lba) | ||
420 | { | 763 | { |
421 | *ei_lba = 0; | 764 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0); |
422 | |||
423 | switch (*cmd) { | ||
424 | case VARIABLE_LENGTH_CMD: | ||
425 | *lba = (u64)cmd[19] | (u64)cmd[18] << 8 | | ||
426 | (u64)cmd[17] << 16 | (u64)cmd[16] << 24 | | ||
427 | (u64)cmd[15] << 32 | (u64)cmd[14] << 40 | | ||
428 | (u64)cmd[13] << 48 | (u64)cmd[12] << 56; | ||
429 | |||
430 | *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 | | ||
431 | (u32)cmd[21] << 16 | (u32)cmd[20] << 24; | ||
432 | |||
433 | *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 | | ||
434 | (u32)cmd[28] << 24; | ||
435 | break; | ||
436 | |||
437 | case WRITE_SAME_16: | ||
438 | case WRITE_16: | ||
439 | case READ_16: | ||
440 | *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | | ||
441 | (u64)cmd[7] << 16 | (u64)cmd[6] << 24 | | ||
442 | (u64)cmd[5] << 32 | (u64)cmd[4] << 40 | | ||
443 | (u64)cmd[3] << 48 | (u64)cmd[2] << 56; | ||
444 | |||
445 | *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 | | ||
446 | (u32)cmd[10] << 24; | ||
447 | break; | ||
448 | case WRITE_12: | ||
449 | case READ_12: | ||
450 | *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | | ||
451 | (u32)cmd[2] << 24; | ||
452 | |||
453 | *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 | | ||
454 | (u32)cmd[6] << 24; | ||
455 | break; | ||
456 | case WRITE_SAME: | ||
457 | case WRITE_10: | ||
458 | case READ_10: | ||
459 | case XDWRITEREAD_10: | ||
460 | *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | | ||
461 | (u32)cmd[2] << 24; | ||
462 | |||
463 | *num = (u32)cmd[8] | (u32)cmd[7] << 8; | ||
464 | break; | ||
465 | case WRITE_6: | ||
466 | case READ_6: | ||
467 | *lba = (u32)cmd[3] | (u32)cmd[2] << 8 | | ||
468 | (u32)(cmd[1] & 0x1f) << 16; | ||
469 | *num = (0 == cmd[4]) ? 256 : cmd[4]; | ||
470 | break; | ||
471 | default: | ||
472 | break; | ||
473 | } | ||
474 | } | 765 | } |
475 | 766 | ||
476 | static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) | 767 | static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) |
@@ -520,6 +811,12 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, | |||
520 | if (debug) | 811 | if (debug) |
521 | cp = "mode parameters changed"; | 812 | cp = "mode parameters changed"; |
522 | break; | 813 | break; |
814 | case SDEBUG_UA_CAPACITY_CHANGED: | ||
815 | mk_sense_buffer(SCpnt, UNIT_ATTENTION, | ||
816 | UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ); | ||
817 | if (debug) | ||
818 | cp = "capacity data changed"; | ||
819 | break; | ||
523 | default: | 820 | default: |
524 | pr_warn("%s: unexpected unit attention code=%d\n", | 821 | pr_warn("%s: unexpected unit attention code=%d\n", |
525 | __func__, k); | 822 | __func__, k); |
@@ -924,19 +1221,20 @@ static int inquiry_evpd_b2(unsigned char *arr) | |||
924 | #define SDEBUG_LONG_INQ_SZ 96 | 1221 | #define SDEBUG_LONG_INQ_SZ 96 |
925 | #define SDEBUG_MAX_INQ_ARR_SZ 584 | 1222 | #define SDEBUG_MAX_INQ_ARR_SZ 584 |
926 | 1223 | ||
927 | static int resp_inquiry(struct scsi_cmnd *scp, int target, | 1224 | static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
928 | struct sdebug_dev_info * devip) | ||
929 | { | 1225 | { |
930 | unsigned char pq_pdt; | 1226 | unsigned char pq_pdt; |
931 | unsigned char * arr; | 1227 | unsigned char * arr; |
932 | unsigned char *cmd = scp->cmnd; | 1228 | unsigned char *cmd = scp->cmnd; |
933 | int alloc_len, n, ret; | 1229 | int alloc_len, n, ret; |
1230 | bool have_wlun; | ||
934 | 1231 | ||
935 | alloc_len = (cmd[3] << 8) + cmd[4]; | 1232 | alloc_len = (cmd[3] << 8) + cmd[4]; |
936 | arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); | 1233 | arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); |
937 | if (! arr) | 1234 | if (! arr) |
938 | return DID_REQUEUE << 16; | 1235 | return DID_REQUEUE << 16; |
939 | if (devip->wlun) | 1236 | have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS); |
1237 | if (have_wlun) | ||
940 | pq_pdt = 0x1e; /* present, wlun */ | 1238 | pq_pdt = 0x1e; /* present, wlun */ |
941 | else if (scsi_debug_no_lun_0 && (0 == devip->lun)) | 1239 | else if (scsi_debug_no_lun_0 && (0 == devip->lun)) |
942 | pq_pdt = 0x7f; /* not present, no device type */ | 1240 | pq_pdt = 0x7f; /* not present, no device type */ |
@@ -944,8 +1242,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target, | |||
944 | pq_pdt = (scsi_debug_ptype & 0x1f); | 1242 | pq_pdt = (scsi_debug_ptype & 0x1f); |
945 | arr[0] = pq_pdt; | 1243 | arr[0] = pq_pdt; |
946 | if (0x2 & cmd[1]) { /* CMDDT bit set */ | 1244 | if (0x2 & cmd[1]) { /* CMDDT bit set */ |
947 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | 1245 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1); |
948 | 0); | ||
949 | kfree(arr); | 1246 | kfree(arr); |
950 | return check_condition_result; | 1247 | return check_condition_result; |
951 | } else if (0x1 & cmd[1]) { /* EVPD bit set */ | 1248 | } else if (0x1 & cmd[1]) { /* EVPD bit set */ |
@@ -957,7 +1254,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target, | |||
957 | (devip->channel & 0x7f); | 1254 | (devip->channel & 0x7f); |
958 | if (0 == scsi_debug_vpd_use_hostno) | 1255 | if (0 == scsi_debug_vpd_use_hostno) |
959 | host_no = 0; | 1256 | host_no = 0; |
960 | lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) + | 1257 | lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) + |
961 | (devip->target * 1000) + devip->lun); | 1258 | (devip->target * 1000) + devip->lun); |
962 | target_dev_id = ((host_no + 1) * 2000) + | 1259 | target_dev_id = ((host_no + 1) * 2000) + |
963 | (devip->target * 1000) - 3; | 1260 | (devip->target * 1000) - 3; |
@@ -1029,9 +1326,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target, | |||
1029 | arr[1] = cmd[2]; /*sanity */ | 1326 | arr[1] = cmd[2]; /*sanity */ |
1030 | arr[3] = inquiry_evpd_b2(&arr[4]); | 1327 | arr[3] = inquiry_evpd_b2(&arr[4]); |
1031 | } else { | 1328 | } else { |
1032 | /* Illegal request, invalid field in cdb */ | 1329 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1); |
1033 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | ||
1034 | INVALID_FIELD_IN_CDB, 0); | ||
1035 | kfree(arr); | 1330 | kfree(arr); |
1036 | return check_condition_result; | 1331 | return check_condition_result; |
1037 | } | 1332 | } |
@@ -1077,18 +1372,20 @@ static int resp_requests(struct scsi_cmnd * scp, | |||
1077 | unsigned char * sbuff; | 1372 | unsigned char * sbuff; |
1078 | unsigned char *cmd = scp->cmnd; | 1373 | unsigned char *cmd = scp->cmnd; |
1079 | unsigned char arr[SCSI_SENSE_BUFFERSIZE]; | 1374 | unsigned char arr[SCSI_SENSE_BUFFERSIZE]; |
1080 | int want_dsense; | 1375 | bool dsense, want_dsense; |
1081 | int len = 18; | 1376 | int len = 18; |
1082 | 1377 | ||
1083 | memset(arr, 0, sizeof(arr)); | 1378 | memset(arr, 0, sizeof(arr)); |
1084 | want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense; | 1379 | dsense = !!(cmd[1] & 1); |
1380 | want_dsense = dsense || scsi_debug_dsense; | ||
1085 | sbuff = scp->sense_buffer; | 1381 | sbuff = scp->sense_buffer; |
1086 | if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { | 1382 | if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { |
1087 | if (want_dsense) { | 1383 | if (dsense) { |
1088 | arr[0] = 0x72; | 1384 | arr[0] = 0x72; |
1089 | arr[1] = 0x0; /* NO_SENSE in sense_key */ | 1385 | arr[1] = 0x0; /* NO_SENSE in sense_key */ |
1090 | arr[2] = THRESHOLD_EXCEEDED; | 1386 | arr[2] = THRESHOLD_EXCEEDED; |
1091 | arr[3] = 0xff; /* TEST set and MRIE==6 */ | 1387 | arr[3] = 0xff; /* TEST set and MRIE==6 */ |
1388 | len = 8; | ||
1092 | } else { | 1389 | } else { |
1093 | arr[0] = 0x70; | 1390 | arr[0] = 0x70; |
1094 | arr[2] = 0x0; /* NO_SENSE in sense_key */ | 1391 | arr[2] = 0x0; /* NO_SENSE in sense_key */ |
@@ -1098,15 +1395,34 @@ static int resp_requests(struct scsi_cmnd * scp, | |||
1098 | } | 1395 | } |
1099 | } else { | 1396 | } else { |
1100 | memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); | 1397 | memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); |
1101 | if ((cmd[1] & 1) && (! scsi_debug_dsense)) { | 1398 | if (arr[0] >= 0x70 && dsense == scsi_debug_dsense) |
1102 | /* DESC bit set and sense_buff in fixed format */ | 1399 | ; /* have sense and formats match */ |
1103 | memset(arr, 0, sizeof(arr)); | 1400 | else if (arr[0] <= 0x70) { |
1401 | if (dsense) { | ||
1402 | memset(arr, 0, 8); | ||
1403 | arr[0] = 0x72; | ||
1404 | len = 8; | ||
1405 | } else { | ||
1406 | memset(arr, 0, 18); | ||
1407 | arr[0] = 0x70; | ||
1408 | arr[7] = 0xa; | ||
1409 | } | ||
1410 | } else if (dsense) { | ||
1411 | memset(arr, 0, 8); | ||
1104 | arr[0] = 0x72; | 1412 | arr[0] = 0x72; |
1105 | arr[1] = sbuff[2]; /* sense key */ | 1413 | arr[1] = sbuff[2]; /* sense key */ |
1106 | arr[2] = sbuff[12]; /* asc */ | 1414 | arr[2] = sbuff[12]; /* asc */ |
1107 | arr[3] = sbuff[13]; /* ascq */ | 1415 | arr[3] = sbuff[13]; /* ascq */ |
1108 | len = 8; | 1416 | len = 8; |
1417 | } else { | ||
1418 | memset(arr, 0, 18); | ||
1419 | arr[0] = 0x70; | ||
1420 | arr[2] = sbuff[1]; | ||
1421 | arr[7] = 0xa; | ||
1422 | arr[12] = sbuff[1]; | ||
1423 | arr[13] = sbuff[3]; | ||
1109 | } | 1424 | } |
1425 | |||
1110 | } | 1426 | } |
1111 | mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0); | 1427 | mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0); |
1112 | return fill_from_dev_buffer(scp, arr, len); | 1428 | return fill_from_dev_buffer(scp, arr, len); |
@@ -1116,15 +1432,11 @@ static int resp_start_stop(struct scsi_cmnd * scp, | |||
1116 | struct sdebug_dev_info * devip) | 1432 | struct sdebug_dev_info * devip) |
1117 | { | 1433 | { |
1118 | unsigned char *cmd = scp->cmnd; | 1434 | unsigned char *cmd = scp->cmnd; |
1119 | int power_cond, errsts, start; | 1435 | int power_cond, start; |
1120 | 1436 | ||
1121 | errsts = check_readiness(scp, UAS_ONLY, devip); | ||
1122 | if (errsts) | ||
1123 | return errsts; | ||
1124 | power_cond = (cmd[4] & 0xf0) >> 4; | 1437 | power_cond = (cmd[4] & 0xf0) >> 4; |
1125 | if (power_cond) { | 1438 | if (power_cond) { |
1126 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | 1439 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7); |
1127 | 0); | ||
1128 | return check_condition_result; | 1440 | return check_condition_result; |
1129 | } | 1441 | } |
1130 | start = cmd[4] & 1; | 1442 | start = cmd[4] & 1; |
@@ -1148,11 +1460,7 @@ static int resp_readcap(struct scsi_cmnd * scp, | |||
1148 | { | 1460 | { |
1149 | unsigned char arr[SDEBUG_READCAP_ARR_SZ]; | 1461 | unsigned char arr[SDEBUG_READCAP_ARR_SZ]; |
1150 | unsigned int capac; | 1462 | unsigned int capac; |
1151 | int errsts; | ||
1152 | 1463 | ||
1153 | errsts = check_readiness(scp, UAS_ONLY, devip); | ||
1154 | if (errsts) | ||
1155 | return errsts; | ||
1156 | /* following just in case virtual_gb changed */ | 1464 | /* following just in case virtual_gb changed */ |
1157 | sdebug_capacity = get_sdebug_capacity(); | 1465 | sdebug_capacity = get_sdebug_capacity(); |
1158 | memset(arr, 0, SDEBUG_READCAP_ARR_SZ); | 1466 | memset(arr, 0, SDEBUG_READCAP_ARR_SZ); |
@@ -1180,11 +1488,8 @@ static int resp_readcap16(struct scsi_cmnd * scp, | |||
1180 | unsigned char *cmd = scp->cmnd; | 1488 | unsigned char *cmd = scp->cmnd; |
1181 | unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; | 1489 | unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; |
1182 | unsigned long long capac; | 1490 | unsigned long long capac; |
1183 | int errsts, k, alloc_len; | 1491 | int k, alloc_len; |
1184 | 1492 | ||
1185 | errsts = check_readiness(scp, UAS_ONLY, devip); | ||
1186 | if (errsts) | ||
1187 | return errsts; | ||
1188 | alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) | 1493 | alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) |
1189 | + cmd[13]); | 1494 | + cmd[13]); |
1190 | /* following just in case virtual_gb changed */ | 1495 | /* following just in case virtual_gb changed */ |
@@ -1300,6 +1605,184 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, | |||
1300 | return ret; | 1605 | return ret; |
1301 | } | 1606 | } |
1302 | 1607 | ||
1608 | static int | ||
1609 | resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | ||
1610 | { | ||
1611 | bool rctd; | ||
1612 | u8 reporting_opts, req_opcode, sdeb_i, supp; | ||
1613 | u16 req_sa, u; | ||
1614 | u32 alloc_len, a_len; | ||
1615 | int k, offset, len, errsts, count, bump, na; | ||
1616 | const struct opcode_info_t *oip; | ||
1617 | const struct opcode_info_t *r_oip; | ||
1618 | u8 *arr; | ||
1619 | u8 *cmd = scp->cmnd; | ||
1620 | |||
1621 | rctd = !!(cmd[2] & 0x80); | ||
1622 | reporting_opts = cmd[2] & 0x7; | ||
1623 | req_opcode = cmd[3]; | ||
1624 | req_sa = get_unaligned_be16(cmd + 4); | ||
1625 | alloc_len = get_unaligned_be32(cmd + 6); | ||
1626 | if (alloc_len < 4 && alloc_len > 0xffff) { | ||
1627 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1); | ||
1628 | return check_condition_result; | ||
1629 | } | ||
1630 | if (alloc_len > 8192) | ||
1631 | a_len = 8192; | ||
1632 | else | ||
1633 | a_len = alloc_len; | ||
1634 | arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_KERNEL); | ||
1635 | if (NULL == arr) { | ||
1636 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, | ||
1637 | INSUFF_RES_ASCQ); | ||
1638 | return check_condition_result; | ||
1639 | } | ||
1640 | switch (reporting_opts) { | ||
1641 | case 0: /* all commands */ | ||
1642 | /* count number of commands */ | ||
1643 | for (count = 0, oip = opcode_info_arr; | ||
1644 | oip->num_attached != 0xff; ++oip) { | ||
1645 | if (F_INV_OP & oip->flags) | ||
1646 | continue; | ||
1647 | count += (oip->num_attached + 1); | ||
1648 | } | ||
1649 | bump = rctd ? 20 : 8; | ||
1650 | put_unaligned_be32(count * bump, arr); | ||
1651 | for (offset = 4, oip = opcode_info_arr; | ||
1652 | oip->num_attached != 0xff && offset < a_len; ++oip) { | ||
1653 | if (F_INV_OP & oip->flags) | ||
1654 | continue; | ||
1655 | na = oip->num_attached; | ||
1656 | arr[offset] = oip->opcode; | ||
1657 | put_unaligned_be16(oip->sa, arr + offset + 2); | ||
1658 | if (rctd) | ||
1659 | arr[offset + 5] |= 0x2; | ||
1660 | if (FF_SA & oip->flags) | ||
1661 | arr[offset + 5] |= 0x1; | ||
1662 | put_unaligned_be16(oip->len_mask[0], arr + offset + 6); | ||
1663 | if (rctd) | ||
1664 | put_unaligned_be16(0xa, arr + offset + 8); | ||
1665 | r_oip = oip; | ||
1666 | for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) { | ||
1667 | if (F_INV_OP & oip->flags) | ||
1668 | continue; | ||
1669 | offset += bump; | ||
1670 | arr[offset] = oip->opcode; | ||
1671 | put_unaligned_be16(oip->sa, arr + offset + 2); | ||
1672 | if (rctd) | ||
1673 | arr[offset + 5] |= 0x2; | ||
1674 | if (FF_SA & oip->flags) | ||
1675 | arr[offset + 5] |= 0x1; | ||
1676 | put_unaligned_be16(oip->len_mask[0], | ||
1677 | arr + offset + 6); | ||
1678 | if (rctd) | ||
1679 | put_unaligned_be16(0xa, | ||
1680 | arr + offset + 8); | ||
1681 | } | ||
1682 | oip = r_oip; | ||
1683 | offset += bump; | ||
1684 | } | ||
1685 | break; | ||
1686 | case 1: /* one command: opcode only */ | ||
1687 | case 2: /* one command: opcode plus service action */ | ||
1688 | case 3: /* one command: if sa==0 then opcode only else opcode+sa */ | ||
1689 | sdeb_i = opcode_ind_arr[req_opcode]; | ||
1690 | oip = &opcode_info_arr[sdeb_i]; | ||
1691 | if (F_INV_OP & oip->flags) { | ||
1692 | supp = 1; | ||
1693 | offset = 4; | ||
1694 | } else { | ||
1695 | if (1 == reporting_opts) { | ||
1696 | if (FF_SA & oip->flags) { | ||
1697 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, | ||
1698 | 2, 2); | ||
1699 | kfree(arr); | ||
1700 | return check_condition_result; | ||
1701 | } | ||
1702 | req_sa = 0; | ||
1703 | } else if (2 == reporting_opts && | ||
1704 | 0 == (FF_SA & oip->flags)) { | ||
1705 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1); | ||
1706 | kfree(arr); /* point at requested sa */ | ||
1707 | return check_condition_result; | ||
1708 | } | ||
1709 | if (0 == (FF_SA & oip->flags) && | ||
1710 | req_opcode == oip->opcode) | ||
1711 | supp = 3; | ||
1712 | else if (0 == (FF_SA & oip->flags)) { | ||
1713 | na = oip->num_attached; | ||
1714 | for (k = 0, oip = oip->arrp; k < na; | ||
1715 | ++k, ++oip) { | ||
1716 | if (req_opcode == oip->opcode) | ||
1717 | break; | ||
1718 | } | ||
1719 | supp = (k >= na) ? 1 : 3; | ||
1720 | } else if (req_sa != oip->sa) { | ||
1721 | na = oip->num_attached; | ||
1722 | for (k = 0, oip = oip->arrp; k < na; | ||
1723 | ++k, ++oip) { | ||
1724 | if (req_sa == oip->sa) | ||
1725 | break; | ||
1726 | } | ||
1727 | supp = (k >= na) ? 1 : 3; | ||
1728 | } else | ||
1729 | supp = 3; | ||
1730 | if (3 == supp) { | ||
1731 | u = oip->len_mask[0]; | ||
1732 | put_unaligned_be16(u, arr + 2); | ||
1733 | arr[4] = oip->opcode; | ||
1734 | for (k = 1; k < u; ++k) | ||
1735 | arr[4 + k] = (k < 16) ? | ||
1736 | oip->len_mask[k] : 0xff; | ||
1737 | offset = 4 + u; | ||
1738 | } else | ||
1739 | offset = 4; | ||
1740 | } | ||
1741 | arr[1] = (rctd ? 0x80 : 0) | supp; | ||
1742 | if (rctd) { | ||
1743 | put_unaligned_be16(0xa, arr + offset); | ||
1744 | offset += 12; | ||
1745 | } | ||
1746 | break; | ||
1747 | default: | ||
1748 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2); | ||
1749 | kfree(arr); | ||
1750 | return check_condition_result; | ||
1751 | } | ||
1752 | offset = (offset < a_len) ? offset : a_len; | ||
1753 | len = (offset < alloc_len) ? offset : alloc_len; | ||
1754 | errsts = fill_from_dev_buffer(scp, arr, len); | ||
1755 | kfree(arr); | ||
1756 | return errsts; | ||
1757 | } | ||
1758 | |||
1759 | static int | ||
1760 | resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | ||
1761 | { | ||
1762 | bool repd; | ||
1763 | u32 alloc_len, len; | ||
1764 | u8 arr[16]; | ||
1765 | u8 *cmd = scp->cmnd; | ||
1766 | |||
1767 | memset(arr, 0, sizeof(arr)); | ||
1768 | repd = !!(cmd[2] & 0x80); | ||
1769 | alloc_len = get_unaligned_be32(cmd + 6); | ||
1770 | if (alloc_len < 4) { | ||
1771 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1); | ||
1772 | return check_condition_result; | ||
1773 | } | ||
1774 | arr[0] = 0xc8; /* ATS | ATSS | LURS */ | ||
1775 | arr[1] = 0x1; /* ITNRS */ | ||
1776 | if (repd) { | ||
1777 | arr[3] = 0xc; | ||
1778 | len = 16; | ||
1779 | } else | ||
1780 | len = 4; | ||
1781 | |||
1782 | len = (len < alloc_len) ? len : alloc_len; | ||
1783 | return fill_from_dev_buffer(scp, arr, len); | ||
1784 | } | ||
1785 | |||
1303 | /* <<Following mode page info copied from ST318451LW>> */ | 1786 | /* <<Following mode page info copied from ST318451LW>> */ |
1304 | 1787 | ||
1305 | static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) | 1788 | static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) |
@@ -1459,20 +1942,18 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol) | |||
1459 | 1942 | ||
1460 | #define SDEBUG_MAX_MSENSE_SZ 256 | 1943 | #define SDEBUG_MAX_MSENSE_SZ 256 |
1461 | 1944 | ||
1462 | static int resp_mode_sense(struct scsi_cmnd * scp, int target, | 1945 | static int |
1463 | struct sdebug_dev_info * devip) | 1946 | resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
1464 | { | 1947 | { |
1465 | unsigned char dbd, llbaa; | 1948 | unsigned char dbd, llbaa; |
1466 | int pcontrol, pcode, subpcode, bd_len; | 1949 | int pcontrol, pcode, subpcode, bd_len; |
1467 | unsigned char dev_spec; | 1950 | unsigned char dev_spec; |
1468 | int k, alloc_len, msense_6, offset, len, errsts, target_dev_id; | 1951 | int k, alloc_len, msense_6, offset, len, target_dev_id; |
1952 | int target = scp->device->id; | ||
1469 | unsigned char * ap; | 1953 | unsigned char * ap; |
1470 | unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; | 1954 | unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; |
1471 | unsigned char *cmd = scp->cmnd; | 1955 | unsigned char *cmd = scp->cmnd; |
1472 | 1956 | ||
1473 | errsts = check_readiness(scp, UAS_ONLY, devip); | ||
1474 | if (errsts) | ||
1475 | return errsts; | ||
1476 | dbd = !!(cmd[1] & 0x8); | 1957 | dbd = !!(cmd[1] & 0x8); |
1477 | pcontrol = (cmd[2] & 0xc0) >> 6; | 1958 | pcontrol = (cmd[2] & 0xc0) >> 6; |
1478 | pcode = cmd[2] & 0x3f; | 1959 | pcode = cmd[2] & 0x3f; |
@@ -1542,8 +2023,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, | |||
1542 | 2023 | ||
1543 | if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) { | 2024 | if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) { |
1544 | /* TODO: Control Extension page */ | 2025 | /* TODO: Control Extension page */ |
1545 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | 2026 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); |
1546 | 0); | ||
1547 | return check_condition_result; | 2027 | return check_condition_result; |
1548 | } | 2028 | } |
1549 | switch (pcode) { | 2029 | switch (pcode) { |
@@ -1569,8 +2049,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, | |||
1569 | break; | 2049 | break; |
1570 | case 0x19: /* if spc==1 then sas phy, control+discover */ | 2050 | case 0x19: /* if spc==1 then sas phy, control+discover */ |
1571 | if ((subpcode > 0x2) && (subpcode < 0xff)) { | 2051 | if ((subpcode > 0x2) && (subpcode < 0xff)) { |
1572 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2052 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); |
1573 | INVALID_FIELD_IN_CDB, 0); | ||
1574 | return check_condition_result; | 2053 | return check_condition_result; |
1575 | } | 2054 | } |
1576 | len = 0; | 2055 | len = 0; |
@@ -1602,15 +2081,13 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, | |||
1602 | } | 2081 | } |
1603 | len += resp_iec_m_pg(ap + len, pcontrol, target); | 2082 | len += resp_iec_m_pg(ap + len, pcontrol, target); |
1604 | } else { | 2083 | } else { |
1605 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2084 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); |
1606 | INVALID_FIELD_IN_CDB, 0); | ||
1607 | return check_condition_result; | 2085 | return check_condition_result; |
1608 | } | 2086 | } |
1609 | offset += len; | 2087 | offset += len; |
1610 | break; | 2088 | break; |
1611 | default: | 2089 | default: |
1612 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | 2090 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5); |
1613 | 0); | ||
1614 | return check_condition_result; | 2091 | return check_condition_result; |
1615 | } | 2092 | } |
1616 | if (msense_6) | 2093 | if (msense_6) |
@@ -1624,24 +2101,21 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, | |||
1624 | 2101 | ||
1625 | #define SDEBUG_MAX_MSELECT_SZ 512 | 2102 | #define SDEBUG_MAX_MSELECT_SZ 512 |
1626 | 2103 | ||
1627 | static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, | 2104 | static int |
1628 | struct sdebug_dev_info * devip) | 2105 | resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
1629 | { | 2106 | { |
1630 | int pf, sp, ps, md_len, bd_len, off, spf, pg_len; | 2107 | int pf, sp, ps, md_len, bd_len, off, spf, pg_len; |
1631 | int param_len, res, errsts, mpage; | 2108 | int param_len, res, mpage; |
1632 | unsigned char arr[SDEBUG_MAX_MSELECT_SZ]; | 2109 | unsigned char arr[SDEBUG_MAX_MSELECT_SZ]; |
1633 | unsigned char *cmd = scp->cmnd; | 2110 | unsigned char *cmd = scp->cmnd; |
2111 | int mselect6 = (MODE_SELECT == cmd[0]); | ||
1634 | 2112 | ||
1635 | errsts = check_readiness(scp, UAS_ONLY, devip); | ||
1636 | if (errsts) | ||
1637 | return errsts; | ||
1638 | memset(arr, 0, sizeof(arr)); | 2113 | memset(arr, 0, sizeof(arr)); |
1639 | pf = cmd[1] & 0x10; | 2114 | pf = cmd[1] & 0x10; |
1640 | sp = cmd[1] & 0x1; | 2115 | sp = cmd[1] & 0x1; |
1641 | param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]); | 2116 | param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]); |
1642 | if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) { | 2117 | if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) { |
1643 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2118 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1); |
1644 | INVALID_FIELD_IN_CDB, 0); | ||
1645 | return check_condition_result; | 2119 | return check_condition_result; |
1646 | } | 2120 | } |
1647 | res = fetch_to_dev_buffer(scp, arr, param_len); | 2121 | res = fetch_to_dev_buffer(scp, arr, param_len); |
@@ -1655,16 +2129,14 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, | |||
1655 | md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2); | 2129 | md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2); |
1656 | bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]); | 2130 | bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]); |
1657 | if (md_len > 2) { | 2131 | if (md_len > 2) { |
1658 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2132 | mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); |
1659 | INVALID_FIELD_IN_PARAM_LIST, 0); | ||
1660 | return check_condition_result; | 2133 | return check_condition_result; |
1661 | } | 2134 | } |
1662 | off = bd_len + (mselect6 ? 4 : 8); | 2135 | off = bd_len + (mselect6 ? 4 : 8); |
1663 | mpage = arr[off] & 0x3f; | 2136 | mpage = arr[off] & 0x3f; |
1664 | ps = !!(arr[off] & 0x80); | 2137 | ps = !!(arr[off] & 0x80); |
1665 | if (ps) { | 2138 | if (ps) { |
1666 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2139 | mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 7); |
1667 | INVALID_FIELD_IN_PARAM_LIST, 0); | ||
1668 | return check_condition_result; | 2140 | return check_condition_result; |
1669 | } | 2141 | } |
1670 | spf = !!(arr[off] & 0x40); | 2142 | spf = !!(arr[off] & 0x40); |
@@ -1701,8 +2173,7 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, | |||
1701 | default: | 2173 | default: |
1702 | break; | 2174 | break; |
1703 | } | 2175 | } |
1704 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2176 | mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 5); |
1705 | INVALID_FIELD_IN_PARAM_LIST, 0); | ||
1706 | return check_condition_result; | 2177 | return check_condition_result; |
1707 | set_mode_changed_ua: | 2178 | set_mode_changed_ua: |
1708 | set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm); | 2179 | set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm); |
@@ -1737,19 +2208,15 @@ static int resp_ie_l_pg(unsigned char * arr) | |||
1737 | static int resp_log_sense(struct scsi_cmnd * scp, | 2208 | static int resp_log_sense(struct scsi_cmnd * scp, |
1738 | struct sdebug_dev_info * devip) | 2209 | struct sdebug_dev_info * devip) |
1739 | { | 2210 | { |
1740 | int ppc, sp, pcontrol, pcode, subpcode, alloc_len, errsts, len, n; | 2211 | int ppc, sp, pcontrol, pcode, subpcode, alloc_len, len, n; |
1741 | unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; | 2212 | unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; |
1742 | unsigned char *cmd = scp->cmnd; | 2213 | unsigned char *cmd = scp->cmnd; |
1743 | 2214 | ||
1744 | errsts = check_readiness(scp, UAS_ONLY, devip); | ||
1745 | if (errsts) | ||
1746 | return errsts; | ||
1747 | memset(arr, 0, sizeof(arr)); | 2215 | memset(arr, 0, sizeof(arr)); |
1748 | ppc = cmd[1] & 0x2; | 2216 | ppc = cmd[1] & 0x2; |
1749 | sp = cmd[1] & 0x1; | 2217 | sp = cmd[1] & 0x1; |
1750 | if (ppc || sp) { | 2218 | if (ppc || sp) { |
1751 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2219 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, ppc ? 1 : 0); |
1752 | INVALID_FIELD_IN_CDB, 0); | ||
1753 | return check_condition_result; | 2220 | return check_condition_result; |
1754 | } | 2221 | } |
1755 | pcontrol = (cmd[2] & 0xc0) >> 6; | 2222 | pcontrol = (cmd[2] & 0xc0) >> 6; |
@@ -1773,8 +2240,7 @@ static int resp_log_sense(struct scsi_cmnd * scp, | |||
1773 | arr[3] = resp_ie_l_pg(arr + 4); | 2240 | arr[3] = resp_ie_l_pg(arr + 4); |
1774 | break; | 2241 | break; |
1775 | default: | 2242 | default: |
1776 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2243 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5); |
1777 | INVALID_FIELD_IN_CDB, 0); | ||
1778 | return check_condition_result; | 2244 | return check_condition_result; |
1779 | } | 2245 | } |
1780 | } else if (0xff == subpcode) { | 2246 | } else if (0xff == subpcode) { |
@@ -1806,13 +2272,11 @@ static int resp_log_sense(struct scsi_cmnd * scp, | |||
1806 | arr[3] = n - 4; | 2272 | arr[3] = n - 4; |
1807 | break; | 2273 | break; |
1808 | default: | 2274 | default: |
1809 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2275 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5); |
1810 | INVALID_FIELD_IN_CDB, 0); | ||
1811 | return check_condition_result; | 2276 | return check_condition_result; |
1812 | } | 2277 | } |
1813 | } else { | 2278 | } else { |
1814 | mk_sense_buffer(scp, ILLEGAL_REQUEST, | 2279 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); |
1815 | INVALID_FIELD_IN_CDB, 0); | ||
1816 | return check_condition_result; | 2280 | return check_condition_result; |
1817 | } | 2281 | } |
1818 | len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); | 2282 | len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); |
@@ -1824,11 +2288,12 @@ static int check_device_access_params(struct scsi_cmnd *scp, | |||
1824 | unsigned long long lba, unsigned int num) | 2288 | unsigned long long lba, unsigned int num) |
1825 | { | 2289 | { |
1826 | if (lba + num > sdebug_capacity) { | 2290 | if (lba + num > sdebug_capacity) { |
1827 | mk_sense_buffer(scp, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0); | 2291 | mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); |
1828 | return check_condition_result; | 2292 | return check_condition_result; |
1829 | } | 2293 | } |
1830 | /* transfer length excessive (tie in to block limits VPD page) */ | 2294 | /* transfer length excessive (tie in to block limits VPD page) */ |
1831 | if (num > sdebug_store_sectors) { | 2295 | if (num > sdebug_store_sectors) { |
2296 | /* needs work to find which cdb byte 'num' comes from */ | ||
1832 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); | 2297 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
1833 | return check_condition_result; | 2298 | return check_condition_result; |
1834 | } | 2299 | } |
@@ -1836,17 +2301,17 @@ static int check_device_access_params(struct scsi_cmnd *scp, | |||
1836 | } | 2301 | } |
1837 | 2302 | ||
1838 | /* Returns number of bytes copied or -1 if error. */ | 2303 | /* Returns number of bytes copied or -1 if error. */ |
1839 | static int do_device_access(struct scsi_cmnd *scmd, | 2304 | static int |
1840 | unsigned long long lba, unsigned int num, int write) | 2305 | do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write) |
1841 | { | 2306 | { |
1842 | int ret; | 2307 | int ret; |
1843 | unsigned long long block, rest = 0; | 2308 | u64 block, rest = 0; |
1844 | struct scsi_data_buffer *sdb; | 2309 | struct scsi_data_buffer *sdb; |
1845 | enum dma_data_direction dir; | 2310 | enum dma_data_direction dir; |
1846 | size_t (*func)(struct scatterlist *, unsigned int, void *, size_t, | 2311 | size_t (*func)(struct scatterlist *, unsigned int, void *, size_t, |
1847 | off_t); | 2312 | off_t); |
1848 | 2313 | ||
1849 | if (write) { | 2314 | if (do_write) { |
1850 | sdb = scsi_out(scmd); | 2315 | sdb = scsi_out(scmd); |
1851 | dir = DMA_TO_DEVICE; | 2316 | dir = DMA_TO_DEVICE; |
1852 | func = sg_pcopy_to_buffer; | 2317 | func = sg_pcopy_to_buffer; |
@@ -1880,6 +2345,38 @@ static int do_device_access(struct scsi_cmnd *scmd, | |||
1880 | return ret; | 2345 | return ret; |
1881 | } | 2346 | } |
1882 | 2347 | ||
2348 | /* If fake_store(lba,num) compares equal to arr(num), then copy top half of | ||
2349 | * arr into fake_store(lba,num) and return true. If comparison fails then | ||
2350 | * return false. */ | ||
2351 | static bool | ||
2352 | comp_write_worker(u64 lba, u32 num, const u8 *arr) | ||
2353 | { | ||
2354 | bool res; | ||
2355 | u64 block, rest = 0; | ||
2356 | u32 store_blks = sdebug_store_sectors; | ||
2357 | u32 lb_size = scsi_debug_sector_size; | ||
2358 | |||
2359 | block = do_div(lba, store_blks); | ||
2360 | if (block + num > store_blks) | ||
2361 | rest = block + num - store_blks; | ||
2362 | |||
2363 | res = !memcmp(fake_storep + (block * lb_size), arr, | ||
2364 | (num - rest) * lb_size); | ||
2365 | if (!res) | ||
2366 | return res; | ||
2367 | if (rest) | ||
2368 | res = memcmp(fake_storep, arr + ((num - rest) * lb_size), | ||
2369 | rest * lb_size); | ||
2370 | if (!res) | ||
2371 | return res; | ||
2372 | arr += num * lb_size; | ||
2373 | memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size); | ||
2374 | if (rest) | ||
2375 | memcpy(fake_storep, arr + ((num - rest) * lb_size), | ||
2376 | rest * lb_size); | ||
2377 | return res; | ||
2378 | } | ||
2379 | |||
1883 | static __be16 dif_compute_csum(const void *buf, int len) | 2380 | static __be16 dif_compute_csum(const void *buf, int len) |
1884 | { | 2381 | { |
1885 | __be16 csum; | 2382 | __be16 csum; |
@@ -1992,55 +2489,143 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1992 | return 0; | 2489 | return 0; |
1993 | } | 2490 | } |
1994 | 2491 | ||
1995 | static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, | 2492 | static int |
1996 | unsigned int num, u32 ei_lba) | 2493 | resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
1997 | { | 2494 | { |
2495 | u8 *cmd = scp->cmnd; | ||
2496 | u64 lba; | ||
2497 | u32 num; | ||
2498 | u32 ei_lba; | ||
1998 | unsigned long iflags; | 2499 | unsigned long iflags; |
1999 | int ret; | 2500 | int ret; |
2501 | bool check_prot; | ||
2000 | 2502 | ||
2001 | ret = check_device_access_params(SCpnt, lba, num); | 2503 | switch (cmd[0]) { |
2002 | if (ret) | 2504 | case READ_16: |
2003 | return ret; | 2505 | ei_lba = 0; |
2506 | lba = get_unaligned_be64(cmd + 2); | ||
2507 | num = get_unaligned_be32(cmd + 10); | ||
2508 | check_prot = true; | ||
2509 | break; | ||
2510 | case READ_10: | ||
2511 | ei_lba = 0; | ||
2512 | lba = get_unaligned_be32(cmd + 2); | ||
2513 | num = get_unaligned_be16(cmd + 7); | ||
2514 | check_prot = true; | ||
2515 | break; | ||
2516 | case READ_6: | ||
2517 | ei_lba = 0; | ||
2518 | lba = (u32)cmd[3] | (u32)cmd[2] << 8 | | ||
2519 | (u32)(cmd[1] & 0x1f) << 16; | ||
2520 | num = (0 == cmd[4]) ? 256 : cmd[4]; | ||
2521 | check_prot = true; | ||
2522 | break; | ||
2523 | case READ_12: | ||
2524 | ei_lba = 0; | ||
2525 | lba = get_unaligned_be32(cmd + 2); | ||
2526 | num = get_unaligned_be32(cmd + 6); | ||
2527 | check_prot = true; | ||
2528 | break; | ||
2529 | case XDWRITEREAD_10: | ||
2530 | ei_lba = 0; | ||
2531 | lba = get_unaligned_be32(cmd + 2); | ||
2532 | num = get_unaligned_be16(cmd + 7); | ||
2533 | check_prot = false; | ||
2534 | break; | ||
2535 | default: /* assume READ(32) */ | ||
2536 | lba = get_unaligned_be64(cmd + 12); | ||
2537 | ei_lba = get_unaligned_be32(cmd + 20); | ||
2538 | num = get_unaligned_be32(cmd + 28); | ||
2539 | check_prot = false; | ||
2540 | break; | ||
2541 | } | ||
2542 | if (check_prot) { | ||
2543 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
2544 | (cmd[1] & 0xe0)) { | ||
2545 | mk_sense_invalid_opcode(scp); | ||
2546 | return check_condition_result; | ||
2547 | } | ||
2548 | if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || | ||
2549 | scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && | ||
2550 | (cmd[1] & 0xe0) == 0) | ||
2551 | sdev_printk(KERN_ERR, scp->device, "Unprotected RD " | ||
2552 | "to DIF device\n"); | ||
2553 | } | ||
2554 | if (sdebug_any_injecting_opt) { | ||
2555 | struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); | ||
2556 | |||
2557 | if (ep->inj_short) | ||
2558 | num /= 2; | ||
2559 | } | ||
2560 | |||
2561 | /* inline check_device_access_params() */ | ||
2562 | if (lba + num > sdebug_capacity) { | ||
2563 | mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); | ||
2564 | return check_condition_result; | ||
2565 | } | ||
2566 | /* transfer length excessive (tie in to block limits VPD page) */ | ||
2567 | if (num > sdebug_store_sectors) { | ||
2568 | /* needs work to find which cdb byte 'num' comes from */ | ||
2569 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); | ||
2570 | return check_condition_result; | ||
2571 | } | ||
2004 | 2572 | ||
2005 | if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && | 2573 | if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && |
2006 | (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && | 2574 | (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && |
2007 | ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { | 2575 | ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { |
2008 | /* claim unrecoverable read error */ | 2576 | /* claim unrecoverable read error */ |
2009 | mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); | 2577 | mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); |
2010 | /* set info field and valid bit for fixed descriptor */ | 2578 | /* set info field and valid bit for fixed descriptor */ |
2011 | if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) { | 2579 | if (0x70 == (scp->sense_buffer[0] & 0x7f)) { |
2012 | SCpnt->sense_buffer[0] |= 0x80; /* Valid bit */ | 2580 | scp->sense_buffer[0] |= 0x80; /* Valid bit */ |
2013 | ret = (lba < OPT_MEDIUM_ERR_ADDR) | 2581 | ret = (lba < OPT_MEDIUM_ERR_ADDR) |
2014 | ? OPT_MEDIUM_ERR_ADDR : (int)lba; | 2582 | ? OPT_MEDIUM_ERR_ADDR : (int)lba; |
2015 | SCpnt->sense_buffer[3] = (ret >> 24) & 0xff; | 2583 | put_unaligned_be32(ret, scp->sense_buffer + 3); |
2016 | SCpnt->sense_buffer[4] = (ret >> 16) & 0xff; | ||
2017 | SCpnt->sense_buffer[5] = (ret >> 8) & 0xff; | ||
2018 | SCpnt->sense_buffer[6] = ret & 0xff; | ||
2019 | } | 2584 | } |
2020 | scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); | 2585 | scsi_set_resid(scp, scsi_bufflen(scp)); |
2021 | return check_condition_result; | 2586 | return check_condition_result; |
2022 | } | 2587 | } |
2023 | 2588 | ||
2024 | read_lock_irqsave(&atomic_rw, iflags); | 2589 | read_lock_irqsave(&atomic_rw, iflags); |
2025 | 2590 | ||
2026 | /* DIX + T10 DIF */ | 2591 | /* DIX + T10 DIF */ |
2027 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { | 2592 | if (scsi_debug_dix && scsi_prot_sg_count(scp)) { |
2028 | int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba); | 2593 | int prot_ret = prot_verify_read(scp, lba, num, ei_lba); |
2029 | 2594 | ||
2030 | if (prot_ret) { | 2595 | if (prot_ret) { |
2031 | read_unlock_irqrestore(&atomic_rw, iflags); | 2596 | read_unlock_irqrestore(&atomic_rw, iflags); |
2032 | mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret); | 2597 | mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret); |
2033 | return illegal_condition_result; | 2598 | return illegal_condition_result; |
2034 | } | 2599 | } |
2035 | } | 2600 | } |
2036 | 2601 | ||
2037 | ret = do_device_access(SCpnt, lba, num, 0); | 2602 | ret = do_device_access(scp, lba, num, false); |
2038 | read_unlock_irqrestore(&atomic_rw, iflags); | 2603 | read_unlock_irqrestore(&atomic_rw, iflags); |
2039 | if (ret == -1) | 2604 | if (ret == -1) |
2040 | return DID_ERROR << 16; | 2605 | return DID_ERROR << 16; |
2041 | 2606 | ||
2042 | scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret; | 2607 | scsi_in(scp)->resid = scsi_bufflen(scp) - ret; |
2608 | |||
2609 | if (sdebug_any_injecting_opt) { | ||
2610 | struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); | ||
2043 | 2611 | ||
2612 | if (ep->inj_recovered) { | ||
2613 | mk_sense_buffer(scp, RECOVERED_ERROR, | ||
2614 | THRESHOLD_EXCEEDED, 0); | ||
2615 | return check_condition_result; | ||
2616 | } else if (ep->inj_transport) { | ||
2617 | mk_sense_buffer(scp, ABORTED_COMMAND, | ||
2618 | TRANSPORT_PROBLEM, ACK_NAK_TO); | ||
2619 | return check_condition_result; | ||
2620 | } else if (ep->inj_dif) { | ||
2621 | /* Logical block guard check failed */ | ||
2622 | mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); | ||
2623 | return illegal_condition_result; | ||
2624 | } else if (ep->inj_dix) { | ||
2625 | mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); | ||
2626 | return illegal_condition_result; | ||
2627 | } | ||
2628 | } | ||
2044 | return 0; | 2629 | return 0; |
2045 | } | 2630 | } |
2046 | 2631 | ||
@@ -2223,31 +2808,95 @@ static void unmap_region(sector_t lba, unsigned int len) | |||
2223 | } | 2808 | } |
2224 | } | 2809 | } |
2225 | 2810 | ||
2226 | static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, | 2811 | static int |
2227 | unsigned int num, u32 ei_lba) | 2812 | resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
2228 | { | 2813 | { |
2814 | u8 *cmd = scp->cmnd; | ||
2815 | u64 lba; | ||
2816 | u32 num; | ||
2817 | u32 ei_lba; | ||
2229 | unsigned long iflags; | 2818 | unsigned long iflags; |
2230 | int ret; | 2819 | int ret; |
2820 | bool check_prot; | ||
2231 | 2821 | ||
2232 | ret = check_device_access_params(SCpnt, lba, num); | 2822 | switch (cmd[0]) { |
2233 | if (ret) | 2823 | case WRITE_16: |
2234 | return ret; | 2824 | ei_lba = 0; |
2825 | lba = get_unaligned_be64(cmd + 2); | ||
2826 | num = get_unaligned_be32(cmd + 10); | ||
2827 | check_prot = true; | ||
2828 | break; | ||
2829 | case WRITE_10: | ||
2830 | ei_lba = 0; | ||
2831 | lba = get_unaligned_be32(cmd + 2); | ||
2832 | num = get_unaligned_be16(cmd + 7); | ||
2833 | check_prot = true; | ||
2834 | break; | ||
2835 | case WRITE_6: | ||
2836 | ei_lba = 0; | ||
2837 | lba = (u32)cmd[3] | (u32)cmd[2] << 8 | | ||
2838 | (u32)(cmd[1] & 0x1f) << 16; | ||
2839 | num = (0 == cmd[4]) ? 256 : cmd[4]; | ||
2840 | check_prot = true; | ||
2841 | break; | ||
2842 | case WRITE_12: | ||
2843 | ei_lba = 0; | ||
2844 | lba = get_unaligned_be32(cmd + 2); | ||
2845 | num = get_unaligned_be32(cmd + 6); | ||
2846 | check_prot = true; | ||
2847 | break; | ||
2848 | case 0x53: /* XDWRITEREAD(10) */ | ||
2849 | ei_lba = 0; | ||
2850 | lba = get_unaligned_be32(cmd + 2); | ||
2851 | num = get_unaligned_be16(cmd + 7); | ||
2852 | check_prot = false; | ||
2853 | break; | ||
2854 | default: /* assume WRITE(32) */ | ||
2855 | lba = get_unaligned_be64(cmd + 12); | ||
2856 | ei_lba = get_unaligned_be32(cmd + 20); | ||
2857 | num = get_unaligned_be32(cmd + 28); | ||
2858 | check_prot = false; | ||
2859 | break; | ||
2860 | } | ||
2861 | if (check_prot) { | ||
2862 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
2863 | (cmd[1] & 0xe0)) { | ||
2864 | mk_sense_invalid_opcode(scp); | ||
2865 | return check_condition_result; | ||
2866 | } | ||
2867 | if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || | ||
2868 | scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && | ||
2869 | (cmd[1] & 0xe0) == 0) | ||
2870 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " | ||
2871 | "to DIF device\n"); | ||
2872 | } | ||
2873 | |||
2874 | /* inline check_device_access_params() */ | ||
2875 | if (lba + num > sdebug_capacity) { | ||
2876 | mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); | ||
2877 | return check_condition_result; | ||
2878 | } | ||
2879 | /* transfer length excessive (tie in to block limits VPD page) */ | ||
2880 | if (num > sdebug_store_sectors) { | ||
2881 | /* needs work to find which cdb byte 'num' comes from */ | ||
2882 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); | ||
2883 | return check_condition_result; | ||
2884 | } | ||
2235 | 2885 | ||
2236 | write_lock_irqsave(&atomic_rw, iflags); | 2886 | write_lock_irqsave(&atomic_rw, iflags); |
2237 | 2887 | ||
2238 | /* DIX + T10 DIF */ | 2888 | /* DIX + T10 DIF */ |
2239 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { | 2889 | if (scsi_debug_dix && scsi_prot_sg_count(scp)) { |
2240 | int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba); | 2890 | int prot_ret = prot_verify_write(scp, lba, num, ei_lba); |
2241 | 2891 | ||
2242 | if (prot_ret) { | 2892 | if (prot_ret) { |
2243 | write_unlock_irqrestore(&atomic_rw, iflags); | 2893 | write_unlock_irqrestore(&atomic_rw, iflags); |
2244 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, | 2894 | mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret); |
2245 | prot_ret); | ||
2246 | return illegal_condition_result; | 2895 | return illegal_condition_result; |
2247 | } | 2896 | } |
2248 | } | 2897 | } |
2249 | 2898 | ||
2250 | ret = do_device_access(SCpnt, lba, num, 1); | 2899 | ret = do_device_access(scp, lba, num, true); |
2251 | if (scsi_debug_lbp()) | 2900 | if (scsi_debug_lbp()) |
2252 | map_region(lba, num); | 2901 | map_region(lba, num); |
2253 | write_unlock_irqrestore(&atomic_rw, iflags); | 2902 | write_unlock_irqrestore(&atomic_rw, iflags); |
@@ -2255,30 +2904,41 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, | |||
2255 | return (DID_ERROR << 16); | 2904 | return (DID_ERROR << 16); |
2256 | else if ((ret < (num * scsi_debug_sector_size)) && | 2905 | else if ((ret < (num * scsi_debug_sector_size)) && |
2257 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) | 2906 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) |
2258 | sdev_printk(KERN_INFO, SCpnt->device, | 2907 | sdev_printk(KERN_INFO, scp->device, |
2259 | "%s: write: cdb indicated=%u, IO sent=%d bytes\n", | 2908 | "%s: write: cdb indicated=%u, IO sent=%d bytes\n", |
2260 | my_name, num * scsi_debug_sector_size, ret); | 2909 | my_name, num * scsi_debug_sector_size, ret); |
2261 | 2910 | ||
2911 | if (sdebug_any_injecting_opt) { | ||
2912 | struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); | ||
2913 | |||
2914 | if (ep->inj_recovered) { | ||
2915 | mk_sense_buffer(scp, RECOVERED_ERROR, | ||
2916 | THRESHOLD_EXCEEDED, 0); | ||
2917 | return check_condition_result; | ||
2918 | } else if (ep->inj_dif) { | ||
2919 | /* Logical block guard check failed */ | ||
2920 | mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1); | ||
2921 | return illegal_condition_result; | ||
2922 | } else if (ep->inj_dix) { | ||
2923 | mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1); | ||
2924 | return illegal_condition_result; | ||
2925 | } | ||
2926 | } | ||
2262 | return 0; | 2927 | return 0; |
2263 | } | 2928 | } |
2264 | 2929 | ||
2265 | static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, | 2930 | static int |
2266 | unsigned int num, u32 ei_lba, unsigned int unmap) | 2931 | resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba, |
2932 | bool unmap, bool ndob) | ||
2267 | { | 2933 | { |
2268 | unsigned long iflags; | 2934 | unsigned long iflags; |
2269 | unsigned long long i; | 2935 | unsigned long long i; |
2270 | int ret; | 2936 | int ret; |
2271 | 2937 | ||
2272 | ret = check_device_access_params(scmd, lba, num); | 2938 | ret = check_device_access_params(scp, lba, num); |
2273 | if (ret) | 2939 | if (ret) |
2274 | return ret; | 2940 | return ret; |
2275 | 2941 | ||
2276 | if (num > scsi_debug_write_same_length) { | ||
2277 | mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | ||
2278 | 0); | ||
2279 | return check_condition_result; | ||
2280 | } | ||
2281 | |||
2282 | write_lock_irqsave(&atomic_rw, iflags); | 2942 | write_lock_irqsave(&atomic_rw, iflags); |
2283 | 2943 | ||
2284 | if (unmap && scsi_debug_lbp()) { | 2944 | if (unmap && scsi_debug_lbp()) { |
@@ -2286,17 +2946,22 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, | |||
2286 | goto out; | 2946 | goto out; |
2287 | } | 2947 | } |
2288 | 2948 | ||
2289 | /* Else fetch one logical block */ | 2949 | /* if ndob then zero 1 logical block, else fetch 1 logical block */ |
2290 | ret = fetch_to_dev_buffer(scmd, | 2950 | if (ndob) { |
2291 | fake_storep + (lba * scsi_debug_sector_size), | 2951 | memset(fake_storep + (lba * scsi_debug_sector_size), 0, |
2292 | scsi_debug_sector_size); | 2952 | scsi_debug_sector_size); |
2953 | ret = 0; | ||
2954 | } else | ||
2955 | ret = fetch_to_dev_buffer(scp, fake_storep + | ||
2956 | (lba * scsi_debug_sector_size), | ||
2957 | scsi_debug_sector_size); | ||
2293 | 2958 | ||
2294 | if (-1 == ret) { | 2959 | if (-1 == ret) { |
2295 | write_unlock_irqrestore(&atomic_rw, iflags); | 2960 | write_unlock_irqrestore(&atomic_rw, iflags); |
2296 | return (DID_ERROR << 16); | 2961 | return (DID_ERROR << 16); |
2297 | } else if ((ret < (num * scsi_debug_sector_size)) && | 2962 | } else if ((ret < (num * scsi_debug_sector_size)) && |
2298 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) | 2963 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) |
2299 | sdev_printk(KERN_INFO, scmd->device, | 2964 | sdev_printk(KERN_INFO, scp->device, |
2300 | "%s: %s: cdb indicated=%u, IO sent=%d bytes\n", | 2965 | "%s: %s: cdb indicated=%u, IO sent=%d bytes\n", |
2301 | my_name, "write same", | 2966 | my_name, "write same", |
2302 | num * scsi_debug_sector_size, ret); | 2967 | num * scsi_debug_sector_size, ret); |
@@ -2315,13 +2980,144 @@ out: | |||
2315 | return 0; | 2980 | return 0; |
2316 | } | 2981 | } |
2317 | 2982 | ||
2983 | static int | ||
2984 | resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | ||
2985 | { | ||
2986 | u8 *cmd = scp->cmnd; | ||
2987 | u32 lba; | ||
2988 | u16 num; | ||
2989 | u32 ei_lba = 0; | ||
2990 | bool unmap = false; | ||
2991 | |||
2992 | if (cmd[1] & 0x8) { | ||
2993 | if (scsi_debug_lbpws10 == 0) { | ||
2994 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3); | ||
2995 | return check_condition_result; | ||
2996 | } else | ||
2997 | unmap = true; | ||
2998 | } | ||
2999 | lba = get_unaligned_be32(cmd + 2); | ||
3000 | num = get_unaligned_be16(cmd + 7); | ||
3001 | if (num > scsi_debug_write_same_length) { | ||
3002 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1); | ||
3003 | return check_condition_result; | ||
3004 | } | ||
3005 | return resp_write_same(scp, lba, num, ei_lba, unmap, false); | ||
3006 | } | ||
3007 | |||
3008 | static int | ||
3009 | resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | ||
3010 | { | ||
3011 | u8 *cmd = scp->cmnd; | ||
3012 | u64 lba; | ||
3013 | u32 num; | ||
3014 | u32 ei_lba = 0; | ||
3015 | bool unmap = false; | ||
3016 | bool ndob = false; | ||
3017 | |||
3018 | if (cmd[1] & 0x8) { /* UNMAP */ | ||
3019 | if (scsi_debug_lbpws == 0) { | ||
3020 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3); | ||
3021 | return check_condition_result; | ||
3022 | } else | ||
3023 | unmap = true; | ||
3024 | } | ||
3025 | if (cmd[1] & 0x1) /* NDOB (no data-out buffer, assumes zeroes) */ | ||
3026 | ndob = true; | ||
3027 | lba = get_unaligned_be64(cmd + 2); | ||
3028 | num = get_unaligned_be32(cmd + 10); | ||
3029 | if (num > scsi_debug_write_same_length) { | ||
3030 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1); | ||
3031 | return check_condition_result; | ||
3032 | } | ||
3033 | return resp_write_same(scp, lba, num, ei_lba, unmap, ndob); | ||
3034 | } | ||
3035 | |||
3036 | static int | ||
3037 | resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | ||
3038 | { | ||
3039 | u8 *cmd = scp->cmnd; | ||
3040 | u8 *arr; | ||
3041 | u8 *fake_storep_hold; | ||
3042 | u64 lba; | ||
3043 | u32 dnum; | ||
3044 | u32 lb_size = scsi_debug_sector_size; | ||
3045 | u8 num; | ||
3046 | unsigned long iflags; | ||
3047 | int ret; | ||
3048 | int retval = 0; | ||
3049 | |||
3050 | lba = get_unaligned_be64(cmd + 2); | ||
3051 | num = cmd[13]; /* 1 to a maximum of 255 logical blocks */ | ||
3052 | if (0 == num) | ||
3053 | return 0; /* degenerate case, not an error */ | ||
3054 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
3055 | (cmd[1] & 0xe0)) { | ||
3056 | mk_sense_invalid_opcode(scp); | ||
3057 | return check_condition_result; | ||
3058 | } | ||
3059 | if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || | ||
3060 | scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && | ||
3061 | (cmd[1] & 0xe0) == 0) | ||
3062 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " | ||
3063 | "to DIF device\n"); | ||
3064 | |||
3065 | /* inline check_device_access_params() */ | ||
3066 | if (lba + num > sdebug_capacity) { | ||
3067 | mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0); | ||
3068 | return check_condition_result; | ||
3069 | } | ||
3070 | /* transfer length excessive (tie in to block limits VPD page) */ | ||
3071 | if (num > sdebug_store_sectors) { | ||
3072 | /* needs work to find which cdb byte 'num' comes from */ | ||
3073 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); | ||
3074 | return check_condition_result; | ||
3075 | } | ||
3076 | dnum = 2 * num; | ||
3077 | arr = kzalloc(dnum * lb_size, GFP_ATOMIC); | ||
3078 | if (NULL == arr) { | ||
3079 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, | ||
3080 | INSUFF_RES_ASCQ); | ||
3081 | return check_condition_result; | ||
3082 | } | ||
3083 | |||
3084 | write_lock_irqsave(&atomic_rw, iflags); | ||
3085 | |||
3086 | /* trick do_device_access() to fetch both compare and write buffers | ||
3087 | * from data-in into arr. Safe (atomic) since write_lock held. */ | ||
3088 | fake_storep_hold = fake_storep; | ||
3089 | fake_storep = arr; | ||
3090 | ret = do_device_access(scp, 0, dnum, true); | ||
3091 | fake_storep = fake_storep_hold; | ||
3092 | if (ret == -1) { | ||
3093 | retval = DID_ERROR << 16; | ||
3094 | goto cleanup; | ||
3095 | } else if ((ret < (dnum * lb_size)) && | ||
3096 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) | ||
3097 | sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb " | ||
3098 | "indicated=%u, IO sent=%d bytes\n", my_name, | ||
3099 | dnum * lb_size, ret); | ||
3100 | if (!comp_write_worker(lba, num, arr)) { | ||
3101 | mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0); | ||
3102 | retval = check_condition_result; | ||
3103 | goto cleanup; | ||
3104 | } | ||
3105 | if (scsi_debug_lbp()) | ||
3106 | map_region(lba, num); | ||
3107 | cleanup: | ||
3108 | write_unlock_irqrestore(&atomic_rw, iflags); | ||
3109 | kfree(arr); | ||
3110 | return retval; | ||
3111 | } | ||
3112 | |||
2318 | struct unmap_block_desc { | 3113 | struct unmap_block_desc { |
2319 | __be64 lba; | 3114 | __be64 lba; |
2320 | __be32 blocks; | 3115 | __be32 blocks; |
2321 | __be32 __reserved; | 3116 | __be32 __reserved; |
2322 | }; | 3117 | }; |
2323 | 3118 | ||
2324 | static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) | 3119 | static int |
3120 | resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | ||
2325 | { | 3121 | { |
2326 | unsigned char *buf; | 3122 | unsigned char *buf; |
2327 | struct unmap_block_desc *desc; | 3123 | struct unmap_block_desc *desc; |
@@ -2329,20 +3125,26 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) | |||
2329 | int ret; | 3125 | int ret; |
2330 | unsigned long iflags; | 3126 | unsigned long iflags; |
2331 | 3127 | ||
2332 | ret = check_readiness(scmd, UAS_ONLY, devip); | ||
2333 | if (ret) | ||
2334 | return ret; | ||
2335 | 3128 | ||
2336 | payload_len = get_unaligned_be16(&scmd->cmnd[7]); | 3129 | if (!scsi_debug_lbp()) |
2337 | BUG_ON(scsi_bufflen(scmd) != payload_len); | 3130 | return 0; /* fib and say its done */ |
3131 | payload_len = get_unaligned_be16(scp->cmnd + 7); | ||
3132 | BUG_ON(scsi_bufflen(scp) != payload_len); | ||
2338 | 3133 | ||
2339 | descriptors = (payload_len - 8) / 16; | 3134 | descriptors = (payload_len - 8) / 16; |
3135 | if (descriptors > scsi_debug_unmap_max_desc) { | ||
3136 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1); | ||
3137 | return check_condition_result; | ||
3138 | } | ||
2340 | 3139 | ||
2341 | buf = kmalloc(scsi_bufflen(scmd), GFP_ATOMIC); | 3140 | buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); |
2342 | if (!buf) | 3141 | if (!buf) { |
3142 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, | ||
3143 | INSUFF_RES_ASCQ); | ||
2343 | return check_condition_result; | 3144 | return check_condition_result; |
3145 | } | ||
2344 | 3146 | ||
2345 | scsi_sg_copy_to_buffer(scmd, buf, scsi_bufflen(scmd)); | 3147 | scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp)); |
2346 | 3148 | ||
2347 | BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2); | 3149 | BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2); |
2348 | BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16); | 3150 | BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16); |
@@ -2355,7 +3157,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) | |||
2355 | unsigned long long lba = get_unaligned_be64(&desc[i].lba); | 3157 | unsigned long long lba = get_unaligned_be64(&desc[i].lba); |
2356 | unsigned int num = get_unaligned_be32(&desc[i].blocks); | 3158 | unsigned int num = get_unaligned_be32(&desc[i].blocks); |
2357 | 3159 | ||
2358 | ret = check_device_access_params(scmd, lba, num); | 3160 | ret = check_device_access_params(scp, lba, num); |
2359 | if (ret) | 3161 | if (ret) |
2360 | goto out; | 3162 | goto out; |
2361 | 3163 | ||
@@ -2373,37 +3175,44 @@ out: | |||
2373 | 3175 | ||
2374 | #define SDEBUG_GET_LBA_STATUS_LEN 32 | 3176 | #define SDEBUG_GET_LBA_STATUS_LEN 32 |
2375 | 3177 | ||
2376 | static int resp_get_lba_status(struct scsi_cmnd * scmd, | 3178 | static int |
2377 | struct sdebug_dev_info * devip) | 3179 | resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) |
2378 | { | 3180 | { |
2379 | unsigned long long lba; | 3181 | u8 *cmd = scp->cmnd; |
2380 | unsigned int alloc_len, mapped, num; | 3182 | u64 lba; |
2381 | unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN]; | 3183 | u32 alloc_len, mapped, num; |
3184 | u8 arr[SDEBUG_GET_LBA_STATUS_LEN]; | ||
2382 | int ret; | 3185 | int ret; |
2383 | 3186 | ||
2384 | ret = check_readiness(scmd, UAS_ONLY, devip); | 3187 | lba = get_unaligned_be64(cmd + 2); |
2385 | if (ret) | 3188 | alloc_len = get_unaligned_be32(cmd + 10); |
2386 | return ret; | ||
2387 | |||
2388 | lba = get_unaligned_be64(&scmd->cmnd[2]); | ||
2389 | alloc_len = get_unaligned_be32(&scmd->cmnd[10]); | ||
2390 | 3189 | ||
2391 | if (alloc_len < 24) | 3190 | if (alloc_len < 24) |
2392 | return 0; | 3191 | return 0; |
2393 | 3192 | ||
2394 | ret = check_device_access_params(scmd, lba, 1); | 3193 | ret = check_device_access_params(scp, lba, 1); |
2395 | if (ret) | 3194 | if (ret) |
2396 | return ret; | 3195 | return ret; |
2397 | 3196 | ||
2398 | mapped = map_state(lba, &num); | 3197 | if (scsi_debug_lbp()) |
3198 | mapped = map_state(lba, &num); | ||
3199 | else { | ||
3200 | mapped = 1; | ||
3201 | /* following just in case virtual_gb changed */ | ||
3202 | sdebug_capacity = get_sdebug_capacity(); | ||
3203 | if (sdebug_capacity - lba <= 0xffffffff) | ||
3204 | num = sdebug_capacity - lba; | ||
3205 | else | ||
3206 | num = 0xffffffff; | ||
3207 | } | ||
2399 | 3208 | ||
2400 | memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN); | 3209 | memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN); |
2401 | put_unaligned_be32(20, &arr[0]); /* Parameter Data Length */ | 3210 | put_unaligned_be32(20, arr); /* Parameter Data Length */ |
2402 | put_unaligned_be64(lba, &arr[8]); /* LBA */ | 3211 | put_unaligned_be64(lba, arr + 8); /* LBA */ |
2403 | put_unaligned_be32(num, &arr[16]); /* Number of blocks */ | 3212 | put_unaligned_be32(num, arr + 16); /* Number of blocks */ |
2404 | arr[20] = !mapped; /* mapped = 0, unmapped = 1 */ | 3213 | arr[20] = !mapped; /* prov_stat=0: mapped; 1: dealloc */ |
2405 | 3214 | ||
2406 | return fill_from_dev_buffer(scmd, arr, SDEBUG_GET_LBA_STATUS_LEN); | 3215 | return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN); |
2407 | } | 3216 | } |
2408 | 3217 | ||
2409 | #define SDEBUG_RLUN_ARR_SZ 256 | 3218 | #define SDEBUG_RLUN_ARR_SZ 256 |
@@ -2412,8 +3221,8 @@ static int resp_report_luns(struct scsi_cmnd * scp, | |||
2412 | struct sdebug_dev_info * devip) | 3221 | struct sdebug_dev_info * devip) |
2413 | { | 3222 | { |
2414 | unsigned int alloc_len; | 3223 | unsigned int alloc_len; |
2415 | int lun_cnt, i, upper, num, n; | 3224 | int lun_cnt, i, upper, num, n, want_wlun, shortish; |
2416 | u64 wlun, lun; | 3225 | u64 lun; |
2417 | unsigned char *cmd = scp->cmnd; | 3226 | unsigned char *cmd = scp->cmnd; |
2418 | int select_report = (int)cmd[2]; | 3227 | int select_report = (int)cmd[2]; |
2419 | struct scsi_lun *one_lun; | 3228 | struct scsi_lun *one_lun; |
@@ -2421,9 +3230,9 @@ static int resp_report_luns(struct scsi_cmnd * scp, | |||
2421 | unsigned char * max_addr; | 3230 | unsigned char * max_addr; |
2422 | 3231 | ||
2423 | alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); | 3232 | alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); |
2424 | if ((alloc_len < 4) || (select_report > 2)) { | 3233 | shortish = (alloc_len < 4); |
2425 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | 3234 | if (shortish || (select_report > 2)) { |
2426 | 0); | 3235 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1); |
2427 | return check_condition_result; | 3236 | return check_condition_result; |
2428 | } | 3237 | } |
2429 | /* can produce response with up to 16k luns (lun 0 to lun 16383) */ | 3238 | /* can produce response with up to 16k luns (lun 0 to lun 16383) */ |
@@ -2433,14 +3242,14 @@ static int resp_report_luns(struct scsi_cmnd * scp, | |||
2433 | lun_cnt = 0; | 3242 | lun_cnt = 0; |
2434 | else if (scsi_debug_no_lun_0 && (lun_cnt > 0)) | 3243 | else if (scsi_debug_no_lun_0 && (lun_cnt > 0)) |
2435 | --lun_cnt; | 3244 | --lun_cnt; |
2436 | wlun = (select_report > 0) ? 1 : 0; | 3245 | want_wlun = (select_report > 0) ? 1 : 0; |
2437 | num = lun_cnt + wlun; | 3246 | num = lun_cnt + want_wlun; |
2438 | arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff; | 3247 | arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff; |
2439 | arr[3] = (sizeof(struct scsi_lun) * num) & 0xff; | 3248 | arr[3] = (sizeof(struct scsi_lun) * num) & 0xff; |
2440 | n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) / | 3249 | n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) / |
2441 | sizeof(struct scsi_lun)), num); | 3250 | sizeof(struct scsi_lun)), num); |
2442 | if (n < num) { | 3251 | if (n < num) { |
2443 | wlun = 0; | 3252 | want_wlun = 0; |
2444 | lun_cnt = n; | 3253 | lun_cnt = n; |
2445 | } | 3254 | } |
2446 | one_lun = (struct scsi_lun *) &arr[8]; | 3255 | one_lun = (struct scsi_lun *) &arr[8]; |
@@ -2454,7 +3263,7 @@ static int resp_report_luns(struct scsi_cmnd * scp, | |||
2454 | (upper | (SAM2_LUN_ADDRESS_METHOD << 6)); | 3263 | (upper | (SAM2_LUN_ADDRESS_METHOD << 6)); |
2455 | one_lun[i].scsi_lun[1] = lun & 0xff; | 3264 | one_lun[i].scsi_lun[1] = lun & 0xff; |
2456 | } | 3265 | } |
2457 | if (wlun) { | 3266 | if (want_wlun) { |
2458 | one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff; | 3267 | one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff; |
2459 | one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff; | 3268 | one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff; |
2460 | i++; | 3269 | i++; |
@@ -2476,8 +3285,8 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, | |||
2476 | /* better not to use temporary buffer. */ | 3285 | /* better not to use temporary buffer. */ |
2477 | buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); | 3286 | buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); |
2478 | if (!buf) { | 3287 | if (!buf) { |
2479 | mk_sense_buffer(scp, NOT_READY, | 3288 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, |
2480 | LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); | 3289 | INSUFF_RES_ASCQ); |
2481 | return check_condition_result; | 3290 | return check_condition_result; |
2482 | } | 3291 | } |
2483 | 3292 | ||
@@ -2500,6 +3309,32 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, | |||
2500 | return 0; | 3309 | return 0; |
2501 | } | 3310 | } |
2502 | 3311 | ||
3312 | static int | ||
3313 | resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | ||
3314 | { | ||
3315 | u8 *cmd = scp->cmnd; | ||
3316 | u64 lba; | ||
3317 | u32 num; | ||
3318 | int errsts; | ||
3319 | |||
3320 | if (!scsi_bidi_cmnd(scp)) { | ||
3321 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, | ||
3322 | INSUFF_RES_ASCQ); | ||
3323 | return check_condition_result; | ||
3324 | } | ||
3325 | errsts = resp_read_dt0(scp, devip); | ||
3326 | if (errsts) | ||
3327 | return errsts; | ||
3328 | if (!(cmd[1] & 0x4)) { /* DISABLE_WRITE is not set */ | ||
3329 | errsts = resp_write_dt0(scp, devip); | ||
3330 | if (errsts) | ||
3331 | return errsts; | ||
3332 | } | ||
3333 | lba = get_unaligned_be32(cmd + 2); | ||
3334 | num = get_unaligned_be16(cmd + 7); | ||
3335 | return resp_xdwriteread(scp, lba, num, devip); | ||
3336 | } | ||
3337 | |||
2503 | /* When timer or tasklet goes off this function is called. */ | 3338 | /* When timer or tasklet goes off this function is called. */ |
2504 | static void sdebug_q_cmd_complete(unsigned long indx) | 3339 | static void sdebug_q_cmd_complete(unsigned long indx) |
2505 | { | 3340 | { |
@@ -2672,10 +3507,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | |||
2672 | open_devip->sdbg_host = sdbg_host; | 3507 | open_devip->sdbg_host = sdbg_host; |
2673 | atomic_set(&open_devip->num_in_q, 0); | 3508 | atomic_set(&open_devip->num_in_q, 0); |
2674 | set_bit(SDEBUG_UA_POR, open_devip->uas_bm); | 3509 | set_bit(SDEBUG_UA_POR, open_devip->uas_bm); |
2675 | open_devip->used = 1; | 3510 | open_devip->used = true; |
2676 | if (sdev->lun == SAM2_WLUN_REPORT_LUNS) | ||
2677 | open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff; | ||
2678 | |||
2679 | return open_devip; | 3511 | return open_devip; |
2680 | } | 3512 | } |
2681 | 3513 | ||
@@ -2701,10 +3533,6 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) | |||
2701 | if (NULL == devip) | 3533 | if (NULL == devip) |
2702 | return 1; /* no resources, will be marked offline */ | 3534 | return 1; /* no resources, will be marked offline */ |
2703 | sdp->hostdata = devip; | 3535 | sdp->hostdata = devip; |
2704 | sdp->tagged_supported = 1; | ||
2705 | if (sdp->host->cmd_per_lun) | ||
2706 | scsi_adjust_queue_depth(sdp, DEF_TAGGED_QUEUING, | ||
2707 | DEF_CMD_PER_LUN); | ||
2708 | blk_queue_max_segment_size(sdp->request_queue, -1U); | 3536 | blk_queue_max_segment_size(sdp->request_queue, -1U); |
2709 | if (scsi_debug_no_uld) | 3537 | if (scsi_debug_no_uld) |
2710 | sdp->no_uld_attach = 1; | 3538 | sdp->no_uld_attach = 1; |
@@ -2721,7 +3549,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) | |||
2721 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | 3549 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
2722 | if (devip) { | 3550 | if (devip) { |
2723 | /* make this slot available for re-use */ | 3551 | /* make this slot available for re-use */ |
2724 | devip->used = 0; | 3552 | devip->used = false; |
2725 | sdp->hostdata = NULL; | 3553 | sdp->hostdata = NULL; |
2726 | } | 3554 | } |
2727 | } | 3555 | } |
@@ -3166,6 +3994,7 @@ module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR); | |||
3166 | module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR); | 3994 | module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR); |
3167 | module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO); | 3995 | module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO); |
3168 | module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); | 3996 | module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); |
3997 | module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR); | ||
3169 | module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO); | 3998 | module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO); |
3170 | module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO); | 3999 | module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO); |
3171 | module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO); | 4000 | module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO); |
@@ -3185,7 +4014,7 @@ MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); | |||
3185 | MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); | 4014 | MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); |
3186 | MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)"); | 4015 | MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)"); |
3187 | MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny"); | 4016 | MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny"); |
3188 | MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)"); | 4017 | MODULE_PARM_DESC(dev_size_mb, "size in MiB of ram shared by devs(def=8)"); |
3189 | MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); | 4018 | MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); |
3190 | MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); | 4019 | MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); |
3191 | MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)"); | 4020 | MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)"); |
@@ -3212,11 +4041,12 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); | |||
3212 | MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); | 4041 | MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); |
3213 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])"); | 4042 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])"); |
3214 | MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); | 4043 | MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); |
4044 | MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)"); | ||
3215 | MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); | 4045 | MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); |
3216 | MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); | 4046 | MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); |
3217 | MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)"); | 4047 | MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)"); |
3218 | MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)"); | 4048 | MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)"); |
3219 | MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); | 4049 | MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)"); |
3220 | MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); | 4050 | MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); |
3221 | MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)"); | 4051 | MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)"); |
3222 | 4052 | ||
@@ -3382,6 +4212,16 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, | |||
3382 | return -EINVAL; | 4212 | return -EINVAL; |
3383 | opts_done: | 4213 | opts_done: |
3384 | scsi_debug_opts = opts; | 4214 | scsi_debug_opts = opts; |
4215 | if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) | ||
4216 | sdebug_any_injecting_opt = true; | ||
4217 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) | ||
4218 | sdebug_any_injecting_opt = true; | ||
4219 | else if (SCSI_DEBUG_OPT_DIF_ERR & opts) | ||
4220 | sdebug_any_injecting_opt = true; | ||
4221 | else if (SCSI_DEBUG_OPT_DIX_ERR & opts) | ||
4222 | sdebug_any_injecting_opt = true; | ||
4223 | else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) | ||
4224 | sdebug_any_injecting_opt = true; | ||
3385 | atomic_set(&sdebug_cmnd_count, 0); | 4225 | atomic_set(&sdebug_cmnd_count, 0); |
3386 | atomic_set(&sdebug_a_tsf, 0); | 4226 | atomic_set(&sdebug_a_tsf, 0); |
3387 | return count; | 4227 | return count; |
@@ -3589,12 +4429,27 @@ static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf, | |||
3589 | size_t count) | 4429 | size_t count) |
3590 | { | 4430 | { |
3591 | int n; | 4431 | int n; |
4432 | bool changed; | ||
3592 | 4433 | ||
3593 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { | 4434 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { |
4435 | changed = (scsi_debug_virtual_gb != n); | ||
3594 | scsi_debug_virtual_gb = n; | 4436 | scsi_debug_virtual_gb = n; |
3595 | |||
3596 | sdebug_capacity = get_sdebug_capacity(); | 4437 | sdebug_capacity = get_sdebug_capacity(); |
3597 | 4438 | if (changed) { | |
4439 | struct sdebug_host_info *sdhp; | ||
4440 | struct sdebug_dev_info *dp; | ||
4441 | |||
4442 | spin_lock(&sdebug_host_list_lock); | ||
4443 | list_for_each_entry(sdhp, &sdebug_host_list, | ||
4444 | host_list) { | ||
4445 | list_for_each_entry(dp, &sdhp->dev_info_list, | ||
4446 | dev_list) { | ||
4447 | set_bit(SDEBUG_UA_CAPACITY_CHANGED, | ||
4448 | dp->uas_bm); | ||
4449 | } | ||
4450 | } | ||
4451 | spin_unlock(&sdebug_host_list_lock); | ||
4452 | } | ||
3598 | return count; | 4453 | return count; |
3599 | } | 4454 | } |
3600 | return -EINVAL; | 4455 | return -EINVAL; |
@@ -3740,6 +4595,23 @@ static ssize_t host_lock_store(struct device_driver *ddp, const char *buf, | |||
3740 | } | 4595 | } |
3741 | static DRIVER_ATTR_RW(host_lock); | 4596 | static DRIVER_ATTR_RW(host_lock); |
3742 | 4597 | ||
4598 | static ssize_t strict_show(struct device_driver *ddp, char *buf) | ||
4599 | { | ||
4600 | return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict); | ||
4601 | } | ||
4602 | static ssize_t strict_store(struct device_driver *ddp, const char *buf, | ||
4603 | size_t count) | ||
4604 | { | ||
4605 | int n; | ||
4606 | |||
4607 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { | ||
4608 | scsi_debug_strict = (n > 0); | ||
4609 | return count; | ||
4610 | } | ||
4611 | return -EINVAL; | ||
4612 | } | ||
4613 | static DRIVER_ATTR_RW(strict); | ||
4614 | |||
3743 | 4615 | ||
3744 | /* Note: The following array creates attribute files in the | 4616 | /* Note: The following array creates attribute files in the |
3745 | /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these | 4617 | /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these |
@@ -3775,6 +4647,7 @@ static struct attribute *sdebug_drv_attrs[] = { | |||
3775 | &driver_attr_removable.attr, | 4647 | &driver_attr_removable.attr, |
3776 | &driver_attr_host_lock.attr, | 4648 | &driver_attr_host_lock.attr, |
3777 | &driver_attr_ndelay.attr, | 4649 | &driver_attr_ndelay.attr, |
4650 | &driver_attr_strict.attr, | ||
3778 | NULL, | 4651 | NULL, |
3779 | }; | 4652 | }; |
3780 | ATTRIBUTE_GROUPS(sdebug_drv); | 4653 | ATTRIBUTE_GROUPS(sdebug_drv); |
@@ -4087,374 +4960,206 @@ static void sdebug_remove_adapter(void) | |||
4087 | } | 4960 | } |
4088 | 4961 | ||
4089 | static int | 4962 | static int |
4090 | scsi_debug_queuecommand(struct scsi_cmnd *SCpnt) | 4963 | sdebug_change_qdepth(struct scsi_device *sdev, int qdepth) |
4091 | { | 4964 | { |
4092 | unsigned char *cmd = SCpnt->cmnd; | 4965 | int num_in_q = 0; |
4093 | int len, k; | 4966 | unsigned long iflags; |
4094 | unsigned int num; | 4967 | struct sdebug_dev_info *devip; |
4095 | unsigned long long lba; | ||
4096 | u32 ei_lba; | ||
4097 | int errsts = 0; | ||
4098 | int target = SCpnt->device->id; | ||
4099 | struct sdebug_dev_info *devip = NULL; | ||
4100 | int inj_recovered = 0; | ||
4101 | int inj_transport = 0; | ||
4102 | int inj_dif = 0; | ||
4103 | int inj_dix = 0; | ||
4104 | int inj_short = 0; | ||
4105 | int delay_override = 0; | ||
4106 | int unmap = 0; | ||
4107 | |||
4108 | scsi_set_resid(SCpnt, 0); | ||
4109 | if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && | ||
4110 | !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) { | ||
4111 | char b[120]; | ||
4112 | int n; | ||
4113 | 4968 | ||
4114 | len = SCpnt->cmd_len; | 4969 | spin_lock_irqsave(&queued_arr_lock, iflags); |
4115 | if (len > 32) | 4970 | devip = (struct sdebug_dev_info *)sdev->hostdata; |
4116 | strcpy(b, "too long, over 32 bytes"); | 4971 | if (NULL == devip) { |
4117 | else { | 4972 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
4118 | for (k = 0, n = 0; k < len; ++k) | 4973 | return -ENODEV; |
4119 | n += scnprintf(b + n, sizeof(b) - n, "%02x ", | 4974 | } |
4120 | (unsigned int)cmd[k]); | 4975 | num_in_q = atomic_read(&devip->num_in_q); |
4121 | } | 4976 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
4122 | sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name, | 4977 | |
4123 | b); | 4978 | if (qdepth < 1) |
4979 | qdepth = 1; | ||
4980 | /* allow to exceed max host queued_arr elements for testing */ | ||
4981 | if (qdepth > SCSI_DEBUG_CANQUEUE + 10) | ||
4982 | qdepth = SCSI_DEBUG_CANQUEUE + 10; | ||
4983 | scsi_change_queue_depth(sdev, qdepth); | ||
4984 | |||
4985 | if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { | ||
4986 | sdev_printk(KERN_INFO, sdev, | ||
4987 | "%s: qdepth=%d, num_in_q=%d\n", | ||
4988 | __func__, qdepth, num_in_q); | ||
4124 | } | 4989 | } |
4990 | return sdev->queue_depth; | ||
4991 | } | ||
4125 | 4992 | ||
4126 | if ((SCpnt->device->lun >= scsi_debug_max_luns) && | 4993 | static int |
4127 | (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) | 4994 | check_inject(struct scsi_cmnd *scp) |
4128 | return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); | 4995 | { |
4129 | devip = devInfoReg(SCpnt->device); | 4996 | struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); |
4130 | if (NULL == devip) | 4997 | |
4131 | return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); | 4998 | memset(ep, 0, sizeof(struct sdebug_scmd_extra_t)); |
4132 | 4999 | ||
4133 | if ((scsi_debug_every_nth != 0) && | 5000 | if (atomic_inc_return(&sdebug_cmnd_count) >= |
4134 | (atomic_inc_return(&sdebug_cmnd_count) >= | 5001 | abs(scsi_debug_every_nth)) { |
4135 | abs(scsi_debug_every_nth))) { | ||
4136 | atomic_set(&sdebug_cmnd_count, 0); | 5002 | atomic_set(&sdebug_cmnd_count, 0); |
4137 | if (scsi_debug_every_nth < -1) | 5003 | if (scsi_debug_every_nth < -1) |
4138 | scsi_debug_every_nth = -1; | 5004 | scsi_debug_every_nth = -1; |
4139 | if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) | 5005 | if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) |
4140 | return 0; /* ignore command causing timeout */ | 5006 | return 1; /* ignore command causing timeout */ |
4141 | else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts && | 5007 | else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts && |
4142 | scsi_medium_access_command(SCpnt)) | 5008 | scsi_medium_access_command(scp)) |
4143 | return 0; /* time out reads and writes */ | 5009 | return 1; /* time out reads and writes */ |
4144 | else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) | 5010 | if (sdebug_any_injecting_opt) { |
4145 | inj_recovered = 1; /* to reads and writes below */ | 5011 | int opts = scsi_debug_opts; |
4146 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) | 5012 | |
4147 | inj_transport = 1; /* to reads and writes below */ | 5013 | if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) |
4148 | else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts) | 5014 | ep->inj_recovered = true; |
4149 | inj_dif = 1; /* to reads and writes below */ | 5015 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) |
4150 | else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts) | 5016 | ep->inj_transport = true; |
4151 | inj_dix = 1; /* to reads and writes below */ | 5017 | else if (SCSI_DEBUG_OPT_DIF_ERR & opts) |
4152 | else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & scsi_debug_opts) | 5018 | ep->inj_dif = true; |
4153 | inj_short = 1; | 5019 | else if (SCSI_DEBUG_OPT_DIX_ERR & opts) |
4154 | } | 5020 | ep->inj_dix = true; |
4155 | 5021 | else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) | |
4156 | if (devip->wlun) { | 5022 | ep->inj_short = true; |
4157 | switch (*cmd) { | ||
4158 | case INQUIRY: | ||
4159 | case REQUEST_SENSE: | ||
4160 | case TEST_UNIT_READY: | ||
4161 | case REPORT_LUNS: | ||
4162 | break; /* only allowable wlun commands */ | ||
4163 | default: | ||
4164 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
4165 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x " | ||
4166 | "not supported for wlun\n", *cmd); | ||
4167 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4168 | INVALID_OPCODE, 0); | ||
4169 | errsts = check_condition_result; | ||
4170 | return schedule_resp(SCpnt, devip, errsts, 0); | ||
4171 | } | 5023 | } |
4172 | } | 5024 | } |
5025 | return 0; | ||
5026 | } | ||
4173 | 5027 | ||
4174 | switch (*cmd) { | 5028 | static int |
4175 | case INQUIRY: /* mandatory, ignore unit attention */ | 5029 | scsi_debug_queuecommand(struct scsi_cmnd *scp) |
4176 | delay_override = 1; | 5030 | { |
4177 | errsts = resp_inquiry(SCpnt, target, devip); | 5031 | u8 sdeb_i; |
4178 | break; | 5032 | struct scsi_device *sdp = scp->device; |
4179 | case REQUEST_SENSE: /* mandatory, ignore unit attention */ | 5033 | const struct opcode_info_t *oip; |
4180 | delay_override = 1; | 5034 | const struct opcode_info_t *r_oip; |
4181 | errsts = resp_requests(SCpnt, devip); | 5035 | struct sdebug_dev_info *devip; |
4182 | break; | 5036 | u8 *cmd = scp->cmnd; |
4183 | case REZERO_UNIT: /* actually this is REWIND for SSC */ | 5037 | int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *); |
4184 | case START_STOP: | 5038 | int k, na; |
4185 | errsts = resp_start_stop(SCpnt, devip); | 5039 | int errsts = 0; |
4186 | break; | 5040 | int errsts_no_connect = DID_NO_CONNECT << 16; |
4187 | case ALLOW_MEDIUM_REMOVAL: | 5041 | u32 flags; |
4188 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | 5042 | u16 sa; |
4189 | if (errsts) | 5043 | u8 opcode = cmd[0]; |
4190 | break; | 5044 | bool has_wlun_rl; |
4191 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 5045 | bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts); |
4192 | printk(KERN_INFO "scsi_debug: Medium removal %s\n", | ||
4193 | cmd[4] ? "inhibited" : "enabled"); | ||
4194 | break; | ||
4195 | case SEND_DIAGNOSTIC: /* mandatory */ | ||
4196 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | ||
4197 | break; | ||
4198 | case TEST_UNIT_READY: /* mandatory */ | ||
4199 | /* delay_override = 1; */ | ||
4200 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | ||
4201 | break; | ||
4202 | case RESERVE: | ||
4203 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | ||
4204 | break; | ||
4205 | case RESERVE_10: | ||
4206 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | ||
4207 | break; | ||
4208 | case RELEASE: | ||
4209 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | ||
4210 | break; | ||
4211 | case RELEASE_10: | ||
4212 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | ||
4213 | break; | ||
4214 | case READ_CAPACITY: | ||
4215 | errsts = resp_readcap(SCpnt, devip); | ||
4216 | break; | ||
4217 | case SERVICE_ACTION_IN: | ||
4218 | if (cmd[1] == SAI_READ_CAPACITY_16) | ||
4219 | errsts = resp_readcap16(SCpnt, devip); | ||
4220 | else if (cmd[1] == SAI_GET_LBA_STATUS) { | ||
4221 | |||
4222 | if (scsi_debug_lbp() == 0) { | ||
4223 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4224 | INVALID_COMMAND_OPCODE, 0); | ||
4225 | errsts = check_condition_result; | ||
4226 | } else | ||
4227 | errsts = resp_get_lba_status(SCpnt, devip); | ||
4228 | } else { | ||
4229 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4230 | INVALID_OPCODE, 0); | ||
4231 | errsts = check_condition_result; | ||
4232 | } | ||
4233 | break; | ||
4234 | case MAINTENANCE_IN: | ||
4235 | if (MI_REPORT_TARGET_PGS != cmd[1]) { | ||
4236 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4237 | INVALID_OPCODE, 0); | ||
4238 | errsts = check_condition_result; | ||
4239 | break; | ||
4240 | } | ||
4241 | errsts = resp_report_tgtpgs(SCpnt, devip); | ||
4242 | break; | ||
4243 | case READ_16: | ||
4244 | case READ_12: | ||
4245 | case READ_10: | ||
4246 | /* READ{10,12,16} and DIF Type 2 are natural enemies */ | ||
4247 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
4248 | cmd[1] & 0xe0) { | ||
4249 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4250 | INVALID_COMMAND_OPCODE, 0); | ||
4251 | errsts = check_condition_result; | ||
4252 | break; | ||
4253 | } | ||
4254 | |||
4255 | if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || | ||
4256 | scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && | ||
4257 | (cmd[1] & 0xe0) == 0) | ||
4258 | printk(KERN_ERR "Unprotected RD/WR to DIF device\n"); | ||
4259 | |||
4260 | /* fall through */ | ||
4261 | case READ_6: | ||
4262 | read: | ||
4263 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | ||
4264 | if (errsts) | ||
4265 | break; | ||
4266 | if (scsi_debug_fake_rw) | ||
4267 | break; | ||
4268 | get_data_transfer_info(cmd, &lba, &num, &ei_lba); | ||
4269 | |||
4270 | if (inj_short) | ||
4271 | num /= 2; | ||
4272 | |||
4273 | errsts = resp_read(SCpnt, lba, num, ei_lba); | ||
4274 | if (inj_recovered && (0 == errsts)) { | ||
4275 | mk_sense_buffer(SCpnt, RECOVERED_ERROR, | ||
4276 | THRESHOLD_EXCEEDED, 0); | ||
4277 | errsts = check_condition_result; | ||
4278 | } else if (inj_transport && (0 == errsts)) { | ||
4279 | mk_sense_buffer(SCpnt, ABORTED_COMMAND, | ||
4280 | TRANSPORT_PROBLEM, ACK_NAK_TO); | ||
4281 | errsts = check_condition_result; | ||
4282 | } else if (inj_dif && (0 == errsts)) { | ||
4283 | /* Logical block guard check failed */ | ||
4284 | mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); | ||
4285 | errsts = illegal_condition_result; | ||
4286 | } else if (inj_dix && (0 == errsts)) { | ||
4287 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); | ||
4288 | errsts = illegal_condition_result; | ||
4289 | } | ||
4290 | break; | ||
4291 | case REPORT_LUNS: /* mandatory, ignore unit attention */ | ||
4292 | delay_override = 1; | ||
4293 | errsts = resp_report_luns(SCpnt, devip); | ||
4294 | break; | ||
4295 | case VERIFY: /* 10 byte SBC-2 command */ | ||
4296 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | ||
4297 | break; | ||
4298 | case WRITE_16: | ||
4299 | case WRITE_12: | ||
4300 | case WRITE_10: | ||
4301 | /* WRITE{10,12,16} and DIF Type 2 are natural enemies */ | ||
4302 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
4303 | cmd[1] & 0xe0) { | ||
4304 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4305 | INVALID_COMMAND_OPCODE, 0); | ||
4306 | errsts = check_condition_result; | ||
4307 | break; | ||
4308 | } | ||
4309 | 5046 | ||
4310 | if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || | 5047 | scsi_set_resid(scp, 0); |
4311 | scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && | 5048 | if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) { |
4312 | (cmd[1] & 0xe0) == 0) | 5049 | char b[120]; |
4313 | printk(KERN_ERR "Unprotected RD/WR to DIF device\n"); | 5050 | int n, len, sb; |
4314 | 5051 | ||
4315 | /* fall through */ | 5052 | len = scp->cmd_len; |
4316 | case WRITE_6: | 5053 | sb = (int)sizeof(b); |
4317 | write: | 5054 | if (len > 32) |
4318 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | 5055 | strcpy(b, "too long, over 32 bytes"); |
4319 | if (errsts) | 5056 | else { |
4320 | break; | 5057 | for (k = 0, n = 0; k < len && n < sb; ++k) |
4321 | if (scsi_debug_fake_rw) | 5058 | n += scnprintf(b + n, sb - n, "%02x ", |
4322 | break; | 5059 | (u32)cmd[k]); |
4323 | get_data_transfer_info(cmd, &lba, &num, &ei_lba); | ||
4324 | errsts = resp_write(SCpnt, lba, num, ei_lba); | ||
4325 | if (inj_recovered && (0 == errsts)) { | ||
4326 | mk_sense_buffer(SCpnt, RECOVERED_ERROR, | ||
4327 | THRESHOLD_EXCEEDED, 0); | ||
4328 | errsts = check_condition_result; | ||
4329 | } else if (inj_dif && (0 == errsts)) { | ||
4330 | mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); | ||
4331 | errsts = illegal_condition_result; | ||
4332 | } else if (inj_dix && (0 == errsts)) { | ||
4333 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); | ||
4334 | errsts = illegal_condition_result; | ||
4335 | } | 5060 | } |
4336 | break; | 5061 | sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b); |
4337 | case WRITE_SAME_16: | 5062 | } |
4338 | case WRITE_SAME: | 5063 | has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS); |
4339 | if (cmd[1] & 0x8) { | 5064 | if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl) |
4340 | if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) || | 5065 | return schedule_resp(scp, NULL, errsts_no_connect, 0); |
4341 | (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) { | 5066 | |
4342 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | 5067 | sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */ |
4343 | INVALID_FIELD_IN_CDB, 0); | 5068 | oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */ |
4344 | errsts = check_condition_result; | 5069 | devip = (struct sdebug_dev_info *)sdp->hostdata; |
4345 | } else | 5070 | if (!devip) { |
4346 | unmap = 1; | 5071 | devip = devInfoReg(sdp); |
5072 | if (NULL == devip) | ||
5073 | return schedule_resp(scp, NULL, errsts_no_connect, 0); | ||
5074 | } | ||
5075 | na = oip->num_attached; | ||
5076 | r_pfp = oip->pfp; | ||
5077 | if (na) { /* multiple commands with this opcode */ | ||
5078 | r_oip = oip; | ||
5079 | if (FF_SA & r_oip->flags) { | ||
5080 | if (F_SA_LOW & oip->flags) | ||
5081 | sa = 0x1f & cmd[1]; | ||
5082 | else | ||
5083 | sa = get_unaligned_be16(cmd + 8); | ||
5084 | for (k = 0; k <= na; oip = r_oip->arrp + k++) { | ||
5085 | if (opcode == oip->opcode && sa == oip->sa) | ||
5086 | break; | ||
5087 | } | ||
5088 | } else { /* since no service action only check opcode */ | ||
5089 | for (k = 0; k <= na; oip = r_oip->arrp + k++) { | ||
5090 | if (opcode == oip->opcode) | ||
5091 | break; | ||
5092 | } | ||
4347 | } | 5093 | } |
4348 | if (errsts) | 5094 | if (k > na) { |
4349 | break; | 5095 | if (F_SA_LOW & r_oip->flags) |
4350 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | 5096 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 4); |
4351 | if (errsts) | 5097 | else if (F_SA_HIGH & r_oip->flags) |
4352 | break; | 5098 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, 7); |
4353 | if (scsi_debug_fake_rw) | 5099 | else |
4354 | break; | 5100 | mk_sense_invalid_opcode(scp); |
4355 | get_data_transfer_info(cmd, &lba, &num, &ei_lba); | 5101 | goto check_cond; |
4356 | errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap); | ||
4357 | break; | ||
4358 | case UNMAP: | ||
4359 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | ||
4360 | if (errsts) | ||
4361 | break; | ||
4362 | if (scsi_debug_fake_rw) | ||
4363 | break; | ||
4364 | |||
4365 | if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) { | ||
4366 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4367 | INVALID_COMMAND_OPCODE, 0); | ||
4368 | errsts = check_condition_result; | ||
4369 | } else | ||
4370 | errsts = resp_unmap(SCpnt, devip); | ||
4371 | break; | ||
4372 | case MODE_SENSE: | ||
4373 | case MODE_SENSE_10: | ||
4374 | errsts = resp_mode_sense(SCpnt, target, devip); | ||
4375 | break; | ||
4376 | case MODE_SELECT: | ||
4377 | errsts = resp_mode_select(SCpnt, 1, devip); | ||
4378 | break; | ||
4379 | case MODE_SELECT_10: | ||
4380 | errsts = resp_mode_select(SCpnt, 0, devip); | ||
4381 | break; | ||
4382 | case LOG_SENSE: | ||
4383 | errsts = resp_log_sense(SCpnt, devip); | ||
4384 | break; | ||
4385 | case SYNCHRONIZE_CACHE: | ||
4386 | delay_override = 1; | ||
4387 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | ||
4388 | break; | ||
4389 | case WRITE_BUFFER: | ||
4390 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | ||
4391 | break; | ||
4392 | case XDWRITEREAD_10: | ||
4393 | if (!scsi_bidi_cmnd(SCpnt)) { | ||
4394 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4395 | INVALID_FIELD_IN_CDB, 0); | ||
4396 | errsts = check_condition_result; | ||
4397 | break; | ||
4398 | } | 5102 | } |
4399 | 5103 | } /* else (when na==0) we assume the oip is a match */ | |
4400 | errsts = check_readiness(SCpnt, UAS_TUR, devip); | 5104 | flags = oip->flags; |
4401 | if (errsts) | 5105 | if (F_INV_OP & flags) { |
4402 | break; | 5106 | mk_sense_invalid_opcode(scp); |
4403 | if (scsi_debug_fake_rw) | 5107 | goto check_cond; |
4404 | break; | 5108 | } |
4405 | get_data_transfer_info(cmd, &lba, &num, &ei_lba); | 5109 | if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) { |
4406 | errsts = resp_read(SCpnt, lba, num, ei_lba); | 5110 | if (debug) |
4407 | if (errsts) | 5111 | sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: " |
4408 | break; | 5112 | "0x%x not supported for wlun\n", opcode); |
4409 | errsts = resp_write(SCpnt, lba, num, ei_lba); | 5113 | mk_sense_invalid_opcode(scp); |
4410 | if (errsts) | 5114 | goto check_cond; |
4411 | break; | 5115 | } |
4412 | errsts = resp_xdwriteread(SCpnt, lba, num, devip); | 5116 | if (scsi_debug_strict) { /* check cdb against mask */ |
4413 | break; | 5117 | u8 rem; |
4414 | case VARIABLE_LENGTH_CMD: | 5118 | int j; |
4415 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) { | 5119 | |
4416 | 5120 | for (k = 1; k < oip->len_mask[0] && k < 16; ++k) { | |
4417 | if ((cmd[10] & 0xe0) == 0) | 5121 | rem = ~oip->len_mask[k] & cmd[k]; |
4418 | printk(KERN_ERR | 5122 | if (rem) { |
4419 | "Unprotected RD/WR to DIF device\n"); | 5123 | for (j = 7; j >= 0; --j, rem <<= 1) { |
4420 | 5124 | if (0x80 & rem) | |
4421 | if (cmd[9] == READ_32) { | 5125 | break; |
4422 | BUG_ON(SCpnt->cmd_len < 32); | 5126 | } |
4423 | goto read; | 5127 | mk_sense_invalid_fld(scp, SDEB_IN_CDB, k, j); |
4424 | } | 5128 | goto check_cond; |
4425 | |||
4426 | if (cmd[9] == WRITE_32) { | ||
4427 | BUG_ON(SCpnt->cmd_len < 32); | ||
4428 | goto write; | ||
4429 | } | 5129 | } |
4430 | } | 5130 | } |
4431 | 5131 | } | |
4432 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | 5132 | if (!(F_SKIP_UA & flags) && |
4433 | INVALID_FIELD_IN_CDB, 0); | 5133 | SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) { |
4434 | errsts = check_condition_result; | 5134 | errsts = check_readiness(scp, UAS_ONLY, devip); |
4435 | break; | ||
4436 | case 0x85: | ||
4437 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
4438 | sdev_printk(KERN_INFO, SCpnt->device, | ||
4439 | "%s: ATA PASS-THROUGH(16) not supported\n", my_name); | ||
4440 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, | ||
4441 | INVALID_OPCODE, 0); | ||
4442 | errsts = check_condition_result; | ||
4443 | break; | ||
4444 | default: | ||
4445 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
4446 | sdev_printk(KERN_INFO, SCpnt->device, | ||
4447 | "%s: Opcode: 0x%x not supported\n", | ||
4448 | my_name, *cmd); | ||
4449 | errsts = check_readiness(SCpnt, UAS_ONLY, devip); | ||
4450 | if (errsts) | 5135 | if (errsts) |
4451 | break; /* Unit attention takes precedence */ | 5136 | goto check_cond; |
4452 | mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); | 5137 | } |
5138 | if ((F_M_ACCESS & flags) && devip->stopped) { | ||
5139 | mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); | ||
5140 | if (debug) | ||
5141 | sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: " | ||
5142 | "%s\n", my_name, "initializing command " | ||
5143 | "required"); | ||
4453 | errsts = check_condition_result; | 5144 | errsts = check_condition_result; |
4454 | break; | 5145 | goto fini; |
5146 | } | ||
5147 | if (scsi_debug_fake_rw && (F_FAKE_RW & flags)) | ||
5148 | goto fini; | ||
5149 | if (scsi_debug_every_nth) { | ||
5150 | if (check_inject(scp)) | ||
5151 | return 0; /* ignore command: make trouble */ | ||
4455 | } | 5152 | } |
4456 | return schedule_resp(SCpnt, devip, errsts, | 5153 | if (oip->pfp) /* if this command has a resp_* function, call it */ |
4457 | (delay_override ? 0 : scsi_debug_delay)); | 5154 | errsts = oip->pfp(scp, devip); |
5155 | else if (r_pfp) /* if leaf function ptr NULL, try the root's */ | ||
5156 | errsts = r_pfp(scp, devip); | ||
5157 | |||
5158 | fini: | ||
5159 | return schedule_resp(scp, devip, errsts, | ||
5160 | ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay)); | ||
5161 | check_cond: | ||
5162 | return schedule_resp(scp, devip, check_condition_result, 0); | ||
4458 | } | 5163 | } |
4459 | 5164 | ||
4460 | static int | 5165 | static int |
@@ -4472,96 +5177,6 @@ sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd) | |||
4472 | return scsi_debug_queuecommand(cmd); | 5177 | return scsi_debug_queuecommand(cmd); |
4473 | } | 5178 | } |
4474 | 5179 | ||
4475 | static int | ||
4476 | sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason) | ||
4477 | { | ||
4478 | int num_in_q = 0; | ||
4479 | int bad = 0; | ||
4480 | unsigned long iflags; | ||
4481 | struct sdebug_dev_info *devip; | ||
4482 | |||
4483 | spin_lock_irqsave(&queued_arr_lock, iflags); | ||
4484 | devip = (struct sdebug_dev_info *)sdev->hostdata; | ||
4485 | if (NULL == devip) { | ||
4486 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
4487 | return -ENODEV; | ||
4488 | } | ||
4489 | num_in_q = atomic_read(&devip->num_in_q); | ||
4490 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
4491 | if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) { | ||
4492 | if (qdepth < 1) | ||
4493 | qdepth = 1; | ||
4494 | /* allow to exceed max host queued_arr elements for testing */ | ||
4495 | if (qdepth > SCSI_DEBUG_CANQUEUE + 10) | ||
4496 | qdepth = SCSI_DEBUG_CANQUEUE + 10; | ||
4497 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); | ||
4498 | } else if (reason == SCSI_QDEPTH_QFULL) | ||
4499 | scsi_track_queue_full(sdev, qdepth); | ||
4500 | else | ||
4501 | bad = 1; | ||
4502 | if (bad) | ||
4503 | sdev_printk(KERN_WARNING, sdev, | ||
4504 | "%s: unknown reason=0x%x\n", __func__, reason); | ||
4505 | if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { | ||
4506 | if (SCSI_QDEPTH_QFULL == reason) | ||
4507 | sdev_printk(KERN_INFO, sdev, | ||
4508 | "%s: -> %d, num_in_q=%d, reason: queue full\n", | ||
4509 | __func__, qdepth, num_in_q); | ||
4510 | else { | ||
4511 | const char *cp; | ||
4512 | |||
4513 | switch (reason) { | ||
4514 | case SCSI_QDEPTH_DEFAULT: | ||
4515 | cp = "default (sysfs ?)"; | ||
4516 | break; | ||
4517 | case SCSI_QDEPTH_RAMP_UP: | ||
4518 | cp = "ramp up"; | ||
4519 | break; | ||
4520 | default: | ||
4521 | cp = "unknown"; | ||
4522 | break; | ||
4523 | } | ||
4524 | sdev_printk(KERN_INFO, sdev, | ||
4525 | "%s: qdepth=%d, num_in_q=%d, reason: %s\n", | ||
4526 | __func__, qdepth, num_in_q, cp); | ||
4527 | } | ||
4528 | } | ||
4529 | return sdev->queue_depth; | ||
4530 | } | ||
4531 | |||
4532 | static int | ||
4533 | sdebug_change_qtype(struct scsi_device *sdev, int qtype) | ||
4534 | { | ||
4535 | if (sdev->tagged_supported) { | ||
4536 | scsi_set_tag_type(sdev, qtype); | ||
4537 | if (qtype) | ||
4538 | scsi_activate_tcq(sdev, sdev->queue_depth); | ||
4539 | else | ||
4540 | scsi_deactivate_tcq(sdev, sdev->queue_depth); | ||
4541 | } else | ||
4542 | qtype = 0; | ||
4543 | if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { | ||
4544 | const char *cp; | ||
4545 | |||
4546 | switch (qtype) { | ||
4547 | case 0: | ||
4548 | cp = "untagged"; | ||
4549 | break; | ||
4550 | case MSG_SIMPLE_TAG: | ||
4551 | cp = "simple tags"; | ||
4552 | break; | ||
4553 | case MSG_ORDERED_TAG: | ||
4554 | cp = "ordered tags"; | ||
4555 | break; | ||
4556 | default: | ||
4557 | cp = "unknown"; | ||
4558 | break; | ||
4559 | } | ||
4560 | sdev_printk(KERN_INFO, sdev, "%s: to %s\n", __func__, cp); | ||
4561 | } | ||
4562 | return qtype; | ||
4563 | } | ||
4564 | |||
4565 | static struct scsi_host_template sdebug_driver_template = { | 5180 | static struct scsi_host_template sdebug_driver_template = { |
4566 | .show_info = scsi_debug_show_info, | 5181 | .show_info = scsi_debug_show_info, |
4567 | .write_info = scsi_debug_write_info, | 5182 | .write_info = scsi_debug_write_info, |
@@ -4574,7 +5189,6 @@ static struct scsi_host_template sdebug_driver_template = { | |||
4574 | .ioctl = scsi_debug_ioctl, | 5189 | .ioctl = scsi_debug_ioctl, |
4575 | .queuecommand = sdebug_queuecommand_lock_or_not, | 5190 | .queuecommand = sdebug_queuecommand_lock_or_not, |
4576 | .change_queue_depth = sdebug_change_qdepth, | 5191 | .change_queue_depth = sdebug_change_qdepth, |
4577 | .change_queue_type = sdebug_change_qtype, | ||
4578 | .eh_abort_handler = scsi_debug_abort, | 5192 | .eh_abort_handler = scsi_debug_abort, |
4579 | .eh_device_reset_handler = scsi_debug_device_reset, | 5193 | .eh_device_reset_handler = scsi_debug_device_reset, |
4580 | .eh_target_reset_handler = scsi_debug_target_reset, | 5194 | .eh_target_reset_handler = scsi_debug_target_reset, |
@@ -4587,13 +5201,16 @@ static struct scsi_host_template sdebug_driver_template = { | |||
4587 | .max_sectors = -1U, | 5201 | .max_sectors = -1U, |
4588 | .use_clustering = DISABLE_CLUSTERING, | 5202 | .use_clustering = DISABLE_CLUSTERING, |
4589 | .module = THIS_MODULE, | 5203 | .module = THIS_MODULE, |
5204 | .track_queue_depth = 1, | ||
5205 | .cmd_size = sizeof(struct sdebug_scmd_extra_t), | ||
4590 | }; | 5206 | }; |
4591 | 5207 | ||
4592 | static int sdebug_driver_probe(struct device * dev) | 5208 | static int sdebug_driver_probe(struct device * dev) |
4593 | { | 5209 | { |
4594 | int error = 0; | 5210 | int error = 0; |
4595 | struct sdebug_host_info *sdbg_host; | 5211 | int opts; |
4596 | struct Scsi_Host *hpnt; | 5212 | struct sdebug_host_info *sdbg_host; |
5213 | struct Scsi_Host *hpnt; | ||
4597 | int host_prot; | 5214 | int host_prot; |
4598 | 5215 | ||
4599 | sdbg_host = to_sdebug_host(dev); | 5216 | sdbg_host = to_sdebug_host(dev); |
@@ -4603,7 +5220,7 @@ static int sdebug_driver_probe(struct device * dev) | |||
4603 | sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; | 5220 | sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; |
4604 | hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); | 5221 | hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); |
4605 | if (NULL == hpnt) { | 5222 | if (NULL == hpnt) { |
4606 | printk(KERN_ERR "%s: scsi_register failed\n", __func__); | 5223 | pr_err("%s: scsi_host_alloc failed\n", __func__); |
4607 | error = -ENODEV; | 5224 | error = -ENODEV; |
4608 | return error; | 5225 | return error; |
4609 | } | 5226 | } |
@@ -4660,6 +5277,18 @@ static int sdebug_driver_probe(struct device * dev) | |||
4660 | else | 5277 | else |
4661 | scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); | 5278 | scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); |
4662 | 5279 | ||
5280 | opts = scsi_debug_opts; | ||
5281 | if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) | ||
5282 | sdebug_any_injecting_opt = true; | ||
5283 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) | ||
5284 | sdebug_any_injecting_opt = true; | ||
5285 | else if (SCSI_DEBUG_OPT_DIF_ERR & opts) | ||
5286 | sdebug_any_injecting_opt = true; | ||
5287 | else if (SCSI_DEBUG_OPT_DIX_ERR & opts) | ||
5288 | sdebug_any_injecting_opt = true; | ||
5289 | else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) | ||
5290 | sdebug_any_injecting_opt = true; | ||
5291 | |||
4663 | error = scsi_add_host(hpnt, &sdbg_host->dev); | 5292 | error = scsi_add_host(hpnt, &sdbg_host->dev); |
4664 | if (error) { | 5293 | if (error) { |
4665 | printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); | 5294 | printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); |