Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] wifi: mt76: mt7925: add wcid publish check in mt76_sta_add
@ 2026-05-26  6:08 Jiajia Liu
  2026-05-26 21:52 ` Sean Wang
  0 siblings, 1 reply; 3+ messages in thread
From: Jiajia Liu @ 2026-05-26  6:08 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Michael Lo, Leon Yen
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Jiajia Liu

Since mt7925_mac_sta_add publishes wcid, add publish check in mt76_sta_add
to avoid reinitializing the wcid->poll_list for mt7925.

Found dev->sta_poll_list corruption when using mt7925 and 7.0-rc4.
According to the corruption information, prev->next was changed to itself.

wlan0: disconnect from AP 90:fb:5d:94:8b:e3 for new auth to 90:fb:5d:94:8b:e2
wlan0: authenticate with 90:fb:5d:94:8b:e2 (local address=84:9e:56:9c:7e:6b)
wlan0: send auth to 90:fb:5d:94:8b:e2 (try 1/3)
 slab kmalloc-8k start ffff8c80958a6000 pointer offset 4160 size 8192
list_add corruption. prev->next should be next (ffff8c808a7488f8), but was ffff8c80958a7040. (prev=ffff8c80958a7040).

 mt76_wcid_add_poll+0x95/0xd0 [mt76]
 mt7925_mac_add_txs.part.0+0xa5/0xe0 [mt7925_common]
 mt7925_rx_check+0xa7/0xc0 [mt7925_common]
 mt76_dma_rx_poll+0x50d/0x790 [mt76]
 mt792x_poll_rx+0x52/0xe0 [mt792x_lib]

Signed-off-by: Jiajia Liu <liujiajia@kylinos.cn>
---

Reproduced and tested using the script below over ssh. Roam between two
bssids with the same SSID on a router.

#!/bin/bash

set -ex

while :; do
	num=$(sudo iw wlan0 scan | grep Polaris | wc -l)
	if [ $num -eq 2 ]; then
		break
	fi
done

for i in $(seq 1 500); do

echo "index $i"
wpa_cli -i wlan0 roam 90:fb:5d:94:8b:e3
sleep 5
wpa_cli -i wlan0 roam 90:fb:5d:94:8b:e2
sleep 5

done

---
 drivers/net/wireless/mediatek/mt76/mac80211.c    | 11 ++++++++---
 drivers/net/wireless/mediatek/mt76/mt76.h        |  1 +
 drivers/net/wireless/mediatek/mt76/mt7925/main.c |  3 +++
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 4ae5e4715a9c..83f4f941b890 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -1595,11 +1595,16 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
 		mtxq->wcid = wcid->idx;
 	}
 
-	ewma_signal_init(&wcid->rssi);
-	rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
+	if (!test_bit(MT_WCID_FLAG_DRV_PUBLISH, &wcid->flags)) {
+		ewma_signal_init(&wcid->rssi);
+		rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
+		mt76_wcid_init(wcid, phy->band_idx);
+	} else {
+		wcid->phy_idx = phy->band_idx;
+	}
+
 	phy->num_sta++;
 
-	mt76_wcid_init(wcid, phy->band_idx);
 out:
 	mutex_unlock(&dev->mutex);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 527bef97e122..8bfce686bff7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -361,6 +361,7 @@ enum mt76_wcid_flags {
 	MT_WCID_FLAG_PS,
 	MT_WCID_FLAG_4ADDR,
 	MT_WCID_FLAG_HDR_TRANS,
+	MT_WCID_FLAG_DRV_PUBLISH,
 };
 
 #define MT76_N_WCIDS 1088
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 73d3722739d0..35b5c718475c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1102,6 +1102,9 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 					      &msta->deflink);
 	}
 
+	if (!err)
+		set_bit(MT_WCID_FLAG_DRV_PUBLISH, &msta->deflink.wcid.flags);
+
 	return err;
 }
 EXPORT_SYMBOL_GPL(mt7925_mac_sta_add);
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] wifi: mt76: mt7925: add wcid publish check in mt76_sta_add
  2026-05-26  6:08 [PATCH] wifi: mt76: mt7925: add wcid publish check in mt76_sta_add Jiajia Liu
@ 2026-05-26 21:52 ` Sean Wang
  2026-05-27 10:00   ` Jiajia Liu
  0 siblings, 1 reply; 3+ messages in thread
From: Sean Wang @ 2026-05-26 21:52 UTC (permalink / raw)
  To: Jiajia Liu
  Cc: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Michael Lo, Leon Yen, linux-wireless,
	linux-kernel, linux-arm-kernel, linux-mediatek

Hi,

On Tue, May 26, 2026 at 1:09 AM Jiajia Liu <liujiajia@kylinos.cn> wrote:
>
> Since mt7925_mac_sta_add publishes wcid, add publish check in mt76_sta_add
> to avoid reinitializing the wcid->poll_list for mt7925.
>
> Found dev->sta_poll_list corruption when using mt7925 and 7.0-rc4.
> According to the corruption information, prev->next was changed to itself.
>
> wlan0: disconnect from AP 90:fb:5d:94:8b:e3 for new auth to 90:fb:5d:94:8b:e2
> wlan0: authenticate with 90:fb:5d:94:8b:e2 (local address=84:9e:56:9c:7e:6b)
> wlan0: send auth to 90:fb:5d:94:8b:e2 (try 1/3)
>  slab kmalloc-8k start ffff8c80958a6000 pointer offset 4160 size 8192
> list_add corruption. prev->next should be next (ffff8c808a7488f8), but was ffff8c80958a7040. (prev=ffff8c80958a7040).
>
>  mt76_wcid_add_poll+0x95/0xd0 [mt76]
>  mt7925_mac_add_txs.part.0+0xa5/0xe0 [mt7925_common]
>  mt7925_rx_check+0xa7/0xc0 [mt7925_common]
>  mt76_dma_rx_poll+0x50d/0x790 [mt76]
>  mt792x_poll_rx+0x52/0xe0 [mt792x_lib]
>
> Signed-off-by: Jiajia Liu <liujiajia@kylinos.cn>
> ---
>
> Reproduced and tested using the script below over ssh. Roam between two
> bssids with the same SSID on a router.
>
> #!/bin/bash
>
> set -ex
>
> while :; do
>         num=$(sudo iw wlan0 scan | grep Polaris | wc -l)
>         if [ $num -eq 2 ]; then
>                 break
>         fi
> done
>
> for i in $(seq 1 500); do
>
> echo "index $i"
> wpa_cli -i wlan0 roam 90:fb:5d:94:8b:e3
> sleep 5
> wpa_cli -i wlan0 roam 90:fb:5d:94:8b:e2
> sleep 5
>
> done
>
> ---
>  drivers/net/wireless/mediatek/mt76/mac80211.c    | 11 ++++++++---
>  drivers/net/wireless/mediatek/mt76/mt76.h        |  1 +
>  drivers/net/wireless/mediatek/mt76/mt7925/main.c |  3 +++
>  3 files changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
> index 4ae5e4715a9c..83f4f941b890 100644
> --- a/drivers/net/wireless/mediatek/mt76/mac80211.c
> +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
> @@ -1595,11 +1595,16 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
>                 mtxq->wcid = wcid->idx;
>         }
>
> -       ewma_signal_init(&wcid->rssi);
> -       rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
> +       if (!test_bit(MT_WCID_FLAG_DRV_PUBLISH, &wcid->flags)) {
> +               ewma_signal_init(&wcid->rssi);
> +               rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
> +               mt76_wcid_init(wcid, phy->band_idx);
> +       } else {
> +               wcid->phy_idx = phy->band_idx;
> +       }
> +
>         phy->num_sta++;
>

Thanks for spotting the roaming issue.

I think we can avoid adding MT_WCID_FLAG_DRV_PUBLISH and instead use the
WCID table itself for the publish check.

dev->wcid[] already encodes whether a WCID has been published, so checking
it directly avoids adding a second mirror state. MT_WCID_FLAG_* is also
better kept for WCID features that affect WTBL setup or data-path handling,
rather than common bookkeeping state.

Something like:

@@ -1620,6 +1620,7 @@ mt76_sta_add(struct mt76_phy *phy, struct
ieee80211_vif *vif,
{
  struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
  struct mt76_dev *dev = phy->dev;
+       struct mt76_wcid *published;
  int ret;
  int i;

@@ -1639,7 +1640,10 @@ mt76_sta_add(struct mt76_phy *phy, struct
ieee80211_vif *vif,
          mtxq->wcid = wcid->idx;
  }

-       if (!test_bit(MT_WCID_FLAG_DRV_PUBLISH, &wcid->flags)) {
+       published = rcu_dereference_protected(dev->wcid[wcid->idx],
+                                             lockdep_is_held(&dev->mutex));
+       if (published != wcid) {
+               WARN_ON_ONCE(published);
                 ewma_signal_init(&wcid->rssi);
                 rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
                 mt76_wcid_init(wcid, phy->band_idx);

   ....


> -       mt76_wcid_init(wcid, phy->band_idx);
>  out:
>         mutex_unlock(&dev->mutex);
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 527bef97e122..8bfce686bff7 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -361,6 +361,7 @@ enum mt76_wcid_flags {
>         MT_WCID_FLAG_PS,
>         MT_WCID_FLAG_4ADDR,
>         MT_WCID_FLAG_HDR_TRANS,
> +       MT_WCID_FLAG_DRV_PUBLISH,
>  };
>
>  #define MT76_N_WCIDS 1088
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> index 73d3722739d0..35b5c718475c 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> @@ -1102,6 +1102,9 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
>                                               &msta->deflink);
>         }
>
> +       if (!err)
> +               set_bit(MT_WCID_FLAG_DRV_PUBLISH, &msta->deflink.wcid.flags);
> +
>         return err;
>  }
>  EXPORT_SYMBOL_GPL(mt7925_mac_sta_add);
> --
> 2.53.0
>
>


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] wifi: mt76: mt7925: add wcid publish check in mt76_sta_add
  2026-05-26 21:52 ` Sean Wang
@ 2026-05-27 10:00   ` Jiajia Liu
  0 siblings, 0 replies; 3+ messages in thread
From: Jiajia Liu @ 2026-05-27 10:00 UTC (permalink / raw)
  To: Sean Wang
  Cc: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Michael Lo, Leon Yen, linux-wireless,
	linux-kernel, linux-arm-kernel, linux-mediatek

On Tue, May 26, 2026 at 04:52:32PM -0500, Sean Wang wrote:
> Hi,
> 
> On Tue, May 26, 2026 at 1:09 AM Jiajia Liu <liujiajia@kylinos.cn> wrote:
> >
> > Since mt7925_mac_sta_add publishes wcid, add publish check in mt76_sta_add
> > to avoid reinitializing the wcid->poll_list for mt7925.
> >
> > Found dev->sta_poll_list corruption when using mt7925 and 7.0-rc4.
> > According to the corruption information, prev->next was changed to itself.
> >
> > wlan0: disconnect from AP 90:fb:5d:94:8b:e3 for new auth to 90:fb:5d:94:8b:e2
> > wlan0: authenticate with 90:fb:5d:94:8b:e2 (local address=84:9e:56:9c:7e:6b)
> > wlan0: send auth to 90:fb:5d:94:8b:e2 (try 1/3)
> >  slab kmalloc-8k start ffff8c80958a6000 pointer offset 4160 size 8192
> > list_add corruption. prev->next should be next (ffff8c808a7488f8), but was ffff8c80958a7040. (prev=ffff8c80958a7040).
> >
> >  mt76_wcid_add_poll+0x95/0xd0 [mt76]
> >  mt7925_mac_add_txs.part.0+0xa5/0xe0 [mt7925_common]
> >  mt7925_rx_check+0xa7/0xc0 [mt7925_common]
> >  mt76_dma_rx_poll+0x50d/0x790 [mt76]
> >  mt792x_poll_rx+0x52/0xe0 [mt792x_lib]
> >
> > Signed-off-by: Jiajia Liu <liujiajia@kylinos.cn>
> > ---
> >
> > Reproduced and tested using the script below over ssh. Roam between two
> > bssids with the same SSID on a router.
> >
> > #!/bin/bash
> >
> > set -ex
> >
> > while :; do
> >         num=$(sudo iw wlan0 scan | grep Polaris | wc -l)
> >         if [ $num -eq 2 ]; then
> >                 break
> >         fi
> > done
> >
> > for i in $(seq 1 500); do
> >
> > echo "index $i"
> > wpa_cli -i wlan0 roam 90:fb:5d:94:8b:e3
> > sleep 5
> > wpa_cli -i wlan0 roam 90:fb:5d:94:8b:e2
> > sleep 5
> >
> > done
> >
> > ---
> >  drivers/net/wireless/mediatek/mt76/mac80211.c    | 11 ++++++++---
> >  drivers/net/wireless/mediatek/mt76/mt76.h        |  1 +
> >  drivers/net/wireless/mediatek/mt76/mt7925/main.c |  3 +++
> >  3 files changed, 12 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
> > index 4ae5e4715a9c..83f4f941b890 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mac80211.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
> > @@ -1595,11 +1595,16 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
> >                 mtxq->wcid = wcid->idx;
> >         }
> >
> > -       ewma_signal_init(&wcid->rssi);
> > -       rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
> > +       if (!test_bit(MT_WCID_FLAG_DRV_PUBLISH, &wcid->flags)) {
> > +               ewma_signal_init(&wcid->rssi);
> > +               rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
> > +               mt76_wcid_init(wcid, phy->band_idx);
> > +       } else {
> > +               wcid->phy_idx = phy->band_idx;
> > +       }
> > +
> >         phy->num_sta++;
> >
> 
> Thanks for spotting the roaming issue.
> 
> I think we can avoid adding MT_WCID_FLAG_DRV_PUBLISH and instead use the
> WCID table itself for the publish check.
> 
> dev->wcid[] already encodes whether a WCID has been published, so checking
> it directly avoids adding a second mirror state. MT_WCID_FLAG_* is also
> better kept for WCID features that affect WTBL setup or data-path handling,
> rather than common bookkeeping state.
> 
> Something like:
> 
> @@ -1620,6 +1620,7 @@ mt76_sta_add(struct mt76_phy *phy, struct
> ieee80211_vif *vif,
> {
>   struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
>   struct mt76_dev *dev = phy->dev;
> +       struct mt76_wcid *published;
>   int ret;
>   int i;
> 
> @@ -1639,7 +1640,10 @@ mt76_sta_add(struct mt76_phy *phy, struct
> ieee80211_vif *vif,
>           mtxq->wcid = wcid->idx;
>   }
> 
> -       if (!test_bit(MT_WCID_FLAG_DRV_PUBLISH, &wcid->flags)) {
> +       published = rcu_dereference_protected(dev->wcid[wcid->idx],
> +                                             lockdep_is_held(&dev->mutex));
> +       if (published != wcid) {
> +               WARN_ON_ONCE(published);
>                  ewma_signal_init(&wcid->rssi);
>                  rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
>                  mt76_wcid_init(wcid, phy->band_idx);
> 
>    ....
> 

Thanks for the suggestion. Will update in v2.

> 
> > -       mt76_wcid_init(wcid, phy->band_idx);
> >  out:
> >         mutex_unlock(&dev->mutex);
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> > index 527bef97e122..8bfce686bff7 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> > @@ -361,6 +361,7 @@ enum mt76_wcid_flags {
> >         MT_WCID_FLAG_PS,
> >         MT_WCID_FLAG_4ADDR,
> >         MT_WCID_FLAG_HDR_TRANS,
> > +       MT_WCID_FLAG_DRV_PUBLISH,
> >  };
> >
> >  #define MT76_N_WCIDS 1088
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> > index 73d3722739d0..35b5c718475c 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> > @@ -1102,6 +1102,9 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
> >                                               &msta->deflink);
> >         }
> >
> > +       if (!err)
> > +               set_bit(MT_WCID_FLAG_DRV_PUBLISH, &msta->deflink.wcid.flags);
> > +
> >         return err;
> >  }
> >  EXPORT_SYMBOL_GPL(mt7925_mac_sta_add);
> > --
> > 2.53.0
> >
> >


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-05-27 10:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-26  6:08 [PATCH] wifi: mt76: mt7925: add wcid publish check in mt76_sta_add Jiajia Liu
2026-05-26 21:52 ` Sean Wang
2026-05-27 10:00   ` Jiajia Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox