Skip to content

Commit 1b4531f

Browse files
committed
wifi: mt76: mt7925: re-arm monitor sniffer on chip_reset recovery
mt7925_mac_reset_work()'s recovery path reconnects STATION and AP vifs via mt7925_vif_connect_iter(), but that function has no handling at all for NL80211_IFTYPE_MONITOR: it never calls mt7925_mcu_set_sniffer()/mt7925_mcu_config_sniffer() for a monitor vif. mac80211's own logical state (interface up, channel) survives the reset, but the firmware's sniffer state does not, and nothing in this recovery path puts it back -- a monitor vif goes silently deaf after a chip reset regardless of which band it was on. This is a distinct bug from the one PR #66 fixes: mac80211's ieee80211_reconfig() is not involved here at all. mt7925_mac_reset_work() never calls ieee80211_restart_hw(), so reconfig() is never reached; this is the driver's own firmware-recovery path silently dropping monitor state on its way back up, independent of anything mac80211 does. The first version of this patch reused mt7925_sniffer_interface_iter() directly, applying it to every active interface via a hw-level monitor flag rather than per-vif type. That is the same pattern mt7925_config()/mt7925_configure_filter() already use, but reusing it unscoped in the reset-recovery path means it would call mt7925_mcu_set_sniffer(dev, vif, true) against STATION/AP vifs too whenever a monitor vif happens to coexist, and none of the underlying MCU calls had their return values checked. Fixed properly instead: add a struct mt7925_sniffer_iter_data (dev, error, monitor_only) so the iterator can restrict itself to actual monitor vifs, check and propagate every MCU call's return value, and expose a dedicated mt7925_sniffer_rearm() entry point (monitor_only set) for the reset path to call under dev->mt76.mutex, with the failure logged and queues woken only after the re-arm attempt completes. mt7925_config()/mt7925_configure_filter() now use the same struct (monitor_only left unset, preserving their existing behavior) and also check/log the iterator's error instead of ignoring it. Signed-off-by: Ashcal9669 <ashcalili@gmail.com>
1 parent e071d81 commit 1b4531f

3 files changed

Lines changed: 81 additions & 10 deletions

File tree

mt7925/mac.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1568,10 +1568,24 @@ void mt7925_mac_reset_work(struct work_struct *work)
15681568
if (test_bit(MT76_REMOVED, &dev->mphy.state))
15691569
return;
15701570

1571-
ieee80211_wake_queues(hw);
15721571
ieee80211_iterate_active_interfaces(hw,
15731572
IEEE80211_IFACE_ITER_RESUME_ALL,
15741573
mt7925_vif_connect_iter, NULL);
1574+
/* mt7925_vif_connect_iter() only reconnects STATION/AP vifs; a
1575+
* monitor vif's firmware sniffer state is lost across the reset
1576+
* and is never re-armed by anything else in this recovery path.
1577+
* Re-arm it before waking queues so RX isn't processed against a
1578+
* vif whose sniffer state hasn't been confirmed yet.
1579+
*/
1580+
if (hw->conf.flags & IEEE80211_CONF_MONITOR) {
1581+
mutex_lock(&dev->mt76.mutex);
1582+
ret = mt7925_sniffer_rearm(dev);
1583+
mutex_unlock(&dev->mt76.mutex);
1584+
if (ret)
1585+
dev_err(dev->mt76.dev,
1586+
"monitor sniffer re-arm failed: %d\n", ret);
1587+
}
1588+
ieee80211_wake_queues(hw);
15751589
mt76_connac_power_save_sched(&dev->mt76.phy, pm);
15761590

15771591
mt7925_regd_change(&dev->phy, "00");

mt7925/main.c

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -793,32 +793,78 @@ mt7925_monitor_update_chan(struct mt792x_vif *mvif,
793793
mconf->mt76.basic_rates_idx += 4;
794794
}
795795

796+
struct mt7925_sniffer_iter_data {
797+
struct mt792x_dev *dev;
798+
int error;
799+
bool monitor_only;
800+
};
801+
796802
static void
797803
mt7925_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
798804
{
799-
struct mt792x_dev *dev = priv;
805+
struct mt7925_sniffer_iter_data *data = priv;
806+
struct mt792x_dev *dev = data->dev;
800807
struct ieee80211_hw *hw = mt76_hw(dev);
801808
struct mt76_connac_pm *pm = &dev->pm;
802809
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
803810
struct ieee80211_chanctx_conf *ctx = mvif->bss_conf.mt76.ctx;
804811
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
812+
int ret;
813+
814+
if (data->error)
815+
return;
816+
817+
if ((data->monitor_only || monitor) &&
818+
vif->type != NL80211_IFTYPE_MONITOR)
819+
return;
805820

806821
if (monitor && !ctx)
807822
return;
808823

809824
if (monitor)
810825
mt7925_monitor_update_chan(mvif, ctx);
811826

812-
mt7925_mcu_set_sniffer(dev, vif, monitor);
813-
if (monitor && is_mt7927(&dev->mt76))
814-
mt7925_mcu_config_sniffer(mvif, ctx);
827+
ret = mt7925_mcu_set_sniffer(dev, vif, monitor);
828+
if (ret)
829+
goto error;
830+
831+
if (monitor && is_mt7927(&dev->mt76)) {
832+
ret = mt7925_mcu_config_sniffer(mvif, ctx);
833+
if (ret)
834+
goto error;
835+
}
836+
815837
pm->enable = pm->enable_user && !monitor;
816838
pm->ds_enable = pm->ds_enable_user && !monitor;
817839

818-
mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
840+
ret = mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
841+
if (ret)
842+
goto error;
819843

820-
if (monitor)
821-
mt7925_mcu_set_beacon_filter(dev, vif, false);
844+
if (monitor) {
845+
ret = mt7925_mcu_set_beacon_filter(dev, vif, false);
846+
if (ret)
847+
goto error;
848+
}
849+
850+
return;
851+
852+
error:
853+
data->error = ret;
854+
}
855+
856+
int mt7925_sniffer_rearm(struct mt792x_dev *dev)
857+
{
858+
struct mt7925_sniffer_iter_data data = {
859+
.dev = dev,
860+
.monitor_only = true,
861+
};
862+
863+
ieee80211_iterate_active_interfaces(mt76_hw(dev),
864+
IEEE80211_IFACE_ITER_RESUME_ALL,
865+
mt7925_sniffer_interface_iter, &data);
866+
867+
return data.error;
822868
}
823869

824870
void mt7925_set_runtime_pm(struct mt792x_dev *dev)
@@ -843,6 +889,9 @@ static int mt7925_config(struct ieee80211_hw *hw, u32 changed)
843889
#endif
844890
{
845891
struct mt792x_dev *dev = mt792x_hw_dev(hw);
892+
struct mt7925_sniffer_iter_data data = {
893+
.dev = dev,
894+
};
846895
int ret = 0;
847896

848897
mt792x_mutex_acquire(dev);
@@ -856,7 +905,8 @@ static int mt7925_config(struct ieee80211_hw *hw, u32 changed)
856905
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
857906
ieee80211_iterate_active_interfaces(hw,
858907
IEEE80211_IFACE_ITER_RESUME_ALL,
859-
mt7925_sniffer_interface_iter, dev);
908+
mt7925_sniffer_interface_iter, &data);
909+
ret = data.error;
860910
}
861911

862912
out:
@@ -875,6 +925,9 @@ static void mt7925_configure_filter(struct ieee80211_hw *hw,
875925
#define MT7925_FILTER_OTHER_BSS BIT(6)
876926
#define MT7925_FILTER_ENABLE BIT(31)
877927
struct mt792x_dev *dev = mt792x_hw_dev(hw);
928+
struct mt7925_sniffer_iter_data data = {
929+
.dev = dev,
930+
};
878931
u32 flags = MT7925_FILTER_ENABLE;
879932

880933
#define MT7925_FILTER(_fif, _type) do { \
@@ -892,7 +945,10 @@ static void mt7925_configure_filter(struct ieee80211_hw *hw,
892945
(hw->conf.flags & IEEE80211_CONF_MONITOR))
893946
ieee80211_iterate_active_interfaces(hw,
894947
IEEE80211_IFACE_ITER_RESUME_ALL,
895-
mt7925_sniffer_interface_iter, dev);
948+
mt7925_sniffer_interface_iter, &data);
949+
if (data.error)
950+
dev_err(dev->mt76.dev, "sniffer configuration failed: %d\n",
951+
data.error);
896952
mt792x_mutex_release(dev);
897953

898954
*total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL);

mt7925/mt7925.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ int mt7925e_mcu_init(struct mt792x_dev *dev);
356356
void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data);
357357
void mt7928_mac_add_txs_msg(struct mt792x_dev *dev, void *evt);
358358
void mt7925_set_runtime_pm(struct mt792x_dev *dev);
359+
int mt7925_sniffer_rearm(struct mt792x_dev *dev);
359360
void mt7925_mcu_set_suspend_iter(void *priv, u8 *mac,
360361
struct ieee80211_vif *vif);
361362
void mt7925_connac_mcu_set_suspend_iter(void *priv, u8 *mac,

0 commit comments

Comments
 (0)