aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2013-10-24 02:50:50 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-01-09 08:15:24 -0500
commit6da9f89172b94411896130c6e1acf159da3dc760 (patch)
treefb656b3cd9cdb5973f6891ccde3be5fb4fcb739a
parent802eee95bde72fd0cd0f3a5b2098375a487d1eda (diff)
drm/omap: fix (un)registering irqs inside an irq handler
omapdrm (un)registers irqs inside an irq handler. The problem is that the (un)register function uses dispc_runtime_get/put() to enable the clocks, and those functions are not irq safe by default. This was kind of fixed in 48664b21aeeffb40c5fa06843f18052e2c4ec9ef (OMAPDSS: DISPC: set irq_safe for runtime PM), which makes dispc's runtime calls irq-safe. However, using pm_runtime_irq_safe in dispc makes the parent of dispc, dss, always enabled, effectively preventing PM for the whole DSS module. This patch makes omapdrm behave better by adding new irq (un)register functions that do not use dispc_runtime_get/put, and using those functions in interrupt context. Thus we can make dispc again non-irq-safe, allowing proper PM. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Cc: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_irq.c22
-rw-r--r--drivers/video/omap2/dss/dispc.c1
4 files changed, 23 insertions, 8 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 0fd2eb139f6e..e6241c2b8b26 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
411 struct drm_crtc *crtc = &omap_crtc->base; 411 struct drm_crtc *crtc = &omap_crtc->base;
412 DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); 412 DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
413 /* avoid getting in a flood, unregister the irq until next vblank */ 413 /* avoid getting in a flood, unregister the irq until next vblank */
414 omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); 414 __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
415} 415}
416 416
417static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) 417static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -421,13 +421,13 @@ static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
421 struct drm_crtc *crtc = &omap_crtc->base; 421 struct drm_crtc *crtc = &omap_crtc->base;
422 422
423 if (!omap_crtc->error_irq.registered) 423 if (!omap_crtc->error_irq.registered)
424 omap_irq_register(crtc->dev, &omap_crtc->error_irq); 424 __omap_irq_register(crtc->dev, &omap_crtc->error_irq);
425 425
426 if (!dispc_mgr_go_busy(omap_crtc->channel)) { 426 if (!dispc_mgr_go_busy(omap_crtc->channel)) {
427 struct omap_drm_private *priv = 427 struct omap_drm_private *priv =
428 crtc->dev->dev_private; 428 crtc->dev->dev_private;
429 DBG("%s: apply done", omap_crtc->name); 429 DBG("%s: apply done", omap_crtc->name);
430 omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); 430 __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
431 queue_work(priv->wq, &omap_crtc->apply_work); 431 queue_work(priv->wq, &omap_crtc->apply_work);
432 } 432 }
433} 433}
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 07847693cf49..e835c27c5ad4 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -145,6 +145,8 @@ irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
145void omap_irq_preinstall(struct drm_device *dev); 145void omap_irq_preinstall(struct drm_device *dev);
146int omap_irq_postinstall(struct drm_device *dev); 146int omap_irq_postinstall(struct drm_device *dev);
147void omap_irq_uninstall(struct drm_device *dev); 147void omap_irq_uninstall(struct drm_device *dev);
148void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
149void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
148void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); 150void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
149void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); 151void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
150int omap_drm_irq_uninstall(struct drm_device *dev); 152int omap_drm_irq_uninstall(struct drm_device *dev);
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index cb858600185f..da690d0e0f03 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_device *dev)
45 dispc_read_irqenable(); /* flush posted write */ 45 dispc_read_irqenable(); /* flush posted write */
46} 46}
47 47
48void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) 48void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
49{ 49{
50 struct omap_drm_private *priv = dev->dev_private; 50 struct omap_drm_private *priv = dev->dev_private;
51 unsigned long flags; 51 unsigned long flags;
52 52
53 dispc_runtime_get();
54 spin_lock_irqsave(&list_lock, flags); 53 spin_lock_irqsave(&list_lock, flags);
55 54
56 if (!WARN_ON(irq->registered)) { 55 if (!WARN_ON(irq->registered)) {
@@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
60 } 59 }
61 60
62 spin_unlock_irqrestore(&list_lock, flags); 61 spin_unlock_irqrestore(&list_lock, flags);
62}
63
64void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
65{
66 dispc_runtime_get();
67
68 __omap_irq_register(dev, irq);
69
63 dispc_runtime_put(); 70 dispc_runtime_put();
64} 71}
65 72
66void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) 73void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
67{ 74{
68 unsigned long flags; 75 unsigned long flags;
69 76
70 dispc_runtime_get();
71 spin_lock_irqsave(&list_lock, flags); 77 spin_lock_irqsave(&list_lock, flags);
72 78
73 if (!WARN_ON(!irq->registered)) { 79 if (!WARN_ON(!irq->registered)) {
@@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
77 } 83 }
78 84
79 spin_unlock_irqrestore(&list_lock, flags); 85 spin_unlock_irqrestore(&list_lock, flags);
86}
87
88void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
89{
90 dispc_runtime_get();
91
92 __omap_irq_unregister(dev, irq);
93
80 dispc_runtime_put(); 94 dispc_runtime_put();
81} 95}
82 96
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 4ec59ca72e5d..91c687fd002e 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3691,7 +3691,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
3691 } 3691 }
3692 3692
3693 pm_runtime_enable(&pdev->dev); 3693 pm_runtime_enable(&pdev->dev);
3694 pm_runtime_irq_safe(&pdev->dev);
3695 3694
3696 r = dispc_runtime_get(); 3695 r = dispc_runtime_get();
3697 if (r) 3696 if (r)