Merge remote-tracking branch 'net-next/master' into mac80211-next
authorJohannes Berg <johannes.berg@intel.com>
Fri, 6 Oct 2017 09:46:32 +0000 (11:46 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 6 Oct 2017 09:46:55 +0000 (11:46 +0200)
Merging this brings in the timer_setup() change, which allows
me to apply Kees's mac80211 changes for it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
23 files changed:
Documentation/driver-api/80211/cfg80211.rst
drivers/net/wireless/mac80211_hwsim.c
include/linux/ieee80211.h
include/net/cfg80211.h
include/net/mac80211.h
include/uapi/linux/nl80211.h
net/mac80211/agg-rx.c
net/mac80211/ht.c
net/mac80211/iface.c
net/mac80211/mesh.c
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/util.c
net/mac80211/vht.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/nl80211.h
net/wireless/sme.c
net/wireless/util.c

index 8ffac57..eeab91b 100644 (file)
@@ -299,9 +299,6 @@ Data path helpers
 .. kernel-doc:: include/net/cfg80211.h
    :functions: ieee80211_data_to_8023
 
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_data_from_8023
-
 .. kernel-doc:: include/net/cfg80211.h
    :functions: ieee80211_amsdu_to_8023s
 
index 6467ffa..ec2f4c3 100644 (file)
@@ -396,7 +396,7 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy,
        if (!tb[QCA_WLAN_VENDOR_ATTR_TEST])
                return -EINVAL;
        val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TEST]);
-       wiphy_debug(wiphy, "%s: test=%u\n", __func__, val);
+       wiphy_dbg(wiphy, "%s: test=%u\n", __func__, val);
 
        /* Send a vendor event as a test. Note that this would not normally be
         * done within a command handler, but rather, based on some other
@@ -643,9 +643,9 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
        if (!vp->assoc)
                return;
 
-       wiphy_debug(data->hw->wiphy,
-                   "%s: send PS-Poll to %pM for aid %d\n",
-                   __func__, vp->bssid, vp->aid);
+       wiphy_dbg(data->hw->wiphy,
+                 "%s: send PS-Poll to %pM for aid %d\n",
+                 __func__, vp->bssid, vp->aid);
 
        skb = dev_alloc_skb(sizeof(*pspoll));
        if (!skb)
@@ -674,9 +674,9 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
        if (!vp->assoc)
                return;
 
-       wiphy_debug(data->hw->wiphy,
-                   "%s: send data::nullfunc to %pM ps=%d\n",
-                   __func__, vp->bssid, ps);
+       wiphy_dbg(data->hw->wiphy,
+                 "%s: send data::nullfunc to %pM ps=%d\n",
+                 __func__, vp->bssid, ps);
 
        skb = dev_alloc_skb(sizeof(*hdr));
        if (!skb)
@@ -1034,7 +1034,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
        msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
                               HWSIM_CMD_FRAME);
        if (msg_head == NULL) {
-               printk(KERN_DEBUG "mac80211_hwsim: problem with msg_head\n");
+               pr_debug("mac80211_hwsim: problem with msg_head\n");
                goto nla_put_failure;
        }
 
@@ -1093,7 +1093,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
 nla_put_failure:
        nlmsg_free(skb);
 err_free_txskb:
-       printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
+       pr_debug("mac80211_hwsim: error occurred in %s\n", __func__);
        ieee80211_free_txskb(hw, my_skb);
        data->tx_failed++;
 }
@@ -1347,7 +1347,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
        }
 
        if (data->idle && !data->tmp_chan) {
-               wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
+               wiphy_dbg(hw->wiphy, "Trying to TX when idle - reject\n");
                ieee80211_free_txskb(hw, skb);
                return;
        }
@@ -1408,7 +1408,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
 static int mac80211_hwsim_start(struct ieee80211_hw *hw)
 {
        struct mac80211_hwsim_data *data = hw->priv;
-       wiphy_debug(hw->wiphy, "%s\n", __func__);
+       wiphy_dbg(hw->wiphy, "%s\n", __func__);
        data->started = true;
        return 0;
 }
@@ -1419,16 +1419,16 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
        struct mac80211_hwsim_data *data = hw->priv;
        data->started = false;
        tasklet_hrtimer_cancel(&data->beacon_timer);
-       wiphy_debug(hw->wiphy, "%s\n", __func__);
+       wiphy_dbg(hw->wiphy, "%s\n", __func__);
 }
 
 
 static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
                                        struct ieee80211_vif *vif)
 {
-       wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
-                   __func__, ieee80211_vif_type_p2p(vif),
-                   vif->addr);
+       wiphy_dbg(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
+                 __func__, ieee80211_vif_type_p2p(vif),
+                 vif->addr);
        hwsim_set_magic(vif);
 
        vif->cab_queue = 0;
@@ -1447,9 +1447,9 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
                                           bool newp2p)
 {
        newtype = ieee80211_iftype_p2p(newtype, newp2p);
-       wiphy_debug(hw->wiphy,
-                   "%s (old type=%d, new type=%d, mac_addr=%pM)\n",
-                   __func__, ieee80211_vif_type_p2p(vif),
+       wiphy_dbg(hw->wiphy,
+                 "%s (old type=%d, new type=%d, mac_addr=%pM)\n",
+                 __func__, ieee80211_vif_type_p2p(vif),
                    newtype, vif->addr);
        hwsim_check_magic(vif);
 
@@ -1465,9 +1465,9 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
 static void mac80211_hwsim_remove_interface(
        struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
-       wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
-                   __func__, ieee80211_vif_type_p2p(vif),
-                   vif->addr);
+       wiphy_dbg(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
+                 __func__, ieee80211_vif_type_p2p(vif),
+                 vif->addr);
        hwsim_check_magic(vif);
        hwsim_clear_magic(vif);
 }
@@ -1589,23 +1589,23 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
        int idx;
 
        if (conf->chandef.chan)
-               wiphy_debug(hw->wiphy,
-                           "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n",
-                           __func__,
-                           conf->chandef.chan->center_freq,
-                           conf->chandef.center_freq1,
-                           conf->chandef.center_freq2,
-                           hwsim_chanwidths[conf->chandef.width],
-                           !!(conf->flags & IEEE80211_CONF_IDLE),
-                           !!(conf->flags & IEEE80211_CONF_PS),
-                           smps_modes[conf->smps_mode]);
+               wiphy_dbg(hw->wiphy,
+                         "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n",
+                         __func__,
+                         conf->chandef.chan->center_freq,
+                         conf->chandef.center_freq1,
+                         conf->chandef.center_freq2,
+                         hwsim_chanwidths[conf->chandef.width],
+                         !!(conf->flags & IEEE80211_CONF_IDLE),
+                         !!(conf->flags & IEEE80211_CONF_PS),
+                         smps_modes[conf->smps_mode]);
        else
-               wiphy_debug(hw->wiphy,
-                           "%s (freq=0 idle=%d ps=%d smps=%s)\n",
-                           __func__,
-                           !!(conf->flags & IEEE80211_CONF_IDLE),
-                           !!(conf->flags & IEEE80211_CONF_PS),
-                           smps_modes[conf->smps_mode]);
+               wiphy_dbg(hw->wiphy,
+                         "%s (freq=0 idle=%d ps=%d smps=%s)\n",
+                         __func__,
+                         !!(conf->flags & IEEE80211_CONF_IDLE),
+                         !!(conf->flags & IEEE80211_CONF_PS),
+                         smps_modes[conf->smps_mode]);
 
        data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 
@@ -1659,7 +1659,7 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
 {
        struct mac80211_hwsim_data *data = hw->priv;
 
-       wiphy_debug(hw->wiphy, "%s\n", __func__);
+       wiphy_dbg(hw->wiphy, "%s\n", __func__);
 
        data->rx_filter = 0;
        if (*total_flags & FIF_ALLMULTI)
@@ -1688,25 +1688,25 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
 
        hwsim_check_magic(vif);
 
-       wiphy_debug(hw->wiphy, "%s(changed=0x%x vif->addr=%pM)\n",
-                   __func__, changed, vif->addr);
+       wiphy_dbg(hw->wiphy, "%s(changed=0x%x vif->addr=%pM)\n",
+                 __func__, changed, vif->addr);
 
        if (changed & BSS_CHANGED_BSSID) {
-               wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n",
-                           __func__, info->bssid);
+               wiphy_dbg(hw->wiphy, "%s: BSSID changed: %pM\n",
+                         __func__, info->bssid);
                memcpy(vp->bssid, info->bssid, ETH_ALEN);
        }
 
        if (changed & BSS_CHANGED_ASSOC) {
-               wiphy_debug(hw->wiphy, "  ASSOC: assoc=%d aid=%d\n",
-                           info->assoc, info->aid);
+               wiphy_dbg(hw->wiphy, "  ASSOC: assoc=%d aid=%d\n",
+                         info->assoc, info->aid);
                vp->assoc = info->assoc;
                vp->aid = info->aid;
        }
 
        if (changed & BSS_CHANGED_BEACON_ENABLED) {
-               wiphy_debug(hw->wiphy, "  BCN EN: %d (BI=%u)\n",
-                           info->enable_beacon, info->beacon_int);
+               wiphy_dbg(hw->wiphy, "  BCN EN: %d (BI=%u)\n",
+                         info->enable_beacon, info->beacon_int);
                vp->bcn_en = info->enable_beacon;
                if (data->started &&
                    !hrtimer_is_queued(&data->beacon_timer.timer) &&
@@ -1725,8 +1725,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
                        ieee80211_iterate_active_interfaces_atomic(
                                data->hw, IEEE80211_IFACE_ITER_NORMAL,
                                mac80211_hwsim_bcn_en_iter, &count);
-                       wiphy_debug(hw->wiphy, "  beaconing vifs remaining: %u",
-                                   count);
+                       wiphy_dbg(hw->wiphy, "  beaconing vifs remaining: %u",
+                                 count);
                        if (count == 0) {
                                tasklet_hrtimer_cancel(&data->beacon_timer);
                                data->beacon_int = 0;
@@ -1735,31 +1735,31 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-               wiphy_debug(hw->wiphy, "  ERP_CTS_PROT: %d\n",
-                           info->use_cts_prot);
+               wiphy_dbg(hw->wiphy, "  ERP_CTS_PROT: %d\n",
+                         info->use_cts_prot);
        }
 
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               wiphy_debug(hw->wiphy, "  ERP_PREAMBLE: %d\n",
-                           info->use_short_preamble);
+               wiphy_dbg(hw->wiphy, "  ERP_PREAMBLE: %d\n",
+                         info->use_short_preamble);
        }
 
        if (changed & BSS_CHANGED_ERP_SLOT) {
-               wiphy_debug(hw->wiphy, "  ERP_SLOT: %d\n", info->use_short_slot);
+               wiphy_dbg(hw->wiphy, "  ERP_SLOT: %d\n", info->use_short_slot);
        }
 
        if (changed & BSS_CHANGED_HT) {
-               wiphy_debug(hw->wiphy, "  HT: op_mode=0x%x\n",
-                           info->ht_operation_mode);
+               wiphy_dbg(hw->wiphy, "  HT: op_mode=0x%x\n",
+                         info->ht_operation_mode);
        }
 
        if (changed & BSS_CHANGED_BASIC_RATES) {
-               wiphy_debug(hw->wiphy, "  BASIC_RATES: 0x%llx\n",
-                           (unsigned long long) info->basic_rates);
+               wiphy_dbg(hw->wiphy, "  BASIC_RATES: 0x%llx\n",
+                         (unsigned long long) info->basic_rates);
        }
 
        if (changed & BSS_CHANGED_TXPOWER)
-               wiphy_debug(hw->wiphy, "  TX Power: %d dBm\n", info->txpower);
+               wiphy_dbg(hw->wiphy, "  TX Power: %d dBm\n", info->txpower);
 }
 
 static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
@@ -1813,11 +1813,11 @@ static int mac80211_hwsim_conf_tx(
        struct ieee80211_vif *vif, u16 queue,
        const struct ieee80211_tx_queue_params *params)
 {
-       wiphy_debug(hw->wiphy,
-                   "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n",
-                   __func__, queue,
-                   params->txop, params->cw_min,
-                   params->cw_max, params->aifs);
+       wiphy_dbg(hw->wiphy,
+                 "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n",
+                 __func__, queue,
+                 params->txop, params->cw_min,
+                 params->cw_max, params->aifs);
        return 0;
 }
 
@@ -1981,7 +1981,7 @@ static void hw_scan_work(struct work_struct *work)
                        .aborted = false,
                };
 
-               wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n");
+               wiphy_dbg(hwsim->hw->wiphy, "hw scan complete\n");
                ieee80211_scan_completed(hwsim->hw, &info);
                hwsim->hw_scan_request = NULL;
                hwsim->hw_scan_vif = NULL;
@@ -1990,8 +1990,8 @@ static void hw_scan_work(struct work_struct *work)
                return;
        }
 
-       wiphy_debug(hwsim->hw->wiphy, "hw scan %d MHz\n",
-                   req->channels[hwsim->scan_chan_idx]->center_freq);
+       wiphy_dbg(hwsim->hw->wiphy, "hw scan %d MHz\n",
+                 req->channels[hwsim->scan_chan_idx]->center_freq);
 
        hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx];
        if (hwsim->tmp_chan->flags & (IEEE80211_CHAN_NO_IR |
@@ -2060,7 +2060,7 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
        memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data));
        mutex_unlock(&hwsim->mutex);
 
-       wiphy_debug(hw->wiphy, "hwsim hw_scan request\n");
+       wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n");
 
        ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0);
 
@@ -2075,7 +2075,7 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
                .aborted = true,
        };
 
-       wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n");
+       wiphy_dbg(hw->wiphy, "hwsim cancel_hw_scan\n");
 
        cancel_delayed_work_sync(&hwsim->hw_scan);
 
@@ -2096,11 +2096,11 @@ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw,
        mutex_lock(&hwsim->mutex);
 
        if (hwsim->scanning) {
-               printk(KERN_DEBUG "two hwsim sw_scans detected!\n");
+               pr_debug("two hwsim sw_scans detected!\n");
                goto out;
        }
 
-       printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n");
+       pr_debug("hwsim sw_scan request, prepping stuff\n");
 
        memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN);
        hwsim->scanning = true;
@@ -2117,7 +2117,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw,
 
        mutex_lock(&hwsim->mutex);
 
-       printk(KERN_DEBUG "hwsim sw_scan_complete\n");
+       pr_debug("hwsim sw_scan_complete\n");
        hwsim->scanning = false;
        eth_zero_addr(hwsim->scan_addr);
 
@@ -2131,7 +2131,7 @@ static void hw_roc_start(struct work_struct *work)
 
        mutex_lock(&hwsim->mutex);
 
-       wiphy_debug(hwsim->hw->wiphy, "hwsim ROC begins\n");
+       wiphy_dbg(hwsim->hw->wiphy, "hwsim ROC begins\n");
        hwsim->tmp_chan = hwsim->roc_chan;
        ieee80211_ready_on_channel(hwsim->hw);
 
@@ -2151,7 +2151,7 @@ static void hw_roc_done(struct work_struct *work)
        hwsim->tmp_chan = NULL;
        mutex_unlock(&hwsim->mutex);
 
-       wiphy_debug(hwsim->hw->wiphy, "hwsim ROC expired\n");
+       wiphy_dbg(hwsim->hw->wiphy, "hwsim ROC expired\n");
 }
 
 static int mac80211_hwsim_roc(struct ieee80211_hw *hw,
@@ -2172,8 +2172,8 @@ static int mac80211_hwsim_roc(struct ieee80211_hw *hw,
        hwsim->roc_duration = duration;
        mutex_unlock(&hwsim->mutex);
 
-       wiphy_debug(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n",
-                   chan->center_freq, duration);
+       wiphy_dbg(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n",
+                 chan->center_freq, duration);
        ieee80211_queue_delayed_work(hw, &hwsim->roc_start, HZ/50);
 
        return 0;
@@ -2190,7 +2190,7 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw)
        hwsim->tmp_chan = NULL;
        mutex_unlock(&hwsim->mutex);
 
-       wiphy_debug(hw->wiphy, "hwsim ROC canceled\n");
+       wiphy_dbg(hw->wiphy, "hwsim ROC canceled\n");
 
        return 0;
 }
@@ -2199,20 +2199,20 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
                                      struct ieee80211_chanctx_conf *ctx)
 {
        hwsim_set_chanctx_magic(ctx);
-       wiphy_debug(hw->wiphy,
-                   "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
-                   ctx->def.chan->center_freq, ctx->def.width,
-                   ctx->def.center_freq1, ctx->def.center_freq2);
+       wiphy_dbg(hw->wiphy,
+                 "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+                 ctx->def.chan->center_freq, ctx->def.width,
+                 ctx->def.center_freq1, ctx->def.center_freq2);
        return 0;
 }
 
 static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
                                          struct ieee80211_chanctx_conf *ctx)
 {
-       wiphy_debug(hw->wiphy,
-                   "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
-                   ctx->def.chan->center_freq, ctx->def.width,
-                   ctx->def.center_freq1, ctx->def.center_freq2);
+       wiphy_dbg(hw->wiphy,
+                 "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+                 ctx->def.chan->center_freq, ctx->def.width,
+                 ctx->def.center_freq1, ctx->def.center_freq2);
        hwsim_check_chanctx_magic(ctx);
        hwsim_clear_chanctx_magic(ctx);
 }
@@ -2222,10 +2222,10 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
                                          u32 changed)
 {
        hwsim_check_chanctx_magic(ctx);
-       wiphy_debug(hw->wiphy,
-                   "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
-                   ctx->def.chan->center_freq, ctx->def.width,
-                   ctx->def.center_freq1, ctx->def.center_freq2);
+       wiphy_dbg(hw->wiphy,
+                 "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+                 ctx->def.chan->center_freq, ctx->def.width,
+                 ctx->def.center_freq1, ctx->def.center_freq2);
 }
 
 static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
@@ -2479,7 +2479,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
                ops = &mac80211_hwsim_mchan_ops;
        hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname);
        if (!hw) {
-               printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n");
+               pr_debug("mac80211_hwsim: ieee80211_alloc_hw failed\n");
                err = -ENOMEM;
                goto failed;
        }
@@ -2507,7 +2507,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
        data->dev->driver = &mac80211_hwsim_driver.driver;
        err = device_bind_driver(data->dev);
        if (err != 0) {
-               printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n",
+               pr_debug("mac80211_hwsim: device_bind_driver failed (%d)\n",
                       err);
                goto failed_bind;
        }
@@ -2698,12 +2698,12 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
 
        err = ieee80211_register_hw(hw);
        if (err < 0) {
-               printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n",
+               pr_debug("mac80211_hwsim: ieee80211_register_hw failed (%d)\n",
                       err);
                goto failed_hw;
        }
 
-       wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr);
+       wiphy_dbg(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr);
 
        if (param->reg_alpha2) {
                data->alpha2[0] = param->reg_alpha2[0];
@@ -3067,7 +3067,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 
        return 0;
 err:
-       printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
+       pr_debug("mac80211_hwsim: error occurred in %s\n", __func__);
 out:
        dev_kfree_skb(skb);
        return -EINVAL;
@@ -3098,7 +3098,7 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
 
        hwsim_register_wmediumd(net, info->snd_portid);
 
-       printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, "
+       pr_debug("mac80211_hwsim: received a REGISTER, "
               "switching to wmediumd mode with pid %d\n", info->snd_portid);
 
        return 0;
@@ -3387,7 +3387,7 @@ static int __init hwsim_init_netlink(void)
        return 0;
 
 failure:
-       printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
+       pr_debug("mac80211_hwsim: error occurred in %s\n", __func__);
        return -EINVAL;
 }
 
@@ -3578,7 +3578,7 @@ module_init(init_mac80211_hwsim);
 
 static void __exit exit_mac80211_hwsim(void)
 {
-       printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
+       pr_debug("mac80211_hwsim: unregister radios\n");
 
        hwsim_exit_netlink();
 
index 55a604a..ee6657a 100644 (file)
@@ -2445,6 +2445,7 @@ enum ieee80211_sa_query_action {
 #define WLAN_OUI_TYPE_MICROSOFT_WPA    1
 #define WLAN_OUI_TYPE_MICROSOFT_WMM    2
 #define WLAN_OUI_TYPE_MICROSOFT_WPS    4
+#define WLAN_OUI_TYPE_MICROSOFT_TPC    8
 
 /*
  * WMM/802.11e Tspec Element
index f12fa52..8b8118a 100644 (file)
@@ -4346,19 +4346,6 @@ static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
        return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
 }
 
-/**
- * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
- * @skb: the 802.3 frame
- * @addr: the device MAC address
- * @iftype: the virtual interface type
- * @bssid: the network bssid (used only for iftype STATION and ADHOC)
- * @qos: build 802.11 QoS data frame
- * Return: 0 on success, or a negative error code.
- */
-int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
-                            enum nl80211_iftype iftype, const u8 *bssid,
-                            bool qos);
-
 /**
  * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
  *
@@ -5441,9 +5428,6 @@ cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
  * @req_ie_len: association request IEs length
  * @resp_ie: association response IEs (may be %NULL)
  * @resp_ie_len: assoc response IEs length
- * @authorized: true if the 802.1X authentication was done by the driver or is
- *     not needed (e.g., when Fast Transition protocol was used), false
- *     otherwise. Ignored for networks that don't use 802.1X authentication.
  */
 struct cfg80211_roam_info {
        struct ieee80211_channel *channel;
@@ -5453,7 +5437,6 @@ struct cfg80211_roam_info {
        size_t req_ie_len;
        const u8 *resp_ie;
        size_t resp_ie_len;
-       bool authorized;
 };
 
 /**
@@ -5477,6 +5460,23 @@ struct cfg80211_roam_info {
 void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
                     gfp_t gfp);
 
+/**
+ * cfg80211_port_authorized - notify cfg80211 of successful security association
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the AP
+ * @gfp: allocation flags
+ *
+ * This function should be called by a driver that supports 4 way handshake
+ * offload after a security association was successfully established (i.e.,
+ * the 4 way handshake was completed successfully). The call to this function
+ * should be preceded with a call to cfg80211_connect_result(),
+ * cfg80211_connect_done(), cfg80211_connect_bss() or cfg80211_roamed() to
+ * indicate the 802.11 association.
+ */
+void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid,
+                             gfp_t gfp);
+
 /**
  * cfg80211_disconnected - notify cfg80211 that connection was dropped
  *
@@ -5934,7 +5934,8 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
  * @ies: the IE buffer
  * @ielen: the length of the IE buffer
  * @ids: an array with element IDs that are allowed before
- *     the split
+ *     the split. A WLAN_EID_EXTENSION value means that the next
+ *     EID in the list is a sub-element of the EXTENSION IE.
  * @n_ids: the size of the element ID array
  * @after_ric: array IE types that come after the RIC element
  * @n_after_ric: size of the @after_ric array
@@ -5965,7 +5966,8 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
  * @ies: the IE buffer
  * @ielen: the length of the IE buffer
  * @ids: an array with element IDs that are allowed before
- *     the split
+ *     the split. A WLAN_EID_EXTENSION value means that the next
+ *     EID in the list is a sub-element of the EXTENSION IE.
  * @n_ids: the size of the element ID array
  * @offset: offset where to start splitting in the buffer
  *
index 885690f..cc9073e 100644 (file)
@@ -5441,8 +5441,14 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
  */
 void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
 
+/**
+ * ieee80211_manage_rx_ba_offl - helper to queue an RX BA work
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback
+ * @addr: station mac address
+ * @tid: the rx tid
+ */
 void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, const u8 *addr,
-                                unsigned int bit);
+                                unsigned int tid);
 
 /**
  * ieee80211_start_rx_ba_session_offl - start a Rx BA session
index 51626b4..95832ce 100644 (file)
  *     authentication/association or not receiving a response from the AP.
  *     Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as
  *     well to remain backwards compatible.
- * @NL80211_CMD_ROAM: notifcation indicating the card/driver roamed by itself.
- *     When the driver roamed in a network that requires 802.1X authentication,
- *     %NL80211_ATTR_PORT_AUTHORIZED should be set if the 802.1X authentication
- *     was done by the driver or if roaming was done using Fast Transition
- *     protocol (in which case 802.1X authentication is not needed). If
- *     %NL80211_ATTR_PORT_AUTHORIZED is not set, user space is responsible for
- *     the 802.1X authentication.
+ *     When establishing a security association, drivers that support 4 way
+ *     handshake offload should send %NL80211_CMD_PORT_AUTHORIZED event when
+ *     the 4 way handshake is completed successfully.
+ * @NL80211_CMD_ROAM: Notification indicating the card/driver roamed by itself.
+ *     When a security association was established with the new AP (e.g. if
+ *     the FT protocol was used for roaming or the driver completed the 4 way
+ *     handshake), this event should be followed by an
+ *     %NL80211_CMD_PORT_AUTHORIZED event.
  * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
  *     userspace that a connection was dropped by the AP or due to other
  *     reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
  * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
  *     configured PMK for the authenticator address identified by
  *     &NL80211_ATTR_MAC.
+ * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way
+ *     handshake was completed successfully by the driver. The BSSID is
+ *     specified with &NL80211_ATTR_MAC. Drivers that support 4 way handshake
+ *     offload should send this event after indicating 802.11 association with
+ *     &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed
+ *     &NL80211_CMD_DISCONNECT should be indicated instead.
  *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
@@ -1185,6 +1192,8 @@ enum nl80211_commands {
        NL80211_CMD_SET_PMK,
        NL80211_CMD_DEL_PMK,
 
+       NL80211_CMD_PORT_AUTHORIZED,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -1407,8 +1416,12 @@ enum nl80211_commands {
  *
  * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is
  *     used for the association (&enum nl80211_mfp, represented as a u32);
- *     this attribute can be used
- *     with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests
+ *     this attribute can be used with %NL80211_CMD_ASSOCIATE and
+ *     %NL80211_CMD_CONNECT requests. %NL80211_MFP_OPTIONAL is not allowed for
+ *     %NL80211_CMD_ASSOCIATE since user space SME is expected and hence, it
+ *     must have decided whether to use management frame protection or not.
+ *     Setting %NL80211_MFP_OPTIONAL with a %NL80211_CMD_CONNECT request will
+ *     let the driver (or the firmware) decide whether to use MFP or not.
  *
  * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
  *     &struct nl80211_sta_flag_update.
@@ -2134,10 +2147,7 @@ enum nl80211_commands {
  *     in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it
  *     wants to use the supported offload of the 4-way handshake.
  * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
- * @NL80211_ATTR_PORT_AUTHORIZED: flag attribute used in %NL80211_CMD_ROAMED
- *     notification indicating that that 802.1X authentication was done by
- *     the driver or is not needed (because roaming used the Fast Transition
- *     protocol).
+ * @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
  *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -3947,10 +3957,12 @@ enum nl80211_key_type {
  * enum nl80211_mfp - Management frame protection state
  * @NL80211_MFP_NO: Management frame protection not used
  * @NL80211_MFP_REQUIRED: Management frame protection required
+ * @NL80211_MFP_OPTIONAL: Management frame protection is optional
  */
 enum nl80211_mfp {
        NL80211_MFP_NO,
        NL80211_MFP_REQUIRED,
+       NL80211_MFP_OPTIONAL,
 };
 
 enum nl80211_wpa_versions {
@@ -4914,6 +4926,17 @@ enum nl80211_feature_flags {
  *     handshake with 802.1X in station mode (will pass EAP frames to the host
  *     and accept the set_pmk/del_pmk commands), doing it in the host might not
  *     be supported.
+ * @NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME: Driver is capable of overriding
+ *     the max channel attribute in the FILS request params IE with the
+ *     actual dwell time.
+ * @NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP: Driver accepts broadcast probe
+ *     response
+ * @NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE: Driver supports sending
+ *     the first probe request in each channel at rate of at least 5.5Mbps.
+ * @NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: Driver supports
+ *     probe request tx deferral and suppression
+ * @NL80211_EXT_FEATURE_MFP_OPTIONAL: Driver supports the %NL80211_MFP_OPTIONAL
+ *     value in %NL80211_ATTR_USE_MFP.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4936,6 +4959,11 @@ enum nl80211_ext_feature_index {
        NL80211_EXT_FEATURE_FILS_SK_OFFLOAD,
        NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK,
        NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,
+       NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME,
+       NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP,
+       NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE,
+       NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
+       NL80211_EXT_FEATURE_MFP_OPTIONAL,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
@@ -5012,12 +5040,28 @@ enum nl80211_timeout_reason {
  *     locally administered 1, multicast 0) is assumed.
  *     This flag must not be requested when the feature isn't supported, check
  *     the nl80211 feature flags for the device.
+ * @NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME: fill the dwell time in the FILS
+ *     request parameters IE in the probe request
+ * @NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP: accept broadcast probe responses
+ * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE: send probe request frames at
+ *     rate of at least 5.5M. In case non OCE AP is dicovered in the channel,
+ *     only the first probe req in the channel will be sent in high rate.
+ * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: allow probe request
+ *     tx deferral (dot11FILSProbeDelay shall be set to 15ms)
+ *     and suppression (if it has received a broadcast Probe Response frame,
+ *     Beacon frame or FILS Discovery frame from an AP that the STA considers
+ *     a suitable candidate for (re-)association - suitable in terms of
+ *     SSID and/or RSSI
  */
 enum nl80211_scan_flags {
-       NL80211_SCAN_FLAG_LOW_PRIORITY                  = 1<<0,
-       NL80211_SCAN_FLAG_FLUSH                         = 1<<1,
-       NL80211_SCAN_FLAG_AP                            = 1<<2,
-       NL80211_SCAN_FLAG_RANDOM_ADDR                   = 1<<3,
+       NL80211_SCAN_FLAG_LOW_PRIORITY                          = 1<<0,
+       NL80211_SCAN_FLAG_FLUSH                                 = 1<<1,
+       NL80211_SCAN_FLAG_AP                                    = 1<<2,
+       NL80211_SCAN_FLAG_RANDOM_ADDR                           = 1<<3,
+       NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME                 = 1<<4,
+       NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP               = 1<<5,
+       NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE            = 1<<6,
+       NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION    = 1<<7,
 };
 
 /**
index 2849a1f..88cc1ae 100644 (file)
@@ -459,7 +459,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 }
 
 void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
-                                const u8 *addr, unsigned int bit)
+                                const u8 *addr, unsigned int tid)
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
        struct ieee80211_local *local = sdata->local;
@@ -470,7 +470,7 @@ void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
        if (!sta)
                goto unlock;
 
-       set_bit(bit, sta->ampdu_mlme.tid_rx_manage_offl);
+       set_bit(tid, sta->ampdu_mlme.tid_rx_manage_offl);
        ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
  unlock:
        rcu_read_unlock();
index d6d0b42..41f5e48 100644 (file)
@@ -290,13 +290,15 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
 {
        int i;
 
+       mutex_lock(&sta->ampdu_mlme.mtx);
        for (i = 0; i <  IEEE80211_NUM_TIDS; i++) {
-               __ieee80211_stop_tx_ba_session(sta, i, reason);
-               __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
-                                              WLAN_REASON_QSTA_LEAVE_QBSS,
-                                              reason != AGG_STOP_DESTROY_STA &&
-                                              reason != AGG_STOP_PEER_REQUEST);
+               ___ieee80211_stop_tx_ba_session(sta, i, reason);
+               ___ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
+                                               WLAN_REASON_QSTA_LEAVE_QBSS,
+                                               reason != AGG_STOP_DESTROY_STA &&
+                                               reason != AGG_STOP_PEER_REQUEST);
        }
+       mutex_unlock(&sta->ampdu_mlme.mtx);
 
        /* stopping might queue the work again - so cancel only afterwards */
        cancel_work_sync(&sta->ampdu_mlme.work);
index f75029a..2619daa 100644 (file)
@@ -1772,7 +1772,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                                 sizeof(void *));
                int txq_size = 0;
 
-               if (local->ops->wake_tx_queue)
+               if (local->ops->wake_tx_queue &&
+                   type != NL80211_IFTYPE_AP_VLAN &&
+                   type != NL80211_IFTYPE_MONITOR)
                        txq_size += sizeof(struct txq_info) +
                                    local->hw.txq_data_size;
 
index a550c70..7a76c4a 100644 (file)
@@ -675,8 +675,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
        enum nl80211_band band;
        u8 *pos;
        struct ieee80211_sub_if_data *sdata;
-       int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) +
-                     sizeof(mgmt->u.beacon);
+       int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
 
        sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
        rcu_read_lock();
index d8bbd0d..146ec6c 100644 (file)
@@ -111,8 +111,8 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
        struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
        u8 *pos, ie_len;
-       int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
-                     sizeof(mgmt->u.action.u.mesh_action);
+       int hdr_len = offsetofend(struct ieee80211_mgmt,
+                                 u.action.u.mesh_action);
 
        skb = dev_alloc_skb(local->tx_headroom +
                            hdr_len +
@@ -242,8 +242,8 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct ieee80211_mgmt *mgmt;
        u8 *pos, ie_len;
-       int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
-                     sizeof(mgmt->u.action.u.mesh_action);
+       int hdr_len = offsetofend(struct ieee80211_mgmt,
+                                 u.action.u.mesh_action);
 
        if (time_before(jiffies, ifmsh->next_perr))
                return -EAGAIN;
index f69c6c3..dc8e10f 100644 (file)
@@ -220,8 +220,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
        bool include_plid = false;
        u16 peering_proto = 0;
        u8 *pos, ie_len = 4;
-       int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
-                     sizeof(mgmt->u.action.u.self_prot);
+       int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot);
        int err = -ENOMEM;
 
        skb = dev_alloc_skb(local->tx_headroom +
index 3b8e270..ee5ca1b 100644 (file)
@@ -780,11 +780,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                        WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
                        WLAN_EID_HT_CAPABILITY,
                        WLAN_EID_BSS_COEX_2040,
+                       /* luckily this is almost always there */
                        WLAN_EID_EXT_CAPABILITY,
                        WLAN_EID_QOS_TRAFFIC_CAPA,
                        WLAN_EID_TIM_BCAST_REQ,
                        WLAN_EID_INTERWORKING,
-                       /* 60GHz doesn't happen right now */
+                       /* 60 GHz (Multi-band, DMG, MMS) can't happen */
                        WLAN_EID_VHT_CAPABILITY,
                        WLAN_EID_OPMODE_NOTIF,
                };
@@ -811,22 +812,16 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        /* if present, add any custom IEs that go before VHT */
        if (assoc_data->ie_len) {
                static const u8 before_vht[] = {
-                       WLAN_EID_SSID,
-                       WLAN_EID_SUPP_RATES,
-                       WLAN_EID_EXT_SUPP_RATES,
-                       WLAN_EID_PWR_CAPABILITY,
-                       WLAN_EID_SUPPORTED_CHANNELS,
-                       WLAN_EID_RSN,
-                       WLAN_EID_QOS_CAPA,
-                       WLAN_EID_RRM_ENABLED_CAPABILITIES,
-                       WLAN_EID_MOBILITY_DOMAIN,
-                       WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
-                       WLAN_EID_HT_CAPABILITY,
+                       /*
+                        * no need to list the ones split off before HT
+                        * or generated here
+                        */
                        WLAN_EID_BSS_COEX_2040,
                        WLAN_EID_EXT_CAPABILITY,
                        WLAN_EID_QOS_TRAFFIC_CAPA,
                        WLAN_EID_TIM_BCAST_REQ,
                        WLAN_EID_INTERWORKING,
+                       /* 60 GHz (Multi-band, DMG, MMS) can't happen */
                };
 
                /* RIC already taken above, so no need to handle here anymore */
index 47d2ed5..ef2beca 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
- * Copyright 2016  Intel Deutschland GmbH
+ * Copyright 2016-2017  Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -183,6 +183,20 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
        return bss;
 }
 
+static bool ieee80211_scan_accept_presp(struct ieee80211_sub_if_data *sdata,
+                                       u32 scan_flags, const u8 *da)
+{
+       if (!sdata)
+               return false;
+       /* accept broadcast for OCE */
+       if (scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP &&
+           is_broadcast_ether_addr(da))
+               return true;
+       if (scan_flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
+               return true;
+       return ether_addr_equal(da, sdata->vif.addr);
+}
+
 void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
 {
        struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
@@ -208,19 +222,24 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
        if (ieee80211_is_probe_resp(mgmt->frame_control)) {
                struct cfg80211_scan_request *scan_req;
                struct cfg80211_sched_scan_request *sched_scan_req;
+               u32 scan_req_flags = 0, sched_scan_req_flags = 0;
 
                scan_req = rcu_dereference(local->scan_req);
                sched_scan_req = rcu_dereference(local->sched_scan_req);
 
-               /* ignore ProbeResp to foreign address unless scanning
-                * with randomised address
+               if (scan_req)
+                       scan_req_flags = scan_req->flags;
+
+               if (sched_scan_req)
+                       sched_scan_req_flags = sched_scan_req->flags;
+
+               /* ignore ProbeResp to foreign address or non-bcast (OCE)
+                * unless scanning with randomised address
                 */
-               if (!(sdata1 &&
-                     (ether_addr_equal(mgmt->da, sdata1->vif.addr) ||
-                      scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) &&
-                   !(sdata2 &&
-                     (ether_addr_equal(mgmt->da, sdata2->vif.addr) ||
-                      sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)))
+               if (!ieee80211_scan_accept_presp(sdata1, scan_req_flags,
+                                                mgmt->da) &&
+                   !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags,
+                                                mgmt->da))
                        return;
 
                elements = mgmt->u.probe_resp.variable;
index 6961501..ffcd25c 100644 (file)
@@ -515,6 +515,31 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local,
        return err;
 }
 
+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);
+       }
+}
+
 /*
  * should be called with sta_mtx locked
  * this function replaces the mutex lock
@@ -561,6 +586,13 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
                goto out_remove;
 
        set_sta_flag(sta, WLAN_STA_INSERTED);
+
+       if (sta->sta_state >= IEEE80211_STA_ASSOC) {
+               ieee80211_recalc_min_chandef(sta->sdata);
+               if (!sta->sta.support_p2p_ps)
+                       ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
+       }
+
        /* accept BA sessions now */
        clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
 
@@ -1788,31 +1820,6 @@ 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)
 {
index 3acbdfa..a35c964 100644 (file)
@@ -398,7 +398,7 @@ struct ieee80211_sta_rx_stats {
        u64 msdu[IEEE80211_NUM_TIDS + 1];
 };
 
-/**
+/*
  * The bandwidth threshold below which the per-station CoDel parameters will be
  * scaled to be more lenient (to prevent starvation of slow stations). This
  * value will be scaled by the number of active stations when it is being
index 6aef679..d57e5f6 100644 (file)
@@ -1392,10 +1392,10 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
        /* insert custom IEs that go before HT */
        if (ie && ie_len) {
                static const u8 before_ht[] = {
-                       WLAN_EID_SSID,
-                       WLAN_EID_SUPP_RATES,
-                       WLAN_EID_REQUEST,
-                       WLAN_EID_EXT_SUPP_RATES,
+                       /*
+                        * no need to list the ones split off already
+                        * (or generated here)
+                        */
                        WLAN_EID_DS_PARAMS,
                        WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
                };
@@ -1424,20 +1424,17 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
        /* insert custom IEs that go before VHT */
        if (ie && ie_len) {
                static const u8 before_vht[] = {
-                       WLAN_EID_SSID,
-                       WLAN_EID_SUPP_RATES,
-                       WLAN_EID_REQUEST,
-                       WLAN_EID_EXT_SUPP_RATES,
-                       WLAN_EID_DS_PARAMS,
-                       WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
-                       WLAN_EID_HT_CAPABILITY,
+                       /*
+                        * no need to list the ones split off already
+                        * (or generated here)
+                        */
                        WLAN_EID_BSS_COEX_2040,
                        WLAN_EID_EXT_CAPABILITY,
                        WLAN_EID_SSID_LIST,
                        WLAN_EID_CHANNEL_USAGE,
                        WLAN_EID_INTERWORKING,
                        WLAN_EID_MESH_ID,
-                       /* 60 GHz can't happen here right now */
+                       /* 60 GHz (Multi-band, DMG, MMS) can't happen */
                };
                noffset = ieee80211_ie_split(ie, ie_len,
                                             before_vht, ARRAY_SIZE(before_vht),
@@ -2980,8 +2977,8 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_mgmt *mgmt;
        struct ieee80211_local *local = sdata->local;
        int freq;
-       int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) +
-                              sizeof(mgmt->u.action.u.chan_switch);
+       int hdr_len = offsetofend(struct ieee80211_mgmt,
+                                 u.action.u.chan_switch);
        u8 *pos;
 
        if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
index 19ec218..b9276ac 100644 (file)
@@ -386,6 +386,16 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
 
        bw = ieee80211_sta_cap_rx_bw(sta);
        bw = min(bw, sta->cur_max_bandwidth);
+
+       /* Don't consider AP's bandwidth for TDLS peers, section 11.23.1 of
+        * IEEE80211-2016 specification makes higher bandwidth operation
+        * possible on the TDLS link if the peers have wider bandwidth
+        * capability.
+        */
+       if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
+           test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW))
+               return bw;
+
        bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
 
        return bw;
index 6e80932..35165f4 100644 (file)
@@ -216,6 +216,7 @@ enum cfg80211_event_type {
        EVENT_DISCONNECTED,
        EVENT_IBSS_JOINED,
        EVENT_STOPPED,
+       EVENT_PORT_AUTHORIZED,
 };
 
 struct cfg80211_event {
@@ -235,6 +236,9 @@ struct cfg80211_event {
                        u8 bssid[ETH_ALEN];
                        struct ieee80211_channel *channel;
                } ij;
+               struct {
+                       u8 bssid[ETH_ALEN];
+               } pa;
        };
 };
 
