diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 1219 |
1 files changed, 537 insertions, 682 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index d1777a9a9625..07103c399fe0 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -39,16 +39,18 @@ | |||
39 | #include <linux/vmalloc.h> | 39 | #include <linux/vmalloc.h> |
40 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
41 | #include <linux/scatterlist.h> | 41 | #include <linux/scatterlist.h> |
42 | |||
43 | #include <linux/blkdev.h> | 42 | #include <linux/blkdev.h> |
44 | #include "scsi.h" | 43 | |
44 | #include <scsi/scsi.h> | ||
45 | #include <scsi/scsi_cmnd.h> | ||
46 | #include <scsi/scsi_device.h> | ||
45 | #include <scsi/scsi_host.h> | 47 | #include <scsi/scsi_host.h> |
46 | #include <scsi/scsicam.h> | 48 | #include <scsi/scsicam.h> |
49 | #include <scsi/scsi_eh.h> | ||
47 | 50 | ||
48 | #include <linux/stat.h> | 51 | #include <linux/stat.h> |
49 | 52 | ||
50 | #include "scsi_logging.h" | 53 | #include "scsi_logging.h" |
51 | #include "scsi_debug.h" | ||
52 | 54 | ||
53 | #define SCSI_DEBUG_VERSION "1.81" | 55 | #define SCSI_DEBUG_VERSION "1.81" |
54 | static const char * scsi_debug_version_date = "20070104"; | 56 | static const char * scsi_debug_version_date = "20070104"; |
@@ -146,7 +148,6 @@ static int scsi_debug_cmnd_count = 0; | |||
146 | #define DEV_READONLY(TGT) (0) | 148 | #define DEV_READONLY(TGT) (0) |
147 | #define DEV_REMOVEABLE(TGT) (0) | 149 | #define DEV_REMOVEABLE(TGT) (0) |
148 | 150 | ||
149 | static unsigned int sdebug_store_size; /* in bytes */ | ||
150 | static unsigned int sdebug_store_sectors; | 151 | static unsigned int sdebug_store_sectors; |
151 | static sector_t sdebug_capacity; /* in sectors */ | 152 | static sector_t sdebug_capacity; /* in sectors */ |
152 | 153 | ||
@@ -165,6 +166,9 @@ static int sdebug_sectors_per; /* sectors per cylinder */ | |||
165 | 166 | ||
166 | #define SDEBUG_SENSE_LEN 32 | 167 | #define SDEBUG_SENSE_LEN 32 |
167 | 168 | ||
169 | #define SCSI_DEBUG_CANQUEUE 255 | ||
170 | #define SCSI_DEBUG_MAX_CMD_LEN 16 | ||
171 | |||
168 | struct sdebug_dev_info { | 172 | struct sdebug_dev_info { |
169 | struct list_head dev_list; | 173 | struct list_head dev_list; |
170 | unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ | 174 | unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ |
@@ -202,30 +206,6 @@ struct sdebug_queued_cmd { | |||
202 | }; | 206 | }; |
203 | static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; | 207 | static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; |
204 | 208 | ||
205 | static struct scsi_host_template sdebug_driver_template = { | ||
206 | .proc_info = scsi_debug_proc_info, | ||
207 | .name = "SCSI DEBUG", | ||
208 | .info = scsi_debug_info, | ||
209 | .slave_alloc = scsi_debug_slave_alloc, | ||
210 | .slave_configure = scsi_debug_slave_configure, | ||
211 | .slave_destroy = scsi_debug_slave_destroy, | ||
212 | .ioctl = scsi_debug_ioctl, | ||
213 | .queuecommand = scsi_debug_queuecommand, | ||
214 | .eh_abort_handler = scsi_debug_abort, | ||
215 | .eh_bus_reset_handler = scsi_debug_bus_reset, | ||
216 | .eh_device_reset_handler = scsi_debug_device_reset, | ||
217 | .eh_host_reset_handler = scsi_debug_host_reset, | ||
218 | .bios_param = scsi_debug_biosparam, | ||
219 | .can_queue = SCSI_DEBUG_CANQUEUE, | ||
220 | .this_id = 7, | ||
221 | .sg_tablesize = 256, | ||
222 | .cmd_per_lun = 16, | ||
223 | .max_sectors = 0xffff, | ||
224 | .unchecked_isa_dma = 0, | ||
225 | .use_clustering = DISABLE_CLUSTERING, | ||
226 | .module = THIS_MODULE, | ||
227 | }; | ||
228 | |||
229 | static unsigned char * fake_storep; /* ramdisk storage */ | 209 | static unsigned char * fake_storep; /* ramdisk storage */ |
230 | 210 | ||
231 | static int num_aborts = 0; | 211 | static int num_aborts = 0; |
@@ -238,8 +218,6 @@ static DEFINE_RWLOCK(atomic_rw); | |||
238 | 218 | ||
239 | static char sdebug_proc_name[] = "scsi_debug"; | 219 | static char sdebug_proc_name[] = "scsi_debug"; |
240 | 220 | ||
241 | static int sdebug_driver_probe(struct device *); | ||
242 | static int sdebug_driver_remove(struct device *); | ||
243 | static struct bus_type pseudo_lld_bus; | 221 | static struct bus_type pseudo_lld_bus; |
244 | 222 | ||
245 | static struct device_driver sdebug_driverfs_driver = { | 223 | static struct device_driver sdebug_driverfs_driver = { |
@@ -255,94 +233,77 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, | |||
255 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, | 233 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, |
256 | 0, 0, 0x0, 0x0}; | 234 | 0, 0, 0x0, 0x0}; |
257 | 235 | ||
258 | /* function declarations */ | ||
259 | static int resp_inquiry(struct scsi_cmnd * SCpnt, int target, | ||
260 | struct sdebug_dev_info * devip); | ||
261 | static int resp_requests(struct scsi_cmnd * SCpnt, | ||
262 | struct sdebug_dev_info * devip); | ||
263 | static int resp_start_stop(struct scsi_cmnd * scp, | ||
264 | struct sdebug_dev_info * devip); | ||
265 | static int resp_report_tgtpgs(struct scsi_cmnd * scp, | ||
266 | struct sdebug_dev_info * devip); | ||
267 | static int resp_readcap(struct scsi_cmnd * SCpnt, | ||
268 | struct sdebug_dev_info * devip); | ||
269 | static int resp_readcap16(struct scsi_cmnd * SCpnt, | ||
270 | struct sdebug_dev_info * devip); | ||
271 | static int resp_mode_sense(struct scsi_cmnd * scp, int target, | ||
272 | struct sdebug_dev_info * devip); | ||
273 | static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, | ||
274 | struct sdebug_dev_info * devip); | ||
275 | static int resp_log_sense(struct scsi_cmnd * scp, | ||
276 | struct sdebug_dev_info * devip); | ||
277 | static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba, | ||
278 | unsigned int num, struct sdebug_dev_info * devip); | ||
279 | static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba, | ||
280 | unsigned int num, struct sdebug_dev_info * devip); | ||
281 | static int resp_report_luns(struct scsi_cmnd * SCpnt, | ||
282 | struct sdebug_dev_info * devip); | ||
283 | static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, | ||
284 | unsigned int num, struct sdebug_dev_info *devip); | ||
285 | static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | ||
286 | int arr_len); | ||
287 | static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | ||
288 | int max_arr_len); | ||
289 | static void timer_intr_handler(unsigned long); | ||
290 | static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev); | ||
291 | static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, | ||
292 | int asc, int asq); | ||
293 | static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only, | ||
294 | struct sdebug_dev_info * devip); | ||
295 | static int schedule_resp(struct scsi_cmnd * cmnd, | ||
296 | struct sdebug_dev_info * devip, | ||
297 | done_funct_t done, int scsi_result, int delta_jiff); | ||
298 | static void __init sdebug_build_parts(unsigned char * ramp); | ||
299 | static void __init init_all_queued(void); | ||
300 | static void stop_all_queued(void); | ||
301 | static int stop_queued_cmnd(struct scsi_cmnd * cmnd); | ||
302 | static int inquiry_evpd_83(unsigned char * arr, int port_group_id, | ||
303 | int target_dev_id, int dev_id_num, | ||
304 | const char * dev_id_str, int dev_id_str_len); | ||
305 | static int inquiry_evpd_88(unsigned char * arr, int target_dev_id); | ||
306 | static int do_create_driverfs_files(void); | ||
307 | static void do_remove_driverfs_files(void); | ||
308 | |||
309 | static int sdebug_add_adapter(void); | 236 | static int sdebug_add_adapter(void); |
310 | static void sdebug_remove_adapter(void); | 237 | static void sdebug_remove_adapter(void); |
311 | static void sdebug_max_tgts_luns(void); | ||
312 | 238 | ||
313 | static struct device pseudo_primary; | 239 | static void sdebug_max_tgts_luns(void) |
314 | static struct bus_type pseudo_lld_bus; | 240 | { |
241 | struct sdebug_host_info *sdbg_host; | ||
242 | struct Scsi_Host *hpnt; | ||
243 | |||
244 | spin_lock(&sdebug_host_list_lock); | ||
245 | list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { | ||
246 | hpnt = sdbg_host->shost; | ||
247 | if ((hpnt->this_id >= 0) && | ||
248 | (scsi_debug_num_tgts > hpnt->this_id)) | ||
249 | hpnt->max_id = scsi_debug_num_tgts + 1; | ||
250 | else | ||
251 | hpnt->max_id = scsi_debug_num_tgts; | ||
252 | /* scsi_debug_max_luns; */ | ||
253 | hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; | ||
254 | } | ||
255 | spin_unlock(&sdebug_host_list_lock); | ||
256 | } | ||
257 | |||
258 | static void mk_sense_buffer(struct sdebug_dev_info *devip, int key, | ||
259 | int asc, int asq) | ||
260 | { | ||
261 | unsigned char *sbuff; | ||
262 | |||
263 | sbuff = devip->sense_buff; | ||
264 | memset(sbuff, 0, SDEBUG_SENSE_LEN); | ||
265 | |||
266 | scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); | ||
267 | |||
268 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
269 | printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " | ||
270 | "[0x%x,0x%x,0x%x]\n", key, asc, asq); | ||
271 | } | ||
315 | 272 | ||
316 | static void get_data_transfer_info(unsigned char *cmd, | 273 | static void get_data_transfer_info(unsigned char *cmd, |
317 | unsigned long long *lba, unsigned int *num) | 274 | unsigned long long *lba, unsigned int *num) |
318 | { | 275 | { |
319 | int i; | ||
320 | |||
321 | switch (*cmd) { | 276 | switch (*cmd) { |
322 | case WRITE_16: | 277 | case WRITE_16: |
323 | case READ_16: | 278 | case READ_16: |
324 | for (*lba = 0, i = 0; i < 8; ++i) { | 279 | *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | |
325 | if (i > 0) | 280 | (u64)cmd[7] << 16 | (u64)cmd[6] << 24 | |
326 | *lba <<= 8; | 281 | (u64)cmd[5] << 32 | (u64)cmd[4] << 40 | |
327 | *lba += cmd[2 + i]; | 282 | (u64)cmd[3] << 48 | (u64)cmd[2] << 56; |
328 | } | 283 | |
329 | *num = cmd[13] + (cmd[12] << 8) + | 284 | *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 | |
330 | (cmd[11] << 16) + (cmd[10] << 24); | 285 | (u32)cmd[10] << 24; |
331 | break; | 286 | break; |
332 | case WRITE_12: | 287 | case WRITE_12: |
333 | case READ_12: | 288 | case READ_12: |
334 | *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); | 289 | *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | |
335 | *num = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); | 290 | (u32)cmd[2] << 24; |
291 | |||
292 | *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 | | ||
293 | (u32)cmd[6] << 24; | ||
336 | break; | 294 | break; |
337 | case WRITE_10: | 295 | case WRITE_10: |
338 | case READ_10: | 296 | case READ_10: |
339 | case XDWRITEREAD_10: | 297 | case XDWRITEREAD_10: |
340 | *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); | 298 | *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 | |
341 | *num = cmd[8] + (cmd[7] << 8); | 299 | (u32)cmd[2] << 24; |
300 | |||
301 | *num = (u32)cmd[8] | (u32)cmd[7] << 8; | ||
342 | break; | 302 | break; |
343 | case WRITE_6: | 303 | case WRITE_6: |
344 | case READ_6: | 304 | case READ_6: |
345 | *lba = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); | 305 | *lba = (u32)cmd[3] | (u32)cmd[2] << 8 | |
306 | (u32)(cmd[1] & 0x1f) << 16; | ||
346 | *num = (0 == cmd[4]) ? 256 : cmd[4]; | 307 | *num = (0 == cmd[4]) ? 256 : cmd[4]; |
347 | break; | 308 | break; |
348 | default: | 309 | default: |
@@ -350,237 +311,6 @@ static void get_data_transfer_info(unsigned char *cmd, | |||
350 | } | 311 | } |
351 | } | 312 | } |
352 | 313 | ||
353 | static | ||
354 | int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | ||
355 | { | ||
356 | unsigned char *cmd = (unsigned char *) SCpnt->cmnd; | ||
357 | int len, k; | ||
358 | unsigned int num; | ||
359 | unsigned long long lba; | ||
360 | int errsts = 0; | ||
361 | int target = SCpnt->device->id; | ||
362 | struct sdebug_dev_info * devip = NULL; | ||
363 | int inj_recovered = 0; | ||
364 | int inj_transport = 0; | ||
365 | int delay_override = 0; | ||
366 | |||
367 | if (done == NULL) | ||
368 | return 0; /* assume mid level reprocessing command */ | ||
369 | |||
370 | scsi_set_resid(SCpnt, 0); | ||
371 | if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { | ||
372 | printk(KERN_INFO "scsi_debug: cmd "); | ||
373 | for (k = 0, len = SCpnt->cmd_len; k < len; ++k) | ||
374 | printk("%02x ", (int)cmd[k]); | ||
375 | printk("\n"); | ||
376 | } | ||
377 | if(target == sdebug_driver_template.this_id) { | ||
378 | printk(KERN_INFO "scsi_debug: initiator's id used as " | ||
379 | "target!\n"); | ||
380 | return schedule_resp(SCpnt, NULL, done, | ||
381 | DID_NO_CONNECT << 16, 0); | ||
382 | } | ||
383 | |||
384 | if ((SCpnt->device->lun >= scsi_debug_max_luns) && | ||
385 | (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) | ||
386 | return schedule_resp(SCpnt, NULL, done, | ||
387 | DID_NO_CONNECT << 16, 0); | ||
388 | devip = devInfoReg(SCpnt->device); | ||
389 | if (NULL == devip) | ||
390 | return schedule_resp(SCpnt, NULL, done, | ||
391 | DID_NO_CONNECT << 16, 0); | ||
392 | |||
393 | if ((scsi_debug_every_nth != 0) && | ||
394 | (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) { | ||
395 | scsi_debug_cmnd_count = 0; | ||
396 | if (scsi_debug_every_nth < -1) | ||
397 | scsi_debug_every_nth = -1; | ||
398 | if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) | ||
399 | return 0; /* ignore command causing timeout */ | ||
400 | else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) | ||
401 | inj_recovered = 1; /* to reads and writes below */ | ||
402 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) | ||
403 | inj_transport = 1; /* to reads and writes below */ | ||
404 | } | ||
405 | |||
406 | if (devip->wlun) { | ||
407 | switch (*cmd) { | ||
408 | case INQUIRY: | ||
409 | case REQUEST_SENSE: | ||
410 | case TEST_UNIT_READY: | ||
411 | case REPORT_LUNS: | ||
412 | break; /* only allowable wlun commands */ | ||
413 | default: | ||
414 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
415 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x " | ||
416 | "not supported for wlun\n", *cmd); | ||
417 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
418 | INVALID_OPCODE, 0); | ||
419 | errsts = check_condition_result; | ||
420 | return schedule_resp(SCpnt, devip, done, errsts, | ||
421 | 0); | ||
422 | } | ||
423 | } | ||
424 | |||
425 | switch (*cmd) { | ||
426 | case INQUIRY: /* mandatory, ignore unit attention */ | ||
427 | delay_override = 1; | ||
428 | errsts = resp_inquiry(SCpnt, target, devip); | ||
429 | break; | ||
430 | case REQUEST_SENSE: /* mandatory, ignore unit attention */ | ||
431 | delay_override = 1; | ||
432 | errsts = resp_requests(SCpnt, devip); | ||
433 | break; | ||
434 | case REZERO_UNIT: /* actually this is REWIND for SSC */ | ||
435 | case START_STOP: | ||
436 | errsts = resp_start_stop(SCpnt, devip); | ||
437 | break; | ||
438 | case ALLOW_MEDIUM_REMOVAL: | ||
439 | if ((errsts = check_readiness(SCpnt, 1, devip))) | ||
440 | break; | ||
441 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
442 | printk(KERN_INFO "scsi_debug: Medium removal %s\n", | ||
443 | cmd[4] ? "inhibited" : "enabled"); | ||
444 | break; | ||
445 | case SEND_DIAGNOSTIC: /* mandatory */ | ||
446 | errsts = check_readiness(SCpnt, 1, devip); | ||
447 | break; | ||
448 | case TEST_UNIT_READY: /* mandatory */ | ||
449 | delay_override = 1; | ||
450 | errsts = check_readiness(SCpnt, 0, devip); | ||
451 | break; | ||
452 | case RESERVE: | ||
453 | errsts = check_readiness(SCpnt, 1, devip); | ||
454 | break; | ||
455 | case RESERVE_10: | ||
456 | errsts = check_readiness(SCpnt, 1, devip); | ||
457 | break; | ||
458 | case RELEASE: | ||
459 | errsts = check_readiness(SCpnt, 1, devip); | ||
460 | break; | ||
461 | case RELEASE_10: | ||
462 | errsts = check_readiness(SCpnt, 1, devip); | ||
463 | break; | ||
464 | case READ_CAPACITY: | ||
465 | errsts = resp_readcap(SCpnt, devip); | ||
466 | break; | ||
467 | case SERVICE_ACTION_IN: | ||
468 | if (SAI_READ_CAPACITY_16 != cmd[1]) { | ||
469 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
470 | INVALID_OPCODE, 0); | ||
471 | errsts = check_condition_result; | ||
472 | break; | ||
473 | } | ||
474 | errsts = resp_readcap16(SCpnt, devip); | ||
475 | break; | ||
476 | case MAINTENANCE_IN: | ||
477 | if (MI_REPORT_TARGET_PGS != cmd[1]) { | ||
478 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
479 | INVALID_OPCODE, 0); | ||
480 | errsts = check_condition_result; | ||
481 | break; | ||
482 | } | ||
483 | errsts = resp_report_tgtpgs(SCpnt, devip); | ||
484 | break; | ||
485 | case READ_16: | ||
486 | case READ_12: | ||
487 | case READ_10: | ||
488 | case READ_6: | ||
489 | if ((errsts = check_readiness(SCpnt, 0, devip))) | ||
490 | break; | ||
491 | if (scsi_debug_fake_rw) | ||
492 | break; | ||
493 | get_data_transfer_info(cmd, &lba, &num); | ||
494 | errsts = resp_read(SCpnt, lba, num, devip); | ||
495 | if (inj_recovered && (0 == errsts)) { | ||
496 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
497 | THRESHOLD_EXCEEDED, 0); | ||
498 | errsts = check_condition_result; | ||
499 | } else if (inj_transport && (0 == errsts)) { | ||
500 | mk_sense_buffer(devip, ABORTED_COMMAND, | ||
501 | TRANSPORT_PROBLEM, ACK_NAK_TO); | ||
502 | errsts = check_condition_result; | ||
503 | } | ||
504 | break; | ||
505 | case REPORT_LUNS: /* mandatory, ignore unit attention */ | ||
506 | delay_override = 1; | ||
507 | errsts = resp_report_luns(SCpnt, devip); | ||
508 | break; | ||
509 | case VERIFY: /* 10 byte SBC-2 command */ | ||
510 | errsts = check_readiness(SCpnt, 0, devip); | ||
511 | break; | ||
512 | case WRITE_16: | ||
513 | case WRITE_12: | ||
514 | case WRITE_10: | ||
515 | case WRITE_6: | ||
516 | if ((errsts = check_readiness(SCpnt, 0, devip))) | ||
517 | break; | ||
518 | if (scsi_debug_fake_rw) | ||
519 | break; | ||
520 | get_data_transfer_info(cmd, &lba, &num); | ||
521 | errsts = resp_write(SCpnt, lba, num, devip); | ||
522 | if (inj_recovered && (0 == errsts)) { | ||
523 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
524 | THRESHOLD_EXCEEDED, 0); | ||
525 | errsts = check_condition_result; | ||
526 | } | ||
527 | break; | ||
528 | case MODE_SENSE: | ||
529 | case MODE_SENSE_10: | ||
530 | errsts = resp_mode_sense(SCpnt, target, devip); | ||
531 | break; | ||
532 | case MODE_SELECT: | ||
533 | errsts = resp_mode_select(SCpnt, 1, devip); | ||
534 | break; | ||
535 | case MODE_SELECT_10: | ||
536 | errsts = resp_mode_select(SCpnt, 0, devip); | ||
537 | break; | ||
538 | case LOG_SENSE: | ||
539 | errsts = resp_log_sense(SCpnt, devip); | ||
540 | break; | ||
541 | case SYNCHRONIZE_CACHE: | ||
542 | delay_override = 1; | ||
543 | errsts = check_readiness(SCpnt, 0, devip); | ||
544 | break; | ||
545 | case WRITE_BUFFER: | ||
546 | errsts = check_readiness(SCpnt, 1, devip); | ||
547 | break; | ||
548 | case XDWRITEREAD_10: | ||
549 | if (!scsi_bidi_cmnd(SCpnt)) { | ||
550 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
551 | INVALID_FIELD_IN_CDB, 0); | ||
552 | errsts = check_condition_result; | ||
553 | break; | ||
554 | } | ||
555 | |||
556 | errsts = check_readiness(SCpnt, 0, devip); | ||
557 | if (errsts) | ||
558 | break; | ||
559 | if (scsi_debug_fake_rw) | ||
560 | break; | ||
561 | get_data_transfer_info(cmd, &lba, &num); | ||
562 | errsts = resp_read(SCpnt, lba, num, devip); | ||
563 | if (errsts) | ||
564 | break; | ||
565 | errsts = resp_write(SCpnt, lba, num, devip); | ||
566 | if (errsts) | ||
567 | break; | ||
568 | errsts = resp_xdwriteread(SCpnt, lba, num, devip); | ||
569 | break; | ||
570 | default: | ||
571 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
572 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " | ||
573 | "supported\n", *cmd); | ||
574 | if ((errsts = check_readiness(SCpnt, 1, devip))) | ||
575 | break; /* Unit attention takes precedence */ | ||
576 | mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0); | ||
577 | errsts = check_condition_result; | ||
578 | break; | ||
579 | } | ||
580 | return schedule_resp(SCpnt, devip, done, errsts, | ||
581 | (delay_override ? 0 : scsi_debug_delay)); | ||
582 | } | ||
583 | |||
584 | static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) | 314 | static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) |
585 | { | 315 | { |
586 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { | 316 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { |
@@ -613,81 +343,37 @@ static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only, | |||
613 | } | 343 | } |
614 | 344 | ||
615 | /* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */ | 345 | /* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */ |
616 | static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | 346 | static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, |
617 | int arr_len) | 347 | int arr_len) |
618 | { | 348 | { |
619 | int k, req_len, act_len, len, active; | 349 | int act_len; |
620 | void * kaddr; | ||
621 | void * kaddr_off; | ||
622 | struct scatterlist *sg; | ||
623 | struct scsi_data_buffer *sdb = scsi_in(scp); | 350 | struct scsi_data_buffer *sdb = scsi_in(scp); |
624 | 351 | ||
625 | if (!sdb->length) | 352 | if (!sdb->length) |
626 | return 0; | 353 | return 0; |
627 | if (!sdb->table.sgl) | ||
628 | return (DID_ERROR << 16); | ||
629 | if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) | 354 | if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) |
630 | return (DID_ERROR << 16); | 355 | return (DID_ERROR << 16); |
631 | active = 1; | 356 | |
632 | req_len = act_len = 0; | 357 | act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents, |
633 | for_each_sg(sdb->table.sgl, sg, sdb->table.nents, k) { | 358 | arr, arr_len); |
634 | if (active) { | ||
635 | kaddr = (unsigned char *) | ||
636 | kmap_atomic(sg_page(sg), KM_USER0); | ||
637 | if (NULL == kaddr) | ||
638 | return (DID_ERROR << 16); | ||
639 | kaddr_off = (unsigned char *)kaddr + sg->offset; | ||
640 | len = sg->length; | ||
641 | if ((req_len + len) > arr_len) { | ||
642 | active = 0; | ||
643 | len = arr_len - req_len; | ||
644 | } | ||
645 | memcpy(kaddr_off, arr + req_len, len); | ||
646 | kunmap_atomic(kaddr, KM_USER0); | ||
647 | act_len += len; | ||
648 | } | ||
649 | req_len += sg->length; | ||
650 | } | ||
651 | if (sdb->resid) | 359 | if (sdb->resid) |
652 | sdb->resid -= act_len; | 360 | sdb->resid -= act_len; |
653 | else | 361 | else |
654 | sdb->resid = req_len - act_len; | 362 | sdb->resid = scsi_bufflen(scp) - act_len; |
363 | |||
655 | return 0; | 364 | return 0; |
656 | } | 365 | } |
657 | 366 | ||
658 | /* Returns number of bytes fetched into 'arr' or -1 if error. */ | 367 | /* Returns number of bytes fetched into 'arr' or -1 if error. */ |
659 | static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | 368 | static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, |
660 | int max_arr_len) | 369 | int arr_len) |
661 | { | 370 | { |
662 | int k, req_len, len, fin; | 371 | if (!scsi_bufflen(scp)) |
663 | void * kaddr; | ||
664 | void * kaddr_off; | ||
665 | struct scatterlist * sg; | ||
666 | |||
667 | if (0 == scsi_bufflen(scp)) | ||
668 | return 0; | 372 | return 0; |
669 | if (NULL == scsi_sglist(scp)) | ||
670 | return -1; | ||
671 | if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE)) | 373 | if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE)) |
672 | return -1; | 374 | return -1; |
673 | req_len = fin = 0; | 375 | |
674 | scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) { | 376 | return scsi_sg_copy_to_buffer(scp, arr, arr_len); |
675 | kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0); | ||
676 | if (NULL == kaddr) | ||
677 | return -1; | ||
678 | kaddr_off = (unsigned char *)kaddr + sg->offset; | ||
679 | len = sg->length; | ||
680 | if ((req_len + len) > max_arr_len) { | ||
681 | len = max_arr_len - req_len; | ||
682 | fin = 1; | ||
683 | } | ||
684 | memcpy(arr + req_len, kaddr_off, len); | ||
685 | kunmap_atomic(kaddr, KM_USER0); | ||
686 | if (fin) | ||
687 | return req_len + len; | ||
688 | req_len += sg->length; | ||
689 | } | ||
690 | return req_len; | ||
691 | } | 377 | } |
692 | 378 | ||
693 | 379 | ||
@@ -1159,6 +845,14 @@ static int resp_start_stop(struct scsi_cmnd * scp, | |||
1159 | return 0; | 845 | return 0; |
1160 | } | 846 | } |
1161 | 847 | ||
848 | static sector_t get_sdebug_capacity(void) | ||
849 | { | ||
850 | if (scsi_debug_virtual_gb > 0) | ||
851 | return 2048 * 1024 * scsi_debug_virtual_gb; | ||
852 | else | ||
853 | return sdebug_store_sectors; | ||
854 | } | ||
855 | |||
1162 | #define SDEBUG_READCAP_ARR_SZ 8 | 856 | #define SDEBUG_READCAP_ARR_SZ 8 |
1163 | static int resp_readcap(struct scsi_cmnd * scp, | 857 | static int resp_readcap(struct scsi_cmnd * scp, |
1164 | struct sdebug_dev_info * devip) | 858 | struct sdebug_dev_info * devip) |
@@ -1170,11 +864,7 @@ static int resp_readcap(struct scsi_cmnd * scp, | |||
1170 | if ((errsts = check_readiness(scp, 1, devip))) | 864 | if ((errsts = check_readiness(scp, 1, devip))) |
1171 | return errsts; | 865 | return errsts; |
1172 | /* following just in case virtual_gb changed */ | 866 | /* following just in case virtual_gb changed */ |
1173 | if (scsi_debug_virtual_gb > 0) { | 867 | sdebug_capacity = get_sdebug_capacity(); |
1174 | sdebug_capacity = 2048 * 1024; | ||
1175 | sdebug_capacity *= scsi_debug_virtual_gb; | ||
1176 | } else | ||
1177 | sdebug_capacity = sdebug_store_sectors; | ||
1178 | memset(arr, 0, SDEBUG_READCAP_ARR_SZ); | 868 | memset(arr, 0, SDEBUG_READCAP_ARR_SZ); |
1179 | if (sdebug_capacity < 0xffffffff) { | 869 | if (sdebug_capacity < 0xffffffff) { |
1180 | capac = (unsigned int)sdebug_capacity - 1; | 870 | capac = (unsigned int)sdebug_capacity - 1; |
@@ -1207,11 +897,7 @@ static int resp_readcap16(struct scsi_cmnd * scp, | |||
1207 | alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) | 897 | alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) |
1208 | + cmd[13]); | 898 | + cmd[13]); |
1209 | /* following just in case virtual_gb changed */ | 899 | /* following just in case virtual_gb changed */ |
1210 | if (scsi_debug_virtual_gb > 0) { | 900 | sdebug_capacity = get_sdebug_capacity(); |
1211 | sdebug_capacity = 2048 * 1024; | ||
1212 | sdebug_capacity *= scsi_debug_virtual_gb; | ||
1213 | } else | ||
1214 | sdebug_capacity = sdebug_store_sectors; | ||
1215 | memset(arr, 0, SDEBUG_READCAP16_ARR_SZ); | 901 | memset(arr, 0, SDEBUG_READCAP16_ARR_SZ); |
1216 | capac = sdebug_capacity - 1; | 902 | capac = sdebug_capacity - 1; |
1217 | for (k = 0; k < 8; ++k, capac >>= 8) | 903 | for (k = 0; k < 8; ++k, capac >>= 8) |
@@ -1505,13 +1191,9 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, | |||
1505 | offset = 8; | 1191 | offset = 8; |
1506 | } | 1192 | } |
1507 | ap = arr + offset; | 1193 | ap = arr + offset; |
1508 | if ((bd_len > 0) && (0 == sdebug_capacity)) { | 1194 | if ((bd_len > 0) && (!sdebug_capacity)) |
1509 | if (scsi_debug_virtual_gb > 0) { | 1195 | sdebug_capacity = get_sdebug_capacity(); |
1510 | sdebug_capacity = 2048 * 1024; | 1196 | |
1511 | sdebug_capacity *= scsi_debug_virtual_gb; | ||
1512 | } else | ||
1513 | sdebug_capacity = sdebug_store_sectors; | ||
1514 | } | ||
1515 | if (8 == bd_len) { | 1197 | if (8 == bd_len) { |
1516 | if (sdebug_capacity > 0xfffffffe) { | 1198 | if (sdebug_capacity > 0xfffffffe) { |
1517 | ap[0] = 0xff; | 1199 | ap[0] = 0xff; |
@@ -1808,25 +1490,53 @@ static int resp_log_sense(struct scsi_cmnd * scp, | |||
1808 | min(len, SDEBUG_MAX_INQ_ARR_SZ)); | 1490 | min(len, SDEBUG_MAX_INQ_ARR_SZ)); |
1809 | } | 1491 | } |
1810 | 1492 | ||
1811 | static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba, | 1493 | static int check_device_access_params(struct sdebug_dev_info *devi, |
1812 | unsigned int num, struct sdebug_dev_info * devip) | 1494 | unsigned long long lba, unsigned int num) |
1813 | { | 1495 | { |
1814 | unsigned long iflags; | ||
1815 | unsigned int block, from_bottom; | ||
1816 | unsigned long long u; | ||
1817 | int ret; | ||
1818 | |||
1819 | if (lba + num > sdebug_capacity) { | 1496 | if (lba + num > sdebug_capacity) { |
1820 | mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, | 1497 | mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0); |
1821 | 0); | ||
1822 | return check_condition_result; | 1498 | return check_condition_result; |
1823 | } | 1499 | } |
1824 | /* transfer length excessive (tie in to block limits VPD page) */ | 1500 | /* transfer length excessive (tie in to block limits VPD page) */ |
1825 | if (num > sdebug_store_sectors) { | 1501 | if (num > sdebug_store_sectors) { |
1826 | mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | 1502 | mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); |
1827 | 0); | ||
1828 | return check_condition_result; | 1503 | return check_condition_result; |
1829 | } | 1504 | } |
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | static int do_device_access(struct scsi_cmnd *scmd, | ||
1509 | struct sdebug_dev_info *devi, | ||
1510 | unsigned long long lba, unsigned int num, int write) | ||
1511 | { | ||
1512 | int ret; | ||
1513 | unsigned int block, rest = 0; | ||
1514 | int (*func)(struct scsi_cmnd *, unsigned char *, int); | ||
1515 | |||
1516 | func = write ? fetch_to_dev_buffer : fill_from_dev_buffer; | ||
1517 | |||
1518 | block = do_div(lba, sdebug_store_sectors); | ||
1519 | if (block + num > sdebug_store_sectors) | ||
1520 | rest = block + num - sdebug_store_sectors; | ||
1521 | |||
1522 | ret = func(scmd, fake_storep + (block * SECT_SIZE), | ||
1523 | (num - rest) * SECT_SIZE); | ||
1524 | if (!ret && rest) | ||
1525 | ret = func(scmd, fake_storep, rest * SECT_SIZE); | ||
1526 | |||
1527 | return ret; | ||
1528 | } | ||
1529 | |||
1530 | static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, | ||
1531 | unsigned int num, struct sdebug_dev_info *devip) | ||
1532 | { | ||
1533 | unsigned long iflags; | ||
1534 | int ret; | ||
1535 | |||
1536 | ret = check_device_access_params(devip, lba, num); | ||
1537 | if (ret) | ||
1538 | return ret; | ||
1539 | |||
1830 | if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && | 1540 | if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && |
1831 | (lba <= OPT_MEDIUM_ERR_ADDR) && | 1541 | (lba <= OPT_MEDIUM_ERR_ADDR) && |
1832 | ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { | 1542 | ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { |
@@ -1845,74 +1555,30 @@ static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba, | |||
1845 | return check_condition_result; | 1555 | return check_condition_result; |
1846 | } | 1556 | } |
1847 | read_lock_irqsave(&atomic_rw, iflags); | 1557 | read_lock_irqsave(&atomic_rw, iflags); |
1848 | if ((lba + num) <= sdebug_store_sectors) | 1558 | ret = do_device_access(SCpnt, devip, lba, num, 0); |
1849 | ret = fill_from_dev_buffer(SCpnt, | ||
1850 | fake_storep + (lba * SECT_SIZE), | ||
1851 | num * SECT_SIZE); | ||
1852 | else { | ||
1853 | /* modulo when one arg is 64 bits needs do_div() */ | ||
1854 | u = lba; | ||
1855 | block = do_div(u, sdebug_store_sectors); | ||
1856 | from_bottom = 0; | ||
1857 | if ((block + num) > sdebug_store_sectors) | ||
1858 | from_bottom = (block + num) - sdebug_store_sectors; | ||
1859 | ret = fill_from_dev_buffer(SCpnt, | ||
1860 | fake_storep + (block * SECT_SIZE), | ||
1861 | (num - from_bottom) * SECT_SIZE); | ||
1862 | if ((0 == ret) && (from_bottom > 0)) | ||
1863 | ret = fill_from_dev_buffer(SCpnt, fake_storep, | ||
1864 | from_bottom * SECT_SIZE); | ||
1865 | } | ||
1866 | read_unlock_irqrestore(&atomic_rw, iflags); | 1559 | read_unlock_irqrestore(&atomic_rw, iflags); |
1867 | return ret; | 1560 | return ret; |
1868 | } | 1561 | } |
1869 | 1562 | ||
1870 | static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba, | 1563 | static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, |
1871 | unsigned int num, struct sdebug_dev_info * devip) | 1564 | unsigned int num, struct sdebug_dev_info *devip) |
1872 | { | 1565 | { |
1873 | unsigned long iflags; | 1566 | unsigned long iflags; |
1874 | unsigned int block, to_bottom; | 1567 | int ret; |
1875 | unsigned long long u; | ||
1876 | int res; | ||
1877 | 1568 | ||
1878 | if (lba + num > sdebug_capacity) { | 1569 | ret = check_device_access_params(devip, lba, num); |
1879 | mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, | 1570 | if (ret) |
1880 | 0); | 1571 | return ret; |
1881 | return check_condition_result; | ||
1882 | } | ||
1883 | /* transfer length excessive (tie in to block limits VPD page) */ | ||
1884 | if (num > sdebug_store_sectors) { | ||
1885 | mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, | ||
1886 | 0); | ||
1887 | return check_condition_result; | ||
1888 | } | ||
1889 | 1572 | ||
1890 | write_lock_irqsave(&atomic_rw, iflags); | 1573 | write_lock_irqsave(&atomic_rw, iflags); |
1891 | if ((lba + num) <= sdebug_store_sectors) | 1574 | ret = do_device_access(SCpnt, devip, lba, num, 1); |
1892 | res = fetch_to_dev_buffer(SCpnt, | ||
1893 | fake_storep + (lba * SECT_SIZE), | ||
1894 | num * SECT_SIZE); | ||
1895 | else { | ||
1896 | /* modulo when one arg is 64 bits needs do_div() */ | ||
1897 | u = lba; | ||
1898 | block = do_div(u, sdebug_store_sectors); | ||
1899 | to_bottom = 0; | ||
1900 | if ((block + num) > sdebug_store_sectors) | ||
1901 | to_bottom = (block + num) - sdebug_store_sectors; | ||
1902 | res = fetch_to_dev_buffer(SCpnt, | ||
1903 | fake_storep + (block * SECT_SIZE), | ||
1904 | (num - to_bottom) * SECT_SIZE); | ||
1905 | if ((0 == res) && (to_bottom > 0)) | ||
1906 | res = fetch_to_dev_buffer(SCpnt, fake_storep, | ||
1907 | to_bottom * SECT_SIZE); | ||
1908 | } | ||
1909 | write_unlock_irqrestore(&atomic_rw, iflags); | 1575 | write_unlock_irqrestore(&atomic_rw, iflags); |
1910 | if (-1 == res) | 1576 | if (-1 == ret) |
1911 | return (DID_ERROR << 16); | 1577 | return (DID_ERROR << 16); |
1912 | else if ((res < (num * SECT_SIZE)) && | 1578 | else if ((ret < (num * SECT_SIZE)) && |
1913 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) | 1579 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) |
1914 | printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " | 1580 | printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " |
1915 | " IO sent=%d bytes\n", num * SECT_SIZE, res); | 1581 | " IO sent=%d bytes\n", num * SECT_SIZE, ret); |
1916 | return 0; | 1582 | return 0; |
1917 | } | 1583 | } |
1918 | 1584 | ||
@@ -1987,16 +1653,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, | |||
1987 | if (!buf) | 1653 | if (!buf) |
1988 | return ret; | 1654 | return ret; |
1989 | 1655 | ||
1990 | offset = 0; | 1656 | scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp)); |
1991 | scsi_for_each_sg(scp, sg, scsi_sg_count(scp), i) { | ||
1992 | kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0); | ||
1993 | if (!kaddr) | ||
1994 | goto out; | ||
1995 | |||
1996 | memcpy(buf + offset, kaddr + sg->offset, sg->length); | ||
1997 | offset += sg->length; | ||
1998 | kunmap_atomic(kaddr, KM_USER0); | ||
1999 | } | ||
2000 | 1657 | ||
2001 | offset = 0; | 1658 | offset = 0; |
2002 | for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) { | 1659 | for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) { |
@@ -2045,7 +1702,73 @@ static void timer_intr_handler(unsigned long indx) | |||
2045 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 1702 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
2046 | } | 1703 | } |
2047 | 1704 | ||
2048 | static int scsi_debug_slave_alloc(struct scsi_device * sdp) | 1705 | |
1706 | static struct sdebug_dev_info * | ||
1707 | sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags) | ||
1708 | { | ||
1709 | struct sdebug_dev_info *devip; | ||
1710 | |||
1711 | devip = kzalloc(sizeof(*devip), flags); | ||
1712 | if (devip) { | ||
1713 | devip->sdbg_host = sdbg_host; | ||
1714 | list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list); | ||
1715 | } | ||
1716 | return devip; | ||
1717 | } | ||
1718 | |||
1719 | static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | ||
1720 | { | ||
1721 | struct sdebug_host_info * sdbg_host; | ||
1722 | struct sdebug_dev_info * open_devip = NULL; | ||
1723 | struct sdebug_dev_info * devip = | ||
1724 | (struct sdebug_dev_info *)sdev->hostdata; | ||
1725 | |||
1726 | if (devip) | ||
1727 | return devip; | ||
1728 | sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); | ||
1729 | if (!sdbg_host) { | ||
1730 | printk(KERN_ERR "Host info NULL\n"); | ||
1731 | return NULL; | ||
1732 | } | ||
1733 | list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { | ||
1734 | if ((devip->used) && (devip->channel == sdev->channel) && | ||
1735 | (devip->target == sdev->id) && | ||
1736 | (devip->lun == sdev->lun)) | ||
1737 | return devip; | ||
1738 | else { | ||
1739 | if ((!devip->used) && (!open_devip)) | ||
1740 | open_devip = devip; | ||
1741 | } | ||
1742 | } | ||
1743 | if (!open_devip) { /* try and make a new one */ | ||
1744 | open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC); | ||
1745 | if (!open_devip) { | ||
1746 | printk(KERN_ERR "%s: out of memory at line %d\n", | ||
1747 | __FUNCTION__, __LINE__); | ||
1748 | return NULL; | ||
1749 | } | ||
1750 | } | ||
1751 | |||
1752 | open_devip->channel = sdev->channel; | ||
1753 | open_devip->target = sdev->id; | ||
1754 | open_devip->lun = sdev->lun; | ||
1755 | open_devip->sdbg_host = sdbg_host; | ||
1756 | open_devip->reset = 1; | ||
1757 | open_devip->used = 1; | ||
1758 | memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN); | ||
1759 | if (scsi_debug_dsense) | ||
1760 | open_devip->sense_buff[0] = 0x72; | ||
1761 | else { | ||
1762 | open_devip->sense_buff[0] = 0x70; | ||
1763 | open_devip->sense_buff[7] = 0xa; | ||
1764 | } | ||
1765 | if (sdev->lun == SAM2_WLUN_REPORT_LUNS) | ||
1766 | open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff; | ||
1767 | |||
1768 | return open_devip; | ||
1769 | } | ||
1770 | |||
1771 | static int scsi_debug_slave_alloc(struct scsi_device *sdp) | ||
2049 | { | 1772 | { |
2050 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 1773 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
2051 | printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", | 1774 | printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", |
@@ -2054,9 +1777,9 @@ static int scsi_debug_slave_alloc(struct scsi_device * sdp) | |||
2054 | return 0; | 1777 | return 0; |
2055 | } | 1778 | } |
2056 | 1779 | ||
2057 | static int scsi_debug_slave_configure(struct scsi_device * sdp) | 1780 | static int scsi_debug_slave_configure(struct scsi_device *sdp) |
2058 | { | 1781 | { |
2059 | struct sdebug_dev_info * devip; | 1782 | struct sdebug_dev_info *devip; |
2060 | 1783 | ||
2061 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 1784 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
2062 | printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", | 1785 | printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", |
@@ -2074,10 +1797,10 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp) | |||
2074 | return 0; | 1797 | return 0; |
2075 | } | 1798 | } |
2076 | 1799 | ||
2077 | static void scsi_debug_slave_destroy(struct scsi_device * sdp) | 1800 | static void scsi_debug_slave_destroy(struct scsi_device *sdp) |
2078 | { | 1801 | { |
2079 | struct sdebug_dev_info * devip = | 1802 | struct sdebug_dev_info *devip = |
2080 | (struct sdebug_dev_info *)sdp->hostdata; | 1803 | (struct sdebug_dev_info *)sdp->hostdata; |
2081 | 1804 | ||
2082 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 1805 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
2083 | printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", | 1806 | printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", |
@@ -2089,84 +1812,44 @@ static void scsi_debug_slave_destroy(struct scsi_device * sdp) | |||
2089 | } | 1812 | } |
2090 | } | 1813 | } |
2091 | 1814 | ||
2092 | static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | 1815 | /* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */ |
1816 | static int stop_queued_cmnd(struct scsi_cmnd *cmnd) | ||
2093 | { | 1817 | { |
2094 | struct sdebug_host_info * sdbg_host; | 1818 | unsigned long iflags; |
2095 | struct sdebug_dev_info * open_devip = NULL; | 1819 | int k; |
2096 | struct sdebug_dev_info * devip = | 1820 | struct sdebug_queued_cmd *sqcp; |
2097 | (struct sdebug_dev_info *)sdev->hostdata; | ||
2098 | 1821 | ||
2099 | if (devip) | 1822 | spin_lock_irqsave(&queued_arr_lock, iflags); |
2100 | return devip; | 1823 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { |
2101 | sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata; | 1824 | sqcp = &queued_arr[k]; |
2102 | if(! sdbg_host) { | 1825 | if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) { |
2103 | printk(KERN_ERR "Host info NULL\n"); | 1826 | del_timer_sync(&sqcp->cmnd_timer); |
2104 | return NULL; | 1827 | sqcp->in_use = 0; |
2105 | } | 1828 | sqcp->a_cmnd = NULL; |
2106 | list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { | 1829 | break; |
2107 | if ((devip->used) && (devip->channel == sdev->channel) && | ||
2108 | (devip->target == sdev->id) && | ||
2109 | (devip->lun == sdev->lun)) | ||
2110 | return devip; | ||
2111 | else { | ||
2112 | if ((!devip->used) && (!open_devip)) | ||
2113 | open_devip = devip; | ||
2114 | } | 1830 | } |
2115 | } | 1831 | } |
2116 | if (NULL == open_devip) { /* try and make a new one */ | 1832 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
2117 | open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC); | 1833 | return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0; |
2118 | if (NULL == open_devip) { | ||
2119 | printk(KERN_ERR "%s: out of memory at line %d\n", | ||
2120 | __FUNCTION__, __LINE__); | ||
2121 | return NULL; | ||
2122 | } | ||
2123 | open_devip->sdbg_host = sdbg_host; | ||
2124 | list_add_tail(&open_devip->dev_list, | ||
2125 | &sdbg_host->dev_info_list); | ||
2126 | } | ||
2127 | if (open_devip) { | ||
2128 | open_devip->channel = sdev->channel; | ||
2129 | open_devip->target = sdev->id; | ||
2130 | open_devip->lun = sdev->lun; | ||
2131 | open_devip->sdbg_host = sdbg_host; | ||
2132 | open_devip->reset = 1; | ||
2133 | open_devip->used = 1; | ||
2134 | memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN); | ||
2135 | if (scsi_debug_dsense) | ||
2136 | open_devip->sense_buff[0] = 0x72; | ||
2137 | else { | ||
2138 | open_devip->sense_buff[0] = 0x70; | ||
2139 | open_devip->sense_buff[7] = 0xa; | ||
2140 | } | ||
2141 | if (sdev->lun == SAM2_WLUN_REPORT_LUNS) | ||
2142 | open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff; | ||
2143 | return open_devip; | ||
2144 | } | ||
2145 | return NULL; | ||
2146 | } | 1834 | } |
2147 | 1835 | ||
2148 | static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, | 1836 | /* Deletes (stops) timers of all queued commands */ |
2149 | int asc, int asq) | 1837 | static void stop_all_queued(void) |
2150 | { | 1838 | { |
2151 | unsigned char * sbuff; | 1839 | unsigned long iflags; |
1840 | int k; | ||
1841 | struct sdebug_queued_cmd *sqcp; | ||
2152 | 1842 | ||
2153 | sbuff = devip->sense_buff; | 1843 | spin_lock_irqsave(&queued_arr_lock, iflags); |
2154 | memset(sbuff, 0, SDEBUG_SENSE_LEN); | 1844 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { |
2155 | if (scsi_debug_dsense) { | 1845 | sqcp = &queued_arr[k]; |
2156 | sbuff[0] = 0x72; /* descriptor, current */ | 1846 | if (sqcp->in_use && sqcp->a_cmnd) { |
2157 | sbuff[1] = key; | 1847 | del_timer_sync(&sqcp->cmnd_timer); |
2158 | sbuff[2] = asc; | 1848 | sqcp->in_use = 0; |
2159 | sbuff[3] = asq; | 1849 | sqcp->a_cmnd = NULL; |
2160 | } else { | 1850 | } |
2161 | sbuff[0] = 0x70; /* fixed, current */ | ||
2162 | sbuff[2] = key; | ||
2163 | sbuff[7] = 0xa; /* implies 18 byte sense buffer */ | ||
2164 | sbuff[12] = asc; | ||
2165 | sbuff[13] = asq; | ||
2166 | } | 1851 | } |
2167 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 1852 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
2168 | printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " | ||
2169 | "[0x%x,0x%x,0x%x]\n", key, asc, asq); | ||
2170 | } | 1853 | } |
2171 | 1854 | ||
2172 | static int scsi_debug_abort(struct scsi_cmnd * SCpnt) | 1855 | static int scsi_debug_abort(struct scsi_cmnd * SCpnt) |
@@ -2226,7 +1909,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) | |||
2226 | printk(KERN_INFO "scsi_debug: bus_reset\n"); | 1909 | printk(KERN_INFO "scsi_debug: bus_reset\n"); |
2227 | ++num_bus_resets; | 1910 | ++num_bus_resets; |
2228 | if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { | 1911 | if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { |
2229 | sdbg_host = *(struct sdebug_host_info **) hp->hostdata; | 1912 | sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); |
2230 | if (sdbg_host) { | 1913 | if (sdbg_host) { |
2231 | list_for_each_entry(dev_info, | 1914 | list_for_each_entry(dev_info, |
2232 | &sdbg_host->dev_info_list, | 1915 | &sdbg_host->dev_info_list, |
@@ -2256,46 +1939,6 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) | |||
2256 | return SUCCESS; | 1939 | return SUCCESS; |
2257 | } | 1940 | } |
2258 | 1941 | ||
2259 | /* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */ | ||
2260 | static int stop_queued_cmnd(struct scsi_cmnd * cmnd) | ||
2261 | { | ||
2262 | unsigned long iflags; | ||
2263 | int k; | ||
2264 | struct sdebug_queued_cmd * sqcp; | ||
2265 | |||
2266 | spin_lock_irqsave(&queued_arr_lock, iflags); | ||
2267 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { | ||
2268 | sqcp = &queued_arr[k]; | ||
2269 | if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) { | ||
2270 | del_timer_sync(&sqcp->cmnd_timer); | ||
2271 | sqcp->in_use = 0; | ||
2272 | sqcp->a_cmnd = NULL; | ||
2273 | break; | ||
2274 | } | ||
2275 | } | ||
2276 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
2277 | return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0; | ||
2278 | } | ||
2279 | |||
2280 | /* Deletes (stops) timers of all queued commands */ | ||
2281 | static void stop_all_queued(void) | ||
2282 | { | ||
2283 | unsigned long iflags; | ||
2284 | int k; | ||
2285 | struct sdebug_queued_cmd * sqcp; | ||
2286 | |||
2287 | spin_lock_irqsave(&queued_arr_lock, iflags); | ||
2288 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { | ||
2289 | sqcp = &queued_arr[k]; | ||
2290 | if (sqcp->in_use && sqcp->a_cmnd) { | ||
2291 | del_timer_sync(&sqcp->cmnd_timer); | ||
2292 | sqcp->in_use = 0; | ||
2293 | sqcp->a_cmnd = NULL; | ||
2294 | } | ||
2295 | } | ||
2296 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
2297 | } | ||
2298 | |||
2299 | /* Initializes timers in queued array */ | 1942 | /* Initializes timers in queued array */ |
2300 | static void __init init_all_queued(void) | 1943 | static void __init init_all_queued(void) |
2301 | { | 1944 | { |
@@ -2313,7 +1956,8 @@ static void __init init_all_queued(void) | |||
2313 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 1956 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
2314 | } | 1957 | } |
2315 | 1958 | ||
2316 | static void __init sdebug_build_parts(unsigned char * ramp) | 1959 | static void __init sdebug_build_parts(unsigned char *ramp, |
1960 | unsigned long store_size) | ||
2317 | { | 1961 | { |
2318 | struct partition * pp; | 1962 | struct partition * pp; |
2319 | int starts[SDEBUG_MAX_PARTS + 2]; | 1963 | int starts[SDEBUG_MAX_PARTS + 2]; |
@@ -2321,7 +1965,7 @@ static void __init sdebug_build_parts(unsigned char * ramp) | |||
2321 | int heads_by_sects, start_sec, end_sec; | 1965 | int heads_by_sects, start_sec, end_sec; |
2322 | 1966 | ||
2323 | /* assume partition table already zeroed */ | 1967 | /* assume partition table already zeroed */ |
2324 | if ((scsi_debug_num_parts < 1) || (sdebug_store_size < 1048576)) | 1968 | if ((scsi_debug_num_parts < 1) || (store_size < 1048576)) |
2325 | return; | 1969 | return; |
2326 | if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { | 1970 | if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { |
2327 | scsi_debug_num_parts = SDEBUG_MAX_PARTS; | 1971 | scsi_debug_num_parts = SDEBUG_MAX_PARTS; |
@@ -2419,7 +2063,6 @@ static int schedule_resp(struct scsi_cmnd * cmnd, | |||
2419 | return 0; | 2063 | return 0; |
2420 | } | 2064 | } |
2421 | } | 2065 | } |
2422 | |||
2423 | /* Note: The following macros create attribute files in the | 2066 | /* Note: The following macros create attribute files in the |
2424 | /sys/module/scsi_debug/parameters directory. Unfortunately this | 2067 | /sys/module/scsi_debug/parameters directory. Unfortunately this |
2425 | driver is unaware of a change and cannot trigger auxiliary actions | 2068 | driver is unaware of a change and cannot trigger auxiliary actions |
@@ -2736,11 +2379,9 @@ static ssize_t sdebug_virtual_gb_store(struct device_driver * ddp, | |||
2736 | 2379 | ||
2737 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { | 2380 | if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { |
2738 | scsi_debug_virtual_gb = n; | 2381 | scsi_debug_virtual_gb = n; |
2739 | if (scsi_debug_virtual_gb > 0) { | 2382 | |
2740 | sdebug_capacity = 2048 * 1024; | 2383 | sdebug_capacity = get_sdebug_capacity(); |
2741 | sdebug_capacity *= scsi_debug_virtual_gb; | 2384 | |
2742 | } else | ||
2743 | sdebug_capacity = sdebug_store_sectors; | ||
2744 | return count; | 2385 | return count; |
2745 | } | 2386 | } |
2746 | return -EINVAL; | 2387 | return -EINVAL; |
@@ -2756,21 +2397,10 @@ static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) | |||
2756 | static ssize_t sdebug_add_host_store(struct device_driver * ddp, | 2397 | static ssize_t sdebug_add_host_store(struct device_driver * ddp, |
2757 | const char * buf, size_t count) | 2398 | const char * buf, size_t count) |
2758 | { | 2399 | { |
2759 | int delta_hosts; | 2400 | int delta_hosts; |
2760 | char work[20]; | ||
2761 | 2401 | ||
2762 | if (1 != sscanf(buf, "%10s", work)) | 2402 | if (sscanf(buf, "%d", &delta_hosts) != 1) |
2763 | return -EINVAL; | 2403 | return -EINVAL; |
2764 | { /* temporary hack around sscanf() problem with -ve nums */ | ||
2765 | int neg = 0; | ||
2766 | |||
2767 | if ('-' == *work) | ||
2768 | neg = 1; | ||
2769 | if (1 != sscanf(work + neg, "%d", &delta_hosts)) | ||
2770 | return -EINVAL; | ||
2771 | if (neg) | ||
2772 | delta_hosts = -delta_hosts; | ||
2773 | } | ||
2774 | if (delta_hosts > 0) { | 2404 | if (delta_hosts > 0) { |
2775 | do { | 2405 | do { |
2776 | sdebug_add_adapter(); | 2406 | sdebug_add_adapter(); |
@@ -2782,7 +2412,7 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp, | |||
2782 | } | 2412 | } |
2783 | return count; | 2413 | return count; |
2784 | } | 2414 | } |
2785 | DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, | 2415 | DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, |
2786 | sdebug_add_host_store); | 2416 | sdebug_add_host_store); |
2787 | 2417 | ||
2788 | static ssize_t sdebug_vpd_use_hostno_show(struct device_driver * ddp, | 2418 | static ssize_t sdebug_vpd_use_hostno_show(struct device_driver * ddp, |
@@ -2851,22 +2481,29 @@ static void do_remove_driverfs_files(void) | |||
2851 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); | 2481 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); |
2852 | } | 2482 | } |
2853 | 2483 | ||
2484 | static void pseudo_0_release(struct device *dev) | ||
2485 | { | ||
2486 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2487 | printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); | ||
2488 | } | ||
2489 | |||
2490 | static struct device pseudo_primary = { | ||
2491 | .bus_id = "pseudo_0", | ||
2492 | .release = pseudo_0_release, | ||
2493 | }; | ||
2494 | |||
2854 | static int __init scsi_debug_init(void) | 2495 | static int __init scsi_debug_init(void) |
2855 | { | 2496 | { |
2856 | unsigned int sz; | 2497 | unsigned long sz; |
2857 | int host_to_add; | 2498 | int host_to_add; |
2858 | int k; | 2499 | int k; |
2859 | int ret; | 2500 | int ret; |
2860 | 2501 | ||
2861 | if (scsi_debug_dev_size_mb < 1) | 2502 | if (scsi_debug_dev_size_mb < 1) |
2862 | scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ | 2503 | scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ |
2863 | sdebug_store_size = (unsigned int)scsi_debug_dev_size_mb * 1048576; | 2504 | sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; |
2864 | sdebug_store_sectors = sdebug_store_size / SECT_SIZE; | 2505 | sdebug_store_sectors = sz / SECT_SIZE; |
2865 | if (scsi_debug_virtual_gb > 0) { | 2506 | sdebug_capacity = get_sdebug_capacity(); |
2866 | sdebug_capacity = 2048 * 1024; | ||
2867 | sdebug_capacity *= scsi_debug_virtual_gb; | ||
2868 | } else | ||
2869 | sdebug_capacity = sdebug_store_sectors; | ||
2870 | 2507 | ||
2871 | /* play around with geometry, don't waste too much on track 0 */ | 2508 | /* play around with geometry, don't waste too much on track 0 */ |
2872 | sdebug_heads = 8; | 2509 | sdebug_heads = 8; |
@@ -2885,7 +2522,6 @@ static int __init scsi_debug_init(void) | |||
2885 | (sdebug_sectors_per * sdebug_heads); | 2522 | (sdebug_sectors_per * sdebug_heads); |
2886 | } | 2523 | } |
2887 | 2524 | ||
2888 | sz = sdebug_store_size; | ||
2889 | fake_storep = vmalloc(sz); | 2525 | fake_storep = vmalloc(sz); |
2890 | if (NULL == fake_storep) { | 2526 | if (NULL == fake_storep) { |
2891 | printk(KERN_ERR "scsi_debug_init: out of memory, 1\n"); | 2527 | printk(KERN_ERR "scsi_debug_init: out of memory, 1\n"); |
@@ -2893,7 +2529,7 @@ static int __init scsi_debug_init(void) | |||
2893 | } | 2529 | } |
2894 | memset(fake_storep, 0, sz); | 2530 | memset(fake_storep, 0, sz); |
2895 | if (scsi_debug_num_parts > 0) | 2531 | if (scsi_debug_num_parts > 0) |
2896 | sdebug_build_parts(fake_storep); | 2532 | sdebug_build_parts(fake_storep, sz); |
2897 | 2533 | ||
2898 | ret = device_register(&pseudo_primary); | 2534 | ret = device_register(&pseudo_primary); |
2899 | if (ret < 0) { | 2535 | if (ret < 0) { |
@@ -2922,8 +2558,6 @@ static int __init scsi_debug_init(void) | |||
2922 | 2558 | ||
2923 | init_all_queued(); | 2559 | init_all_queued(); |
2924 | 2560 | ||
2925 | sdebug_driver_template.proc_name = sdebug_proc_name; | ||
2926 | |||
2927 | host_to_add = scsi_debug_add_host; | 2561 | host_to_add = scsi_debug_add_host; |
2928 | scsi_debug_add_host = 0; | 2562 | scsi_debug_add_host = 0; |
2929 | 2563 | ||
@@ -2972,30 +2606,6 @@ static void __exit scsi_debug_exit(void) | |||
2972 | device_initcall(scsi_debug_init); | 2606 | device_initcall(scsi_debug_init); |
2973 | module_exit(scsi_debug_exit); | 2607 | module_exit(scsi_debug_exit); |
2974 | 2608 | ||
2975 | static void pseudo_0_release(struct device * dev) | ||
2976 | { | ||
2977 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2978 | printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); | ||
2979 | } | ||
2980 | |||
2981 | static struct device pseudo_primary = { | ||
2982 | .bus_id = "pseudo_0", | ||
2983 | .release = pseudo_0_release, | ||
2984 | }; | ||
2985 | |||
2986 | static int pseudo_lld_bus_match(struct device *dev, | ||
2987 | struct device_driver *dev_driver) | ||
2988 | { | ||
2989 | return 1; | ||
2990 | } | ||
2991 | |||
2992 | static struct bus_type pseudo_lld_bus = { | ||
2993 | .name = "pseudo", | ||
2994 | .match = pseudo_lld_bus_match, | ||
2995 | .probe = sdebug_driver_probe, | ||
2996 | .remove = sdebug_driver_remove, | ||
2997 | }; | ||
2998 | |||
2999 | static void sdebug_release_adapter(struct device * dev) | 2609 | static void sdebug_release_adapter(struct device * dev) |
3000 | { | 2610 | { |
3001 | struct sdebug_host_info *sdbg_host; | 2611 | struct sdebug_host_info *sdbg_host; |
@@ -3009,8 +2619,7 @@ static int sdebug_add_adapter(void) | |||
3009 | int k, devs_per_host; | 2619 | int k, devs_per_host; |
3010 | int error = 0; | 2620 | int error = 0; |
3011 | struct sdebug_host_info *sdbg_host; | 2621 | struct sdebug_host_info *sdbg_host; |
3012 | struct sdebug_dev_info *sdbg_devinfo; | 2622 | struct sdebug_dev_info *sdbg_devinfo, *tmp; |
3013 | struct list_head *lh, *lh_sf; | ||
3014 | 2623 | ||
3015 | sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); | 2624 | sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); |
3016 | if (NULL == sdbg_host) { | 2625 | if (NULL == sdbg_host) { |
@@ -3023,16 +2632,13 @@ static int sdebug_add_adapter(void) | |||
3023 | 2632 | ||
3024 | devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns; | 2633 | devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns; |
3025 | for (k = 0; k < devs_per_host; k++) { | 2634 | for (k = 0; k < devs_per_host; k++) { |
3026 | sdbg_devinfo = kzalloc(sizeof(*sdbg_devinfo),GFP_KERNEL); | 2635 | sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL); |
3027 | if (NULL == sdbg_devinfo) { | 2636 | if (!sdbg_devinfo) { |
3028 | printk(KERN_ERR "%s: out of memory at line %d\n", | 2637 | printk(KERN_ERR "%s: out of memory at line %d\n", |
3029 | __FUNCTION__, __LINE__); | 2638 | __FUNCTION__, __LINE__); |
3030 | error = -ENOMEM; | 2639 | error = -ENOMEM; |
3031 | goto clean; | 2640 | goto clean; |
3032 | } | 2641 | } |
3033 | sdbg_devinfo->sdbg_host = sdbg_host; | ||
3034 | list_add_tail(&sdbg_devinfo->dev_list, | ||
3035 | &sdbg_host->dev_info_list); | ||
3036 | } | 2642 | } |
3037 | 2643 | ||
3038 | spin_lock(&sdebug_host_list_lock); | 2644 | spin_lock(&sdebug_host_list_lock); |
@@ -3053,9 +2659,8 @@ static int sdebug_add_adapter(void) | |||
3053 | return error; | 2659 | return error; |
3054 | 2660 | ||
3055 | clean: | 2661 | clean: |
3056 | list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { | 2662 | list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list, |
3057 | sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, | 2663 | dev_list) { |
3058 | dev_list); | ||
3059 | list_del(&sdbg_devinfo->dev_list); | 2664 | list_del(&sdbg_devinfo->dev_list); |
3060 | kfree(sdbg_devinfo); | 2665 | kfree(sdbg_devinfo); |
3061 | } | 2666 | } |
@@ -3083,6 +2688,263 @@ static void sdebug_remove_adapter(void) | |||
3083 | --scsi_debug_add_host; | 2688 | --scsi_debug_add_host; |
3084 | } | 2689 | } |
3085 | 2690 | ||
2691 | static | ||
2692 | int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) | ||
2693 | { | ||
2694 | unsigned char *cmd = (unsigned char *) SCpnt->cmnd; | ||
2695 | int len, k; | ||
2696 | unsigned int num; | ||
2697 | unsigned long long lba; | ||
2698 | int errsts = 0; | ||
2699 | int target = SCpnt->device->id; | ||
2700 | struct sdebug_dev_info *devip = NULL; | ||
2701 | int inj_recovered = 0; | ||
2702 | int inj_transport = 0; | ||
2703 | int delay_override = 0; | ||
2704 | |||
2705 | scsi_set_resid(SCpnt, 0); | ||
2706 | if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { | ||
2707 | printk(KERN_INFO "scsi_debug: cmd "); | ||
2708 | for (k = 0, len = SCpnt->cmd_len; k < len; ++k) | ||
2709 | printk("%02x ", (int)cmd[k]); | ||
2710 | printk("\n"); | ||
2711 | } | ||
2712 | |||
2713 | if (target == SCpnt->device->host->hostt->this_id) { | ||
2714 | printk(KERN_INFO "scsi_debug: initiator's id used as " | ||
2715 | "target!\n"); | ||
2716 | return schedule_resp(SCpnt, NULL, done, | ||
2717 | DID_NO_CONNECT << 16, 0); | ||
2718 | } | ||
2719 | |||
2720 | if ((SCpnt->device->lun >= scsi_debug_max_luns) && | ||
2721 | (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) | ||
2722 | return schedule_resp(SCpnt, NULL, done, | ||
2723 | DID_NO_CONNECT << 16, 0); | ||
2724 | devip = devInfoReg(SCpnt->device); | ||
2725 | if (NULL == devip) | ||
2726 | return schedule_resp(SCpnt, NULL, done, | ||
2727 | DID_NO_CONNECT << 16, 0); | ||
2728 | |||
2729 | if ((scsi_debug_every_nth != 0) && | ||
2730 | (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) { | ||
2731 | scsi_debug_cmnd_count = 0; | ||
2732 | if (scsi_debug_every_nth < -1) | ||
2733 | scsi_debug_every_nth = -1; | ||
2734 | if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) | ||
2735 | return 0; /* ignore command causing timeout */ | ||
2736 | else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) | ||
2737 | inj_recovered = 1; /* to reads and writes below */ | ||
2738 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) | ||
2739 | inj_transport = 1; /* to reads and writes below */ | ||
2740 | } | ||
2741 | |||
2742 | if (devip->wlun) { | ||
2743 | switch (*cmd) { | ||
2744 | case INQUIRY: | ||
2745 | case REQUEST_SENSE: | ||
2746 | case TEST_UNIT_READY: | ||
2747 | case REPORT_LUNS: | ||
2748 | break; /* only allowable wlun commands */ | ||
2749 | default: | ||
2750 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2751 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x " | ||
2752 | "not supported for wlun\n", *cmd); | ||
2753 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2754 | INVALID_OPCODE, 0); | ||
2755 | errsts = check_condition_result; | ||
2756 | return schedule_resp(SCpnt, devip, done, errsts, | ||
2757 | 0); | ||
2758 | } | ||
2759 | } | ||
2760 | |||
2761 | switch (*cmd) { | ||
2762 | case INQUIRY: /* mandatory, ignore unit attention */ | ||
2763 | delay_override = 1; | ||
2764 | errsts = resp_inquiry(SCpnt, target, devip); | ||
2765 | break; | ||
2766 | case REQUEST_SENSE: /* mandatory, ignore unit attention */ | ||
2767 | delay_override = 1; | ||
2768 | errsts = resp_requests(SCpnt, devip); | ||
2769 | break; | ||
2770 | case REZERO_UNIT: /* actually this is REWIND for SSC */ | ||
2771 | case START_STOP: | ||
2772 | errsts = resp_start_stop(SCpnt, devip); | ||
2773 | break; | ||
2774 | case ALLOW_MEDIUM_REMOVAL: | ||
2775 | errsts = check_readiness(SCpnt, 1, devip); | ||
2776 | if (errsts) | ||
2777 | break; | ||
2778 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2779 | printk(KERN_INFO "scsi_debug: Medium removal %s\n", | ||
2780 | cmd[4] ? "inhibited" : "enabled"); | ||
2781 | break; | ||
2782 | case SEND_DIAGNOSTIC: /* mandatory */ | ||
2783 | errsts = check_readiness(SCpnt, 1, devip); | ||
2784 | break; | ||
2785 | case TEST_UNIT_READY: /* mandatory */ | ||
2786 | delay_override = 1; | ||
2787 | errsts = check_readiness(SCpnt, 0, devip); | ||
2788 | break; | ||
2789 | case RESERVE: | ||
2790 | errsts = check_readiness(SCpnt, 1, devip); | ||
2791 | break; | ||
2792 | case RESERVE_10: | ||
2793 | errsts = check_readiness(SCpnt, 1, devip); | ||
2794 | break; | ||
2795 | case RELEASE: | ||
2796 | errsts = check_readiness(SCpnt, 1, devip); | ||
2797 | break; | ||
2798 | case RELEASE_10: | ||
2799 | errsts = check_readiness(SCpnt, 1, devip); | ||
2800 | break; | ||
2801 | case READ_CAPACITY: | ||
2802 | errsts = resp_readcap(SCpnt, devip); | ||
2803 | break; | ||
2804 | case SERVICE_ACTION_IN: | ||
2805 | if (SAI_READ_CAPACITY_16 != cmd[1]) { | ||
2806 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2807 | INVALID_OPCODE, 0); | ||
2808 | errsts = check_condition_result; | ||
2809 | break; | ||
2810 | } | ||
2811 | errsts = resp_readcap16(SCpnt, devip); | ||
2812 | break; | ||
2813 | case MAINTENANCE_IN: | ||
2814 | if (MI_REPORT_TARGET_PGS != cmd[1]) { | ||
2815 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2816 | INVALID_OPCODE, 0); | ||
2817 | errsts = check_condition_result; | ||
2818 | break; | ||
2819 | } | ||
2820 | errsts = resp_report_tgtpgs(SCpnt, devip); | ||
2821 | break; | ||
2822 | case READ_16: | ||
2823 | case READ_12: | ||
2824 | case READ_10: | ||
2825 | case READ_6: | ||
2826 | errsts = check_readiness(SCpnt, 0, devip); | ||
2827 | if (errsts) | ||
2828 | break; | ||
2829 | if (scsi_debug_fake_rw) | ||
2830 | break; | ||
2831 | get_data_transfer_info(cmd, &lba, &num); | ||
2832 | errsts = resp_read(SCpnt, lba, num, devip); | ||
2833 | if (inj_recovered && (0 == errsts)) { | ||
2834 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
2835 | THRESHOLD_EXCEEDED, 0); | ||
2836 | errsts = check_condition_result; | ||
2837 | } else if (inj_transport && (0 == errsts)) { | ||
2838 | mk_sense_buffer(devip, ABORTED_COMMAND, | ||
2839 | TRANSPORT_PROBLEM, ACK_NAK_TO); | ||
2840 | errsts = check_condition_result; | ||
2841 | } | ||
2842 | break; | ||
2843 | case REPORT_LUNS: /* mandatory, ignore unit attention */ | ||
2844 | delay_override = 1; | ||
2845 | errsts = resp_report_luns(SCpnt, devip); | ||
2846 | break; | ||
2847 | case VERIFY: /* 10 byte SBC-2 command */ | ||
2848 | errsts = check_readiness(SCpnt, 0, devip); | ||
2849 | break; | ||
2850 | case WRITE_16: | ||
2851 | case WRITE_12: | ||
2852 | case WRITE_10: | ||
2853 | case WRITE_6: | ||
2854 | errsts = check_readiness(SCpnt, 0, devip); | ||
2855 | if (errsts) | ||
2856 | break; | ||
2857 | if (scsi_debug_fake_rw) | ||
2858 | break; | ||
2859 | get_data_transfer_info(cmd, &lba, &num); | ||
2860 | errsts = resp_write(SCpnt, lba, num, devip); | ||
2861 | if (inj_recovered && (0 == errsts)) { | ||
2862 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
2863 | THRESHOLD_EXCEEDED, 0); | ||
2864 | errsts = check_condition_result; | ||
2865 | } | ||
2866 | break; | ||
2867 | case MODE_SENSE: | ||
2868 | case MODE_SENSE_10: | ||
2869 | errsts = resp_mode_sense(SCpnt, target, devip); | ||
2870 | break; | ||
2871 | case MODE_SELECT: | ||
2872 | errsts = resp_mode_select(SCpnt, 1, devip); | ||
2873 | break; | ||
2874 | case MODE_SELECT_10: | ||
2875 | errsts = resp_mode_select(SCpnt, 0, devip); | ||
2876 | break; | ||
2877 | case LOG_SENSE: | ||
2878 | errsts = resp_log_sense(SCpnt, devip); | ||
2879 | break; | ||
2880 | case SYNCHRONIZE_CACHE: | ||
2881 | delay_override = 1; | ||
2882 | errsts = check_readiness(SCpnt, 0, devip); | ||
2883 | break; | ||
2884 | case WRITE_BUFFER: | ||
2885 | errsts = check_readiness(SCpnt, 1, devip); | ||
2886 | break; | ||
2887 | case XDWRITEREAD_10: | ||
2888 | if (!scsi_bidi_cmnd(SCpnt)) { | ||
2889 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2890 | INVALID_FIELD_IN_CDB, 0); | ||
2891 | errsts = check_condition_result; | ||
2892 | break; | ||
2893 | } | ||
2894 | |||
2895 | errsts = check_readiness(SCpnt, 0, devip); | ||
2896 | if (errsts) | ||
2897 | break; | ||
2898 | if (scsi_debug_fake_rw) | ||
2899 | break; | ||
2900 | get_data_transfer_info(cmd, &lba, &num); | ||
2901 | errsts = resp_read(SCpnt, lba, num, devip); | ||
2902 | if (errsts) | ||
2903 | break; | ||
2904 | errsts = resp_write(SCpnt, lba, num, devip); | ||
2905 | if (errsts) | ||
2906 | break; | ||
2907 | errsts = resp_xdwriteread(SCpnt, lba, num, devip); | ||
2908 | break; | ||
2909 | default: | ||
2910 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2911 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " | ||
2912 | "supported\n", *cmd); | ||
2913 | errsts = check_readiness(SCpnt, 1, devip); | ||
2914 | if (errsts) | ||
2915 | break; /* Unit attention takes precedence */ | ||
2916 | mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0); | ||
2917 | errsts = check_condition_result; | ||
2918 | break; | ||
2919 | } | ||
2920 | return schedule_resp(SCpnt, devip, done, errsts, | ||
2921 | (delay_override ? 0 : scsi_debug_delay)); | ||
2922 | } | ||
2923 | |||
2924 | static struct scsi_host_template sdebug_driver_template = { | ||
2925 | .proc_info = scsi_debug_proc_info, | ||
2926 | .proc_name = sdebug_proc_name, | ||
2927 | .name = "SCSI DEBUG", | ||
2928 | .info = scsi_debug_info, | ||
2929 | .slave_alloc = scsi_debug_slave_alloc, | ||
2930 | .slave_configure = scsi_debug_slave_configure, | ||
2931 | .slave_destroy = scsi_debug_slave_destroy, | ||
2932 | .ioctl = scsi_debug_ioctl, | ||
2933 | .queuecommand = scsi_debug_queuecommand, | ||
2934 | .eh_abort_handler = scsi_debug_abort, | ||
2935 | .eh_bus_reset_handler = scsi_debug_bus_reset, | ||
2936 | .eh_device_reset_handler = scsi_debug_device_reset, | ||
2937 | .eh_host_reset_handler = scsi_debug_host_reset, | ||
2938 | .bios_param = scsi_debug_biosparam, | ||
2939 | .can_queue = SCSI_DEBUG_CANQUEUE, | ||
2940 | .this_id = 7, | ||
2941 | .sg_tablesize = 256, | ||
2942 | .cmd_per_lun = 16, | ||
2943 | .max_sectors = 0xffff, | ||
2944 | .use_clustering = DISABLE_CLUSTERING, | ||
2945 | .module = THIS_MODULE, | ||
2946 | }; | ||
2947 | |||
3086 | static int sdebug_driver_probe(struct device * dev) | 2948 | static int sdebug_driver_probe(struct device * dev) |
3087 | { | 2949 | { |
3088 | int error = 0; | 2950 | int error = 0; |
@@ -3120,9 +2982,8 @@ static int sdebug_driver_probe(struct device * dev) | |||
3120 | 2982 | ||
3121 | static int sdebug_driver_remove(struct device * dev) | 2983 | static int sdebug_driver_remove(struct device * dev) |
3122 | { | 2984 | { |
3123 | struct list_head *lh, *lh_sf; | ||
3124 | struct sdebug_host_info *sdbg_host; | 2985 | struct sdebug_host_info *sdbg_host; |
3125 | struct sdebug_dev_info *sdbg_devinfo; | 2986 | struct sdebug_dev_info *sdbg_devinfo, *tmp; |
3126 | 2987 | ||
3127 | sdbg_host = to_sdebug_host(dev); | 2988 | sdbg_host = to_sdebug_host(dev); |
3128 | 2989 | ||
@@ -3134,9 +2995,8 @@ static int sdebug_driver_remove(struct device * dev) | |||
3134 | 2995 | ||
3135 | scsi_remove_host(sdbg_host->shost); | 2996 | scsi_remove_host(sdbg_host->shost); |
3136 | 2997 | ||
3137 | list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { | 2998 | list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list, |
3138 | sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, | 2999 | dev_list) { |
3139 | dev_list); | ||
3140 | list_del(&sdbg_devinfo->dev_list); | 3000 | list_del(&sdbg_devinfo->dev_list); |
3141 | kfree(sdbg_devinfo); | 3001 | kfree(sdbg_devinfo); |
3142 | } | 3002 | } |
@@ -3145,20 +3005,15 @@ static int sdebug_driver_remove(struct device * dev) | |||
3145 | return 0; | 3005 | return 0; |
3146 | } | 3006 | } |
3147 | 3007 | ||
3148 | static void sdebug_max_tgts_luns(void) | 3008 | static int pseudo_lld_bus_match(struct device *dev, |
3009 | struct device_driver *dev_driver) | ||
3149 | { | 3010 | { |
3150 | struct sdebug_host_info * sdbg_host; | 3011 | return 1; |
3151 | struct Scsi_Host *hpnt; | ||
3152 | |||
3153 | spin_lock(&sdebug_host_list_lock); | ||
3154 | list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { | ||
3155 | hpnt = sdbg_host->shost; | ||
3156 | if ((hpnt->this_id >= 0) && | ||
3157 | (scsi_debug_num_tgts > hpnt->this_id)) | ||
3158 | hpnt->max_id = scsi_debug_num_tgts + 1; | ||
3159 | else | ||
3160 | hpnt->max_id = scsi_debug_num_tgts; | ||
3161 | hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* scsi_debug_max_luns; */ | ||
3162 | } | ||
3163 | spin_unlock(&sdebug_host_list_lock); | ||
3164 | } | 3012 | } |
3013 | |||
3014 | static struct bus_type pseudo_lld_bus = { | ||
3015 | .name = "pseudo", | ||
3016 | .match = pseudo_lld_bus_match, | ||
3017 | .probe = sdebug_driver_probe, | ||
3018 | .remove = sdebug_driver_remove, | ||
3019 | }; | ||