Commit 36499e4c authored by Emily.Deng's avatar Emily.Deng Committed by Alex Deucher
Browse files

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: default avatarEmily.Deng <Emily.Deng@amd.com>
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9de9a54a
Loading
Loading
Loading
Loading
+17 −18
Original line number Diff line number Diff line
@@ -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 int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
					      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,
							int crtc,
							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;
	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;
}

@@ -476,7 +484,7 @@ static int dce_virtual_hw_fini(void *handle)

	for (i = 0; i<adev->mode_info.num_crtc; 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;
}
@@ -698,9 +706,15 @@ static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vbla
						       struct amdgpu_crtc, vblank_timer);
	struct drm_device *ddev = amdgpu_crtc->base.dev;
	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);
		dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
	}
	hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
		      HRTIMER_MODE_REL);

@@ -716,21 +730,6 @@ static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *ad
		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;
	DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
}