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

amiflop: convert to blk-mq



Straightforward conversion, just use the existing amiflop_lock to
serialize access to the controller. Compile-tested only.

Cc: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>

Converted to blk_mq_init_sq_queue()

Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 53d0f8db
Loading
Loading
Loading
Loading
+35 −78
Original line number Diff line number Diff line
@@ -201,6 +201,7 @@ struct amiga_floppy_struct {
	int dirty;			/* true when trackbuf is not on disk */
	int status;			/* current error code for unit */
	struct gendisk *gendisk;
	struct blk_mq_tag_set tag_set;
};

/*
@@ -281,7 +282,6 @@ static volatile int selected = -1; /* currently selected drive */
static int writepending;
static int writefromint;
static char *raw_buf;
static int fdc_queue;

static DEFINE_SPINLOCK(amiflop_lock);

@@ -1454,76 +1454,20 @@ static int get_track(int drive, int track)
	return -1;
}

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

	/* Find next queue we can dispatch from */
	fdc_queue = fdc_queue + 1;
	if (fdc_queue == FD_MAX_UNITS)
		fdc_queue = 0;

	for(cnt = FD_MAX_UNITS; cnt > 0; cnt--) {

		if (unit[fdc_queue].type->code == FD_NODRIVE) {
			if (++fdc_queue == FD_MAX_UNITS)
				fdc_queue = 0;
			continue;
		}

		q = unit[fdc_queue].gendisk->queue;
		if (q) {
			rq = blk_fetch_request(q);
			if (rq)
				break;
		}

		if (++fdc_queue == FD_MAX_UNITS)
			fdc_queue = 0;
	}

	return rq;
}

static void redo_fd_request(void)
static blk_status_t amiflop_rw_cur_segment(struct amiga_floppy_struct *floppy,
					   struct request *rq)
{
	struct request *rq;
	int drive = floppy - unit;
	unsigned int cnt, block, track, sector;
	int drive;
	struct amiga_floppy_struct *floppy;
	char *data;
	unsigned long flags;
	blk_status_t err;

next_req:
	rq = set_next_request();
	if (!rq) {
		/* Nothing left to do */
		return;
	}

	floppy = rq->rq_disk->private_data;
	drive = floppy - unit;

next_segment:
	/* Here someone could investigate to be more efficient */
	for (cnt = 0, err = BLK_STS_OK; cnt < blk_rq_cur_sectors(rq); cnt++) {
	for (cnt = 0; cnt < blk_rq_cur_sectors(rq); cnt++) {
#ifdef DEBUG
		printk("fd: sector %ld + %d requested for %s\n",
		       blk_rq_pos(rq), cnt,
		       (rq_data_dir(rq) == READ) ? "read" : "write");
#endif
		block = blk_rq_pos(rq) + cnt;
		if ((int)block > floppy->blocks) {
			err = BLK_STS_IOERR;
			break;
		}

		track = block / (floppy->dtype->sects * floppy->type->sect_mult);
		sector = block % (floppy->dtype->sects * floppy->type->sect_mult);
		data = bio_data(rq->bio) + 512 * cnt;
@@ -1532,10 +1476,8 @@ next_segment:
		       "0x%08lx\n", track, sector, data);
#endif

		if (get_track(drive, track) == -1) {
			err = BLK_STS_IOERR;
			break;
		}
		if (get_track(drive, track) == -1)
			return BLK_STS_IOERR;

		if (rq_data_dir(rq) == READ) {
			memcpy(data, floppy->trackbuf + sector * 512, 512);
@@ -1543,31 +1485,40 @@ next_segment:
			memcpy(floppy->trackbuf + sector * 512, data, 512);

			/* keep the drive spinning while writes are scheduled */
			if (!fd_motor_on(drive)) {
				err = BLK_STS_IOERR;
				break;
			}
			if (!fd_motor_on(drive))
				return BLK_STS_IOERR;
			/*
			 * setup a callback to write the track buffer
			 * after a short (1 tick) delay.
			 */
			local_irq_save(flags);

			floppy->dirty = 1;
		        /* reset the timer */
			mod_timer (flush_track_timer + drive, jiffies + 1);
			local_irq_restore(flags);
		}
	}

	if (__blk_end_request_cur(rq, err))
		goto next_segment;
	goto next_req;
	return BLK_STS_OK;
}

static void do_fd_request(struct request_queue * q)
static blk_status_t amiflop_queue_rq(struct blk_mq_hw_ctx *hctx,
				     const struct blk_mq_queue_data *bd)
{
	redo_fd_request();
	struct request *rq = bd->rq;
	struct amiga_floppy_struct *floppy = rq->rq_disk->private_data;
	blk_status_t err;

	if (!spin_trylock_irq(&amiflop_lock))
		return BLK_STS_DEV_RESOURCE;

	blk_mq_start_request(rq);

	do {
		err = amiflop_rw_cur_segment(floppy, rq);
	} while (blk_update_request(rq, err, blk_rq_cur_bytes(rq)));
	blk_mq_end_request(rq, err);

	spin_unlock_irq(&amiflop_lock);
	return BLK_STS_OK;
}

static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
@@ -1818,6 +1769,10 @@ static const struct block_device_operations floppy_fops = {
	.check_events	= amiga_check_events,
};

static const struct blk_mq_ops amiflop_mq_ops = {
	.queue_rq = amiflop_queue_rq,
};

static struct gendisk *fd_alloc_disk(int drive)
{
	struct gendisk *disk;
@@ -1826,7 +1781,8 @@ static struct gendisk *fd_alloc_disk(int drive)
	if (!disk)
		goto out;

	disk->queue = blk_init_queue(do_fd_request, &amiflop_lock);
	disk->queue = blk_mq_init_sq_queue(&unit[drive].tag_set, &amiflop_mq_ops,
						2, BLK_MQ_F_SHOULD_MERGE);
	if (IS_ERR(disk->queue)) {
		disk->queue = NULL;
		goto out_put_disk;
@@ -1841,6 +1797,7 @@ static struct gendisk *fd_alloc_disk(int drive)
out_cleanup_queue:
	blk_cleanup_queue(disk->queue);
	disk->queue = NULL;
	blk_mq_free_tag_set(&unit[drive].tag_set);
out_put_disk:
	put_disk(disk);
out: