aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-03-30 01:14:41 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-04-08 20:15:40 -0400
commita5acac66685397a73bed8638114262520565e41c (patch)
treeb5538c51a89db9afa8ea4dc563ad9f0968259889 /drivers/gpu/drm
parent6f335a7afa6bc57603f39430dc6f9e57de288a91 (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')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.c1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c14
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.h1
4 files changed, 12 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index f7d4d2a10052..c4f5658b9e49 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -520,6 +520,7 @@ struct drm_nouveau_private {
520 520
521 struct workqueue_struct *wq; 521 struct workqueue_struct *wq;
522 struct work_struct irq_work; 522 struct work_struct irq_work;
523 struct work_struct hpd_work;
523 524
524 struct list_head vbl_waiting; 525 struct list_head vbl_waiting;
525 526
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 2bd59a92fee5..13e73cee4c44 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -51,6 +51,7 @@ nouveau_irq_preinstall(struct drm_device *dev)
51 51
52 if (dev_priv->card_type == NV_50) { 52 if (dev_priv->card_type == NV_50) {
53 INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); 53 INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
54 INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);
54 INIT_LIST_HEAD(&dev_priv->vbl_waiting); 55 INIT_LIST_HEAD(&dev_priv->vbl_waiting);
55 } 56 }
56} 57}
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)
887 nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); 887 nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
888} 888}
889 889
890static void 890void
891nv50_display_irq_hotplug(struct drm_device *dev) 891nv50_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);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h
index 3ae8d0725f63..581d405ac014 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.h
+++ b/drivers/gpu/drm/nouveau/nv50_display.h
@@ -37,6 +37,7 @@
37 37
38void nv50_display_irq_handler(struct drm_device *dev); 38void nv50_display_irq_handler(struct drm_device *dev);
39void nv50_display_irq_handler_bh(struct work_struct *work); 39void nv50_display_irq_handler_bh(struct work_struct *work);
40void nv50_display_irq_hotplug_bh(struct work_struct *work);
40int nv50_display_init(struct drm_device *dev); 41int nv50_display_init(struct drm_device *dev);
41int nv50_display_create(struct drm_device *dev); 42int nv50_display_create(struct drm_device *dev);
42int nv50_display_destroy(struct drm_device *dev); 43int nv50_display_destroy(struct drm_device *dev);