scsi: sr: cdrom: Move cdrom_read_cdda_bpc() into the sr driver
authorChristoph Hellwig <hch@lst.de>
Mon, 5 Jul 2021 13:02:43 +0000 (15:02 +0200)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 31 Jul 2021 02:13:09 +0000 (22:13 -0400)
cdrom_read_cdda_bpc() relies on sending SCSI command to the low level
driver using a REQ_OP_SCSI_IN request.  This isn't generic block layer
functionality, so move the actual low-level code into the sr driver and
call it through a new read_cdda_bpc method in the cdrom_device_ops
structure.

With this the CDROM code does not have to pull in scsi_normalize_sense()
and depend on CONFIG_SCSI_COMMON.

Link: https://lore.kernel.org/r/20210730072752.GB23847%40lst.de
Tested-by: Anders Roxell <anders.roxell@linaro.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/cdrom/cdrom.c
drivers/scsi/sr.c
include/linux/cdrom.h

index 8882b31..bd2e5b1 100644 (file)
@@ -629,7 +629,7 @@ int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi)
        if (CDROM_CAN(CDC_MRW_W))
                cdi->exit = cdrom_mrw_exit;
 
-       if (cdi->disk)
+       if (cdi->ops->read_cdda_bpc)
                cdi->cdda_method = CDDA_BPC_FULL;
        else
                cdi->cdda_method = CDDA_OLD;
@@ -2159,81 +2159,26 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
                               int lba, int nframes)
 {
-       struct request_queue *q = cdi->disk->queue;
-       struct request *rq;
-       struct scsi_request *req;
-       struct bio *bio;
-       unsigned int len;
+       int max_frames = (queue_max_sectors(cdi->disk->queue) << 9) /
+                         CD_FRAMESIZE_RAW;
        int nr, ret = 0;
 
-       if (!q)
-               return -ENXIO;
-
-       if (!blk_queue_scsi_passthrough(q)) {
-               WARN_ONCE(true,
-                         "Attempt read CDDA info through a non-SCSI queue\n");
-               return -EINVAL;
-       }
-
        cdi->last_sense = 0;
 
        while (nframes) {
-               nr = nframes;
                if (cdi->cdda_method == CDDA_BPC_SINGLE)
                        nr = 1;
-               if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9))
-                       nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW;
-
-               len = nr * CD_FRAMESIZE_RAW;
-
-               rq = blk_get_request(q, REQ_OP_DRV_IN, 0);
-               if (IS_ERR(rq)) {
-                       ret = PTR_ERR(rq);
-                       break;
-               }
-               req = scsi_req(rq);
-
-               ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
-               if (ret) {
-                       blk_put_request(rq);
-                       break;
-               }
-
-               req->cmd[0] = GPCMD_READ_CD;
-               req->cmd[1] = 1 << 2;
-               req->cmd[2] = (lba >> 24) & 0xff;
-               req->cmd[3] = (lba >> 16) & 0xff;
-               req->cmd[4] = (lba >>  8) & 0xff;
-               req->cmd[5] = lba & 0xff;
-               req->cmd[6] = (nr >> 16) & 0xff;
-               req->cmd[7] = (nr >>  8) & 0xff;
-               req->cmd[8] = nr & 0xff;
-               req->cmd[9] = 0xf8;
-
-               req->cmd_len = 12;
-               rq->timeout = 60 * HZ;
-               bio = rq->bio;
-
-               blk_execute_rq(cdi->disk, rq, 0);
-               if (scsi_req(rq)->result) {
-                       struct scsi_sense_hdr sshdr;
-
-                       ret = -EIO;
-                       scsi_normalize_sense(req->sense, req->sense_len,
-                                            &sshdr);
-                       cdi->last_sense = sshdr.sense_key;
-               }
-
-               if (blk_rq_unmap_user(bio))
-                       ret = -EFAULT;
-               blk_put_request(rq);
+               else
+                       nr = min(nframes, max_frames);
 
+               ret = cdi->ops->read_cdda_bpc(cdi, ubuf, lba, nr,
+                                             &cdi->last_sense);
                if (ret)
                        break;
 
                nframes -= nr;
                lba += nr;
