diff options
author | Gustavo Diaz Prado <x0083741@ti.com> | 2011-05-31 09:25:07 +0100 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2011-05-31 09:25:07 +0100 |
commit | aaa926d9d5f9e0cfe8d559d017f8bfd689a724f1 (patch) | |
tree | aa6ef14f5a65b56313b205c8622f0860ce4ede35 | |
parent | b3eafa1ae7b712fa827cc047088d96cdae5409e0 (diff) |
SGX: UDD: Fix crash when cloning with FB sysfs entries
When a 3D app is runnning (avoiding the tearing effect) there
is a very high chance the pointer to the display is null just
after it has been extracted from the framebuffer and the UI is
cloned using the sysfs entries from the framebuffer.
This problem can be fixed by locking the framebuffer when the
synchronization is happening and also when the frame is being
pushed to the display as well.
Signed-off-by: Gustavo Diaz Prado <x0083741@ti.com>
Change-Id: Ia4e6cc6d52ba03f0098bc45ee019173d44925333
-rw-r--r-- | drivers/gpu/pvr/omaplfb/omaplfb_linux.c | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/drivers/gpu/pvr/omaplfb/omaplfb_linux.c b/drivers/gpu/pvr/omaplfb/omaplfb_linux.c index 9fbb66f2ef1..10805d64158 100644 --- a/drivers/gpu/pvr/omaplfb/omaplfb_linux.c +++ b/drivers/gpu/pvr/omaplfb/omaplfb_linux.c @@ -145,31 +145,26 @@ OMAP_ERROR OMAPLFBGetLibFuncAddr (char *szFunctionName, return OMAP_OK; } - #if defined(FLIP_TECHNIQUE_FRAMEBUFFER) /* * Presents the flip in the display with the framebuffer API * in: psSwapChain, aPhyAddr */ -void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) +static void OMAPLFBFlipNoLock(OMAPLFB_SWAPCHAIN *psSwapChain, + unsigned long aPhyAddr) { - OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)psSwapChain->pvDevInfo; - struct fb_info * framebuffer = psDevInfo->psLINFBInfo; - struct omapfb_info *ofbi = FB2OFB(framebuffer); - struct omapfb2_device *fbdev = ofbi->fbdev; + OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)psSwapChain->pvDevInfo; + struct fb_info *framebuffer = psDevInfo->psLINFBInfo; + /* Get the framebuffer physical address base */ unsigned long fb_base_phyaddr = psDevInfo->sSystemBuffer.sSysAddr.uiAddr; - omapfb_lock(fbdev); - /* Calculate the virtual Y to move in the framebuffer */ framebuffer->var.yoffset = (aPhyAddr - fb_base_phyaddr) / framebuffer->fix.line_length; framebuffer->var.activate = FB_ACTIVATE_FORCE; fb_set_var(framebuffer, &framebuffer->var); - - omapfb_unlock(fbdev); } #elif defined(FLIP_TECHNIQUE_OVERLAY) @@ -177,19 +172,17 @@ void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) * Presents the flip in the display with the DSS2 overlay API * in: psSwapChain, aPhyAddr */ -void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) +static void OMAPLFBFlipNoLock(OMAPLFB_SWAPCHAIN *psSwapChain, + unsigned long aPhyAddr) { - OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)psSwapChain->pvDevInfo; + OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)psSwapChain->pvDevInfo; struct fb_info * framebuffer = psDevInfo->psLINFBInfo; struct omapfb_info *ofbi = FB2OFB(framebuffer); - struct omapfb2_device *fbdev = ofbi->fbdev; unsigned long fb_offset; int i; fb_offset = aPhyAddr - psDevInfo->sSystemBuffer.sSysAddr.uiAddr; - omapfb_lock(fbdev); - for(i = 0; i < ofbi->num_overlays ; i++) { struct omap_dss_device *display = NULL; @@ -207,9 +200,12 @@ void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) overlay->set_overlay_info(overlay, &overlay_info); if (manager) { - manager->apply(manager); display = manager->device; - driver = display ? display->driver : NULL; + /* No display attached to this overlay, don't update */ + if (!display) + continue; + driver = display->driver; + manager->apply(manager); } if (dss_ovl_manually_updated(overlay)) { @@ -225,8 +221,6 @@ void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) } } - - omapfb_unlock(fbdev); } #else @@ -234,6 +228,18 @@ void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) FLIP_TECHNIQUE_FRAMEBUFFER or FLIP_TECHNIQUE_OVERLAY #endif +void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) +{ + OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)psSwapChain->pvDevInfo; + struct fb_info *framebuffer = psDevInfo->psLINFBInfo; + struct omapfb_info *ofbi = FB2OFB(framebuffer); + struct omapfb2_device *fbdev = ofbi->fbdev; + + omapfb_lock(fbdev); + OMAPLFBFlipNoLock(psSwapChain, aPhyAddr); + omapfb_unlock(fbdev); +} + /* * Present frame and synchronize with the display to prevent tearing * On DSI panels the sync function is used to handle FRAMEDONE IRQ @@ -243,15 +249,22 @@ void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr) void OMAPLFBPresentSync(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_FLIP_ITEM *psFlipItem) { - struct fb_info * framebuffer = psDevInfo->psLINFBInfo; - struct omap_dss_device *display = fb2display(framebuffer); + struct fb_info *framebuffer = psDevInfo->psLINFBInfo; + struct omapfb_info *ofbi = FB2OFB(framebuffer); + struct omap_dss_device *display; + struct omapfb2_device *fbdev = ofbi->fbdev; struct omap_dss_driver *driver; struct omap_overlay_manager *manager; int err = 1; - if (!display) - WARNING_PRINTK("No DSS device to sync with display %u!", - psDevInfo->uDeviceID); + omapfb_lock(fbdev); + + display = fb2display(framebuffer); + /* The framebuffer doesn't have a display attached, just bail out */ + if (!display) { + omapfb_unlock(fbdev); + return; + } driver = display->driver; manager = display->manager; @@ -260,14 +273,14 @@ void OMAPLFBPresentSync(OMAPLFB_DEVINFO *psDevInfo, driver->get_update_mode(display) == OMAP_DSS_UPDATE_MANUAL) { /* Wait first for the DSI bus to be released then update */ err = driver->sync(display); - OMAPLFBFlip(psDevInfo->psSwapChain, + OMAPLFBFlipNoLock(psDevInfo->psSwapChain, (unsigned long)psFlipItem->sSysAddr->uiAddr); } else if (manager && manager->wait_for_vsync) { /* * Update the video pipelines registers then wait until the * frame is shown with a VSYNC */ - OMAPLFBFlip(psDevInfo->psSwapChain, + OMAPLFBFlipNoLock(psDevInfo->psSwapChain, (unsigned long)psFlipItem->sSysAddr->uiAddr); err = manager->wait_for_vsync(manager); } @@ -275,6 +288,8 @@ void OMAPLFBPresentSync(OMAPLFB_DEVINFO *psDevInfo, if (err) WARNING_PRINTK("Unable to sync with display %u!", psDevInfo->uDeviceID); + + omapfb_unlock(fbdev); } #if defined(LDM_PLATFORM) |