aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c18
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.h2
3 files changed, 8 insertions, 13 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index da426b95cc82..8f6491845692 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -653,7 +653,6 @@ struct drm_nouveau_private {
653 /* interrupt handling */ 653 /* interrupt handling */
654 void (*irq_handler[32])(struct drm_device *); 654 void (*irq_handler[32])(struct drm_device *);
655 bool msi_enabled; 655 bool msi_enabled;
656 struct work_struct irq_work;
657 656
658 struct list_head vbl_waiting; 657 struct list_head vbl_waiting;
659 658
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index c6c3e6ceb24e..e295a17d68f4 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 }
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h
index 97d3ed57fdef..ea37f230aee8 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.h
+++ b/drivers/gpu/drm/nouveau/nv50_display.h
@@ -38,6 +38,7 @@
38struct nv50_display { 38struct nv50_display {
39 struct nouveau_channel *master; 39 struct nouveau_channel *master;
40 40
41 struct tasklet_struct tasklet;
41 struct { 42 struct {
42 struct dcb_entry *dcb; 43 struct dcb_entry *dcb;
43 u16 script; 44 u16 script;
@@ -52,7 +53,6 @@ nv50_display(struct drm_device *dev)
52 return dev_priv->engine.display.priv; 53 return dev_priv->engine.display.priv;
53} 54}
54 55
55void nv50_display_irq_handler_bh(struct work_struct *work);
56int nv50_display_early_init(struct drm_device *dev); 56int nv50_display_early_init(struct drm_device *dev);
57void nv50_display_late_takedown(struct drm_device *dev); 57void nv50_display_late_takedown(struct drm_device *dev);
58int nv50_display_create(struct drm_device *dev); 58int nv50_display_create(struct drm_device *dev);