[PATCH] [Streak] Add workaround for TTY kernel OOPS at the cost of performance.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The current framebuffer driver oopses when used as a console (kernel
parameter: console=tty ).
Here is a patch that makes it work - at the cost of performance.

Signed-off-by: Bradley Smith <brad@xxxxxxxxxxxxxxxx>
(cherry picked from commit 28d06a6366c851c6e0c5b954353bf82cb641d4e7)
---
 drivers/video/msm/Kconfig     |    4 ++++
 drivers/video/msm/mdp.c       |   20 ++++++++++++++++++++
 drivers/video/msm/mdp.h       |    3 +++
 drivers/video/msm/mdp_dma.c   |   15 +++++++++++++++
 drivers/video/msm/mdp_dma_s.c |   28 ++++++++++++++++++++++++++++
 drivers/video/msm/msm_fb.c    |    2 ++
 drivers/video/msm/msm_fb.h    |   14 ++++++++++++++
 7 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index e887a2d..cff8435 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -14,3 +14,7 @@ config FB_MSM_LCDC
 	depends on FB_MSM && MSM_MDP31
 	default y
 
+config MSM_FB_TTY_WORKAROUND
+	bool "Workaround TTY kernel OOPS at the cost of performance"
+	depends on FB_MSM
+	default n
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index e56dd81..8bc2b13 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -118,6 +118,10 @@ static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
 struct timeval mdp_dma2_timeval;
 struct timeval mdp_ppp_timeval;
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+LIST_HEAD(msm_fb_dma_task_list);
+#endif
+
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static struct early_suspend early_suspend;
 #endif
@@ -634,10 +638,26 @@ irqreturn_t mdp_isr(int irq, void *ptr)
 		/* DMA2 LCD-Out Complete */
 		if (mdp_interrupt & MDP_DMA_S_DONE) {
 			dma = &dma_s_data;
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+			if(!list_empty(&msm_fb_dma_task_list)) {
+				struct msm_fb_dma_task *tsk = list_first_entry(
+					&msm_fb_dma_task_list, struct msm_fb_dma_task, list);
+				dma->busy = TRUE;
+				mdp_dma_s_update_lcd(tsk->mfd, &tsk->ibuf);
+				list_del(&tsk->list);
+				kfree(tsk);
+			}
+			else {
+				mdp_disable_irq(MDP_DMA_S_TERM);
+				mdp_disable_irq(MDP_DMA_E_TERM);
+				dma->busy = FALSE;
+			}
+#else
 			dma->busy = FALSE;
 			mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
 				      TRUE);
 			complete(&dma->comp);
+#endif
 		}
 		/* DMA_E LCD-Out Complete */
 		if (mdp_interrupt & MDP_DMA_E_DONE) {
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index d60ccae..f3d064b 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -680,4 +680,7 @@ int mdp_debugfs_init(void);
 #endif
 
 void mdp_dma_s_update(struct msm_fb_data_type *mfd);
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd, MDPIBUF *iBuf);
+#endif
 #endif /* MDP_H */
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index dc8d58d..f62c7e3 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -433,7 +433,9 @@ void mdp_dma2_update(struct msm_fb_data_type *mfd)
 	down(&mfd->dma->mutex);
 	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
 		down(&mfd->sem);
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
 		mfd->ibuf_flushed = TRUE;
+#endif
 		mdp_dma2_update_lcd(mfd);
 
 		mdp_enable_irq(MDP_DMA2_TERM);
@@ -448,11 +450,13 @@ void mdp_dma2_update(struct msm_fb_data_type *mfd)
 		wait_for_completion_killable(&mfd->dma->comp);
 		mdp_disable_irq(MDP_DMA2_TERM);
 
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
 	/* signal if pan function is waiting for the update completion */
 		if (mfd->pan_waiting) {
 			mfd->pan_waiting = FALSE;
 			complete(&mfd->pan_comp);
 		}
+#endif
 	}
 	up(&mfd->dma->mutex);
 }
