diff options
author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2018-02-09 13:30:46 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2018-02-23 17:44:08 +0100 |
commit | fdbeb96258141d911ca8ba98931b9024038b84e0 (patch) | |
tree | 48e67807fb83b4e191608848a709e8ec20930dc0 /drivers/media/dvb-core | |
parent | media: dvb: add continuity error indicators for memory mapped buffers (diff) | |
download | linux-fdbeb96258141d911ca8ba98931b9024038b84e0.tar.xz linux-fdbeb96258141d911ca8ba98931b9024038b84e0.zip |
media: dvb: update buffer mmaped flags and frame counter
Now that we have support for a buffer counter and for
error flags, update them at DMX_DQBUF.
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/dvb-core')
-rw-r--r-- | drivers/media/dvb-core/dmxdev.c | 24 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_demux.c | 112 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_net.c | 5 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_vb2.c | 31 |
4 files changed, 113 insertions, 59 deletions
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 09c2626b5bf9..61a750fae465 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -385,7 +385,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_section_filter *filter) + struct dmx_section_filter *filter, + u32 *buffer_flags) { struct dmxdev_filter *dmxdevfilter = filter->priv; int ret; @@ -404,10 +405,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, dprintk("section callback %*ph\n", 6, buffer1); if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, - buffer1, buffer1_len); + buffer1, buffer1_len, + buffer_flags); if (ret == buffer1_len) ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, - buffer2, buffer2_len); + buffer2, buffer2_len, + buffer_flags); } else { ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len); @@ -427,7 +430,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_ts_feed *feed) + struct dmx_ts_feed *feed, + u32 *buffer_flags) { struct dmxdev_filter *dmxdevfilter = feed->priv; struct dvb_ringbuffer *buffer; @@ -456,9 +460,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, } if (dvb_vb2_is_streaming(ctx)) { - ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len); + ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len, + buffer_flags); if (ret == buffer1_len) - ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len); + ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len, + buffer_flags); } else { if (buffer->error) { spin_unlock(&dmxdevfilter->dev->lock); @@ -1218,7 +1224,7 @@ static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma) int ret; if (!dmxdev->may_do_mmap) - return -EOPNOTSUPP; + return -ENOTTY; if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; @@ -1318,7 +1324,7 @@ static int dvb_dvr_do_ioctl(struct file *file, break; #endif default: - ret = -EINVAL; + ret = -ENOTTY; break; } mutex_unlock(&dmxdev->mutex); @@ -1367,7 +1373,7 @@ static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma) int ret; if (!dmxdev->may_do_mmap) - return -EOPNOTSUPP; + return -ENOTTY; if (dmxdev->exit) return -ENODEV; diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 210eed0269b0..f45091246bdc 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -55,6 +55,17 @@ MODULE_PARM_DESC(dvb_demux_feed_err_pkts, dprintk(x); \ } while (0) +#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG +# define dprintk_sect_loss(x...) dprintk(x) +#else +# define dprintk_sect_loss(x...) +#endif + +#define set_buf_flags(__feed, __flag) \ + do { \ + (__feed)->buffer_flags |= (__flag); \ + } while (0) + /****************************************************************************** * static inlined helper functions ******************************************************************************/ @@ -104,31 +115,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, { int count = payload(buf); int p; -#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG int ccok; u8 cc; -#endif if (count == 0) return -1; p = 188 - count; -#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG cc = buf[3] & 0x0f; ccok = ((feed->cc + 1) & 0x0f) == cc; feed->cc = cc; - if (!ccok) - dprintk("missed packet: %d instead of %d!\n", - cc, (feed->cc + 1) & 0x0f); -#endif + if (!ccok) { + set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); + dprintk_sect_loss("missed packet: %d instead of %d!\n", + cc, (feed->cc + 1) & 0x0f); + } if (buf[1] & 0x40) // PUSI ? feed->peslen = 0xfffa; feed->peslen += count; - return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts); + return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, + &feed->buffer_flags); } static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, @@ -150,7 +160,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, return 0; return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen, - NULL, 0, &f->filter); + NULL, 0, &f->filter, &feed->buffer_flags); } static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) @@ -169,8 +179,10 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) if (sec->check_crc) { section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0); if (section_syntax_indicator && - demux->check_crc32(feed, sec->secbuf, sec->seclen)) + demux->check_crc32(feed, sec->secbuf, sec->seclen)) { + set_buf_flags(feed, DMX_BUFFER_FLAG_HAD_CRC32_DISCARD); return -1; + } } do { @@ -187,7 +199,6 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) { struct dmx_section_feed *sec = &feed->feed.sec; -#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG if (sec->secbufp < sec->tsfeedp) { int n = sec->tsfeedp - sec->secbufp; @@ -197,12 +208,13 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) * but just first and last. */ if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) { - dprintk("section ts padding loss: %d/%d\n", - n, sec->tsfeedp); - dprintk("pad data: %*ph\n", n, sec->secbuf); + set_buf_flags(feed, + DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); + dprintk_sect_loss("section ts padding loss: %d/%d\n", + n, sec->tsfeedp); + dprintk_sect_loss("pad data: %*ph\n", n, sec->secbuf); } } -#endif sec->tsfeedp = sec->secbufp = sec->seclen = 0; sec->secbuf = sec->secbuf_base; @@ -237,11 +249,10 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, return 0; if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) { -#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG - dprintk("section buffer full loss: %d/%d\n", - sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, - DMX_MAX_SECFEED_SIZE); -#endif + set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); + dprintk_sect_loss("section buffer full loss: %d/%d\n", + sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, + DMX_MAX_SECFEED_SIZE); len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; } @@ -269,12 +280,13 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, sec->seclen = seclen; sec->crc_val = ~0; /* dump [secbuf .. secbuf+seclen) */ - if (feed->pusi_seen) + if (feed->pusi_seen) { dvb_dmx_swfilter_section_feed(feed); -#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG - else - dprintk("pusi not seen, discarding section data\n"); -#endif + } else { + set_buf_flags(feed, + DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); + dprintk_sect_loss("pusi not seen, discarding section data\n"); + } sec->secbufp += seclen; /* secbufp and secbuf moving together is */ sec->secbuf += seclen; /* redundant but saves pointer arithmetic */ } @@ -307,18 +319,22 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, } if (!ccok || dc_i) { -#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG - if (dc_i) - dprintk("%d frame with disconnect indicator\n", + if (dc_i) { + set_buf_flags(feed, + DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR); + dprintk_sect_loss("%d frame with disconnect indicator\n", cc); - else - dprintk("discontinuity: %d instead of %d. %d bytes lost\n", + } else { + set_buf_flags(feed, + DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); + dprintk_sect_loss("discontinuity: %d instead of %d. %d bytes lost\n", cc, (feed->cc + 1) & 0x0f, count + 4); + } /* - * those bytes under sume circumstances will again be reported + * those bytes under some circumstances will again be reported * in the following dvb_dmx_swfilter_section_new */ -#endif + /* * Discontinuity detected. Reset pusi_seen to * stop feeding of suspicious data until next PUSI=1 arrives @@ -326,6 +342,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, * FIXME: does it make sense if the MPEG-TS is the one * reporting discontinuity? */ + feed->pusi_seen = false; dvb_dmx_swfilter_section_new(feed); } @@ -345,11 +362,11 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, dvb_dmx_swfilter_section_new(feed); dvb_dmx_swfilter_section_copy_dump(feed, after, after_len); + } else if (count > 0) { + set_buf_flags(feed, + DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); + dprintk_sect_loss("PUSI=1 but %d bytes lost\n", count); } -#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG - else if (count > 0) - dprintk("PUSI=1 but %d bytes lost\n", count); -#endif } else { /* PUSI=0 (is not set), no section boundary */ dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count); @@ -369,7 +386,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, if (feed->ts_type & TS_PAYLOAD_ONLY) dvb_dmx_swfilter_payload(feed, buf); else - feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); + feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, + &feed->buffer_flags); } /* Used only on full-featured devices */ if (feed->ts_type & TS_DECODER) @@ -430,6 +448,11 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) } if (buf[1] & 0x80) { + list_for_each_entry(feed, &demux->feed_list, list_head) { + if ((feed->pid != pid) && (feed->pid != 0x2000)) + continue; + set_buf_flags(feed, DMX_BUFFER_FLAG_TEI); + } dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n", pid, buf[1]); /* data in this packet can't be trusted - drop it unless @@ -445,6 +468,13 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) (demux->cnt_storage[pid] + 1) & 0xf; if ((buf[3] & 0xf) != demux->cnt_storage[pid]) { + list_for_each_entry(feed, &demux->feed_list, list_head) { + if ((feed->pid != pid) && (feed->pid != 0x2000)) + continue; + set_buf_flags(feed, + DMX_BUFFER_PKT_COUNTER_MISMATCH); + } + dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n", pid, demux->cnt_storage[pid], buf[3] & 0xf); @@ -466,7 +496,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) if (feed->pid == pid) dvb_dmx_swfilter_packet_type(feed, buf); else if (feed->pid == 0x2000) - feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts); + feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, + &feed->buffer_flags); } } @@ -585,7 +616,8 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count) spin_lock_irqsave(&demux->lock, flags); - demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts); + demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, + &demux->feed->buffer_flags); spin_unlock_irqrestore(&demux->lock, flags); } @@ -785,6 +817,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, feed->demux = demux; feed->pid = 0xffff; feed->peslen = 0xfffa; + feed->buffer_flags = 0; (*ts_feed) = &feed->feed.ts; (*ts_feed)->parent = dmx; @@ -1042,6 +1075,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, dvbdmxfeed->cb.sec = callback; dvbdmxfeed->demux = dvbdmx; dvbdmxfeed->pid = 0xffff; + dvbdmxfeed->buffer_flags = 0; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.tsfeedp = 0; diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index b6c7eec863b9..ba39f9942e1d 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -883,7 +883,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_ts_feed *feed) + struct dmx_ts_feed *feed, + u32 *buffer_flags) { struct net_device *dev = feed->priv; @@ -992,7 +993,7 @@ static void dvb_net_sec(struct net_device *dev, static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - struct dmx_section_filter *filter) + struct dmx_section_filter *filter, u32 *buffer_flags) { struct net_device *dev = filter->priv; diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c index 763145d74e83..b811adf88afa 100644 --- a/drivers/media/dvb-core/dvb_vb2.c +++ b/drivers/media/dvb-core/dvb_vb2.c @@ -256,7 +256,8 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx) } int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, - const unsigned char *src, int len) + const unsigned char *src, int len, + enum dmx_buffer_flags *buffer_flags) { unsigned long flags = 0; void *vbuf = NULL; @@ -264,15 +265,17 @@ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, unsigned char *psrc = (unsigned char *)src; int ll = 0; - dprintk(3, "[%s] %d bytes are rcvd\n", ctx->name, len); - if (!src) { - dprintk(3, "[%s]:NULL pointer src\n", ctx->name); - /**normal case: This func is called twice from demux driver - * once with valid src pointer, second time with NULL pointer - */ + /* + * normal case: This func is called twice from demux driver + * one with valid src pointer, second time with NULL pointer + */ + if (!src || !len) return 0; - } spin_lock_irqsave(&ctx->slock, flags); + if (buffer_flags && *buffer_flags) { + ctx->flags |= *buffer_flags; + *buffer_flags = 0; + } while (todo) { if (!ctx->buf) { if (list_empty(&ctx->dvb_q)) { @@ -395,6 +398,7 @@ int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) { + unsigned long flags; int ret; ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking); @@ -402,7 +406,16 @@ int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b) dprintk(1, "[%s] errno=%d\n", ctx->name, ret); return ret; } - dprintk(5, "[%s] index=%d\n", ctx->name, b->index); + + spin_lock_irqsave(&ctx->slock, flags); + b->count = ctx->count++; + b->flags = ctx->flags; + ctx->flags = 0; + spin_unlock_irqrestore(&ctx->slock, flags); + + dprintk(5, "[%s] index=%d, count=%d, flags=%d\n", + ctx->name, b->index, ctx->count, b->flags); + return 0; } |