Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Mario Kleiner <mario.kleiner.de@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Mario Kleiner and committed by
Alex Deucher
39dc5454 9eb401af

+27 -5
+2 -1
drivers/gpu/drm/radeon/cik.c
··· 7977 7977 case 16: /* D5 page flip */ 7978 7978 case 18: /* D6 page flip */ 7979 7979 DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); 7980 - radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); 7980 + if (radeon_use_pflipirq > 0) 7981 + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); 7981 7982 break; 7982 7983 case 42: /* HPD hotplug */ 7983 7984 switch (src_data) {
+2 -1
drivers/gpu/drm/radeon/evergreen.c
··· 4964 4964 case 16: /* D5 page flip */ 4965 4965 case 18: /* D6 page flip */ 4966 4966 DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); 4967 - radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); 4967 + if (radeon_use_pflipirq > 0) 4968 + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); 4968 4969 break; 4969 4970 case 42: /* HPD hotplug */ 4970 4971 switch (src_data) {
+4 -2
drivers/gpu/drm/radeon/r600.c
··· 3923 3923 break; 3924 3924 case 9: /* D1 pflip */ 3925 3925 DRM_DEBUG("IH: D1 flip\n"); 3926 - radeon_crtc_handle_flip(rdev, 0); 3926 + if (radeon_use_pflipirq > 0) 3927 + radeon_crtc_handle_flip(rdev, 0); 3927 3928 break; 3928 3929 case 11: /* D2 pflip */ 3929 3930 DRM_DEBUG("IH: D2 flip\n"); 3930 - radeon_crtc_handle_flip(rdev, 1); 3931 + if (radeon_use_pflipirq > 0) 3932 + radeon_crtc_handle_flip(rdev, 1); 3931 3933 break; 3932 3934 case 19: /* HPD/DAC hotplug */ 3933 3935 switch (src_data) {
+1
drivers/gpu/drm/radeon/radeon.h
··· 104 104 extern int radeon_vm_size; 105 105 extern int radeon_vm_block_size; 106 106 extern int radeon_deep_color; 107 + extern int radeon_use_pflipirq; 107 108 108 109 /* 109 110 * Copy from radeon_drv.h so we don't have to include both and have conflicting
+12
drivers/gpu/drm/radeon/radeon_display.c
··· 293 293 if (radeon_crtc == NULL) 294 294 return; 295 295 296 + /* Skip the pageflip completion check below (based on polling) on 297 + * asics which reliably support hw pageflip completion irqs. pflip 298 + * irqs are a reliable and race-free method of handling pageflip 299 + * completion detection. A use_pflipirq module parameter < 2 allows 300 + * to override this in case of asics with faulty pflip irqs. 301 + * A module parameter of 0 would only use this polling based path, 302 + * a parameter of 1 would use pflip irq only as a backup to this 303 + * path, as in Linux 3.16. 304 + */ 305 + if ((radeon_use_pflipirq == 2) && ASIC_IS_DCE4(rdev)) 306 + return; 307 + 296 308 spin_lock_irqsave(&rdev->ddev->event_lock, flags); 297 309 if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) { 298 310 DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
+4
drivers/gpu/drm/radeon/radeon_drv.c
··· 178 178 int radeon_vm_size = 8; 179 179 int radeon_vm_block_size = -1; 180 180 int radeon_deep_color = 0; 181 + int radeon_use_pflipirq = 2; 181 182 182 183 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); 183 184 module_param_named(no_wb, radeon_no_wb, int, 0444); ··· 254 253 255 254 MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))"); 256 255 module_param_named(deep_color, radeon_deep_color, int, 0444); 256 + 257 + MODULE_PARM_DESC(use_pflipirq, "Pflip irqs for pageflip completion (0 = disable, 1 = as fallback, 2 = exclusive (default))"); 258 + module_param_named(use_pflipirq, radeon_use_pflipirq, int, 0444); 257 259 258 260 static struct pci_device_id pciidlist[] = { 259 261 radeon_PCI_IDS
+2 -1
drivers/gpu/drm/radeon/si.c
··· 6531 6531 case 16: /* D5 page flip */ 6532 6532 case 18: /* D6 page flip */ 6533 6533 DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); 6534 - radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); 6534 + if (radeon_use_pflipirq > 0) 6535 + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); 6535 6536 break; 6536 6537 case 42: /* HPD hotplug */ 6537 6538 switch (src_data) {