MLK-22201 mxc: mlb: fix interrupt rw lock dead lock
authorClark Wang <xiaoning.wang@nxp.com>
Fri, 28 Jun 2019 09:10:36 +0000 (17:10 +0800)
committerClark Wang <xiaoning.wang@nxp.com>
Fri, 5 Jul 2019 08:31:43 +0000 (16:31 +0800)
If read lock is called in mlb150_trans_complete_check, when the same
lock is called from interrupt at the same time it will result in:

[   73.688839] WARNING: inconsistent lock state
[   73.693116] 5.2.0-rc3-next-20190607-20092-ge32edc4b91df-dirty #38 Not tainted
[   73.700256] --------------------------------
[   73.704533] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-R} usage.
[   73.710546] mxc_mlb_test.ou/612 [HC0[0]:SC0[0]:HE1:SE1] takes:
[   73.716386] 554a05da (mlb_devinfo[1].tx_rbuf.rb_lock){-?--}, at: mxc_mlb150_ioctl+0x6a8/0x9a8
[   73.724937] {IN-HARDIRQ-W} state was registered at:
[   73.729827]   _raw_write_lock+0x28/0x38
[   73.733669]   mlb_tx_isr+0x54/0xf8
[   73.737078]   mlb_ahb_isr+0x98/0x124
[   73.740668]   __handle_irq_event_percpu+0x48/0x360
[   73.745467]   handle_irq_event_percpu+0x28/0x7c
[   73.750002]   handle_irq_event+0x38/0x5c
[   73.753934]   handle_fasteoi_irq+0xc0/0x17c
[   73.758125]   generic_handle_irq+0x20/0x34
[   73.762228]   __handle_domain_irq+0x64/0xe0
[   73.766422]   gic_handle_irq+0x4c/0xa8
[   73.770179]   __irq_svc+0x70/0x98
[   73.773506]   cpuidle_enter_state+0x164/0x574
[   73.777869]   cpuidle_enter_state+0x164/0x574
[   73.782232]   cpuidle_enter+0x28/0x38
[   73.785905]   do_idle+0x220/0x2c0
[   73.789226]   cpu_startup_entry+0x18/0x20
[   73.793247]   start_kernel+0x3f4/0x4a0

Fix this by always using irq save rw locks in trans_complete_check.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
drivers/mxc/mlb/mxc_mlb.c

index 4e10cb6..e6d20be 100755 (executable)
@@ -1527,14 +1527,15 @@ static s32 mlb150_trans_complete_check(struct mlb_dev_info *pdevinfo)
        struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf;
        struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf;
        s32 timeout = 1024;
+       unsigned long flags;
 
        while (timeout--) {
-               read_lock(&tx_rbuf->rb_lock);
+               read_lock_irqsave(&tx_rbuf->rb_lock, flags);
                if (!CIRC_CNT(tx_rbuf->head, tx_rbuf->tail, TRANS_RING_NODES)) {
-                       read_unlock(&tx_rbuf->rb_lock);
+                       read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
                        break;
                } else
-                       read_unlock(&tx_rbuf->rb_lock);
+                       read_unlock_irqrestore(&tx_rbuf->rb_lock, flags);
        }
 
        if (timeout <= 0) {
@@ -1544,12 +1545,12 @@ static s32 mlb150_trans_complete_check(struct mlb_dev_info *pdevinfo)
 
        timeout = 1024;
        while (timeout--) {
-               read_lock(&rx_rbuf->rb_lock);
+               read_lock_irqsave(&rx_rbuf->rb_lock, flags);
                if (!CIRC_CNT(rx_rbuf->head, rx_rbuf->tail, TRANS_RING_NODES)) {
-                       read_unlock(&rx_rbuf->rb_lock);
+                       read_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
                        break;
                } else
-                       read_unlock(&rx_rbuf->rb_lock);
+                       read_unlock_irqrestore(&rx_rbuf->rb_lock, flags);
        }
 
        if (timeout <= 0) {