From: Carsten Haitzler carsten.haitzler@arm.com
Vblank is a bit different because it produces events that then can copy pointers/capabilities back to userspace via a read on the DRM device as opposed to the ioctl. The compat handler called the normal native/purecap one and this happened to work for compat but not for purecap. Make the shared "native" purecap handling work for both and share that infra properly to avoid copy and paste.
Signed-off-by: Carsten Haitzler Carsten.Haitzler@arm.com --- drivers/gpu/drm/drm_atomic_uapi.c | 3 ++- drivers/gpu/drm/drm_ioc32.c | 1 + drivers/gpu/drm/drm_vblank.c | 39 ++++++++++++++++++++++--------- include/drm/drm_vblank.h | 23 ++++++++++++++++++ include/uapi/drm/drm.h | 6 ++--- include/uapi/drm/drm_mode.h | 2 +- tools/include/uapi/drm/drm.h | 2 +- 7 files changed, 59 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 3e4668a20157..08474a1ea90e 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -940,7 +940,8 @@ int drm_atomic_get_property(struct drm_mode_object *obj, */
static struct drm_pending_vblank_event *create_vblank_event( - struct drm_crtc *crtc, uint64_t user_data) + struct drm_crtc *crtc, + __kernel_uintptr_t user_data) { struct drm_pending_vblank_event *e = NULL;
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index 504c2fcd9c89..a081ee3f4dac 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -33,6 +33,7 @@
#include <drm/drm_file.h> #include <drm/drm_print.h> +#include <drm/drm_drv.h>
#include "drm_crtc_internal.h" #include "drm_internal.h" diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 877e2067534f..fbd60acc5eda 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1031,14 +1031,20 @@ static void send_vblank_event(struct drm_device *dev, case DRM_EVENT_VBLANK: case DRM_EVENT_FLIP_COMPLETE: tv = ktime_to_timespec64(now); - e->event.vbl.sequence = seq; /* * e->event is a user space structure, with hardcoded unsigned * 32-bit seconds/microseconds. This is safe as we always use * monotonic timestamps since linux-4.15 */ - e->event.vbl.tv_sec = tv.tv_sec; - e->event.vbl.tv_usec = tv.tv_nsec / 1000; + if (e->compat) { + e->event.vbl32.sequence = seq; + e->event.vbl32.tv_sec = tv.tv_sec; + e->event.vbl32.tv_usec = tv.tv_nsec / 1000; + } else { + e->event.vbl.sequence = seq; + e->event.vbl.tv_sec = tv.tv_sec; + e->event.vbl.tv_usec = tv.tv_nsec / 1000; + } break; case DRM_EVENT_CRTC_SEQUENCE: if (seq) @@ -1659,10 +1665,13 @@ int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, u64 req_seq, union drm_wait_vblank *vblwait, - struct drm_file *file_priv) + struct drm_file *file_priv, + bool compat + ) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct drm_pending_vblank_event *e; + struct drm_crtc *crtc = NULL; ktime_t now; u64 seq; int ret; @@ -1675,12 +1684,19 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
e->pipe = pipe; e->event.base.type = DRM_EVENT_VBLANK; - e->event.base.length = sizeof(e->event.vbl); - e->event.vbl.user_data = vblwait->request.signal; - e->event.vbl.crtc_id = 0; - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); - + if (drm_core_check_feature(dev, DRIVER_MODESET)) + crtc = drm_crtc_from_index(dev, pipe); + e->compat = compat; + if (compat) { + e->event.base.length = sizeof(e->event.vbl32); + e->event.vbl32.user_data = vblwait->request.signal; + e->event.vbl32.crtc_id = 0; + if (crtc) + e->event.vbl32.crtc_id = crtc->base.id; + } else { + e->event.base.length = sizeof(e->event.vbl); + e->event.vbl.user_data = vblwait->request.signal; + e->event.vbl.crtc_id = 0; if (crtc) e->event.vbl.crtc_id = crtc->base.id; } @@ -1886,7 +1902,8 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, /* must hold on to the vblank ref until the event fires * drm_vblank_put will be called asynchronously */ - return drm_queue_vblank_event(dev, pipe, req_seq, vblwait, file_priv); + return drm_queue_vblank_event(dev, pipe, req_seq, vblwait, + file_priv, in_compat64_syscall()); }
if (req_seq != seq) { diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 7f3957943dd1..ccbcea75ba13 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -36,6 +36,22 @@ struct drm_device; struct drm_crtc; struct drm_vblank_work;
+struct drm_event_vblank32 { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 sequence; + __u32 crtc_id; /* 0 on older kernels that do not support this */ +}; + +struct drm_event_crtc_sequence32 { + struct drm_event base; + __u64 user_data; + __s64 time_ns; + __u64 sequence; +}; + /** * struct drm_pending_vblank_event - pending vblank event tracking */ @@ -52,6 +68,10 @@ struct drm_pending_vblank_event { * @sequence: frame event should be triggered at */ u64 sequence; + /** + * @compat: This is a compat event + */ + bool compat; /** * @event: Actual event which will be sent to userspace. */ @@ -75,6 +95,9 @@ struct drm_pending_vblank_event { * @event.seq: Event payload for the MODE_QUEUEU_SEQUENCE IOCTL. */ struct drm_event_crtc_sequence seq; + + struct drm_event_vblank32 vbl32; + struct drm_event_crtc_sequence32 seq32; } event; };
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index de723566c5ae..c5cc98abbffe 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -494,7 +494,7 @@ enum drm_vblank_seq_type { struct drm_wait_vblank_request { enum drm_vblank_seq_type type; unsigned int sequence; - unsigned long signal; + __kernel_uintptr_t signal; };
struct drm_wait_vblank_reply { @@ -971,7 +971,7 @@ struct drm_crtc_queue_sequence { __u32 crtc_id; __u32 flags; __u64 sequence; /* on input, target sequence. on output, actual sequence */ - __u64 user_data; /* user data passed to event */ + __kernel_uintptr_t user_data; /* user data passed to event */ };
#if defined(__cplusplus) @@ -1277,7 +1277,7 @@ struct drm_event {
struct drm_event_vblank { struct drm_event base; - __u64 user_data; + __kernel_uintptr_t user_data; __u32 tv_sec; __u32 tv_usec; __u32 sequence; diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 128d09138ceb..3a426e7ed775 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -1135,7 +1135,7 @@ struct drm_mode_atomic { __u64 props_ptr; __u64 prop_values_ptr; __u64 reserved; - __u64 user_data; + __kernel_uintptr_t user_data; };
struct drm_format_modifier_blob { diff --git a/tools/include/uapi/drm/drm.h b/tools/include/uapi/drm/drm.h index de723566c5ae..82797c95efa6 100644 --- a/tools/include/uapi/drm/drm.h +++ b/tools/include/uapi/drm/drm.h @@ -1277,7 +1277,7 @@ struct drm_event {
struct drm_event_vblank { struct drm_event base; - __u64 user_data; + uintptr_t user_data; __u32 tv_sec; __u32 tv_usec; __u32 sequence;