summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Diaz Prado <x0083741@ti.com>2011-05-31 09:25:07 +0100
committerAndy Green <andy.green@linaro.org>2011-05-31 09:25:07 +0100
commitaaa926d9d5f9e0cfe8d559d017f8bfd689a724f1 (patch)
treeaa6ef14f5a65b56313b205c8622f0860ce4ede35
parentb3eafa1ae7b712fa827cc047088d96cdae5409e0 (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.c67
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)