From 1614f8b17b8cc3ad143541d41569623d30dbc9ec Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 1 Dec 2009 16:04:56 +1000 Subject: [PATCH] drm/radeon/kms: add irq mitigation code for sw interrupt. 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 --- drivers/gpu/drm/radeon/r100.c | 1 - drivers/gpu/drm/radeon/r300.c | 1 - drivers/gpu/drm/radeon/r420.c | 1 - drivers/gpu/drm/radeon/r520.c | 1 - drivers/gpu/drm/radeon/r600.c | 1 - drivers/gpu/drm/radeon/radeon.h | 5 ++++- drivers/gpu/drm/radeon/radeon_fence.c | 4 ++++ drivers/gpu/drm/radeon/radeon_irq_kms.c | 28 ++++++++++++++++++++++++- drivers/gpu/drm/radeon/rs400.c | 1 - drivers/gpu/drm/radeon/rs600.c | 1 - drivers/gpu/drm/radeon/rs690.c | 1 - drivers/gpu/drm/radeon/rv515.c | 1 - drivers/gpu/drm/radeon/rv770.c | 1 - 13 files changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 0862fa4b746d0..04d4b4ca0ef3a 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -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); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 430fc2a984b2c..6be3acdc9e7d9 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -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); diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index e7c34776a013e..885610f8dd853 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -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); diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 26c37792c8fef..92fbc982b8896 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -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); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 5067ab7fdcede..5966027aa9672 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -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); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 0b8dad604ad8c..bdad153953e6e 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -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. diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index ab2a8b16836c5..2ac31633d72c4 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -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)) { diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 84f8a6fb0da30..26789970c5cf6 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -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); +} + diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 2e5b9450a804d..50907f84461b5 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -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); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index d2dac45173c2f..9b6303dd7d3a6 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -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); diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 7ffd6db1223f5..4607025125c03 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -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); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 93de4a9807ab3..0ecf5d939aa0e 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -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); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 479684bda7e23..a96be8b3a5300 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -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); -- 2.30.2