drm/radeon: Use pflip irqs for pageflip completion if possible. (v2)
authorMario Kleiner <mario.kleiner.de@gmail.com>
Tue, 29 Jul 2014 04:21:44 +0000 (06:21 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 5 Aug 2014 12:54:00 +0000 (08:54 -0400)
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>
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/si.c

index 2693c57de80cc55739db516b1294d4bea7df6d3e..b625646bf3e242c11d21fd268c698a502604fae0 100644 (file)
@@ -7977,7 +7977,8 @@ restart_ih:
                case 16: /* D5 page flip */
                case 18: /* D6 page flip */
                        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;
                case 42: /* HPD hotplug */
                        switch (src_data) {
index cb2043973583f6c2d8602021902e447a1154f1be..4fedd14e670aeb33e07fadcf5ff2564c2cc2681c 100644 (file)
@@ -4964,7 +4964,8 @@ restart_ih:
                case 16: /* D5 page flip */
                case 18: /* D6 page flip */
                        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;
                case 42: /* HPD hotplug */
                        switch (src_data) {
index 76e1616a25c86ae1b9e61751e1d536adf06c54a5..c70a504d96af5a8ac6f8a9f8e40dd2039917e467 100644 (file)
@@ -3923,11 +3923,13 @@ restart_ih:
                        break;
                case 9: /* D1 pflip */
                        DRM_DEBUG("IH: D1 flip\n");
-                       radeon_crtc_handle_flip(rdev, 0);
+                       if (radeon_use_pflipirq > 0)
+                               radeon_crtc_handle_flip(rdev, 0);
                        break;
                case 11: /* D2 pflip */
                        DRM_DEBUG("IH: D2 flip\n");
-                       radeon_crtc_handle_flip(rdev, 1);
+                       if (radeon_use_pflipirq > 0)
+                               radeon_crtc_handle_flip(rdev, 1);
                        break;
                case 19: /* HPD/DAC hotplug */
                        switch (src_data) {
index 142cad63c3fad28e27872fee55dad7989bdecbce..9e1732eb402c5ec831c9bbd514084e7ce30462c2 100644 (file)
@@ -104,6 +104,7 @@ extern int radeon_hard_reset;
 extern int radeon_vm_size;
 extern int radeon_vm_block_size;
 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
index a966074a4fbaea80d65effff6788abf99f4beb24..3fdf87318069f1a6b26e1e37f9fd504641b19132 100644 (file)
@@ -293,6 +293,18 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
        if (radeon_crtc == NULL)
                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);
        if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
                DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
index 8688e860e6a07776c66cb660539420ec26783d7e..a773830c6c40cdf8570d2d90814379eeeb6aaf14 100644 (file)
@@ -178,6 +178,7 @@ int radeon_hard_reset = 0;
 int radeon_vm_size = 8;
 int radeon_vm_block_size = -1;
 int radeon_deep_color = 0;
+int radeon_use_pflipirq = 2;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 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);
 MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))");
 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[] = {
        radeon_PCI_IDS
 };
index 806bed1758d6aad2066c12672e4fb78da756089b..011779bd2b3da677129b38709742f673bbaa3398 100644 (file)
@@ -6531,7 +6531,8 @@ restart_ih:
                case 16: /* D5 page flip */
                case 18: /* D6 page flip */
                        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;
                case 42: /* HPD hotplug */
                        switch (src_data) {