Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac802...
authorJohn W. Linville <linville@tuxdriver.com>
Thu, 20 Mar 2014 15:53:20 +0000 (11:53 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 20 Mar 2014 15:53:20 +0000 (11:53 -0400)
27 files changed:
include/linux/ieee80211.h
include/net/cfg80211.h
include/net/mac80211.h
include/net/regulatory.h
include/uapi/linux/nl80211.h
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/pm.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/tx.c
net/wireless/ap.c
net/wireless/chan.c
net/wireless/core.c
net/wireless/core.h
net/wireless/genregdb.awk
net/wireless/ibss.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/reg.h
net/wireless/scan.c
net/wireless/sme.c
net/wireless/util.c
net/wireless/wext-sme.c

index 06299048c4f41dc66ac549b76c4618efccfa73c7..f194ccb8539c9b7d95af35b00a426ce2a06b61a6 100644 (file)
@@ -154,6 +154,10 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
    802.11e clarifies the figure in section 7.1.2. The frame body is
    up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */
 #define IEEE80211_MAX_DATA_LEN         2304
+/* 802.11ad extends maximum MSDU size for DMG (freq > 40Ghz) networks
+ * to 7920 bytes, see 8.2.3 General frame format
+ */
+#define IEEE80211_MAX_DATA_LEN_DMG     7920
 /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
 #define IEEE80211_MAX_FRAME_LEN                2352
 
index 8c9ba44fb7cf37a3505226094dd022e1859086a5..f3539a15c41103b743c0571913fbb93dc402f40a 100644 (file)
@@ -151,6 +151,7 @@ enum ieee80211_channel_flags {
  * @dfs_state: current state of this channel. Only relevant if radar is required
  *     on this channel.
  * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
+ * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
  */
 struct ieee80211_channel {
        enum ieee80211_band band;
@@ -165,6 +166,7 @@ struct ieee80211_channel {
        int orig_mag, orig_mpwr;
        enum nl80211_dfs_state dfs_state;
        unsigned long dfs_state_entered;
+       unsigned int dfs_cac_ms;
 };
 
 /**
@@ -2503,7 +2505,8 @@ struct cfg80211_ops {
 
        int     (*start_radar_detection)(struct wiphy *wiphy,
                                         struct net_device *dev,
-                                        struct cfg80211_chan_def *chandef);
+                                        struct cfg80211_chan_def *chandef,
+                                        u32 cac_time_ms);
        int     (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
                                 struct cfg80211_update_ft_ies_params *ftie);
        int     (*crit_proto_start)(struct wiphy *wiphy,
@@ -3180,6 +3183,7 @@ struct cfg80211_cached_keys;
  * @p2p_started: true if this is a P2P Device that has been started
  * @cac_started: true if DFS channel availability check has been started
  * @cac_start_time: timestamp (jiffies) when the dfs state was entered.
+ * @cac_time_ms: CAC time in ms
  * @ps: powersave mode is enabled
  * @ps_timeout: dynamic powersave timeout
  * @ap_unexpected_nlportid: (private) netlink port ID of application
@@ -3235,6 +3239,7 @@ struct wireless_dev {
 
        bool cac_started;
        unsigned long cac_start_time;
+       unsigned int cac_time_ms;
 
 #ifdef CONFIG_CFG80211_WEXT
        /* wext data */
@@ -3667,7 +3672,7 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
  * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame
  *
  * @wiphy: the wiphy reporting the BSS
- * @channel: The channel the frame was received on
+ * @rx_channel: The channel the frame was received on
  * @scan_width: width of the control channel
  * @mgmt: the management frame (probe response or beacon)
  * @len: length of the management frame
@@ -3682,18 +3687,18 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
  */
 struct cfg80211_bss * __must_check
 cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
-                               struct ieee80211_channel *channel,
+                               struct ieee80211_channel *rx_channel,
                                enum nl80211_bss_scan_width scan_width,
                                struct ieee80211_mgmt *mgmt, size_t len,
                                s32 signal, gfp_t gfp);
 
 static inline struct cfg80211_bss * __must_check
 cfg80211_inform_bss_frame(struct wiphy *wiphy,
-                         struct ieee80211_channel *channel,
+                         struct ieee80211_channel *rx_channel,
                          struct ieee80211_mgmt *mgmt, size_t len,
                          s32 signal, gfp_t gfp)
 {
-       return cfg80211_inform_bss_width_frame(wiphy, channel,
+       return cfg80211_inform_bss_width_frame(wiphy, rx_channel,
                                               NL80211_BSS_CHAN_WIDTH_20,
                                               mgmt, len, signal, gfp);
 }
@@ -3702,7 +3707,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
  * cfg80211_inform_bss - inform cfg80211 of a new BSS
  *
  * @wiphy: the wiphy reporting the BSS
- * @channel: The channel the frame was received on
+ * @rx_channel: The channel the frame was received on
  * @scan_width: width of the control channel
  * @bssid: the BSSID of the BSS
  * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
@@ -3721,7 +3726,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
  */
 struct cfg80211_bss * __must_check
 cfg80211_inform_bss_width(struct wiphy *wiphy,
-                         struct ieee80211_channel *channel,
+                         struct ieee80211_channel *rx_channel,
                          enum nl80211_bss_scan_width scan_width,
                          const u8 *bssid, u64 tsf, u16 capability,
                          u16 beacon_interval, const u8 *ie, size_t ielen,
@@ -3729,12 +3734,12 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
 
 static inline struct cfg80211_bss * __must_check
 cfg80211_inform_bss(struct wiphy *wiphy,
-                   struct ieee80211_channel *channel,
+                   struct ieee80211_channel *rx_channel,
                    const u8 *bssid, u64 tsf, u16 capability,
                    u16 beacon_interval, const u8 *ie, size_t ielen,
                    s32 signal, gfp_t gfp)
 {
-       return cfg80211_inform_bss_width(wiphy, channel,
+       return cfg80211_inform_bss_width(wiphy, rx_channel,
                                         NL80211_BSS_CHAN_WIDTH_20,
                                         bssid, tsf, capability,
                                         beacon_interval, ie, ielen, signal,
index 86faa413b37d043979cd5983164a65060f4f2965..2de7ff42ff3aae4f0e7e8f5eb140d4269853228a 100644 (file)
@@ -697,11 +697,11 @@ struct ieee80211_tx_info {
                } control;
                struct {
                        struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
-                       int ack_signal;
+                       s32 ack_signal;
                        u8 ampdu_ack_len;
                        u8 ampdu_len;
                        u8 antenna;
-                       /* 21 bytes free */
+                       void *status_driver_data[21 / sizeof(void *)];
                } status;
                struct {
                        struct ieee80211_tx_rate driver_rates[
@@ -877,11 +877,13 @@ enum mac80211_rx_flags {
  * @RX_VHT_FLAG_80MHZ: 80 MHz was used
  * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used
  * @RX_VHT_FLAG_160MHZ: 160 MHz was used
+ * @RX_VHT_FLAG_BF: packet was beamformed
  */
 enum mac80211_rx_vht_flags {
        RX_VHT_FLAG_80MHZ               = BIT(0),
        RX_VHT_FLAG_80P80MHZ            = BIT(1),
        RX_VHT_FLAG_160MHZ              = BIT(2),
+       RX_VHT_FLAG_BF                  = BIT(3),
 };
 
 /**
index b07cdc9fa454a57fe43d1eea0235522c26d0c1a6..75fc1f5a948d685fcfff12e04cc6b85e194cd541 100644 (file)
@@ -155,6 +155,7 @@ struct ieee80211_reg_rule {
        struct ieee80211_freq_range freq_range;
        struct ieee80211_power_rule power_rule;
        u32 flags;
+       u32 dfs_cac_ms;
 };
 
 struct ieee80211_regdomain {
@@ -172,14 +173,18 @@ struct ieee80211_regdomain {
 #define DBM_TO_MBM(gain) ((gain) * 100)
 #define MBM_TO_DBM(gain) ((gain) / 100)
 
-#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
-{                                                      \
-       .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
-       .freq_range.end_freq_khz = MHZ_TO_KHZ(end),     \
-       .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \
-       .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\
-       .power_rule.max_eirp = DBM_TO_MBM(eirp),        \
-       .flags = reg_flags,                             \
+#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags)   \
+{                                                                      \
+       .freq_range.start_freq_khz = MHZ_TO_KHZ(start),                 \
+       .freq_range.end_freq_khz = MHZ_TO_KHZ(end),                     \
+       .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw),                 \
+       .power_rule.max_antenna_gain = DBI_TO_MBI(gain),                \
+       .power_rule.max_eirp = DBM_TO_MBM(eirp),                        \
+       .flags = reg_flags,                                             \
+       .dfs_cac_ms = dfs_cac,                                          \
 }
 
+#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
+       REG_RULE_EXT(start, end, bw, gain, eirp, 0, reg_flags)
+
 #endif
index ff72cab3cd3a1355b03a1e5e54aff51d65802086..1ba9d626aa833db91c462560f27054b30e91939d 100644 (file)
@@ -2335,6 +2335,7 @@ enum nl80211_band_attr {
  * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel
  *     using this channel as the primary or any of the secondary channels
  *     isn't possible
+ * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
  * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
  *     currently defined
  * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -2353,6 +2354,7 @@ enum nl80211_frequency_attr {
        NL80211_FREQUENCY_ATTR_NO_HT40_PLUS,
        NL80211_FREQUENCY_ATTR_NO_80MHZ,
        NL80211_FREQUENCY_ATTR_NO_160MHZ,
+       NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
 
        /* keep last */
        __NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -2449,6 +2451,8 @@ enum nl80211_reg_type {
  *     If you don't have one then don't send this.
  * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
  *     a given frequency range. The value is in mBm (100 * dBm).
+ * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
+ *     If not present or 0 default CAC time will be used.
  * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
  *     currently defined
  * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
@@ -2464,6 +2468,8 @@ enum nl80211_reg_rule_attr {
        NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
        NL80211_ATTR_POWER_RULE_MAX_EIRP,
 
+       NL80211_ATTR_DFS_CAC_TIME,
+
        /* keep last */
        __NL80211_REG_RULE_ATTR_AFTER_LAST,
        NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
index 1acb29109b45dfc9d76d83b0506d8ed47932b10d..aaa59d719592c0b7dc6ef3ddb4df8aaa578bc45c 100644 (file)
@@ -2914,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
 
 static int ieee80211_start_radar_detection(struct wiphy *wiphy,
                                           struct net_device *dev,
-                                          struct cfg80211_chan_def *chandef)
+                                          struct cfg80211_chan_def *chandef,
+                                          u32 cac_time_ms)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
-       unsigned long timeout;
        int err;
 
        mutex_lock(&local->mtx);
@@ -2937,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
        if (err)
                goto out_unlock;
 
-       timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
        ieee80211_queue_delayed_work(&sdata->local->hw,
-                                    &sdata->dfs_cac_timer_work, timeout);
+                                    &sdata->dfs_cac_timer_work,
+                                    msecs_to_jiffies(cac_time_ms));
 
  out_unlock:
        mutex_unlock(&local->mtx);
@@ -3089,52 +3089,11 @@ unlock:
        sdata_unlock(sdata);
 }
 
-int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
-                            struct cfg80211_csa_settings *params)
+static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
+                                   struct cfg80211_csa_settings *params,
+                                   u32 *changed)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_chanctx_conf *chanctx_conf;
-       struct ieee80211_chanctx *chanctx;
-       struct ieee80211_if_mesh __maybe_unused *ifmsh;
-       int err, num_chanctx, changed = 0;
-
-       sdata_assert_lock(sdata);
-
-       if (!list_empty(&local->roc_list) || local->scanning)
-               return -EBUSY;
-
-       if (sdata->wdev.cac_started)
-               return -EBUSY;
-
-       if (cfg80211_chandef_identical(&params->chandef,
-                                      &sdata->vif.bss_conf.chandef))
-               return -EINVAL;
-
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-       if (!chanctx_conf) {
-               rcu_read_unlock();
-               return -EBUSY;
-       }
-
-       /* don't handle for multi-VIF cases */
-       chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
-       if (chanctx->refcount > 1) {
-               rcu_read_unlock();
-               return -EBUSY;
-       }
-       num_chanctx = 0;
-       list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
-               num_chanctx++;
-       rcu_read_unlock();
-
-       if (num_chanctx > 1)
-               return -EBUSY;
-
-       /* don't allow another channel switch if one is already active. */
-       if (sdata->vif.csa_active)
-               return -EBUSY;
+       int err;
 
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP:
@@ -3170,7 +3129,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                        kfree(sdata->u.ap.next_beacon);
                        return err;
                }
-               changed |= err;
+               *changed |= err;
 
                break;
        case NL80211_IFTYPE_ADHOC:
@@ -3204,15 +3163,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                        err = ieee80211_ibss_csa_beacon(sdata, params);
                        if (err < 0)
                                return err;
-                       changed |= err;
+                       *changed |= err;
                }
 
                ieee80211_send_action_csa(sdata, params);
 
                break;
 #ifdef CONFIG_MAC80211_MESH
-       case NL80211_IFTYPE_MESH_POINT:
-               ifmsh = &sdata->u.mesh;
+       case NL80211_IFTYPE_MESH_POINT: {
+               struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 
                if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
                        return -EINVAL;
@@ -3237,18 +3196,72 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                                ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
                                return err;
                        }
-                       changed |= err;
+                       *changed |= err;
                }
 
                if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
                        ieee80211_send_action_csa(sdata, params);
 
                break;
+               }
 #endif
        default:
                return -EOPNOTSUPP;
        }
 
+       return 0;
+}
+
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+                            struct cfg80211_csa_settings *params)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_chanctx *chanctx;
+       int err, num_chanctx, changed = 0;
+
+       sdata_assert_lock(sdata);
+
+       if (!list_empty(&local->roc_list) || local->scanning)
+               return -EBUSY;
+
+       if (sdata->wdev.cac_started)
+               return -EBUSY;
+
+       if (cfg80211_chandef_identical(&params->chandef,
+                                      &sdata->vif.bss_conf.chandef))
+               return -EINVAL;
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (!chanctx_conf) {
+               rcu_read_unlock();
+               return -EBUSY;
+       }
+
+       /* don't handle for multi-VIF cases */
+       chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
+       if (chanctx->refcount > 1) {
+               rcu_read_unlock();
+               return -EBUSY;
+       }
+       num_chanctx = 0;
+       list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
+               num_chanctx++;
+       rcu_read_unlock();
+
+       if (num_chanctx > 1)
+               return -EBUSY;
+
+       /* don't allow another channel switch if one is already active. */
+       if (sdata->vif.csa_active)
+               return -EBUSY;
+
+       err = ieee80211_set_csa_beacon(sdata, params, &changed);
+       if (err)
+               return err;
+
        sdata->csa_radar_required = params->radar_required;
 
        if (params->block_tx)
index e458ca0dffec12fcaca7e614eb14204760ca9b17..06d28787945b513e6672457a1e6990da0fd644d8 100644 (file)
@@ -991,7 +991,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                                  struct ieee802_11_elems *elems)
 {
        struct ieee80211_local *local = sdata->local;
-       int freq;
        struct cfg80211_bss *cbss;
        struct ieee80211_bss *bss;
        struct sta_info *sta;
@@ -1003,15 +1002,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
        bool rates_updated = false;
 
-       if (elems->ds_params)
-               freq = ieee80211_channel_to_frequency(elems->ds_params[0],
-                                                     band);
-       else
-               freq = rx_status->freq;
-
-       channel = ieee80211_get_channel(local->hw.wiphy, freq);
-
-       if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
+       channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
+       if (!channel)
                return;
 
        if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
index 0d1a0f801b9413bdb0ce9a105a2c35811b4a4e30..222c28b75315f1ab43226e08566a5f911c6bacc7 100644 (file)
@@ -1391,6 +1391,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
 void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
 void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata,
                                  __le16 fc, bool acked);
+void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
 
 /* IBSS code */
index 94f0af29b7424fd443c1f2c0e0fb7c92ba2b7fbd..dee50aefd6e868e247ba869e9e9883d4640330e3 100644 (file)
@@ -2783,28 +2783,20 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                                  struct ieee802_11_elems *elems)
 {
        struct ieee80211_local *local = sdata->local;
-       int freq;
        struct ieee80211_bss *bss;
        struct ieee80211_channel *channel;
 
        sdata_assert_lock(sdata);
 
-       if (elems->ds_params)
-               freq = ieee80211_channel_to_frequency(elems->ds_params[0],
-                                                     rx_status->band);
-       else
-               freq = rx_status->freq;
-
-       channel = ieee80211_get_channel(local->hw.wiphy, freq);
-
-       if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
+       channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
+       if (!channel)
                return;
 
        bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
                                        channel);
        if (bss) {
-               ieee80211_rx_bss_put(local, bss);
                sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
+               ieee80211_rx_bss_put(local, bss);
        }
 }
 
@@ -3599,6 +3591,32 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
 }
 
 #ifdef CONFIG_PM
+void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+       sdata_lock(sdata);
+
+       if (ifmgd->auth_data) {
+               /*
+                * If we are trying to authenticate while suspending, cfg80211
+                * won't know and won't actually abort those attempts, thus we
+                * need to do that ourselves.
+                */
+               ieee80211_send_deauth_disassoc(sdata,
+                                              ifmgd->auth_data->bss->bssid,
+                                              IEEE80211_STYPE_DEAUTH,
+                                              WLAN_REASON_DEAUTH_LEAVING,
+                                              false, frame_buf);
+               ieee80211_destroy_auth_data(sdata, false);
+               cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
+                                     IEEE80211_DEAUTH_FRAME_LEN);
+       }
+
+       sdata_unlock(sdata);
+}
+
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -4417,37 +4435,41 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
        bool tx = !req->local_state_change;
-       bool report_frame = false;
 
-       sdata_info(sdata,
-                  "deauthenticating from %pM by local choice (Reason: %u=%s)\n",
-                  req->bssid, req->reason_code, ieee80211_get_reason_code_string(req->reason_code));
+       if (ifmgd->auth_data &&
+           ether_addr_equal(ifmgd->auth_data->bss->bssid, req->bssid)) {
+               sdata_info(sdata,
+                          "aborting authentication with %pM by local choice (Reason: %u=%s)\n",
+                          req->bssid, req->reason_code,
+                          ieee80211_get_reason_code_string(req->reason_code));
 
-       if (ifmgd->auth_data) {
                drv_mgd_prepare_tx(sdata->local, sdata);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
                                               req->reason_code, tx,
                                               frame_buf);
                ieee80211_destroy_auth_data(sdata, false);
+               cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
+                                     IEEE80211_DEAUTH_FRAME_LEN);
 
-               report_frame = true;
-               goto out;
+               return 0;
        }
 
        if (ifmgd->associated &&
            ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
+               sdata_info(sdata,
+                          "deauthenticating from %pM by local choice (Reason: %u=%s)\n",
+                          req->bssid, req->reason_code,
+                          ieee80211_get_reason_code_string(req->reason_code));
+
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
                                       req->reason_code, tx, frame_buf);
-               report_frame = true;
-       }
-
- out:
-       if (report_frame)
                cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
                                      IEEE80211_DEAUTH_FRAME_LEN);
+               return 0;
+       }
 
-       return 0;
+       return -ENOTCONN;
 }
 
 int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
index af64fb8e8addb58e5933cc3a45a8043f55659f81..d478b880a0afd676dae699d5b5541c150a7e819f 100644 (file)
@@ -100,10 +100,18 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 
        /* remove all interfaces that were created in the driver */
        list_for_each_entry(sdata, &local->interfaces, list) {
-               if (!ieee80211_sdata_running(sdata) ||
-                   sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
-                   sdata->vif.type == NL80211_IFTYPE_MONITOR)
+               if (!ieee80211_sdata_running(sdata))
                        continue;
+               switch (sdata->vif.type) {
+               case NL80211_IFTYPE_AP_VLAN:
+               case NL80211_IFTYPE_MONITOR:
+                       continue;
+               case NL80211_IFTYPE_STATION:
+                       ieee80211_mgd_quiesce(sdata);
+                       break;
+               default:
+                       break;
+               }
 
                drv_remove_interface(local, sdata);
        }
index 5b617660b0ba5c7c12755b6a9b5ffb9a69923c97..216c45b949e513382447050eb560098a5edaa4b3 100644 (file)
@@ -333,6 +333,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                /* in VHT, STBC is binary */
                if (status->flag & RX_FLAG_STBC_MASK)
                        *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
+               if (status->vht_flag & RX_VHT_FLAG_BF)
+                       *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
                pos++;
                /* bandwidth */
                if (status->vht_flag & RX_VHT_FLAG_80MHZ)
@@ -1245,6 +1247,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
                if (ieee80211_is_data(hdr->frame_control)) {
                        sta->last_rx_rate_idx = status->rate_idx;
                        sta->last_rx_rate_flag = status->flag;
+                       sta->last_rx_rate_vht_flag = status->vht_flag;
                        sta->last_rx_rate_vht_nss = status->vht_nss;
                }
        }
index 836f500dfbf3c989f1f4d21fa281da0d506468fa..3ce7f2c8539a1f626f7488833ee966fb3af5d502 100644 (file)
@@ -1055,9 +1055,11 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
        /* We don't want to restart sched scan anymore. */
        local->sched_scan_req = NULL;
 
-       if (rcu_access_pointer(local->sched_scan_sdata))
+       if (rcu_access_pointer(local->sched_scan_sdata)) {
                ret = drv_sched_scan_stop(local, sdata);
-
+               if (!ret)
+                       rcu_assign_pointer(local->sched_scan_sdata, NULL);
+       }
 out:
        mutex_unlock(&local->mtx);
 
index cd9f80498c48ef2d8811133c4dbc40eada9a39a1..19d36d4117e0da0b5524b7e3f8102a86810dceed 100644 (file)
@@ -2900,7 +2900,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
                                cpu_to_le16(IEEE80211_FCTL_MOREDATA);
                }
 
-               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               if (sdata->vif.type == NL80211_IFTYPE_AP)
                        sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
                if (!ieee80211_tx_prepare(sdata, &tx, skb))
                        break;
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 5946450c540676b75b726e20b016395ae08e6b7c..8659d5cee2a6ba01b4f17830608795768c92d107 100644 (file)
@@ -490,6 +490,62 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
        return r;
 }
 
+static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
+                                                   u32 center_freq,
+                                                   u32 bandwidth)
+{
+       struct ieee80211_channel *c;
+       u32 start_freq, end_freq, freq;
+       unsigned int dfs_cac_ms = 0;
+
+       start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
+       end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
+
+       for (freq = start_freq; freq <= end_freq; freq += 20) {
+               c = ieee80211_get_channel(wiphy, freq);
+               if (!c)
+                       return 0;
+
+               if (c->flags & IEEE80211_CHAN_DISABLED)
+                       return 0;
+
+               if (!(c->flags & IEEE80211_CHAN_RADAR))
+                       continue;
+
+               if (c->dfs_cac_ms > dfs_cac_ms)
+                       dfs_cac_ms = c->dfs_cac_ms;
+       }
+
+       return dfs_cac_ms;
+}
+
+unsigned int
+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
+                             const struct cfg80211_chan_def *chandef)
+{
+       int width;
+       unsigned int t1 = 0, t2 = 0;
+
+       if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+               return 0;
+
+       width = cfg80211_chandef_get_width(chandef);
+       if (width < 0)
+               return 0;
+
+       t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
+                                            chandef->center_freq1,
+                                            width);
+
+       if (!chandef->center_freq2)
+               return t1;
+
+       t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
+                                            chandef->center_freq2,
+                                            width);
+
+       return max(t1, t2);
+}
 
 static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
                                        u32 center_freq, u32 bandwidth,
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 40683004d52338fa8830a11cd38fdd42c74c156a..5b1fdcadd46985548f4a04f4f64ddaccbc935661 100644 (file)
@@ -166,7 +166,6 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
        mutex_unlock(&wdev->mtx);
 }
 
-#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
 #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
 
 static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
@@ -246,10 +245,6 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
                       unsigned long age_secs);
 
 /* IBSS */
-int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
-                        struct net_device *dev,
-                        struct cfg80211_ibss_params *params,
-                        struct cfg80211_cached_keys *connkeys);
 int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
                       struct net_device *dev,
                       struct cfg80211_ibss_params *params,
@@ -283,7 +278,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,
@@ -402,6 +397,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
 
 void cfg80211_dfs_channels_update_work(struct work_struct *work);
 
+unsigned int
+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
+                             const struct cfg80211_chan_def *chandef);
 
 static inline int
 cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
index fdfd3f063a9bcad326377d4da0b2f6c5354c5cb5..b35da8dc85deff4640ecb0975cc829326b68034c 100644 (file)
@@ -66,6 +66,7 @@ function parse_reg_rule()
        units = $8
        sub(/\)/, "", units)
        sub(/,/, "", units)
+       dfs_cac = $9
        if (units == "mW") {
                if (power == 100) {
                        power = 20
@@ -78,7 +79,12 @@ function parse_reg_rule()
                } else {
                        print "Unknown power value in database!"
                }
+       } else {
+               dfs_cac = $8
        }
+       sub(/,/, "", dfs_cac)
+       sub(/\(/, "", dfs_cac)
+       sub(/\)/, "", dfs_cac)
        flagstr = ""
        for (i=8; i<=NF; i++)
                flagstr = flagstr $i
@@ -111,7 +117,7 @@ function parse_reg_rule()
 
        }
        flags = flags "0"
-       printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
+       printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
        rules++
 }
 
index 349db9ddc0d13737eb84f874bc3b556b61b38026..a6b5bdad039c7450f276d1e56994661e2e41952c 100644 (file)
@@ -82,10 +82,10 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 }
 EXPORT_SYMBOL(cfg80211_ibss_joined);
 
-int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
-                        struct net_device *dev,
-                        struct cfg80211_ibss_params *params,
-                        struct cfg80211_cached_keys *connkeys)
+static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
+                               struct net_device *dev,
+                               struct cfg80211_ibss_params *params,
+                               struct cfg80211_cached_keys *connkeys)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct ieee80211_channel *check_chan;
index d47c9d127b1eef3bef4e8d00f65dcf1392d70c2d..c52ff59a3e96d7cabb892bff220b86c580069a43 100644 (file)
@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev,
        switch (event) {
        case NL80211_RADAR_CAC_FINISHED:
                timeout = wdev->cac_start_time +
-                         msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
+                         msecs_to_jiffies(wdev->cac_time_ms);
                WARN_ON(!time_after_eq(jiffies, timeout));
                cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
                break;
index 2c38b28a85b9b1d800caaf617be18f06517b63cd..052c1bf8ffaceb92d3f117231a46fca78ed30216 100644 (file)
@@ -593,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
                        if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
                                        time))
                                goto nla_put_failure;
+                       if (nla_put_u32(msg,
+                                       NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
+                                       chan->dfs_cac_ms))
+                               goto nla_put_failure;
                }
        }
 
@@ -3328,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] = {
@@ -4614,6 +4618,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] =
        [NL80211_ATTR_FREQ_RANGE_MAX_BW]        = { .type = NLA_U32 },
        [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]  = { .type = NLA_U32 },
        [NL80211_ATTR_POWER_RULE_MAX_EIRP]      = { .type = NLA_U32 },
+       [NL80211_ATTR_DFS_CAC_TIME]             = { .type = NLA_U32 },
 };
 
 static int parse_reg_rule(struct nlattr *tb[],
@@ -4649,6 +4654,10 @@ static int parse_reg_rule(struct nlattr *tb[],
                power_rule->max_antenna_gain =
                        nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
 
+       if (tb[NL80211_ATTR_DFS_CAC_TIME])
+               reg_rule->dfs_cac_ms =
+                       nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
+
        return 0;
 }
 
@@ -5136,7 +5145,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
                    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
                                power_rule->max_antenna_gain) ||
                    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
-                               power_rule->max_eirp))
+                               power_rule->max_eirp) ||
+                   nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
+                               reg_rule->dfs_cac_ms))
                        goto nla_put_failure_rcu;
 
                nla_nest_end(msg, nl_reg_rule);
@@ -5768,6 +5779,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_chan_def chandef;
        enum nl80211_dfs_regions dfs_region;
+       unsigned int cac_time_ms;
        int err;
 
        dfs_region = reg_get_dfs_region(wdev->wiphy);
@@ -5803,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
        if (err)
                return err;
 
-       err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
+       cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
+       if (WARN_ON(!cac_time_ms))
+               cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+
+       err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef,
+                                              cac_time_ms);
        if (!err) {
                wdev->chandef = chandef;
                wdev->cac_started = true;
                wdev->cac_start_time = jiffies;
+               wdev->cac_time_ms = cac_time_ms;
        }
        return err;
 }
index 90b82e08ae699b31bd405a495375a88dd5dd1af3..f59aaac586f8cf10905135324c3913646910a662 100644 (file)
@@ -91,10 +91,6 @@ static struct regulatory_request __rcu *last_request =
 /* To trigger userspace events */
 static struct platform_device *reg_pdev;
 
-static const struct device_type reg_device_type = {
-       .uevent = reg_device_uevent,
-};
-
 /*
  * Central wireless core regulatory domains, we only need two,
  * the current one and a world regulatory domain in case we have no
@@ -244,19 +240,21 @@ static char user_alpha2[2];
 module_param(ieee80211_regdom, charp, 0444);
 MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
 
-static void reg_kfree_last_request(void)
+static void reg_free_request(struct regulatory_request *lr)
 {
-       struct regulatory_request *lr;
-
-       lr = get_last_request();
-
        if (lr != &core_request_world && lr)
                kfree_rcu(lr, rcu_head);
 }
 
 static void reg_update_last_request(struct regulatory_request *request)
 {
-       reg_kfree_last_request();
+       struct regulatory_request *lr;
+
+       lr = get_last_request();
+       if (lr == request)
+               return;
+
+       reg_free_request(lr);
        rcu_assign_pointer(last_request, request);
 }
 
@@ -487,11 +485,16 @@ static inline void reg_regdb_query(const char *alpha2) {}
 
 /*
  * This lets us keep regulatory code which is updated on a regulatory
- * basis in userspace. Country information is filled in by
- * reg_device_uevent
+ * basis in userspace.
  */
 static int call_crda(const char *alpha2)
 {
+       char country[12];
+       char *env[] = { country, NULL };
+
+       snprintf(country, sizeof(country), "COUNTRY=%c%c",
+                alpha2[0], alpha2[1]);
+
        if (!is_world_regdom((char *) alpha2))
                pr_info("Calling CRDA for country: %c%c\n",
                        alpha2[0], alpha2[1]);
@@ -501,7 +504,7 @@ static int call_crda(const char *alpha2)
        /* query internal regulatory database (if it exists) */
        reg_regdb_query(alpha2);
 
-       return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
+       return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env);
 }
 
 static enum reg_request_treatment