@@ -385,6 +389,7 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                        bool wextev);
 void __cfg80211_roamed(struct wireless_dev *wdev,
                       struct cfg80211_roam_info *info);
+void __cfg80211_port_authorized(struct wireless_dev *wdev, const u8 *bssid);
 int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
                              struct wireless_dev *wdev);
 void cfg80211_autodisconnect_wk(struct work_struct *work);
index 6908742..5129342 100644 (file)
@@ -2122,6 +2122,15 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
                case NL80211_CHAN_HT40MINUS:
                        cfg80211_chandef_create(chandef, chandef->chan,
                                                chantype);
+                       /* user input for center_freq is incorrect */
+                       if (info->attrs[NL80211_ATTR_CENTER_FREQ1] &&
+                           chandef->center_freq1 != nla_get_u32(
+                                       info->attrs[NL80211_ATTR_CENTER_FREQ1]))
+                               return -EINVAL;
+                       /* center_freq2 must be zero */
+                       if (info->attrs[NL80211_ATTR_CENTER_FREQ2] &&
+                           nla_get_u32(info->attrs[NL80211_ATTR_CENTER_FREQ2]))
+                               return -EINVAL;
                        break;
                default:
                        return -EINVAL;
@@ -6610,6 +6619,77 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
        return regulatory_pre_cac_allowed(wdev->wiphy);
 }
 
