| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* GD ROM driver for the SEGA Dreamcast |
|---|
| 2 | 3 | * copyright Adrian McMenamin, 2007 |
|---|
| 3 | 4 | * With thanks to Marcus Comstedt and Nathan Keynes |
|---|
| 4 | 5 | * for work in reversing PIO and DMA |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 8 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 9 | | - * (at your option) any later version. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | | - * |
|---|
| 16 | | - * You should have received a copy of the GNU General Public License along |
|---|
| 17 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 18 | | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|---|
| 19 | | - * |
|---|
| 20 | 6 | */ |
|---|
| 21 | 7 | |
|---|
| 22 | 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 31 | 17 | #include <linux/cdrom.h> |
|---|
| 32 | 18 | #include <linux/genhd.h> |
|---|
| 33 | 19 | #include <linux/bio.h> |
|---|
| 34 | | -#include <linux/blkdev.h> |
|---|
| 20 | +#include <linux/blk-mq.h> |
|---|
| 35 | 21 | #include <linux/interrupt.h> |
|---|
| 36 | 22 | #include <linux/device.h> |
|---|
| 37 | 23 | #include <linux/mutex.h> |
|---|
| 38 | 24 | #include <linux/wait.h> |
|---|
| 39 | | -#include <linux/workqueue.h> |
|---|
| 40 | 25 | #include <linux/platform_device.h> |
|---|
| 41 | 26 | #include <scsi/scsi.h> |
|---|
| 42 | 27 | #include <asm/io.h> |
|---|
| .. | .. |
|---|
| 102 | 87 | static DECLARE_WAIT_QUEUE_HEAD(command_queue); |
|---|
| 103 | 88 | static DECLARE_WAIT_QUEUE_HEAD(request_queue); |
|---|
| 104 | 89 | |
|---|
| 105 | | -static DEFINE_SPINLOCK(gdrom_lock); |
|---|
| 106 | | -static void gdrom_readdisk_dma(struct work_struct *work); |
|---|
| 107 | | -static DECLARE_WORK(work, gdrom_readdisk_dma); |
|---|
| 108 | | -static LIST_HEAD(gdrom_deferred); |
|---|
| 109 | | - |
|---|
| 110 | 90 | struct gdromtoc { |
|---|
| 111 | 91 | unsigned int entry[99]; |
|---|
| 112 | 92 | unsigned int first, last; |
|---|
| .. | .. |
|---|
| 122 | 102 | char disk_type; |
|---|
| 123 | 103 | struct gdromtoc *toc; |
|---|
| 124 | 104 | struct request_queue *gdrom_rq; |
|---|
| 105 | + struct blk_mq_tag_set tag_set; |
|---|
| 125 | 106 | } gd; |
|---|
| 126 | 107 | |
|---|
| 127 | 108 | struct gdrom_id { |
|---|
| .. | .. |
|---|
| 332 | 313 | static int gdrom_get_last_session(struct cdrom_device_info *cd_info, |
|---|
| 333 | 314 | struct cdrom_multisession *ms_info) |
|---|
| 334 | 315 | { |
|---|
| 335 | | - int fentry, lentry, track, data, tocuse, err; |
|---|
| 316 | + int fentry, lentry, track, data, err; |
|---|
| 317 | + |
|---|
| 336 | 318 | if (!gd.toc) |
|---|
| 337 | 319 | return -ENOMEM; |
|---|
| 338 | | - tocuse = 1; |
|---|
| 320 | + |
|---|
| 339 | 321 | /* Check if GD-ROM */ |
|---|
| 340 | 322 | err = gdrom_readtoc_cmd(gd.toc, 1); |
|---|
| 341 | 323 | /* Not a GD-ROM so check if standard CD-ROM */ |
|---|
| 342 | 324 | if (err) { |
|---|
| 343 | | - tocuse = 0; |
|---|
| 344 | 325 | err = gdrom_readtoc_cmd(gd.toc, 0); |
|---|
| 345 | 326 | if (err) { |
|---|
| 346 | 327 | pr_info("Could not get CD table of contents\n"); |
|---|
| .. | .. |
|---|
| 498 | 479 | { |
|---|
| 499 | 480 | int ret; |
|---|
| 500 | 481 | |
|---|
| 501 | | - check_disk_change(bdev); |
|---|
| 482 | + bdev_check_media_change(bdev); |
|---|
| 502 | 483 | |
|---|
| 503 | 484 | mutex_lock(&gdrom_mutex); |
|---|
| 504 | 485 | ret = cdrom_open(gd.cd_info, bdev, mode); |
|---|
| .. | .. |
|---|
| 537 | 518 | .release = gdrom_bdops_release, |
|---|
| 538 | 519 | .check_events = gdrom_bdops_check_events, |
|---|
| 539 | 520 | .ioctl = gdrom_bdops_ioctl, |
|---|
| 521 | +#ifdef CONFIG_COMPAT |
|---|
| 522 | + .compat_ioctl = blkdev_compat_ptr_ioctl, |
|---|
| 523 | +#endif |
|---|
| 540 | 524 | }; |
|---|
| 541 | 525 | |
|---|
| 542 | 526 | static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id) |
|---|
| .. | .. |
|---|
| 584 | 568 | * 9 -> sectors >> 8 |
|---|
| 585 | 569 | * 10 -> sectors |
|---|
| 586 | 570 | */ |
|---|
| 587 | | -static void gdrom_readdisk_dma(struct work_struct *work) |
|---|
| 571 | +static blk_status_t gdrom_readdisk_dma(struct request *req) |
|---|
| 588 | 572 | { |
|---|
| 589 | 573 | int block, block_cnt; |
|---|
| 590 | 574 | blk_status_t err; |
|---|
| 591 | 575 | struct packet_command *read_command; |
|---|
| 592 | | - struct list_head *elem, *next; |
|---|
| 593 | | - struct request *req; |
|---|
| 594 | 576 | unsigned long timeout; |
|---|
| 595 | 577 | |
|---|
| 596 | | - if (list_empty(&gdrom_deferred)) |
|---|
| 597 | | - return; |
|---|
| 598 | 578 | read_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL); |
|---|
| 599 | 579 | if (!read_command) |
|---|
| 600 | | - return; /* get more memory later? */ |
|---|
| 580 | + return BLK_STS_RESOURCE; |
|---|
| 581 | + |
|---|
| 601 | 582 | read_command->cmd[0] = 0x30; |
|---|
| 602 | 583 | read_command->cmd[1] = 0x20; |
|---|
| 603 | | - spin_lock(&gdrom_lock); |
|---|
| 604 | | - list_for_each_safe(elem, next, &gdrom_deferred) { |
|---|
| 605 | | - req = list_entry(elem, struct request, queuelist); |
|---|
| 606 | | - spin_unlock(&gdrom_lock); |
|---|
| 607 | | - block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET; |
|---|
| 608 | | - block_cnt = blk_rq_sectors(req)/GD_TO_BLK; |
|---|
| 609 | | - __raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG); |
|---|
| 610 | | - __raw_writel(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); |
|---|
| 611 | | - __raw_writel(1, GDROM_DMA_DIRECTION_REG); |
|---|
| 612 | | - __raw_writel(1, GDROM_DMA_ENABLE_REG); |
|---|
| 613 | | - read_command->cmd[2] = (block >> 16) & 0xFF; |
|---|
| 614 | | - read_command->cmd[3] = (block >> 8) & 0xFF; |
|---|
| 615 | | - read_command->cmd[4] = block & 0xFF; |
|---|
| 616 | | - read_command->cmd[8] = (block_cnt >> 16) & 0xFF; |
|---|
| 617 | | - read_command->cmd[9] = (block_cnt >> 8) & 0xFF; |
|---|
| 618 | | - read_command->cmd[10] = block_cnt & 0xFF; |
|---|
| 619 | | - /* set for DMA */ |
|---|
| 620 | | - __raw_writeb(1, GDROM_ERROR_REG); |
|---|
| 621 | | - /* other registers */ |
|---|
| 622 | | - __raw_writeb(0, GDROM_SECNUM_REG); |
|---|
| 623 | | - __raw_writeb(0, GDROM_BCL_REG); |
|---|
| 624 | | - __raw_writeb(0, GDROM_BCH_REG); |
|---|
| 625 | | - __raw_writeb(0, GDROM_DSEL_REG); |
|---|
| 626 | | - __raw_writeb(0, GDROM_INTSEC_REG); |
|---|
| 627 | | - /* Wait for registers to reset after any previous activity */ |
|---|
| 628 | | - timeout = jiffies + HZ / 2; |
|---|
| 629 | | - while (gdrom_is_busy() && time_before(jiffies, timeout)) |
|---|
| 630 | | - cpu_relax(); |
|---|
| 631 | | - __raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG); |
|---|
| 632 | | - timeout = jiffies + HZ / 2; |
|---|
| 633 | | - /* Wait for packet command to finish */ |
|---|
| 634 | | - while (gdrom_is_busy() && time_before(jiffies, timeout)) |
|---|
| 635 | | - cpu_relax(); |
|---|
| 636 | | - gd.pending = 1; |
|---|
| 637 | | - gd.transfer = 1; |
|---|
| 638 | | - outsw(GDROM_DATA_REG, &read_command->cmd, 6); |
|---|
| 639 | | - timeout = jiffies + HZ / 2; |
|---|
| 640 | | - /* Wait for any pending DMA to finish */ |
|---|
| 641 | | - while (__raw_readb(GDROM_DMA_STATUS_REG) && |
|---|
| 642 | | - time_before(jiffies, timeout)) |
|---|
| 643 | | - cpu_relax(); |
|---|
| 644 | | - /* start transfer */ |
|---|
| 645 | | - __raw_writeb(1, GDROM_DMA_STATUS_REG); |
|---|
| 646 | | - wait_event_interruptible_timeout(request_queue, |
|---|
| 647 | | - gd.transfer == 0, GDROM_DEFAULT_TIMEOUT); |
|---|
| 648 | | - err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK; |
|---|
| 649 | | - gd.transfer = 0; |
|---|
| 650 | | - gd.pending = 0; |
|---|
| 651 | | - /* now seek to take the request spinlock |
|---|
| 652 | | - * before handling ending the request */ |
|---|
| 653 | | - spin_lock(&gdrom_lock); |
|---|
| 654 | | - list_del_init(&req->queuelist); |
|---|
| 655 | | - __blk_end_request_all(req, err); |
|---|
| 656 | | - } |
|---|
| 657 | | - spin_unlock(&gdrom_lock); |
|---|
| 584 | + block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET; |
|---|
| 585 | + block_cnt = blk_rq_sectors(req)/GD_TO_BLK; |
|---|
| 586 | + __raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG); |
|---|
| 587 | + __raw_writel(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); |
|---|
| 588 | + __raw_writel(1, GDROM_DMA_DIRECTION_REG); |
|---|
| 589 | + __raw_writel(1, GDROM_DMA_ENABLE_REG); |
|---|
| 590 | + read_command->cmd[2] = (block >> 16) & 0xFF; |
|---|
| 591 | + read_command->cmd[3] = (block >> 8) & 0xFF; |
|---|
| 592 | + read_command->cmd[4] = block & 0xFF; |
|---|
| 593 | + read_command->cmd[8] = (block_cnt >> 16) & 0xFF; |
|---|
| 594 | + read_command->cmd[9] = (block_cnt >> 8) & 0xFF; |
|---|
| 595 | + read_command->cmd[10] = block_cnt & 0xFF; |
|---|
| 596 | + /* set for DMA */ |
|---|
| 597 | + __raw_writeb(1, GDROM_ERROR_REG); |
|---|
| 598 | + /* other registers */ |
|---|
| 599 | + __raw_writeb(0, GDROM_SECNUM_REG); |
|---|
| 600 | + __raw_writeb(0, GDROM_BCL_REG); |
|---|
| 601 | + __raw_writeb(0, GDROM_BCH_REG); |
|---|
| 602 | + __raw_writeb(0, GDROM_DSEL_REG); |
|---|
| 603 | + __raw_writeb(0, GDROM_INTSEC_REG); |
|---|
| 604 | + /* Wait for registers to reset after any previous activity */ |
|---|
| 605 | + timeout = jiffies + HZ / 2; |
|---|
| 606 | + while (gdrom_is_busy() && time_before(jiffies, timeout)) |
|---|
| 607 | + cpu_relax(); |
|---|
| 608 | + __raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG); |
|---|
| 609 | + timeout = jiffies + HZ / 2; |
|---|
| 610 | + /* Wait for packet command to finish */ |
|---|
| 611 | + while (gdrom_is_busy() && time_before(jiffies, timeout)) |
|---|
| 612 | + cpu_relax(); |
|---|
| 613 | + gd.pending = 1; |
|---|
| 614 | + gd.transfer = 1; |
|---|
| 615 | + outsw(GDROM_DATA_REG, &read_command->cmd, 6); |
|---|
| 616 | + timeout = jiffies + HZ / 2; |
|---|
| 617 | + /* Wait for any pending DMA to finish */ |
|---|
| 618 | + while (__raw_readb(GDROM_DMA_STATUS_REG) && |
|---|
| 619 | + time_before(jiffies, timeout)) |
|---|
| 620 | + cpu_relax(); |
|---|
| 621 | + /* start transfer */ |
|---|
| 622 | + __raw_writeb(1, GDROM_DMA_STATUS_REG); |
|---|
| 623 | + wait_event_interruptible_timeout(request_queue, |
|---|
| 624 | + gd.transfer == 0, GDROM_DEFAULT_TIMEOUT); |
|---|
| 625 | + err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK; |
|---|
| 626 | + gd.transfer = 0; |
|---|
| 627 | + gd.pending = 0; |
|---|
| 628 | + |
|---|
| 629 | + blk_mq_end_request(req, err); |
|---|
| 658 | 630 | kfree(read_command); |
|---|
| 631 | + return BLK_STS_OK; |
|---|
| 659 | 632 | } |
|---|
| 660 | 633 | |
|---|
| 661 | | -static void gdrom_request(struct request_queue *rq) |
|---|
| 634 | +static blk_status_t gdrom_queue_rq(struct blk_mq_hw_ctx *hctx, |
|---|
| 635 | + const struct blk_mq_queue_data *bd) |
|---|
| 662 | 636 | { |
|---|
| 663 | | - struct request *req; |
|---|
| 637 | + blk_mq_start_request(bd->rq); |
|---|
| 664 | 638 | |
|---|
| 665 | | - while ((req = blk_fetch_request(rq)) != NULL) { |
|---|
| 666 | | - switch (req_op(req)) { |
|---|
| 667 | | - case REQ_OP_READ: |
|---|
| 668 | | - /* |
|---|
| 669 | | - * Add to list of deferred work and then schedule |
|---|
| 670 | | - * workqueue. |
|---|
| 671 | | - */ |
|---|
| 672 | | - list_add_tail(&req->queuelist, &gdrom_deferred); |
|---|
| 673 | | - schedule_work(&work); |
|---|
| 674 | | - break; |
|---|
| 675 | | - case REQ_OP_WRITE: |
|---|
| 676 | | - pr_notice("Read only device - write request ignored\n"); |
|---|
| 677 | | - __blk_end_request_all(req, BLK_STS_IOERR); |
|---|
| 678 | | - break; |
|---|
| 679 | | - default: |
|---|
| 680 | | - printk(KERN_DEBUG "gdrom: Non-fs request ignored\n"); |
|---|
| 681 | | - __blk_end_request_all(req, BLK_STS_IOERR); |
|---|
| 682 | | - break; |
|---|
| 683 | | - } |
|---|
| 639 | + switch (req_op(bd->rq)) { |
|---|
| 640 | + case REQ_OP_READ: |
|---|
| 641 | + return gdrom_readdisk_dma(bd->rq); |
|---|
| 642 | + case REQ_OP_WRITE: |
|---|
| 643 | + pr_notice("Read only device - write request ignored\n"); |
|---|
| 644 | + return BLK_STS_IOERR; |
|---|
| 645 | + default: |
|---|
| 646 | + printk(KERN_DEBUG "gdrom: Non-fs request ignored\n"); |
|---|
| 647 | + return BLK_STS_IOERR; |
|---|
| 684 | 648 | } |
|---|
| 685 | 649 | } |
|---|
| 686 | 650 | |
|---|
| .. | .. |
|---|
| 768 | 732 | return gdrom_init_dma_mode(); |
|---|
| 769 | 733 | } |
|---|
| 770 | 734 | |
|---|
| 735 | +static const struct blk_mq_ops gdrom_mq_ops = { |
|---|
| 736 | + .queue_rq = gdrom_queue_rq, |
|---|
| 737 | +}; |
|---|
| 738 | + |
|---|
| 771 | 739 | /* |
|---|
| 772 | 740 | * register this as a block device and as compliant with the |
|---|
| 773 | 741 | * universal CD Rom driver interface |
|---|
| .. | .. |
|---|
| 784 | 752 | |
|---|
| 785 | 753 | /* Start the device */ |
|---|
| 786 | 754 | if (gdrom_execute_diagnostic() != 1) { |
|---|
| 787 | | - pr_warning("ATA Probe for GDROM failed\n"); |
|---|
| 755 | + pr_warn("ATA Probe for GDROM failed\n"); |
|---|
| 788 | 756 | return -ENODEV; |
|---|
| 789 | 757 | } |
|---|
| 790 | 758 | /* Print out firmware ID */ |
|---|
| .. | .. |
|---|
| 809 | 777 | goto probe_fail_no_disk; |
|---|
| 810 | 778 | } |
|---|
| 811 | 779 | probe_gdrom_setupdisk(); |
|---|
| 812 | | - if (register_cdrom(gd.cd_info)) { |
|---|
| 780 | + if (register_cdrom(gd.disk, gd.cd_info)) { |
|---|
| 813 | 781 | err = -ENODEV; |
|---|
| 814 | 782 | goto probe_fail_cdrom_register; |
|---|
| 815 | 783 | } |
|---|
| 816 | 784 | gd.disk->fops = &gdrom_bdops; |
|---|
| 785 | + gd.disk->events = DISK_EVENT_MEDIA_CHANGE; |
|---|
| 817 | 786 | /* latch on to the interrupt */ |
|---|
| 818 | 787 | err = gdrom_set_interrupt_handlers(); |
|---|
| 819 | 788 | if (err) |
|---|
| 820 | 789 | goto probe_fail_cmdirq_register; |
|---|
| 821 | | - gd.gdrom_rq = blk_init_queue(gdrom_request, &gdrom_lock); |
|---|
| 822 | | - if (!gd.gdrom_rq) { |
|---|
| 823 | | - err = -ENOMEM; |
|---|
| 790 | + |
|---|
| 791 | + gd.gdrom_rq = blk_mq_init_sq_queue(&gd.tag_set, &gdrom_mq_ops, 1, |
|---|
| 792 | + BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); |
|---|
| 793 | + if (IS_ERR(gd.gdrom_rq)) { |
|---|
| 794 | + err = PTR_ERR(gd.gdrom_rq); |
|---|
| 795 | + gd.gdrom_rq = NULL; |
|---|
| 824 | 796 | goto probe_fail_requestq; |
|---|
| 825 | 797 | } |
|---|
| 798 | + |
|---|
| 826 | 799 | blk_queue_bounce_limit(gd.gdrom_rq, BLK_BOUNCE_HIGH); |
|---|
| 827 | 800 | |
|---|
| 828 | 801 | err = probe_gdrom_setupqueue(); |
|---|
| .. | .. |
|---|
| 839 | 812 | |
|---|
| 840 | 813 | probe_fail_toc: |
|---|
| 841 | 814 | blk_cleanup_queue(gd.gdrom_rq); |
|---|
| 815 | + blk_mq_free_tag_set(&gd.tag_set); |
|---|
| 842 | 816 | probe_fail_requestq: |
|---|
| 843 | 817 | free_irq(HW_EVENT_GDROM_DMA, &gd); |
|---|
| 844 | 818 | free_irq(HW_EVENT_GDROM_CMD, &gd); |
|---|
| .. | .. |
|---|
| 850 | 824 | probe_fail_no_mem: |
|---|
| 851 | 825 | unregister_blkdev(gdrom_major, GDROM_DEV_NAME); |
|---|
| 852 | 826 | gdrom_major = 0; |
|---|
| 853 | | - pr_warning("Probe failed - error is 0x%X\n", err); |
|---|
| 827 | + pr_warn("Probe failed - error is 0x%X\n", err); |
|---|
| 854 | 828 | return err; |
|---|
| 855 | 829 | } |
|---|
| 856 | 830 | |
|---|
| 857 | 831 | static int remove_gdrom(struct platform_device *devptr) |
|---|
| 858 | 832 | { |
|---|
| 859 | | - flush_work(&work); |
|---|
| 860 | 833 | blk_cleanup_queue(gd.gdrom_rq); |
|---|
| 834 | + blk_mq_free_tag_set(&gd.tag_set); |
|---|
| 861 | 835 | free_irq(HW_EVENT_GDROM_CMD, &gd); |
|---|
| 862 | 836 | free_irq(HW_EVENT_GDROM_DMA, &gd); |
|---|
| 863 | 837 | del_gendisk(gd.disk); |
|---|