Commit a9f38e1d authored by Omar Sandoval's avatar Omar Sandoval Committed by Jens Axboe

floppy: convert to blk-mq

This driver likes to fetch requests from all over the place, so make
queue_rq put requests on a list so that the logic stays the same. Tested
with QEMU.
Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>

Converted to blk_mq_init_sq_queue() and fixed a few spots where the
tag_set leaked on cleanup.
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 6ec3938c
...@@ -252,13 +252,13 @@ static int allowed_drive_mask = 0x33; ...@@ -252,13 +252,13 @@ static int allowed_drive_mask = 0x33;
static int irqdma_allocated; static int irqdma_allocated;
#include <linux/blkdev.h> #include <linux/blk-mq.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/cdrom.h> /* for the compatibility eject ioctl */ #include <linux/cdrom.h> /* for the compatibility eject ioctl */
#include <linux/completion.h> #include <linux/completion.h>
static LIST_HEAD(floppy_reqs);
static struct request *current_req; static struct request *current_req;
static void do_fd_request(struct request_queue *q);
static int set_next_request(void); static int set_next_request(void);
#ifndef fd_get_dma_residue #ifndef fd_get_dma_residue
...@@ -414,10 +414,10 @@ static struct floppy_drive_struct drive_state[N_DRIVE]; ...@@ -414,10 +414,10 @@ static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE];
static struct gendisk *disks[N_DRIVE]; static struct gendisk *disks[N_DRIVE];
static struct blk_mq_tag_set tag_sets[N_DRIVE];
static struct block_device *opened_bdev[N_DRIVE]; static struct block_device *opened_bdev[N_DRIVE];
static DEFINE_MUTEX(open_lock); static DEFINE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
static int fdc_queue;
/* /*
* This struct defines the different floppy types. * This struct defines the different floppy types.
...@@ -2216,8 +2216,9 @@ static void floppy_end_request(struct request *req, blk_status_t error) ...@@ -2216,8 +2216,9 @@ static void floppy_end_request(struct request *req, blk_status_t error)
/* current_count_sectors can be zero if transfer failed */ /* current_count_sectors can be zero if transfer failed */
if (error) if (error)
nr_sectors = blk_rq_cur_sectors(req); nr_sectors = blk_rq_cur_sectors(req);
if (__blk_end_request(req, error, nr_sectors << 9)) if (blk_update_request(req, error, nr_sectors << 9))
return; return;
__blk_mq_end_request(req, error);
/* We're done with the request */ /* We're done with the request */
floppy_off(drive); floppy_off(drive);
...@@ -2797,27 +2798,14 @@ static int make_raw_rw_request(void) ...@@ -2797,27 +2798,14 @@ static int make_raw_rw_request(void)
return 2; return 2;
} }
/*
* Round-robin between our available drives, doing one request from each
*/
static int set_next_request(void) static int set_next_request(void)
{ {
struct request_queue *q; current_req = list_first_entry_or_null(&floppy_reqs, struct request,
int old_pos = fdc_queue; queuelist);
do {
q = disks[fdc_queue]->queue;
if (++fdc_queue == N_DRIVE)
fdc_queue = 0;
if (q) {
current_req = blk_fetch_request(q);
if (current_req) { if (current_req) {
current_req->error_count = 0; current_req->error_count = 0;
break; list_del_init(&current_req->queuelist);
}
} }
} while (fdc_queue != old_pos);
return current_req != NULL; return current_req != NULL;
} }
...@@ -2901,29 +2889,38 @@ static void process_fd_request(void) ...@@ -2901,29 +2889,38 @@ static void process_fd_request(void)
schedule_bh(redo_fd_request); schedule_bh(redo_fd_request);
} }
static void do_fd_request(struct request_queue *q) static blk_status_t floppy_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{ {
blk_mq_start_request(bd->rq);
if (WARN(max_buffer_sectors == 0, if (WARN(max_buffer_sectors == 0,
"VFS: %s called on non-open device\n", __func__)) "VFS: %s called on non-open device\n", __func__))
return; return BLK_STS_IOERR;
if (WARN(atomic_read(&usage_count) == 0, if (WARN(atomic_read(&usage_count) == 0,
"warning: usage count=0, current_req=%p sect=%ld flags=%llx\n", "warning: usage count=0, current_req=%p sect=%ld flags=%llx\n",
current_req, (long)blk_rq_pos(current_req), current_req, (long)blk_rq_pos(current_req),
(unsigned long long) current_req->cmd_flags)) (unsigned long long) current_req->cmd_flags))
return; return BLK_STS_IOERR;
spin_lock_irq(&floppy_lock);
list_add_tail(&bd->rq->queuelist, &floppy_reqs);
spin_unlock_irq(&floppy_lock);
if (test_and_set_bit(0, &fdc_busy)) { if (test_and_set_bit(0, &fdc_busy)) {
/* fdc busy, this new request will be treated when the /* fdc busy, this new request will be treated when the
current one is done */ current one is done */
is_alive(__func__, "old request running"); is_alive(__func__, "old request running");
return; return BLK_STS_OK;
} }
command_status = FD_COMMAND_NONE; command_status = FD_COMMAND_NONE;
__reschedule_timeout(MAXTIMEOUT, "fd_request"); __reschedule_timeout(MAXTIMEOUT, "fd_request");
set_fdc(0); set_fdc(0);
process_fd_request(); process_fd_request();
is_alive(__func__, ""); is_alive(__func__, "");
return BLK_STS_OK;
} }
static const struct cont_t poll_cont = { static const struct cont_t poll_cont = {
...@@ -4486,6 +4483,10 @@ static struct platform_driver floppy_driver = { ...@@ -4486,6 +4483,10 @@ static struct platform_driver floppy_driver = {
}, },
}; };
static const struct blk_mq_ops floppy_mq_ops = {
.queue_rq = floppy_queue_rq,
};
static struct platform_device floppy_device[N_DRIVE]; static struct platform_device floppy_device[N_DRIVE];
static bool floppy_available(int drive) static bool floppy_available(int drive)
...@@ -4533,9 +4534,12 @@ static int __init do_floppy_init(void) ...@@ -4533,9 +4534,12 @@ static int __init do_floppy_init(void)
goto out_put_disk; goto out_put_disk;
} }
disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock); disks[drive]->queue = blk_mq_init_sq_queue(&tag_sets[drive],
if (!disks[drive]->queue) { &floppy_mq_ops, 2,
err = -ENOMEM; BLK_MQ_F_SHOULD_MERGE);
if (IS_ERR(disks[drive]->queue)) {
err = PTR_ERR(disks[drive]->queue);
disks[drive]->queue = NULL;
goto out_put_disk; goto out_put_disk;
} }
...@@ -4708,6 +4712,7 @@ static int __init do_floppy_init(void) ...@@ -4708,6 +4712,7 @@ static int __init do_floppy_init(void)
del_timer_sync(&motor_off_timer[drive]); del_timer_sync(&motor_off_timer[drive]);
blk_cleanup_queue(disks[drive]->queue); blk_cleanup_queue(disks[drive]->queue);
disks[drive]->queue = NULL; disks[drive]->queue = NULL;
blk_mq_free_tag_set(&tag_sets[drive]);
} }
put_disk(disks[drive]); put_disk(disks[drive]);
} }
...@@ -4935,6 +4940,7 @@ static void __exit floppy_module_exit(void) ...@@ -4935,6 +4940,7 @@ static void __exit floppy_module_exit(void)
platform_device_unregister(&floppy_device[drive]); platform_device_unregister(&floppy_device[drive]);
} }
blk_cleanup_queue(disks[drive]->queue); blk_cleanup_queue(disks[drive]->queue);
blk_mq_free_tag_set(&tag_sets[drive]);
/* /*
* These disks have not called add_disk(). Don't put down * These disks have not called add_disk(). Don't put down
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment