提交 d173d3dc 编写于 作者: L Laurent Pinchart

drm: omapdrm: Use a spinlock to protect the CRTC pending flag

The CRTC pending flag will need to be accessed atomically in the vblank
interrupt handler, memory barriers won't be enough to protect it. Use a
spinlock instead.
Signed-off-by: NLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: NTomi Valkeinen <tomi.valkeinen@ti.com>
上级 577d3983
......@@ -69,6 +69,19 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
return omap_crtc->channel;
}
static bool omap_crtc_is_pending(struct drm_crtc *crtc)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
unsigned long flags;
bool pending;
spin_lock_irqsave(&crtc->dev->event_lock, flags);
pending = omap_crtc->pending;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
return pending;
}
int omap_crtc_wait_pending(struct drm_crtc *crtc)
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
......@@ -78,7 +91,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc)
* a single frame refresh even on slower displays.
*/
return wait_event_timeout(omap_crtc->pending_wait,
!omap_crtc->pending,
!omap_crtc_is_pending(crtc),
msecs_to_jiffies(250));
}
......@@ -296,6 +309,7 @@ static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
struct omap_crtc *omap_crtc =
container_of(irq, struct omap_crtc, vblank_irq);
struct drm_device *dev = omap_crtc->base.dev;
struct drm_crtc *crtc = &omap_crtc->base;
if (dispc_mgr_go_busy(omap_crtc->channel))
return;
......@@ -304,10 +318,10 @@ static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
__omap_irq_unregister(dev, &omap_crtc->vblank_irq);
rmb();
spin_lock(&crtc->dev->event_lock);
WARN_ON(!omap_crtc->pending);
omap_crtc->pending = false;
wmb();
spin_unlock(&crtc->dev->event_lock);
/* wake up userspace */
omap_crtc_complete_page_flip(&omap_crtc->base);
......@@ -339,10 +353,10 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
DBG("%s", omap_crtc->name);
rmb();
spin_lock_irq(&crtc->dev->event_lock);
WARN_ON(omap_crtc->pending);
omap_crtc->pending = true;
wmb();
spin_unlock_irq(&crtc->dev->event_lock);
omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
......@@ -427,16 +441,13 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
DBG("%s: GO", omap_crtc->name);
rmb();
spin_lock_irq(&crtc->dev->event_lock);
WARN_ON(omap_crtc->pending);
omap_crtc->pending = true;
wmb();
if (crtc->state->event) {
spin_lock_irq(&crtc->dev->event_lock);
if (crtc->state->event)
omap_crtc->event = crtc->state->event;
spin_unlock_irq(&crtc->dev->event_lock);
}
spin_unlock_irq(&crtc->dev->event_lock);
dispc_mgr_go(omap_crtc->channel);
omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册