mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
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>
This commit is contained in:
parent
08dc2f9b53
commit
ba51bdafaa
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user