|
@@ -1767,6 +1767,31 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
|
|
|
}
|
|
|
EXPORT_SYMBOL(ieee80211_sta_set_buffered);
|
|
|
|
|
|
+static void
|
|
|
+ieee80211_recalc_p2p_go_ps_allowed(struct ieee80211_sub_if_data *sdata)
|
|
|
+{
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
+ bool allow_p2p_go_ps = sdata->vif.p2p;
|
|
|
+ struct sta_info *sta;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
|
|
|
+ if (sdata != sta->sdata ||
|
|
|
+ !test_sta_flag(sta, WLAN_STA_ASSOC))
|
|
|
+ continue;
|
|
|
+ if (!sta->sta.support_p2p_ps) {
|
|
|
+ allow_p2p_go_ps = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rcu_read_unlock();
|
|
|
+
|
|
|
+ if (allow_p2p_go_ps != sdata->vif.bss_conf.allow_p2p_go_ps) {
|
|
|
+ sdata->vif.bss_conf.allow_p2p_go_ps = allow_p2p_go_ps;
|
|
|
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_P2P_PS);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
int sta_info_move_state(struct sta_info *sta,
|
|
|
enum ieee80211_sta_state new_state)
|
|
|
{
|
|
@@ -1828,12 +1853,16 @@ int sta_info_move_state(struct sta_info *sta,
|
|
|
} else if (sta->sta_state == IEEE80211_STA_ASSOC) {
|
|
|
clear_bit(WLAN_STA_ASSOC, &sta->_flags);
|
|
|
ieee80211_recalc_min_chandef(sta->sdata);
|
|
|
+ if (!sta->sta.support_p2p_ps)
|
|
|
+ ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
|
|
|
}
|
|
|
break;
|
|
|
case IEEE80211_STA_ASSOC:
|
|
|
if (sta->sta_state == IEEE80211_STA_AUTH) {
|
|
|
set_bit(WLAN_STA_ASSOC, &sta->_flags);
|
|
|
ieee80211_recalc_min_chandef(sta->sdata);
|
|
|
+ if (!sta->sta.support_p2p_ps)
|
|
|
+ ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
|
|
|
} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
|
|
|
if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
|
(sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
|