Commit 67680d3c authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Dave Airlie

drm: vblank: use ktime_t instead of timeval

The drm vblank handling uses 'timeval' to store timestamps in either
monotonic or wall-clock time base. In either case, it reads the current
time as a ktime_t in get_drm_timestamp() and converts it from there.

This is a bit suspicious, as users of 'timeval' often suffer from
the time_t overflow in y2038. I have gone through this code and
found that it is unlikely to cause problems here:

- The user space ABI does not use time_t or timeval, but uses
  'u32' and 'long' as the types. This means at least that rebuilding
  user programs against a new libc with 64-bit time_t does not
  change the ABI.

- As of commit c61eef72 ("drm: add support for monotonic vblank
  timestamps") in linux-3.8, the monotonic timestamp is the default
  and can only get reverted to wall-clock through a module-parameter.

- With the default monotonic timestamps, there is no problem at all.

- The drm_wait_vblank_ioctl() interface is alway safe on 64-bit
  architectures, on 32-bit it might overflow the 'long' timestamps
  in 2038 with wall-clock timestamps.

- The event handling uses 'u32' seconds, which overflow in 2106
  on both 32-bit and 64-bit machines, when wall-clock timestamps
  are used.

- The effect of overflowing either of the two is only temporary
  (during the overflow, and is likely to keep working again
  afterwards. It is likely the same problem as observing a
  'settimeofday()' call, which was the reason for moving to the
  monotonic timestamps in the first place.

Overall, this seems good enough, so my patch removes the use of
'timeval' from the vblank handling altogether and uses ktime_t
consistently, except for the part where we copy the data to user
space structures in the existing format.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarSean Paul <seanpaul@chromium.org>
Reviewed-by: default avatarKeith Packard <keithp@keithp.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent c5c7bc71
This diff is collapsed.
...@@ -324,7 +324,7 @@ struct drm_driver { ...@@ -324,7 +324,7 @@ struct drm_driver {
*/ */
bool (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe, bool (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe,
int *max_error, int *max_error,
struct timeval *vblank_time, ktime_t *vblank_time,
bool in_vblank_irq); bool in_vblank_irq);
/** /**
......
...@@ -92,7 +92,7 @@ struct drm_vblank_crtc { ...@@ -92,7 +92,7 @@ struct drm_vblank_crtc {
/** /**
* @time: Vblank timestamp corresponding to @count. * @time: Vblank timestamp corresponding to @count.
*/ */
struct timeval time; ktime_t time;
/** /**
* @refcount: Number of users/waiters of the vblank interrupt. Only when * @refcount: Number of users/waiters of the vblank interrupt. Only when
...@@ -154,7 +154,7 @@ struct drm_vblank_crtc { ...@@ -154,7 +154,7 @@ struct drm_vblank_crtc {
int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
u32 drm_crtc_vblank_count(struct drm_crtc *crtc); u32 drm_crtc_vblank_count(struct drm_crtc *crtc);
u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *vblanktime); ktime_t *vblanktime);
void drm_crtc_send_vblank_event(struct drm_crtc *crtc, void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
struct drm_pending_vblank_event *e); struct drm_pending_vblank_event *e);
void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
...@@ -172,7 +172,7 @@ u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); ...@@ -172,7 +172,7 @@ u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
unsigned int pipe, int *max_error, unsigned int pipe, int *max_error,
struct timeval *vblank_time, ktime_t *vblank_time,
bool in_vblank_irq); bool in_vblank_irq);
void drm_calc_timestamping_constants(struct drm_crtc *crtc, void drm_calc_timestamping_constants(struct drm_crtc *crtc,
const struct drm_display_mode *mode); const struct drm_display_mode *mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment