diff options
Diffstat (limited to 'drivers/block/pktcdvd.c')
| -rw-r--r-- | drivers/block/pktcdvd.c | 97 |
1 files changed, 25 insertions, 72 deletions
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 68b5957f107c..b72935b8f203 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
| @@ -569,6 +569,7 @@ static struct packet_data *pkt_alloc_packet_data(int frames) | |||
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | spin_lock_init(&pkt->lock); | 571 | spin_lock_init(&pkt->lock); |
| 572 | bio_list_init(&pkt->orig_bios); | ||
| 572 | 573 | ||
| 573 | for (i = 0; i < frames; i++) { | 574 | for (i = 0; i < frames; i++) { |
| 574 | struct bio *bio = pkt_bio_alloc(1); | 575 | struct bio *bio = pkt_bio_alloc(1); |
| @@ -721,43 +722,6 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod | |||
| 721 | } | 722 | } |
| 722 | 723 | ||
| 723 | /* | 724 | /* |
| 724 | * Add a bio to a single linked list defined by its head and tail pointers. | ||
| 725 | */ | ||
| 726 | static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) | ||
| 727 | { | ||
| 728 | bio->bi_next = NULL; | ||
| 729 | if (*list_tail) { | ||
| 730 | BUG_ON((*list_head) == NULL); | ||
| 731 | (*list_tail)->bi_next = bio; | ||
| 732 | (*list_tail) = bio; | ||
| 733 | } else { | ||
| 734 | BUG_ON((*list_head) != NULL); | ||
| 735 | (*list_head) = bio; | ||
| 736 | (*list_tail) = bio; | ||
| 737 | } | ||
| 738 | } | ||
| 739 | |||
| 740 | /* | ||
| 741 | * Remove and return the first bio from a single linked list defined by its | ||
| 742 | * head and tail pointers. | ||
| 743 | */ | ||
| 744 | static inline struct bio *pkt_get_list_first(struct bio **list_head, struct bio **list_tail) | ||
| 745 | { | ||
| 746 | struct bio *bio; | ||
| 747 | |||
| 748 | if (*list_head == NULL) | ||
| 749 | return NULL; | ||
| 750 | |||
| 751 | bio = *list_head; | ||
| 752 | *list_head = bio->bi_next; | ||
| 753 | if (*list_head == NULL) | ||
| 754 | *list_tail = NULL; | ||
| 755 | |||
| 756 | bio->bi_next = NULL; | ||
| 757 | return bio; | ||
| 758 | } | ||
| 759 | |||
| 760 | /* | ||
| 761 | * Send a packet_command to the underlying block device and | 725 | * Send a packet_command to the underlying block device and |
| 762 | * wait for completion. | 726 | * wait for completion. |
| 763 | */ | 727 | */ |
| @@ -876,13 +840,10 @@ static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd, | |||
| 876 | static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio) | 840 | static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio) |
| 877 | { | 841 | { |
| 878 | spin_lock(&pd->iosched.lock); | 842 | spin_lock(&pd->iosched.lock); |
| 879 | if (bio_data_dir(bio) == READ) { | 843 | if (bio_data_dir(bio) == READ) |
| 880 | pkt_add_list_last(bio, &pd->iosched.read_queue, | 844 | bio_list_add(&pd->iosched.read_queue, bio); |
| 881 | &pd->iosched.read_queue_tail); | 845 | else |
| 882 | } else { | 846 | bio_list_add(&pd->iosched.write_queue, bio); |
| 883 | pkt_add_list_last(bio, &pd->iosched.write_queue, | ||
| 884 | &pd->iosched.write_queue_tail); | ||
| 885 | } | ||
| 886 | spin_unlock(&pd->iosched.lock); | 847 | spin_unlock(&pd->iosched.lock); |
| 887 | 848 | ||
| 888 | atomic_set(&pd->iosched.attention, 1); | 849 | atomic_set(&pd->iosched.attention, 1); |
| @@ -917,8 +878,8 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | |||
| 917 | int reads_queued, writes_queued; | 878 | int reads_queued, writes_queued; |
| 918 | 879 | ||
| 919 | spin_lock(&pd->iosched.lock); | 880 | spin_lock(&pd->iosched.lock); |
| 920 | reads_queued = (pd->iosched.read_queue != NULL); | 881 | reads_queued = !bio_list_empty(&pd->iosched.read_queue); |
| 921 | writes_queued = (pd->iosched.write_queue != NULL); | 882 | writes_queued = !bio_list_empty(&pd->iosched.write_queue); |
| 922 | spin_unlock(&pd->iosched.lock); | 883 | spin_unlock(&pd->iosched.lock); |
| 923 | 884 | ||
| 924 | if (!reads_queued && !writes_queued) | 885 | if (!reads_queued && !writes_queued) |
| @@ -927,7 +888,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | |||
| 927 | if (pd->iosched.writing) { | 888 | if (pd->iosched.writing) { |
| 928 | int need_write_seek = 1; | 889 | int need_write_seek = 1; |
| 929 | spin_lock(&pd->iosched.lock); | 890 | spin_lock(&pd->iosched.lock); |
| 930 | bio = pd->iosched.write_queue; | 891 | bio = bio_list_peek(&pd->iosched.write_queue); |
| 931 | spin_unlock(&pd->iosched.lock); | 892 | spin_unlock(&pd->iosched.lock); |
| 932 | if (bio && (bio->bi_sector == pd->iosched.last_write)) | 893 | if (bio && (bio->bi_sector == pd->iosched.last_write)) |
| 933 | need_write_seek = 0; | 894 | need_write_seek = 0; |
| @@ -950,13 +911,10 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | |||
| 950 | } | 911 | } |
| 951 | 912 | ||
| 952 | spin_lock(&pd->iosched.lock); | 913 | spin_lock(&pd->iosched.lock); |
| 953 | if (pd->iosched.writing) { | 914 | if (pd->iosched.writing) |
| 954 | bio = pkt_get_list_first(&pd->iosched.write_queue, | 915 | bio = bio_list_pop(&pd->iosched.write_queue); |
| 955 | &pd->iosched.write_queue_tail); | 916 | else |
| 956 | } else { | 917 | bio = bio_list_pop(&pd->iosched.read_queue); |
| 957 | bio = pkt_get_list_first(&pd->iosched.read_queue, | ||
| 958 | &pd->iosched.read_queue_tail); | ||
| 959 | } | ||
| 960 | spin_unlock(&pd->iosched.lock); | 918 | spin_unlock(&pd->iosched.lock); |
| 961 | 919 | ||
| 962 | if (!bio) | 920 | if (!bio) |
| @@ -992,14 +950,14 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | |||
| 992 | static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q) | 950 | static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q) |
| 993 | { | 951 | { |
| 994 | if ((pd->settings.size << 9) / CD_FRAMESIZE | 952 | if ((pd->settings.size << 9) / CD_FRAMESIZE |
| 995 | <= queue_max_phys_segments(q)) { | 953 | <= queue_max_segments(q)) { |
| 996 | /* | 954 | /* |
| 997 | * The cdrom device can handle one segment/frame | 955 | * The cdrom device can handle one segment/frame |
| 998 | */ | 956 | */ |
| 999 | clear_bit(PACKET_MERGE_SEGS, &pd->flags); | 957 | clear_bit(PACKET_MERGE_SEGS, &pd->flags); |
| 1000 | return 0; | 958 | return 0; |
| 1001 | } else if ((pd->settings.size << 9) / PAGE_SIZE | 959 | } else if ((pd->settings.size << 9) / PAGE_SIZE |
| 1002 | <= queue_max_phys_segments(q)) { | 960 | <= queue_max_segments(q)) { |
| 1003 | /* | 961 | /* |
| 1004 | * We can handle this case at the expense of some extra memory | 962 | * We can handle this case at the expense of some extra memory |
| 1005 | * copies during write operations | 963 | * copies during write operations |
| @@ -1114,7 +1072,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
| 1114 | int f; | 1072 | int f; |
| 1115 | char written[PACKET_MAX_SIZE]; | 1073 | char written[PACKET_MAX_SIZE]; |
| 1116 | 1074 | ||
| 1117 | BUG_ON(!pkt->orig_bios); | 1075 | BUG_ON(bio_list_empty(&pkt->orig_bios)); |
| 1118 | 1076 | ||
| 1119 | atomic_set(&pkt->io_wait, 0); | 1077 | atomic_set(&pkt->io_wait, 0); |
| 1120 | atomic_set(&pkt->io_errors, 0); | 1078 | atomic_set(&pkt->io_errors, 0); |
| @@ -1124,7 +1082,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
| 1124 | */ | 1082 | */ |
| 1125 | memset(written, 0, sizeof(written)); | 1083 | memset(written, 0, sizeof(written)); |
| 1126 | spin_lock(&pkt->lock); | 1084 | spin_lock(&pkt->lock); |
| 1127 | for (bio = pkt->orig_bios; bio; bio = bio->bi_next) { | 1085 | bio_list_for_each(bio, &pkt->orig_bios) { |
| 1128 | int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9); | 1086 | int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9); |
| 1129 | int num_frames = bio->bi_size / CD_FRAMESIZE; | 1087 | int num_frames = bio->bi_size / CD_FRAMESIZE; |
| 1130 | pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9); | 1088 | pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9); |
| @@ -1363,7 +1321,7 @@ try_next_bio: | |||
| 1363 | break; | 1321 | break; |
| 1364 | pkt_rbtree_erase(pd, node); | 1322 | pkt_rbtree_erase(pd, node); |
| 1365 | spin_lock(&pkt->lock); | 1323 | spin_lock(&pkt->lock); |
| 1366 | pkt_add_list_last(bio, &pkt->orig_bios, &pkt->orig_bios_tail); | 1324 | bio_list_add(&pkt->orig_bios, bio); |
| 1367 | pkt->write_size += bio->bi_size / CD_FRAMESIZE; | 1325 | pkt->write_size += bio->bi_size / CD_FRAMESIZE; |
| 1368 | spin_unlock(&pkt->lock); | 1326 | spin_unlock(&pkt->lock); |
| 1369 | } | 1327 | } |
| @@ -1409,7 +1367,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
| 1409 | */ | 1367 | */ |
| 1410 | frames_write = 0; | 1368 | frames_write = 0; |
| 1411 | spin_lock(&pkt->lock); | 1369 | spin_lock(&pkt->lock); |
| 1412 | for (bio = pkt->orig_bios; bio; bio = bio->bi_next) { | 1370 | bio_list_for_each(bio, &pkt->orig_bios) { |
| 1413 | int segment = bio->bi_idx; | 1371 | int segment = bio->bi_idx; |
| 1414 | int src_offs = 0; | 1372 | int src_offs = 0; |
| 1415 | int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9); | 1373 | int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9); |
| @@ -1472,20 +1430,14 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
| 1472 | 1430 | ||
| 1473 | static void pkt_finish_packet(struct packet_data *pkt, int uptodate) | 1431 | static void pkt_finish_packet(struct packet_data *pkt, int uptodate) |
| 1474 | { | 1432 | { |
| 1475 | struct bio *bio, *next; | 1433 | struct bio *bio; |
| 1476 | 1434 | ||
| 1477 | if (!uptodate) | 1435 | if (!uptodate) |
| 1478 | pkt->cache_valid = 0; | 1436 | pkt->cache_valid = 0; |
| 1479 | 1437 | ||
| 1480 | /* Finish all bios corresponding to this packet */ | 1438 | /* Finish all bios corresponding to this packet */ |
| 1481 | bio = pkt->orig_bios; | 1439 | while ((bio = bio_list_pop(&pkt->orig_bios))) |
| 1482 | while (bio) { | ||
| 1483 | next = bio->bi_next; | ||
| 1484 | bio->bi_next = NULL; | ||
| 1485 | bio_endio(bio, uptodate ? 0 : -EIO); | 1440 | bio_endio(bio, uptodate ? 0 : -EIO); |
| 1486 | bio = next; | ||
| 1487 | } | ||
| 1488 | pkt->orig_bios = pkt->orig_bios_tail = NULL; | ||
| 1489 | } | 1441 | } |
| 1490 | 1442 | ||
| 1491 | static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt) | 1443 | static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt) |
| @@ -2360,7 +2312,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write) | |||
| 2360 | * even if the size is a multiple of the packet size. | 2312 | * even if the size is a multiple of the packet size. |
| 2361 | */ | 2313 | */ |
| 2362 | spin_lock_irq(q->queue_lock); | 2314 | spin_lock_irq(q->queue_lock); |
| 2363 | blk_queue_max_sectors(q, pd->settings.size); | 2315 | blk_queue_max_hw_sectors(q, pd->settings.size); |
| 2364 | spin_unlock_irq(q->queue_lock); | 2316 | spin_unlock_irq(q->queue_lock); |
| 2365 | set_bit(PACKET_WRITABLE, &pd->flags); | 2317 | set_bit(PACKET_WRITABLE, &pd->flags); |
| 2366 | } else { | 2318 | } else { |
| @@ -2567,8 +2519,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) | |||
| 2567 | spin_lock(&pkt->lock); | 2519 | spin_lock(&pkt->lock); |
| 2568 | if ((pkt->state == PACKET_WAITING_STATE) || | 2520 | if ((pkt->state == PACKET_WAITING_STATE) || |
| 2569 | (pkt->state == PACKET_READ_WAIT_STATE)) { | 2521 | (pkt->state == PACKET_READ_WAIT_STATE)) { |
| 2570 | pkt_add_list_last(bio, &pkt->orig_bios, | 2522 | bio_list_add(&pkt->orig_bios, bio); |
| 2571 | &pkt->orig_bios_tail); | ||
| 2572 | pkt->write_size += bio->bi_size / CD_FRAMESIZE; | 2523 | pkt->write_size += bio->bi_size / CD_FRAMESIZE; |
| 2573 | if ((pkt->write_size >= pkt->frames) && | 2524 | if ((pkt->write_size >= pkt->frames) && |
| 2574 | (pkt->state == PACKET_WAITING_STATE)) { | 2525 | (pkt->state == PACKET_WAITING_STATE)) { |
| @@ -2662,7 +2613,7 @@ static void pkt_init_queue(struct pktcdvd_device *pd) | |||
| 2662 | 2613 | ||
| 2663 | blk_queue_make_request(q, pkt_make_request); | 2614 | blk_queue_make_request(q, pkt_make_request); |
| 2664 | blk_queue_logical_block_size(q, CD_FRAMESIZE); | 2615 | blk_queue_logical_block_size(q, CD_FRAMESIZE); |
| 2665 | blk_queue_max_sectors(q, PACKET_MAX_SECTORS); | 2616 | blk_queue_max_hw_sectors(q, PACKET_MAX_SECTORS); |
| 2666 | blk_queue_merge_bvec(q, pkt_merge_bvec); | 2617 | blk_queue_merge_bvec(q, pkt_merge_bvec); |
| 2667 | q->queuedata = pd; | 2618 | q->queuedata = pd; |
| 2668 | } | 2619 | } |
| @@ -2898,6 +2849,8 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) | |||
| 2898 | 2849 | ||
| 2899 | spin_lock_init(&pd->lock); | 2850 | spin_lock_init(&pd->lock); |
| 2900 | spin_lock_init(&pd->iosched.lock); | 2851 | spin_lock_init(&pd->iosched.lock); |
| 2852 | bio_list_init(&pd->iosched.read_queue); | ||
| 2853 | bio_list_init(&pd->iosched.write_queue); | ||
| 2901 | sprintf(pd->name, DRIVER_NAME"%d", idx); | 2854 | sprintf(pd->name, DRIVER_NAME"%d", idx); |
| 2902 | init_waitqueue_head(&pd->wqueue); | 2855 | init_waitqueue_head(&pd->wqueue); |
| 2903 | pd->bio_queue = RB_ROOT; | 2856 | pd->bio_queue = RB_ROOT; |
