Convert floppy drivers to blk-mq
Subsystems (3)
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!
1: https://github.com/osandov/linux/tree/mq-conversions.
Omar Sandoval (13):
swim: fix cleanup on setup error
swim: convert to blk-mq
swim3: add real error handling in setup
swim3: end whole request on error
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: end whole request on error
floppy: convert to blk-mq
arch/m68k/include/asm/atafd.h | 13 -- arch/m68k/include/asm/atafdreg.h | 80 -------- drivers/block/amiflop.c | 330 +++++++++++++++++++------------ drivers/block/ataflop.c | 288 ++++++++++++++++----------- drivers/block/floppy.c | 80 +++++--- drivers/block/swim.c | 116 ++++++----- drivers/block/swim3.c | 221 +++++++++++---------- include/linux/amifd.h | 63 ------ include/linux/amifdreg.h | 82 -------- 9 files changed, 604 insertions(+), 669 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 1/13 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 2/13 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 | 103 +++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 52 deletions(-)
drivers/block/swim.c +51 -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,38 @@ 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)); +if (err) +break ; + }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 +803,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 +836,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 +892,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 +968,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 3/13 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 4/13 swim3: end whole request on error
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
When swim3_end_request() gets passed an error, it seems that the intent is to end the whole request, but we're only ending the current segment.
--- drivers/block/swim3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/block/swim3.c +1 -1
@@ -266,7 +266,7 @@ static bool swim3_end_request(struct floppy_state *fs, blk_status_t err, unsigne err, nr_bytes, req);if (err) - nr_bytes =blk_rq_cur_bytes (req); + nr_bytes =blk_rq_bytes (req); rc =__blk_end_request (req, err, nr_bytes);if (rc)return true;
Signature · 1 line
2.19.1
PATCH 5/13 swim3: convert to blk-mq
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
Pretty simple conversion. To avoid extra churn, we keep the swim3_end_request() wrapper. 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_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 6/13 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
PATCH 7/13 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 8/13 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 | 127 +++++++++++++++------------------------- 1 file changed, 48 insertions(+), 79 deletions(-)
drivers/block/amiflop.c +48 -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 ) +static blk_status_t amiflop_rw_cur_segment (struct amiga_floppy_struct *floppy, +struct request *rq) { -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 ) -{ -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,42 @@ 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); +if (err) +break ; + }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 +1771,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 +1808,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 9/13 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 10/13 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 11/13 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 | 188 ++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 102 deletions(-)
drivers/block/ataflop.c +86 -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,16 @@ 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 (err) { +blk_mq_end_request (fd_request, err); +return ; + } + +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 +710,6 @@ static void fd_error( void )if (SelectedDrive !=-1 )SUD .track =-1 ; } -redo_fd_request (); }
@@ -724,14 +727,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 +744,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 +792,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 +826,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 +1230,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 +1387,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 +1476,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 +1519,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 +1542,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 +1626,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 +1693,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 +1950,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 +1967,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 +1977,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 +2017,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 +2046,8 @@ static int __init atari_floppy_init (void)config_types ();return 0 ; -Enomem: + +err: do { struct gendisk *disk = unit[i].disk;
@@ -2072,12 +2056,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 +2109,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 12/13 floppy: end whole request on error
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
If floppy_end_request() gets passed an error, it should end the whole request, not just the current segment.
--- drivers/block/floppy.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/block/floppy.c +5 -3
@@ -2210,13 +2210,15 @@ static int do_format(int drive, struct format_descr *tmp_format_req)static void floppy_end_request (struct request *req,blk_status_t error) { -unsigned int nr_sectors = current_count_sectors; +unsigned int nr_bytes;unsigned int drive = (unsigned long )req->rq_disk->private_data;/* 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 )) + nr_bytes =blk_rq_bytes (req); +else + nr_bytes = current_count_sectors <<9 ; +if (__blk_end_request (req, error, nr_bytes))return ;/* We're done with the request */
Signature · 1 line
2.19.1
Jens Axboe
maintainerRe: [PATCH 12/13] floppy: end whole request on error
Quoted 4 lines · Omar Sandoval
From: Omar Sandoval <[email protected]>
If
floppy_end_request()gets passed an error, it should end the whole request, not just the current segment.
I don't think this is correct, we should still just end the individual chunks.
Signature · 1 line
Jens Axboe
Re: [PATCH 12/13] floppy: end whole request on error
Quoted 8 lines · Jens Axboe
Quoted 4 lines · Omar Sandoval
From: Omar Sandoval <[email protected]>
If
floppy_end_request()gets passed an error, it should end the whole request, not just the current segment.I don't think this is correct, we should still just end the individual chunks.
Yup, I'll drop this and the swim3 equivalent, thanks.
PATCH 13/13 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.
@@ -2218,8 +2218,9 @@ static void floppy_end_request(struct request *req, blk_status_t error) nr_bytes =blk_rq_bytes (req); else nr_bytes = current_count_sectors <<9 ; -if (__blk_end_request (req, error, nr_bytes)) +if (blk_update_request (req, error, nr_bytes))return ; +__blk_mq_end_request (req, error);/* We're done with the request */ floppy_off (drive);
@@ -2799,27 +2800,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 ; }
@@ -2903,29 +2891,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 = {
@@ -4488,6 +4485,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)
@@ -4529,15 +4530,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