summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorFancy Fang <chen.fang@nxp.com>2017-09-27 15:49:41 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:28:38 +0800
commitba438d65c565445663577d213cf5d902e15aea5c (patch)
tree8790c0fae245d3f04051807212e092c1e2bf8a28 /drivers/video
parent9b34ec841eb81471fae9bdc7cb0325602dd8b1b3 (diff)
MLK-16536-13 video: fbdev: dcss: improve 'kfifo_to_end_len()' macro
The macro 'kfifo_to_end_len()' is used to get the length between the current kfifo 'in' and the kfifo end. Previous implementation has a short-coming under the new strategy that multiple commits are combined into one cfifo flush. For a simple example, commits 'A' and 'B' are going to be combined into one flush, and the last byte of 'A' exactly occupy the last byte of fifo coincidently. Then when handling the 'B' commit, the old 'kfifo_to_end_len()' logic returns the fifo size instead of 0, So the condition 'commit_size > kfifo_to_end_len(&cfifo->fifo)' will be false and let 'B' to be stored from fifo beginning which finally triggers below kernel BUG log: [ 568.558341] ------------[ cut here ]------------ [ 568.558343] kernel BUG at drivers/video/fbdev/mxc/imx_dcss.c:2261! [ 568.558348] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [ 568.558354] Modules linked in: [ 568.558362] CPU: 0 PID: 34 Comm: kworker/u8:1 Not tainted [ 568.558364] Hardware name: Freescale i.MX8MQ EVK (DT) [ 568.558385] Workqueue: ctxld-wq dcss_ctxld_config [ 568.558387] task: ffff8000ba2d8c80 task.stack: ffff8000ba2f8000 [ 568.558392] PC is at dcss_ctxld_config+0x1dc/0x1e8 [ 568.558396] LR is at dcss_ctxld_config+0x1dc/0x1e8 [ 568.558398] pc : [<ffff0000084786c4>] lr : [<ffff0000084786c4>] pstate: 80000145 [ 568.558399] sp : ffff8000ba2fbd30 [ 568.558404] x29: ffff8000ba2fbd30 x28: ffff8000ba1f0000 [ 568.558407] x27: ffff8000ba0096a8 x26: ffff8000ba9d8930 [ 568.558411] x25: ffff8000ba3a2410 x24: 0000000000000003 [ 568.558414] x23: 0000000000000008 x22: ffff8000ba9d8918 [ 568.558417] x21: ffff8000ba9d88f0 x20: ffff8000ba9d8818 [ 568.558421] x19: ffff8000bbdd0080 x18: ffffffffffffffff [ 568.558424] x17: 0000ffff934c8b60 x16: ffff0000081df178 [ 568.558427] x15: ffff0000092db010 x14: 202c387830203d20 [ 568.558431] x13: ffff0000092dafe0 x12: ffff0000091be498 [ 568.558434] x11: ffff0000091be498 x10: ffff0000092d8650 [ 568.558437] x9 : 0000000000000000 x8 : ffff8000bff7352f [ 568.558441] x7 : 0000000000000000 x6 : 0000000000000016 [ 568.558444] x5 : 0000000000804738 x4 : 0000000000000000 [ 568.558447] x3 : 0000000000000140 x2 : 000000000000f9bd [ 568.558450] x1 : ffff8000ba2f8000 x0 : 0000000000000030 [ 568.558451] [ 568.558453] Process kworker/u8:1 (pid: 34, stack limit = 0xffff8000ba2f8020) ... [ 568.558541] Call trace: [ 568.558545] Exception stack(0xffff8000ba2fbb60 to 0xffff8000ba2fbc90) ... [ 568.558586] [<ffff0000084786c4>] dcss_ctxld_config+0x1dc/0x1e8 [ 568.558595] [<ffff0000080d3bb4>] process_one_work+0x11c/0x370 [ 568.558600] [<ffff0000080d3e58>] worker_thread+0x50/0x4a0 [ 568.558606] [<ffff0000080d9a70>] kthread+0xd0/0xe8 [ 568.558611] [<ffff000008082e80>] ret_from_fork+0x10/0x50 [ 568.558616] Code: d00055e1 aa1903e0 91074021 94056a66 (d4210000) [ 568.558623] ---[ end trace faae62afa988e865 ]--- [ 568.558707] Unable to handle kernel paging request at virtual address ffffffffffffffd8 [ 568.558709] pgd = ffff8000bbda1000 [ 568.558712] [ffffffffffffffd8] *pgd=00000000fb7ad003 [ 568.558714] , *pud=00000000fb6a0003 [ 568.558715] , *pmd=0000000000000000 ... Signed-off-by: Fancy Fang <chen.fang@nxp.com> Reviewed-by: Robby Cai <robby.cai@nxp.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/mxc/imx_dcss.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/video/fbdev/mxc/imx_dcss.c b/drivers/video/fbdev/mxc/imx_dcss.c
index f1e0be355ad1..62db1fb657d1 100644
--- a/drivers/video/fbdev/mxc/imx_dcss.c
+++ b/drivers/video/fbdev/mxc/imx_dcss.c
@@ -192,7 +192,18 @@
* kfifo_to_end_len - returns the size from 'out' to buffer end
* this is a kfifo extend interface as required
*/
-#define kfifo_to_end_len(fifo) ((kfifo_size(fifo)) - ((fifo)->kfifo.in & (fifo)->kfifo.mask))
+#define kfifo_to_end_len(fifo) ( \
+{ \
+ unsigned int ptr; \
+ \
+ if (!(fifo)->kfifo.in) \
+ ptr = 0; \
+ else \
+ ptr = ((((fifo)->kfifo.in - 1) & (fifo)->kfifo.mask) + 1); \
+ \
+ kfifo_size(fifo) - ptr; \
+} \
+)
/* TODO: */
struct coordinate {