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 | |
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')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_irq.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.h | 1 |
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 | ||
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); |
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 | ||
38 | void nv50_display_irq_handler(struct drm_device *dev); | 38 | void nv50_display_irq_handler(struct drm_device *dev); |
39 | void nv50_display_irq_handler_bh(struct work_struct *work); | 39 | void nv50_display_irq_handler_bh(struct work_struct *work); |
40 | void nv50_display_irq_hotplug_bh(struct work_struct *work); | ||
40 | int nv50_display_init(struct drm_device *dev); | 41 | int nv50_display_init(struct drm_device *dev); |
41 | int nv50_display_create(struct drm_device *dev); | 42 | int nv50_display_create(struct drm_device *dev); |
42 | int nv50_display_destroy(struct drm_device *dev); | 43 | int nv50_display_destroy(struct drm_device *dev); |