@@ -755,6 +758,9 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
        power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
                power_rule2->max_antenna_gain);
 
+       intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms,
+                                          rule2->dfs_cac_ms);
+
        if (!is_valid_reg_rule(intersected_rule))
                return -EINVAL;
 
@@ -1077,6 +1083,14 @@ static void handle_channel(struct wiphy *wiphy,
                min_t(int, chan->orig_mag,
                      MBI_TO_DBI(power_rule->max_antenna_gain));
        chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+
+       if (chan->flags & IEEE80211_CHAN_RADAR) {
+               if (reg_rule->dfs_cac_ms)
+                       chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
+               else
+                       chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+       }
+
        if (chan->orig_mpwr) {
                /*
                 * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
@@ -2255,9 +2269,9 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
        const struct ieee80211_reg_rule *reg_rule = NULL;
        const struct ieee80211_freq_range *freq_range = NULL;
        const struct ieee80211_power_rule *power_rule = NULL;
-       char bw[32];
+       char bw[32], cac_time[32];
 
-       pr_info("  (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
+       pr_info("  (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
 
        for (i = 0; i < rd->n_reg_rules; i++) {
                reg_rule = &rd->reg_rules[i];
@@ -2272,23 +2286,32 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
                        snprintf(bw, sizeof(bw), "%d KHz",
                                 freq_range->max_bandwidth_khz);
 
+               if (reg_rule->flags & NL80211_RRF_DFS)
+                       scnprintf(cac_time, sizeof(cac_time), "%u s",
+                                 reg_rule->dfs_cac_ms/1000);
+               else
+                       scnprintf(cac_time, sizeof(cac_time), "N/A");
+
+
                /*
                 * There may not be documentation for max antenna gain
                 * in certain regions
                 */
                if (power_rule->max_antenna_gain)
-                       pr_info("  (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n",
+                       pr_info("  (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
                                freq_range->start_freq_khz,
                                freq_range->end_freq_khz,
                                bw,
                                power_rule->max_antenna_gain,
-                               power_rule->max_eirp);
+                               power_rule->max_eirp,
+                               cac_time);
                else
-                       pr_info("  (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n",
+                       pr_info("  (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
                                freq_range->start_freq_khz,
                                freq_range->end_freq_khz,
                                bw,
-                               power_rule->max_eirp);
+                               power_rule->max_eirp,
+                               cac_time);
        }
 }
 
@@ -2361,9 +2384,6 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
 {
        const struct ieee80211_regdomain *intersected_rd = NULL;
 
-       if (is_world_regdom(rd->alpha2))
-               return -EINVAL;
-
        if (!regdom_changes(rd->alpha2))
                return -EALREADY;
 
@@ -2552,26 +2572,6 @@ int set_regdom(const struct ieee80211_regdomain *rd)
        return 0;
 }
 
-int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       struct regulatory_request *lr;
-       u8 alpha2[2];
-       bool add = false;
-
-       rcu_read_lock();
-       lr = get_last_request();
-       if (lr && !lr->processed) {
-               memcpy(alpha2, lr->alpha2, 2);
-               add = true;
-       }
-       rcu_read_unlock();
-
-       if (add)
-               return add_uevent_var(env, "COUNTRY=%c%c",
-                                     alpha2[0], alpha2[1]);
-       return 0;
-}
-
 void wiphy_regulatory_register(struct wiphy *wiphy)
 {
        struct regulatory_request *lr;
@@ -2622,8 +2622,6 @@ int __init regulatory_init(void)
        if (IS_ERR(reg_pdev))
                return PTR_ERR(reg_pdev);
 
-       reg_pdev->dev.type = &reg_device_type;
-
        spin_lock_init(&reg_requests_lock);
        spin_lock_init(&reg_pending_beacons_lock);
 
index 18524617ab62642d5b8cbd59644d7e2be2e4fede..37c180df34b72a1195aacb6d72b7b07ddc44a9ef 100644 (file)
@@ -26,7 +26,6 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
 int regulatory_hint_user(const char *alpha2,
                         enum nl80211_user_reg_hint_type user_reg_hint_type);
 
-int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 void wiphy_regulatory_register(struct wiphy *wiphy);
 void wiphy_regulatory_deregister(struct wiphy *wiphy);
 
index d1ed4aebbbb7dcc6dca3fccea4222e3eb7eb2fb0..7d09a712cb1f1353f13310f5c68b38e750d199a6 100644 (file)
@@ -659,9 +659,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
                        continue;
                if (ssidlen && ie[1] != ssidlen)
                        continue;
-               /* that would be odd ... */
-               if (bss->pub.beacon_ies)
-                       continue;
                if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss))
                        continue;
                if (WARN_ON_ONCE(!list_empty(&bss->hidden_list)))
