drm/radeon/kms: add irq mitigation code for sw interrupt.
authorDave Airlie <airlied@redhat.com>
Tue, 1 Dec 2009 06:04:56 +0000 (16:04 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 2 Dec 2009 04:00:13 +0000 (14:00 +1000)
We really don't need to process every irq that comes in, we only
really want to do SW irq processing when we are actually waiting for
a fence to pass. I'm not 100% sure this is race free esp on non-MSI systems
so it needs some testing.

Signed-off-by: Dave Airlie <airlied@redhat.com>
13 files changed:
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c

index 0862fa4b746d04fd07212b3914d02030ff1f1fbc..04d4b4ca0ef3a85f0fbaa7a593f1e58d1209cf29 100644 (file)
@@ -3129,7 +3129,6 @@ static int r100_startup(struct radeon_device *rdev)
                        return r;
        }
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        r100_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index 430fc2a984b2c4c8383b1a6470f96326324a482f..6be3acdc9e7d9906a23dd9992d330d14c2df3dfc 100644 (file)
@@ -1205,7 +1205,6 @@ static int r300_startup(struct radeon_device *rdev)
                        return r;
        }
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        r100_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index e7c34776a013eac161af6a2ee889e1b1cebce1ca..885610f8dd853491293a54ad71c9258b94c2f7a7 100644 (file)
@@ -186,7 +186,6 @@ static int r420_startup(struct radeon_device *rdev)
        }
        r420_pipes_init(rdev);
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        r100_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index 26c37792c8fef94bf072570cafaf6573413dcb0b..92fbc982b8896401c8066e84a193f310a5ef0ee2 100644 (file)
@@ -185,7 +185,6 @@ static int r520_startup(struct radeon_device *rdev)
                        return r;
        }
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        rs600_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index 5067ab7fdcedea9b60621f4335bb77a96725f34d..5966027aa96721b9843fae9493602e036312f007 100644 (file)
@@ -1571,7 +1571,6 @@ int r600_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        r = r600_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);
index 0b8dad604ad8c59948cd718c920a9d3cd2370d45..bdad153953e6ece97936a5328a88ebd52b51cfc6 100644 (file)
@@ -352,11 +352,14 @@ struct radeon_irq {
        bool            sw_int;
        /* FIXME: use a define max crtc rather than hardcode it */
        bool            crtc_vblank_int[2];
+       spinlock_t sw_lock;
+       int sw_refcount;
 };
 
 int radeon_irq_kms_init(struct radeon_device *rdev);
 void radeon_irq_kms_fini(struct radeon_device *rdev);
-
+void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev);
+void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev);
 
 /*
  * CP & ring.
index ab2a8b16836c5aedba199f5c98170a6b3812ade2..2ac31633d72c4d802e32fb2a2d1849690f244a74 100644 (file)
@@ -193,14 +193,18 @@ retry:
        }
 
        if (intr) {
+               radeon_irq_kms_sw_irq_get(rdev);
                r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
                                radeon_fence_signaled(fence), timeout);
+               radeon_irq_kms_sw_irq_put(rdev);
                if (unlikely(r == -ERESTARTSYS)) {
                        return -EBUSY;
                }
        } else {
+               radeon_irq_kms_sw_irq_get(rdev);
                r = wait_event_timeout(rdev->fence_drv.queue,
                         radeon_fence_signaled(fence), timeout);
+               radeon_irq_kms_sw_irq_put(rdev);
        }
        if (unlikely(!radeon_fence_signaled(fence))) {
                if (unlikely(r == 0)) {
index 84f8a6fb0da30e1e02408daea422f674d966e47c..26789970c5cf60f5f57c9e9a390d86e4a1512b89 100644 (file)
@@ -87,7 +87,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
 
        if (rdev->flags & RADEON_SINGLE_CRTC)
                num_crtc = 1;
-
+       spin_lock_init(&rdev->irq.sw_lock);
        r = drm_vblank_init(rdev->ddev, num_crtc);
        if (r) {
                return r;
@@ -122,3 +122,29 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
                        pci_disable_msi(rdev->pdev);
        }
 }
+
+void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&rdev->irq.sw_lock, irqflags);
+       if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount == 1)) {
+               rdev->irq.sw_int = true;
+               radeon_irq_set(rdev);
+       }
+       spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags);
+}
+
+void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&rdev->irq.sw_lock, irqflags);
+       BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount <= 0);
+       if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount == 0)) {
+               rdev->irq.sw_int = false;
+               radeon_irq_set(rdev);
+       }
+       spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags);
+}
+
index 2e5b9450a804d79a2bbfe2a5618aec872fe54481..50907f84461b5990a81074e515b2c5829d304f3e 100644 (file)
@@ -394,7 +394,6 @@ static int rs400_startup(struct radeon_device *rdev)
        if (r)
                return r;
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        r100_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index d2dac45173c2fabc30bd36133ad00967f7879b7b..9b6303dd7d3a6a7bb2da852ea7904d252ca4704a 100644 (file)
@@ -388,7 +388,6 @@ static int rs600_startup(struct radeon_device *rdev)
        if (r)
                return r;
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        rs600_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index 7ffd6db1223f51d760d7fddb1481c10c87da3797..4607025125c03d79021546c7e5f86c32d270fcf8 100644 (file)
@@ -605,7 +605,6 @@ static int rs690_startup(struct radeon_device *rdev)
        if (r)
                return r;
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        rs600_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index 93de4a9807ab34a65a2b0abefb7d953fd2f5ed88..0ecf5d939aa0efcc944e5c4e4ff89062f420f5ef 100644 (file)
@@ -478,7 +478,6 @@ static int rv515_startup(struct radeon_device *rdev)
                        return r;
        }
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        rs600_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
index 479684bda7e23f33f54b794f36da3676fb229207..a96be8b3a53009a92c9cc0f39efda891267d2970 100644 (file)
@@ -888,7 +888,6 @@ static int rv770_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
-       rdev->irq.sw_int = true;
        r = r600_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);