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.
Unified · Split
| @@ -629,7 +629,7 @@ int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi) · 628 unmodified lines | ||
| 629 | 629 | if (CDROM_CAN(CDC_MRW_W)) |
| 630 | 630 | cdi->exit = cdrom_mrw_exit; |
| 631 | 631 | |
| 632 | − if (cdi->disk) | |
| 632 | + if (cdi->ops->read_cdda_bpc) | |
| 633 | 633 | cdi->cdda_method = CDDA_BPC_FULL; |
| 634 | 634 | else |
| 635 | 635 | cdi->cdda_method = CDDA_OLD; |
| @@ -2159,81 +2159,26 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, · 1523 unmodified lines | ||
| 2159 | 2159 | static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, |
| 2160 | 2160 | int lba, int nframes) |
| 2161 | 2161 | { |
| 2162 | − struct request_queue *q = cdi->disk->queue; | |
| 2163 | − struct request *rq; | |
| 2164 | − struct scsi_request *req; | |
| 2165 | − struct bio *bio; | |
| 2166 | − unsigned int len; | |
| 2162 | + int max_frames = (queue_max_sectors(cdi->disk->queue) << 9) / | |
| 2163 | + CD_FRAMESIZE_RAW; | |
| 2167 | 2164 | int nr, ret = 0; |
| 2168 | 2165 | |
| 2169 | − if (!q) | |
| 2170 | − return -ENXIO; | |
| 2171 | − | |
| 2172 | − if (!blk_queue_scsi_passthrough(q)) { | |
| 2173 | − WARN_ONCE(true, | |
| 2174 | − "Attempt read CDDA info through a non-SCSI queue\n"); | |
| 2175 | − return -EINVAL; | |
| 2176 | − } | |
| 2177 | − | |
| 2178 | 2166 | cdi->last_sense = 0; |
| 2179 | 2167 | |
| 2180 | 2168 | while (nframes) { |
| 2181 | − nr = nframes; | |
| 2182 | 2169 | if (cdi->cdda_method == CDDA_BPC_SINGLE) |
| 2183 | 2170 | nr = 1; |
| 2184 | − if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9)) | |
| 2185 | − nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW; | |
| 2186 | − | |
| 2187 | − len = nr * CD_FRAMESIZE_RAW; | |
| 2188 | − | |
| 2189 | − rq = blk_get_request(q, REQ_OP_DRV_IN, 0); | |
| 2190 | − if (IS_ERR(rq)) { | |
| 2191 | − ret = PTR_ERR(rq); | |
| 2192 | − break; | |
| 2193 | − } | |
| 2194 | − req = scsi_req(rq); | |
| 2195 | − | |
| 2196 | − ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL); | |
| 2197 | − if (ret) { | |
| 2198 | − blk_put_request(rq); | |
| 2199 | − break; | |
| 2200 | − } | |
| 2201 | − | |
| 2202 | − req->cmd[0] = GPCMD_READ_CD; | |
| 2203 | − req->cmd[1] = 1 << 2; | |
| 2204 | − req->cmd[2] = (lba >> 24) & 0xff; | |
| 2205 | − req->cmd[3] = (lba >> 16) & 0xff; | |
| 2206 | − req->cmd[4] = (lba >> 8) & 0xff; | |
| 2207 | − req->cmd[5] = lba & 0xff; | |
| 2208 | − req->cmd[6] = (nr >> 16) & 0xff; | |
| 2209 | − req->cmd[7] = (nr >> 8) & 0xff; | |
| 2210 | − req->cmd[8] = nr & 0xff; | |
| 2211 | − req->cmd[9] = 0xf8; | |
| 2212 | − | |
| 2213 | − req->cmd_len = 12; | |
| 2214 | − rq->timeout = 60 * HZ; | |
| 2215 | − bio = rq->bio; | |
| 2216 | − | |
| 2217 | − blk_execute_rq(cdi->disk, rq, 0); | |
| 2218 | − if (scsi_req(rq)->result) { | |
| 2219 | − struct scsi_sense_hdr sshdr; | |
| 2220 | − | |
| 2221 | − ret = -EIO; | |
| 2222 | − scsi_normalize_sense(req->sense, req->sense_len, | |
| 2223 | − &sshdr); | |
| 2224 | − cdi->last_sense = sshdr.sense_key; | |
| 2225 | − } | |
| 2226 | − | |
| 2227 | − if (blk_rq_unmap_user(bio)) | |
| 2228 | − ret = -EFAULT; | |
| 2229 | − blk_put_request(rq); | |
| 2171 | + else | |
| 2172 | + nr = min(nframes, max_frames); | |
| 2230 | 2173 | |
| 2174 | + ret = cdi->ops->read_cdda_bpc(cdi, ubuf, lba, nr, | |
| 2175 | + &cdi->last_sense); | |
| 2231 | 2176 | if (ret) |
| 2232 | 2177 | break; |
| 2233 | 2178 | |
| 2234 | 2179 | nframes -= nr; |
| 2235 | 2180 | lba += nr; |
| 2236 | − ubuf += len; | |
| 2181 | + ubuf += (nr * CD_FRAMESIZE_RAW); | |
| 2237 | 2182 | } |
| 2238 | 2183 | |
| 2239 | 2184 | return ret; |
| @@ -120,6 +120,8 @@ static void get_capabilities(struct scsi_cd *); · 119 unmodified lines | ||
| 120 | 120 | static unsigned int sr_check_events(struct cdrom_device_info *cdi, |
| 121 | 121 | unsigned int clearing, int slot); |
| 122 | 122 | static int sr_packet(struct cdrom_device_info *, struct packet_command *); |
| 123 | +static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, | |
| 124 | + u32 lba, u32 nr, u8 *last_sense); | |
| 123 | 125 | |
| 124 | 126 | static const struct cdrom_device_ops sr_dops = { |
| 125 | 127 | .open = sr_open, |
| @@ -133,8 +135,9 @@ static const struct cdrom_device_ops sr_dops = { · 7 unmodified lines | ||
| 133 | 135 | .get_mcn = sr_get_mcn, |
| 134 | 136 | .reset = sr_reset, |
| 135 | 137 | .audio_ioctl = sr_audio_ioctl, |
| 136 | − .capability = SR_CAPABILITIES, | |
| 137 | 138 | .generic_packet = sr_packet, |
| 139 | + .read_cdda_bpc = sr_read_cdda_bpc, | |
| 140 | + .capability = SR_CAPABILITIES, | |
| 138 | 141 | }; |
| 139 | 142 | |
| 140 | 143 | static void sr_kref_release(struct kref *kref); |
| @@ -951,6 +954,57 @@ static int sr_packet(struct cdrom_device_info *cdi, · 810 unmodified lines | ||
| 951 | 954 | return cgc->stat; |
| 952 | 955 | } |
| 953 | 956 | |
| 957 | +static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, | |
| 958 | + u32 lba, u32 nr, u8 *last_sense) | |
| 959 | +{ | |
| 960 | + struct gendisk *disk = cdi->disk; | |
| 961 | + u32 len = nr * CD_FRAMESIZE_RAW; | |
| 962 | + struct scsi_request *req; | |
| 963 | + struct request *rq; | |
| 964 | + struct bio *bio; | |
| 965 | + int ret; | |
| 966 | + | |
| 967 | + rq = blk_get_request(disk->queue, REQ_OP_DRV_IN, 0); | |
| 968 | + if (IS_ERR(rq)) | |
| 969 | + return PTR_ERR(rq); | |
| 970 | + req = scsi_req(rq); | |
| 971 | + | |
| 972 | + ret = blk_rq_map_user(disk->queue, rq, NULL, ubuf, len, GFP_KERNEL); | |
| 973 | + if (ret) | |
| 974 | + goto out_put_request; | |
| 975 | + | |
| 976 | + req->cmd[0] = GPCMD_READ_CD; | |
| 977 | + req->cmd[1] = 1 << 2; | |
| 978 | + req->cmd[2] = (lba >> 24) & 0xff; | |
| 979 | + req->cmd[3] = (lba >> 16) & 0xff; | |
| 980 | + req->cmd[4] = (lba >> 8) & 0xff; | |
| 981 | + req->cmd[5] = lba & 0xff; | |
| 982 | + req->cmd[6] = (nr >> 16) & 0xff; | |
| 983 | + req->cmd[7] = (nr >> 8) & 0xff; | |
| 984 | + req->cmd[8] = nr & 0xff; | |
| 985 | + req->cmd[9] = 0xf8; | |
| 986 | + req->cmd_len = 12; | |
| 987 | + rq->timeout = 60 * HZ; | |
| 988 | + bio = rq->bio; | |
| 989 | + | |
| 990 | + blk_execute_rq(disk, rq, 0); | |
| 991 | + if (scsi_req(rq)->result) { | |
| 992 | + struct scsi_sense_hdr sshdr; | |
| 993 | + | |
| 994 | + scsi_normalize_sense(req->sense, req->sense_len, | |
| 995 | + &sshdr); | |
| 996 | + *last_sense = sshdr.sense_key; | |
| 997 | + ret = -EIO; | |
| 998 | + } | |
| 999 | + | |
| 1000 | + if (blk_rq_unmap_user(bio)) | |
| 1001 | + ret = -EFAULT; | |
| 1002 | +out_put_request: | |
| 1003 | + blk_put_request(rq); | |
| 1004 | + return ret; | |
| 1005 | +} | |
| 1006 | + | |
| 1007 | + | |
| 954 | 1008 | /** |
| 955 | 1009 | * sr_kref_release - Called to free the scsi_cd structure |
| 956 | 1010 | * @kref: pointer to embedded kref |
| @@ -86,11 +86,13 @@ struct cdrom_device_ops { · 85 unmodified lines | ||
| 86 | 86 | /* play stuff */ |
| 87 | 87 | int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *); |
| 88 | 88 | |
| 89 | −/* driver specifications */ | |
| 90 | − const int capability; /* capability flags */ | |
| 91 | 89 | /* handle uniform packets for scsi type devices (scsi,atapi) */ |
| 92 | 90 | int (*generic_packet) (struct cdrom_device_info *, |
| 93 | 91 | struct packet_command *); |
| 92 | + int (*read_cdda_bpc)(struct cdrom_device_info *cdi, void __user *ubuf, | |
| 93 | + u32 lba, u32 nframes, u8 *last_sense); | |
| 94 | +/* driver specifications */ | |
| 95 | + const int capability; /* capability flags */ | |
| 94 | 96 | }; |
| 95 | 97 | |
| 96 | 98 | int cdrom_multisession(struct cdrom_device_info *cdi, |