+static int
+nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
+                        void *request, struct nlattr **attrs,
+                        bool is_sched_scan)
+{
+       u8 *mac_addr, *mac_addr_mask;
+       u32 *flags;
+       enum nl80211_feature_flags randomness_flag;
+
+       if (!attrs[NL80211_ATTR_SCAN_FLAGS])
+               return 0;
+
+       if (is_sched_scan) {
+               struct cfg80211_sched_scan_request *req = request;
+
+               randomness_flag = wdev ?
+                                 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
+                                 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
+               flags = &req->flags;
+               mac_addr = req->mac_addr;
+               mac_addr_mask = req->mac_addr_mask;
+       } else {
+               struct cfg80211_scan_request *req = request;
+
+               randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+               flags = &req->flags;
+               mac_addr = req->mac_addr;
+               mac_addr_mask = req->mac_addr_mask;
+       }
+
+       *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
+
+       if ((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+           !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN))
+               return -EOPNOTSUPP;
+
+       if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+               int err;
+
+               if (!(wiphy->features & randomness_flag) ||
+                   (wdev && wdev->current_bss))
+                       return -EOPNOTSUPP;
+
+               err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
+               if (err)
+                       return err;
+       }
+
+       if ((*flags & NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME) &&
+           !wiphy_ext_feature_isset(wiphy,
+                                    NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME))
+               return -EOPNOTSUPP;
+
+       if ((*flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP) &&
+          !wiphy_ext_feature_isset(wiphy,
+                                   NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP))
+               return -EOPNOTSUPP;
+
+       if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) &&
+           !wiphy_ext_feature_isset(wiphy,
+                                    NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION))
+               return -EOPNOTSUPP;
+
+       if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE) &&
+           !wiphy_ext_feature_isset(wiphy,
+                                    NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE))
+               return -EOPNOTSUPP;
+
+       return 0;
+}
+
 static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6815,34 +6895,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                        nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
        }
 