@@ -680,7 +677,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 static struct cfg80211_internal_bss *
 cfg80211_bss_update(struct cfg80211_registered_device *dev,
-                   struct cfg80211_internal_bss *tmp)
+                   struct cfg80211_internal_bss *tmp,
+                   bool signal_valid)
 {
        struct cfg80211_internal_bss *found = NULL;
 
@@ -765,7 +763,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
                }
 
                found->pub.beacon_interval = tmp->pub.beacon_interval;
-               found->pub.signal = tmp->pub.signal;
+               /*
+                * don't update the signal if beacon was heard on
+                * adjacent channel.
+                */
+               if (signal_valid)
+                       found->pub.signal = tmp->pub.signal;
                found->pub.capability = tmp->pub.capability;
                found->ts = tmp->ts;
        } else {
@@ -869,13 +872,14 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 struct cfg80211_bss*
 cfg80211_inform_bss_width(struct wiphy *wiphy,
-                         struct ieee80211_channel *channel,
+                         struct ieee80211_channel *rx_channel,
                          enum nl80211_bss_scan_width scan_width,
                          const u8 *bssid, u64 tsf, u16 capability,
                          u16 beacon_interval, const u8 *ie, size_t ielen,
                          s32 signal, gfp_t gfp)
 {
        struct cfg80211_bss_ies *ies;
+       struct ieee80211_channel *channel;
        struct cfg80211_internal_bss tmp = {}, *res;
 
        if (WARN_ON(!wiphy))
@@ -885,7 +889,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
                        (signal < 0 || signal > 100)))
                return NULL;
 
-       channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel);
+       channel = cfg80211_get_bss_channel(wiphy, ie, ielen, rx_channel);
        if (!channel)
                return NULL;
 
@@ -913,7 +917,8 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
        rcu_assign_pointer(tmp.pub.beacon_ies, ies);
        rcu_assign_pointer(tmp.pub.ies, ies);
 
-       res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
+       res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp,
+                                 rx_channel == channel);
        if (!res)
                return NULL;
 
@@ -929,20 +934,21 @@ EXPORT_SYMBOL(cfg80211_inform_bss_width);
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 struct cfg80211_bss *
 cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
-                               struct ieee80211_channel *channel,
+                               struct ieee80211_channel *rx_channel,
                                enum nl80211_bss_scan_width scan_width,
                                struct ieee80211_mgmt *mgmt, size_t len,
                                s32 signal, gfp_t gfp)
 {
        struct cfg80211_internal_bss tmp = {}, *res;
        struct cfg80211_bss_ies *ies;
+       struct ieee80211_channel *channel;
        size_t ielen = len - offsetof(struct ieee80211_mgmt,
                                      u.probe_resp.variable);
 
        BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
                        offsetof(struct ieee80211_mgmt, u.beacon.variable));
 
-       trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt,
+       trace_cfg80211_inform_bss_width_frame(wiphy, rx_channel, scan_width, mgmt,
                                              len, signal);
 
        if (WARN_ON(!mgmt))
@@ -959,7 +965,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
                return NULL;
 
        channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
-                                          ielen, channel);
+                                          ielen, rx_channel);
        if (!channel)
                return NULL;
 
@@ -983,7 +989,8 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
        tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
        tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
 
-       res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
+       res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp,
+                                 rx_channel == channel);
        if (!res)
                return NULL;
 
index f04d4c32e96e144d37b49de5d1be69add8a55b2c..acdcb4a81817b7c78e8e721ff632284b9b806fa9 100644 (file)
@@ -64,7 +64,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
        int n_channels, err;
 
        ASSERT_RTNL();
-       ASSERT_RDEV_LOCK(rdev);
        ASSERT_WDEV_LOCK(wdev);
 
        if (rdev->scan_req || rdev->scan_msg)
index 57b3ce7a6b9255df15b5064ac5fd177414a662cc..39fc1d70da6980a1e9457884e96ee3da582ce259 100644 (file)
@@ -838,7 +838,6 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
        struct wireless_dev *wdev;
 
        ASSERT_RTNL();
-       ASSERT_RDEV_LOCK(rdev);
 
        list_for_each_entry(wdev, &rdev->wdev_list, list)
                cfg80211_process_wdev_events(wdev);
@@ -851,7 +850,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
        int err;
        enum nl80211_iftype otype = dev->ieee80211_ptr->iftype;
 
-       ASSERT_RDEV_LOCK(rdev);
+       ASSERT_RTNL();
 
        /* don't support changing VLANs, you just re-create them */
        if (otype == NL80211_IFTYPE_AP_VLAN)
@@ -886,7 +885,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);
index 14c9a2583ba0926a2e14a777aaa5b69fd09f8963..86c331a65664a77bfe6c083224b7eae2c91f5b9c 100644 (file)
@@ -21,7 +21,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
        const u8 *prev_bssid = NULL;
        int err, i;
 
-       ASSERT_RDEV_LOCK(rdev);
+       ASSERT_RTNL();
        ASSERT_WDEV_LOCK(wdev);
 
        if (!netif_running(wdev->netdev))
This page took 0.0505 seconds and 5 git commands to generate.