.. | .. |
---|
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); |
---|