From: "Jérôme Pouiller" <jerome.pouiller@silabs.com>
To: "kvalo@kernel.org" <kvalo@kernel.org>,
"Sverdlin, Alexander" <alexander.sverdlin@siemens.com>
Cc: "linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v3 7/8] wifi: wfx: allow to send frames during ROC
Date: Tue, 26 Nov 2024 15:45:31 +0100 [thread overview]
Message-ID: <1769588.QkHrqEjB74@nb0018864> (raw)
In-Reply-To: <d8e9a080b3fa9a444e4634bcc85b22bcc1ed57a6.camel@siemens.com>
On Tuesday 26 November 2024 08:27:43 CET Sverdlin, Alexander wrote:
>
> Hi Jerome,
>
> I've just got this (with CONFIG_PROVE_LOCKING) in idle,
> without any traffic on the wlan interface:
>
> [119012.104386] INFO: trying to register non-static key.
> [119012.109730] The code is fine but needs lockdep annotation, or maybe
> [119012.116313] you didn't initialize this object before use?
> [119012.121992] turning off the locking correctness validator.
> [119012.127778] CPU: 0 UID: 0 PID: 336 Comm: kworker/0:1H Tainted: G O 6.11.0
> [119012.139802] Tainted: [O]=OOT_MODULE
> [119012.148547] Workqueue: wfx_bh_wq bh_work [wfx]
> [119012.153591] Call trace:
> [119012.156282] dump_backtrace+0xa0/0x128
> [119012.160340] show_stack+0x20/0x38
> [119012.163939] dump_stack_lvl+0x8c/0xd0
> [119012.167890] dump_stack+0x18/0x28
> [119012.171472] register_lock_class+0x4b0/0x4c0
> [119012.176033] __lock_acquire+0xa0/0x1f50
> [119012.180148] lock_acquire+0x1f8/0x330
> [119012.184083] _raw_spin_lock_irqsave+0x68/0x98
> [119012.188731] skb_dequeue+0x2c/0xa8
> [119012.192390] wfx_tx_queues_get+0x20c/0x5a0 [wfx]
> [119012.197525] bh_work+0x3bc/0x950 [wfx]
> [119012.201749] process_one_work+0x234/0x658
> [119012.206040] worker_thread+0x1bc/0x360
> [119012.210056] kthread+0x124/0x130
> [119012.213535] ret_from_fork+0x10/0x20
>
> the uptime is pretty high, as you can see, it's not in startup.
> But I've noticed that NetworkManeger closes and opens
> the interface from time to time, which leads to
> wfx_remove_interface() of wvif->id 0 and consequent
> wfx_add_interface() of wvif->id 0. And only 0, which seems to be relevant,
> see below...
Thank you for the report. Let's dive into this.
> On Wed, 2023-10-04 at 19:28 +0200, Jérôme Pouiller wrote:
> > Until now, all the traffic was blocked during scan operation. However,
> > scan operation is going to be used to implement Remain On Channel (ROC).
> > In this case, special frames (marked with IEEE80211_TX_CTL_TX_OFFCHAN)
> > must be sent during the operation.
> >
> > These frames need to be sent on the virtual interface #2. Until now,
> > this interface was only used by the device for internal purpose. But
> > since API 3.9, it can be used to send data during scan operation (we
> > hijack the scan process to implement ROC).
> >
> > Thus, we need to change a bit the way we match the frames with the
> > interface.
> >
> > Fortunately, the frames received during the scan are marked with the
> > correct interface number. So there is no change to do on this part.
> >
> > Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
> > ---
> > drivers/net/wireless/silabs/wfx/data_tx.c | 36 ++++++++++++++++-----
> > drivers/net/wireless/silabs/wfx/data_tx.h | 2 ++
> > drivers/net/wireless/silabs/wfx/queue.c | 38 ++++++++++++++++++-----
> > drivers/net/wireless/silabs/wfx/queue.h | 1 +
> > 4 files changed, 62 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/net/wireless/silabs/wfx/data_tx.c b/drivers/net/wireless/silabs/wfx/data_tx.c
> > index ce2b5dcfd8d89..e8b6d41f55196 100644
> > --- a/drivers/net/wireless/silabs/wfx/data_tx.c
> > +++ b/drivers/net/wireless/silabs/wfx/data_tx.c
> > @@ -226,6 +226,18 @@ struct wfx_hif_req_tx *wfx_skb_txreq(struct sk_buff *skb)
> > return req;
> > }
> >
> > +struct wfx_vif *wfx_skb_wvif(struct wfx_dev *wdev, struct sk_buff *skb)
> > +{
> > + struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb);
> > + struct wfx_hif_msg *hif = (struct wfx_hif_msg *)skb->data;
> > +
> > + if (tx_priv->vif_id != hif->interface && hif->interface != 2) {
> > + dev_err(wdev->dev, "corrupted skb");
> > + return wdev_to_wvif(wdev, hif->interface);
> > + }
> > + return wdev_to_wvif(wdev, tx_priv->vif_id);
> > +}
> > +
> > static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta,
> > struct ieee80211_hdr *hdr)
> > {
> > @@ -352,6 +364,7 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct
> > /* Fill tx_priv */
> > tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data;
> > tx_priv->icv_size = wfx_tx_get_icv_len(hw_key);
> > + tx_priv->vif_id = wvif->id;
> >
> > /* Fill hif_msg */
> > WARN(skb_headroom(skb) < wmsg_len, "not enough space in skb");
> > @@ -362,7 +375,10 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct
> > hif_msg = (struct wfx_hif_msg *)skb->data;
> > hif_msg->len = cpu_to_le16(skb->len);
> > hif_msg->id = HIF_REQ_ID_TX;
> > - hif_msg->interface = wvif->id;
> > + if (tx_info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
> > + hif_msg->interface = 2;
>
> I never actually see wfx_add_interface() with id 2...
> Which leaves all the queues uninitialized....
This is expected. Interface 2 is not a real interface. You can consider
it as a special queue (for offchannel packets) on the device.
[...]
> > @@ -246,6 +250,26 @@ static struct sk_buff *wfx_tx_queues_get_skb(struct wfx_dev *wdev)
> > }
> > }
> >
> > + wvif = NULL;
> > + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Is there actually any point in iterating over wvifs here?
> It has been done right before and all the queues are now sorted in
> the common "queues"?
hmm... you're probably right.
>
> > + for (i = 0; i < num_queues; i++) {
> > + skb = skb_dequeue(&queues[i]->offchan);
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Nevertheless, the lockdep splat comes from here, because
> wfx_tx_queues_init() has never been called for wvif->id == 2.
>
> What was your original plan for this to happen?
> Do we need an explicit analogue of wfx_add_interface() for vif->id 2 somewhere?
>
> I still have not come with a reproducer yet, but you definitely have more
> insight into this code, maybe this will ring some bells on your side...
>
> PS. It's v6.11, even though it's exactly the same splan as in
> "staging: wfx: fix potential use before init", but the patch in indeed inside.
Yes, probably a very similar issue to "staging: wfx: fix potential use
before init". I don't believe the issue is related to wvif->id == 2.
You have only produced this issue once, that's it?
I wonder why this does not happen with queues[i]->normal and
queues[i]->cab. Is it because queues[i]->offchan is the first to be
checked? Or mutex_is_locked(&wdev->scan_lock) has an impact in the
process?
In wfx_add_interface(), the list of wvif is protected by conf_lock.
However, wfx_tx_queues_get_skb() is not protected by conf_lock. We
initialize struct wvif before to add it to the wvif list and we
consider it is sufficient. However, after reading memory-barriers.txt
again, it's probably a wrong assumption.
So, maybe this could fix the issue:
diff --git i/drivers/net/wireless/silabs/wfx/sta.c w/drivers/net/wireless/silabs/wfx/sta.c
index a904602f02ce..b22ea4243c0f 100644
--- i/drivers/net/wireless/silabs/wfx/sta.c
+++ w/drivers/net/wireless/silabs/wfx/sta.c
@@ -748,6 +748,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
if (!wdev->vif[i]) {
+ smp_mb();
wdev->vif[i] = vif;
wvif->id = i;
break;
However, I am not confident in playing with memory barriers.
--
Jérôme Pouiller
next prev parent reply other threads:[~2024-11-26 15:06 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-04 17:28 [PATCH v3 0/8] wfx: implement Remain On Channel Jérôme Pouiller
2023-10-04 17:28 ` [PATCH v3 1/8] wifi: wfx: fix power_save setting when AP is stopped Jérôme Pouiller
2023-10-09 6:53 ` Kalle Valo
2023-10-04 17:28 ` [PATCH v3 2/8] wifi: wfx: relocate wfx_rate_mask_to_hw() Jérôme Pouiller
2023-10-04 17:28 ` [PATCH v3 3/8] wifi: wfx: move wfx_skb_*() out of the header file Jérôme Pouiller
2023-10-04 17:28 ` [PATCH v3 4/8] wifi: wfx: introduce hif_scan_uniq() Jérôme Pouiller
2023-10-04 17:28 ` [PATCH v3 5/8] wifi: wfx: simplify exclusion between scan and Rx filters Jérôme Pouiller
2023-10-04 17:28 ` [PATCH v3 6/8] wifi: wfx: scan_lock is global to the device Jérôme Pouiller
2023-10-04 17:28 ` [PATCH v3 7/8] wifi: wfx: allow to send frames during ROC Jérôme Pouiller
2024-11-26 7:27 ` Sverdlin, Alexander
2024-11-26 14:45 ` Jérôme Pouiller [this message]
2024-11-26 15:41 ` Sverdlin, Alexander
2024-11-26 15:54 ` Sverdlin, Alexander
2024-11-27 9:18 ` Jérôme Pouiller
2023-10-04 17:28 ` [PATCH v3 8/8] wifi: wfx: implement wfx_remain_on_channel() Jérôme Pouiller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1769588.QkHrqEjB74@nb0018864 \
--to=jerome.pouiller@silabs.com \
--cc=alexander.sverdlin@siemens.com \
--cc=kvalo@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox