diff options
author | Fancy Fang <chen.fang@nxp.com> | 2017-09-27 15:49:41 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 75c109fb4eb7c4fb0893a2c3f71e7c5715429c45 (patch) | |
tree | 18c880a22b58ea3d3b359dfa0412d38e25a9d220 /drivers/video | |
parent | b6e98d0e8949d2ce6e89ff434e774266ee5f6274 (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.c | 13 |
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 { |