-       if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
-               request->flags = nla_get_u32(
-                       info->attrs[NL80211_ATTR_SCAN_FLAGS]);
-               if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
-                   !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
-                       err = -EOPNOTSUPP;
-                       goto out_free;
-               }
-
-               if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
-                       if (!(wiphy->features &
-                                       NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR)) {
-                               err = -EOPNOTSUPP;
-                               goto out_free;
-                       }
-
-                       if (wdev->current_bss) {
-                               err = -EOPNOTSUPP;
-                               goto out_free;
-                       }
-
-                       err = nl80211_parse_random_mac(info->attrs,
-                                                      request->mac_addr,
-                                                      request->mac_addr_mask);
-                       if (err)
-                               goto out_free;
-               }
-       }
+       err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
+                                      false);
+       if (err)
+               goto out_free;
 
        request->no_cck =
                nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
@@ -7290,37 +7346,9 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                       request->ie_len);
        }
 
-       if (attrs[NL80211_ATTR_SCAN_FLAGS]) {
-               request->flags = nla_get_u32(
-                       attrs[NL80211_ATTR_SCAN_FLAGS]);
-               if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
-                   !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
-                       err = -EOPNOTSUPP;
-                       goto out_free;
-               }
-
-               if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
-                       u32 flg = NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
-
-                       if (!wdev) /* must be net-detect */
-                               flg = NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
-
-                       if (!(wiphy->features & flg)) {
-                               err = -EOPNOTSUPP;
-                               goto out_free;
-                       }
-
-                       if (wdev && wdev->current_bss) {
-                               err = -EOPNOTSUPP;
-                               goto out_free;
-                       }
-
-                       err = nl80211_parse_random_mac(attrs, request->mac_addr,
-                                                      request->mac_addr_mask);
-                       if (err)
-                               goto out_free;
-               }
-       }
+       err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
+       if (err)
+               goto out_free;
 
        if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
                request->delay =
