Skip to content

Commit ba420af

Browse files
shayennerodrigosiqueira
authored andcommitted
drm/vkms: Bugfix racing hrtimer vblank handle
When the vblank irq happens, kernel time subsystem executes `vkms_vblank_simulate`. In parallel or not, it prepares all stuff necessary to the next vblank with arm, and it must flush these stuff before the next vblank irq. However, vblank counter is ahead when arm is executed in parallel with handle vblank. CPU 0: CPU 1: | | atomic_commit_tail is ongoing | | | | hrtimer: vkms_vblank_simulate() | | | drm_crtc_handle_vblank() | | drm_crtc_arm_vblank() | | | ->get_vblank_timestamp() | | | | hrtimer_forward_now() Then, we should guarantee that the vblank interval time is correct (not changed) before finish the vblank handle. Fix the bug including the call to `hrtimer_forward_now()` in the same lock of `drm_crtc_handle_vblank()` to ensure that the timestamp update is correct when finish the vblank handle. Signed-off-by: Shayenne Moura <shayenneluzmoura@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Reviewed-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Signed-off-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/e2e4b8f3a5cab7b2dba75bf1930f86b0a4ee08c9.1548856186.git.shayenneluzmoura@gmail.com
1 parent def35e7 commit ba420af

File tree

1 file changed

+6
-12
lines changed

1 file changed

+6
-12
lines changed

drivers/gpu/drm/vkms/vkms_crtc.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@
1010
#include <drm/drm_atomic_helper.h>
1111
#include <drm/drm_probe_helper.h>
1212

13-
static void _vblank_handle(struct vkms_output *output)
13+
static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
1414
{
15+
struct vkms_output *output = container_of(timer, struct vkms_output,
16+
vblank_hrtimer);
1517
struct drm_crtc *crtc = &output->crtc;
1618
struct vkms_crtc_state *state = to_vkms_crtc_state(crtc->state);
19+
int ret_overrun;
1720
bool ret;
1821

1922
spin_lock(&output->lock);
23+
2024
ret = drm_crtc_handle_vblank(crtc);
2125
if (!ret)
2226
DRM_ERROR("vkms failure on handling vblank");
@@ -37,19 +41,9 @@ static void _vblank_handle(struct vkms_output *output)
3741
DRM_WARN("failed to queue vkms_crc_work_handle");
3842
}
3943

40-
spin_unlock(&output->lock);
41-
}
42-
43-
static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
44-
{
45-
struct vkms_output *output = container_of(timer, struct vkms_output,
46-
vblank_hrtimer);
47-
int ret_overrun;
48-
49-
_vblank_handle(output);
50-
5144
ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
5245
output->period_ns);
46+
spin_unlock(&output->lock);
5347

5448
return HRTIMER_RESTART;
5549
}

0 commit comments

Comments
 (0)