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: Omar Sandoval <osandov@fb.com>

Converted to blk_mq_init_sq_queue()

Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Omar Sandoval 2018-10-15 09:16:37 -06:00 committed by Jens Axboe
parent 53d0f8dbde
commit 21b07f3554
1 changed files with 35 additions and 78 deletions

View File

@ -201,6 +201,7 @@ struct amiga_floppy_struct {
int dirty; /* true when trackbuf is not on disk */ int dirty; /* true when trackbuf is not on disk */
int status; /* current error code for unit */ int status; /* current error code for unit */
struct gendisk *gendisk; 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 writepending;
static int writefromint; static int writefromint;
static char *raw_buf; static char *raw_buf;
static int fdc_queue;
static DEFINE_SPINLOCK(amiflop_lock); static DEFINE_SPINLOCK(amiflop_lock);
@ -1454,76 +1454,20 @@ static int get_track(int drive, int track)
return -1; return -1;
} }
/* static blk_status_t amiflop_rw_cur_segment(struct amiga_floppy_struct *floppy,
* Round-robin between our available drives, doing one request from each struct request *rq)
*/
static struct request *set_next_request(void)
{ {
struct request_queue *q; int drive = floppy - unit;
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)
{
struct request *rq;
unsigned int cnt, block, track, sector; unsigned int cnt, block, track, sector;
int drive;
struct amiga_floppy_struct *floppy;
char *data; char *data;
unsigned long flags;
blk_status_t err;
next_req: for (cnt = 0; cnt < blk_rq_cur_sectors(rq); cnt++) {
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++) {
#ifdef DEBUG #ifdef DEBUG
printk("fd: sector %ld + %d requested for %s\n", printk("fd: sector %ld + %d requested for %s\n",
blk_rq_pos(rq), cnt, blk_rq_pos(rq), cnt,
(rq_data_dir(rq) == READ) ? "read" : "write"); (rq_data_dir(rq) == READ) ? "read" : "write");
#endif #endif
block = blk_rq_pos(rq) + cnt; 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); track = block / (floppy->dtype->sects * floppy->type->sect_mult);
sector = block % (floppy->dtype->sects * floppy->type->sect_mult); sector = block % (floppy->dtype->sects * floppy->type->sect_mult);
data = bio_data(rq->bio) + 512 * cnt; data = bio_data(rq->bio) + 512 * cnt;
@ -1532,10 +1476,8 @@ next_segment:
"0x%08lx\n", track, sector, data); "0x%08lx\n", track, sector, data);
#endif #endif
if (get_track(drive, track) == -1) { if (get_track(drive, track) == -1)
err = BLK_STS_IOERR; return BLK_STS_IOERR;
break;
}
if (rq_data_dir(rq) == READ) { if (rq_data_dir(rq) == READ) {
memcpy(data, floppy->trackbuf + sector * 512, 512); memcpy(data, floppy->trackbuf + sector * 512, 512);
@ -1543,31 +1485,40 @@ next_segment:
memcpy(floppy->trackbuf + sector * 512, data, 512); memcpy(floppy->trackbuf + sector * 512, data, 512);
/* keep the drive spinning while writes are scheduled */ /* keep the drive spinning while writes are scheduled */
if (!fd_motor_on(drive)) { if (!fd_motor_on(drive))
err = BLK_STS_IOERR; return BLK_STS_IOERR;
break;
}
/* /*
* setup a callback to write the track buffer * setup a callback to write the track buffer
* after a short (1 tick) delay. * after a short (1 tick) delay.
*/ */
local_irq_save(flags);
floppy->dirty = 1; floppy->dirty = 1;
/* reset the timer */ /* reset the timer */
mod_timer (flush_track_timer + drive, jiffies + 1); mod_timer (flush_track_timer + drive, jiffies + 1);
local_irq_restore(flags);
} }
} }
if (__blk_end_request_cur(rq, err)) return BLK_STS_OK;
goto next_segment;
goto next_req;
} }
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) 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, .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) static struct gendisk *fd_alloc_disk(int drive)
{ {
struct gendisk *disk; struct gendisk *disk;
@ -1826,7 +1781,8 @@ static struct gendisk *fd_alloc_disk(int drive)
if (!disk) if (!disk)
goto out; 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)) { if (IS_ERR(disk->queue)) {
disk->queue = NULL; disk->queue = NULL;
goto out_put_disk; goto out_put_disk;
@ -1841,6 +1797,7 @@ static struct gendisk *fd_alloc_disk(int drive)
out_cleanup_queue: out_cleanup_queue:
blk_cleanup_queue(disk->queue); blk_cleanup_queue(disk->queue);
disk->queue = NULL; disk->queue = NULL;
blk_mq_free_tag_set(&unit[drive].tag_set);
out_put_disk: out_put_disk:
put_disk(disk); put_disk(disk);
out: out: