mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
drm/rockchip: vvop: fix a potential race condition when vvop_disable_vblank
A very similar case on amdgpu_vkms:
commit 826c1e923b ("drm/amdgpu/vkms: relax timer deactivation by
hrtimer_try_to_cancel")
Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
Change-Id: I0692cd2c4ad3e3f090c0df040537995f99c2fcff
This commit is contained in:
@@ -101,12 +101,15 @@ static enum hrtimer_restart vvop_vblank_simulate(struct hrtimer *timer)
|
|||||||
struct drm_crtc *crtc = &vcrtc->crtc;
|
struct drm_crtc *crtc = &vcrtc->crtc;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
ret = drm_crtc_handle_vblank(crtc);
|
|
||||||
if (!ret)
|
|
||||||
DRM_ERROR("vvop failure on handling vblank");
|
|
||||||
|
|
||||||
hrtimer_forward_now(&vcrtc->vblank_hrtimer, vcrtc->period_ns);
|
hrtimer_forward_now(&vcrtc->vblank_hrtimer, vcrtc->period_ns);
|
||||||
|
|
||||||
|
ret = drm_crtc_handle_vblank(crtc);
|
||||||
|
/* Don't queue timer again when vblank is disabled. */
|
||||||
|
if (!ret) {
|
||||||
|
drm_dbg(crtc->dev, "vblank is already disabled\n");
|
||||||
|
return HRTIMER_NORESTART;
|
||||||
|
}
|
||||||
|
|
||||||
return HRTIMER_RESTART;
|
return HRTIMER_RESTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +122,6 @@ static int vvop_enable_vblank(struct drm_crtc *crtc)
|
|||||||
|
|
||||||
drm_calc_timestamping_constants(crtc, &crtc->mode);
|
drm_calc_timestamping_constants(crtc, &crtc->mode);
|
||||||
|
|
||||||
hrtimer_init(&vcrtc->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
||||||
vcrtc->vblank_hrtimer.function = &vvop_vblank_simulate;
|
|
||||||
vcrtc->period_ns = ktime_set(0, vblank->framedur_ns);
|
vcrtc->period_ns = ktime_set(0, vblank->framedur_ns);
|
||||||
hrtimer_start(&vcrtc->vblank_hrtimer, vcrtc->period_ns, HRTIMER_MODE_REL);
|
hrtimer_start(&vcrtc->vblank_hrtimer, vcrtc->period_ns, HRTIMER_MODE_REL);
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ static void vvop_disable_vblank(struct drm_crtc *crtc)
|
|||||||
{
|
{
|
||||||
struct vvop_crtc *vcrtc = drm_crtc_to_vvop_crtc(crtc);
|
struct vvop_crtc *vcrtc = drm_crtc_to_vvop_crtc(crtc);
|
||||||
|
|
||||||
hrtimer_cancel(&vcrtc->vblank_hrtimer);
|
hrtimer_try_to_cancel(&vcrtc->vblank_hrtimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vvop_connector_destroy(struct drm_connector *connector)
|
static void vvop_connector_destroy(struct drm_connector *connector)
|
||||||
@@ -460,6 +461,14 @@ static u64 vvop_get_soc_id(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vvop_crtc_deinit(struct drm_crtc *vcrtc)
|
||||||
|
{
|
||||||
|
struct vvop_crtc *vcrtc = drm_crtc_to_vvop_crtc(crtc);
|
||||||
|
|
||||||
|
hrtimer_cancel(&vcrtc->vblank_hrtimer);
|
||||||
|
drm_crtc_cleanup(crtc);
|
||||||
|
}
|
||||||
|
|
||||||
static int vvop_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
static int vvop_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
||||||
struct drm_plane *primary, struct drm_plane *cursor)
|
struct drm_plane *primary, struct drm_plane *cursor)
|
||||||
{
|
{
|
||||||
@@ -487,6 +496,9 @@ static int vvop_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
|||||||
"SOC_ID", DRM_MODE_OBJECT_CRTC);
|
"SOC_ID", DRM_MODE_OBJECT_CRTC);
|
||||||
drm_object_attach_property(&crtc->base, vcrtc->soc_id_prop, vvop_get_soc_id());
|
drm_object_attach_property(&crtc->base, vcrtc->soc_id_prop, vvop_get_soc_id());
|
||||||
|
|
||||||
|
hrtimer_init(&vcrtc->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||||
|
vcrtc->vblank_hrtimer.function = &vvop_vblank_simulate;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,7 +561,7 @@ err_encoder:
|
|||||||
err_connector_register:
|
err_connector_register:
|
||||||
drm_connector_cleanup(connector);
|
drm_connector_cleanup(connector);
|
||||||
err_connector:
|
err_connector:
|
||||||
drm_crtc_cleanup(crtc);
|
vvop_crtc_deinit(crtc);
|
||||||
err_crtc:
|
err_crtc:
|
||||||
drm_plane_cleanup(primary);
|
drm_plane_cleanup(primary);
|
||||||
|
|
||||||
@@ -609,7 +621,7 @@ static void vvop_unbind(struct device *dev, struct device *master, void *data)
|
|||||||
drm_connector_cleanup(&vcrtc->connector);
|
drm_connector_cleanup(&vcrtc->connector);
|
||||||
drm_plane_cleanup(&vcrtc->plane);
|
drm_plane_cleanup(&vcrtc->plane);
|
||||||
vvop->crtc_mask &= ~(drm_crtc_mask(crtc));
|
vvop->crtc_mask &= ~(drm_crtc_mask(crtc));
|
||||||
drm_crtc_cleanup(crtc);
|
vvop_crtc_deinit(crtc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user