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 | if (CDROM_CAN(CDC_MRW_W)) | 629 | if (CDROM_CAN(CDC_MRW_W)) |
| 630 | cdi->exit = cdrom_mrw_exit; | 630 | cdi->exit = cdrom_mrw_exit; |
| 631 | 631 | ||
| 632 | if (cdi->disk) | 632 | if (cdi->ops->read_cdda_bpc) |
| 633 | cdi->cdda_method = CDDA_BPC_FULL; | 633 | cdi->cdda_method = CDDA_BPC_FULL; |
| 634 | else | 634 | else |
| 635 | cdi->cdda_method = CDDA_OLD; | 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 | static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, | 2159 | static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, |
| 2160 | int lba, int nframes) | 2160 | int lba, int nframes) |
| 2161 | { | 2161 | { |
| 2162 | struct request_queue *q = cdi->disk->queue; | 2162 | int max_frames = (queue_max_sectors(cdi->disk->queue) << 9) / |
| 2163 | struct request *rq; | 2163 | CD_FRAMESIZE_RAW; |
| 2164 | struct scsi_request *req; | ||
| 2165 | struct bio *bio; | ||
| 2166 | unsigned int len; | ||
| 2167 | int nr, ret = 0; | 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 | cdi->last_sense = 0; | 2166 | cdi->last_sense = 0; |
| 2179 | 2167 | ||
| 2180 | while (nframes) { | 2168 | while (nframes) { |
| 2181 | nr = nframes; | ||
| 2182 | if (cdi->cdda_method == CDDA_BPC_SINGLE) | 2169 | if (cdi->cdda_method == CDDA_BPC_SINGLE) |
| 2183 | nr = 1; | 2170 | nr = 1; |
| 2184 | if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9)) | 2171 | else |
| 2185 | nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW; | 2172 | nr = min(nframes, max_frames); |
| 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); | ||
| 2230 | 2173 | ||
| 2174 | ret = cdi->ops->read_cdda_bpc(cdi, ubuf, lba, nr, | ||
| 2175 | &cdi->last_sense); | ||
| 2231 | if (ret) | 2176 | if (ret) |
| 2232 | break; | 2177 | break; |
| 2233 | 2178 | ||
| 2234 | nframes -= nr; | 2179 | nframes -= nr; |
| 2235 | lba += nr; | 2180 | lba += nr; |
| 2236 | ubuf += len; | 2181 | ubuf += (nr * CD_FRAMESIZE_RAW); |
| 2237 | } | 2182 | } |
| 2238 | 2183 | ||
| 2239 | return ret; | 2184 | return ret; |
| @@ -120,6 +120,8 @@ static void get_capabilities(struct scsi_cd *); · 119 unmodified lines | |||
| 120 | static unsigned int sr_check_events(struct cdrom_device_info *cdi, | 120 | static unsigned int sr_check_events(struct cdrom_device_info *cdi, |
| 121 | unsigned int clearing, int slot); | 121 | unsigned int clearing, int slot); |
| 122 | static int sr_packet(struct cdrom_device_info *, struct packet_command *); | 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 | static const struct cdrom_device_ops sr_dops = { | 126 | static const struct cdrom_device_ops sr_dops = { |
| 125 | .open = sr_open, | 127 | .open = sr_open, |
| @@ -133,8 +135,9 @@ static const struct cdrom_device_ops sr_dops = { · 7 unmodified lines | |||
| 133 | .get_mcn = sr_get_mcn, | 135 | .get_mcn = sr_get_mcn, |
| 134 | .reset = sr_reset, | 136 | .reset = sr_reset, |
| 135 | .audio_ioctl = sr_audio_ioctl, | 137 | .audio_ioctl = sr_audio_ioctl, |
| 136 | .capability = SR_CAPABILITIES, | ||
| 137 | .generic_packet = sr_packet, | 138 | .generic_packet = sr_packet, |
| 139 | .read_cdda_bpc = sr_read_cdda_bpc, | ||
| 140 | .capability = SR_CAPABILITIES, | ||
| 138 | }; | 141 | }; |
| 139 | 142 | ||
| 140 | static void sr_kref_release(struct kref *kref); | 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 | return cgc->stat; | 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 | * sr_kref_release - Called to free the scsi_cd structure | 1009 | * sr_kref_release - Called to free the scsi_cd structure |
| 956 | * @kref: pointer to embedded kref | 1010 | * @kref: pointer to embedded kref |
| @@ -86,11 +86,13 @@ struct cdrom_device_ops { · 85 unmodified lines | |||
| 86 | /* play stuff */ | 86 | /* play stuff */ |
| 87 | int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *); | 87 | int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *); |
| 88 | 88 | ||
| 89 | /* driver specifications */ | ||
| 90 | const int capability; /* capability flags */ | ||
| 91 | /* handle uniform packets for scsi type devices (scsi,atapi) */ | 89 | /* handle uniform packets for scsi type devices (scsi,atapi) */ |
| 92 | int (*generic_packet) (struct cdrom_device_info *, | 90 | int (*generic_packet) (struct cdrom_device_info *, |
| 93 | struct packet_command *); | 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 | int cdrom_multisession(struct cdrom_device_info *cdi, | 98 | int cdrom_multisession(struct cdrom_device_info *cdi, |