cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vivid-kthread-out.c (10838B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * vivid-kthread-out.h - video/vbi output thread support functions.
      4 *
      5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
      6 */
      7
      8#include <linux/module.h>
      9#include <linux/errno.h>
     10#include <linux/kernel.h>
     11#include <linux/init.h>
     12#include <linux/sched.h>
     13#include <linux/slab.h>
     14#include <linux/font.h>
     15#include <linux/mutex.h>
     16#include <linux/videodev2.h>
     17#include <linux/kthread.h>
     18#include <linux/freezer.h>
     19#include <linux/random.h>
     20#include <linux/v4l2-dv-timings.h>
     21#include <linux/jiffies.h>
     22#include <asm/div64.h>
     23#include <media/videobuf2-vmalloc.h>
     24#include <media/v4l2-dv-timings.h>
     25#include <media/v4l2-ioctl.h>
     26#include <media/v4l2-fh.h>
     27#include <media/v4l2-event.h>
     28
     29#include "vivid-core.h"
     30#include "vivid-vid-common.h"
     31#include "vivid-vid-cap.h"
     32#include "vivid-vid-out.h"
     33#include "vivid-radio-common.h"
     34#include "vivid-radio-rx.h"
     35#include "vivid-radio-tx.h"
     36#include "vivid-sdr-cap.h"
     37#include "vivid-vbi-cap.h"
     38#include "vivid-vbi-out.h"
     39#include "vivid-osd.h"
     40#include "vivid-ctrls.h"
     41#include "vivid-kthread-out.h"
     42#include "vivid-meta-out.h"
     43
     44static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
     45{
     46	struct vivid_buffer *vid_out_buf = NULL;
     47	struct vivid_buffer *vbi_out_buf = NULL;
     48	struct vivid_buffer *meta_out_buf = NULL;
     49
     50	dprintk(dev, 1, "Video Output Thread Tick\n");
     51
     52	/* Drop a certain percentage of buffers. */
     53	if (dev->perc_dropped_buffers &&
     54	    prandom_u32_max(100) < dev->perc_dropped_buffers)
     55		return;
     56
     57	spin_lock(&dev->slock);
     58	/*
     59	 * Only dequeue buffer if there is at least one more pending.
     60	 * This makes video loopback possible.
     61	 */
     62	if (!list_empty(&dev->vid_out_active) &&
     63	    !list_is_singular(&dev->vid_out_active)) {
     64		vid_out_buf = list_entry(dev->vid_out_active.next,
     65					 struct vivid_buffer, list);
     66		list_del(&vid_out_buf->list);
     67	}
     68	if (!list_empty(&dev->vbi_out_active) &&
     69	    (dev->field_out != V4L2_FIELD_ALTERNATE ||
     70	     (dev->vbi_out_seq_count & 1))) {
     71		vbi_out_buf = list_entry(dev->vbi_out_active.next,
     72					 struct vivid_buffer, list);
     73		list_del(&vbi_out_buf->list);
     74	}
     75	if (!list_empty(&dev->meta_out_active)) {
     76		meta_out_buf = list_entry(dev->meta_out_active.next,
     77					  struct vivid_buffer, list);
     78		list_del(&meta_out_buf->list);
     79	}
     80	spin_unlock(&dev->slock);
     81
     82	if (!vid_out_buf && !vbi_out_buf && !meta_out_buf)
     83		return;
     84
     85	if (vid_out_buf) {
     86		v4l2_ctrl_request_setup(vid_out_buf->vb.vb2_buf.req_obj.req,
     87					&dev->ctrl_hdl_vid_out);
     88		v4l2_ctrl_request_complete(vid_out_buf->vb.vb2_buf.req_obj.req,
     89					   &dev->ctrl_hdl_vid_out);
     90		vid_out_buf->vb.sequence = dev->vid_out_seq_count;
     91		if (dev->field_out == V4L2_FIELD_ALTERNATE) {
     92			/*
     93			 * The sequence counter counts frames, not fields.
     94			 * So divide by two.
     95			 */
     96			vid_out_buf->vb.sequence /= 2;
     97		}
     98		vid_out_buf->vb.vb2_buf.timestamp =
     99			ktime_get_ns() + dev->time_wrap_offset;
    100		vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ?
    101				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
    102		dprintk(dev, 2, "vid_out buffer %d done\n",
    103			vid_out_buf->vb.vb2_buf.index);
    104	}
    105
    106	if (vbi_out_buf) {
    107		v4l2_ctrl_request_setup(vbi_out_buf->vb.vb2_buf.req_obj.req,
    108					&dev->ctrl_hdl_vbi_out);
    109		v4l2_ctrl_request_complete(vbi_out_buf->vb.vb2_buf.req_obj.req,
    110					   &dev->ctrl_hdl_vbi_out);
    111		if (dev->stream_sliced_vbi_out)
    112			vivid_sliced_vbi_out_process(dev, vbi_out_buf);
    113
    114		vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
    115		vbi_out_buf->vb.vb2_buf.timestamp =
    116			ktime_get_ns() + dev->time_wrap_offset;
    117		vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ?
    118				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
    119		dprintk(dev, 2, "vbi_out buffer %d done\n",
    120			vbi_out_buf->vb.vb2_buf.index);
    121	}
    122	if (meta_out_buf) {
    123		v4l2_ctrl_request_setup(meta_out_buf->vb.vb2_buf.req_obj.req,
    124					&dev->ctrl_hdl_meta_out);
    125		v4l2_ctrl_request_complete(meta_out_buf->vb.vb2_buf.req_obj.req,
    126					   &dev->ctrl_hdl_meta_out);
    127		vivid_meta_out_process(dev, meta_out_buf);
    128		meta_out_buf->vb.sequence = dev->meta_out_seq_count;
    129		meta_out_buf->vb.vb2_buf.timestamp =
    130			ktime_get_ns() + dev->time_wrap_offset;
    131		vb2_buffer_done(&meta_out_buf->vb.vb2_buf, dev->dqbuf_error ?
    132				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
    133		dprintk(dev, 2, "meta_out buffer %d done\n",
    134			meta_out_buf->vb.vb2_buf.index);
    135	}
    136
    137	dev->dqbuf_error = false;
    138}
    139
    140static int vivid_thread_vid_out(void *data)
    141{
    142	struct vivid_dev *dev = data;
    143	u64 numerators_since_start;
    144	u64 buffers_since_start;
    145	u64 next_jiffies_since_start;
    146	unsigned long jiffies_since_start;
    147	unsigned long cur_jiffies;
    148	unsigned wait_jiffies;
    149	unsigned numerator;
    150	unsigned denominator;
    151
    152	dprintk(dev, 1, "Video Output Thread Start\n");
    153
    154	set_freezable();
    155
    156	/* Resets frame counters */
    157	dev->out_seq_offset = 0;
    158	dev->out_seq_count = 0;
    159	dev->jiffies_vid_out = jiffies;
    160	dev->out_seq_resync = false;
    161	if (dev->time_wrap)
    162		dev->time_wrap_offset = dev->time_wrap - ktime_get_ns();
    163	else
    164		dev->time_wrap_offset = 0;
    165
    166	for (;;) {
    167		try_to_freeze();
    168		if (kthread_should_stop())
    169			break;
    170
    171		if (!mutex_trylock(&dev->mutex)) {
    172			schedule();
    173			continue;
    174		}
    175
    176		cur_jiffies = jiffies;
    177		if (dev->out_seq_resync) {
    178			dev->jiffies_vid_out = cur_jiffies;
    179			dev->out_seq_offset = dev->out_seq_count + 1;
    180			dev->out_seq_count = 0;
    181			dev->out_seq_resync = false;
    182		}
    183		numerator = dev->timeperframe_vid_out.numerator;
    184		denominator = dev->timeperframe_vid_out.denominator;
    185
    186		if (dev->field_out == V4L2_FIELD_ALTERNATE)
    187			denominator *= 2;
    188
    189		/* Calculate the number of jiffies since we started streaming */
    190		jiffies_since_start = cur_jiffies - dev->jiffies_vid_out;
    191		/* Get the number of buffers streamed since the start */
    192		buffers_since_start = (u64)jiffies_since_start * denominator +
    193				      (HZ * numerator) / 2;
    194		do_div(buffers_since_start, HZ * numerator);
    195
    196		/*
    197		 * After more than 0xf0000000 (rounded down to a multiple of
    198		 * 'jiffies-per-day' to ease jiffies_to_msecs calculation)
    199		 * jiffies have passed since we started streaming reset the
    200		 * counters and keep track of the sequence offset.
    201		 */
    202		if (jiffies_since_start > JIFFIES_RESYNC) {
    203			dev->jiffies_vid_out = cur_jiffies;
    204			dev->out_seq_offset = buffers_since_start;
    205			buffers_since_start = 0;
    206		}
    207		dev->out_seq_count = buffers_since_start + dev->out_seq_offset;
    208		dev->vid_out_seq_count = dev->out_seq_count - dev->vid_out_seq_start;
    209		dev->vbi_out_seq_count = dev->out_seq_count - dev->vbi_out_seq_start;
    210		dev->meta_out_seq_count = dev->out_seq_count - dev->meta_out_seq_start;
    211
    212		vivid_thread_vid_out_tick(dev);
    213		mutex_unlock(&dev->mutex);
    214
    215		/*
    216		 * Calculate the number of 'numerators' streamed since we started,
    217		 * not including the current buffer.
    218		 */
    219		numerators_since_start = buffers_since_start * numerator;
    220
    221		/* And the number of jiffies since we started */
    222		jiffies_since_start = jiffies - dev->jiffies_vid_out;
    223
    224		/* Increase by the 'numerator' of one buffer */
    225		numerators_since_start += numerator;
    226		/*
    227		 * Calculate when that next buffer is supposed to start
    228		 * in jiffies since we started streaming.
    229		 */
    230		next_jiffies_since_start = numerators_since_start * HZ +
    231					   denominator / 2;
    232		do_div(next_jiffies_since_start, denominator);
    233		/* If it is in the past, then just schedule asap */
    234		if (next_jiffies_since_start < jiffies_since_start)
    235			next_jiffies_since_start = jiffies_since_start;
    236
    237		wait_jiffies = next_jiffies_since_start - jiffies_since_start;
    238		while (time_is_after_jiffies(cur_jiffies + wait_jiffies) &&
    239		       !kthread_should_stop())
    240			schedule();
    241	}
    242	dprintk(dev, 1, "Video Output Thread End\n");
    243	return 0;
    244}
    245
    246static void vivid_grab_controls(struct vivid_dev *dev, bool grab)
    247{
    248	v4l2_ctrl_grab(dev->ctrl_has_crop_out, grab);
    249	v4l2_ctrl_grab(dev->ctrl_has_compose_out, grab);
    250	v4l2_ctrl_grab(dev->ctrl_has_scaler_out, grab);
    251	v4l2_ctrl_grab(dev->ctrl_tx_mode, grab);
    252	v4l2_ctrl_grab(dev->ctrl_tx_rgb_range, grab);
    253}
    254
    255int vivid_start_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
    256{
    257	dprintk(dev, 1, "%s\n", __func__);
    258
    259	if (dev->kthread_vid_out) {
    260		u32 seq_count = dev->out_seq_count + dev->seq_wrap * 128;
    261
    262		if (pstreaming == &dev->vid_out_streaming)
    263			dev->vid_out_seq_start = seq_count;
    264		else if (pstreaming == &dev->vbi_out_streaming)
    265			dev->vbi_out_seq_start = seq_count;
    266		else
    267			dev->meta_out_seq_start = seq_count;
    268		*pstreaming = true;
    269		return 0;
    270	}
    271
    272	/* Resets frame counters */
    273	dev->jiffies_vid_out = jiffies;
    274	dev->vid_out_seq_start = dev->seq_wrap * 128;
    275	dev->vbi_out_seq_start = dev->seq_wrap * 128;
    276	dev->meta_out_seq_start = dev->seq_wrap * 128;
    277
    278	dev->kthread_vid_out = kthread_run(vivid_thread_vid_out, dev,
    279			"%s-vid-out", dev->v4l2_dev.name);
    280
    281	if (IS_ERR(dev->kthread_vid_out)) {
    282		int err = PTR_ERR(dev->kthread_vid_out);
    283
    284		dev->kthread_vid_out = NULL;
    285		v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
    286		return err;
    287	}
    288	*pstreaming = true;
    289	vivid_grab_controls(dev, true);
    290
    291	dprintk(dev, 1, "returning from %s\n", __func__);
    292	return 0;
    293}
    294
    295void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
    296{
    297	dprintk(dev, 1, "%s\n", __func__);
    298
    299	if (dev->kthread_vid_out == NULL)
    300		return;
    301
    302	*pstreaming = false;
    303	if (pstreaming == &dev->vid_out_streaming) {
    304		/* Release all active buffers */
    305		while (!list_empty(&dev->vid_out_active)) {
    306			struct vivid_buffer *buf;
    307
    308			buf = list_entry(dev->vid_out_active.next,
    309					 struct vivid_buffer, list);
    310			list_del(&buf->list);
    311			v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
    312						   &dev->ctrl_hdl_vid_out);
    313			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
    314			dprintk(dev, 2, "vid_out buffer %d done\n",
    315				buf->vb.vb2_buf.index);
    316		}
    317	}
    318
    319	if (pstreaming == &dev->vbi_out_streaming) {
    320		while (!list_empty(&dev->vbi_out_active)) {
    321			struct vivid_buffer *buf;
    322
    323			buf = list_entry(dev->vbi_out_active.next,
    324					 struct vivid_buffer, list);
    325			list_del(&buf->list);
    326			v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
    327						   &dev->ctrl_hdl_vbi_out);
    328			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
    329			dprintk(dev, 2, "vbi_out buffer %d done\n",
    330				buf->vb.vb2_buf.index);
    331		}
    332	}
    333
    334	if (pstreaming == &dev->meta_out_streaming) {
    335		while (!list_empty(&dev->meta_out_active)) {
    336			struct vivid_buffer *buf;
    337
    338			buf = list_entry(dev->meta_out_active.next,
    339					 struct vivid_buffer, list);
    340			list_del(&buf->list);
    341			v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
    342						   &dev->ctrl_hdl_meta_out);
    343			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
    344			dprintk(dev, 2, "meta_out buffer %d done\n",
    345				buf->vb.vb2_buf.index);
    346		}
    347	}
    348
    349	if (dev->vid_out_streaming || dev->vbi_out_streaming ||
    350	    dev->meta_out_streaming)
    351		return;
    352
    353	/* shutdown control thread */
    354	vivid_grab_controls(dev, false);
    355	kthread_stop(dev->kthread_vid_out);
    356	dev->kthread_vid_out = NULL;
    357}