@@ -484,6 +488,12 @@ void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
 
 	iBuf->vsync_enable = sync;
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+	iBuf->dma_x = 0;
+	iBuf->dma_y = 0;
+	iBuf->dma_w = info->var.xres;
+	iBuf->dma_h = info->var.yres;
+#else
 	if (dirty) {
 		/*
 		 * ToDo: dirty region check inside var.xoffset+xres
@@ -500,6 +510,7 @@ void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
 		iBuf->dma_h = info->var.yres;
 	}
 	mfd->ibuf_flushed = FALSE;
+#endif
 	up(&mfd->sem);
 }
 
@@ -510,6 +521,9 @@ void mdp_dma_pan_update(struct fb_info *info)
 
 	iBuf = &mfd->ibuf;
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+	mfd->dma_fnc(mfd);
+#else
 	if (mfd->sw_currently_refreshing) {
 		/* we need to wait for the pending update */
 		mfd->pan_waiting = TRUE;
@@ -521,6 +535,7 @@ void mdp_dma_pan_update(struct fb_info *info)
 		wait_for_completion_killable(&mfd->pan_comp);
 	} else
 		mfd->dma_fnc(mfd);
+#endif
 }
 
 void mdp_refresh_screen(unsigned long data)
diff --git a/drivers/video/msm/mdp_dma_s.c b/drivers/video/msm/mdp_dma_s.c
index ee39504..c9b67d5 100644
--- a/drivers/video/msm/mdp_dma_s.c
+++ b/drivers/video/msm/mdp_dma_s.c
@@ -37,9 +37,14 @@
 #include "mdp.h"
 #include "msm_fb.h"
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd, MDPIBUF *iBuf)
+{
+#else
 static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
 {
 	MDPIBUF *iBuf = &mfd->ibuf;
+#endif
 	int mddi_dest = FALSE;
 	uint32 outBpp = iBuf->bpp;
 	uint32 dma_s_cfg_reg;
@@ -141,6 +146,28 @@ static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
 void mdp_dma_s_update(struct msm_fb_data_type *mfd)
 {
 	down(&mfd->dma->mutex);
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+	if(mfd && mfd->panel_power_on) {
+		if (!mfd->dma->busy) {
+			down(&mfd->sem);
+			mdp_enable_irq(MDP_DMA_S_TERM);
+			if (mfd->panel_info.type == MDDI_PANEL)
+				mdp_enable_irq(MDP_DMA_S_TERM);
+			else
+				mdp_enable_irq(MDP_DMA_E_TERM);
+			mfd->dma->busy = TRUE;
+			mdp_dma_s_update_lcd(mfd, &mfd->ibuf);
+			up(&mfd->sem);
+		}
+		else {
+			struct msm_fb_dma_task *tsk = kzalloc(sizeof(
+				struct msm_fb_dma_task), GFP_ATOMIC);
+			tsk->mfd = mfd;
+			tsk->ibuf = mfd->ibuf;
+			list_add_tail(&tsk->list, &msm_fb_dma_task_list);
+		}
+	}
+#else
 	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
 		down(&mfd->sem);
 		mdp_enable_irq(MDP_DMA_S_TERM);
@@ -167,5 +194,6 @@ void mdp_dma_s_update(struct msm_fb_data_type *mfd)
 			complete(&mfd->pan_comp);
 		}
 	}
+#endif
 	up(&mfd->dma->mutex);
 }
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 14b1860..d355813 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1025,8 +1025,10 @@ static int msm_fb_register(struct msm_fb_data_type *mfd)
 	mfd->sw_refreshing_enable = TRUE;
 	mfd->panel_power_on = FALSE;
 
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
 	mfd->pan_waiting = FALSE;
 	init_completion(&mfd->pan_comp);
+#endif
 	init_completion(&mfd->refresher_comp);
 	init_MUTEX(&mfd->sem);
 
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 2395cb2..2e1e38a 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -63,6 +63,10 @@
 #define MFD_KEY  0x11161126
 #define MSM_FB_MAX_DEV_LIST 32
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+extern struct list_head msm_fb_dma_task_list;
+#endif
+
 struct disp_info_type_suspend {
 	boolean op_enable;
 	boolean sw_refreshing_enable;
@@ -91,12 +95,16 @@ struct msm_fb_data_type {
 #endif
 
 	MDPIBUF ibuf;
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
 	boolean ibuf_flushed;
+#endif
 	struct timer_list refresh_timer;
 	struct completion refresher_comp;
 
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
 	boolean pan_waiting;
 	struct completion pan_comp;
+#endif
 
 	/* vsync */
 	boolean use_mdp_vsync;
@@ -167,6 +175,12 @@ struct msm_fb_data_type {
 	struct pm_qos_request_list *pm_qos_req;
 };
 
+struct msm_fb_dma_task {
+	struct msm_fb_data_type* mfd;
+	MDPIBUF ibuf;
+	struct list_head list;
+};
+
 struct dentry *msm_fb_get_debugfs_root(void);
 void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
 				u32 *var);
-- 
1.7.0.4


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux