diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-07-16 04:19:24 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-10-16 05:14:18 -0400 |
commit | 852e034de7727f91dd51995c460a04db2955f1b3 (patch) | |
tree | 89d7152009dcec589a2bd2995eef29f8f3263f17 | |
parent | 8726021626780a73e795c9b939e1ee49ac8c9136 (diff) |
scsi_debug: support sg chaining
Signed-off-by: Douglas Gilbert <dougg@torque.net>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | drivers/scsi/scsi_debug.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 4947dfe625a6..72ee4c9cfb1a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/proc_fs.h> | 38 | #include <linux/proc_fs.h> |
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 | 42 | ||
42 | #include <linux/blkdev.h> | 43 | #include <linux/blkdev.h> |
43 | #include "scsi.h" | 44 | #include "scsi.h" |
@@ -600,7 +601,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
600 | int k, req_len, act_len, len, active; | 601 | int k, req_len, act_len, len, active; |
601 | void * kaddr; | 602 | void * kaddr; |
602 | void * kaddr_off; | 603 | void * kaddr_off; |
603 | struct scatterlist * sgpnt; | 604 | struct scatterlist * sg; |
604 | 605 | ||
605 | if (0 == scp->request_bufflen) | 606 | if (0 == scp->request_bufflen) |
606 | return 0; | 607 | return 0; |
@@ -619,16 +620,16 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
619 | scp->resid = req_len - act_len; | 620 | scp->resid = req_len - act_len; |
620 | return 0; | 621 | return 0; |
621 | } | 622 | } |
622 | sgpnt = (struct scatterlist *)scp->request_buffer; | ||
623 | active = 1; | 623 | active = 1; |
624 | for (k = 0, req_len = 0, act_len = 0; k < scp->use_sg; ++k, ++sgpnt) { | 624 | req_len = act_len = 0; |
625 | scsi_for_each_sg(scp, sg, scp->use_sg, k) { | ||
625 | if (active) { | 626 | if (active) { |
626 | kaddr = (unsigned char *) | 627 | kaddr = (unsigned char *) |
627 | kmap_atomic(sgpnt->page, KM_USER0); | 628 | kmap_atomic(sg->page, KM_USER0); |
628 | if (NULL == kaddr) | 629 | if (NULL == kaddr) |
629 | return (DID_ERROR << 16); | 630 | return (DID_ERROR << 16); |
630 | kaddr_off = (unsigned char *)kaddr + sgpnt->offset; | 631 | kaddr_off = (unsigned char *)kaddr + sg->offset; |
631 | len = sgpnt->length; | 632 | len = sg->length; |
632 | if ((req_len + len) > arr_len) { | 633 | if ((req_len + len) > arr_len) { |
633 | active = 0; | 634 | active = 0; |
634 | len = arr_len - req_len; | 635 | len = arr_len - req_len; |
@@ -637,7 +638,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
637 | kunmap_atomic(kaddr, KM_USER0); | 638 | kunmap_atomic(kaddr, KM_USER0); |
638 | act_len += len; | 639 | act_len += len; |
639 | } | 640 | } |
640 | req_len += sgpnt->length; | 641 | req_len += sg->length; |
641 | } | 642 | } |
642 | if (scp->resid) | 643 | if (scp->resid) |
643 | scp->resid -= act_len; | 644 | scp->resid -= act_len; |
@@ -653,7 +654,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
653 | int k, req_len, len, fin; | 654 | int k, req_len, len, fin; |
654 | void * kaddr; | 655 | void * kaddr; |
655 | void * kaddr_off; | 656 | void * kaddr_off; |
656 | struct scatterlist * sgpnt; | 657 | struct scatterlist * sg; |
657 | 658 | ||
658 | if (0 == scp->request_bufflen) | 659 | if (0 == scp->request_bufflen) |
659 | return 0; | 660 | return 0; |
@@ -668,13 +669,14 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
668 | memcpy(arr, scp->request_buffer, len); | 669 | memcpy(arr, scp->request_buffer, len); |
669 | return len; | 670 | return len; |
670 | } | 671 | } |
671 | sgpnt = (struct scatterlist *)scp->request_buffer; | 672 | sg = scsi_sglist(scp); |
672 | for (k = 0, req_len = 0, fin = 0; k < scp->use_sg; ++k, ++sgpnt) { | 673 | req_len = fin = 0; |
673 | kaddr = (unsigned char *)kmap_atomic(sgpnt->page, KM_USER0); | 674 | for (k = 0; k < scp->use_sg; ++k, sg = sg_next(sg)) { |
675 | kaddr = (unsigned char *)kmap_atomic(sg->page, KM_USER0); | ||
674 | if (NULL == kaddr) | 676 | if (NULL == kaddr) |
675 | return -1; | 677 | return -1; |
676 | kaddr_off = (unsigned char *)kaddr + sgpnt->offset; | 678 | kaddr_off = (unsigned char *)kaddr + sg->offset; |
677 | len = sgpnt->length; | 679 | len = sg->length; |
678 | if ((req_len + len) > max_arr_len) { | 680 | if ((req_len + len) > max_arr_len) { |
679 | len = max_arr_len - req_len; | 681 | len = max_arr_len - req_len; |
680 | fin = 1; | 682 | fin = 1; |
@@ -683,7 +685,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | |||
683 | kunmap_atomic(kaddr, KM_USER0); | 685 | kunmap_atomic(kaddr, KM_USER0); |
684 | if (fin) | 686 | if (fin) |
685 | return req_len + len; | 687 | return req_len + len; |
686 | req_len += sgpnt->length; | 688 | req_len += sg->length; |
687 | } | 689 | } |
688 | return req_len; | 690 | return req_len; |
689 | } | 691 | } |