cfg80211: send stop AP event only due to internal reason
Commit "nl80211: send event when AP operation is stopped" added an event to notify user space that an AP interface has been stopped, to handle cases such as suspend etc. The event is sent regardless if the stop AP flow was triggered by user space or due to internal state change. This might cause issues with wpa_supplicant/hostapd flows that consider stop AP flow as a synchronous one, e.g., AP/GO channel change in the absence of CSA support. In such cases, the flow will restart the AP immediately after the stop AP flow is done, and only handle the stop AP event after the current flow is done, and as a result stop the AP again. Change the current implementation to only send the event in case the stop AP was triggered due to an internal reason. Signed-off-by: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
31559f35c5
commit
7c8d5e03ac
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev)
|
||||
struct net_device *dev, bool notify)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
@ -30,6 +30,7 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
|||
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
|
||||
wdev->ssid_len = 0;
|
||||
rdev_set_qos_map(rdev, dev, NULL);
|
||||
if (notify)
|
||||
nl80211_send_ap_stopped(wdev);
|
||||
}
|
||||
|
||||
|
@ -37,13 +38,13 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
|
||||
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev)
|
||||
struct net_device *dev, bool notify)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
||||
wdev_lock(wdev);
|
||||
err = __cfg80211_stop_ap(rdev, dev);
|
||||
err = __cfg80211_stop_ap(rdev, dev, notify);
|
||||
wdev_unlock(wdev);
|
||||
|
||||
return err;
|
||||
|
|
|
@ -783,7 +783,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
cfg80211_stop_ap(rdev, dev);
|
||||
cfg80211_stop_ap(rdev, dev, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -283,7 +283,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
|||
|
||||
/* AP */
|
||||
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev);
|
||||
struct net_device *dev, bool notify);
|
||||
|
||||
/* MLME */
|
||||
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
|
|
|
@ -3332,7 +3332,7 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
|
||||
return cfg80211_stop_ap(rdev, dev);
|
||||
return cfg80211_stop_ap(rdev, dev, false);
|
||||
}
|
||||
|
||||
static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
|
||||
|
|
|
@ -886,7 +886,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
|||
|
||||
switch (otype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
cfg80211_stop_ap(rdev, dev);
|
||||
cfg80211_stop_ap(rdev, dev, true);
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cfg80211_leave_ibss(rdev, dev, false);
|
||||
|
|
Loading…
Reference in New Issue