@@ -8924,8 +8952,14 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 
        if (info->attrs[NL80211_ATTR_USE_MFP]) {
                connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
+               if (connect.mfp == NL80211_MFP_OPTIONAL &&
+                   !wiphy_ext_feature_isset(&rdev->wiphy,
+                                            NL80211_EXT_FEATURE_MFP_OPTIONAL))
+                       return -EOPNOTSUPP;
+
                if (connect.mfp != NL80211_MFP_REQUIRED &&
-                   connect.mfp != NL80211_MFP_NO)
+                   connect.mfp != NL80211_MFP_NO &&
+                   connect.mfp != NL80211_MFP_OPTIONAL)
                        return -EINVAL;
        } else {
                connect.mfp = NL80211_MFP_NO;
@@ -13802,9 +13836,7 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
                     info->req_ie)) ||
            (info->resp_ie &&
             nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
-                    info->resp_ie)) ||
-           (info->authorized &&
-            nla_put_flag(msg, NL80211_ATTR_PORT_AUTHORIZED)))
+                    info->resp_ie)))
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
@@ -13818,6 +13850,36 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
        nlmsg_free(msg);
 }
 
+void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
+                                 struct net_device *netdev, const u8 *bssid)
+{
+       struct sk_buff *msg;
+       void *hdr;
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
+               return;
+
+       hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
+       if (!hdr) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
+               goto nla_put_failure;
+
+       genlmsg_end(msg, hdr);
+
+       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+                               NL80211_MCGRP_MLME, GFP_KERNEL);
+       return;
+
+ nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+       nlmsg_free(msg);
+}
+
 void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
                               struct net_device *netdev, u16 reason,
                               const u8 *ie, size_t ie_len, bool from_ap)
index b969333..bf9e772 100644 (file)
@@ -58,6 +58,8 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
 void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
                         struct net_device *netdev,
                         struct cfg80211_roam_info *info, gfp_t gfp);
+void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
+                                 struct net_device *netdev, const u8 *bssid);
 void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
                               struct net_device *netdev, u16 reason,
                               const u8 *ie, size_t ie_len, bool from_ap);
index 0a49b88..f38ed49 100644 (file)
@@ -960,7 +960,6 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
        ev->rm.resp_ie_len = info->resp_ie_len;
        memcpy((void *)ev->rm.resp_ie, info->resp_ie, info->resp_ie_len);
        ev->rm.bss = info->bss;
-       ev->rm.authorized = info->authorized;
 
        spin_lock_irqsave(&wdev->event_lock, flags);
        list_add_tail(&ev->list, &wdev->event_list);
@@ -969,6 +968,50 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
 }
 EXPORT_SYMBOL(cfg80211_roamed);
 
+void __cfg80211_port_authorized(struct wireless_dev *wdev, const u8 *bssid)
+{
+       ASSERT_WDEV_LOCK(wdev);
+
+       if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+               return;
+
+       if (WARN_ON(!wdev->current_bss) ||
+           WARN_ON(!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
+               return;
+
+       nl80211_send_port_authorized(wiphy_to_rdev(wdev->wiphy), wdev->netdev,
+                                    bssid);
+}
+
+void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid,
+                             gfp_t gfp)
+{
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+       struct cfg80211_event *ev;
+       unsigned long flags;
+
+       if (WARN_ON(!bssid))
+               return;
+
+       ev = kzalloc(sizeof(*ev), gfp);
+       if (!ev)
+               return;
+
+       ev->type = EVENT_PORT_AUTHORIZED;
+       memcpy(ev->pa.bssid, bssid, ETH_ALEN);
+
+       /*
+        * Use the wdev event list so that if there are pending
+        * connected/roamed events, they will be reported first.
+        */
+       spin_lock_irqsave(&wdev->event_lock, flags);
+       list_add_tail(&ev->list, &wdev->event_list);
+       spin_unlock_irqrestore(&wdev->event_lock, flags);
+       queue_work(cfg80211_wq, &rdev->event_work);
+}
+EXPORT_SYMBOL(cfg80211_port_authorized);
+
 void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
                             size_t ie_len, u16 reason, bool from_ap)
 {
index bcb1284..ff21c31 100644 (file)
@@ -157,32 +157,30 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
        case NL80211_BAND_2GHZ:
                want = 7;
                for (i = 0; i < sband->n_bitrates; i++) {
-                       if (sband->bitrates[i].bitrate == 10) {
+                       switch (sband->bitrates[i].bitrate) {
+                       case 10:
+                       case 20:
+                       case 55:
+                       case 110:
                                sband->bitrates[i].flags |=
                                        IEEE80211_RATE_MANDATORY_B |
                                        IEEE80211_RATE_MANDATORY_G;
                                want--;
-                       }
-
-                       if (sband->bitrates[i].bitrate == 20 ||
-                           sband->bitrates[i].bitrate == 55 ||
-                           sband->bitrates[i].bitrate == 110 ||
-                           sband->bitrates[i].bitrate == 60 ||
-                           sband->bitrates[i].bitrate == 120 ||
-                           sband->bitrates[i].bitrate == 240) {
+                               break;
+                       case 60:
+                       case 120:
+                       case 240:
                                sband->bitrates[i].flags |=
                                        IEEE80211_RATE_MANDATORY_G;
                                want--;
-                       }
-
-                       if (sband->bitrates[i].bitrate != 10 &&
-                           sband->bitrates[i].bitrate != 20 &&
-                           sband->bitrates[i].bitrate != 55 &&
-                           sband->bitrates[i].bitrate != 110)
+                               /* fall through */
+                       default:
                                sband->bitrates[i].flags |=
                                        IEEE80211_RATE_ERP_G;
+                               break;
+                       }
                }
-               WARN_ON(want != 0 && want != 3 && want != 6);
+               WARN_ON(want != 0 && want != 3);
                break;
        case NL80211_BAND_60GHZ:
                /* check for mandatory HT MCS 1..4 */
@@ -529,121 +527,6 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
 }
 EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr);
 
