summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorFancy Fang <chen.fang@nxp.com>2017-09-27 15:49:41 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commit75c109fb4eb7c4fb0893a2c3f71e7c5715429c45 (patch)
tree18c880a22b58ea3d3b359dfa0412d38e25a9d220 /drivers/video
parentb6e98d0e8949d2ce6e89ff434e774266ee5f6274 (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 3ef2d741c319..f581c7f3d856 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 {