diff mbox

[v2,7/9,media] v4l2: introduce v4l2_timeval

Message ID 1442524780-781677-8-git-send-email-arnd@arndb.de (mailing list archive)
State New, archived
Headers show

Commit Message

Arnd Bergmann Sept. 17, 2015, 9:19 p.m. UTC
The v4l2 API uses a 'struct timeval' to communicate time stamps to user
space. This is broken on 32-bit architectures as soon as we have a C library
that defines time_t as 64 bit, which then changes the structure layout of
struct v4l2_buffer.

Since existing user space source code relies on the type to be 'struct
timeva' and we want to preserve compile-time compatibility when moving
to a new libc, we cannot make user-visible changes to the header file.

In this patch, we change the type of the timestamp to 'struct v4l2_timeval'
as a preparation for a follow-up that adds API compatiblity for both
32-bit and 64-bit time_t. This patch should have no impact on generated
code in either user space or kernel.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/media/pci/bt8xx/bttv-driver.c      |  2 +-
 drivers/media/pci/meye/meye.h              |  2 +-
 drivers/media/pci/zoran/zoran.h            |  2 +-
 drivers/media/platform/coda/coda.h         |  2 +-
 drivers/media/platform/omap/omap_vout.c    |  4 ++--
 drivers/media/platform/omap3isp/ispstat.c  |  3 ++-
 drivers/media/platform/omap3isp/ispstat.h  |  2 +-
 drivers/media/platform/vim2m.c             |  2 +-
 drivers/media/platform/vivid/vivid-ctrls.c |  2 +-
 drivers/media/usb/cpia2/cpia2.h            |  2 +-
 drivers/media/usb/cpia2/cpia2_v4l.c        |  2 +-
 drivers/media/usb/gspca/gspca.c            |  2 +-
 drivers/media/usb/usbvision/usbvision.h    |  2 +-
 drivers/media/v4l2-core/v4l2-common.c      |  6 +++---
 include/media/v4l2-common.h                |  2 +-
 include/media/videobuf-core.h              |  2 +-
 include/trace/events/v4l2.h                | 12 ++++++++++--
 include/uapi/linux/videodev2.h             | 17 +++++++++++++++++
 18 files changed, 47 insertions(+), 21 deletions(-)

Comments

Hans Verkuil Sept. 18, 2015, 8:05 a.m. UTC | #1
On 09/17/15 23:19, Arnd Bergmann wrote:
> The v4l2 API uses a 'struct timeval' to communicate time stamps to user
> space. This is broken on 32-bit architectures as soon as we have a C library
> that defines time_t as 64 bit, which then changes the structure layout of
> struct v4l2_buffer.
> 
> Since existing user space source code relies on the type to be 'struct
> timeva' and we want to preserve compile-time compatibility when moving

s/timeva/timeval/

> to a new libc, we cannot make user-visible changes to the header file.
> 
> In this patch, we change the type of the timestamp to 'struct v4l2_timeval'

Don't we need a kernel-wide timeval64? Rather than adding a v4l2-specific
struct?

> as a preparation for a follow-up that adds API compatiblity for both
> 32-bit and 64-bit time_t. This patch should have no impact on generated
> code in either user space or kernel.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/media/pci/bt8xx/bttv-driver.c      |  2 +-
>  drivers/media/pci/meye/meye.h              |  2 +-
>  drivers/media/pci/zoran/zoran.h            |  2 +-
>  drivers/media/platform/coda/coda.h         |  2 +-
>  drivers/media/platform/omap/omap_vout.c    |  4 ++--
>  drivers/media/platform/omap3isp/ispstat.c  |  3 ++-
>  drivers/media/platform/omap3isp/ispstat.h  |  2 +-
>  drivers/media/platform/vim2m.c             |  2 +-
>  drivers/media/platform/vivid/vivid-ctrls.c |  2 +-
>  drivers/media/usb/cpia2/cpia2.h            |  2 +-
>  drivers/media/usb/cpia2/cpia2_v4l.c        |  2 +-
>  drivers/media/usb/gspca/gspca.c            |  2 +-
>  drivers/media/usb/usbvision/usbvision.h    |  2 +-
>  drivers/media/v4l2-core/v4l2-common.c      |  6 +++---
>  include/media/v4l2-common.h                |  2 +-
>  include/media/videobuf-core.h              |  2 +-
>  include/trace/events/v4l2.h                | 12 ++++++++++--
>  include/uapi/linux/videodev2.h             | 17 +++++++++++++++++
>  18 files changed, 47 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
> index 15a4ebc2844d..b0ed8d799c14 100644
> --- a/drivers/media/pci/bt8xx/bttv-driver.c
> +++ b/drivers/media/pci/bt8xx/bttv-driver.c
> @@ -3585,7 +3585,7 @@ static void
>  bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
>  		      struct bttv_buffer_set *curr, unsigned int state)
>  {
> -	struct timeval ts;
> +	struct v4l2_timeval ts;
>  
>  	v4l2_get_timestamp(&ts);
>  
> diff --git a/drivers/media/pci/meye/meye.h b/drivers/media/pci/meye/meye.h
> index 751be5e533c7..a06aa5ba9abc 100644
> --- a/drivers/media/pci/meye/meye.h
> +++ b/drivers/media/pci/meye/meye.h
> @@ -281,7 +281,7 @@
>  struct meye_grab_buffer {
>  	int state;			/* state of buffer */
>  	unsigned long size;		/* size of jpg frame */
> -	struct timeval timestamp;	/* timestamp */
> +	struct v4l2_timeval timestamp;	/* timestamp */
>  	unsigned long sequence;		/* sequence number */
>  };
>  
> diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h
> index 4e7db8939c2b..9a9f782cede9 100644
> --- a/drivers/media/pci/zoran/zoran.h
> +++ b/drivers/media/pci/zoran/zoran.h
> @@ -39,7 +39,7 @@ struct zoran_sync {
>  	unsigned long frame;	/* number of buffer that has been free'd */
>  	unsigned long length;	/* number of code bytes in buffer (capture only) */
>  	unsigned long seq;	/* frame sequence number */
> -	struct timeval timestamp;	/* timestamp */
> +	struct v4l2_timeval timestamp;	/* timestamp */
>  };
>  
>  
> diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
> index 59b2af9c7749..fa1e15a757cd 100644
> --- a/drivers/media/platform/coda/coda.h
> +++ b/drivers/media/platform/coda/coda.h
> @@ -138,7 +138,7 @@ struct coda_buffer_meta {
>  	struct list_head	list;
>  	u32			sequence;
>  	struct v4l2_timecode	timecode;
> -	struct timeval		timestamp;
> +	struct v4l2_timeval	timestamp;
>  	u32			start;
>  	u32			end;
>  };
> diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
> index 70c28d19ea04..974a238a86fe 100644
> --- a/drivers/media/platform/omap/omap_vout.c
> +++ b/drivers/media/platform/omap/omap_vout.c
> @@ -513,7 +513,7 @@ static int omapvid_apply_changes(struct omap_vout_device *vout)
>  }
>  
>  static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
> -		unsigned int irqstatus, struct timeval timevalue)
> +		unsigned int irqstatus, struct v4l2_timeval timevalue)
>  {
>  	u32 fid;
>  
> @@ -557,7 +557,7 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus)
>  	int ret, fid, mgr_id;
>  	u32 addr, irq;
>  	struct omap_overlay *ovl;
> -	struct timeval timevalue;
> +	struct v4l2_timeval timevalue;
>  	struct omapvideo_info *ovid;
>  	struct omap_dss_device *cur_display;
>  	struct omap_vout_device *vout = (struct omap_vout_device *)arg;
> diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
> index 94d4c295d3d0..fa96e330c563 100644
> --- a/drivers/media/platform/omap3isp/ispstat.c
> +++ b/drivers/media/platform/omap3isp/ispstat.c
> @@ -496,7 +496,8 @@ int omap3isp_stat_request_statistics(struct ispstat *stat,
>  		return PTR_ERR(buf);
>  	}
>  
> -	data->ts = buf->ts;
> +	data->ts.tv_sec = buf->ts.tv_sec;
> +	data->ts.tv_usec = buf->ts.tv_usec;
>  	data->config_counter = buf->config_counter;
>  	data->frame_number = buf->frame_number;
>  	data->buf_size = buf->buf_size;
> diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
> index 6d9b0244f320..7b4f136567a3 100644
> --- a/drivers/media/platform/omap3isp/ispstat.h
> +++ b/drivers/media/platform/omap3isp/ispstat.h
> @@ -39,7 +39,7 @@ struct ispstat_buffer {
>  	struct sg_table sgt;
>  	void *virt_addr;
>  	dma_addr_t dma_addr;
> -	struct timeval ts;
> +	struct v4l2_timeval ts;
>  	u32 buf_size;
>  	u32 frame_number;
>  	u16 config_counter;
> diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
> index 295fde5fdb75..df5daac6d099 100644
> --- a/drivers/media/platform/vim2m.c
> +++ b/drivers/media/platform/vim2m.c
> @@ -235,7 +235,7 @@ static int device_process(struct vim2m_ctx *ctx,
>  	in_vb->v4l2_buf.sequence = q_data->sequence++;
>  	memcpy(&out_vb->v4l2_buf.timestamp,
>  			&in_vb->v4l2_buf.timestamp,
> -			sizeof(struct timeval));
> +			sizeof(struct v4l2_timeval));
>  	if (in_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE)
>  		memcpy(&out_vb->v4l2_buf.timecode, &in_vb->v4l2_buf.timecode,
>  			sizeof(struct v4l2_timecode));

See https://patchwork.linuxtv.org/patch/31405/

I'll merge that one for 4.4 very soon.

> diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
> index 339c8b7e53c8..065f3d6c2409 100644
> --- a/drivers/media/platform/vivid/vivid-ctrls.c
> +++ b/drivers/media/platform/vivid/vivid-ctrls.c
> @@ -935,7 +935,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
>  static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
>  {
>  	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
> -	struct timeval tv;
> +	struct v4l2_timeval tv;
>  
>  	switch (ctrl->id) {
>  	case VIVID_CID_DQBUF_ERROR:
> diff --git a/drivers/media/usb/cpia2/cpia2.h b/drivers/media/usb/cpia2/cpia2.h
> index cdef677d57ec..3e7c523784e7 100644
> --- a/drivers/media/usb/cpia2/cpia2.h
> +++ b/drivers/media/usb/cpia2/cpia2.h
> @@ -354,7 +354,7 @@ struct cpia2_sbuf {
>  };
>  
>  struct framebuf {
> -	struct timeval timestamp;
> +	struct v4l2_timeval timestamp;
>  	unsigned long seq;
>  	int num;
>  	int length;
> diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
> index 9caea8344547..ce50d7ef4da7 100644
> --- a/drivers/media/usb/cpia2/cpia2_v4l.c
> +++ b/drivers/media/usb/cpia2/cpia2_v4l.c
> @@ -892,7 +892,7 @@ static int find_earliest_filled_buffer(struct camera_data *cam)
>  				found = i;
>  			} else {
>  				/* find which buffer is earlier */
> -				struct timeval *tv1, *tv2;
> +				struct v4l2_timeval *tv1, *tv2;
>  				tv1 = &cam->buffers[i].timestamp;
>  				tv2 = &cam->buffers[found].timestamp;
>  				if(tv1->tv_sec < tv2->tv_sec ||
> diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
> index af5cd8213e8b..c977937da9c4 100644
> --- a/drivers/media/usb/gspca/gspca.c
> +++ b/drivers/media/usb/gspca/gspca.c
> @@ -1898,7 +1898,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
>  	struct gspca_dev *gspca_dev = video_drvdata(file);
>  	struct gspca_frame *frame;
>  	struct v4l2_buffer v4l2_buf;
> -	struct timeval timestamp;
> +	struct v4l2_timeval timestamp;
>  	int n, ret, ret2;
>  
>  	PDEBUG(D_FRAM, "read (%zd)", count);
> diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h
> index 4f2e4fde38f2..512de31613df 100644
> --- a/drivers/media/usb/usbvision/usbvision.h
> +++ b/drivers/media/usb/usbvision/usbvision.h
> @@ -320,7 +320,7 @@ struct usbvision_frame {
>  	long bytes_read;				/* amount of scanlength that has been read from data */
>  	struct usbvision_v4l2_format_st v4l2_format;	/* format the user needs*/
>  	int v4l2_linesize;				/* bytes for one videoline*/
> -	struct timeval timestamp;
> +	struct v4l2_timeval timestamp;
>  	int sequence;					/* How many video frames we send to user */
>  };
>  
> diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> index 5b808500e7e7..589fab615f21 100644
> --- a/drivers/media/v4l2-core/v4l2-common.c
> +++ b/drivers/media/v4l2-core/v4l2-common.c
> @@ -396,11 +396,11 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
>  }
>  EXPORT_SYMBOL_GPL(v4l2_find_nearest_format);
>  
> -void v4l2_get_timestamp(struct timeval *tv)
> +void v4l2_get_timestamp(struct v4l2_timeval *tv)
>  {
> -	struct timespec ts;
> +	struct timespec64 ts;
>  
> -	ktime_get_ts(&ts);
> +	ktime_get_ts64(&ts);
>  	tv->tv_sec = ts.tv_sec;
>  	tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
>  }
> diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
> index 1cc0c5ba16b3..6e77d889c3f8 100644
> --- a/include/media/v4l2-common.h
> +++ b/include/media/v4l2-common.h
> @@ -187,6 +187,6 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
>  		const struct v4l2_discrete_probe *probe,
>  		s32 width, s32 height);
>  
> -void v4l2_get_timestamp(struct timeval *tv);
> +void v4l2_get_timestamp(struct v4l2_timeval *tv);
>  
>  #endif /* V4L2_COMMON_H_ */
> diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
> index d760aa73ebbb..6381338a9588 100644
> --- a/include/media/videobuf-core.h
> +++ b/include/media/videobuf-core.h
> @@ -80,7 +80,7 @@ struct videobuf_buffer {
>  	struct list_head        queue;
>  	wait_queue_head_t       done;
>  	unsigned int            field_count;
> -	struct timeval          ts;
> +	struct v4l2_timeval     ts;
>  
>  	/* Memory type */
>  	enum v4l2_memory        memory;
> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
> index dbf017bfddd9..a88be48dc473 100644
> --- a/include/trace/events/v4l2.h
> +++ b/include/trace/events/v4l2.h
> @@ -6,6 +6,14 @@
>  
>  #include <linux/tracepoint.h>
>  
> +#ifndef v4l2_timeval_to_ns
> +#define v4l2_timeval_to_ns v4l2_timeval_to_ns
> +static inline u64 v4l2_timeval_to_ns(struct v4l2_timeval *tv)
> +{
> +	return (u64)tv->tv_sec * NSEC_PER_SEC + tv->tv_usec * NSEC_PER_USEC;
> +}
> +#endif
> +
>  /* Enums require being exported to userspace, for user tool parsing */
>  #undef EM
>  #undef EMe
> @@ -126,7 +134,7 @@ DECLARE_EVENT_CLASS(v4l2_event_class,
>  		__entry->bytesused = buf->bytesused;
>  		__entry->flags = buf->flags;
>  		__entry->field = buf->field;
> -		__entry->timestamp = timeval_to_ns(&buf->timestamp);
> +		__entry->timestamp = v4l2_timeval_to_ns(&buf->timestamp);
>  		__entry->timecode_type = buf->timecode.type;
>  		__entry->timecode_flags = buf->timecode.flags;
>  		__entry->timecode_frames = buf->timecode.frames;
> @@ -211,7 +219,7 @@ DECLARE_EVENT_CLASS(vb2_event_class,
>  		__entry->bytesused = vb->v4l2_planes[0].bytesused;
>  		__entry->flags = vb->v4l2_buf.flags;
>  		__entry->field = vb->v4l2_buf.field;
> -		__entry->timestamp = timeval_to_ns(&vb->v4l2_buf.timestamp);
> +		__entry->timestamp = v4l2_timeval_to_ns(&vb->v4l2_buf.timestamp);
>  		__entry->timecode_type = vb->v4l2_buf.timecode.type;
>  		__entry->timecode_flags = vb->v4l2_buf.timecode.flags;
>  		__entry->timecode_frames = vb->v4l2_buf.timecode.frames;
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 3e2c497c31fd..450b3249ba30 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -803,6 +803,19 @@ struct v4l2_plane {
>  	__u32			reserved[11];
>  };
>  
> +#ifdef __KERNEL__
> +/*
> + * This is used for the in-kernel version of v4l2_buffer, as we are
> + * migrating away from using time_t based structures in the kernel.
> + * User space might see this defined either using 32-bit or 64-bit
> + * time_t, so we have to convert it when accessing user data.
> + */
> +struct v4l2_timeval {
> +	long tv_sec;
> +	long tv_usec;
> +};
> +#endif
> +
>  /**
>   * struct v4l2_buffer - video buffer info
>   * @index:	id number of the buffer
> @@ -839,7 +852,11 @@ struct v4l2_buffer {
>  	__u32			bytesused;
>  	__u32			flags;
>  	__u32			field;
> +#ifdef __KERNEL__
> +	struct v4l2_timeval	timestamp;
> +#else
>  	struct timeval		timestamp;
> +#endif
>  	struct v4l2_timecode	timecode;
>  	__u32			sequence;
>  
> 

Regards,

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann Sept. 18, 2015, 9:09 a.m. UTC | #2
On Friday 18 September 2015 10:05:06 Hans Verkuil wrote:
> On 09/17/15 23:19, Arnd Bergmann wrote:
> > The v4l2 API uses a 'struct timeval' to communicate time stamps to user
> > space. This is broken on 32-bit architectures as soon as we have a C library
> > that defines time_t as 64 bit, which then changes the structure layout of
> > struct v4l2_buffer.
> > 
> > Since existing user space source code relies on the type to be 'struct
> > timeva' and we want to preserve compile-time compatibility when moving
> 
> s/timeva/timeval/

Fixed

> > to a new libc, we cannot make user-visible changes to the header file.
> > 
> > In this patch, we change the type of the timestamp to 'struct v4l2_timeval'
> 
> Don't we need a kernel-wide timeval64? Rather than adding a v4l2-specific
> struct?

I still hope to avoid doing that. All in-kernel users should be changed to
use timespec64 or ktime_t, which are always more efficient and accurate.

For the system call interface, all timeval APIs are deprecated and have
replacements using timespec64 (e.g. clock_gettime() replaces gettimeofday).

Only a handful of ioctls pass timeval, and so far my impression is that
we are better off handling each one separately. The total amount of code
we need to add this way should be less than if we have to duplicate all
common code functions that today operate on timeval and can eventually
get removed.

> > diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
> > index 295fde5fdb75..df5daac6d099 100644
> > --- a/drivers/media/platform/vim2m.c
> > +++ b/drivers/media/platform/vim2m.c
> > @@ -235,7 +235,7 @@ static int device_process(struct vim2m_ctx *ctx,
> >  	in_vb->v4l2_buf.sequence = q_data->sequence++;
> >  	memcpy(&out_vb->v4l2_buf.timestamp,
> >  			&in_vb->v4l2_buf.timestamp,
> > -			sizeof(struct timeval));
> > +			sizeof(struct v4l2_timeval));
> >  	if (in_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE)
> >  		memcpy(&out_vb->v4l2_buf.timecode, &in_vb->v4l2_buf.timecode,
> >  			sizeof(struct v4l2_timecode));
> 
> See https://patchwork.linuxtv.org/patch/31405/
> 
> I'll merge that one for 4.4 very soon.

Ok.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil Sept. 18, 2015, 9:27 a.m. UTC | #3
On 09/18/15 11:09, Arnd Bergmann wrote:
> On Friday 18 September 2015 10:05:06 Hans Verkuil wrote:
>> On 09/17/15 23:19, Arnd Bergmann wrote:
>>> The v4l2 API uses a 'struct timeval' to communicate time stamps to user
>>> space. This is broken on 32-bit architectures as soon as we have a C library
>>> that defines time_t as 64 bit, which then changes the structure layout of
>>> struct v4l2_buffer.
>>>
>>> Since existing user space source code relies on the type to be 'struct
>>> timeva' and we want to preserve compile-time compatibility when moving
>>
>> s/timeva/timeval/
> 
> Fixed
> 
>>> to a new libc, we cannot make user-visible changes to the header file.
>>>
>>> In this patch, we change the type of the timestamp to 'struct v4l2_timeval'
>>
>> Don't we need a kernel-wide timeval64? Rather than adding a v4l2-specific
>> struct?
> 
> I still hope to avoid doing that. All in-kernel users should be changed to
> use timespec64 or ktime_t, which are always more efficient and accurate.
> 
> For the system call interface, all timeval APIs are deprecated and have
> replacements using timespec64 (e.g. clock_gettime() replaces gettimeofday).
> 
> Only a handful of ioctls pass timeval, and so far my impression is that
> we are better off handling each one separately. The total amount of code
> we need to add this way should be less than if we have to duplicate all
> common code functions that today operate on timeval and can eventually
> get removed.

Ah, OK. Got it.

I think this is dependent on the upcoming media workshop next month. If we
decide to redesign v4l2_buffer anyway, then we can avoid timeval completely.
And the only place where we would need to convert it in the compat code
hidden in the v4l2 core (likely v4l2-ioctl.c).

I am not really keen on having v4l2_timeval in all these drivers. I would
have to check them anyway since I suspect that in several drivers the local
timeval variable can be avoided by rewriting that part of the driver.

Personally I am in favor of a redesigned v4l2_buffer: it's awkward to use
with multiplanar formats, there is cruft in there that can be removed (timecode),
and there is little space for additions (HW-specific timecodes, more buffer
meta data, etc).

We'll see.

Regards,

	Hans

> 
>>> diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
>>> index 295fde5fdb75..df5daac6d099 100644
>>> --- a/drivers/media/platform/vim2m.c
>>> +++ b/drivers/media/platform/vim2m.c
>>> @@ -235,7 +235,7 @@ static int device_process(struct vim2m_ctx *ctx,
>>>  	in_vb->v4l2_buf.sequence = q_data->sequence++;
>>>  	memcpy(&out_vb->v4l2_buf.timestamp,
>>>  			&in_vb->v4l2_buf.timestamp,
>>> -			sizeof(struct timeval));
>>> +			sizeof(struct v4l2_timeval));
>>>  	if (in_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE)
>>>  		memcpy(&out_vb->v4l2_buf.timecode, &in_vb->v4l2_buf.timecode,
>>>  			sizeof(struct v4l2_timecode));
>>
>> See https://patchwork.linuxtv.org/patch/31405/
>>
>> I'll merge that one for 4.4 very soon.
> 
> Ok.
> 
> 	Arnd
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann Sept. 18, 2015, 9:43 a.m. UTC | #4
On Friday 18 September 2015 11:27:40 Hans Verkuil wrote:
> Ah, OK. Got it.
> 
> I think this is dependent on the upcoming media workshop next month. If we
> decide to redesign v4l2_buffer anyway, then we can avoid timeval completely.
> And the only place where we would need to convert it in the compat code
> hidden in the v4l2 core (likely v4l2-ioctl.c).

Ah, I think I understood the idea now, I missed that earlier when you mention
the idea.

So what you are saying here is that you could come up with a new unambiguous
(using only __u32 and __u64 types and no pointers) format that gets exposed
to a new set of ioctls, and then change the handling of the existing three
formats (native 64-bit, traditional 32-bit, and 32-bit with 64-bit time_t)
so they get converted into the new format by the common ioctl handling code?

> I am not really keen on having v4l2_timeval in all these drivers. I would
> have to check them anyway since I suspect that in several drivers the local
> timeval variable can be avoided by rewriting that part of the driver.

I've tried to do that for all the drivers where I could find an easy solution
in patch 6/9, but I'm sure you can do it for a couple more.

We could also do a lightweight redesign and use 'timespec64' internally
in all the drivers and then convert that to 'timeval' or the 64-bit
format of that in the ioctl handler. This is also something I tried at
some point but then found it a bit more intuitive to leave the normal ioctl
path alone and have an explicit type.

> Personally I am in favor of a redesigned v4l2_buffer: it's awkward to use
> with multiplanar formats, there is cruft in there that can be removed (timecode),
> and there is little space for additions (HW-specific timecodes, more buffer
> meta data, etc).
> 
> We'll see.

Ok.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil Sept. 18, 2015, 9:52 a.m. UTC | #5
On 09/18/15 11:43, Arnd Bergmann wrote:
> On Friday 18 September 2015 11:27:40 Hans Verkuil wrote:
>> Ah, OK. Got it.
>>
>> I think this is dependent on the upcoming media workshop next month. If we
>> decide to redesign v4l2_buffer anyway, then we can avoid timeval completely.
>> And the only place where we would need to convert it in the compat code
>> hidden in the v4l2 core (likely v4l2-ioctl.c).
> 
> Ah, I think I understood the idea now, I missed that earlier when you mention
> the idea.
> 
> So what you are saying here is that you could come up with a new unambiguous
> (using only __u32 and __u64 types and no pointers) format that gets exposed
> to a new set of ioctls, and then change the handling of the existing three
> formats (native 64-bit, traditional 32-bit, and 32-bit with 64-bit time_t)
> so they get converted into the new format by the common ioctl handling code?

Right. Drivers only see the new struct, and only v4l2-ioctl.c (and possible
v4l2-compat-ioctl32.c) see the old ones.

BTW, I will probably pick up patches 4 and 6 for 4.4. That should help a bit.

Regards,

	Hans

>> I am not really keen on having v4l2_timeval in all these drivers. I would
>> have to check them anyway since I suspect that in several drivers the local
>> timeval variable can be avoided by rewriting that part of the driver.
> 
> I've tried to do that for all the drivers where I could find an easy solution
> in patch 6/9, but I'm sure you can do it for a couple more.
> 
> We could also do a lightweight redesign and use 'timespec64' internally
> in all the drivers and then convert that to 'timeval' or the 64-bit
> format of that in the ioctl handler. This is also something I tried at
> some point but then found it a bit more intuitive to leave the normal ioctl
> path alone and have an explicit type.
> 
>> Personally I am in favor of a redesigned v4l2_buffer: it's awkward to use
>> with multiplanar formats, there is cruft in there that can be removed (timecode),
>> and there is little space for additions (HW-specific timecodes, more buffer
>> meta data, etc).
>>
>> We'll see.
> 
> Ok.
> 
> 	Arnd
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arnd Bergmann Sept. 18, 2015, 10:08 a.m. UTC | #6
On Friday 18 September 2015 11:52:28 Hans Verkuil wrote:
> On 09/18/15 11:43, Arnd Bergmann wrote:
> > On Friday 18 September 2015 11:27:40 Hans Verkuil wrote:
> >> Ah, OK. Got it.
> >>
> >> I think this is dependent on the upcoming media workshop next month. If we
> >> decide to redesign v4l2_buffer anyway, then we can avoid timeval completely.
> >> And the only place where we would need to convert it in the compat code
> >> hidden in the v4l2 core (likely v4l2-ioctl.c).
> > 
> > Ah, I think I understood the idea now, I missed that earlier when you mention
> > the idea.
> > 
> > So what you are saying here is that you could come up with a new unambiguous
> > (using only __u32 and __u64 types and no pointers) format that gets exposed
> > to a new set of ioctls, and then change the handling of the existing three
> > formats (native 64-bit, traditional 32-bit, and 32-bit with 64-bit time_t)
> > so they get converted into the new format by the common ioctl handling code?
> 
> Right. Drivers only see the new struct, and only v4l2-ioctl.c (and possible
> v4l2-compat-ioctl32.c) see the old ones.
> 
> BTW, I will probably pick up patches 4 and 6 for 4.4. That should help a bit.

Ok, thanks!

I guess it's up to Mauro to pick up the first three patches?

As I don't see anything more to do for me here until you've had the
discussion about the new format, I'll move on to another subsystem now.
I have around 70 patches waiting to be submitted, plus the system call
series.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil Sept. 18, 2015, 10:22 a.m. UTC | #7
On 09/18/15 12:08, Arnd Bergmann wrote:
> On Friday 18 September 2015 11:52:28 Hans Verkuil wrote:
>> On 09/18/15 11:43, Arnd Bergmann wrote:
>>> On Friday 18 September 2015 11:27:40 Hans Verkuil wrote:
>>>> Ah, OK. Got it.
>>>>
>>>> I think this is dependent on the upcoming media workshop next month. If we
>>>> decide to redesign v4l2_buffer anyway, then we can avoid timeval completely.
>>>> And the only place where we would need to convert it in the compat code
>>>> hidden in the v4l2 core (likely v4l2-ioctl.c).
>>>
>>> Ah, I think I understood the idea now, I missed that earlier when you mention
>>> the idea.
>>>
>>> So what you are saying here is that you could come up with a new unambiguous
>>> (using only __u32 and __u64 types and no pointers) format that gets exposed
>>> to a new set of ioctls, and then change the handling of the existing three
>>> formats (native 64-bit, traditional 32-bit, and 32-bit with 64-bit time_t)
>>> so they get converted into the new format by the common ioctl handling code?
>>
>> Right. Drivers only see the new struct, and only v4l2-ioctl.c (and possible
>> v4l2-compat-ioctl32.c) see the old ones.
>>
>> BTW, I will probably pick up patches 4 and 6 for 4.4. That should help a bit.
> 
> Ok, thanks!
> 
> I guess it's up to Mauro to pick up the first three patches?

Yes.

> As I don't see anything more to do for me here until you've had the
> discussion about the new format, I'll move on to another subsystem now.
> I have around 70 patches waiting to be submitted, plus the system call
> series.

Agreed.

Thanks again for working on this!

Regards,

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 15a4ebc2844d..b0ed8d799c14 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -3585,7 +3585,7 @@  static void
 bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
 		      struct bttv_buffer_set *curr, unsigned int state)
 {
-	struct timeval ts;
+	struct v4l2_timeval ts;
 
 	v4l2_get_timestamp(&ts);
 
diff --git a/drivers/media/pci/meye/meye.h b/drivers/media/pci/meye/meye.h
index 751be5e533c7..a06aa5ba9abc 100644
--- a/drivers/media/pci/meye/meye.h
+++ b/drivers/media/pci/meye/meye.h
@@ -281,7 +281,7 @@ 
 struct meye_grab_buffer {
 	int state;			/* state of buffer */
 	unsigned long size;		/* size of jpg frame */
-	struct timeval timestamp;	/* timestamp */
+	struct v4l2_timeval timestamp;	/* timestamp */
 	unsigned long sequence;		/* sequence number */
 };
 
diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h
index 4e7db8939c2b..9a9f782cede9 100644
--- a/drivers/media/pci/zoran/zoran.h
+++ b/drivers/media/pci/zoran/zoran.h
@@ -39,7 +39,7 @@  struct zoran_sync {
 	unsigned long frame;	/* number of buffer that has been free'd */
 	unsigned long length;	/* number of code bytes in buffer (capture only) */
 	unsigned long seq;	/* frame sequence number */
-	struct timeval timestamp;	/* timestamp */
+	struct v4l2_timeval timestamp;	/* timestamp */
 };
 
 
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 59b2af9c7749..fa1e15a757cd 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -138,7 +138,7 @@  struct coda_buffer_meta {
 	struct list_head	list;
 	u32			sequence;
 	struct v4l2_timecode	timecode;
-	struct timeval		timestamp;
+	struct v4l2_timeval	timestamp;
 	u32			start;
 	u32			end;
 };
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index 70c28d19ea04..974a238a86fe 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -513,7 +513,7 @@  static int omapvid_apply_changes(struct omap_vout_device *vout)
 }
 
 static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
-		unsigned int irqstatus, struct timeval timevalue)
+		unsigned int irqstatus, struct v4l2_timeval timevalue)
 {
 	u32 fid;
 
@@ -557,7 +557,7 @@  static void omap_vout_isr(void *arg, unsigned int irqstatus)
 	int ret, fid, mgr_id;
 	u32 addr, irq;
 	struct omap_overlay *ovl;
-	struct timeval timevalue;
+	struct v4l2_timeval timevalue;
 	struct omapvideo_info *ovid;
 	struct omap_dss_device *cur_display;
 	struct omap_vout_device *vout = (struct omap_vout_device *)arg;
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index 94d4c295d3d0..fa96e330c563 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -496,7 +496,8 @@  int omap3isp_stat_request_statistics(struct ispstat *stat,
 		return PTR_ERR(buf);
 	}
 
-	data->ts = buf->ts;
+	data->ts.tv_sec = buf->ts.tv_sec;
+	data->ts.tv_usec = buf->ts.tv_usec;
 	data->config_counter = buf->config_counter;
 	data->frame_number = buf->frame_number;
 	data->buf_size = buf->buf_size;
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index 6d9b0244f320..7b4f136567a3 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -39,7 +39,7 @@  struct ispstat_buffer {
 	struct sg_table sgt;
 	void *virt_addr;
 	dma_addr_t dma_addr;
-	struct timeval ts;
+	struct v4l2_timeval ts;
 	u32 buf_size;
 	u32 frame_number;
 	u16 config_counter;
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 295fde5fdb75..df5daac6d099 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -235,7 +235,7 @@  static int device_process(struct vim2m_ctx *ctx,
 	in_vb->v4l2_buf.sequence = q_data->sequence++;
 	memcpy(&out_vb->v4l2_buf.timestamp,
 			&in_vb->v4l2_buf.timestamp,
-			sizeof(struct timeval));
+			sizeof(struct v4l2_timeval));
 	if (in_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE)
 		memcpy(&out_vb->v4l2_buf.timecode, &in_vb->v4l2_buf.timecode,
 			sizeof(struct v4l2_timecode));
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 339c8b7e53c8..065f3d6c2409 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -935,7 +935,7 @@  static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
 static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
-	struct timeval tv;
+	struct v4l2_timeval tv;
 
 	switch (ctrl->id) {
 	case VIVID_CID_DQBUF_ERROR:
diff --git a/drivers/media/usb/cpia2/cpia2.h b/drivers/media/usb/cpia2/cpia2.h
index cdef677d57ec..3e7c523784e7 100644
--- a/drivers/media/usb/cpia2/cpia2.h
+++ b/drivers/media/usb/cpia2/cpia2.h
@@ -354,7 +354,7 @@  struct cpia2_sbuf {
 };
 
 struct framebuf {
-	struct timeval timestamp;
+	struct v4l2_timeval timestamp;
 	unsigned long seq;
 	int num;
 	int length;
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
index 9caea8344547..ce50d7ef4da7 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -892,7 +892,7 @@  static int find_earliest_filled_buffer(struct camera_data *cam)
 				found = i;
 			} else {
 				/* find which buffer is earlier */
-				struct timeval *tv1, *tv2;
+				struct v4l2_timeval *tv1, *tv2;
 				tv1 = &cam->buffers[i].timestamp;
 				tv2 = &cam->buffers[found].timestamp;
 				if(tv1->tv_sec < tv2->tv_sec ||
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index af5cd8213e8b..c977937da9c4 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -1898,7 +1898,7 @@  static ssize_t dev_read(struct file *file, char __user *data,
 	struct gspca_dev *gspca_dev = video_drvdata(file);
 	struct gspca_frame *frame;
 	struct v4l2_buffer v4l2_buf;
-	struct timeval timestamp;
+	struct v4l2_timeval timestamp;
 	int n, ret, ret2;
 
 	PDEBUG(D_FRAM, "read (%zd)", count);
diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h
index 4f2e4fde38f2..512de31613df 100644
--- a/drivers/media/usb/usbvision/usbvision.h
+++ b/drivers/media/usb/usbvision/usbvision.h
@@ -320,7 +320,7 @@  struct usbvision_frame {
 	long bytes_read;				/* amount of scanlength that has been read from data */
 	struct usbvision_v4l2_format_st v4l2_format;	/* format the user needs*/
 	int v4l2_linesize;				/* bytes for one videoline*/
-	struct timeval timestamp;
+	struct v4l2_timeval timestamp;
 	int sequence;					/* How many video frames we send to user */
 };
 
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 5b808500e7e7..589fab615f21 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -396,11 +396,11 @@  const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
 }
 EXPORT_SYMBOL_GPL(v4l2_find_nearest_format);
 
-void v4l2_get_timestamp(struct timeval *tv)
+void v4l2_get_timestamp(struct v4l2_timeval *tv)
 {
-	struct timespec ts;
+	struct timespec64 ts;
 
-	ktime_get_ts(&ts);
+	ktime_get_ts64(&ts);
 	tv->tv_sec = ts.tv_sec;
 	tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 }
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 1cc0c5ba16b3..6e77d889c3f8 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -187,6 +187,6 @@  const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
 		const struct v4l2_discrete_probe *probe,
 		s32 width, s32 height);
 
-void v4l2_get_timestamp(struct timeval *tv);
+void v4l2_get_timestamp(struct v4l2_timeval *tv);
 
 #endif /* V4L2_COMMON_H_ */
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
index d760aa73ebbb..6381338a9588 100644
--- a/include/media/videobuf-core.h
+++ b/include/media/videobuf-core.h
@@ -80,7 +80,7 @@  struct videobuf_buffer {
 	struct list_head        queue;
 	wait_queue_head_t       done;
 	unsigned int            field_count;
-	struct timeval          ts;
+	struct v4l2_timeval     ts;
 
 	/* Memory type */
 	enum v4l2_memory        memory;
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index dbf017bfddd9..a88be48dc473 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -6,6 +6,14 @@ 
 
 #include <linux/tracepoint.h>
 
+#ifndef v4l2_timeval_to_ns
+#define v4l2_timeval_to_ns v4l2_timeval_to_ns
+static inline u64 v4l2_timeval_to_ns(struct v4l2_timeval *tv)
+{
+	return (u64)tv->tv_sec * NSEC_PER_SEC + tv->tv_usec * NSEC_PER_USEC;
+}
+#endif
+
 /* Enums require being exported to userspace, for user tool parsing */
 #undef EM
 #undef EMe
@@ -126,7 +134,7 @@  DECLARE_EVENT_CLASS(v4l2_event_class,
 		__entry->bytesused = buf->bytesused;
 		__entry->flags = buf->flags;
 		__entry->field = buf->field;
-		__entry->timestamp = timeval_to_ns(&buf->timestamp);
+		__entry->timestamp = v4l2_timeval_to_ns(&buf->timestamp);
 		__entry->timecode_type = buf->timecode.type;
 		__entry->timecode_flags = buf->timecode.flags;
 		__entry->timecode_frames = buf->timecode.frames;
@@ -211,7 +219,7 @@  DECLARE_EVENT_CLASS(vb2_event_class,
 		__entry->bytesused = vb->v4l2_planes[0].bytesused;
 		__entry->flags = vb->v4l2_buf.flags;
 		__entry->field = vb->v4l2_buf.field;
-		__entry->timestamp = timeval_to_ns(&vb->v4l2_buf.timestamp);
+		__entry->timestamp = v4l2_timeval_to_ns(&vb->v4l2_buf.timestamp);
 		__entry->timecode_type = vb->v4l2_buf.timecode.type;
 		__entry->timecode_flags = vb->v4l2_buf.timecode.flags;
 		__entry->timecode_frames = vb->v4l2_buf.timecode.frames;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 3e2c497c31fd..450b3249ba30 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -803,6 +803,19 @@  struct v4l2_plane {
 	__u32			reserved[11];
 };
 
+#ifdef __KERNEL__
+/*
+ * This is used for the in-kernel version of v4l2_buffer, as we are
+ * migrating away from using time_t based structures in the kernel.
+ * User space might see this defined either using 32-bit or 64-bit
+ * time_t, so we have to convert it when accessing user data.
+ */
+struct v4l2_timeval {
+	long tv_sec;
+	long tv_usec;
+};
+#endif
+
 /**
  * struct v4l2_buffer - video buffer info
  * @index:	id number of the buffer
@@ -839,7 +852,11 @@  struct v4l2_buffer {
 	__u32			bytesused;
 	__u32			flags;
 	__u32			field;
+#ifdef __KERNEL__
+	struct v4l2_timeval	timestamp;
+#else
 	struct timeval		timestamp;
+#endif
 	struct v4l2_timecode	timecode;
 	__u32			sequence;