.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Driver for SWIM (Sander Woz Integrated Machine) floppy controller |
---|
3 | 4 | * |
---|
.. | .. |
---|
7 | 8 | * based on SWIM3 driver (c) Paul Mackerras, 1996 |
---|
8 | 9 | * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath. |
---|
9 | 10 | * |
---|
10 | | - * This program is free software; you can redistribute it and/or |
---|
11 | | - * modify it under the terms of the GNU General Public License |
---|
12 | | - * as published by the Free Software Foundation; either version |
---|
13 | | - * 2 of the License, or (at your option) any later version. |
---|
14 | | - * |
---|
15 | 11 | * 2004-08-21 (lv) - Initial implementation |
---|
16 | 12 | * 2008-10-30 (lv) - Port to 2.6 |
---|
17 | 13 | */ |
---|
.. | .. |
---|
19 | 15 | #include <linux/module.h> |
---|
20 | 16 | #include <linux/fd.h> |
---|
21 | 17 | #include <linux/slab.h> |
---|
22 | | -#include <linux/blkdev.h> |
---|
| 18 | +#include <linux/blk-mq.h> |
---|
23 | 19 | #include <linux/mutex.h> |
---|
24 | 20 | #include <linux/hdreg.h> |
---|
25 | 21 | #include <linux/kernel.h> |
---|
.. | .. |
---|
190 | 186 | int ref_count; |
---|
191 | 187 | |
---|
192 | 188 | struct gendisk *disk; |
---|
| 189 | + struct blk_mq_tag_set tag_set; |
---|
193 | 190 | |
---|
194 | 191 | /* parent controller */ |
---|
195 | 192 | |
---|
.. | .. |
---|
211 | 208 | struct swim_priv { |
---|
212 | 209 | struct swim __iomem *base; |
---|
213 | 210 | spinlock_t lock; |
---|
214 | | - int fdc_queue; |
---|
215 | 211 | int floppy_count; |
---|
216 | 212 | struct floppy_state unit[FD_MAX_UNIT]; |
---|
217 | 213 | }; |
---|
.. | .. |
---|
331 | 327 | swim_select(base, RELAX); |
---|
332 | 328 | if (swim_readbit(base, MOTOR_ON)) |
---|
333 | 329 | break; |
---|
334 | | - current->state = TASK_INTERRUPTIBLE; |
---|
| 330 | + set_current_state(TASK_INTERRUPTIBLE); |
---|
335 | 331 | schedule_timeout(1); |
---|
336 | 332 | } |
---|
337 | 333 | } else if (action == OFF) { |
---|
.. | .. |
---|
350 | 346 | swim_select(base, RELAX); |
---|
351 | 347 | if (!swim_readbit(base, DISK_IN)) |
---|
352 | 348 | break; |
---|
353 | | - current->state = TASK_INTERRUPTIBLE; |
---|
| 349 | + set_current_state(TASK_INTERRUPTIBLE); |
---|
354 | 350 | schedule_timeout(1); |
---|
355 | 351 | } |
---|
356 | 352 | swim_select(base, RELAX); |
---|
.. | .. |
---|
374 | 370 | |
---|
375 | 371 | for (wait = 0; wait < HZ; wait++) { |
---|
376 | 372 | |
---|
377 | | - current->state = TASK_INTERRUPTIBLE; |
---|
| 373 | + set_current_state(TASK_INTERRUPTIBLE); |
---|
378 | 374 | schedule_timeout(1); |
---|
379 | 375 | |
---|
380 | 376 | swim_select(base, RELAX); |
---|
.. | .. |
---|
525 | 521 | return 0; |
---|
526 | 522 | } |
---|
527 | 523 | |
---|
528 | | -static struct request *swim_next_request(struct swim_priv *swd) |
---|
| 524 | +static blk_status_t swim_queue_rq(struct blk_mq_hw_ctx *hctx, |
---|
| 525 | + const struct blk_mq_queue_data *bd) |
---|
529 | 526 | { |
---|
530 | | - struct request_queue *q; |
---|
531 | | - struct request *rq; |
---|
532 | | - int old_pos = swd->fdc_queue; |
---|
| 527 | + struct floppy_state *fs = hctx->queue->queuedata; |
---|
| 528 | + struct swim_priv *swd = fs->swd; |
---|
| 529 | + struct request *req = bd->rq; |
---|
| 530 | + blk_status_t err; |
---|
| 531 | + |
---|
| 532 | + if (!spin_trylock_irq(&swd->lock)) |
---|
| 533 | + return BLK_STS_DEV_RESOURCE; |
---|
| 534 | + |
---|
| 535 | + blk_mq_start_request(req); |
---|
| 536 | + |
---|
| 537 | + if (!fs->disk_in || rq_data_dir(req) == WRITE) { |
---|
| 538 | + err = BLK_STS_IOERR; |
---|
| 539 | + goto out; |
---|
| 540 | + } |
---|
533 | 541 | |
---|
534 | 542 | do { |
---|
535 | | - q = swd->unit[swd->fdc_queue].disk->queue; |
---|
536 | | - if (++swd->fdc_queue == swd->floppy_count) |
---|
537 | | - swd->fdc_queue = 0; |
---|
538 | | - if (q) { |
---|
539 | | - rq = blk_fetch_request(q); |
---|
540 | | - if (rq) |
---|
541 | | - return rq; |
---|
542 | | - } |
---|
543 | | - } while (swd->fdc_queue != old_pos); |
---|
| 543 | + err = floppy_read_sectors(fs, blk_rq_pos(req), |
---|
| 544 | + blk_rq_cur_sectors(req), |
---|
| 545 | + bio_data(req->bio)); |
---|
| 546 | + } while (blk_update_request(req, err, blk_rq_cur_bytes(req))); |
---|
| 547 | + __blk_mq_end_request(req, err); |
---|
544 | 548 | |
---|
545 | | - return NULL; |
---|
546 | | -} |
---|
| 549 | + err = BLK_STS_OK; |
---|
| 550 | +out: |
---|
| 551 | + spin_unlock_irq(&swd->lock); |
---|
| 552 | + return err; |
---|
547 | 553 | |
---|
548 | | -static void do_fd_request(struct request_queue *q) |
---|
549 | | -{ |
---|
550 | | - struct swim_priv *swd = q->queuedata; |
---|
551 | | - struct request *req; |
---|
552 | | - struct floppy_state *fs; |
---|
553 | | - |
---|
554 | | - req = swim_next_request(swd); |
---|
555 | | - while (req) { |
---|
556 | | - blk_status_t err = BLK_STS_IOERR; |
---|
557 | | - |
---|
558 | | - fs = req->rq_disk->private_data; |
---|
559 | | - if (blk_rq_pos(req) >= fs->total_secs) |
---|
560 | | - goto done; |
---|
561 | | - if (!fs->disk_in) |
---|
562 | | - goto done; |
---|
563 | | - if (rq_data_dir(req) == WRITE && fs->write_protected) |
---|
564 | | - goto done; |
---|
565 | | - |
---|
566 | | - switch (rq_data_dir(req)) { |
---|
567 | | - case WRITE: |
---|
568 | | - /* NOT IMPLEMENTED */ |
---|
569 | | - break; |
---|
570 | | - case READ: |
---|
571 | | - err = floppy_read_sectors(fs, blk_rq_pos(req), |
---|
572 | | - blk_rq_cur_sectors(req), |
---|
573 | | - bio_data(req->bio)); |
---|
574 | | - break; |
---|
575 | | - } |
---|
576 | | - done: |
---|
577 | | - if (!__blk_end_request_cur(req, err)) |
---|
578 | | - req = swim_next_request(swd); |
---|
579 | | - } |
---|
580 | 554 | } |
---|
581 | 555 | |
---|
582 | 556 | static struct floppy_struct floppy_type[4] = { |
---|
.. | .. |
---|
664 | 638 | return 0; |
---|
665 | 639 | |
---|
666 | 640 | if (mode & (FMODE_READ|FMODE_WRITE)) { |
---|
667 | | - check_disk_change(bdev); |
---|
| 641 | + if (bdev_check_media_change(bdev) && fs->disk_in) |
---|
| 642 | + fs->ejected = 0; |
---|
668 | 643 | if ((mode & FMODE_WRITE) && fs->write_protected) { |
---|
669 | 644 | err = -EROFS; |
---|
670 | 645 | goto out; |
---|
.. | .. |
---|
761 | 736 | return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0; |
---|
762 | 737 | } |
---|
763 | 738 | |
---|
764 | | -static int floppy_revalidate(struct gendisk *disk) |
---|
765 | | -{ |
---|
766 | | - struct floppy_state *fs = disk->private_data; |
---|
767 | | - struct swim __iomem *base = fs->swd->base; |
---|
768 | | - |
---|
769 | | - swim_drive(base, fs->location); |
---|
770 | | - |
---|
771 | | - if (fs->ejected) |
---|
772 | | - setup_medium(fs); |
---|
773 | | - |
---|
774 | | - if (!fs->disk_in) |
---|
775 | | - swim_motor(base, OFF); |
---|
776 | | - else |
---|
777 | | - fs->ejected = 0; |
---|
778 | | - |
---|
779 | | - return !fs->disk_in; |
---|
780 | | -} |
---|
781 | | - |
---|
782 | 739 | static const struct block_device_operations floppy_fops = { |
---|
783 | 740 | .owner = THIS_MODULE, |
---|
784 | 741 | .open = floppy_unlocked_open, |
---|
.. | .. |
---|
786 | 743 | .ioctl = floppy_ioctl, |
---|
787 | 744 | .getgeo = floppy_getgeo, |
---|
788 | 745 | .check_events = floppy_check_events, |
---|
789 | | - .revalidate_disk = floppy_revalidate, |
---|
790 | 746 | }; |
---|
791 | 747 | |
---|
792 | 748 | static struct kobject *floppy_find(dev_t dev, int *part, void *data) |
---|
.. | .. |
---|
823 | 779 | return 0; |
---|
824 | 780 | } |
---|
825 | 781 | |
---|
| 782 | +static const struct blk_mq_ops swim_mq_ops = { |
---|
| 783 | + .queue_rq = swim_queue_rq, |
---|
| 784 | +}; |
---|
| 785 | + |
---|
826 | 786 | static int swim_floppy_init(struct swim_priv *swd) |
---|
827 | 787 | { |
---|
828 | 788 | int err; |
---|
.. | .. |
---|
852 | 812 | spin_lock_init(&swd->lock); |
---|
853 | 813 | |
---|
854 | 814 | for (drive = 0; drive < swd->floppy_count; drive++) { |
---|
| 815 | + struct request_queue *q; |
---|
| 816 | + |
---|
855 | 817 | swd->unit[drive].disk = alloc_disk(1); |
---|
856 | 818 | if (swd->unit[drive].disk == NULL) { |
---|
857 | 819 | err = -ENOMEM; |
---|
858 | 820 | goto exit_put_disks; |
---|
859 | 821 | } |
---|
860 | | - swd->unit[drive].disk->queue = blk_init_queue(do_fd_request, |
---|
861 | | - &swd->lock); |
---|
862 | | - if (!swd->unit[drive].disk->queue) { |
---|
863 | | - err = -ENOMEM; |
---|
| 822 | + |
---|
| 823 | + q = blk_mq_init_sq_queue(&swd->unit[drive].tag_set, &swim_mq_ops, |
---|
| 824 | + 2, BLK_MQ_F_SHOULD_MERGE); |
---|
| 825 | + if (IS_ERR(q)) { |
---|
| 826 | + err = PTR_ERR(q); |
---|
864 | 827 | goto exit_put_disks; |
---|
865 | 828 | } |
---|
| 829 | + |
---|
| 830 | + swd->unit[drive].disk->queue = q; |
---|
866 | 831 | blk_queue_bounce_limit(swd->unit[drive].disk->queue, |
---|
867 | 832 | BLK_BOUNCE_HIGH); |
---|
868 | | - swd->unit[drive].disk->queue->queuedata = swd; |
---|
| 833 | + swd->unit[drive].disk->queue->queuedata = &swd->unit[drive]; |
---|
869 | 834 | swd->unit[drive].swd = swd; |
---|
870 | 835 | } |
---|
871 | 836 | |
---|
.. | .. |
---|
875 | 840 | swd->unit[drive].disk->first_minor = drive; |
---|
876 | 841 | sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive); |
---|
877 | 842 | swd->unit[drive].disk->fops = &floppy_fops; |
---|
| 843 | + swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE; |
---|
878 | 844 | swd->unit[drive].disk->private_data = &swd->unit[drive]; |
---|
879 | 845 | set_capacity(swd->unit[drive].disk, 2880); |
---|
880 | 846 | add_disk(swd->unit[drive].disk); |
---|
.. | .. |
---|
895 | 861 | blk_cleanup_queue(disk->queue); |
---|
896 | 862 | disk->queue = NULL; |
---|
897 | 863 | } |
---|
| 864 | + blk_mq_free_tag_set(&swd->unit[drive].tag_set); |
---|
898 | 865 | put_disk(disk); |
---|
899 | 866 | } |
---|
900 | 867 | } while (drive--); |
---|
.. | .. |
---|
970 | 937 | for (drive = 0; drive < swd->floppy_count; drive++) { |
---|
971 | 938 | del_gendisk(swd->unit[drive].disk); |
---|
972 | 939 | blk_cleanup_queue(swd->unit[drive].disk->queue); |
---|
| 940 | + blk_mq_free_tag_set(&swd->unit[drive].tag_set); |
---|
973 | 941 | put_disk(swd->unit[drive].disk); |
---|
974 | 942 | } |
---|
975 | 943 | |
---|