diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-03-30 01:14:41 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-04-08 20:15:40 -0400 |
commit | a5acac66685397a73bed8638114262520565e41c (patch) | |
tree | b5538c51a89db9afa8ea4dc563ad9f0968259889 /drivers/gpu/drm/nouveau/nv50_display.c | |
parent | 6f335a7afa6bc57603f39430dc6f9e57de288a91 (diff) |
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 fd00f4000f1..649db4c1b69 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) | |||
887 | nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); | 887 | nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); |
888 | } | 888 | } |
889 | 889 | ||
890 | static void | 890 | void |
891 | nv50_display_irq_hotplug(struct drm_device *dev) | 891 | nv50_display_irq_hotplug_bh(struct work_struct *work) |
892 | { | 892 | { |
893 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 893 | struct drm_nouveau_private *dev_priv = |
894 | container_of(work, struct drm_nouveau_private, hpd_work); | ||
895 | struct drm_device *dev = dev_priv->dev; | ||
894 | struct drm_connector *connector; | 896 | struct drm_connector *connector; |
895 | const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; | 897 | const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; |
896 | uint32_t unplug_mask, plug_mask, change_mask; | 898 | uint32_t unplug_mask, plug_mask, change_mask; |
@@ -951,8 +953,10 @@ nv50_display_irq_handler(struct drm_device *dev) | |||
951 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 953 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
952 | uint32_t delayed = 0; | 954 | uint32_t delayed = 0; |
953 | 955 | ||
954 | while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) | 956 | if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { |
955 | nv50_display_irq_hotplug(dev); | 957 | if (!work_pending(&dev_priv->hpd_work)) |
958 | queue_work(dev_priv->wq, &dev_priv->hpd_work); | ||
959 | } | ||
956 | 960 | ||
957 | while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { | 961 | while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { |
958 | uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); | 962 | uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); |