| .. | .. |
|---|
| 137 | 137 | #include <linux/delay.h> |
|---|
| 138 | 138 | #include <linux/cdrom.h> |
|---|
| 139 | 139 | #include <linux/spinlock.h> |
|---|
| 140 | | -#include <linux/blkdev.h> |
|---|
| 140 | +#include <linux/blk-mq.h> |
|---|
| 141 | 141 | #include <linux/mutex.h> |
|---|
| 142 | 142 | #include <linux/uaccess.h> |
|---|
| 143 | 143 | |
|---|
| .. | .. |
|---|
| 186 | 186 | static int pcd_detect(void); |
|---|
| 187 | 187 | static void pcd_probe_capabilities(void); |
|---|
| 188 | 188 | static void do_pcd_read_drq(void); |
|---|
| 189 | | -static void do_pcd_request(struct request_queue * q); |
|---|
| 189 | +static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx, |
|---|
| 190 | + const struct blk_mq_queue_data *bd); |
|---|
| 190 | 191 | static void do_pcd_read(void); |
|---|
| 191 | 192 | |
|---|
| 192 | 193 | struct pcd_unit { |
|---|
| .. | .. |
|---|
| 199 | 200 | char *name; /* pcd0, pcd1, etc */ |
|---|
| 200 | 201 | struct cdrom_device_info info; /* uniform cdrom interface */ |
|---|
| 201 | 202 | struct gendisk *disk; |
|---|
| 203 | + struct blk_mq_tag_set tag_set; |
|---|
| 204 | + struct list_head rq_list; |
|---|
| 202 | 205 | }; |
|---|
| 203 | 206 | |
|---|
| 204 | 207 | static struct pcd_unit pcd[PCD_UNITS]; |
|---|
| .. | .. |
|---|
| 230 | 233 | struct pcd_unit *cd = bdev->bd_disk->private_data; |
|---|
| 231 | 234 | int ret; |
|---|
| 232 | 235 | |
|---|
| 233 | | - check_disk_change(bdev); |
|---|
| 236 | + bdev_check_media_change(bdev); |
|---|
| 234 | 237 | |
|---|
| 235 | 238 | mutex_lock(&pcd_mutex); |
|---|
| 236 | 239 | ret = cdrom_open(&cd->info, bdev, mode); |
|---|
| .. | .. |
|---|
| 272 | 275 | .open = pcd_block_open, |
|---|
| 273 | 276 | .release = pcd_block_release, |
|---|
| 274 | 277 | .ioctl = pcd_block_ioctl, |
|---|
| 278 | +#ifdef CONFIG_COMPAT |
|---|
| 279 | + .compat_ioctl = blkdev_compat_ptr_ioctl, |
|---|
| 280 | +#endif |
|---|
| 275 | 281 | .check_events = pcd_block_check_events, |
|---|
| 276 | 282 | }; |
|---|
| 277 | 283 | |
|---|
| .. | .. |
|---|
| 292 | 298 | CDC_CD_RW, |
|---|
| 293 | 299 | }; |
|---|
| 294 | 300 | |
|---|
| 301 | +static const struct blk_mq_ops pcd_mq_ops = { |
|---|
| 302 | + .queue_rq = pcd_queue_rq, |
|---|
| 303 | +}; |
|---|
| 304 | + |
|---|
| 295 | 305 | static void pcd_init_units(void) |
|---|
| 296 | 306 | { |
|---|
| 297 | 307 | struct pcd_unit *cd; |
|---|
| .. | .. |
|---|
| 300 | 310 | pcd_drive_count = 0; |
|---|
| 301 | 311 | for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { |
|---|
| 302 | 312 | struct gendisk *disk = alloc_disk(1); |
|---|
| 313 | + |
|---|
| 303 | 314 | if (!disk) |
|---|
| 304 | 315 | continue; |
|---|
| 305 | | - disk->queue = blk_init_queue(do_pcd_request, &pcd_lock); |
|---|
| 306 | | - if (!disk->queue) { |
|---|
| 316 | + |
|---|
| 317 | + disk->queue = blk_mq_init_sq_queue(&cd->tag_set, &pcd_mq_ops, |
|---|
| 318 | + 1, BLK_MQ_F_SHOULD_MERGE); |
|---|
| 319 | + if (IS_ERR(disk->queue)) { |
|---|
| 320 | + disk->queue = NULL; |
|---|
| 307 | 321 | put_disk(disk); |
|---|
| 308 | 322 | continue; |
|---|
| 309 | 323 | } |
|---|
| 324 | + |
|---|
| 325 | + INIT_LIST_HEAD(&cd->rq_list); |
|---|
| 326 | + disk->queue->queuedata = cd; |
|---|
| 310 | 327 | blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); |
|---|
| 311 | 328 | cd->disk = disk; |
|---|
| 312 | 329 | cd->pi = &cd->pia; |
|---|
| .. | .. |
|---|
| 329 | 346 | strcpy(disk->disk_name, cd->name); /* umm... */ |
|---|
| 330 | 347 | disk->fops = &pcd_bdops; |
|---|
| 331 | 348 | disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; |
|---|
| 349 | + disk->events = DISK_EVENT_MEDIA_CHANGE; |
|---|
| 332 | 350 | } |
|---|
| 333 | 351 | } |
|---|
| 334 | 352 | |
|---|
| .. | .. |
|---|
| 708 | 726 | k = 0; |
|---|
| 709 | 727 | if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ |
|---|
| 710 | 728 | cd = pcd; |
|---|
| 711 | | - if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer, |
|---|
| 712 | | - PI_PCD, verbose, cd->name)) { |
|---|
| 713 | | - if (!pcd_probe(cd, -1, id) && cd->disk) { |
|---|
| 729 | + if (cd->disk && pi_init(cd->pi, 1, -1, -1, -1, -1, -1, |
|---|
| 730 | + pcd_buffer, PI_PCD, verbose, cd->name)) { |
|---|
| 731 | + if (!pcd_probe(cd, -1, id)) { |
|---|
| 714 | 732 | cd->present = 1; |
|---|
| 715 | 733 | k++; |
|---|
| 716 | 734 | } else |
|---|
| .. | .. |
|---|
| 721 | 739 | int *conf = *drives[unit]; |
|---|
| 722 | 740 | if (!conf[D_PRT]) |
|---|
| 723 | 741 | continue; |
|---|
| 742 | + if (!cd->disk) |
|---|
| 743 | + continue; |
|---|
| 724 | 744 | if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD], |
|---|
| 725 | 745 | conf[D_UNI], conf[D_PRO], conf[D_DLY], |
|---|
| 726 | 746 | pcd_buffer, PI_PCD, verbose, cd->name)) |
|---|
| 727 | 747 | continue; |
|---|
| 728 | | - if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) { |
|---|
| 748 | + if (!pcd_probe(cd, conf[D_SLV], id)) { |
|---|
| 729 | 749 | cd->present = 1; |
|---|
| 730 | 750 | k++; |
|---|
| 731 | 751 | } else |
|---|
| .. | .. |
|---|
| 736 | 756 | return 0; |
|---|
| 737 | 757 | |
|---|
| 738 | 758 | printk("%s: No CD-ROM drive found\n", name); |
|---|
| 739 | | - for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) |
|---|
| 759 | + for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { |
|---|
| 760 | + if (!cd->disk) |
|---|
| 761 | + continue; |
|---|
| 762 | + blk_cleanup_queue(cd->disk->queue); |
|---|
| 763 | + cd->disk->queue = NULL; |
|---|
| 764 | + blk_mq_free_tag_set(&cd->tag_set); |
|---|
| 740 | 765 | put_disk(cd->disk); |
|---|
| 766 | + } |
|---|
| 741 | 767 | pi_unregister_driver(par_drv); |
|---|
| 742 | 768 | return -1; |
|---|
| 743 | 769 | } |
|---|
| .. | .. |
|---|
| 748 | 774 | static int set_next_request(void) |
|---|
| 749 | 775 | { |
|---|
| 750 | 776 | struct pcd_unit *cd; |
|---|
| 751 | | - struct request_queue *q; |
|---|
| 752 | 777 | int old_pos = pcd_queue; |
|---|
| 753 | 778 | |
|---|
| 754 | 779 | do { |
|---|
| 755 | 780 | cd = &pcd[pcd_queue]; |
|---|
| 756 | | - q = cd->present ? cd->disk->queue : NULL; |
|---|
| 757 | 781 | if (++pcd_queue == PCD_UNITS) |
|---|
| 758 | 782 | pcd_queue = 0; |
|---|
| 759 | | - if (q) { |
|---|
| 760 | | - pcd_req = blk_fetch_request(q); |
|---|
| 761 | | - if (pcd_req) |
|---|
| 762 | | - break; |
|---|
| 783 | + if (cd->present && !list_empty(&cd->rq_list)) { |
|---|
| 784 | + pcd_req = list_first_entry(&cd->rq_list, struct request, |
|---|
| 785 | + queuelist); |
|---|
| 786 | + list_del_init(&pcd_req->queuelist); |
|---|
| 787 | + blk_mq_start_request(pcd_req); |
|---|
| 788 | + break; |
|---|
| 763 | 789 | } |
|---|
| 764 | 790 | } while (pcd_queue != old_pos); |
|---|
| 765 | 791 | |
|---|
| .. | .. |
|---|
| 768 | 794 | |
|---|
| 769 | 795 | static void pcd_request(void) |
|---|
| 770 | 796 | { |
|---|
| 797 | + struct pcd_unit *cd; |
|---|
| 798 | + |
|---|
| 771 | 799 | if (pcd_busy) |
|---|
| 772 | 800 | return; |
|---|
| 773 | | - while (1) { |
|---|
| 774 | | - if (!pcd_req && !set_next_request()) |
|---|
| 775 | | - return; |
|---|
| 776 | 801 | |
|---|
| 777 | | - if (rq_data_dir(pcd_req) == READ) { |
|---|
| 778 | | - struct pcd_unit *cd = pcd_req->rq_disk->private_data; |
|---|
| 779 | | - if (cd != pcd_current) |
|---|
| 780 | | - pcd_bufblk = -1; |
|---|
| 781 | | - pcd_current = cd; |
|---|
| 782 | | - pcd_sector = blk_rq_pos(pcd_req); |
|---|
| 783 | | - pcd_count = blk_rq_cur_sectors(pcd_req); |
|---|
| 784 | | - pcd_buf = bio_data(pcd_req->bio); |
|---|
| 785 | | - pcd_busy = 1; |
|---|
| 786 | | - ps_set_intr(do_pcd_read, NULL, 0, nice); |
|---|
| 787 | | - return; |
|---|
| 788 | | - } else { |
|---|
| 789 | | - __blk_end_request_all(pcd_req, BLK_STS_IOERR); |
|---|
| 790 | | - pcd_req = NULL; |
|---|
| 791 | | - } |
|---|
| 792 | | - } |
|---|
| 802 | + if (!pcd_req && !set_next_request()) |
|---|
| 803 | + return; |
|---|
| 804 | + |
|---|
| 805 | + cd = pcd_req->rq_disk->private_data; |
|---|
| 806 | + if (cd != pcd_current) |
|---|
| 807 | + pcd_bufblk = -1; |
|---|
| 808 | + pcd_current = cd; |
|---|
| 809 | + pcd_sector = blk_rq_pos(pcd_req); |
|---|
| 810 | + pcd_count = blk_rq_cur_sectors(pcd_req); |
|---|
| 811 | + pcd_buf = bio_data(pcd_req->bio); |
|---|
| 812 | + pcd_busy = 1; |
|---|
| 813 | + ps_set_intr(do_pcd_read, NULL, 0, nice); |
|---|
| 793 | 814 | } |
|---|
| 794 | 815 | |
|---|
| 795 | | -static void do_pcd_request(struct request_queue *q) |
|---|
| 816 | +static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx, |
|---|
| 817 | + const struct blk_mq_queue_data *bd) |
|---|
| 796 | 818 | { |
|---|
| 819 | + struct pcd_unit *cd = hctx->queue->queuedata; |
|---|
| 820 | + |
|---|
| 821 | + if (rq_data_dir(bd->rq) != READ) { |
|---|
| 822 | + blk_mq_start_request(bd->rq); |
|---|
| 823 | + return BLK_STS_IOERR; |
|---|
| 824 | + } |
|---|
| 825 | + |
|---|
| 826 | + spin_lock_irq(&pcd_lock); |
|---|
| 827 | + list_add_tail(&bd->rq->queuelist, &cd->rq_list); |
|---|
| 797 | 828 | pcd_request(); |
|---|
| 829 | + spin_unlock_irq(&pcd_lock); |
|---|
| 830 | + |
|---|
| 831 | + return BLK_STS_OK; |
|---|
| 798 | 832 | } |
|---|
| 799 | 833 | |
|---|
| 800 | 834 | static inline void next_request(blk_status_t err) |
|---|
| .. | .. |
|---|
| 802 | 836 | unsigned long saved_flags; |
|---|
| 803 | 837 | |
|---|
| 804 | 838 | spin_lock_irqsave(&pcd_lock, saved_flags); |
|---|
| 805 | | - if (!__blk_end_request_cur(pcd_req, err)) |
|---|
| 839 | + if (!blk_update_request(pcd_req, err, blk_rq_cur_bytes(pcd_req))) { |
|---|
| 840 | + __blk_mq_end_request(pcd_req, err); |
|---|
| 806 | 841 | pcd_req = NULL; |
|---|
| 842 | + } |
|---|
| 807 | 843 | pcd_busy = 0; |
|---|
| 808 | 844 | pcd_request(); |
|---|
| 809 | 845 | spin_unlock_irqrestore(&pcd_lock, saved_flags); |
|---|
| .. | .. |
|---|
| 983 | 1019 | pcd_probe_capabilities(); |
|---|
| 984 | 1020 | |
|---|
| 985 | 1021 | if (register_blkdev(major, name)) { |
|---|
| 986 | | - for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) |
|---|
| 1022 | + for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { |
|---|
| 1023 | + if (!cd->disk) |
|---|
| 1024 | + continue; |
|---|
| 1025 | + |
|---|
| 1026 | + blk_cleanup_queue(cd->disk->queue); |
|---|
| 1027 | + blk_mq_free_tag_set(&cd->tag_set); |
|---|
| 987 | 1028 | put_disk(cd->disk); |
|---|
| 1029 | + } |
|---|
| 988 | 1030 | return -EBUSY; |
|---|
| 989 | 1031 | } |
|---|
| 990 | 1032 | |
|---|
| 991 | 1033 | for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { |
|---|
| 992 | 1034 | if (cd->present) { |
|---|
| 993 | | - register_cdrom(&cd->info); |
|---|
| 1035 | + register_cdrom(cd->disk, &cd->info); |
|---|
| 994 | 1036 | cd->disk->private_data = cd; |
|---|
| 995 | 1037 | add_disk(cd->disk); |
|---|
| 996 | 1038 | } |
|---|
| .. | .. |
|---|
| 1005 | 1047 | int unit; |
|---|
| 1006 | 1048 | |
|---|
| 1007 | 1049 | for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { |
|---|
| 1050 | + if (!cd->disk) |
|---|
| 1051 | + continue; |
|---|
| 1052 | + |
|---|
| 1008 | 1053 | if (cd->present) { |
|---|
| 1009 | 1054 | del_gendisk(cd->disk); |
|---|
| 1010 | 1055 | pi_release(cd->pi); |
|---|
| 1011 | 1056 | unregister_cdrom(&cd->info); |
|---|
| 1012 | 1057 | } |
|---|
| 1013 | 1058 | blk_cleanup_queue(cd->disk->queue); |
|---|
| 1059 | + blk_mq_free_tag_set(&cd->tag_set); |
|---|
| 1014 | 1060 | put_disk(cd->disk); |
|---|
| 1015 | 1061 | } |
|---|
| 1016 | 1062 | unregister_blkdev(major, name); |
|---|