mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
drm/amdgpu: Fix dead lock issue for vblank
Always start vblank timer, but only calls vblank function when vblank is enabled. This is used to fix the dead lock issue. When drm_crtc_vblank_off want to disable vblank, it first get event_lock, and then call hrtimer_cancel, but hrtimer_cancel want to wait timer handler function finished. Timer handler also want to aquire event_lock in drm_handle_vblank. Signed-off-by: Emily.Deng <Emily.Deng@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
9de9a54aba
commit
36499e4c77
1 changed files with 17 additions and 18 deletions
|
@ -47,6 +47,9 @@ static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
|
||||||
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
|
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
|
||||||
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
|
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
|
||||||
int index);
|
int index);
|
||||||
|
static int dce_virtual_pageflip(struct amdgpu_device *adev,
|
||||||
|
unsigned crtc_id);
|
||||||
|
static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer);
|
||||||
static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
|
static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
|
||||||
int crtc,
|
int crtc,
|
||||||
enum amdgpu_interrupt_state state);
|
enum amdgpu_interrupt_state state);
|
||||||
|
@ -247,6 +250,11 @@ static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
|
||||||
amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
|
amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
|
||||||
drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
|
drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
|
||||||
|
|
||||||
|
hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||||
|
hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD);
|
||||||
|
amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle;
|
||||||
|
hrtimer_start(&amdgpu_crtc->vblank_timer,
|
||||||
|
DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +484,7 @@ static int dce_virtual_hw_fini(void *handle)
|
||||||
|
|
||||||
for (i = 0; i<adev->mode_info.num_crtc; i++)
|
for (i = 0; i<adev->mode_info.num_crtc; i++)
|
||||||
if (adev->mode_info.crtcs[i])
|
if (adev->mode_info.crtcs[i])
|
||||||
dce_virtual_set_crtc_vblank_interrupt_state(adev, i, AMDGPU_IRQ_STATE_DISABLE);
|
hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -698,9 +706,15 @@ static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vbla
|
||||||
struct amdgpu_crtc, vblank_timer);
|
struct amdgpu_crtc, vblank_timer);
|
||||||
struct drm_device *ddev = amdgpu_crtc->base.dev;
|
struct drm_device *ddev = amdgpu_crtc->base.dev;
|
||||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||||
|
struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources
|
||||||
|
[VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER];
|
||||||
|
int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev,
|
||||||
|
amdgpu_crtc->crtc_id);
|
||||||
|
|
||||||
|
if (amdgpu_irq_enabled(adev, source, irq_type)) {
|
||||||
drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
|
drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
|
||||||
dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
|
dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
|
||||||
|
}
|
||||||
hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
|
hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
|
||||||
HRTIMER_MODE_REL);
|
HRTIMER_MODE_REL);
|
||||||
|
|
||||||
|
@ -716,21 +730,6 @@ static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *ad
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
|
|
||||||
DRM_DEBUG("Enable software vsync timer\n");
|
|
||||||
hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer,
|
|
||||||
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
||||||
hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer,
|
|
||||||
DCE_VIRTUAL_VBLANK_PERIOD);
|
|
||||||
adev->mode_info.crtcs[crtc]->vblank_timer.function =
|
|
||||||
dce_virtual_vblank_timer_handle;
|
|
||||||
hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer,
|
|
||||||
DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
|
|
||||||
} else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
|
|
||||||
DRM_DEBUG("Disable software vsync timer\n");
|
|
||||||
hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
|
adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
|
||||||
DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
|
DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue