提交 39dc5454 编写于 作者: M Mario Kleiner 提交者: Alex Deucher

drm/radeon: Use pflip irqs for pageflip completion if possible. (v2)

Skip the "manual" pageflip completion checks via polling and
guessing in the vblank handler radeon_crtc_handle_vblank() on
asics which are known to reliably support hw pageflip completion
irqs. Those pflip irqs are a more reliable and race-free method
of handling pageflip completion detection, whereas the "classic"
polling method has some small races in combination with dpm on,
and with the reworked pageflip implementation since Linux 3.16.

On old asics without pflip irqs, the classic method is used.

On asics with known good pflip irqs, only pflip irqs are used
by default, but a new module parameter "use_pflipirqs" allows to
override this in case we encounter asics in the wild with
unreliable or faulty pflip irqs. A module parameter of 0 allows
to use the classic method only in such a case. A parameter of 1
allows to use both classic method and pflip irqs as additional
band-aid to avoid some small races which could happen with the
classic method alone. The setting 1 gives Linux 3.16 behaviour.

Hw pflip irqs are available since R600.

Tested on DCE-4, AMD Cedar - FirePro 2270.

v2:  agd5f: only enable pflip interrupts on DCE4+ as they are not
reliable on older asics.
Signed-off-by: NMario Kleiner <mario.kleiner.de@gmail.com>
Signed-off-by: NAlex Deucher <alexander.deucher@amd.com>
上级 9eb401af
...@@ -7977,7 +7977,8 @@ int cik_irq_process(struct radeon_device *rdev) ...@@ -7977,7 +7977,8 @@ int cik_irq_process(struct radeon_device *rdev)
case 16: /* D5 page flip */ case 16: /* D5 page flip */
case 18: /* D6 page flip */ case 18: /* D6 page flip */
DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); if (radeon_use_pflipirq > 0)
radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
break; break;
case 42: /* HPD hotplug */ case 42: /* HPD hotplug */
switch (src_data) { switch (src_data) {
......
...@@ -4964,7 +4964,8 @@ int evergreen_irq_process(struct radeon_device *rdev) ...@@ -4964,7 +4964,8 @@ int evergreen_irq_process(struct radeon_device *rdev)
case 16: /* D5 page flip */ case 16: /* D5 page flip */
case 18: /* D6 page flip */ case 18: /* D6 page flip */
DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); if (radeon_use_pflipirq > 0)
radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
break; break;
case 42: /* HPD hotplug */ case 42: /* HPD hotplug */
switch (src_data) { switch (src_data) {
......
...@@ -3923,11 +3923,13 @@ int r600_irq_process(struct radeon_device *rdev) ...@@ -3923,11 +3923,13 @@ int r600_irq_process(struct radeon_device *rdev)
break; break;
case 9: /* D1 pflip */ case 9: /* D1 pflip */
DRM_DEBUG("IH: D1 flip\n"); DRM_DEBUG("IH: D1 flip\n");
radeon_crtc_handle_flip(rdev, 0); if (radeon_use_pflipirq > 0)
radeon_crtc_handle_flip(rdev, 0);
break; break;
case 11: /* D2 pflip */ case 11: /* D2 pflip */
DRM_DEBUG("IH: D2 flip\n"); DRM_DEBUG("IH: D2 flip\n");
radeon_crtc_handle_flip(rdev, 1); if (radeon_use_pflipirq > 0)
radeon_crtc_handle_flip(rdev, 1);
break; break;
case 19: /* HPD/DAC hotplug */ case 19: /* HPD/DAC hotplug */
switch (src_data) { switch (src_data) {
......
...@@ -104,6 +104,7 @@ extern int radeon_hard_reset; ...@@ -104,6 +104,7 @@ extern int radeon_hard_reset;
extern int radeon_vm_size; extern int radeon_vm_size;
extern int radeon_vm_block_size; extern int radeon_vm_block_size;
extern int radeon_deep_color; extern int radeon_deep_color;
extern int radeon_use_pflipirq;
/* /*
* Copy from radeon_drv.h so we don't have to include both and have conflicting * Copy from radeon_drv.h so we don't have to include both and have conflicting
......
...@@ -293,6 +293,18 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) ...@@ -293,6 +293,18 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
if (radeon_crtc == NULL) if (radeon_crtc == NULL)
return; return;
/* Skip the pageflip completion check below (based on polling) on
* asics which reliably support hw pageflip completion irqs. pflip
* irqs are a reliable and race-free method of handling pageflip
* completion detection. A use_pflipirq module parameter < 2 allows
* to override this in case of asics with faulty pflip irqs.
* A module parameter of 0 would only use this polling based path,
* a parameter of 1 would use pflip irq only as a backup to this
* path, as in Linux 3.16.
*/
if ((radeon_use_pflipirq == 2) && ASIC_IS_DCE4(rdev))
return;
spin_lock_irqsave(&rdev->ddev->event_lock, flags); spin_lock_irqsave(&rdev->ddev->event_lock, flags);
if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) { if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != " DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
......
...@@ -178,6 +178,7 @@ int radeon_hard_reset = 0; ...@@ -178,6 +178,7 @@ int radeon_hard_reset = 0;
int radeon_vm_size = 8; int radeon_vm_size = 8;
int radeon_vm_block_size = -1; int radeon_vm_block_size = -1;
int radeon_deep_color = 0; int radeon_deep_color = 0;
int radeon_use_pflipirq = 2;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444); module_param_named(no_wb, radeon_no_wb, int, 0444);
...@@ -254,6 +255,9 @@ module_param_named(vm_block_size, radeon_vm_block_size, int, 0444); ...@@ -254,6 +255,9 @@ module_param_named(vm_block_size, radeon_vm_block_size, int, 0444);
MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))"); MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))");
module_param_named(deep_color, radeon_deep_color, int, 0444); module_param_named(deep_color, radeon_deep_color, int, 0444);
MODULE_PARM_DESC(use_pflipirq, "Pflip irqs for pageflip completion (0 = disable, 1 = as fallback, 2 = exclusive (default))");
module_param_named(use_pflipirq, radeon_use_pflipirq, int, 0444);
static struct pci_device_id pciidlist[] = { static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS radeon_PCI_IDS
}; };
......
...@@ -6531,7 +6531,8 @@ int si_irq_process(struct radeon_device *rdev) ...@@ -6531,7 +6531,8 @@ int si_irq_process(struct radeon_device *rdev)
case 16: /* D5 page flip */ case 16: /* D5 page flip */
case 18: /* D6 page flip */ case 18: /* D6 page flip */
DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); if (radeon_use_pflipirq > 0)
radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
break; break;
case 42: /* HPD hotplug */ case 42: /* HPD hotplug */
switch (src_data) { switch (src_data) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册