Convert floppy drivers to blk-mq
Subsystems (3)
v2 cover Convert floppy drivers to blk-mq
From: Omar Sandoval <[email protected]>
Hi,
This series converts the various floppy drivers to blk-mq. Save for the last one (floppy), they're compile-tested only. If I've Cc'd you, it's because I think you might be able to test the changes. Please test if you can, or let me know if there's a way to use QEMU/some other emulator to test. The full series is available at [1]. Thanks!
Changes from v1:
- Drop "swim3: end whole request on error" and "floppy: end whole request on error".
- Handle errors on individual bios correctly in the other drivers.
1: https://github.com/osandov/linux/tree/mq-conversions.
Omar Sandoval (11):
swim: fix cleanup on setup error
swim: convert to blk-mq
swim3: add real error handling in setup
swim3: convert to blk-mq
amiflop: fold headers into C file
amiflop: clean up on errors during setup
amiflop: convert to blk-mq
ataflop: fold headers into C file
ataflop: fix error handling during setup
ataflop: convert to blk-mq
floppy: convert to blk-mq
arch/m68k/include/asm/atafd.h | 13 -- arch/m68k/include/asm/atafdreg.h | 80 -------- drivers/block/amiflop.c | 328 +++++++++++++++++++------------ drivers/block/ataflop.c | 283 +++++++++++++++----------- drivers/block/floppy.c | 74 ++++--- drivers/block/swim.c | 114 ++++++----- drivers/block/swim3.c | 219 ++++++++++----------- include/linux/amifd.h | 63 ------ include/linux/amifdreg.h | 82 -------- 9 files changed, 590 insertions(+), 666 deletions(-) delete mode 100644 arch/m68k/include/asm/atafd.h delete mode 100644 arch/m68k/include/asm/atafdreg.h delete mode 100644 include/linux/amifd.h delete mode 100644 include/linux/amifdreg.h
Signature · 1 line
2.19.1
PATCH v2 1/11 swim: fix cleanup on setup error
From: Omar Sandoval <[email protected]>
If we fail to allocate the request queue for a disk, we still need to free that disk, not just the previous ones. Additionally, we need to cleanup the previous request queues.
--- drivers/block/swim.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/block/swim.c +11 -2
@@ -887,8 +887,17 @@ static int swim_floppy_init(struct swim_priv *swd) exit_put_disks:unregister_blkdev (FLOPPY_MAJOR ,"fd" ); -while (drive--) -put_disk (swd->unit[drive].disk); +do { +struct gendisk *disk = swd->unit[drive].disk; + +if (disk) { +if (disk->queue) { +blk_cleanup_queue (disk->queue); + disk->queue =NULL ; + } +put_disk (disk); + } + }while (drive--);return err; }
Signature · 1 line
2.19.1
PATCH v2 2/11 swim: convert to blk-mq
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
The only interesting thing here is that there may be two floppies (i.e., request queues) sharing the same controller, so we use the global struct swim_priv->lock to check whether the controller is busy. Compile-tested only.
--- drivers/block/swim.c | 101 +++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 52 deletions(-)
drivers/block/swim.c +49 -52
@@ -19,7 +19,7 @@#include <linux/module.h> #include <linux/fd.h> #include <linux/slab.h> -#include <linux/blkdev.h> +#include <linux/blk-mq.h> #include <linux/mutex.h> #include <linux/hdreg.h> #include <linux/kernel.h>
@@ -190,6 +190,7 @@ struct floppy_state {int ref_count;struct gendisk *disk; +struct blk_mq_tag_set tag_set;/* parent controller */
@@ -211,7 +212,6 @@ enum head {struct swim_priv {struct swim __iomem *base;spinlock_t lock; -int fdc_queue;int floppy_count;struct floppy_state unit[FD_MAX_UNIT ]; };
@@ -525,58 +525,36 @@ static blk_status_t floppy_read_sectors(struct floppy_state *fs,return 0 ; } -static struct request *swim_next_request (struct swim_priv *swd) +static blk_status_t swim_queue_rq (struct blk_mq_hw_ctx *hctx, +const struct blk_mq_queue_data *bd) { -struct request_queue *q; -struct request *rq; -int old_pos = swd->fdc_queue; +struct floppy_state *fs = hctx->queue->queuedata; +struct swim_priv *swd = fs->swd; +struct request *req = bd->rq; +blk_status_t err; -do { - q = swd->unit[swd->fdc_queue].disk->queue; -if (++swd->fdc_queue == swd->floppy_count) - swd->fdc_queue =0 ; -if (q) { - rq =blk_fetch_request (q); -if (rq) -return rq; - } - }while (swd->fdc_queue != old_pos); +if (!spin_trylock_irq (&swd->lock)) +return BLK_STS_DEV_RESOURCE ; -return NULL ; -} +blk_mq_start_request (req); -static void do_fd_request (struct request_queue *q) -{ -struct swim_priv *swd = q->queuedata; -struct request *req; -struct floppy_state *fs; +if (!fs->disk_in ||rq_data_dir (req) ==WRITE ) { + err =BLK_STS_IOERR ; + goto out; + } - req =swim_next_request (swd); -while (req) { -blk_status_t err =BLK_STS_IOERR ; +do { + err =floppy_read_sectors (fs,blk_rq_pos (req), +blk_rq_cur_sectors (req), +bio_data (req->bio)); + }while (blk_update_request (req, err,blk_rq_cur_bytes (req))); +__blk_mq_end_request (req, err); - fs = req->rq_disk->private_data; -if (blk_rq_pos (req) >= fs->total_secs) - goto done; -if (!fs->disk_in) - goto done; -if (rq_data_dir (req) ==WRITE && fs->write_protected) - goto done; + err =BLK_STS_OK ; +out: +spin_unlock_irq (&swd->lock); +return err; -switch (rq_data_dir (req)) { -case WRITE : -/* NOT IMPLEMENTED */ -break ; -case READ : - err =floppy_read_sectors (fs,blk_rq_pos (req), -blk_rq_cur_sectors (req), -bio_data (req->bio)); -break ; - } - done: -if (!__blk_end_request_cur (req, err)) - req =swim_next_request (swd); - } }static struct floppy_struct floppy_type[4 ] = {
@@ -823,6 +801,10 @@ static int swim_add_floppy(struct swim_priv *swd, enum drive_location location)return 0 ; } +static const struct blk_mq_ops swim_mq_ops = { + .queue_rq = swim_queue_rq, +}; +static int swim_floppy_init (struct swim_priv *swd) {int err;
@@ -852,20 +834,33 @@ static int swim_floppy_init(struct swim_priv *swd)spin_lock_init (&swd->lock);for (drive =0 ; drive < swd->floppy_count; drive++) { +struct blk_mq_tag_set *set; + swd->unit[drive].disk =alloc_disk (1 );if (swd->unit[drive].disk ==NULL ) { err = -ENOMEM ; goto exit_put_disks; } - swd->unit[drive].disk->queue =blk_init_queue (do_fd_request, - &swd->lock); -if (!swd->unit[drive].disk->queue) { - err = -ENOMEM ; + + set = &swd->unit[drive].tag_set; + set->ops = &swim_mq_ops; + set->nr_hw_queues =1 ; + set->queue_depth =2 ; + set->numa_node =NUMA_NO_NODE ; + set->flags =BLK_MQ_F_SHOULD_MERGE ; + err =blk_mq_alloc_tag_set (set); +if (err) + goto exit_put_disks; + + swd->unit[drive].disk->queue =blk_mq_init_queue (set); +if (IS_ERR (swd->unit[drive].disk->queue)) { + err =PTR_ERR (swd->unit[drive].disk->queue); + swd->unit[drive].disk->queue =NULL ; goto exit_put_disks; }blk_queue_bounce_limit (swd->unit[drive].disk->queue,BLK_BOUNCE_HIGH ); - swd->unit[drive].disk->queue->queuedata = swd; + swd->unit[drive].disk->queue->queuedata = &swd->unit[drive]; swd->unit[drive].swd = swd; }
@@ -895,6 +890,7 @@ static int swim_floppy_init(struct swim_priv *swd)blk_cleanup_queue (disk->queue); disk->queue =NULL ; } +blk_mq_free_tag_set (&swd->unit[drive].tag_set);put_disk (disk); } }while (drive--);
@@ -970,6 +966,7 @@ static int swim_remove(struct platform_device *dev)for (drive =0 ; drive < swd->floppy_count; drive++) {del_gendisk (swd->unit[drive].disk);blk_cleanup_queue (swd->unit[drive].disk->queue); +blk_mq_free_tag_set (&swd->unit[drive].tag_set);put_disk (swd->unit[drive].disk); }
Signature · 1 line
2.19.1
PATCH v2 3/11 swim3: add real error handling in setup
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
The driver doesn't have support for removing a device that has already been configured, but with more careful ordering we can avoid the need for that and make sure that we don't leak generic resources.
--- drivers/block/swim3.c | 60 ++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 24 deletions(-)
drivers/block/swim3.c +36 -24
@@ -1202,47 +1202,59 @@ static int swim3_add_device(struct macio_dev *mdev, int index)static int swim3_attach (struct macio_dev *mdev,const struct of_device_id *match) { +struct floppy_state *fs;struct gendisk *disk; -int index, rc; +int rc; - index = floppy_count++; -if (index >=MAX_FLOPPIES ) +if (floppy_count >=MAX_FLOPPIES )return -ENXIO ; -/* Add the drive */ - rc =swim3_add_device (mdev, index); -if (rc) -return rc; -/* Now register that disk. Same comment about failure handling */ - disk = disks[index] =alloc_disk (1 ); -if (disk ==NULL ) -return -ENOMEM ; +if (floppy_count ==0 ) { + rc =register_blkdev (FLOPPY_MAJOR ,"fd" ); +if (rc) +return rc; + } + + fs = &floppy_states[floppy_count]; + + disk =alloc_disk (1 ); +if (disk ==NULL ) { + rc = -ENOMEM ; + goto out_unregister; + } disk->queue =blk_init_queue (do_fd_request, &swim3_lock);if (disk->queue ==NULL ) { -put_disk (disk); -return -ENOMEM ; + rc = -ENOMEM ; + goto out_put_disk; }blk_queue_bounce_limit (disk->queue,BLK_BOUNCE_HIGH ); - disk->queue->queuedata = &floppy_states[index]; + disk->queue->queuedata = fs; -if (index ==0 ) { -/* If we failed, there isn't much we can do as the driver is still -* too dumb to remove the device, just bail out -*/ -if (register_blkdev (FLOPPY_MAJOR ,"fd" )) -return 0 ; - } + rc =swim3_add_device (mdev, floppy_count); +if (rc) + goto out_cleanup_queue; disk->major =FLOPPY_MAJOR ; - disk->first_minor = index; + disk->first_minor = floppy_count; disk->fops = &floppy_fops; - disk->private_data = &floppy_states[index]; + disk->private_data = fs; disk->flags |=GENHD_FL_REMOVABLE ; -sprintf (disk->disk_name,"fd%d" , index); +sprintf (disk->disk_name,"fd%d" , floppy_count);set_capacity (disk,2880 );add_disk (disk); + disks[floppy_count++] = disk;return 0 ; + +out_cleanup_queue: +blk_cleanup_queue (disk->queue); + disk->queue =NULL ; +out_put_disk: +put_disk (disk); +out_unregister: +if (floppy_count ==0 ) +unregister_blkdev (FLOPPY_MAJOR ,"fd" ); +return rc; } static const struct of_device_id swim3_match[] =
Signature · 1 line
2.19.1
PATCH v2 4/11 swim3: convert to blk-mq
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
Pretty simple conversion. grab_drive() could probably be replaced by some freeze/quiesce incantation, but I left it alone, and just used freeze/quiesce for eject. Compile-tested only.
--- drivers/block/swim3.c | 163 +++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 88 deletions(-)
drivers/block/swim3.c +75 -88
@@ -25,7 +25,7 @@#include <linux/delay.h> #include <linux/fd.h> #include <linux/ioctl.h> -#include <linux/blkdev.h> +#include <linux/blk-mq.h> #include <linux/interrupt.h> #include <linux/mutex.h> #include <linux/module.h>
@@ -206,6 +206,7 @@ struct floppy_state {char dbdma_cmd_space[5 *sizeof (struct dbdma_cmd )];int index;struct request *cur_req; +struct blk_mq_tag_set tag_set; }; #define swim3_err(fmt, arg...) dev_err(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
@@ -260,16 +261,15 @@ static int floppy_revalidate(struct gendisk *disk);static bool swim3_end_request (struct floppy_state *fs,blk_status_t err,unsigned int nr_bytes) {struct request *req = fs->cur_req; -int rc;swim3_dbg (" end request, err=%d nr_bytes=%d, cur_req=%p\n" , err, nr_bytes, req);if (err) nr_bytes =blk_rq_cur_bytes (req); - rc =__blk_end_request (req, err, nr_bytes); -if (rc) +if (blk_update_request (req, err, nr_bytes))return true; +__blk_mq_end_request (req, err); fs->cur_req =NULL ;return false; }
@@ -309,86 +309,58 @@ static int swim3_readbit(struct floppy_state *fs, int bit)return (stat &DATA ) ==0 ; } -static void start_request (struct floppy_state *fs) +static blk_status_t swim3_queue_rq (struct blk_mq_hw_ctx *hctx, +const struct blk_mq_queue_data *bd) { -struct request *req; +struct floppy_state *fs = hctx->queue->queuedata; +struct request *req = bd->rq;unsigned long x; -swim3_dbg ("start request, initial state=%d\n" , fs->state); - -if (fs->state == idle && fs->wanted) { - fs->state = available; -wake_up (&fs->wait); -return ; +spin_lock_irq (&swim3_lock); +if (fs->cur_req || fs->state != idle) { +spin_unlock_irq (&swim3_lock); +return BLK_STS_DEV_RESOURCE ; } -while (fs->state == idle) { -swim3_dbg ("start request, idle loop, cur_req=%p\n" , fs->cur_req); -if (!fs->cur_req) { - fs->cur_req =blk_fetch_request (disks[fs->index]->queue); -swim3_dbg (" fetched request %p\n" , fs->cur_req); -if (!fs->cur_req) -break ; - } - req = fs->cur_req; - -if (fs->mdev->media_bay && -check_media_bay (fs->mdev->media_bay) !=MB_FD ) { -swim3_dbg ("%s" ," media bay absent, dropping req\n" ); -swim3_end_request (fs,BLK_STS_IOERR ,0 ); -continue ; - } - -#if 0 /* This is really too verbose */ -swim3_dbg ("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n" , - req->rq_disk->disk_name, req->cmd, - (long )blk_rq_pos (req),blk_rq_sectors (req), -bio_data (req->bio)); -swim3_dbg (" current_nr_sectors=%u\n" , -blk_rq_cur_sectors (req)); -#endif - -if (blk_rq_pos (req) >= fs->total_secs) { -swim3_dbg (" pos out of bounds (%ld, max is %ld)\n" , - (long )blk_rq_pos (req), (long )fs->total_secs); -swim3_end_request (fs,BLK_STS_IOERR ,0 ); -continue ; - } -if (fs->ejected) { -swim3_dbg ("%s" ," disk ejected\n" ); +blk_mq_start_request (req); + fs->cur_req = req; +if (fs->mdev->media_bay && +check_media_bay (fs->mdev->media_bay) !=MB_FD ) { +swim3_dbg ("%s" ," media bay absent, dropping req\n" ); +swim3_end_request (fs,BLK_STS_IOERR ,0 ); + goto out; + } +if (fs->ejected) { +swim3_dbg ("%s" ," disk ejected\n" ); +swim3_end_request (fs,BLK_STS_IOERR ,0 ); + goto out; + } +if (rq_data_dir (req) ==WRITE ) { +if (fs->write_prot <0 ) + fs->write_prot =swim3_readbit (fs,WRITE_PROT ); +if (fs->write_prot) { +swim3_dbg ("%s" ," try to write, disk write protected\n" );swim3_end_request (fs,BLK_STS_IOERR ,0 ); -continue ; - } - -if (rq_data_dir (req) ==WRITE ) { -if (fs->write_prot <0 ) - fs->write_prot =swim3_readbit (fs,WRITE_PROT ); -if (fs->write_prot) { -swim3_dbg ("%s" ," try to write, disk write protected\n" ); -swim3_end_request (fs,BLK_STS_IOERR ,0 ); -continue ; - } + goto out; } - -/* Do not remove the cast. blk_rq_pos(req) is now a -* sector_t and can be 64 bits, but it will never go -* past 32 bits for this driver anyway, so we can -* safely cast it down and not have to do a 64/32 -* division -*/ - fs->req_cyl = ((long )blk_rq_pos (req)) / fs->secpercyl; - x = ((long )blk_rq_pos (req)) % fs->secpercyl; - fs->head = x / fs->secpertrack; - fs->req_sector = x % fs->secpertrack +1 ; - fs->state = do_transfer; - fs->retries =0 ; - -act (fs); } -} -static void do_fd_request (struct request_queue * q) -{ -start_request (q->queuedata); +/* +* Do not remove the cast. blk_rq_pos(req) is now a sector_t and can be +* 64 bits, but it will never go past 32 bits for this driver anyway, so +* we can safely cast it down and not have to do a 64/32 division +*/ + fs->req_cyl = ((long )blk_rq_pos (req)) / fs->secpercyl; + x = ((long )blk_rq_pos (req)) % fs->secpercyl; + fs->head = x / fs->secpertrack; + fs->req_sector = x % fs->secpertrack +1 ; + fs->state = do_transfer; + fs->retries =0 ; + +act (fs); + +out: +spin_unlock_irq (&swim3_lock); +return BLK_STS_OK ; } static void set_timeout(struct floppy_state *fs, int nticks,
@@ -585,7 +557,6 @@ static void scan_timeout(struct timer_list *t)if (fs->retries >5 ) {swim3_end_request (fs,BLK_STS_IOERR ,0 ); fs->state = idle; -start_request (fs); }else { fs->state = jogging;act (fs);
@@ -609,7 +580,6 @@ static void seek_timeout(struct timer_list *t)swim3_err ("%s" ,"Seek timeout\n" );swim3_end_request (fs,BLK_STS_IOERR ,0 ); fs->state = idle; -start_request (fs);spin_unlock_irqrestore (&swim3_lock, flags); }
@@ -638,7 +608,6 @@ static void settle_timeout(struct timer_list *t)swim3_err ("%s" ,"Seek settle timeout\n" );swim3_end_request (fs,BLK_STS_IOERR ,0 ); fs->state = idle; -start_request (fs); unlock:spin_unlock_irqrestore (&swim3_lock, flags); }
@@ -667,7 +636,6 @@ static void xfer_timeout(struct timer_list *t) (long)blk_rq_pos(fs->cur_req));swim3_end_request (fs,BLK_STS_IOERR ,0 ); fs->state = idle; -start_request (fs);spin_unlock_irqrestore (&swim3_lock, flags); }
@@ -704,7 +672,6 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)if (fs->retries >5 ) {swim3_end_request (fs,BLK_STS_IOERR ,0 ); fs->state = idle; -start_request (fs); }else { fs->state = jogging;act (fs);
@@ -796,7 +763,6 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) fs->state, rq_data_dir(req), intr, err);swim3_end_request (fs,BLK_STS_IOERR ,0 ); fs->state = idle; -start_request (fs);break ; } fs->retries =0 ;
@@ -813,8 +779,6 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) }else fs->state = idle; } -if (fs->state == idle) -start_request (fs);break ;default :swim3_err ("Don't know what to do in state %d\n" , fs->state);
@@ -862,14 +826,19 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,static void release_drive (struct floppy_state *fs) { +struct request_queue *q = disks[fs->index]->queue;unsigned long flags;swim3_dbg ("%s" ,"-> release drive\n" );spin_lock_irqsave (&swim3_lock, flags); fs->state = idle; -start_request (fs);spin_unlock_irqrestore (&swim3_lock, flags); + +blk_mq_freeze_queue (q); +blk_mq_quiesce_queue (q); +blk_mq_unquiesce_queue (q); +blk_mq_unfreeze_queue (q); }static int fd_eject (struct floppy_state *fs)
@@ -1089,6 +1058,10 @@ static const struct block_device_operations floppy_fops = { .revalidate_disk= floppy_revalidate, }; +static const struct blk_mq_ops swim3_mq_ops = { + .queue_rq = swim3_queue_rq, +}; +static void swim3_mb_event (struct macio_dev * mdev,int mb_state) {struct floppy_state *fs =macio_get_drvdata (mdev);
@@ -1222,10 +1195,22 @@ static int swim3_attach(struct macio_dev *mdev, rc = -ENOMEM ; goto out_unregister; } - disk->queue =blk_init_queue (do_fd_request, &swim3_lock); -if (disk->queue ==NULL ) { - rc = -ENOMEM ; + + fs->tag_set.ops = &swim3_mq_ops; + fs->tag_set.nr_hw_queues =1 ; + fs->tag_set.queue_depth =2 ; + fs->tag_set.numa_node =NUMA_NO_NODE ; + fs->tag_set.flags =BLK_MQ_F_SHOULD_MERGE ; + + rc =blk_mq_alloc_tag_set (&fs->tag_set); +if (rc) goto out_put_disk; + + disk->queue =blk_mq_init_queue (&fs->tag_set); +if (IS_ERR (disk->queue)) { + rc =PTR_ERR (disk->queue); + disk->queue =NULL ; + goto out_free_tag_set; }blk_queue_bounce_limit (disk->queue,BLK_BOUNCE_HIGH ); disk->queue->queuedata = fs;
@@ -1249,6 +1234,8 @@ static int swim3_attach(struct macio_dev *mdev, out_cleanup_queue:blk_cleanup_queue (disk->queue); disk->queue =NULL ; +out_free_tag_set: +blk_mq_free_tag_set (&fs->tag_set); out_put_disk:put_disk (disk); out_unregister:
Signature · 1 line
2.19.1
PATCH v2 6/11 amiflop: clean up on errors during setup
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
The error handling in fd_probe_drives() doesn't clean up at all. Fix it up in preparation for converting to blk-mq. While we're here, get rid of the commented out amiga_floppy_remove().
--- drivers/block/amiflop.c | 84 ++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 44 deletions(-)
drivers/block/amiflop.c +40 -44
@@ -1818,11 +1818,41 @@ static const struct block_device_operations floppy_fops = { .check_events = amiga_check_events, }; +static struct gendisk *fd_alloc_disk (int drive) +{ +struct gendisk *disk; + + disk =alloc_disk (1 ); +if (!disk) + goto out; + + disk->queue =blk_init_queue (do_fd_request, &amiflop_lock); +if (IS_ERR (disk->queue)) { + disk->queue =NULL ; + goto out_put_disk; + } + + unit[drive].trackbuf =kmalloc (FLOPPY_MAX_SECTORS *512 ,GFP_KERNEL ); +if (!unit[drive].trackbuf) + goto out_cleanup_queue; + +return disk; + +out_cleanup_queue: +blk_cleanup_queue (disk->queue); + disk->queue =NULL ; +out_put_disk: +put_disk (disk); +out: + unit[drive].type->code =FD_NODRIVE ; +return NULL ; +} +static int __init fd_probe_drives (void ) {int drive,drives,nomem; -printk (KERN_INFO "FD: probing units\nfound " ); +pr_info ("FD: probing units\nfound" ); drives=0 ; nomem=0 ;for (drive=0 ;drive<FD_MAX_UNITS ;drive++) {
@@ -1830,27 +1860,17 @@ static int __init fd_probe_drives(void)fd_probe (drive);if (unit[drive].type->code ==FD_NODRIVE )continue ; - disk =alloc_disk (1 ); + + disk =fd_alloc_disk (drive);if (!disk) { - unit[drive].type->code =FD_NODRIVE ; +pr_cont (" no mem for fd%d" , drive); + nomem =1 ;continue ; } unit[drive].gendisk = disk; - - disk->queue =blk_init_queue (do_fd_request, &amiflop_lock); -if (!disk->queue) { - unit[drive].type->code =FD_NODRIVE ; -continue ; - } - drives++; -if ((unit[drive].trackbuf =kmalloc (FLOPPY_MAX_SECTORS *512 ,GFP_KERNEL )) ==NULL ) { -printk ("no mem for " ); - unit[drive].type = &drive_types[num_dr_types -1 ];/* FD_NODRIVE */ - drives--; - nomem =1 ; - } -printk ("fd%d " ,drive); + +pr_cont (" fd%d" ,drive); disk->major =FLOPPY_MAJOR ; disk->first_minor = drive; disk->fops = &floppy_fops;
@@ -1861,11 +1881,11 @@ static int __init fd_probe_drives(void) }if ((drives >0 ) || (nomem ==0 )) {if (drives ==0 ) -printk ("no drives" ); -printk ("\n" ); +pr_cont (" no drives" ); +pr_cont ("\n" );return drives; } -printk ("\n" ); +pr_cont ("\n" );return -ENOMEM ; }
@@ -1948,30 +1968,6 @@ static int __init amiga_floppy_probe(struct platform_device *pdev)return ret; } -#if 0 /* not safe to unload */ -static int __exit amiga_floppy_remove(struct platform_device *pdev) -{ -int i; - -for ( i =0 ; i <FD_MAX_UNITS ; i++) { -if (unit[i].type->code !=FD_NODRIVE ) { -struct request_queue *q = unit[i].gendisk->queue; -del_gendisk (unit[i].gendisk); -put_disk (unit[i].gendisk); -kfree (unit[i].trackbuf); -if (q) -blk_cleanup_queue (q); - } - } -blk_unregister_region (MKDEV (FLOPPY_MAJOR ,0 ),256 ); -free_irq (IRQ_AMIGA_CIAA_TB ,NULL ); -free_irq (IRQ_AMIGA_DSKBLK ,NULL ); - custom.dmacon =DMAF_DISK ;/* disable DMA */ -amiga_chip_free (raw_buf); -unregister_blkdev (FLOPPY_MAJOR ,"fd" ); -} -#endif -static struct platform_driver amiga_floppy_driver = { .driver = { .name ="amiga-floppy" ,
Signature · 1 line
2.19.1
PATCH v2 7/11 amiflop: convert to blk-mq
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
Straightforward conversion, just use the existing amiflop_lock to serialize access to the controller. Compile-tested only.
--- drivers/block/amiflop.c | 125 +++++++++++++++------------------------- 1 file changed, 46 insertions(+), 79 deletions(-)
drivers/block/amiflop.c +46 -79
@@ -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 @@ static void redo_fd_request(void) "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 @@ static void redo_fd_request(void)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,18 +1769,32 @@ 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; +struct blk_mq_tag_set *set; disk =alloc_disk (1 );if (!disk) goto out; - disk->queue =blk_init_queue (do_fd_request, &amiflop_lock); + set = &unit[drive].tag_set; + set->ops = &amiflop_mq_ops; + set->nr_hw_queues =1 ; + set->queue_depth =2 ; + set->numa_node =NUMA_NO_NODE ; + set->flags =BLK_MQ_F_SHOULD_MERGE ; +if (blk_mq_alloc_tag_set (set)) + goto out_put_disk; + + disk->queue =blk_mq_init_queue (set);if (IS_ERR (disk->queue)) { disk->queue =NULL ; - goto out_put_disk; + goto out_free_tag_set; } unit[drive].trackbuf =kmalloc (FLOPPY_MAX_SECTORS *512 ,GFP_KERNEL );
@@ -1841,6 +1806,8 @@ static struct gendisk *fd_alloc_disk(int drive) out_cleanup_queue:blk_cleanup_queue (disk->queue); disk->queue =NULL ; +out_free_tag_set: +blk_mq_free_tag_set (set); out_put_disk:put_disk (disk); out:
Signature · 1 line
2.19.1
PATCH v2 8/11 ataflop: fold headers into C file
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
atafd.h and atafdreg.h are only used from ataflop.c, so merge them in there.
--- arch/m68k/include/asm/atafd.h | 13 ----- arch/m68k/include/asm/atafdreg.h | 80 ------------------------------ drivers/block/ataflop.c | 83 +++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 95 deletions(-) delete mode 100644 arch/m68k/include/asm/atafd.h delete mode 100644 arch/m68k/include/asm/atafdreg.h
arch/m68k/include/asm/atafd.h deleted +0 -13
@@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_M68K_FD_H -#define _ASM_M68K_FD_H - -/* Definitions for the Atari Floppy driver */ - -struct atari_format_descr { -int track;/* to be formatted */ -int head;/* "" "" */ -int sect_offset;/* offset of first sector */ -}; - -#endif
arch/m68k/include/asm/atafdreg.h deleted +0 -80
80 lines not on this page · raw message
drivers/block/ataflop.c +81 -2
95 lines not on this page · raw message
Signature · 1 line
2.19.1
PATCH v2 9/11 ataflop: fix error handling during setup
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
Move queue allocation next to disk allocation to fix a couple of issues:
- If add_disk() hasn't been called, we should clear disk->queue before calling put_disk().
- If we fail to allocate a request queue, we still need to put all of the disks, not just the ones that we allocated queues for.
--- drivers/block/ataflop.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
drivers/block/ataflop.c +15 -10
@@ -2014,6 +2014,11 @@ static int __init atari_floppy_init (void) unit[i].disk =alloc_disk (1 );if (!unit[i].disk) goto Enomem; + + unit[i].disk->queue =blk_init_queue (do_fd_request, + &ataflop_lock); +if (!unit[i].disk->queue) + goto Enomem; }if (UseTrackbuffer <0 )
@@ -2045,10 +2050,6 @@ static int __init atari_floppy_init (void)sprintf (unit[i].disk->disk_name,"fd%d" , i); unit[i].disk->fops = &floppy_fops; unit[i].disk->private_data = &unit[i]; - unit[i].disk->queue =blk_init_queue (do_fd_request, - &ataflop_lock); -if (!unit[i].disk->queue) - goto Enomem;set_capacity (unit[i].disk,MAX_DISK_SIZE *2 );add_disk (unit[i].disk); }
@@ -2063,13 +2064,17 @@ static int __init atari_floppy_init (void)return 0 ; Enomem: -while (i--) { -struct request_queue *q = unit[i].disk->queue; +do { +struct gendisk *disk = unit[i].disk; -put_disk (unit[i].disk); -if (q) -blk_cleanup_queue (q); - } +if (disk) { +if (disk->queue) { +blk_cleanup_queue (disk->queue); + disk->queue =NULL ; + } +put_disk (unit[i].disk); + } + }while (i--);unregister_blkdev (FLOPPY_MAJOR ,"fd" );return -ENOMEM ;
Signature · 1 line
2.19.1
PATCH v2 10/11 ataflop: convert to blk-mq
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
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.
--- drivers/block/ataflop.c | 183 ++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 102 deletions(-)
drivers/block/ataflop.c +81 -102
@@ -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 ; - -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); - -return rq; -} - +struct atari_floppy_struct *floppy = bd->rq->rq_disk->private_data; +int drive = floppy - unit; +int type = floppy->type; -static void redo_fd_request (void ) -{ -int drive, type; -struct atari_floppy_struct *floppy; +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); -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 @@ static void redo_fd_request(void)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 @@ static void redo_fd_request(void)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 :-) */
@@ -2011,14 +1972,30 @@ static int __init atari_floppy_init (void)return -EBUSY ;for (i =0 ; i <FD_MAX_UNITS ; i++) { +struct blk_mq_tag_set *set; + 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; + set = &unit[i].tag_set; + set->ops = &ataflop_mq_ops; + set->nr_hw_queues =1 ; + set->queue_depth =2 ; + set->numa_node =NUMA_NO_NODE ; + set->flags =BLK_MQ_F_SHOULD_MERGE ; + ret =blk_mq_alloc_tag_set (set); +if (ret) + goto err; + + unit[i].disk->queue =blk_mq_init_queue (set); +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 +2012,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 +2041,8 @@ static int __init atari_floppy_init (void)config_types ();return 0 ; -Enomem: + +err: do { struct gendisk *disk = unit[i].disk;
@@ -2072,12 +2051,13 @@ static int __init atari_floppy_init (void)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 +2104,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" );
Signature · 1 line
2.19.1
PATCH v2 11/11 floppy: convert to blk-mq
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
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.
--- drivers/block/floppy.c | 74 +++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 30 deletions(-)
drivers/block/floppy.c +44 -30
@@ -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); -if (current_req) { - current_req->error_count =0 ; -break ; - } - } - }while (fdc_queue != old_pos); - + current_req = list_first_entry_or_null(&floppy_reqs, struct request, + queuelist); +if (current_req) { + current_req->error_count =0 ; +list_del_init (¤t_req->queuelist); + }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)
@@ -4527,15 +4528,28 @@ static int __init do_floppy_init(void)return -ENOMEM ;for (drive =0 ; drive <N_DRIVE ; drive++) { +struct blk_mq_tag_set *set; + disks[drive] =alloc_disk (1 );if (!disks[drive]) { err = -ENOMEM ; goto out_put_disk; } - disks[drive]->queue =blk_init_queue (do_fd_request, &floppy_lock); -if (!disks[drive]->queue) { - err = -ENOMEM ; + set = &tag_sets[drive]; + set->ops = &floppy_mq_ops; + set->nr_hw_queues =1 ; + set->queue_depth =2 ; + set->numa_node =NUMA_NO_NODE ; + set->flags =BLK_MQ_F_SHOULD_MERGE ; + err =blk_mq_alloc_tag_set (set); +if (err) + goto out_put_disk; + + disks[drive]->queue =blk_mq_init_queue (set); +if (IS_ERR (disks[drive]->queue)) { + err =PTR_ERR (disks[drive]->queue); + disks[drive]->queue =NULL ; goto out_put_disk; }
Signature · 1 line
2.19.1
PATCH v2 5/11 amiflop: fold headers into C file
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
amifd.h and amifdreg.h are only used from amiflop.c, and they're pretty small, so move the contents to amiflop.c and get rid of the .h files. This is preparation for adding a struct blk_mq_tag_set to struct amiga_floppy_struct.
--- drivers/block/amiflop.c | 123 ++++++++++++++++++++++++++++++++++++++- include/linux/amifd.h | 63 -------------------- include/linux/amifdreg.h | 82 -------------------------- 3 files changed, 120 insertions(+), 148 deletions(-) delete mode 100644 include/linux/amifd.h delete mode 100644 include/linux/amifdreg.h
drivers/block/amiflop.c +120 -3
@@ -61,10 +61,8 @@#include <linux/delay.h> #include <linux/init.h> #include <linux/mutex.h> -#include <linux/amifdreg.h> -#include <linux/amifd.h> #include <linux/fs.h> -#include <linux/blkdev.h> +#include <linux/blk-mq.h> #include <linux/elevator.h> #include <linux/interrupt.h> #include <linux/platform_device.h>
@@ -86,6 +84,125 @@* Defines */ +/* +* CIAAPRA bits (read only) +*/ + +#define DSKRDY (0x1<<5)/* disk ready when low */ +#define DSKTRACK0 (0x1<<4)/* head at track zero when low */ +#define DSKPROT (0x1<<3)/* disk protected when low */ +#define DSKCHANGE (0x1<<2)/* low when disk removed */ + +/* +* CIAAPRB bits (read/write) +*/ + +#define DSKMOTOR (0x1<<7)/* motor on when low */ +#define DSKSEL3 (0x1<<6)/* select drive 3 when low */ +#define DSKSEL2 (0x1<<5)/* select drive 2 when low */ +#define DSKSEL1 (0x1<<4)/* select drive 1 when low */ +#define DSKSEL0 (0x1<<3)/* select drive 0 when low */ +#define DSKSIDE (0x1<<2)/* side selection: 0 = upper, 1 = lower */ +#define DSKDIREC (0x1<<1)/* step direction: 0=in, 1=out (to trk 0) */ +#define DSKSTEP (0x1)/* pulse low to step head 1 track */ + +/* +* DSKBYTR bits (read only) +*/ + +#define DSKBYT (1<<15)/* register contains valid byte when set */ +#define DMAON (1<<14)/* disk DMA enabled */ +#define DISKWRITE (1<<13)/* disk write bit in DSKLEN enabled */ +#define WORDEQUAL (1<<12)/* DSKSYNC register match when true */ +/* bits 7-0 are data */ + +/* +* ADKCON/ADKCONR bits +*/ + +#ifndef SETCLR +#define ADK_SETCLR (1<<15)/* control bit */ +#endif +#define ADK_PRECOMP1 (1<<14)/* precompensation selection */ +#define ADK_PRECOMP0 (1<<13)/* 00=none, 01=140ns, 10=280ns, 11=500ns */ +#define ADK_MFMPREC (1<<12)/* 0=GCR precomp., 1=MFM precomp. */ +#define ADK_WORDSYNC (1<<10)/* enable DSKSYNC auto DMA */ +#define ADK_MSBSYNC (1<<9)/* when 1, enable sync on MSbit (for GCR) */ +#define ADK_FAST (1<<8)/* bit cell: 0=2us (GCR), 1=1us (MFM) */ + +/* +* DSKLEN bits +*/ + +#define DSKLEN_DMAEN (1<<15) +#define DSKLEN_WRITE (1<<14) + +/* +* INTENA/INTREQ bits +*/ + +#define DSKINDEX (0x1<<4)/* DSKINDEX bit */ + +/* +* Misc +*/ + +#define MFM_SYNC 0x4489/* standard MFM sync value */ + +/* Values for FD_COMMAND */ +#define FD_RECALIBRATE 0x07/* move to track 0 */ +#define FD_SEEK 0x0F/* seek track */ +#define FD_READ 0xE6/* read with MT, MFM, SKip deleted */ +#define FD_WRITE 0xC5/* write with MT, MFM */ +#define FD_SENSEI 0x08/* Sense Interrupt Status */ +#define FD_SPECIFY 0x03/* specify HUT etc */ +#define FD_FORMAT 0x4D/* format one track */ +#define FD_VERSION 0x10/* get version code */ +#define FD_CONFIGURE 0x13/* configure FIFO operation */ +#define FD_PERPENDICULAR 0x12/* perpendicular r/w mode */ + +#define FD_MAX_UNITS 4/* Max. Number of drives */ +#define FLOPPY_MAX_SECTORS 22/* Max. Number of sectors per track */ + +struct fd_data_type { +char *name;/* description of data type */ +int sects;/* sectors per track */ +int (*read_fkt)(int );/* read whole track */ +void (*write_fkt)(int );/* write whole track */ +}; + +struct fd_drive_type { +unsigned long code;/* code returned from drive */ +char *name;/* description of drive */ +unsigned int tracks;/* number of tracks */ +unsigned int heads;/* number of heads */ +unsigned int read_size;/* raw read size for one track */ +unsigned int write_size;/* raw write size for one track */ +unsigned int sect_mult;/* sectors and gap multiplier (HD = 2) */ +unsigned int precomp1;/* start track for precomp 1 */ +unsigned int precomp2;/* start track for precomp 2 */ +unsigned int step_delay;/* time (in ms) for delay after step */ +unsigned int settle_time;/* time to settle after dir change */ +unsigned int side_time;/* time needed to change sides */ +}; + +struct amiga_floppy_struct { +struct fd_drive_type *type;/* type of floppy for this unit */ +struct fd_data_type *dtype;/* type of floppy for this unit */ +int track;/* current track (-1 == unknown) */ +unsigned char *trackbuf;/* current track (kmaloc()'d */ + +int blocks;/* total # blocks on disk */ + +int changed;/* true when not known */ +int disk;/* disk in drive (-1 == unknown) */ +int motor;/* true when motor is at speed */ +int busy;/* true when drive is active */ +int dirty;/* true when trackbuf is not on disk */ +int status;/* current error code for unit */ +struct gendisk *gendisk; +}; +/* * Error codes */
include/linux/amifd.h deleted +0 -63
63 lines not on this page · raw message
include/linux/amifdreg.h deleted +0 -82
82 lines not on this page · raw message
Signature · 1 line
2.19.1
Quoted 10 lines · Omar Sandoval
From: Omar Sandoval <[email protected]>
Hi,
This series converts the various floppy drivers to blk-mq. Save for the last one (floppy), they're compile-tested only. If I've Cc'd you, it's because I think you might be able to test the changes. Please test if you can, or let me know if there's a way to use QEMU/some other emulator to test. The full series is available at [1]. Thanks!
I built your mq-conversions branch (425e985d1937) and asked Stan to test this on his Centris 650. There are no regressions in the swim driver.
Quoted 41 lines
Changes from v1:
- Drop "swim3: end whole request on error" and "floppy: end whole request on error".
- Handle errors on individual bios correctly in the other drivers.Cc Benjamin Herrenschmidt <[email protected]>Cc Finn Thain <[email protected]>Cc Laurent Vivier <[email protected]>1: https://github.com/osandov/linux/tree/mq-conversions.
Omar Sandoval (11):
swim: fix cleanup on setup error
swim: convert to blk-mq
swim3: add real error handling in setup
swim3: convert to blk-mq
amiflop: fold headers into C file
amiflop: clean up on errors during setup
amiflop: convert to blk-mq
ataflop: fold headers into C file
ataflop: fix error handling during setup
ataflop: convert to blk-mq
floppy: convert to blk-mqarch/m68k/include/asm/atafd.h | 13 -- arch/m68k/include/asm/atafdreg.h | 80 -------- drivers/block/amiflop.c | 328 +++++++++++++++++++------------ drivers/block/ataflop.c | 283 +++++++++++++++----------- drivers/block/floppy.c | 74 ++++--- drivers/block/swim.c | 114 ++++++----- drivers/block/swim3.c | 219 ++++++++++----------- include/linux/amifd.h | 63 ------ include/linux/amifdreg.h | 82 -------- 9 files changed, 590 insertions(+), 666 deletions(-) delete mode 100644 arch/m68k/include/asm/atafd.h delete mode 100644 arch/m68k/include/asm/atafdreg.h delete mode 100644 include/linux/amifd.h delete mode 100644 include/linux/amifdreg.h
Re: [PATCH v2 02/11] swim: convert to blk-mq
In reply to Omar SandovalQuoted 7 lines · Omar Sandoval
From: Omar Sandoval <[email protected]>
The only interesting thing here is that there may be two floppies (i.e., request queues) sharing the same controller, so we use the global struct
swim_priv->lockto check whether the controller is busy. Compile-tested only.
Quoted 7 lines
Cc Finn Thain <[email protected]>Cc Laurent Vivier <[email protected]>Signed-off-by Omar Sandoval <[email protected]>--- drivers/block/swim.c | 101 +++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 52 deletions(-)
Quoted 13 lines · Finn Thain
Quoted 10 lines · Omar Sandoval
From: Omar Sandoval <[email protected]>
Hi,
This series converts the various floppy drivers to blk-mq. Save for the last one (floppy), they're compile-tested only. If I've Cc'd you, it's because I think you might be able to test the changes. Please test if you can, or let me know if there's a way to use QEMU/some other emulator to test. The full series is available at [1]. Thanks!
Quoted 2 lines
I built your mq-conversions branch (
425e985d1937) and asked Stan to test this on his Centris 650. There are no regressions in the swim driver.
Thanks for testing :) I'm pretty impressed that it's still possible to run Linux on those at all.