diff options
Diffstat (limited to 'drivers/block/floppy.c')
-rw-r--r-- | drivers/block/floppy.c | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index cf04c1b234ed..aa42e7766c6a 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -258,8 +258,8 @@ static int irqdma_allocated; | |||
258 | #include <linux/completion.h> | 258 | #include <linux/completion.h> |
259 | 259 | ||
260 | static struct request *current_req; | 260 | static struct request *current_req; |
261 | static struct request_queue *floppy_queue; | ||
262 | static void do_fd_request(struct request_queue *q); | 261 | static void do_fd_request(struct request_queue *q); |
262 | static int set_next_request(void); | ||
263 | 263 | ||
264 | #ifndef fd_get_dma_residue | 264 | #ifndef fd_get_dma_residue |
265 | #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) | 265 | #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) |
@@ -413,6 +413,7 @@ static struct gendisk *disks[N_DRIVE]; | |||
413 | static struct block_device *opened_bdev[N_DRIVE]; | 413 | static struct block_device *opened_bdev[N_DRIVE]; |
414 | static DEFINE_MUTEX(open_lock); | 414 | static DEFINE_MUTEX(open_lock); |
415 | static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; | 415 | static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; |
416 | static int fdc_queue; | ||
416 | 417 | ||
417 | /* | 418 | /* |
418 | * This struct defines the different floppy types. | 419 | * This struct defines the different floppy types. |
@@ -890,8 +891,8 @@ static void unlock_fdc(void) | |||
890 | del_timer(&fd_timeout); | 891 | del_timer(&fd_timeout); |
891 | cont = NULL; | 892 | cont = NULL; |
892 | clear_bit(0, &fdc_busy); | 893 | clear_bit(0, &fdc_busy); |
893 | if (current_req || blk_peek_request(floppy_queue)) | 894 | if (current_req || set_next_request()) |
894 | do_fd_request(floppy_queue); | 895 | do_fd_request(current_req->q); |
895 | spin_unlock_irqrestore(&floppy_lock, flags); | 896 | spin_unlock_irqrestore(&floppy_lock, flags); |
896 | wake_up(&fdc_wait); | 897 | wake_up(&fdc_wait); |
897 | } | 898 | } |
@@ -2243,8 +2244,8 @@ static void floppy_end_request(struct request *req, int error) | |||
2243 | * logical buffer */ | 2244 | * logical buffer */ |
2244 | static void request_done(int uptodate) | 2245 | static void request_done(int uptodate) |
2245 | { | 2246 | { |
2246 | struct request_queue *q = floppy_queue; | ||
2247 | struct request *req = current_req; | 2247 | struct request *req = current_req; |
2248 | struct request_queue *q; | ||
2248 | unsigned long flags; | 2249 | unsigned long flags; |
2249 | int block; | 2250 | int block; |
2250 | char msg[sizeof("request done ") + sizeof(int) * 3]; | 2251 | char msg[sizeof("request done ") + sizeof(int) * 3]; |
@@ -2258,6 +2259,8 @@ static void request_done(int uptodate) | |||
2258 | return; | 2259 | return; |
2259 | } | 2260 | } |
2260 | 2261 | ||
2262 | q = req->q; | ||
2263 | |||
2261 | if (uptodate) { | 2264 | if (uptodate) { |
2262 | /* maintain values for invalidation on geometry | 2265 | /* maintain values for invalidation on geometry |
2263 | * change */ | 2266 | * change */ |
@@ -2811,6 +2814,28 @@ static int make_raw_rw_request(void) | |||
2811 | return 2; | 2814 | return 2; |
2812 | } | 2815 | } |
2813 | 2816 | ||
2817 | /* | ||
2818 | * Round-robin between our available drives, doing one request from each | ||
2819 | */ | ||
2820 | static int set_next_request(void) | ||
2821 | { | ||
2822 | struct request_queue *q; | ||
2823 | int old_pos = fdc_queue; | ||
2824 | |||
2825 | do { | ||
2826 | q = disks[fdc_queue]->queue; | ||
2827 | if (++fdc_queue == N_DRIVE) | ||
2828 | fdc_queue = 0; | ||
2829 | if (q) { | ||
2830 | current_req = blk_fetch_request(q); | ||
2831 | if (current_req) | ||
2832 | break; | ||
2833 | } | ||
2834 | } while (fdc_queue != old_pos); | ||
2835 | |||
2836 | return current_req != NULL; | ||
2837 | } | ||
2838 | |||
2814 | static void redo_fd_request(void) | 2839 | static void redo_fd_request(void) |
2815 | { | 2840 | { |
2816 | int drive; | 2841 | int drive; |
@@ -2822,17 +2847,17 @@ static void redo_fd_request(void) | |||
2822 | 2847 | ||
2823 | do_request: | 2848 | do_request: |
2824 | if (!current_req) { | 2849 | if (!current_req) { |
2825 | struct request *req; | 2850 | int pending; |
2851 | |||
2852 | spin_lock_irq(&floppy_lock); | ||
2853 | pending = set_next_request(); | ||
2854 | spin_unlock_irq(&floppy_lock); | ||
2826 | 2855 | ||
2827 | spin_lock_irq(floppy_queue->queue_lock); | 2856 | if (!pending) { |
2828 | req = blk_fetch_request(floppy_queue); | ||
2829 | spin_unlock_irq(floppy_queue->queue_lock); | ||
2830 | if (!req) { | ||
2831 | do_floppy = NULL; | 2857 | do_floppy = NULL; |
2832 | unlock_fdc(); | 2858 | unlock_fdc(); |
2833 | return; | 2859 | return; |
2834 | } | 2860 | } |
2835 | current_req = req; | ||
2836 | } | 2861 | } |
2837 | drive = (long)current_req->rq_disk->private_data; | 2862 | drive = (long)current_req->rq_disk->private_data; |
2838 | set_fdc(drive); | 2863 | set_fdc(drive); |
@@ -4165,6 +4190,13 @@ static int __init floppy_init(void) | |||
4165 | goto out_put_disk; | 4190 | goto out_put_disk; |
4166 | } | 4191 | } |
4167 | 4192 | ||
4193 | disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); | ||
4194 | if (!disks[dr]->queue) { | ||
4195 | err = -ENOMEM; | ||
4196 | goto out_put_disk; | ||
4197 | } | ||
4198 | |||
4199 | blk_queue_max_hw_sectors(disks[dr]->queue, 64); | ||
4168 | disks[dr]->major = FLOPPY_MAJOR; | 4200 | disks[dr]->major = FLOPPY_MAJOR; |
4169 | disks[dr]->first_minor = TOMINOR(dr); | 4201 | disks[dr]->first_minor = TOMINOR(dr); |
4170 | disks[dr]->fops = &floppy_fops; | 4202 | disks[dr]->fops = &floppy_fops; |
@@ -4183,13 +4215,6 @@ static int __init floppy_init(void) | |||
4183 | if (err) | 4215 | if (err) |
4184 | goto out_unreg_blkdev; | 4216 | goto out_unreg_blkdev; |
4185 | 4217 | ||
4186 | floppy_queue = blk_init_queue(do_fd_request, &floppy_lock); | ||
4187 | if (!floppy_queue) { | ||
4188 | err = -ENOMEM; | ||
4189 | goto out_unreg_driver; | ||
4190 | } | ||
4191 | blk_queue_max_hw_sectors(floppy_queue, 64); | ||
4192 | |||
4193 | blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, | 4218 | blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, |
4194 | floppy_find, NULL, NULL); | 4219 | floppy_find, NULL, NULL); |
4195 | 4220 | ||
@@ -4317,7 +4342,6 @@ static int __init floppy_init(void) | |||
4317 | 4342 | ||
4318 | /* to be cleaned up... */ | 4343 | /* to be cleaned up... */ |
4319 | disks[drive]->private_data = (void *)(long)drive; | 4344 | disks[drive]->private_data = (void *)(long)drive; |
4320 | disks[drive]->queue = floppy_queue; | ||
4321 | disks[drive]->flags |= GENHD_FL_REMOVABLE; | 4345 | disks[drive]->flags |= GENHD_FL_REMOVABLE; |
4322 | disks[drive]->driverfs_dev = &floppy_device[drive].dev; | 4346 | disks[drive]->driverfs_dev = &floppy_device[drive].dev; |
4323 | add_disk(disks[drive]); | 4347 | add_disk(disks[drive]); |
@@ -4333,8 +4357,6 @@ out_flush_work: | |||
4333 | floppy_release_irq_and_dma(); | 4357 | floppy_release_irq_and_dma(); |
4334 | out_unreg_region: | 4358 | out_unreg_region: |
4335 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); | 4359 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); |
4336 | blk_cleanup_queue(floppy_queue); | ||
4337 | out_unreg_driver: | ||
4338 | platform_driver_unregister(&floppy_driver); | 4360 | platform_driver_unregister(&floppy_driver); |
4339 | out_unreg_blkdev: | 4361 | out_unreg_blkdev: |
4340 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 4362 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
@@ -4342,6 +4364,8 @@ out_put_disk: | |||
4342 | while (dr--) { | 4364 | while (dr--) { |
4343 | del_timer(&motor_off_timer[dr]); | 4365 | del_timer(&motor_off_timer[dr]); |
4344 | put_disk(disks[dr]); | 4366 | put_disk(disks[dr]); |
4367 | if (disks[dr]->queue) | ||
4368 | blk_cleanup_queue(disks[dr]->queue); | ||
4345 | } | 4369 | } |
4346 | return err; | 4370 | return err; |
4347 | } | 4371 | } |
@@ -4550,11 +4574,11 @@ static void __exit floppy_module_exit(void) | |||
4550 | platform_device_unregister(&floppy_device[drive]); | 4574 | platform_device_unregister(&floppy_device[drive]); |
4551 | } | 4575 | } |
4552 | put_disk(disks[drive]); | 4576 | put_disk(disks[drive]); |
4577 | blk_cleanup_queue(disks[drive]->queue); | ||
4553 | } | 4578 | } |
4554 | 4579 | ||
4555 | del_timer_sync(&fd_timeout); | 4580 | del_timer_sync(&fd_timeout); |
4556 | del_timer_sync(&fd_timer); | 4581 | del_timer_sync(&fd_timer); |
4557 | blk_cleanup_queue(floppy_queue); | ||
4558 | 4582 | ||
4559 | if (atomic_read(&usage_count)) | 4583 | if (atomic_read(&usage_count)) |
4560 | floppy_release_irq_and_dma(); | 4584 | floppy_release_irq_and_dma(); |