diff options
author | Christoph Hellwig <hch@lst.de> | 2021-07-05 15:02:43 +0200 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2021-07-30 22:13:09 -0400 |
commit | ba51bdafaafc065019c6f6a2cdae006d176cee48 (patch) | |
tree | c46134baf01607cb8f6ea34b54428e476475d1dd /drivers/cdrom | |
parent | 08dc2f9b53afbbc897bc895aa41906194f5af1cf (diff) | |
download | lwn-ba51bdafaafc065019c6f6a2cdae006d176cee48.tar.gz lwn-ba51bdafaafc065019c6f6a2cdae006d176cee48.zip |
scsi: sr: cdrom: Move cdrom_read_cdda_bpc() into the sr driver
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>
Diffstat (limited to 'drivers/cdrom')
-rw-r--r-- | drivers/cdrom/cdrom.c | 71 |
1 files changed, 8 insertions, 63 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 8882b311bafd..bd2e5b1560f5 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -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; |