diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 174 |
1 files changed, 118 insertions, 56 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 82c06f0a9d02..1541c174937a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -280,6 +280,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba, | |||
280 | unsigned int num, struct sdebug_dev_info * devip); | 280 | unsigned int num, struct sdebug_dev_info * devip); |
281 | static int resp_report_luns(struct scsi_cmnd * SCpnt, | 281 | static int resp_report_luns(struct scsi_cmnd * SCpnt, |
282 | struct sdebug_dev_info * devip); | 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); | ||
283 | static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | 285 | static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, |
284 | int arr_len); | 286 | int arr_len); |
285 | static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | 287 | static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, |
@@ -311,12 +313,48 @@ static void sdebug_max_tgts_luns(void); | |||
311 | static struct device pseudo_primary; | 313 | static struct device pseudo_primary; |
312 | static struct bus_type pseudo_lld_bus; | 314 | static struct bus_type pseudo_lld_bus; |
313 | 315 | ||
316 | static void get_data_transfer_info(unsigned char *cmd, | ||
317 | unsigned long long *lba, unsigned int *num) | ||
318 | { | ||
319 | int i; | ||
320 | |||
321 | switch (*cmd) { | ||
322 | case WRITE_16: | ||
323 | case READ_16: | ||
324 | for (*lba = 0, i = 0; i < 8; ++i) { | ||
325 | if (i > 0) | ||
326 | *lba <<= 8; | ||
327 | *lba += cmd[2 + i]; | ||
328 | } | ||
329 | *num = cmd[13] + (cmd[12] << 8) + | ||
330 | (cmd[11] << 16) + (cmd[10] << 24); | ||
331 | break; | ||
332 | case WRITE_12: | ||
333 | case READ_12: | ||
334 | *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); | ||
335 | *num = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); | ||
336 | break; | ||
337 | case WRITE_10: | ||
338 | case READ_10: | ||
339 | case XDWRITEREAD_10: | ||
340 | *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); | ||
341 | *num = cmd[8] + (cmd[7] << 8); | ||
342 | break; | ||
343 | case WRITE_6: | ||
344 | case READ_6: | ||
345 | *lba = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); | ||
346 | *num = (0 == cmd[4]) ? 256 : cmd[4]; | ||
347 | break; | ||
348 | default: | ||
349 | break; | ||
350 | } | ||
351 | } | ||
314 | 352 | ||
315 | static | 353 | static |
316 | int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | 354 | int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) |
317 | { | 355 | { |
318 | unsigned char *cmd = (unsigned char *) SCpnt->cmnd; | 356 | unsigned char *cmd = (unsigned char *) SCpnt->cmnd; |
319 | int len, k, j; | 357 | int len, k; |
320 | unsigned int num; | 358 | unsigned int num; |
321 | unsigned long long lba; | 359 | unsigned long long lba; |
322 | int errsts = 0; | 360 | int errsts = 0; |
@@ -452,28 +490,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | |||
452 | break; | 490 | break; |
453 | if (scsi_debug_fake_rw) | 491 | if (scsi_debug_fake_rw) |
454 | break; | 492 | break; |
455 | if ((*cmd) == READ_16) { | 493 | get_data_transfer_info(cmd, &lba, &num); |
456 | for (lba = 0, j = 0; j < 8; ++j) { | ||
457 | if (j > 0) | ||
458 | lba <<= 8; | ||
459 | lba += cmd[2 + j]; | ||
460 | } | ||
461 | num = cmd[13] + (cmd[12] << 8) + | ||
462 | (cmd[11] << 16) + (cmd[10] << 24); | ||
463 | } else if ((*cmd) == READ_12) { | ||
464 | lba = cmd[5] + (cmd[4] << 8) + | ||
465 | (cmd[3] << 16) + (cmd[2] << 24); | ||
466 | num = cmd[9] + (cmd[8] << 8) + | ||
467 | (cmd[7] << 16) + (cmd[6] << 24); | ||
468 | } else if ((*cmd) == READ_10) { | ||
469 | lba = cmd[5] + (cmd[4] << 8) + | ||
470 | (cmd[3] << 16) + (cmd[2] << 24); | ||
471 | num = cmd[8] + (cmd[7] << 8); | ||
472 | } else { /* READ (6) */ | ||
473 | lba = cmd[3] + (cmd[2] << 8) + | ||
474 | ((cmd[1] & 0x1f) << 16); | ||
475 | num = (0 == cmd[4]) ? 256 : cmd[4]; | ||
476 | } | ||
477 | errsts = resp_read(SCpnt, lba, num, devip); | 494 | errsts = resp_read(SCpnt, lba, num, devip); |
478 | if (inj_recovered && (0 == errsts)) { | 495 | if (inj_recovered && (0 == errsts)) { |
479 | mk_sense_buffer(devip, RECOVERED_ERROR, | 496 | mk_sense_buffer(devip, RECOVERED_ERROR, |
@@ -500,28 +517,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | |||
500 | break; | 517 | break; |
501 | if (scsi_debug_fake_rw) | 518 | if (scsi_debug_fake_rw) |
502 | break; | 519 | break; |
503 | if ((*cmd) == WRITE_16) { | 520 | get_data_transfer_info(cmd, &lba, &num); |
504 | for (lba = 0, j = 0; j < 8; ++j) { | ||
505 | if (j > 0) | ||
506 | lba <<= 8; | ||
507 | lba += cmd[2 + j]; | ||
508 | } | ||
509 | num = cmd[13] + (cmd[12] << 8) + | ||
510 | (cmd[11] << 16) + (cmd[10] << 24); | ||
511 | } else if ((*cmd) == WRITE_12) { | ||
512 | lba = cmd[5] + (cmd[4] << 8) + | ||
513 | (cmd[3] << 16) + (cmd[2] << 24); | ||
514 | num = cmd[9] + (cmd[8] << 8) + | ||
515 | (cmd[7] << 16) + (cmd[6] << 24); | ||
516 | } else if ((*cmd) == WRITE_10) { | ||
517 | lba = cmd[5] + (cmd[4] << 8) + | ||
518 | (cmd[3] << 16) + (cmd[2] << 24); | ||
519 | num = cmd[8] + (cmd[7] << 8); | ||
520 | } else { /* WRITE (6) */ | ||
521 | lba = cmd[3] + (cmd[2] << 8) + | ||
522 | ((cmd[1] & 0x1f) << 16); | ||
523 | num = (0 == cmd[4]) ? 256 : cmd[4]; | ||
524 | } | ||
525 | errsts = resp_write(SCpnt, lba, num, devip); | 521 | errsts = resp_write(SCpnt, lba, num, devip); |
526 | if (inj_recovered && (0 == errsts)) { | 522 | if (inj_recovered && (0 == errsts)) { |
527 | mk_sense_buffer(devip, RECOVERED_ERROR, | 523 | mk_sense_buffer(devip, RECOVERED_ERROR, |
@@ -549,6 +545,28 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | |||
549 | case WRITE_BUFFER: | 545 | case WRITE_BUFFER: |
550 | errsts = check_readiness(SCpnt, 1, devip); | 546 | errsts = check_readiness(SCpnt, 1, devip); |
551 | break; | 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; | ||
552 | default: | 570 | default: |
553 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 571 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
554 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " | 572 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " |
@@ -601,18 +619,18 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
601 | int k, req_len, act_len, len, active; | 619 | int k, req_len, act_len, len, active; |
602 | void * kaddr; | 620 | void * kaddr; |
603 | void * kaddr_off; | 621 | void * kaddr_off; |
604 | struct scatterlist * sg; | 622 | struct scatterlist *sg; |
623 | struct scsi_data_buffer *sdb = scsi_in(scp); | ||
605 | 624 | ||
606 | if (0 == scsi_bufflen(scp)) | 625 | if (!sdb->length) |
607 | return 0; | 626 | return 0; |
608 | if (NULL == scsi_sglist(scp)) | 627 | if (!sdb->table.sgl) |
609 | return (DID_ERROR << 16); | 628 | return (DID_ERROR << 16); |
610 | if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) || | 629 | if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE)) |
611 | (scp->sc_data_direction == DMA_FROM_DEVICE))) | ||
612 | return (DID_ERROR << 16); | 630 | return (DID_ERROR << 16); |
613 | active = 1; | 631 | active = 1; |
614 | req_len = act_len = 0; | 632 | req_len = act_len = 0; |
615 | scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) { | 633 | for_each_sg(sdb->table.sgl, sg, sdb->table.nents, k) { |
616 | if (active) { | 634 | if (active) { |
617 | kaddr = (unsigned char *) | 635 | kaddr = (unsigned char *) |
618 | kmap_atomic(sg_page(sg), KM_USER0); | 636 | kmap_atomic(sg_page(sg), KM_USER0); |
@@ -630,10 +648,10 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
630 | } | 648 | } |
631 | req_len += sg->length; | 649 | req_len += sg->length; |
632 | } | 650 | } |
633 | if (scsi_get_resid(scp)) | 651 | if (sdb->resid) |
634 | scsi_set_resid(scp, scsi_get_resid(scp) - act_len); | 652 | sdb->resid -= act_len; |
635 | else | 653 | else |
636 | scsi_set_resid(scp, req_len - act_len); | 654 | sdb->resid = req_len - act_len; |
637 | return 0; | 655 | return 0; |
638 | } | 656 | } |
639 | 657 | ||
@@ -650,8 +668,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
650 | return 0; | 668 | return 0; |
651 | if (NULL == scsi_sglist(scp)) | 669 | if (NULL == scsi_sglist(scp)) |
652 | return -1; | 670 | return -1; |
653 | if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) || | 671 | if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE)) |
654 | (scp->sc_data_direction == DMA_TO_DEVICE))) | ||
655 | return -1; | 672 | return -1; |
656 | req_len = fin = 0; | 673 | req_len = fin = 0; |
657 | scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) { | 674 | scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) { |
@@ -1956,6 +1973,50 @@ static int resp_report_luns(struct scsi_cmnd * scp, | |||
1956 | min((int)alloc_len, SDEBUG_RLUN_ARR_SZ)); | 1973 | min((int)alloc_len, SDEBUG_RLUN_ARR_SZ)); |
1957 | } | 1974 | } |
1958 | 1975 | ||
1976 | static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, | ||
1977 | unsigned int num, struct sdebug_dev_info *devip) | ||
1978 | { | ||
1979 | int i, j, ret = -1; | ||
1980 | unsigned char *kaddr, *buf; | ||
1981 | unsigned int offset; | ||
1982 | struct scatterlist *sg; | ||
1983 | struct scsi_data_buffer *sdb = scsi_in(scp); | ||
1984 | |||
1985 | /* better not to use temporary buffer. */ | ||
1986 | buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); | ||
1987 | if (!buf) | ||
1988 | return ret; | ||
1989 | |||
1990 | offset = 0; | ||
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 | |||
2001 | offset = 0; | ||
2002 | for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) { | ||
2003 | kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0); | ||
2004 | if (!kaddr) | ||
2005 | goto out; | ||
2006 | |||
2007 | for (j = 0; j < sg->length; j++) | ||
2008 | *(kaddr + sg->offset + j) ^= *(buf + offset + j); | ||
2009 | |||
2010 | offset += sg->length; | ||
2011 | kunmap_atomic(kaddr, KM_USER0); | ||
2012 | } | ||
2013 | ret = 0; | ||
2014 | out: | ||
2015 | kfree(buf); | ||
2016 | |||
2017 | return ret; | ||
2018 | } | ||
2019 | |||
1959 | /* When timer goes off this function is called. */ | 2020 | /* When timer goes off this function is called. */ |
1960 | static void timer_intr_handler(unsigned long indx) | 2021 | static void timer_intr_handler(unsigned long indx) |
1961 | { | 2022 | { |
@@ -1989,6 +2050,7 @@ static int scsi_debug_slave_alloc(struct scsi_device * sdp) | |||
1989 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 2050 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
1990 | printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", | 2051 | printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", |
1991 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | 2052 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
2053 | set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags); | ||
1992 | return 0; | 2054 | return 0; |
1993 | } | 2055 | } |
1994 | 2056 | ||