| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * sr.c Copyright (C) 1992 David Giller |
|---|
| 3 | 4 | * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale |
|---|
| .. | .. |
|---|
| 37 | 38 | #include <linux/kernel.h> |
|---|
| 38 | 39 | #include <linux/mm.h> |
|---|
| 39 | 40 | #include <linux/bio.h> |
|---|
| 41 | +#include <linux/compat.h> |
|---|
| 40 | 42 | #include <linux/string.h> |
|---|
| 41 | 43 | #include <linux/errno.h> |
|---|
| 42 | 44 | #include <linux/cdrom.h> |
|---|
| 43 | 45 | #include <linux/interrupt.h> |
|---|
| 44 | 46 | #include <linux/init.h> |
|---|
| 45 | 47 | #include <linux/blkdev.h> |
|---|
| 48 | +#include <linux/blk-pm.h> |
|---|
| 46 | 49 | #include <linux/mutex.h> |
|---|
| 47 | 50 | #include <linux/slab.h> |
|---|
| 48 | 51 | #include <linux/pm_runtime.h> |
|---|
| 49 | 52 | #include <linux/uaccess.h> |
|---|
| 53 | + |
|---|
| 54 | +#include <asm/unaligned.h> |
|---|
| 50 | 55 | |
|---|
| 51 | 56 | #include <scsi/scsi.h> |
|---|
| 52 | 57 | #include <scsi/scsi_dbg.h> |
|---|
| .. | .. |
|---|
| 76 | 81 | CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ |
|---|
| 77 | 82 | CDC_MRW|CDC_MRW_W|CDC_RAM) |
|---|
| 78 | 83 | |
|---|
| 79 | | -static DEFINE_MUTEX(sr_mutex); |
|---|
| 80 | 84 | static int sr_probe(struct device *); |
|---|
| 81 | 85 | static int sr_remove(struct device *); |
|---|
| 82 | | -static int sr_init_command(struct scsi_cmnd *SCpnt); |
|---|
| 86 | +static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt); |
|---|
| 83 | 87 | static int sr_done(struct scsi_cmnd *); |
|---|
| 84 | 88 | static int sr_runtime_suspend(struct device *dev); |
|---|
| 85 | 89 | |
|---|
| .. | .. |
|---|
| 344 | 348 | case ILLEGAL_REQUEST: |
|---|
| 345 | 349 | if (!(SCpnt->sense_buffer[0] & 0x90)) |
|---|
| 346 | 350 | break; |
|---|
| 347 | | - error_sector = (SCpnt->sense_buffer[3] << 24) | |
|---|
| 348 | | - (SCpnt->sense_buffer[4] << 16) | |
|---|
| 349 | | - (SCpnt->sense_buffer[5] << 8) | |
|---|
| 350 | | - SCpnt->sense_buffer[6]; |
|---|
| 351 | + error_sector = |
|---|
| 352 | + get_unaligned_be32(&SCpnt->sense_buffer[3]); |
|---|
| 351 | 353 | if (SCpnt->request->bio != NULL) |
|---|
| 352 | 354 | block_sectors = |
|---|
| 353 | 355 | bio_sectors(SCpnt->request->bio); |
|---|
| .. | .. |
|---|
| 385 | 387 | return good_bytes; |
|---|
| 386 | 388 | } |
|---|
| 387 | 389 | |
|---|
| 388 | | -static int sr_init_command(struct scsi_cmnd *SCpnt) |
|---|
| 390 | +static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt) |
|---|
| 389 | 391 | { |
|---|
| 390 | 392 | int block = 0, this_count, s_size; |
|---|
| 391 | 393 | struct scsi_cd *cd; |
|---|
| 392 | 394 | struct request *rq = SCpnt->request; |
|---|
| 393 | | - int ret; |
|---|
| 395 | + blk_status_t ret; |
|---|
| 394 | 396 | |
|---|
| 395 | | - ret = scsi_init_io(SCpnt); |
|---|
| 396 | | - if (ret != BLKPREP_OK) |
|---|
| 397 | | - goto out; |
|---|
| 398 | | - WARN_ON_ONCE(SCpnt != rq->special); |
|---|
| 397 | + ret = scsi_alloc_sgtables(SCpnt); |
|---|
| 398 | + if (ret != BLK_STS_OK) |
|---|
| 399 | + return ret; |
|---|
| 399 | 400 | cd = scsi_cd(rq->rq_disk); |
|---|
| 400 | | - |
|---|
| 401 | | - /* from here on until we're complete, any goto out |
|---|
| 402 | | - * is used for a killable error condition */ |
|---|
| 403 | | - ret = BLKPREP_KILL; |
|---|
| 404 | 401 | |
|---|
| 405 | 402 | SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, |
|---|
| 406 | 403 | "Doing sr request, block = %d\n", block)); |
|---|
| .. | .. |
|---|
| 496 | 493 | SCpnt->sdb.length = this_count * s_size; |
|---|
| 497 | 494 | } |
|---|
| 498 | 495 | |
|---|
| 499 | | - SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; |
|---|
| 500 | | - SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; |
|---|
| 501 | | - SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; |
|---|
| 502 | | - SCpnt->cmnd[5] = (unsigned char) block & 0xff; |
|---|
| 496 | + put_unaligned_be32(block, &SCpnt->cmnd[2]); |
|---|
| 503 | 497 | SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0; |
|---|
| 504 | | - SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; |
|---|
| 505 | | - SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; |
|---|
| 498 | + put_unaligned_be16(this_count, &SCpnt->cmnd[7]); |
|---|
| 506 | 499 | |
|---|
| 507 | 500 | /* |
|---|
| 508 | 501 | * We shouldn't disconnect in the middle of a sector, so with a dumb |
|---|
| .. | .. |
|---|
| 512 | 505 | SCpnt->transfersize = cd->device->sector_size; |
|---|
| 513 | 506 | SCpnt->underflow = this_count << 9; |
|---|
| 514 | 507 | SCpnt->allowed = MAX_RETRIES; |
|---|
| 508 | + SCpnt->cmd_len = 10; |
|---|
| 515 | 509 | |
|---|
| 516 | 510 | /* |
|---|
| 517 | | - * This indicates that the command is ready from our end to be |
|---|
| 518 | | - * queued. |
|---|
| 511 | + * This indicates that the command is ready from our end to be queued. |
|---|
| 519 | 512 | */ |
|---|
| 520 | | - ret = BLKPREP_OK; |
|---|
| 513 | + return BLK_STS_OK; |
|---|
| 521 | 514 | out: |
|---|
| 522 | | - return ret; |
|---|
| 515 | + scsi_free_sgtables(SCpnt); |
|---|
| 516 | + return BLK_STS_IOERR; |
|---|
| 517 | +} |
|---|
| 518 | + |
|---|
| 519 | +static void sr_revalidate_disk(struct scsi_cd *cd) |
|---|
| 520 | +{ |
|---|
| 521 | + struct scsi_sense_hdr sshdr; |
|---|
| 522 | + |
|---|
| 523 | + /* if the unit is not ready, nothing more to do */ |
|---|
| 524 | + if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) |
|---|
| 525 | + return; |
|---|
| 526 | + sr_cd_check(&cd->cdi); |
|---|
| 527 | + get_sectorsize(cd); |
|---|
| 523 | 528 | } |
|---|
| 524 | 529 | |
|---|
| 525 | 530 | static int sr_block_open(struct block_device *bdev, fmode_t mode) |
|---|
| .. | .. |
|---|
| 534 | 539 | |
|---|
| 535 | 540 | sdev = cd->device; |
|---|
| 536 | 541 | scsi_autopm_get_device(sdev); |
|---|
| 537 | | - check_disk_change(bdev); |
|---|
| 542 | + if (bdev_check_media_change(bdev)) |
|---|
| 543 | + sr_revalidate_disk(cd); |
|---|
| 538 | 544 | |
|---|
| 539 | | - mutex_lock(&sr_mutex); |
|---|
| 545 | + mutex_lock(&cd->lock); |
|---|
| 540 | 546 | ret = cdrom_open(&cd->cdi, bdev, mode); |
|---|
| 541 | | - mutex_unlock(&sr_mutex); |
|---|
| 547 | + mutex_unlock(&cd->lock); |
|---|
| 542 | 548 | |
|---|
| 543 | 549 | scsi_autopm_put_device(sdev); |
|---|
| 544 | 550 | if (ret) |
|---|
| .. | .. |
|---|
| 551 | 557 | static void sr_block_release(struct gendisk *disk, fmode_t mode) |
|---|
| 552 | 558 | { |
|---|
| 553 | 559 | struct scsi_cd *cd = scsi_cd(disk); |
|---|
| 554 | | - mutex_lock(&sr_mutex); |
|---|
| 560 | + |
|---|
| 561 | + mutex_lock(&cd->lock); |
|---|
| 555 | 562 | cdrom_release(&cd->cdi, mode); |
|---|
| 563 | + mutex_unlock(&cd->lock); |
|---|
| 564 | + |
|---|
| 556 | 565 | scsi_cd_put(cd); |
|---|
| 557 | | - mutex_unlock(&sr_mutex); |
|---|
| 558 | 566 | } |
|---|
| 559 | 567 | |
|---|
| 560 | 568 | static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, |
|---|
| .. | .. |
|---|
| 565 | 573 | void __user *argp = (void __user *)arg; |
|---|
| 566 | 574 | int ret; |
|---|
| 567 | 575 | |
|---|
| 568 | | - mutex_lock(&sr_mutex); |
|---|
| 576 | + mutex_lock(&cd->lock); |
|---|
| 569 | 577 | |
|---|
| 570 | 578 | ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, |
|---|
| 571 | 579 | (mode & FMODE_NDELAY) != 0); |
|---|
| .. | .. |
|---|
| 595 | 603 | scsi_autopm_put_device(sdev); |
|---|
| 596 | 604 | |
|---|
| 597 | 605 | out: |
|---|
| 598 | | - mutex_unlock(&sr_mutex); |
|---|
| 606 | + mutex_unlock(&cd->lock); |
|---|
| 599 | 607 | return ret; |
|---|
| 600 | 608 | } |
|---|
| 609 | + |
|---|
| 610 | +#ifdef CONFIG_COMPAT |
|---|
| 611 | +static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, |
|---|
| 612 | + unsigned long arg) |
|---|
| 613 | +{ |
|---|
| 614 | + struct scsi_cd *cd = scsi_cd(bdev->bd_disk); |
|---|
| 615 | + struct scsi_device *sdev = cd->device; |
|---|
| 616 | + void __user *argp = compat_ptr(arg); |
|---|
| 617 | + int ret; |
|---|
| 618 | + |
|---|
| 619 | + mutex_lock(&cd->lock); |
|---|
| 620 | + |
|---|
| 621 | + ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, |
|---|
| 622 | + (mode & FMODE_NDELAY) != 0); |
|---|
| 623 | + if (ret) |
|---|
| 624 | + goto out; |
|---|
| 625 | + |
|---|
| 626 | + scsi_autopm_get_device(sdev); |
|---|
| 627 | + |
|---|
| 628 | + /* |
|---|
| 629 | + * Send SCSI addressing ioctls directly to mid level, send other |
|---|
| 630 | + * ioctls to cdrom/block level. |
|---|
| 631 | + */ |
|---|
| 632 | + switch (cmd) { |
|---|
| 633 | + case SCSI_IOCTL_GET_IDLUN: |
|---|
| 634 | + case SCSI_IOCTL_GET_BUS_NUMBER: |
|---|
| 635 | + ret = scsi_compat_ioctl(sdev, cmd, argp); |
|---|
| 636 | + goto put; |
|---|
| 637 | + } |
|---|
| 638 | + |
|---|
| 639 | + ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, (unsigned long)argp); |
|---|
| 640 | + if (ret != -ENOSYS) |
|---|
| 641 | + goto put; |
|---|
| 642 | + |
|---|
| 643 | + ret = scsi_compat_ioctl(sdev, cmd, argp); |
|---|
| 644 | + |
|---|
| 645 | +put: |
|---|
| 646 | + scsi_autopm_put_device(sdev); |
|---|
| 647 | + |
|---|
| 648 | +out: |
|---|
| 649 | + mutex_unlock(&cd->lock); |
|---|
| 650 | + return ret; |
|---|
| 651 | + |
|---|
| 652 | +} |
|---|
| 653 | +#endif |
|---|
| 601 | 654 | |
|---|
| 602 | 655 | static unsigned int sr_block_check_events(struct gendisk *disk, |
|---|
| 603 | 656 | unsigned int clearing) |
|---|
| .. | .. |
|---|
| 616 | 669 | return ret; |
|---|
| 617 | 670 | } |
|---|
| 618 | 671 | |
|---|
| 619 | | -static int sr_block_revalidate_disk(struct gendisk *disk) |
|---|
| 620 | | -{ |
|---|
| 621 | | - struct scsi_sense_hdr sshdr; |
|---|
| 622 | | - struct scsi_cd *cd; |
|---|
| 623 | | - |
|---|
| 624 | | - cd = scsi_cd_get(disk); |
|---|
| 625 | | - if (!cd) |
|---|
| 626 | | - return -ENXIO; |
|---|
| 627 | | - |
|---|
| 628 | | - /* if the unit is not ready, nothing more to do */ |
|---|
| 629 | | - if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) |
|---|
| 630 | | - goto out; |
|---|
| 631 | | - |
|---|
| 632 | | - sr_cd_check(&cd->cdi); |
|---|
| 633 | | - get_sectorsize(cd); |
|---|
| 634 | | -out: |
|---|
| 635 | | - scsi_cd_put(cd); |
|---|
| 636 | | - return 0; |
|---|
| 637 | | -} |
|---|
| 638 | | - |
|---|
| 639 | 672 | static const struct block_device_operations sr_bdops = |
|---|
| 640 | 673 | { |
|---|
| 641 | 674 | .owner = THIS_MODULE, |
|---|
| 642 | 675 | .open = sr_block_open, |
|---|
| 643 | 676 | .release = sr_block_release, |
|---|
| 644 | 677 | .ioctl = sr_block_ioctl, |
|---|
| 678 | +#ifdef CONFIG_COMPAT |
|---|
| 679 | + .compat_ioctl = sr_block_compat_ioctl, |
|---|
| 680 | +#endif |
|---|
| 645 | 681 | .check_events = sr_block_check_events, |
|---|
| 646 | | - .revalidate_disk = sr_block_revalidate_disk, |
|---|
| 647 | | - /* |
|---|
| 648 | | - * No compat_ioctl for now because sr_block_ioctl never |
|---|
| 649 | | - * seems to pass arbitrary ioctls down to host drivers. |
|---|
| 650 | | - */ |
|---|
| 651 | 682 | }; |
|---|
| 652 | 683 | |
|---|
| 653 | 684 | static int sr_open(struct cdrom_device_info *cdi, int purpose) |
|---|
| .. | .. |
|---|
| 701 | 732 | disk = alloc_disk(1); |
|---|
| 702 | 733 | if (!disk) |
|---|
| 703 | 734 | goto fail_free; |
|---|
| 735 | + mutex_init(&cd->lock); |
|---|
| 704 | 736 | |
|---|
| 705 | 737 | spin_lock(&sr_index_lock); |
|---|
| 706 | 738 | minor = find_first_zero_bit(sr_index_bits, SR_DISKS); |
|---|
| .. | .. |
|---|
| 718 | 750 | disk->fops = &sr_bdops; |
|---|
| 719 | 751 | disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; |
|---|
| 720 | 752 | disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST; |
|---|
| 753 | + disk->event_flags = DISK_EVENT_FLAG_POLL | DISK_EVENT_FLAG_UEVENT; |
|---|
| 721 | 754 | |
|---|
| 722 | 755 | blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); |
|---|
| 723 | 756 | |
|---|
| .. | .. |
|---|
| 747 | 780 | set_capacity(disk, cd->capacity); |
|---|
| 748 | 781 | disk->private_data = &cd->driver; |
|---|
| 749 | 782 | disk->queue = sdev->request_queue; |
|---|
| 750 | | - cd->cdi.disk = disk; |
|---|
| 751 | 783 | |
|---|
| 752 | | - if (register_cdrom(&cd->cdi)) |
|---|
| 784 | + if (register_cdrom(disk, &cd->cdi)) |
|---|
| 753 | 785 | goto fail_minor; |
|---|
| 754 | 786 | |
|---|
| 755 | 787 | /* |
|---|
| .. | .. |
|---|
| 760 | 792 | |
|---|
| 761 | 793 | dev_set_drvdata(dev, cd); |
|---|
| 762 | 794 | disk->flags |= GENHD_FL_REMOVABLE; |
|---|
| 763 | | - device_add_disk(&sdev->sdev_gendev, disk); |
|---|
| 795 | + sr_revalidate_disk(cd); |
|---|
| 796 | + device_add_disk(&sdev->sdev_gendev, disk, NULL); |
|---|
| 764 | 797 | |
|---|
| 765 | 798 | sdev_printk(KERN_DEBUG, sdev, |
|---|
| 766 | 799 | "Attached scsi CD-ROM %s\n", cd->cdi.name); |
|---|
| .. | .. |
|---|
| 774 | 807 | spin_unlock(&sr_index_lock); |
|---|
| 775 | 808 | fail_put: |
|---|
| 776 | 809 | put_disk(disk); |
|---|
| 810 | + mutex_destroy(&cd->lock); |
|---|
| 777 | 811 | fail_free: |
|---|
| 778 | 812 | kfree(cd); |
|---|
| 779 | 813 | fail: |
|---|
| .. | .. |
|---|
| 811 | 845 | } else { |
|---|
| 812 | 846 | long last_written; |
|---|
| 813 | 847 | |
|---|
| 814 | | - cd->capacity = 1 + ((buffer[0] << 24) | (buffer[1] << 16) | |
|---|
| 815 | | - (buffer[2] << 8) | buffer[3]); |
|---|
| 848 | + cd->capacity = 1 + get_unaligned_be32(&buffer[0]); |
|---|
| 816 | 849 | /* |
|---|
| 817 | 850 | * READ_CAPACITY doesn't return the correct size on |
|---|
| 818 | 851 | * certain UDF media. If last_written is larger, use |
|---|
| .. | .. |
|---|
| 823 | 856 | if (!cdrom_get_last_written(&cd->cdi, &last_written)) |
|---|
| 824 | 857 | cd->capacity = max_t(long, cd->capacity, last_written); |
|---|
| 825 | 858 | |
|---|
| 826 | | - sector_size = (buffer[4] << 24) | |
|---|
| 827 | | - (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; |
|---|
| 859 | + sector_size = get_unaligned_be32(&buffer[4]); |
|---|
| 828 | 860 | switch (sector_size) { |
|---|
| 829 | 861 | /* |
|---|
| 830 | 862 | * HP 4020i CD-Recorder reports 2340 byte sectors |
|---|
| .. | .. |
|---|
| 836 | 868 | case 2340: |
|---|
| 837 | 869 | case 2352: |
|---|
| 838 | 870 | sector_size = 2048; |
|---|
| 839 | | - /* fall through */ |
|---|
| 871 | + fallthrough; |
|---|
| 840 | 872 | case 2048: |
|---|
| 841 | 873 | cd->capacity *= 4; |
|---|
| 842 | | - /* fall through */ |
|---|
| 874 | + fallthrough; |
|---|
| 843 | 875 | case 512: |
|---|
| 844 | 876 | break; |
|---|
| 845 | 877 | default: |
|---|
| .. | .. |
|---|
| 898 | 930 | rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len, |
|---|
| 899 | 931 | SR_TIMEOUT, 3, &data, NULL); |
|---|
| 900 | 932 | |
|---|
| 901 | | - if (!scsi_status_is_good(rc) || data.length > ms_len || |
|---|
| 933 | + if (rc < 0 || data.length > ms_len || |
|---|
| 902 | 934 | data.header_length + data.block_descriptor_length > data.length) { |
|---|
| 903 | 935 | /* failed, drive doesn't have capabilities mode page */ |
|---|
| 904 | 936 | cd->cdi.speed = 1; |
|---|
| .. | .. |
|---|
| 912 | 944 | } |
|---|
| 913 | 945 | |
|---|
| 914 | 946 | n = data.header_length + data.block_descriptor_length; |
|---|
| 915 | | - cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; |
|---|
| 947 | + cd->cdi.speed = get_unaligned_be16(&buffer[n + 8]) / 176; |
|---|
| 916 | 948 | cd->readcd_known = 1; |
|---|
| 917 | 949 | cd->readcd_cdda = buffer[n + 5] & 0x01; |
|---|
| 918 | 950 | /* print some capability bits */ |
|---|
| 919 | 951 | sr_printk(KERN_INFO, cd, |
|---|
| 920 | 952 | "scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", |
|---|
| 921 | | - ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, |
|---|
| 953 | + get_unaligned_be16(&buffer[n + 14]) / 176, |
|---|
| 922 | 954 | cd->cdi.speed, |
|---|
| 923 | 955 | buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ |
|---|
| 924 | 956 | buffer[n + 3] & 0x20 ? "dvd-ram " : "", |
|---|
| .. | .. |
|---|
| 1014 | 1046 | |
|---|
| 1015 | 1047 | put_disk(disk); |
|---|
| 1016 | 1048 | |
|---|
| 1049 | + mutex_destroy(&cd->lock); |
|---|
| 1050 | + |
|---|
| 1017 | 1051 | kfree(cd); |
|---|
| 1018 | 1052 | } |
|---|
| 1019 | 1053 | |
|---|