-int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
-                            enum nl80211_iftype iftype,
-                            const u8 *bssid, bool qos)
-{
-       struct ieee80211_hdr hdr;
-       u16 hdrlen, ethertype;
-       __le16 fc;
-       const u8 *encaps_data;
-       int encaps_len, skip_header_bytes;
-       int nh_pos, h_pos;
-       int head_need;
-
-       if (unlikely(skb->len < ETH_HLEN))
-               return -EINVAL;
-
-       nh_pos = skb_network_header(skb) - skb->data;
-       h_pos = skb_transport_header(skb) - skb->data;
-
-       /* convert Ethernet header to proper 802.11 header (based on
-        * operation mode) */
-       ethertype = (skb->data[12] << 8) | skb->data[13];
-       fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
-
-       switch (iftype) {
-       case NL80211_IFTYPE_AP:
-       case NL80211_IFTYPE_AP_VLAN:
-       case NL80211_IFTYPE_P2P_GO:
-               fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
-               /* DA BSSID SA */
-               memcpy(hdr.addr1, skb->data, ETH_ALEN);
-               memcpy(hdr.addr2, addr, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
-               hdrlen = 24;
-               break;
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_P2P_CLIENT:
-               fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
-               /* BSSID SA DA */
-               memcpy(hdr.addr1, bssid, ETH_ALEN);
-               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data, ETH_ALEN);
-               hdrlen = 24;
-               break;
-       case NL80211_IFTYPE_OCB:
-       case NL80211_IFTYPE_ADHOC:
-               /* DA SA BSSID */
-               memcpy(hdr.addr1, skb->data, ETH_ALEN);
-               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-               memcpy(hdr.addr3, bssid, ETH_ALEN);
-               hdrlen = 24;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       if (qos) {
-               fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
-               hdrlen += 2;
-       }
-
-       hdr.frame_control = fc;
-       hdr.duration_id = 0;
-       hdr.seq_ctrl = 0;
-
-       skip_header_bytes = ETH_HLEN;
-       if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
-               encaps_data = bridge_tunnel_header;
-               encaps_len = sizeof(bridge_tunnel_header);
-               skip_header_bytes -= 2;
-       } else if (ethertype >= ETH_P_802_3_MIN) {
-               encaps_data = rfc1042_header;
-               encaps_len = sizeof(rfc1042_header);
-               skip_header_bytes -= 2;
-       } else {
-               encaps_data = NULL;
-               encaps_len = 0;
-       }
-
-       skb_pull(skb, skip_header_bytes);
-       nh_pos -= skip_header_bytes;
-       h_pos -= skip_header_bytes;
-
-       head_need = hdrlen + encaps_len - skb_headroom(skb);
-
-       if (head_need > 0 || skb_cloned(skb)) {
-               head_need = max(head_need, 0);
-               if (head_need)
-                       skb_orphan(skb);
-
-               if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC))
-                       return -ENOMEM;
-       }
-
-       if (encaps_data) {
-               memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
-               nh_pos += encaps_len;
-               h_pos += encaps_len;
-       }
-
-       memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
-
-       nh_pos += hdrlen;
-       h_pos += hdrlen;
-
-       /* Update skb pointers to various headers since this modified frame
-        * is going to go through Linux networking code that may potentially
-        * need things like pointer to IP header. */
-       skb_reset_mac_header(skb);
-       skb_set_network_header(skb, nh_pos);
-       skb_set_transport_header(skb, h_pos);
-
-       return 0;
-}
-EXPORT_SYMBOL(ieee80211_data_from_8023);
-
 static void
 __frame_add_frag(struct sk_buff *skb, struct page *page,
                 void *ptr, int len, int size)
@@ -963,6 +846,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
                case EVENT_STOPPED:
                        __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev);
                        break;
+               case EVENT_PORT_AUTHORIZED:
+                       __cfg80211_port_authorized(wdev, ev->pa.bssid);
+                       break;
                }
                wdev_unlock(wdev);
 
@@ -1367,13 +1253,29 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
 }
 EXPORT_SYMBOL(cfg80211_get_p2p_attr);
 
-static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
+static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id, bool id_ext)
 {
        int i;
 
-       for (i = 0; i < n_ids; i++)
-               if (ids[i] == id)
+       /* Make sure array values are legal */
+       if (WARN_ON(ids[n_ids - 1] == WLAN_EID_EXTENSION))
+               return false;
+
+       i = 0;
+       while (i < n_ids) {
+               if (ids[i] == WLAN_EID_EXTENSION) {
+                       if (id_ext && (ids[i + 1] == id))
+                               return true;
+
+                       i += 2;
+                       continue;
+               }
+
+               if (ids[i] == id && !id_ext)
                        return true;
+
+               i++;
+       }
        return false;
 }
 
@@ -1403,14 +1305,36 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
 {
        size_t pos = offset;
 
-       while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
+       while (pos < ielen) {
+               u8 ext = 0;
+
+               if (ies[pos] == WLAN_EID_EXTENSION)
+                       ext = 2;
+               if ((pos + ext) >= ielen)
+                       break;
+
+               if (!ieee80211_id_in_list(ids, n_ids, ies[pos + ext],
+                                         ies[pos] == WLAN_EID_EXTENSION))
+                       break;
+
                if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
                        pos = skip_ie(ies, ielen, pos);
 
-                       while (pos < ielen &&
-                              !ieee80211_id_in_list(after_ric, n_after_ric,
-                                                    ies[pos]))
-                               pos = skip_ie(ies, ielen, pos);
+                       while (pos < ielen) {
+                               if (ies[pos] == WLAN_EID_EXTENSION)
+                                       ext = 2;
+                               else
+                                       ext = 0;
+
+                               if ((pos + ext) >= ielen)
+                                       break;
+
+                               if (!ieee80211_id_in_list(after_ric,
+                                                         n_after_ric,
+                                                         ies[pos + ext],
+                                                         ext == 2))
+                                       pos = skip_ie(ies, ielen, pos);
+                       }
                } else {
                        pos = skip_ie(ies, ielen, pos);
                }