forked from Minki/linux
ataflop: convert to blk-mq
This driver is already pretty broken, in that it has two wait_events() (one in stdma_lock()) in request_fn. Get rid of the first one by freezing/quiescing the queue on format, and the second one by replacing it with stdma_try_lock(). The rest is straightforward. Compile-tested only and probably incorrect. 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:
parent
71327f547e
commit
6ec3938cff
@ -66,7 +66,7 @@
|
||||
#include <linux/fd.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/blk-mq.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/wait.h>
|
||||
@ -81,7 +81,6 @@
|
||||
|
||||
static DEFINE_MUTEX(ataflop_mutex);
|
||||
static struct request *fd_request;
|
||||
static int fdc_queue;
|
||||
|
||||
/*
|
||||
* WD1772 stuff
|
||||
@ -300,6 +299,7 @@ static struct atari_floppy_struct {
|
||||
struct gendisk *disk;
|
||||
int ref;
|
||||
int type;
|
||||
struct blk_mq_tag_set tag_set;
|
||||
} unit[FD_MAX_UNITS];
|
||||
|
||||
#define UD unit[drive]
|
||||
@ -379,9 +379,6 @@ static int IsFormatting = 0, FormatError;
|
||||
static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
|
||||
module_param_array(UserSteprate, int, NULL, 0);
|
||||
|
||||
/* Synchronization of FDC access. */
|
||||
static volatile int fdc_busy = 0;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
|
||||
static DECLARE_COMPLETION(format_wait);
|
||||
|
||||
static unsigned long changed_floppies = 0xff, fake_change = 0;
|
||||
@ -441,7 +438,6 @@ static void fd_times_out(struct timer_list *unused);
|
||||
static void finish_fdc( void );
|
||||
static void finish_fdc_done( int dummy );
|
||||
static void setup_req_params( int drive );
|
||||
static void redo_fd_request( void);
|
||||
static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
|
||||
cmd, unsigned long param);
|
||||
static void fd_probe( int drive );
|
||||
@ -459,8 +455,11 @@ static DEFINE_TIMER(fd_timer, check_change);
|
||||
|
||||
static void fd_end_request_cur(blk_status_t err)
|
||||
{
|
||||
if (!__blk_end_request_cur(fd_request, err))
|
||||
if (!blk_update_request(fd_request, err,
|
||||
blk_rq_cur_bytes(fd_request))) {
|
||||
__blk_mq_end_request(fd_request, err);
|
||||
fd_request = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void start_motor_off_timer(void)
|
||||
@ -706,7 +705,6 @@ static void fd_error( void )
|
||||
if (SelectedDrive != -1)
|
||||
SUD.track = -1;
|
||||
}
|
||||
redo_fd_request();
|
||||
}
|
||||
|
||||
|
||||
@ -724,14 +722,15 @@ static void fd_error( void )
|
||||
|
||||
static int do_format(int drive, int type, struct atari_format_descr *desc)
|
||||
{
|
||||
struct request_queue *q = unit[drive].disk->queue;
|
||||
unsigned char *p;
|
||||
int sect, nsect;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
|
||||
drive, desc->track, desc->head, desc->sect_offset ));
|
||||
blk_mq_freeze_queue(q);
|
||||
blk_mq_quiesce_queue(q);
|
||||
|
||||
wait_event(fdc_wait, cmpxchg(&fdc_busy, 0, 1) == 0);
|
||||
local_irq_save(flags);
|
||||
stdma_lock(floppy_irq, NULL);
|
||||
atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
|
||||
@ -740,16 +739,16 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
|
||||
if (type) {
|
||||
if (--type >= NUM_DISK_MINORS ||
|
||||
minor2disktype[type].drive_types > DriveType) {
|
||||
redo_fd_request();
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
type = minor2disktype[type].index;
|
||||
UDT = &atari_disk_type[type];
|
||||
}
|
||||
|
||||
if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
|
||||
redo_fd_request();
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nsect = UDT->spt;
|
||||
@ -788,8 +787,11 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
|
||||
|
||||
wait_for_completion(&format_wait);
|
||||
|
||||
redo_fd_request();
|
||||
return( FormatError ? -EIO : 0 );
|
||||
ret = FormatError ? -EIO : 0;
|
||||
out:
|
||||
blk_mq_unquiesce_queue(q);
|
||||
blk_mq_unfreeze_queue(q);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -819,7 +821,6 @@ static void do_fd_action( int drive )
|
||||
else {
|
||||
/* all sectors finished */
|
||||
fd_end_request_cur(BLK_STS_OK);
|
||||
redo_fd_request();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1224,7 +1225,6 @@ static void fd_rwsec_done1(int status)
|
||||
else {
|
||||
/* all sectors finished */
|
||||
fd_end_request_cur(BLK_STS_OK);
|
||||
redo_fd_request();
|
||||
}
|
||||
return;
|
||||
|
||||
@ -1382,8 +1382,6 @@ static void finish_fdc_done( int dummy )
|
||||
|
||||
local_irq_save(flags);
|
||||
stdma_release();
|
||||
fdc_busy = 0;
|
||||
wake_up( &fdc_wait );
|
||||
local_irq_restore(flags);
|
||||
|
||||
DPRINT(("finish_fdc() finished\n"));
|
||||
@ -1473,59 +1471,34 @@ static void setup_req_params( int drive )
|
||||
ReqTrack, ReqSector, (unsigned long)ReqData ));
|
||||
}
|
||||
|
||||
/*
|
||||
* Round-robin between our available drives, doing one request from each
|
||||
*/
|
||||
static struct request *set_next_request(void)
|
||||
static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
const struct blk_mq_queue_data *bd)
|
||||
{
|
||||
struct request_queue *q;
|
||||
int old_pos = fdc_queue;
|
||||
struct request *rq = NULL;
|
||||
struct atari_floppy_struct *floppy = bd->rq->rq_disk->private_data;
|
||||
int drive = floppy - unit;
|
||||
int type = floppy->type;
|
||||
|
||||
do {
|
||||
q = unit[fdc_queue].disk->queue;
|
||||
if (++fdc_queue == FD_MAX_UNITS)
|
||||
fdc_queue = 0;
|
||||
if (q) {
|
||||
rq = blk_fetch_request(q);
|
||||
if (rq) {
|
||||
rq->error_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (fdc_queue != old_pos);
|
||||
spin_lock_irq(&ataflop_lock);
|
||||
if (fd_request) {
|
||||
spin_unlock_irq(&ataflop_lock);
|
||||
return BLK_STS_DEV_RESOURCE;
|
||||
}
|
||||
if (!stdma_try_lock(floppy_irq, NULL)) {
|
||||
spin_unlock_irq(&ataflop_lock);
|
||||
return BLK_STS_RESOURCE;
|
||||
}
|
||||
fd_request = bd->rq;
|
||||
blk_mq_start_request(fd_request);
|
||||
|
||||
return rq;
|
||||
}
|
||||
|
||||
|
||||
static void redo_fd_request(void)
|
||||
{
|
||||
int drive, type;
|
||||
struct atari_floppy_struct *floppy;
|
||||
|
||||
DPRINT(("redo_fd_request: fd_request=%p dev=%s fd_request->sector=%ld\n",
|
||||
fd_request, fd_request ? fd_request->rq_disk->disk_name : "",
|
||||
fd_request ? blk_rq_pos(fd_request) : 0 ));
|
||||
atari_disable_irq( IRQ_MFP_FDC );
|
||||
|
||||
IsFormatting = 0;
|
||||
|
||||
repeat:
|
||||
if (!fd_request) {
|
||||
fd_request = set_next_request();
|
||||
if (!fd_request)
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
floppy = fd_request->rq_disk->private_data;
|
||||
drive = floppy - unit;
|
||||
type = floppy->type;
|
||||
|
||||
if (!UD.connected) {
|
||||
/* drive not connected */
|
||||
printk(KERN_ERR "Unknown Device: fd%d\n", drive );
|
||||
fd_end_request_cur(BLK_STS_IOERR);
|
||||
goto repeat;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (type == 0) {
|
||||
@ -1541,23 +1514,18 @@ repeat:
|
||||
if (--type >= NUM_DISK_MINORS) {
|
||||
printk(KERN_WARNING "fd%d: invalid disk format", drive );
|
||||
fd_end_request_cur(BLK_STS_IOERR);
|
||||
goto repeat;
|
||||
goto out;
|
||||
}
|
||||
if (minor2disktype[type].drive_types > DriveType) {
|
||||
printk(KERN_WARNING "fd%d: unsupported disk format", drive );
|
||||
fd_end_request_cur(BLK_STS_IOERR);
|
||||
goto repeat;
|
||||
goto out;
|
||||
}
|
||||
type = minor2disktype[type].index;
|
||||
UDT = &atari_disk_type[type];
|
||||
set_capacity(floppy->disk, UDT->blocks);
|
||||
UD.autoprobe = 0;
|
||||
}
|
||||
|
||||
if (blk_rq_pos(fd_request) + 1 > UDT->blocks) {
|
||||
fd_end_request_cur(BLK_STS_IOERR);
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
/* stop deselect timer */
|
||||
del_timer( &motor_off_timer );
|
||||
@ -1569,22 +1537,13 @@ repeat:
|
||||
setup_req_params( drive );
|
||||
do_fd_action( drive );
|
||||
|
||||
return;
|
||||
|
||||
the_end:
|
||||
finish_fdc();
|
||||
}
|
||||
|
||||
|
||||
void do_fd_request(struct request_queue * q)
|
||||
{
|
||||
DPRINT(("do_fd_request for pid %d\n",current->pid));
|
||||
wait_event(fdc_wait, cmpxchg(&fdc_busy, 0, 1) == 0);
|
||||
stdma_lock(floppy_irq, NULL);
|
||||
|
||||
atari_disable_irq( IRQ_MFP_FDC );
|
||||
redo_fd_request();
|
||||
if (bd->last)
|
||||
finish_fdc();
|
||||
atari_enable_irq( IRQ_MFP_FDC );
|
||||
|
||||
out:
|
||||
spin_unlock_irq(&ataflop_lock);
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
|
||||
static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
@ -1662,7 +1621,6 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
/* what if type > 0 here? Overwrite specified entry ? */
|
||||
if (type) {
|
||||
/* refuse to re-set a predefined type for now */
|
||||
redo_fd_request();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1730,10 +1688,8 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
|
||||
/* sanity check */
|
||||
if (setprm.track != dtp->blocks/dtp->spt/2 ||
|
||||
setprm.head != 2) {
|
||||
redo_fd_request();
|
||||
setprm.head != 2)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
UDT = dtp;
|
||||
set_capacity(floppy->disk, UDT->blocks);
|
||||
@ -1989,6 +1945,10 @@ static const struct block_device_operations floppy_fops = {
|
||||
.revalidate_disk= floppy_revalidate,
|
||||
};
|
||||
|
||||
static const struct blk_mq_ops ataflop_mq_ops = {
|
||||
.queue_rq = ataflop_queue_rq,
|
||||
};
|
||||
|
||||
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
|
||||
{
|
||||
int drive = *part & 3;
|
||||
@ -2002,6 +1962,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
|
||||
static int __init atari_floppy_init (void)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (!MACH_IS_ATARI)
|
||||
/* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
|
||||
@ -2012,13 +1973,19 @@ static int __init atari_floppy_init (void)
|
||||
|
||||
for (i = 0; i < FD_MAX_UNITS; i++) {
|
||||
unit[i].disk = alloc_disk(1);
|
||||
if (!unit[i].disk)
|
||||
goto Enomem;
|
||||
if (!unit[i].disk) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
unit[i].disk->queue = blk_init_queue(do_fd_request,
|
||||
&ataflop_lock);
|
||||
if (!unit[i].disk->queue)
|
||||
goto Enomem;
|
||||
unit[i].disk->queue = blk_mq_init_sq_queue(&unit[i].tag_set,
|
||||
&ataflop_mq_ops, 2,
|
||||
BLK_MQ_F_SHOULD_MERGE);
|
||||
if (IS_ERR(unit[i].disk->queue)) {
|
||||
ret = PTR_ERR(unit[i].disk->queue);
|
||||
unit[i].disk->queue = NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (UseTrackbuffer < 0)
|
||||
@ -2035,7 +2002,8 @@ static int __init atari_floppy_init (void)
|
||||
DMABuffer = atari_stram_alloc(BUFFER_SIZE+512, "ataflop");
|
||||
if (!DMABuffer) {
|
||||
printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
|
||||
goto Enomem;
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
TrackBuffer = DMABuffer + 512;
|
||||
PhysDMABuffer = atari_stram_to_phys(DMABuffer);
|
||||
@ -2063,7 +2031,8 @@ static int __init atari_floppy_init (void)
|
||||
config_types();
|
||||
|
||||
return 0;
|
||||
Enomem:
|
||||
|
||||
err:
|
||||
do {
|
||||
struct gendisk *disk = unit[i].disk;
|
||||
|
||||
@ -2072,12 +2041,13 @@ Enomem:
|
||||
blk_cleanup_queue(disk->queue);
|
||||
disk->queue = NULL;
|
||||
}
|
||||
blk_mq_free_tag_set(&unit[i].tag_set);
|
||||
put_disk(unit[i].disk);
|
||||
}
|
||||
} while (i--);
|
||||
|
||||
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
||||
return -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef MODULE
|
||||
@ -2124,11 +2094,10 @@ static void __exit atari_floppy_exit(void)
|
||||
int i;
|
||||
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
|
||||
for (i = 0; i < FD_MAX_UNITS; i++) {
|
||||
struct request_queue *q = unit[i].disk->queue;
|
||||
|
||||
del_gendisk(unit[i].disk);
|
||||
blk_cleanup_queue(unit[i].disk->queue);
|
||||
blk_mq_free_tag_set(&unit[i].tag_set);
|
||||
put_disk(unit[i].disk);
|
||||
blk_cleanup_queue(q);
|
||||
}
|
||||
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user