diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/ub.c | 185 |
1 files changed, 126 insertions, 59 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index a026567f5d18..fb3d1e9bc407 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
@@ -16,9 +16,10 @@ | |||
16 | * -- verify the 13 conditions and do bulk resets | 16 | * -- verify the 13 conditions and do bulk resets |
17 | * -- kill last_pipe and simply do two-state clearing on both pipes | 17 | * -- kill last_pipe and simply do two-state clearing on both pipes |
18 | * -- verify protocol (bulk) from USB descriptors (maybe...) | 18 | * -- verify protocol (bulk) from USB descriptors (maybe...) |
19 | * -- highmem and sg | 19 | * -- highmem |
20 | * -- move top_sense and work_bcs into separate allocations (if they survive) | 20 | * -- move top_sense and work_bcs into separate allocations (if they survive) |
21 | * for cache purists and esoteric architectures. | 21 | * for cache purists and esoteric architectures. |
22 | * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ? | ||
22 | * -- prune comments, they are too volumnous | 23 | * -- prune comments, they are too volumnous |
23 | * -- Exterminate P3 printks | 24 | * -- Exterminate P3 printks |
24 | * -- Resove XXX's | 25 | * -- Resove XXX's |
@@ -171,7 +172,7 @@ struct bulk_cs_wrap { | |||
171 | */ | 172 | */ |
172 | struct ub_dev; | 173 | struct ub_dev; |
173 | 174 | ||
174 | #define UB_MAX_REQ_SG 1 | 175 | #define UB_MAX_REQ_SG 4 |
175 | #define UB_MAX_SECTORS 64 | 176 | #define UB_MAX_SECTORS 64 |
176 | 177 | ||
177 | /* | 178 | /* |
@@ -240,13 +241,21 @@ struct ub_scsi_cmd { | |||
240 | */ | 241 | */ |
241 | char *data; /* Requested buffer */ | 242 | char *data; /* Requested buffer */ |
242 | unsigned int len; /* Requested length */ | 243 | unsigned int len; /* Requested length */ |
243 | // struct scatterlist sgv[UB_MAX_REQ_SG]; | ||
244 | 244 | ||
245 | struct ub_lun *lun; | 245 | struct ub_lun *lun; |
246 | void (*done)(struct ub_dev *, struct ub_scsi_cmd *); | 246 | void (*done)(struct ub_dev *, struct ub_scsi_cmd *); |
247 | void *back; | 247 | void *back; |
248 | }; | 248 | }; |
249 | 249 | ||
250 | struct ub_request { | ||
251 | struct request *rq; | ||
252 | unsigned char dir; | ||
253 | unsigned int current_block; | ||
254 | unsigned int current_sg; | ||
255 | unsigned int nsg; /* sgv[nsg] */ | ||
256 | struct scatterlist sgv[UB_MAX_REQ_SG]; | ||
257 | }; | ||
258 | |||
250 | /* | 259 | /* |
251 | */ | 260 | */ |
252 | struct ub_capacity { | 261 | struct ub_capacity { |
@@ -342,6 +351,8 @@ struct ub_lun { | |||
342 | int readonly; | 351 | int readonly; |
343 | int first_open; /* Kludge. See ub_bd_open. */ | 352 | int first_open; /* Kludge. See ub_bd_open. */ |
344 | 353 | ||
354 | struct ub_request urq; | ||
355 | |||
345 | /* Use Ingo's mempool if or when we have more than one command. */ | 356 | /* Use Ingo's mempool if or when we have more than one command. */ |
346 | /* | 357 | /* |
347 | * Currently we never need more than one command for the whole device. | 358 | * Currently we never need more than one command for the whole device. |
@@ -389,6 +400,7 @@ struct ub_dev { | |||
389 | struct bulk_cs_wrap work_bcs; | 400 | struct bulk_cs_wrap work_bcs; |
390 | struct usb_ctrlrequest work_cr; | 401 | struct usb_ctrlrequest work_cr; |
391 | 402 | ||
403 | int sg_stat[UB_MAX_REQ_SG+1]; | ||
392 | struct ub_scsi_trace tr; | 404 | struct ub_scsi_trace tr; |
393 | }; | 405 | }; |
394 | 406 | ||
@@ -398,10 +410,14 @@ static void ub_cleanup(struct ub_dev *sc); | |||
398 | static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq); | 410 | static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq); |
399 | static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | 411 | static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, |
400 | struct ub_scsi_cmd *cmd, struct request *rq); | 412 | struct ub_scsi_cmd *cmd, struct request *rq); |
401 | static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, | 413 | static void ub_scsi_build_block(struct ub_lun *lun, |
402 | struct request *rq); | 414 | struct ub_scsi_cmd *cmd, struct ub_request *urq); |
415 | static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, | ||
416 | struct ub_scsi_cmd *cmd, struct request *rq); | ||
403 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 417 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
404 | static void ub_end_rq(struct request *rq, int uptodate); | 418 | static void ub_end_rq(struct request *rq, int uptodate); |
419 | static int ub_request_advance(struct ub_dev *sc, struct ub_lun *lun, | ||
420 | struct ub_request *urq, struct ub_scsi_cmd *cmd); | ||
405 | static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 421 | static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
406 | static void ub_urb_complete(struct urb *urb, struct pt_regs *pt); | 422 | static void ub_urb_complete(struct urb *urb, struct pt_regs *pt); |
407 | static void ub_scsi_action(unsigned long _dev); | 423 | static void ub_scsi_action(unsigned long _dev); |
@@ -523,6 +539,13 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, c | |||
523 | cnt += sprintf(page + cnt, | 539 | cnt += sprintf(page + cnt, |
524 | "qlen %d qmax %d\n", | 540 | "qlen %d qmax %d\n", |
525 | sc->cmd_queue.qlen, sc->cmd_queue.qmax); | 541 | sc->cmd_queue.qlen, sc->cmd_queue.qmax); |
542 | cnt += sprintf(page + cnt, | ||
543 | "sg %d %d %d %d %d\n", | ||
544 | sc->sg_stat[0], | ||
545 | sc->sg_stat[1], | ||
546 | sc->sg_stat[2], | ||
547 | sc->sg_stat[3], | ||
548 | sc->sg_stat[4]); | ||
526 | 549 | ||
527 | list_for_each (p, &sc->luns) { | 550 | list_for_each (p, &sc->luns) { |
528 | lun = list_entry(p, struct ub_lun, link); | 551 | lun = list_entry(p, struct ub_lun, link); |
@@ -769,14 +792,15 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) | |||
769 | return 0; | 792 | return 0; |
770 | } | 793 | } |
771 | 794 | ||
795 | if (lun->urq.rq != NULL) | ||
796 | return -1; | ||
772 | if ((cmd = ub_get_cmd(lun)) == NULL) | 797 | if ((cmd = ub_get_cmd(lun)) == NULL) |
773 | return -1; | 798 | return -1; |
774 | memset(cmd, 0, sizeof(struct ub_scsi_cmd)); | 799 | memset(cmd, 0, sizeof(struct ub_scsi_cmd)); |
775 | 800 | ||
776 | blkdev_dequeue_request(rq); | 801 | blkdev_dequeue_request(rq); |
777 | |||
778 | if (blk_pc_request(rq)) { | 802 | if (blk_pc_request(rq)) { |
779 | rc = ub_cmd_build_packet(sc, cmd, rq); | 803 | rc = ub_cmd_build_packet(sc, lun, cmd, rq); |
780 | } else { | 804 | } else { |
781 | rc = ub_cmd_build_block(sc, lun, cmd, rq); | 805 | rc = ub_cmd_build_block(sc, lun, cmd, rq); |
782 | } | 806 | } |
@@ -788,10 +812,10 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) | |||
788 | cmd->state = UB_CMDST_INIT; | 812 | cmd->state = UB_CMDST_INIT; |
789 | cmd->lun = lun; | 813 | cmd->lun = lun; |
790 | cmd->done = ub_rw_cmd_done; | 814 | cmd->done = ub_rw_cmd_done; |
791 | cmd->back = rq; | 815 | cmd->back = &lun->urq; |
792 | 816 | ||
793 | cmd->tag = sc->tagcnt++; | 817 | cmd->tag = sc->tagcnt++; |
794 | if ((rc = ub_submit_scsi(sc, cmd)) != 0) { | 818 | if (ub_submit_scsi(sc, cmd) != 0) { |
795 | ub_put_cmd(lun, cmd); | 819 | ub_put_cmd(lun, cmd); |
796 | ub_end_rq(rq, 0); | 820 | ub_end_rq(rq, 0); |
797 | return 0; | 821 | return 0; |
@@ -803,12 +827,12 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) | |||
803 | static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | 827 | static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, |
804 | struct ub_scsi_cmd *cmd, struct request *rq) | 828 | struct ub_scsi_cmd *cmd, struct request *rq) |
805 | { | 829 | { |
830 | struct ub_request *urq; | ||
806 | int ub_dir; | 831 | int ub_dir; |
807 | #if 0 /* We use rq->buffer for now */ | ||
808 | struct scatterlist *sg; | ||
809 | int n_elem; | 832 | int n_elem; |
810 | #endif | 833 | |
811 | unsigned int block, nblks; | 834 | urq = &lun->urq; |
835 | memset(urq, 0, sizeof(struct ub_request)); | ||
812 | 836 | ||
813 | if (rq_data_dir(rq) == WRITE) | 837 | if (rq_data_dir(rq) == WRITE) |
814 | ub_dir = UB_DIR_WRITE; | 838 | ub_dir = UB_DIR_WRITE; |
@@ -818,44 +842,19 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | |||
818 | /* | 842 | /* |
819 | * get scatterlist from block layer | 843 | * get scatterlist from block layer |
820 | */ | 844 | */ |
821 | #if 0 /* We use rq->buffer for now */ | 845 | n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]); |
822 | sg = &cmd->sgv[0]; | ||
823 | n_elem = blk_rq_map_sg(q, rq, sg); | ||
824 | if (n_elem <= 0) { | 846 | if (n_elem <= 0) { |
825 | ub_put_cmd(lun, cmd); | 847 | printk(KERN_INFO "%s: failed request map (%d)\n", |
826 | ub_end_rq(rq, 0); | 848 | sc->name, n_elem); /* P3 */ |
827 | blk_start_queue(q); | 849 | return -1; /* request with no s/g entries? */ |
828 | return 0; /* request with no s/g entries? */ | ||
829 | } | 850 | } |
830 | 851 | if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ | |
831 | if (n_elem != 1) { /* Paranoia */ | ||
832 | printk(KERN_WARNING "%s: request with %d segments\n", | 852 | printk(KERN_WARNING "%s: request with %d segments\n", |
833 | sc->name, n_elem); | 853 | sc->name, n_elem); |
834 | ub_put_cmd(lun, cmd); | ||
835 | ub_end_rq(rq, 0); | ||
836 | blk_start_queue(q); | ||
837 | return 0; | ||
838 | } | ||
839 | #endif | ||
840 | |||
841 | /* | ||
842 | * XXX Unfortunately, this check does not work. It is quite possible | ||
843 | * to get bogus non-null rq->buffer if you allow sg by mistake. | ||
844 | */ | ||
845 | if (rq->buffer == NULL) { | ||
846 | /* | ||
847 | * This must not happen if we set the queue right. | ||
848 | * The block level must create bounce buffers for us. | ||
849 | */ | ||
850 | static int do_print = 1; | ||
851 | if (do_print) { | ||
852 | printk(KERN_WARNING "%s: unmapped block request" | ||
853 | " flags 0x%lx sectors %lu\n", | ||
854 | sc->name, rq->flags, rq->nr_sectors); | ||
855 | do_print = 0; | ||
856 | } | ||
857 | return -1; | 854 | return -1; |
858 | } | 855 | } |
856 | urq->nsg = n_elem; | ||
857 | sc->sg_stat[n_elem]++; | ||
859 | 858 | ||
860 | /* | 859 | /* |
861 | * build the command | 860 | * build the command |
@@ -863,10 +862,29 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | |||
863 | * The call to blk_queue_hardsect_size() guarantees that request | 862 | * The call to blk_queue_hardsect_size() guarantees that request |
864 | * is aligned, but it is given in terms of 512 byte units, always. | 863 | * is aligned, but it is given in terms of 512 byte units, always. |
865 | */ | 864 | */ |
866 | block = rq->sector >> lun->capacity.bshift; | 865 | urq->current_block = rq->sector >> lun->capacity.bshift; |
867 | nblks = rq->nr_sectors >> lun->capacity.bshift; | 866 | // nblks = rq->nr_sectors >> lun->capacity.bshift; |
867 | |||
868 | urq->rq = rq; | ||
869 | urq->current_sg = 0; | ||
870 | urq->dir = ub_dir; | ||
871 | |||
872 | ub_scsi_build_block(lun, cmd, urq); | ||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static void ub_scsi_build_block(struct ub_lun *lun, | ||
877 | struct ub_scsi_cmd *cmd, struct ub_request *urq) | ||
878 | { | ||
879 | struct scatterlist *sg; | ||
880 | unsigned int block, nblks; | ||
881 | |||
882 | sg = &urq->sgv[urq->current_sg]; | ||
883 | |||
884 | block = urq->current_block; | ||
885 | nblks = sg->length >> (lun->capacity.bshift + 9); | ||
868 | 886 | ||
869 | cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10; | 887 | cmd->cdb[0] = (urq->dir == UB_DIR_READ)? READ_10: WRITE_10; |
870 | /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */ | 888 | /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */ |
871 | cmd->cdb[2] = block >> 24; | 889 | cmd->cdb[2] = block >> 24; |
872 | cmd->cdb[3] = block >> 16; | 890 | cmd->cdb[3] = block >> 16; |
@@ -876,16 +894,20 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | |||
876 | cmd->cdb[8] = nblks; | 894 | cmd->cdb[8] = nblks; |
877 | cmd->cdb_len = 10; | 895 | cmd->cdb_len = 10; |
878 | 896 | ||
879 | cmd->dir = ub_dir; | 897 | cmd->dir = urq->dir; |
880 | cmd->data = rq->buffer; | 898 | cmd->data = page_address(sg->page) + sg->offset; |
881 | cmd->len = rq->nr_sectors * 512; | 899 | cmd->len = sg->length; |
882 | |||
883 | return 0; | ||
884 | } | 900 | } |
885 | 901 | ||
886 | static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, | 902 | static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, |
887 | struct request *rq) | 903 | struct ub_scsi_cmd *cmd, struct request *rq) |
888 | { | 904 | { |
905 | struct ub_request *urq; | ||
906 | |||
907 | urq = &lun->urq; | ||
908 | memset(urq, 0, sizeof(struct ub_request)); | ||
909 | urq->rq = rq; | ||
910 | sc->sg_stat[0]++; | ||
889 | 911 | ||
890 | if (rq->data_len != 0 && rq->data == NULL) { | 912 | if (rq->data_len != 0 && rq->data == NULL) { |
891 | static int do_print = 1; | 913 | static int do_print = 1; |
@@ -917,12 +939,13 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, | |||
917 | 939 | ||
918 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | 940 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) |
919 | { | 941 | { |
920 | struct request *rq = cmd->back; | ||
921 | struct ub_lun *lun = cmd->lun; | 942 | struct ub_lun *lun = cmd->lun; |
922 | struct gendisk *disk = lun->disk; | 943 | struct ub_request *urq = cmd->back; |
923 | request_queue_t *q = disk->queue; | 944 | struct request *rq; |
924 | int uptodate; | 945 | int uptodate; |
925 | 946 | ||
947 | rq = urq->rq; | ||
948 | |||
926 | if (blk_pc_request(rq)) { | 949 | if (blk_pc_request(rq)) { |
927 | /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ | 950 | /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ |
928 | memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); | 951 | memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); |
@@ -934,9 +957,19 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
934 | else | 957 | else |
935 | uptodate = 0; | 958 | uptodate = 0; |
936 | 959 | ||
960 | if (cmd->error == 0 && urq->current_sg+1 < urq->nsg) { | ||
961 | if (ub_request_advance(sc, lun, urq, cmd) == 0) { | ||
962 | /* Stay on target... */ | ||
963 | return; | ||
964 | } | ||
965 | uptodate = 0; | ||
966 | } | ||
967 | |||
968 | urq->rq = NULL; | ||
969 | |||
937 | ub_put_cmd(lun, cmd); | 970 | ub_put_cmd(lun, cmd); |
938 | ub_end_rq(rq, uptodate); | 971 | ub_end_rq(rq, uptodate); |
939 | blk_start_queue(q); | 972 | blk_start_queue(lun->disk->queue); |
940 | } | 973 | } |
941 | 974 | ||
942 | static void ub_end_rq(struct request *rq, int uptodate) | 975 | static void ub_end_rq(struct request *rq, int uptodate) |
@@ -948,6 +981,40 @@ static void ub_end_rq(struct request *rq, int uptodate) | |||
948 | end_that_request_last(rq); | 981 | end_that_request_last(rq); |
949 | } | 982 | } |
950 | 983 | ||
984 | static int ub_request_advance(struct ub_dev *sc, struct ub_lun *lun, | ||
985 | struct ub_request *urq, struct ub_scsi_cmd *cmd) | ||
986 | { | ||
987 | struct scatterlist *sg; | ||
988 | unsigned int nblks; | ||
989 | |||
990 | /* XXX This is temporary, until we sort out S/G in packet requests. */ | ||
991 | if (blk_pc_request(urq->rq)) { | ||
992 | printk(KERN_WARNING | ||
993 | "2-segment packet request completed\n"); /* P3 */ | ||
994 | return -1; | ||
995 | } | ||
996 | |||
997 | sg = &urq->sgv[urq->current_sg]; | ||
998 | nblks = sg->length >> (lun->capacity.bshift + 9); | ||
999 | urq->current_block += nblks; | ||
1000 | urq->current_sg++; | ||
1001 | sg++; | ||
1002 | |||
1003 | memset(cmd, 0, sizeof(struct ub_scsi_cmd)); | ||
1004 | ub_scsi_build_block(lun, cmd, urq); | ||
1005 | cmd->state = UB_CMDST_INIT; | ||
1006 | cmd->lun = lun; | ||
1007 | cmd->done = ub_rw_cmd_done; | ||
1008 | cmd->back = &lun->urq; | ||
1009 | |||
1010 | cmd->tag = sc->tagcnt++; | ||
1011 | if (ub_submit_scsi(sc, cmd) != 0) { | ||
1012 | return -1; | ||
1013 | } | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
951 | /* | 1018 | /* |
952 | * Submit a regular SCSI operation (not an auto-sense). | 1019 | * Submit a regular SCSI operation (not an auto-sense). |
953 | * | 1020 | * |