diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_crc.c | 36 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_crtc.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/vkms/vkms_drv.h | 8 |
3 files changed, 54 insertions, 6 deletions
diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c index ed47d67cecd6..68db42f15086 100644 --- a/drivers/gpu/drm/vkms/vkms_crc.c +++ b/drivers/gpu/drm/vkms/vkms_crc.c | |||
| @@ -34,6 +34,15 @@ out: | |||
| 34 | return crc; | 34 | return crc; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /** | ||
| 38 | * vkms_crc_work_handle - ordered work_struct to compute CRC | ||
| 39 | * | ||
| 40 | * @work: work_struct | ||
| 41 | * | ||
| 42 | * Work handler for computing CRCs. work_struct scheduled in | ||
| 43 | * an ordered workqueue that's periodically scheduled to run by | ||
| 44 | * _vblank_handle() and flushed at vkms_atomic_crtc_destroy_state(). | ||
| 45 | */ | ||
| 37 | void vkms_crc_work_handle(struct work_struct *work) | 46 | void vkms_crc_work_handle(struct work_struct *work) |
| 38 | { | 47 | { |
| 39 | struct vkms_crtc_state *crtc_state = container_of(work, | 48 | struct vkms_crtc_state *crtc_state = container_of(work, |
| @@ -45,8 +54,18 @@ void vkms_crc_work_handle(struct work_struct *work) | |||
| 45 | output); | 54 | output); |
| 46 | struct vkms_crc_data *primary_crc = NULL; | 55 | struct vkms_crc_data *primary_crc = NULL; |
| 47 | struct drm_plane *plane; | 56 | struct drm_plane *plane; |
| 48 | |||
| 49 | u32 crc32 = 0; | 57 | u32 crc32 = 0; |
| 58 | u64 frame_start, frame_end; | ||
| 59 | unsigned long flags; | ||
| 60 | |||
| 61 | spin_lock_irqsave(&out->state_lock, flags); | ||
| 62 | frame_start = crtc_state->frame_start; | ||
| 63 | frame_end = crtc_state->frame_end; | ||
| 64 | spin_unlock_irqrestore(&out->state_lock, flags); | ||
| 65 | |||
| 66 | /* _vblank_handle() hasn't updated frame_start yet */ | ||
| 67 | if (!frame_start || frame_start == frame_end) | ||
| 68 | goto out; | ||
| 50 | 69 | ||
| 51 | drm_for_each_plane(plane, &vdev->drm) { | 70 | drm_for_each_plane(plane, &vdev->drm) { |
| 52 | struct vkms_plane_state *vplane_state; | 71 | struct vkms_plane_state *vplane_state; |
| @@ -67,7 +86,20 @@ void vkms_crc_work_handle(struct work_struct *work) | |||
| 67 | if (primary_crc) | 86 | if (primary_crc) |
| 68 | crc32 = _vkms_get_crc(primary_crc); | 87 | crc32 = _vkms_get_crc(primary_crc); |
| 69 | 88 | ||
| 70 | drm_crtc_add_crc_entry(crtc, true, crtc_state->n_frame, &crc32); | 89 | frame_end = drm_crtc_accurate_vblank_count(crtc); |
| 90 | |||
| 91 | /* queue_work can fail to schedule crc_work; add crc for | ||
| 92 | * missing frames | ||
| 93 | */ | ||
| 94 | while (frame_start <= frame_end) | ||
| 95 | drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); | ||
| 96 | |||
| 97 | out: | ||
| 98 | /* to avoid using the same value for frame number again */ | ||
| 99 | spin_lock_irqsave(&out->state_lock, flags); | ||
| 100 | crtc_state->frame_end = frame_end; | ||
| 101 | crtc_state->frame_start = 0; | ||
| 102 | spin_unlock_irqrestore(&out->state_lock, flags); | ||
| 71 | } | 103 | } |
| 72 | 104 | ||
| 73 | static int vkms_crc_parse_source(const char *src_name, bool *enabled) | 105 | static int vkms_crc_parse_source(const char *src_name, bool *enabled) |
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 9d0b1a325a78..177bbcb38306 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c | |||
| @@ -22,8 +22,19 @@ static void _vblank_handle(struct vkms_output *output) | |||
| 22 | DRM_ERROR("vkms failure on handling vblank"); | 22 | DRM_ERROR("vkms failure on handling vblank"); |
| 23 | 23 | ||
| 24 | if (state && output->crc_enabled) { | 24 | if (state && output->crc_enabled) { |
| 25 | state->n_frame = drm_crtc_accurate_vblank_count(crtc); | 25 | u64 frame = drm_crtc_accurate_vblank_count(crtc); |
| 26 | queue_work(output->crc_workq, &state->crc_work); | 26 | |
| 27 | /* update frame_start only if a queued vkms_crc_work_handle() | ||
| 28 | * has read the data | ||
| 29 | */ | ||
| 30 | spin_lock(&output->state_lock); | ||
| 31 | if (!state->frame_start) | ||
| 32 | state->frame_start = frame; | ||
| 33 | spin_unlock(&output->state_lock); | ||
| 34 | |||
| 35 | ret = queue_work(output->crc_workq, &state->crc_work); | ||
| 36 | if (!ret) | ||
| 37 | DRM_WARN("failed to queue vkms_crc_work_handle"); | ||
| 27 | } | 38 | } |
| 28 | 39 | ||
| 29 | spin_unlock(&output->lock); | 40 | spin_unlock(&output->lock); |
| @@ -211,6 +222,7 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | |||
| 211 | drm_crtc_helper_add(crtc, &vkms_crtc_helper_funcs); | 222 | drm_crtc_helper_add(crtc, &vkms_crtc_helper_funcs); |
| 212 | 223 | ||
| 213 | spin_lock_init(&vkms_out->lock); | 224 | spin_lock_init(&vkms_out->lock); |
| 225 | spin_lock_init(&vkms_out->state_lock); | ||
| 214 | 226 | ||
| 215 | vkms_out->crc_workq = alloc_ordered_workqueue("vkms_crc_workq", 0); | 227 | vkms_out->crc_workq = alloc_ordered_workqueue("vkms_crc_workq", 0); |
| 216 | 228 | ||
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 2017a2ccc43d..80af6d3a65e7 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h | |||
| @@ -39,12 +39,14 @@ struct vkms_plane_state { | |||
| 39 | * vkms_crtc_state - Driver specific CRTC state | 39 | * vkms_crtc_state - Driver specific CRTC state |
| 40 | * @base: base CRTC state | 40 | * @base: base CRTC state |
| 41 | * @crc_work: work struct to compute and add CRC entries | 41 | * @crc_work: work struct to compute and add CRC entries |
| 42 | * @n_frame: frame number for computed CRC | 42 | * @n_frame_start: start frame number for computed CRC |
| 43 | * @n_frame_end: end frame number for computed CRC | ||
| 43 | */ | 44 | */ |
| 44 | struct vkms_crtc_state { | 45 | struct vkms_crtc_state { |
| 45 | struct drm_crtc_state base; | 46 | struct drm_crtc_state base; |
| 46 | struct work_struct crc_work; | 47 | struct work_struct crc_work; |
| 47 | unsigned int n_frame; | 48 | u64 frame_start; |
| 49 | u64 frame_end; | ||
| 48 | }; | 50 | }; |
| 49 | 51 | ||
| 50 | struct vkms_output { | 52 | struct vkms_output { |
| @@ -59,6 +61,8 @@ struct vkms_output { | |||
| 59 | struct workqueue_struct *crc_workq; | 61 | struct workqueue_struct *crc_workq; |
| 60 | /* protects concurrent access to crc_data */ | 62 | /* protects concurrent access to crc_data */ |
| 61 | spinlock_t lock; | 63 | spinlock_t lock; |
| 64 | /* protects concurrent access to crtc_state */ | ||
| 65 | spinlock_t state_lock; | ||
| 62 | }; | 66 | }; |
| 63 | 67 | ||
| 64 | struct vkms_device { | 68 | struct vkms_device { |
