From: Jérôme Pouiller <jerome.pouil...@silabs.com>

[ Upstream commit ce3653a8d3db096aa163fc80239d8ec1305c81fa ]

The trace below can appear:

    [83613.832200] INFO: trying to register non-static key.
    [83613.837248] the code is fine but needs lockdep annotation.
    [83613.842808] turning off the locking correctness validator.
    [83613.848375] CPU: 3 PID: 141 Comm: kworker/3:2H Tainted: G           O    
  5.6.13-silabs15 #2
    [83613.857019] Hardware name: BCM2835
    [83613.860605] Workqueue: events_highpri bh_work [wfx]
    [83613.865552] Backtrace:
    [83613.868041] [<c010f2cc>] (dump_backtrace) from [<c010f7b8>] 
(show_stack+0x20/0x24)
    [83613.881463] [<c010f798>] (show_stack) from [<c0d82138>] 
(dump_stack+0xe8/0x114)
    [83613.888882] [<c0d82050>] (dump_stack) from [<c01a02ec>] 
(register_lock_class+0x748/0x768)
    [83613.905035] [<c019fba4>] (register_lock_class) from [<c019da04>] 
(__lock_acquire+0x88/0x13dc)
    [83613.924192] [<c019d97c>] (__lock_acquire) from [<c019f6a4>] 
(lock_acquire+0xe8/0x274)
    [83613.942644] [<c019f5bc>] (lock_acquire) from [<c0daa5dc>] 
(_raw_spin_lock_irqsave+0x58/0x6c)
    [83613.961714] [<c0daa584>] (_raw_spin_lock_irqsave) from [<c0ab3248>] 
(skb_dequeue+0x24/0x78)
    [83613.974967] [<c0ab3224>] (skb_dequeue) from [<bf330db0>] 
(wfx_tx_queues_get+0x96c/0x1294 [wfx])
    [83613.989728] [<bf330444>] (wfx_tx_queues_get [wfx]) from [<bf320454>] 
(bh_work+0x454/0x26d8 [wfx])
    [83614.009337] [<bf320000>] (bh_work [wfx]) from [<c014c920>] 
(process_one_work+0x23c/0x7ec)
    [83614.028141] [<c014c6e4>] (process_one_work) from [<c014cf1c>] 
(worker_thread+0x4c/0x55c)
    [83614.046861] [<c014ced0>] (worker_thread) from [<c0154c04>] 
(kthread+0x138/0x168)
    [83614.064876] [<c0154acc>] (kthread) from [<c01010b4>] 
(ret_from_fork+0x14/0x20)
    [83614.072200] Exception stack(0xecad3fb0 to 0xecad3ff8)
    [83614.077323] 3fa0:                                     00000000 00000000 
00000000 00000000
    [83614.085620] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 
00000000 00000000
    [83614.093914] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000

Indeed, the code of wfx_add_interface() shows that the interface is
enabled to early. So, the spinlock associated with some skb_queue may
not yet initialized when wfx_tx_queues_get() is called.

Signed-off-by: Jérôme Pouiller <jerome.pouil...@silabs.com>
Link: 
https://lore.kernel.org/r/20200825085828.399505-8-jerome.pouil...@silabs.com
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/staging/wfx/sta.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c
index 4e30ab17a93d4..b96c83671caeb 100644
--- a/drivers/staging/wfx/sta.c
+++ b/drivers/staging/wfx/sta.c
@@ -760,17 +760,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif)
                return -EOPNOTSUPP;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
-               if (!wdev->vif[i]) {
-                       wdev->vif[i] = vif;
-                       wvif->id = i;
-                       break;
-               }
-       }
-       if (i == ARRAY_SIZE(wdev->vif)) {
-               mutex_unlock(&wdev->conf_mutex);
-               return -EOPNOTSUPP;
-       }
        // FIXME: prefer use of container_of() to get vif
        wvif->vif = vif;
        wvif->wdev = wdev;
@@ -787,12 +776,22 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif)
        init_completion(&wvif->scan_complete);
        INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
 
-       mutex_unlock(&wdev->conf_mutex);
+       wfx_tx_queues_init(wvif);
+       wfx_tx_policy_init(wvif);
+
+       for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
+               if (!wdev->vif[i]) {
+                       wdev->vif[i] = vif;
+                       wvif->id = i;
+                       break;
+               }
+       }
+       WARN(i == ARRAY_SIZE(wdev->vif), "try to instantiate more vif than 
supported");
 
        hif_set_macaddr(wvif, vif->addr);
 
-       wfx_tx_queues_init(wvif);
-       wfx_tx_policy_init(wvif);
+       mutex_unlock(&wdev->conf_mutex);
+
        wvif = NULL;
        while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
                // Combo mode does not support Block Acks. We can re-enable them
@@ -824,6 +823,7 @@ void wfx_remove_interface(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif)
        wvif->vif = NULL;
 
        mutex_unlock(&wdev->conf_mutex);
+
        wvif = NULL;
        while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
                // Combo mode does not support Block Acks. We can re-enable them
-- 
2.25.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to