diff options
Diffstat (limited to 'drivers/media/dvb-core/dmxdev.c')
-rw-r--r-- | drivers/media/dvb-core/dmxdev.c | 115 |
1 files changed, 65 insertions, 50 deletions
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 6d53af00190e..61a750fae465 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c | |||
@@ -128,11 +128,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) | |||
128 | struct dvb_device *dvbdev = file->private_data; | 128 | struct dvb_device *dvbdev = file->private_data; |
129 | struct dmxdev *dmxdev = dvbdev->priv; | 129 | struct dmxdev *dmxdev = dvbdev->priv; |
130 | struct dmx_frontend *front; | 130 | struct dmx_frontend *front; |
131 | #ifndef DVB_MMAP | ||
132 | bool need_ringbuffer = false; | 131 | bool need_ringbuffer = false; |
133 | #else | ||
134 | const bool need_ringbuffer = true; | ||
135 | #endif | ||
136 | 132 | ||
137 | dprintk("%s\n", __func__); | 133 | dprintk("%s\n", __func__); |
138 | 134 | ||
@@ -144,17 +140,31 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) | |||
144 | return -ENODEV; | 140 | return -ENODEV; |
145 | } | 141 | } |
146 | 142 | ||
147 | #ifndef DVB_MMAP | 143 | dmxdev->may_do_mmap = 0; |
144 | |||
145 | /* | ||
146 | * The logic here is a little tricky due to the ifdef. | ||
147 | * | ||
148 | * The ringbuffer is used for both read and mmap. | ||
149 | * | ||
150 | * It is not needed, however, on two situations: | ||
151 | * - Write devices (access with O_WRONLY); | ||
152 | * - For duplex device nodes, opened with O_RDWR. | ||
153 | */ | ||
154 | |||
148 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | 155 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) |
149 | need_ringbuffer = true; | 156 | need_ringbuffer = true; |
150 | #else | 157 | else if ((file->f_flags & O_ACCMODE) == O_RDWR) { |
151 | if ((file->f_flags & O_ACCMODE) == O_RDWR) { | ||
152 | if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { | 158 | if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { |
159 | #ifdef CONFIG_DVB_MMAP | ||
160 | dmxdev->may_do_mmap = 1; | ||
161 | need_ringbuffer = true; | ||
162 | #else | ||
153 | mutex_unlock(&dmxdev->mutex); | 163 | mutex_unlock(&dmxdev->mutex); |
154 | return -EOPNOTSUPP; | 164 | return -EOPNOTSUPP; |
165 | #endif | ||
155 | } | 166 | } |
156 | } | 167 | } |
157 | #endif | ||
158 | 168 | ||
159 | if (need_ringbuffer) { | 169 | if (need_ringbuffer) { |
160 | void *mem; | 170 | void *mem; |
@@ -169,8 +179,9 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) | |||
169 | return -ENOMEM; | 179 | return -ENOMEM; |
170 | } | 180 | } |
171 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); | 181 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); |
172 | dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr", | 182 | if (dmxdev->may_do_mmap) |
173 | file->f_flags & O_NONBLOCK); | 183 | dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr", |
184 | file->f_flags & O_NONBLOCK); | ||
174 | dvbdev->readers--; | 185 | dvbdev->readers--; |
175 | } | 186 | } |
176 | 187 | ||
@@ -200,11 +211,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) | |||
200 | { | 211 | { |
201 | struct dvb_device *dvbdev = file->private_data; | 212 | struct dvb_device *dvbdev = file->private_data; |
202 | struct dmxdev *dmxdev = dvbdev->priv; | 213 | struct dmxdev *dmxdev = dvbdev->priv; |
203 | #ifndef DVB_MMAP | ||
204 | bool need_ringbuffer = false; | ||
205 | #else | ||
206 | const bool need_ringbuffer = true; | ||
207 | #endif | ||
208 | 214 | ||
209 | mutex_lock(&dmxdev->mutex); | 215 | mutex_lock(&dmxdev->mutex); |
210 | 216 | ||
@@ -213,15 +219,14 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) | |||
213 | dmxdev->demux->connect_frontend(dmxdev->demux, | 219 | dmxdev->demux->connect_frontend(dmxdev->demux, |
214 | dmxdev->dvr_orig_fe); | 220 | dmxdev->dvr_orig_fe); |
215 | } | 221 | } |
216 | #ifndef DVB_MMAP | ||
217 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | ||
218 | need_ringbuffer = true; | ||
219 | #endif | ||
220 | 222 | ||
221 | if (need_ringbuffer) { | 223 | if (((file->f_flags & O_ACCMODE) == O_RDONLY) || |
222 | if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) | 224 | dmxdev->may_do_mmap) { |
223 | dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx); | 225 | if (dmxdev->may_do_mmap) { |
224 | dvb_vb2_release(&dmxdev->dvr_vb2_ctx); | 226 | if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) |
227 | dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx); | ||
228 | dvb_vb2_release(&dmxdev->dvr_vb2_ctx); | ||
229 | } | ||
225 | dvbdev->readers++; | 230 | dvbdev->readers++; |
226 | if (dmxdev->dvr_buffer.data) { | 231 | if (dmxdev->dvr_buffer.data) { |
227 | void *mem = dmxdev->dvr_buffer.data; | 232 | void *mem = dmxdev->dvr_buffer.data; |
@@ -380,7 +385,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) | |||
380 | 385 | ||
381 | static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | 386 | static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, |
382 | const u8 *buffer2, size_t buffer2_len, | 387 | const u8 *buffer2, size_t buffer2_len, |
383 | struct dmx_section_filter *filter) | 388 | struct dmx_section_filter *filter, |
389 | u32 *buffer_flags) | ||
384 | { | 390 | { |
385 | struct dmxdev_filter *dmxdevfilter = filter->priv; | 391 | struct dmxdev_filter *dmxdevfilter = filter->priv; |
386 | int ret; | 392 | int ret; |
@@ -399,10 +405,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | |||
399 | dprintk("section callback %*ph\n", 6, buffer1); | 405 | dprintk("section callback %*ph\n", 6, buffer1); |
400 | if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { | 406 | if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { |
401 | ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, | 407 | ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, |
402 | buffer1, buffer1_len); | 408 | buffer1, buffer1_len, |
409 | buffer_flags); | ||
403 | if (ret == buffer1_len) | 410 | if (ret == buffer1_len) |
404 | ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, | 411 | ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, |
405 | buffer2, buffer2_len); | 412 | buffer2, buffer2_len, |
413 | buffer_flags); | ||
406 | } else { | 414 | } else { |
407 | ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, | 415 | ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, |
408 | buffer1, buffer1_len); | 416 | buffer1, buffer1_len); |
@@ -422,11 +430,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | |||
422 | 430 | ||
423 | static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | 431 | static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, |
424 | const u8 *buffer2, size_t buffer2_len, | 432 | const u8 *buffer2, size_t buffer2_len, |
425 | struct dmx_ts_feed *feed) | 433 | struct dmx_ts_feed *feed, |
434 | u32 *buffer_flags) | ||
426 | { | 435 | { |
427 | struct dmxdev_filter *dmxdevfilter = feed->priv; | 436 | struct dmxdev_filter *dmxdevfilter = feed->priv; |
428 | struct dvb_ringbuffer *buffer; | 437 | struct dvb_ringbuffer *buffer; |
429 | #ifdef DVB_MMAP | 438 | #ifdef CONFIG_DVB_MMAP |
430 | struct dvb_vb2_ctx *ctx; | 439 | struct dvb_vb2_ctx *ctx; |
431 | #endif | 440 | #endif |
432 | int ret; | 441 | int ret; |
@@ -440,20 +449,22 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | |||
440 | if (dmxdevfilter->params.pes.output == DMX_OUT_TAP || | 449 | if (dmxdevfilter->params.pes.output == DMX_OUT_TAP || |
441 | dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) { | 450 | dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) { |
442 | buffer = &dmxdevfilter->buffer; | 451 | buffer = &dmxdevfilter->buffer; |
443 | #ifdef DVB_MMAP | 452 | #ifdef CONFIG_DVB_MMAP |
444 | ctx = &dmxdevfilter->vb2_ctx; | 453 | ctx = &dmxdevfilter->vb2_ctx; |
445 | #endif | 454 | #endif |
446 | } else { | 455 | } else { |
447 | buffer = &dmxdevfilter->dev->dvr_buffer; | 456 | buffer = &dmxdevfilter->dev->dvr_buffer; |
448 | #ifdef DVB_MMAP | 457 | #ifdef CONFIG_DVB_MMAP |
449 | ctx = &dmxdevfilter->dev->dvr_vb2_ctx; | 458 | ctx = &dmxdevfilter->dev->dvr_vb2_ctx; |
450 | #endif | 459 | #endif |
451 | } | 460 | } |
452 | 461 | ||
453 | if (dvb_vb2_is_streaming(ctx)) { | 462 | if (dvb_vb2_is_streaming(ctx)) { |
454 | ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len); | 463 | ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len, |
464 | buffer_flags); | ||
455 | if (ret == buffer1_len) | 465 | if (ret == buffer1_len) |
456 | ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len); | 466 | ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len, |
467 | buffer_flags); | ||
457 | } else { | 468 | } else { |
458 | if (buffer->error) { | 469 | if (buffer->error) { |
459 | spin_unlock(&dmxdevfilter->dev->lock); | 470 | spin_unlock(&dmxdevfilter->dev->lock); |
@@ -802,6 +813,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file) | |||
802 | mutex_init(&dmxdevfilter->mutex); | 813 | mutex_init(&dmxdevfilter->mutex); |
803 | file->private_data = dmxdevfilter; | 814 | file->private_data = dmxdevfilter; |
804 | 815 | ||
816 | #ifdef CONFIG_DVB_MMAP | ||
817 | dmxdev->may_do_mmap = 1; | ||
818 | #else | ||
819 | dmxdev->may_do_mmap = 0; | ||
820 | #endif | ||
821 | |||
805 | dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); | 822 | dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); |
806 | dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter", | 823 | dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter", |
807 | file->f_flags & O_NONBLOCK); | 824 | file->f_flags & O_NONBLOCK); |
@@ -1111,7 +1128,7 @@ static int dvb_demux_do_ioctl(struct file *file, | |||
1111 | mutex_unlock(&dmxdevfilter->mutex); | 1128 | mutex_unlock(&dmxdevfilter->mutex); |
1112 | break; | 1129 | break; |
1113 | 1130 | ||
1114 | #ifdef DVB_MMAP | 1131 | #ifdef CONFIG_DVB_MMAP |
1115 | case DMX_REQBUFS: | 1132 | case DMX_REQBUFS: |
1116 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | 1133 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { |
1117 | mutex_unlock(&dmxdev->mutex); | 1134 | mutex_unlock(&dmxdev->mutex); |
@@ -1160,7 +1177,7 @@ static int dvb_demux_do_ioctl(struct file *file, | |||
1160 | break; | 1177 | break; |
1161 | #endif | 1178 | #endif |
1162 | default: | 1179 | default: |
1163 | ret = -EINVAL; | 1180 | ret = -ENOTTY; |
1164 | break; | 1181 | break; |
1165 | } | 1182 | } |
1166 | mutex_unlock(&dmxdev->mutex); | 1183 | mutex_unlock(&dmxdev->mutex); |
@@ -1199,13 +1216,16 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait) | |||
1199 | return mask; | 1216 | return mask; |
1200 | } | 1217 | } |
1201 | 1218 | ||
1202 | #ifdef DVB_MMAP | 1219 | #ifdef CONFIG_DVB_MMAP |
1203 | static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) | 1220 | static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) |
1204 | { | 1221 | { |
1205 | struct dmxdev_filter *dmxdevfilter = file->private_data; | 1222 | struct dmxdev_filter *dmxdevfilter = file->private_data; |
1206 | struct dmxdev *dmxdev = dmxdevfilter->dev; | 1223 | struct dmxdev *dmxdev = dmxdevfilter->dev; |
1207 | int ret; | 1224 | int ret; |
1208 | 1225 | ||
1226 | if (!dmxdev->may_do_mmap) | ||
1227 | return -ENOTTY; | ||
1228 | |||
1209 | if (mutex_lock_interruptible(&dmxdev->mutex)) | 1229 | if (mutex_lock_interruptible(&dmxdev->mutex)) |
1210 | return -ERESTARTSYS; | 1230 | return -ERESTARTSYS; |
1211 | 1231 | ||
@@ -1249,7 +1269,7 @@ static const struct file_operations dvb_demux_fops = { | |||
1249 | .release = dvb_demux_release, | 1269 | .release = dvb_demux_release, |
1250 | .poll = dvb_demux_poll, | 1270 | .poll = dvb_demux_poll, |
1251 | .llseek = default_llseek, | 1271 | .llseek = default_llseek, |
1252 | #ifdef DVB_MMAP | 1272 | #ifdef CONFIG_DVB_MMAP |
1253 | .mmap = dvb_demux_mmap, | 1273 | .mmap = dvb_demux_mmap, |
1254 | #endif | 1274 | #endif |
1255 | }; | 1275 | }; |
@@ -1280,7 +1300,7 @@ static int dvb_dvr_do_ioctl(struct file *file, | |||
1280 | ret = dvb_dvr_set_buffer_size(dmxdev, arg); | 1300 | ret = dvb_dvr_set_buffer_size(dmxdev, arg); |
1281 | break; | 1301 | break; |
1282 | 1302 | ||
1283 | #ifdef DVB_MMAP | 1303 | #ifdef CONFIG_DVB_MMAP |
1284 | case DMX_REQBUFS: | 1304 | case DMX_REQBUFS: |
1285 | ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg); | 1305 | ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg); |
1286 | break; | 1306 | break; |
@@ -1304,7 +1324,7 @@ static int dvb_dvr_do_ioctl(struct file *file, | |||
1304 | break; | 1324 | break; |
1305 | #endif | 1325 | #endif |
1306 | default: | 1326 | default: |
1307 | ret = -EINVAL; | 1327 | ret = -ENOTTY; |
1308 | break; | 1328 | break; |
1309 | } | 1329 | } |
1310 | mutex_unlock(&dmxdev->mutex); | 1330 | mutex_unlock(&dmxdev->mutex); |
@@ -1322,11 +1342,6 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) | |||
1322 | struct dvb_device *dvbdev = file->private_data; | 1342 | struct dvb_device *dvbdev = file->private_data; |
1323 | struct dmxdev *dmxdev = dvbdev->priv; | 1343 | struct dmxdev *dmxdev = dvbdev->priv; |
1324 | __poll_t mask = 0; | 1344 | __poll_t mask = 0; |
1325 | #ifndef DVB_MMAP | ||
1326 | bool need_ringbuffer = false; | ||
1327 | #else | ||
1328 | const bool need_ringbuffer = true; | ||
1329 | #endif | ||
1330 | 1345 | ||
1331 | dprintk("%s\n", __func__); | 1346 | dprintk("%s\n", __func__); |
1332 | 1347 | ||
@@ -1337,11 +1352,8 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) | |||
1337 | 1352 | ||
1338 | poll_wait(file, &dmxdev->dvr_buffer.queue, wait); | 1353 | poll_wait(file, &dmxdev->dvr_buffer.queue, wait); |
1339 | 1354 | ||
1340 | #ifndef DVB_MMAP | 1355 | if (((file->f_flags & O_ACCMODE) == O_RDONLY) || |
1341 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | 1356 | dmxdev->may_do_mmap) { |
1342 | need_ringbuffer = true; | ||
1343 | #endif | ||
1344 | if (need_ringbuffer) { | ||
1345 | if (dmxdev->dvr_buffer.error) | 1357 | if (dmxdev->dvr_buffer.error) |
1346 | mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); | 1358 | mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); |
1347 | 1359 | ||
@@ -1353,13 +1365,16 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) | |||
1353 | return mask; | 1365 | return mask; |
1354 | } | 1366 | } |
1355 | 1367 | ||
1356 | #ifdef DVB_MMAP | 1368 | #ifdef CONFIG_DVB_MMAP |
1357 | static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) | 1369 | static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) |
1358 | { | 1370 | { |
1359 | struct dvb_device *dvbdev = file->private_data; | 1371 | struct dvb_device *dvbdev = file->private_data; |
1360 | struct dmxdev *dmxdev = dvbdev->priv; | 1372 | struct dmxdev *dmxdev = dvbdev->priv; |
1361 | int ret; | 1373 | int ret; |
1362 | 1374 | ||
1375 | if (!dmxdev->may_do_mmap) | ||
1376 | return -ENOTTY; | ||
1377 | |||
1363 | if (dmxdev->exit) | 1378 | if (dmxdev->exit) |
1364 | return -ENODEV; | 1379 | return -ENODEV; |
1365 | 1380 | ||
@@ -1381,7 +1396,7 @@ static const struct file_operations dvb_dvr_fops = { | |||
1381 | .release = dvb_dvr_release, | 1396 | .release = dvb_dvr_release, |
1382 | .poll = dvb_dvr_poll, | 1397 | .poll = dvb_dvr_poll, |
1383 | .llseek = default_llseek, | 1398 | .llseek = default_llseek, |
1384 | #ifdef DVB_MMAP | 1399 | #ifdef CONFIG_DVB_MMAP |
1385 | .mmap = dvb_dvr_mmap, | 1400 | .mmap = dvb_dvr_mmap, |
1386 | #endif | 1401 | #endif |
1387 | }; | 1402 | }; |