aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv50_display.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-02-03 05:06:14 -0500
committerBen Skeggs <bskeggs@redhat.com>2011-02-24 15:44:59 -0500
commitf13e435c59573aa0ac398210777cc0406c476593 (patch)
treee3426e7fab3016eb8ec9b34bb793854b3dbc24dd /drivers/gpu/drm/nouveau/nv50_display.c
parentc7ca4d1b6b529dac9de9ff3f951689f2e4365cc2 (diff)
drm/nv50-nvc0: switch to tasklet for display isr bh
We need to be able to have the bh run while possibly spinning waiting for the EVO notifier to signal. This apparently happens in some circumstances with preempt disabled, so our workqueue was never being run. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c18
1 files changed, 7 insertions, 11 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index c6c3e6ceb24..e295a17d68f 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -35,6 +35,7 @@
35#include "drm_crtc_helper.h" 35#include "drm_crtc_helper.h"
36 36
37static void nv50_display_isr(struct drm_device *); 37static void nv50_display_isr(struct drm_device *);
38static void nv50_display_bh(unsigned long);
38 39
39static inline int 40static inline int
40nv50_sor_nr(struct drm_device *dev) 41nv50_sor_nr(struct drm_device *dev)
@@ -339,7 +340,7 @@ int nv50_display_create(struct drm_device *dev)
339 } 340 }
340 } 341 }
341 342
342 INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); 343 tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev);
343 nouveau_irq_register(dev, 26, nv50_display_isr); 344 nouveau_irq_register(dev, 26, nv50_display_isr);
344 345
345 ret = nv50_display_init(dev); 346 ret = nv50_display_init(dev);
@@ -354,7 +355,6 @@ int nv50_display_create(struct drm_device *dev)
354void 355void
355nv50_display_destroy(struct drm_device *dev) 356nv50_display_destroy(struct drm_device *dev)
356{ 357{
357 struct drm_nouveau_private *dev_priv = dev->dev_private;
358 struct nv50_display *disp = nv50_display(dev); 358 struct nv50_display *disp = nv50_display(dev);
359 359
360 NV_DEBUG_KMS(dev, "\n"); 360 NV_DEBUG_KMS(dev, "\n");
@@ -363,7 +363,6 @@ nv50_display_destroy(struct drm_device *dev)
363 363
364 nv50_display_disable(dev); 364 nv50_display_disable(dev);
365 nouveau_irq_unregister(dev, 26); 365 nouveau_irq_unregister(dev, 26);
366 flush_work_sync(&dev_priv->irq_work);
367 kfree(disp); 366 kfree(disp);
368} 367}
369 368
@@ -770,12 +769,10 @@ ack:
770 nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); 769 nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8);
771} 770}
772 771
773void 772static void
774nv50_display_irq_handler_bh(struct work_struct *work) 773nv50_display_bh(unsigned long data)
775{ 774{
776 struct drm_nouveau_private *dev_priv = 775 struct drm_device *dev = (struct drm_device *)data;
777 container_of(work, struct drm_nouveau_private, irq_work);
778 struct drm_device *dev = dev_priv->dev;
779 776
780 for (;;) { 777 for (;;) {
781 uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); 778 uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
@@ -823,7 +820,7 @@ nv50_display_error_handler(struct drm_device *dev)
823static void 820static void
824nv50_display_isr(struct drm_device *dev) 821nv50_display_isr(struct drm_device *dev)
825{ 822{
826 struct drm_nouveau_private *dev_priv = dev->dev_private; 823 struct nv50_display *disp = nv50_display(dev);
827 uint32_t delayed = 0; 824 uint32_t delayed = 0;
828 825
829 while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { 826 while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {
@@ -851,8 +848,7 @@ nv50_display_isr(struct drm_device *dev)
851 NV50_PDISPLAY_INTR_1_CLK_UNK40)); 848 NV50_PDISPLAY_INTR_1_CLK_UNK40));
852 if (clock) { 849 if (clock) {
853 nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); 850 nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
854 if (!work_pending(&dev_priv->irq_work)) 851 tasklet_schedule(&disp->tasklet);
855 schedule_work(&dev_priv->irq_work);
856 delayed |= clock; 852 delayed |= clock;
857 intr1 &= ~clock; 853 intr1 &= ~clock;
858 } 854 }