diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-03-30 15:14:41 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-04-09 10:15:40 +1000 |
commit | a5acac66685397a73bed8638114262520565e41c (patch) | |
tree | b5538c51a89db9afa8ea4dc563ad9f0968259889 /drivers/gpu/drm/nouveau/nv50_display.c | |
parent | 6f335a7afa6bc57603f39430dc6f9e57de288a91 (diff) | |
download | blackbird-op-linux-a5acac66685397a73bed8638114262520565e41c.tar.gz blackbird-op-linux-a5acac66685397a73bed8638114262520565e41c.zip |
drm/nv50: punt hotplug irq handling out to workqueue
On DP outputs we'll likely end up running vbios init tables here, which
may sleep.
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 | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index fd00f4000f14..649db4c1b690 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -887,10 +887,12 @@ nv50_display_error_handler(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); } -static void -nv50_display_irq_hotplug(struct drm_device *dev) +void +nv50_display_irq_hotplug_bh(struct work_struct *work) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = + container_of(work, struct drm_nouveau_private, hpd_work); + struct drm_device *dev = dev_priv->dev; struct drm_connector *connector; const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; uint32_t unplug_mask, plug_mask, change_mask; @@ -951,8 +953,10 @@ nv50_display_irq_handler(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t delayed = 0; - while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) - nv50_display_irq_hotplug(dev); + if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { + if (!work_pending(&dev_priv->hpd_work)) + queue_work(dev_priv->wq, &dev_priv->hpd_work); + } while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); |