diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-02-03 05:06:14 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-02-24 15:44:59 -0500 |
commit | f13e435c59573aa0ac398210777cc0406c476593 (patch) | |
tree | e3426e7fab3016eb8ec9b34bb793854b3dbc24dd /drivers/gpu/drm/nouveau/nv50_display.c | |
parent | c7ca4d1b6b529dac9de9ff3f951689f2e4365cc2 (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.c | 18 |
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 | ||
37 | static void nv50_display_isr(struct drm_device *); | 37 | static void nv50_display_isr(struct drm_device *); |
38 | static void nv50_display_bh(unsigned long); | ||
38 | 39 | ||
39 | static inline int | 40 | static inline int |
40 | nv50_sor_nr(struct drm_device *dev) | 41 | nv50_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) | |||
354 | void | 355 | void |
355 | nv50_display_destroy(struct drm_device *dev) | 356 | nv50_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 | ||
773 | void | 772 | static void |
774 | nv50_display_irq_handler_bh(struct work_struct *work) | 773 | nv50_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) | |||
823 | static void | 820 | static void |
824 | nv50_display_isr(struct drm_device *dev) | 821 | nv50_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 | } |