-               ubuf += len;
+               ubuf += (nr * CD_FRAMESIZE_RAW);
        }
 
        return ret;
index b98e77f..6203a8b 100644 (file)
@@ -120,6 +120,8 @@ static void get_capabilities(struct scsi_cd *);
 static unsigned int sr_check_events(struct cdrom_device_info *cdi,
                                    unsigned int clearing, int slot);
 static int sr_packet(struct cdrom_device_info *, struct packet_command *);
+static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf,
+               u32 lba, u32 nr, u8 *last_sense);
 
 static const struct cdrom_device_ops sr_dops = {
        .open                   = sr_open,
@@ -133,8 +135,9 @@ static const struct cdrom_device_ops sr_dops = {
        .get_mcn                = sr_get_mcn,
        .reset                  = sr_reset,
        .audio_ioctl            = sr_audio_ioctl,
-       .capability             = SR_CAPABILITIES,
        .generic_packet         = sr_packet,
+       .read_cdda_bpc          = sr_read_cdda_bpc,
+       .capability             = SR_CAPABILITIES,
 };
 
 static void sr_kref_release(struct kref *kref);
@@ -951,6 +954,57 @@ static int sr_packet(struct cdrom_device_info *cdi,
        return cgc->stat;
 }
 
+static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf,
+               u32 lba, u32 nr, u8 *last_sense)
+{
+       struct gendisk *disk = cdi->disk;
+       u32 len = nr * CD_FRAMESIZE_RAW;
+       struct scsi_request *req;
+       struct request *rq;
+       struct bio *bio;
+       int ret;
+
+       rq = blk_get_request(disk->queue, REQ_OP_DRV_IN, 0);
+       if (IS_ERR(rq))
+               return PTR_ERR(rq);
+       req = scsi_req(rq);
+
+       ret = blk_rq_map_user(disk->queue, rq, NULL, ubuf, len, GFP_KERNEL);
+       if (ret)
+               goto out_put_request;
+
+       req->cmd[0] = GPCMD_READ_CD;
+       req->cmd[1] = 1 << 2;
+       req->cmd[2] = (lba >> 24) & 0xff;
+       req->cmd[3] = (lba >> 16) & 0xff;
+       req->cmd[4] = (lba >>  8) & 0xff;
+       req->cmd[5] = lba & 0xff;
+       req->cmd[6] = (nr >> 16) & 0xff;
+       req->cmd[7] = (nr >>  8) & 0xff;
+       req->cmd[8] = nr & 0xff;
+       req->cmd[9] = 0xf8;
+       req->cmd_len = 12;
+       rq->timeout = 60 * HZ;
+       bio = rq->bio;
+
+       blk_execute_rq(disk, rq, 0);
+       if (scsi_req(rq)->result) {
+               struct scsi_sense_hdr sshdr;
+
+               scsi_normalize_sense(req->sense, req->sense_len,
+                                    &sshdr);
+               *last_sense = sshdr.sense_key;
+               ret = -EIO;
+       }
+
+       if (blk_rq_unmap_user(bio))
+               ret = -EFAULT;
+out_put_request:
+       blk_put_request(rq);
+       return ret;
+}
+
+
 /**
  *     sr_kref_release - Called to free the scsi_cd structure
  *     @kref: pointer to embedded kref
index f48d0a3..c4fef00 100644 (file)
@@ -86,11 +86,13 @@ struct cdrom_device_ops {
        /* play stuff */
        int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *);
 
-/* driver specifications */
-       const int capability;   /* capability flags */
        /* handle uniform packets for scsi type devices (scsi,atapi) */
        int (*generic_packet) (struct cdrom_device_info *,
                               struct packet_command *);
+       int (*read_cdda_bpc)(struct cdrom_device_info *cdi, void __user *ubuf,
+                              u32 lba, u32 nframes, u8 *last_sense);
+/* driver specifications */
+       const int capability;   /* capability flags */
 };
 
 int cdrom_multisession(struct cdrom_device_info *cdi,