mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-13 00:29:50 +00:00
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/fd.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blk-mq.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
@ -81,7 +81,6 @@
|
|||||||
|
|
||||||
static DEFINE_MUTEX(ataflop_mutex);
|
static DEFINE_MUTEX(ataflop_mutex);
|
||||||
static struct request *fd_request;
|
static struct request *fd_request;
|
||||||
static int fdc_queue;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WD1772 stuff
|
* WD1772 stuff
|
||||||
@ -300,6 +299,7 @@ static struct atari_floppy_struct {
|
|||||||
struct gendisk *disk;
|
struct gendisk *disk;
|
||||||
int ref;
|
int ref;
|
||||||
int type;
|
int type;
|
||||||
|
struct blk_mq_tag_set tag_set;
|
||||||
} unit[FD_MAX_UNITS];
|
} unit[FD_MAX_UNITS];
|
||||||
|
|
||||||
#define UD unit[drive]
|
#define UD unit[drive]
|
||||||
@ -379,9 +379,6 @@ static int IsFormatting = 0, FormatError;
|
|||||||
static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
|
static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
|
||||||
module_param_array(UserSteprate, int, NULL, 0);
|
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 DECLARE_COMPLETION(format_wait);
|
||||||
|
|
||||||
static unsigned long changed_floppies = 0xff, fake_change = 0;
|
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( void );
|
||||||
static void finish_fdc_done( int dummy );
|
static void finish_fdc_done( int dummy );
|
||||||
static void setup_req_params( int drive );
|
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
|
static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
|
||||||
cmd, unsigned long param);
|
cmd, unsigned long param);
|
||||||
static void fd_probe( int drive );
|
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)
|
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;
|
fd_request = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void start_motor_off_timer(void)
|
static inline void start_motor_off_timer(void)
|
||||||
@ -706,7 +705,6 @@ static void fd_error( void )
|
|||||||
if (SelectedDrive != -1)
|
if (SelectedDrive != -1)
|
||||||
SUD.track = -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)
|
static int do_format(int drive, int type, struct atari_format_descr *desc)
|
||||||
{
|
{
|
||||||
|
struct request_queue *q = unit[drive].disk->queue;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
int sect, nsect;
|
int sect, nsect;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
|
blk_mq_freeze_queue(q);
|
||||||
drive, desc->track, desc->head, desc->sect_offset ));
|
blk_mq_quiesce_queue(q);
|
||||||
|
|
||||||
wait_event(fdc_wait, cmpxchg(&fdc_busy, 0, 1) == 0);
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
stdma_lock(floppy_irq, NULL);
|
stdma_lock(floppy_irq, NULL);
|
||||||
atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
|
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) {
|
||||||
if (--type >= NUM_DISK_MINORS ||
|
if (--type >= NUM_DISK_MINORS ||
|
||||||
minor2disktype[type].drive_types > DriveType) {
|
minor2disktype[type].drive_types > DriveType) {
|
||||||
redo_fd_request();
|
ret = -EINVAL;
|
||||||
return -EINVAL;
|
goto out;
|
||||||
}
|
}
|
||||||
type = minor2disktype[type].index;
|
type = minor2disktype[type].index;
|
||||||
UDT = &atari_disk_type[type];
|
UDT = &atari_disk_type[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
|
if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
|
||||||
redo_fd_request();
|
ret = -EINVAL;
|
||||||
return -EINVAL;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsect = UDT->spt;
|
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);
|
wait_for_completion(&format_wait);
|
||||||
|
|
||||||
redo_fd_request();
|
ret = FormatError ? -EIO : 0;
|
||||||
return( 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 {
|
else {
|
||||||
/* all sectors finished */
|
/* all sectors finished */
|
||||||
fd_end_request_cur(BLK_STS_OK);
|
fd_end_request_cur(BLK_STS_OK);
|
||||||
redo_fd_request();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1224,7 +1225,6 @@ static void fd_rwsec_done1(int status)
|
|||||||
else {
|
else {
|
||||||
/* all sectors finished */
|
/* all sectors finished */
|
||||||
fd_end_request_cur(BLK_STS_OK);
|
fd_end_request_cur(BLK_STS_OK);
|
||||||
redo_fd_request();
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1382,8 +1382,6 @@ static void finish_fdc_done( int dummy )
|
|||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
stdma_release();
|
stdma_release();
|
||||||
fdc_busy = 0;
|
|
||||||
wake_up( &fdc_wait );
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
|
||||||
DPRINT(("finish_fdc() finished\n"));
|
DPRINT(("finish_fdc() finished\n"));
|
||||||
@ -1473,59 +1471,34 @@ static void setup_req_params( int drive )
|
|||||||
ReqTrack, ReqSector, (unsigned long)ReqData ));
|
ReqTrack, ReqSector, (unsigned long)ReqData ));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
* Round-robin between our available drives, doing one request from each
|
const struct blk_mq_queue_data *bd)
|
||||||
*/
|
|
||||||
static struct request *set_next_request(void)
|
|
||||||
{
|
{
|
||||||
struct request_queue *q;
|
struct atari_floppy_struct *floppy = bd->rq->rq_disk->private_data;
|
||||||
int old_pos = fdc_queue;
|
int drive = floppy - unit;
|
||||||
struct request *rq = NULL;
|
int type = floppy->type;
|
||||||
|
|
||||||
do {
|
spin_lock_irq(&ataflop_lock);
|
||||||
q = unit[fdc_queue].disk->queue;
|
if (fd_request) {
|
||||||
if (++fdc_queue == FD_MAX_UNITS)
|
spin_unlock_irq(&ataflop_lock);
|
||||||
fdc_queue = 0;
|
return BLK_STS_DEV_RESOURCE;
|
||||||
if (q) {
|
}
|
||||||
rq = blk_fetch_request(q);
|
if (!stdma_try_lock(floppy_irq, NULL)) {
|
||||||
if (rq) {
|
spin_unlock_irq(&ataflop_lock);
|
||||||
rq->error_count = 0;
|
return BLK_STS_RESOURCE;
|
||||||
break;
|
}
|
||||||
}
|
fd_request = bd->rq;
|
||||||
}
|
blk_mq_start_request(fd_request);
|
||||||
} while (fdc_queue != old_pos);
|
|
||||||
|
|
||||||
return rq;
|
atari_disable_irq( IRQ_MFP_FDC );
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 ));
|
|
||||||
|
|
||||||
IsFormatting = 0;
|
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) {
|
if (!UD.connected) {
|
||||||
/* drive not connected */
|
/* drive not connected */
|
||||||
printk(KERN_ERR "Unknown Device: fd%d\n", drive );
|
printk(KERN_ERR "Unknown Device: fd%d\n", drive );
|
||||||
fd_end_request_cur(BLK_STS_IOERR);
|
fd_end_request_cur(BLK_STS_IOERR);
|
||||||
goto repeat;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
@ -1541,23 +1514,18 @@ repeat:
|
|||||||
if (--type >= NUM_DISK_MINORS) {
|
if (--type >= NUM_DISK_MINORS) {
|
||||||
printk(KERN_WARNING "fd%d: invalid disk format", drive );
|
printk(KERN_WARNING "fd%d: invalid disk format", drive );
|
||||||
fd_end_request_cur(BLK_STS_IOERR);
|
fd_end_request_cur(BLK_STS_IOERR);
|
||||||
goto repeat;
|
goto out;
|
||||||
}
|
}
|
||||||
if (minor2disktype[type].drive_types > DriveType) {
|
if (minor2disktype[type].drive_types > DriveType) {
|
||||||
printk(KERN_WARNING "fd%d: unsupported disk format", drive );
|
printk(KERN_WARNING "fd%d: unsupported disk format", drive );
|
||||||
fd_end_request_cur(BLK_STS_IOERR);
|
fd_end_request_cur(BLK_STS_IOERR);
|
||||||
goto repeat;
|
goto out;
|
||||||
}
|
}
|
||||||
type = minor2disktype[type].index;
|
type = minor2disktype[type].index;
|
||||||
UDT = &atari_disk_type[type];
|
UDT = &atari_disk_type[type];
|
||||||
set_capacity(floppy->disk, UDT->blocks);
|
set_capacity(floppy->disk, UDT->blocks);
|
||||||
UD.autoprobe = 0;
|
UD.autoprobe = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blk_rq_pos(fd_request) + 1 > UDT->blocks) {
|
|
||||||
fd_end_request_cur(BLK_STS_IOERR);
|
|
||||||
goto repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stop deselect timer */
|
/* stop deselect timer */
|
||||||
del_timer( &motor_off_timer );
|
del_timer( &motor_off_timer );
|
||||||
@ -1569,22 +1537,13 @@ repeat:
|
|||||||
setup_req_params( drive );
|
setup_req_params( drive );
|
||||||
do_fd_action( drive );
|
do_fd_action( drive );
|
||||||
|
|
||||||
return;
|
if (bd->last)
|
||||||
|
finish_fdc();
|
||||||
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();
|
|
||||||
atari_enable_irq( IRQ_MFP_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,
|
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 ? */
|
/* what if type > 0 here? Overwrite specified entry ? */
|
||||||
if (type) {
|
if (type) {
|
||||||
/* refuse to re-set a predefined type for now */
|
/* refuse to re-set a predefined type for now */
|
||||||
redo_fd_request();
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1730,10 +1688,8 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
|
|||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (setprm.track != dtp->blocks/dtp->spt/2 ||
|
if (setprm.track != dtp->blocks/dtp->spt/2 ||
|
||||||
setprm.head != 2) {
|
setprm.head != 2)
|
||||||
redo_fd_request();
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
UDT = dtp;
|
UDT = dtp;
|
||||||
set_capacity(floppy->disk, UDT->blocks);
|
set_capacity(floppy->disk, UDT->blocks);
|
||||||
@ -1989,6 +1945,10 @@ static const struct block_device_operations floppy_fops = {
|
|||||||
.revalidate_disk= floppy_revalidate,
|
.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)
|
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
|
||||||
{
|
{
|
||||||
int drive = *part & 3;
|
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)
|
static int __init atari_floppy_init (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!MACH_IS_ATARI)
|
if (!MACH_IS_ATARI)
|
||||||
/* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
|
/* 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++) {
|
for (i = 0; i < FD_MAX_UNITS; i++) {
|
||||||
unit[i].disk = alloc_disk(1);
|
unit[i].disk = alloc_disk(1);
|
||||||
if (!unit[i].disk)
|
if (!unit[i].disk) {
|
||||||
goto Enomem;
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
unit[i].disk->queue = blk_init_queue(do_fd_request,
|
unit[i].disk->queue = blk_mq_init_sq_queue(&unit[i].tag_set,
|
||||||
&ataflop_lock);
|
&ataflop_mq_ops, 2,
|
||||||
if (!unit[i].disk->queue)
|
BLK_MQ_F_SHOULD_MERGE);
|
||||||
goto Enomem;
|
if (IS_ERR(unit[i].disk->queue)) {
|
||||||
|
ret = PTR_ERR(unit[i].disk->queue);
|
||||||
|
unit[i].disk->queue = NULL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UseTrackbuffer < 0)
|
if (UseTrackbuffer < 0)
|
||||||
@ -2035,7 +2002,8 @@ static int __init atari_floppy_init (void)
|
|||||||
DMABuffer = atari_stram_alloc(BUFFER_SIZE+512, "ataflop");
|
DMABuffer = atari_stram_alloc(BUFFER_SIZE+512, "ataflop");
|
||||||
if (!DMABuffer) {
|
if (!DMABuffer) {
|
||||||
printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
|
printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
|
||||||
goto Enomem;
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
TrackBuffer = DMABuffer + 512;
|
TrackBuffer = DMABuffer + 512;
|
||||||
PhysDMABuffer = atari_stram_to_phys(DMABuffer);
|
PhysDMABuffer = atari_stram_to_phys(DMABuffer);
|
||||||
@ -2063,7 +2031,8 @@ static int __init atari_floppy_init (void)
|
|||||||
config_types();
|
config_types();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
Enomem:
|
|
||||||
|
err:
|
||||||
do {
|
do {
|
||||||
struct gendisk *disk = unit[i].disk;
|
struct gendisk *disk = unit[i].disk;
|
||||||
|
|
||||||
@ -2072,12 +2041,13 @@ Enomem:
|
|||||||
blk_cleanup_queue(disk->queue);
|
blk_cleanup_queue(disk->queue);
|
||||||
disk->queue = NULL;
|
disk->queue = NULL;
|
||||||
}
|
}
|
||||||
|
blk_mq_free_tag_set(&unit[i].tag_set);
|
||||||
put_disk(unit[i].disk);
|
put_disk(unit[i].disk);
|
||||||
}
|
}
|
||||||
} while (i--);
|
} while (i--);
|
||||||
|
|
||||||
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
||||||
return -ENOMEM;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
@ -2124,11 +2094,10 @@ static void __exit atari_floppy_exit(void)
|
|||||||
int i;
|
int i;
|
||||||
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
|
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
|
||||||
for (i = 0; i < FD_MAX_UNITS; i++) {
|
for (i = 0; i < FD_MAX_UNITS; i++) {
|
||||||
struct request_queue *q = unit[i].disk->queue;
|
|
||||||
|
|
||||||
del_gendisk(unit[i].disk);
|
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);
|
put_disk(unit[i].disk);
|
||||||
blk_cleanup_queue(q);
|
|
||||||
}
|
}
|
||||||
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user