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

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
Loading
Loading
Loading
Loading
+36 −30
Original line number Diff line number Diff line
@@ -252,13 +252,13 @@ static int allowed_drive_mask = 0x33;

static int irqdma_allocated;

#include <linux/blkdev.h>
#include <linux/blk-mq.h>
#include <linux/blkpg.h>
#include <linux/cdrom.h>	/* for the compatibility eject ioctl */
#include <linux/completion.h>

static LIST_HEAD(floppy_reqs);
static struct request *current_req;
static void do_fd_request(struct request_queue *q);
static int set_next_request(void);

#ifndef fd_get_dma_residue
@@ -414,10 +414,10 @@ static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[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 DEFINE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
static int fdc_queue;

/*
 * This struct defines the different floppy types.
@@ -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 */
	if (error)
		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;
	__blk_mq_end_request(req, error);

	/* We're done with the request */
	floppy_off(drive);
@@ -2797,27 +2798,14 @@ static int make_raw_rw_request(void)
	return 2;
}

/*
 * Round-robin between our available drives, doing one request from each
 */
static int set_next_request(void)
{
	struct request_queue *q;
	int old_pos = fdc_queue;

	do {
		q = disks[fdc_queue]->queue;
		if (++fdc_queue == N_DRIVE)
			fdc_queue = 0;
		if (q) {
			current_req = blk_fetch_request(q);
	current_req = list_first_entry_or_null(&floppy_reqs, struct request,
					       queuelist);
	if (current_req) {
		current_req->error_count = 0;
				break;
			}
		list_del_init(&current_req->queuelist);
	}
	} while (fdc_queue != old_pos);

	return current_req != NULL;
}

@@ -2901,29 +2889,38 @@ static void process_fd_request(void)
	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,
		 "VFS: %s called on non-open device\n", __func__))
		return;
		return BLK_STS_IOERR;

	if (WARN(atomic_read(&usage_count) == 0,
		 "warning: usage count=0, current_req=%p sect=%ld flags=%llx\n",
		 current_req, (long)blk_rq_pos(current_req),
		 (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)) {
		/* fdc busy, this new request will be treated when the
		   current one is done */
		is_alive(__func__, "old request running");
		return;
		return BLK_STS_OK;
	}

	command_status = FD_COMMAND_NONE;
	__reschedule_timeout(MAXTIMEOUT, "fd_request");
	set_fdc(0);
	process_fd_request();
	is_alive(__func__, "");
	return BLK_STS_OK;
}

static const struct cont_t poll_cont = {
@@ -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 bool floppy_available(int drive)
@@ -4533,9 +4534,12 @@ static int __init do_floppy_init(void)
			goto out_put_disk;
		}

		disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
		if (!disks[drive]->queue) {
			err = -ENOMEM;
		disks[drive]->queue = blk_mq_init_sq_queue(&tag_sets[drive],
							   &floppy_mq_ops, 2,
							   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;
		}

@@ -4708,6 +4712,7 @@ out_put_disk:
			del_timer_sync(&motor_off_timer[drive]);
			blk_cleanup_queue(disks[drive]->queue);
			disks[drive]->queue = NULL;
			blk_mq_free_tag_set(&tag_sets[drive]);
		}
		put_disk(disks[drive]);
	}
@@ -4935,6 +4940,7 @@ static void __exit floppy_module_exit(void)
			platform_device_unregister(&floppy_device[drive]);
		}
		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