Restructure the ASYNC case to allow calling idpf_vc_xn_forward_reply()
outside of idpf_vc_xn_lock(). This avoids invalid wait context reported by
the kernel due to the async handler taking BH spinlock:

[  805.726977] =============================
[  805.726991] [ BUG: Invalid wait context ]
[  805.727006] 7.0.0-rc2-net-devq-031026+ #28 Tainted: G S         OE
[  805.727026] -----------------------------
[  805.727038] kworker/u261:0/572 is trying to lock:
[  805.727051] ff190da6a8dbb6a0 
(&vport_config->mac_filter_list_lock){+...}-{3:3}, at: 
idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727099] other info that might help us debug this:
[  805.727111] context-{5:5}
[  805.727119] 3 locks held by kworker/u261:0/572:
[  805.727132]  #0: ff190da6db3e6148 
((wq_completion)idpf-0000:83:00.0-mbx){+.+.}-{0:0}, at: 
process_one_work+0x4b5/0x730
[  805.727163]  #1: ff3c6f0a6131fe50 
((work_completion)(&(&adapter->mbx_task)->work)){+.+.}-{0:0}, at: 
process_one_work+0x1e5/0x730
[  805.727191]  #2: ff190da765190020 (&x->wait#34){+.+.}-{2:2}, at: 
idpf_recv_mb_msg+0xc8/0x710 [idpf]
[  805.727218] stack backtrace:
...
[  805.727238] Workqueue: idpf-0000:83:00.0-mbx idpf_mbx_task [idpf]
[  805.727247] Call Trace:
[  805.727249]  <TASK>
[  805.727251]  dump_stack_lvl+0x77/0xb0
[  805.727259]  __lock_acquire+0xb3b/0x2290
[  805.727268]  ? __irq_work_queue_local+0x59/0x130
[  805.727275]  lock_acquire+0xc6/0x2f0
[  805.727277]  ? idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727284]  ? _printk+0x5b/0x80
[  805.727290]  _raw_spin_lock_bh+0x38/0x50
[  805.727298]  ? idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727303]  idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727310]  idpf_recv_mb_msg+0x1c8/0x710 [idpf]
[  805.727317]  process_one_work+0x226/0x730
[  805.727322]  worker_thread+0x19e/0x340
[  805.727325]  ? __pfx_worker_thread+0x10/0x10
[  805.727328]  kthread+0xf4/0x130
[  805.727333]  ? __pfx_kthread+0x10/0x10
[  805.727336]  ret_from_fork+0x32c/0x410
[  805.727345]  ? __pfx_kthread+0x10/0x10
[  805.727347]  ret_from_fork_asm+0x1a/0x30
[  805.727354]  </TASK>

Fixes: 34c21fa894a1 ("idpf: implement virtchnl transaction manager")
Reported-by: Ray Zhang <[email protected]>
Signed-off-by: Emil Tantilov <[email protected]>
Reviewed-by: Aleksandr Loktionov <[email protected]>
---
 .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 21 +++++++------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c 
b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index 6b9692b30040..8ceabd86e172 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -546,32 +546,24 @@ static int
 idpf_vc_xn_forward_async(struct idpf_adapter *adapter, struct idpf_vc_xn *xn,
                         const struct idpf_ctlq_msg *ctlq_msg)
 {
-       int err = 0;
-
        if (ctlq_msg->cookie.mbx.chnl_opcode != xn->vc_op) {
                dev_err_ratelimited(&adapter->pdev->dev, "Async message opcode 
does not match transaction opcode (msg: %d) (xn: %d)\n",
                                    ctlq_msg->cookie.mbx.chnl_opcode, 
xn->vc_op);
                xn->reply_sz = 0;
-               err = -EINVAL;
-               goto release_bufs;
+               return -EINVAL;
        }
 
-       if (xn->async_handler) {
-               err = xn->async_handler(adapter, xn, ctlq_msg);
-               goto release_bufs;
-       }
+       if (xn->async_handler)
+               return xn->async_handler(adapter, xn, ctlq_msg);
 
        if (ctlq_msg->cookie.mbx.chnl_retval) {
                xn->reply_sz = 0;
                dev_err_ratelimited(&adapter->pdev->dev, "Async message failure 
(op %d)\n",
                                    ctlq_msg->cookie.mbx.chnl_opcode);
-               err = -EINVAL;
+               return -EINVAL;
        }
 
-release_bufs:
-       idpf_vc_xn_release_bufs(xn);
-
-       return err;
+       return 0;
 }
 
 /**
@@ -631,7 +623,10 @@ idpf_vc_xn_forward_reply(struct idpf_adapter *adapter,
                 * can evaluate the response.
                 */
                xn->reply_sz = ctlq_msg->data_len;
+               idpf_vc_xn_unlock(xn);
                err = idpf_vc_xn_forward_async(adapter, xn, ctlq_msg);
+               idpf_vc_xn_lock(xn);
+               idpf_vc_xn_release_bufs(xn);
                idpf_vc_xn_unlock(xn);
                idpf_vc_xn_push_free(adapter->vcxn_mngr, xn);
                return err;
-- 
2.37.3

Reply via email to