cfg80211: send stop AP event only due to internal reason
authorIlan Peer <ilan.peer@intel.com>
Tue, 25 Feb 2014 13:33:38 +0000 (15:33 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 25 Feb 2014 16:34:18 +0000 (17:34 +0100)
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>
net/wireless/ap.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/util.c

index 68602be07cc10ae1ff0b4356e6e2a95492e34717..3e02ade508d8804d4158a03ad5de474d64bf7594 100644 (file)
@@ -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,20 +30,21 @@ 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);
-               nl80211_send_ap_stopped(wdev);
+               if (notify)
+                       nl80211_send_ap_stopped(wdev);
        }
 
        return err;
 }
 
 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;
index 76ae6a605abb3366ab757bda121606d1b4747f10..276cf938f7646f44201c698ece575258c3606776 100644 (file)
@@ -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;
index 64fde38c1a7e2019809018efdac31b3dc2ad7f66..3975ffa8feb2536b57984e173f8223714afeeb31 100644 (file)
@@ -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,
index 8fa02a3fa7f78a53a1331e2d1dde3fa64ed86337..052c1bf8ffaceb92d3f117231a46fca78ed30216 100644 (file)
@@ -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] = {
index 57b3ce7a6b9255df15b5064ac5fd177414a662cc..dadc934d987f90ba8022d85ea847e8dca9b502f8 100644 (file)
@@ -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);