--- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1601,6 +1601,7 @@ enum ieee80211_vif_flags { * @addr: address of this interface * @p2p: indicates whether this AP or STA interface is a p2p * interface, i.e. a GO or p2p-sta respectively + * @use_4addr: indicates whether this STA interface uses 4-address frames * @csa_active: marks whether a channel switch is going on. Internally it is * write-protected by sdata_lock and local->mtx so holding either is fine * for read access. @@ -1632,6 +1633,7 @@ struct ieee80211_vif { struct ieee80211_bss_conf bss_conf; u8 addr[ETH_ALEN] __aligned(2); bool p2p; + bool use_4addr; bool csa_active; bool mu_mimo_owner; @@ -3879,6 +3881,9 @@ struct ieee80211_ops { struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state); + void (*sta_use_4addr)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -163,6 +163,7 @@ static int ieee80211_change_iface(struct ieee80211_check_fast_rx_iface(sdata); } else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) { sdata->u.mgd.use_4addr = params->use_4addr; + sdata->vif.use_4addr = params->use_4addr; } if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { @@ -1689,6 +1690,8 @@ static int ieee80211_change_station(stru rcu_assign_pointer(vlansdata->u.vlan.sta, sta); __ieee80211_check_fast_rx_iface(vlansdata); + + drv_sta_use_4addr(local, sdata, sta); } if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -135,6 +135,21 @@ int drv_sta_state(struct ieee80211_local return ret; } +void drv_sta_use_4addr(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta) +{ + sdata = get_bss_sdata(sdata); + if (!check_sdata_in_driver(sdata)) + return; + + trace_drv_sta_use_4addr(local, sdata, &sta->sta); + if (local->ops->sta_use_4addr) + local->ops->sta_use_4addr(&local->hw, &sdata->vif, + &sta->sta); + trace_drv_return_void(local); +} + __must_check int drv_sta_set_txpwr(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -529,6 +529,10 @@ int drv_sta_state(struct ieee80211_local enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state); +void drv_sta_use_4addr(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta); + __must_check int drv_sta_set_txpwr(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1716,8 +1716,10 @@ int ieee80211_if_change_type(struct ieee } /* reset some values that shouldn't be kept across type changes */ - if (type == NL80211_IFTYPE_STATION) + if (type == NL80211_IFTYPE_STATION) { sdata->u.mgd.use_4addr = false; + sdata->vif.use_4addr = false; + } return 0; } @@ -2007,8 +2009,10 @@ int ieee80211_if_add(struct ieee80211_lo if (ndev) { ndev->ieee80211_ptr->use_4addr = params->use_4addr; - if (type == NL80211_IFTYPE_STATION) + if (type == NL80211_IFTYPE_STATION) { sdata->u.mgd.use_4addr = params->use_4addr; + sdata->vif.use_4addr = params->use_4addr; + } ndev->features |= local->hw.netdev_features; ndev->hw_features |= ndev->features & --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1077,10 +1077,6 @@ static void ieee80211_send_4addr_nullfun if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) return; - /* Don't send NDPs when connected HE */ - if (!(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE)) - return; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); if (!skb) return; --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1851,6 +1851,7 @@ ieee80211_rx_h_sta_process(struct ieee80 (rx->sdata->vif.type == NL80211_IFTYPE_AP || (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !rx->sdata->u.vlan.sta))) { + drv_sta_use_4addr(sta->local, rx->sdata, sta); if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT)) cfg80211_rx_unexpected_4addr_frame( rx->sdata->dev, sta->sta.addr, @@ -2891,9 +2892,11 @@ ieee80211_rx_h_data(struct ieee80211_rx_ if (ieee80211_has_a4(hdr->frame_control) && sdata->vif.type == NL80211_IFTYPE_AP) { if (rx->sta && - !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) + !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) { + drv_sta_use_4addr(local, sdata, rx->sta); cfg80211_rx_unexpected_4addr_frame( rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); + } return RX_DROP_MONITOR; } --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -828,6 +828,31 @@ TRACE_EVENT(drv_sta_state, ) ); +TRACE_EVENT(drv_sta_use_4addr, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta), + + TP_ARGS(local, sdata, sta), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " use_4addr", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG + ) +); + TRACE_EVENT(drv_sta_set_txpwr, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata,