media: vivid: fix timestamp and sequence wrapping
authorDeborah Brouwer <deborahbrouwer3563@gmail.com>
Wed, 8 Dec 2021 00:40:42 +0000 (01:40 +0100)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Sun, 23 Jan 2022 20:18:42 +0000 (21:18 +0100)
The error injection controls that test wrap-around sequence and timestamp
counters were partially broken. Add a menu option for 64 or 32 bit signed
timestamp wrapping. Prevent the timestamp from wrapping around before the
device can be tested.  Remove the sequence count from the timestamp
calculation so that sequence wrapping does not interfere with the
timestamp.  Add consistent time and sequence wrapping to sdr and touch
devices.

Signed-off-by: Deborah Brouwer <deborahbrouwer3563@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/test-drivers/vivid/vivid-core.h
drivers/media/test-drivers/vivid/vivid-ctrls.c
drivers/media/test-drivers/vivid/vivid-kthread-cap.c
drivers/media/test-drivers/vivid/vivid-kthread-out.c
drivers/media/test-drivers/vivid/vivid-kthread-touch.c
drivers/media/test-drivers/vivid/vivid-sdr-cap.c
drivers/media/test-drivers/vivid/vivid-touch-cap.c

index 45f96706edde6e8aeb3e7fe45708c0a142158ee7..176b72cb143b6fc83bbdca7a580241529a7986c5 100644 (file)
@@ -307,7 +307,7 @@ struct vivid_dev {
        bool                            dqbuf_error;
        bool                            req_validate_error;
        bool                            seq_wrap;
-       bool                            time_wrap;
+       u64                             time_wrap;
        u64                             time_wrap_offset;
        unsigned                        perc_dropped_buffers;
        enum vivid_signal_mode          std_signal_mode[MAX_INPUTS];
@@ -437,6 +437,7 @@ struct vivid_dev {
        bool                            touch_cap_seq_resync;
        u32                             touch_cap_seq_start;
        u32                             touch_cap_seq_count;
+       u32                             touch_cap_with_seq_wrap_count;
        bool                            touch_cap_streaming;
        struct v4l2_fract               timeperframe_tch_cap;
        struct v4l2_pix_format          tch_format;
@@ -524,7 +525,9 @@ struct vivid_dev {
        struct task_struct              *kthread_sdr_cap;
        unsigned long                   jiffies_sdr_cap;
        u32                             sdr_cap_seq_offset;
+       u32                             sdr_cap_seq_start;
        u32                             sdr_cap_seq_count;
+       u32                             sdr_cap_with_seq_wrap_count;
        bool                            sdr_cap_seq_resync;
 
        /* RDS generator */
index 8dc50fe229723f144601875b3f79cc5bc4c8ea9b..e7516dc1227b3307760813156c1249d2d27fd325 100644 (file)
@@ -1084,7 +1084,6 @@ static const struct v4l2_ctrl_config vivid_ctrl_display_present = {
 static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
-       u64 rem;
 
        switch (ctrl->id) {
        case VIVID_CID_DQBUF_ERROR:
@@ -1122,20 +1121,10 @@ static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
                break;
        case VIVID_CID_TIME_WRAP:
                dev->time_wrap = ctrl->val;
-               if (ctrl->val == 0) {
-                       dev->time_wrap_offset = 0;
-                       break;
-               }
-               /*
-                * We want to set the time 16 seconds before the 32 bit tv_sec
-                * value of struct timeval would wrap around. So first we
-                * calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and
-                * then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC).
-                */
-               div64_u64_rem(ktime_get_ns(),
-                       0x100000000ULL * NSEC_PER_SEC, &rem);
-               dev->time_wrap_offset =
-                       (0x100000000ULL - 16) * NSEC_PER_SEC - rem;
+               if (dev->time_wrap == 1)
+                       dev->time_wrap = (1ULL << 63) - NSEC_PER_SEC * 16ULL;
+               else if (dev->time_wrap == 2)
+                       dev->time_wrap = ((1ULL << 31) - 16) * NSEC_PER_SEC;
                break;
        }
        return 0;
@@ -1208,13 +1197,20 @@ static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
        .step = 1,
 };
 
+static const char * const vivid_ctrl_time_wrap_strings[] = {
+       "None",
+       "64 Bit",
+       "32 Bit",
+       NULL,
+};
+
 static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
        .ops = &vivid_streaming_ctrl_ops,
        .id = VIVID_CID_TIME_WRAP,
        .name = "Wrap Timestamp",
-       .type = V4L2_CTRL_TYPE_BOOLEAN,
-       .max = 1,
-       .step = 1,
+       .type = V4L2_CTRL_TYPE_MENU,
+       .max = ARRAY_SIZE(vivid_ctrl_time_wrap_strings) - 2,
+       .qmenu = vivid_ctrl_time_wrap_strings,
 };
 
 
index 9da730ccfa94f3579912cc9999ccc1025c64ede5..6baa046c1ae390915d97ee2e1eb21a695085d60a 100644 (file)
@@ -719,8 +719,7 @@ static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev,
        if (!vid_cap_buf && !vbi_cap_buf && !meta_cap_buf)
                goto update_mv;
 
-       f_time = dev->cap_frame_period * dev->vid_cap_seq_count +
-                dev->cap_stream_start + dev->time_wrap_offset;
+       f_time = ktime_get_ns() + dev->time_wrap_offset;
 
        if (vid_cap_buf) {
                v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req,
@@ -813,6 +812,10 @@ static int vivid_thread_vid_cap(void *data)
        dev->cap_seq_resync = false;
        dev->jiffies_vid_cap = jiffies;
        dev->cap_stream_start = ktime_get_ns();
+       if (dev->time_wrap)
+               dev->time_wrap_offset = dev->time_wrap - dev->cap_stream_start;
+       else
+               dev->time_wrap_offset = 0;
        vivid_cap_update_frame_period(dev);
 
        for (;;) {
index 79c57d14ac4e4710661fc274511e65e3a2c92a3a..b6d43169e970b3bc5886308ac0bd6dc22062a53f 100644 (file)
@@ -154,12 +154,13 @@ static int vivid_thread_vid_out(void *data)
 
        /* Resets frame counters */
        dev->out_seq_offset = 0;
-       if (dev->seq_wrap)
-               dev->out_seq_count = 0xffffff80U;
+       dev->out_seq_count = 0;
        dev->jiffies_vid_out = jiffies;
-       dev->vid_out_seq_start = dev->vbi_out_seq_start = 0;
-       dev->meta_out_seq_start = 0;
        dev->out_seq_resync = false;
+       if (dev->time_wrap)
+               dev->time_wrap_offset = dev->time_wrap - ktime_get_ns();
+       else
+               dev->time_wrap_offset = 0;
 
        for (;;) {
                try_to_freeze();
index 38fdfee794986add40261960436ea7440fe90d2d..f065faae4988819a0b2b8e045a84b808f51e9b2f 100644 (file)
@@ -62,6 +62,10 @@ static int vivid_thread_touch_cap(void *data)
        dev->touch_cap_seq_count = 0;
        dev->touch_cap_seq_resync = false;
        dev->jiffies_touch_cap = jiffies;
+       if (dev->time_wrap)
+               dev->time_wrap_offset = dev->time_wrap - ktime_get_ns();
+       else
+               dev->time_wrap_offset = 0;
 
        for (;;) {
                try_to_freeze();
@@ -102,6 +106,8 @@ static int vivid_thread_touch_cap(void *data)
                }
                dropped_bufs = buffers_since_start + dev->touch_cap_seq_offset - dev->touch_cap_seq_count;
                dev->touch_cap_seq_count = buffers_since_start + dev->touch_cap_seq_offset;
+               dev->touch_cap_with_seq_wrap_count =
+                       dev->touch_cap_seq_count - dev->touch_cap_seq_start;
 
                vivid_thread_tch_cap_tick(dev, dropped_bufs);
 
@@ -143,6 +149,7 @@ int vivid_start_generating_touch_cap(struct vivid_dev *dev)
                return 0;
        }
 
+       dev->touch_cap_seq_start = dev->seq_wrap * 128;
        dev->kthread_touch_cap = kthread_run(vivid_thread_touch_cap, dev,
                                             "%s-tch-cap", dev->v4l2_dev.name);
 
index 265db2114671f1da15dae9a9d28e1532ae30653e..59fd508e27c843d39ac2aeb8c9c7c3ee90d61b55 100644 (file)
@@ -101,7 +101,7 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
        spin_unlock(&dev->slock);
 
        if (sdr_cap_buf) {
-               sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count;
+               sdr_cap_buf->vb.sequence = dev->sdr_cap_with_seq_wrap_count;
                v4l2_ctrl_request_setup(sdr_cap_buf->vb.vb2_buf.req_obj.req,
                                        &dev->ctrl_hdl_sdr_cap);
                v4l2_ctrl_request_complete(sdr_cap_buf->vb.vb2_buf.req_obj.req,
@@ -131,10 +131,13 @@ static int vivid_thread_sdr_cap(void *data)
 
        /* Resets frame counters */
        dev->sdr_cap_seq_offset = 0;
-       if (dev->seq_wrap)
-               dev->sdr_cap_seq_offset = 0xffffff80U;
+       dev->sdr_cap_seq_count = 0;
        dev->jiffies_sdr_cap = jiffies;
        dev->sdr_cap_seq_resync = false;
+       if (dev->time_wrap)
+               dev->time_wrap_offset = dev->time_wrap - ktime_get_ns();
+       else
+               dev->time_wrap_offset = 0;
 
        for (;;) {
                try_to_freeze();
@@ -174,6 +177,7 @@ static int vivid_thread_sdr_cap(void *data)
                }
                dev->sdr_cap_seq_count =
                        buffers_since_start + dev->sdr_cap_seq_offset;
+               dev->sdr_cap_with_seq_wrap_count = dev->sdr_cap_seq_count - dev->sdr_cap_seq_start;
 
                vivid_thread_sdr_cap_tick(dev);
                mutex_unlock(&dev->mutex);
@@ -263,7 +267,7 @@ static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count)
        int err = 0;
 
        dprintk(dev, 1, "%s\n", __func__);
-       dev->sdr_cap_seq_count = 0;
+       dev->sdr_cap_seq_start = dev->seq_wrap * 128;
        if (dev->start_streaming_error) {
                dev->start_streaming_error = false;
                err = -EINVAL;
index ebb00b128030c9d88c4f4296c014a0766ac369e4..64e3e4cb30c20ce893c84933d39dafddd2018df0 100644 (file)
@@ -262,7 +262,7 @@ void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf)
 
        __s16 *tch_buf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 
-       buf->vb.sequence = dev->touch_cap_seq_count;
+       buf->vb.sequence = dev->touch_cap_with_seq_wrap_count;
        test_pattern = (buf->vb.sequence / TCH_SEQ_COUNT) % TEST_CASE_MAX;
        test_pat_idx = buf->vb.sequence % TCH_SEQ_COUNT;