]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'mac80211-next-for-john-2014-08-29' of git://git.kernel.org/pub/scm/linux...
authorJohn W. Linville <linville@tuxdriver.com>
Thu, 4 Sep 2014 17:41:33 +0000 (13:41 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 4 Sep 2014 17:41:33 +0000 (13:41 -0400)
Johannes Berg <johannes@sipsolutions.net> says:

"Not that much content this time. Some RCU cleanups, crypto
performance improvements, and various patches all over,
rather than listing them one might as well look into the
git log instead."

Signed-off-by: John W. Linville <linville@tuxdriver.com>
Conflicts:
drivers/net/wireless/ath/wil6210/wmi.c

39 files changed:
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/wil6210/wmi.c
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/orinoco/scan.c
drivers/net/wireless/rndis_wlan.c
drivers/staging/rtl8723au/core/rtw_mlme_ext.c
drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
drivers/staging/wlan-ng/cfg80211.c
include/linux/ieee80211.h
include/net/cfg80211.h
include/net/mac80211.h
include/uapi/linux/nl80211.h
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/debugfs_sta.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/key.c
net/mac80211/mesh_pathtbl.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tdls.c
net/mac80211/tx.c
net/mac80211/wme.c
net/rfkill/rfkill-gpio.c
net/wireless/core.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/scan.c

index e535807c3d8912863da3604dc9e698ee664f0a48..ba60e37213eb1d289fa983e8eacbce48c1616b0a 100644 (file)
@@ -717,6 +717,7 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,
                memcpy(ie + 2, vif->ssid, vif->ssid_len);
                memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len);
                bss = cfg80211_inform_bss(ar->wiphy, chan,
+                                         CFG80211_BSS_FTYPE_UNKNOWN,
                                          bssid, 0, cap_val, 100,
                                          ie, 2 + vif->ssid_len + beacon_ie_len,
                                          0, GFP_KERNEL);
index 94df345d08c24210fefe4b707079f85fe75e386f..b921005ad7eef7bb9ab25dedadf6c50f7ad85d26 100644 (file)
@@ -619,8 +619,7 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
                   dlen, freq, vif->probe_req_report);
 
        if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
-               cfg80211_rx_mgmt(&vif->wdev, freq, 0, ev->data, dlen, 0,
-                                GFP_ATOMIC);
+               cfg80211_rx_mgmt(&vif->wdev, freq, 0, ev->data, dlen, 0);
 
        return 0;
 }
@@ -659,7 +658,7 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
                return -EINVAL;
        }
        ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
-       cfg80211_rx_mgmt(&vif->wdev, freq, 0, ev->data, dlen, 0, GFP_ATOMIC);
+       cfg80211_rx_mgmt(&vif->wdev, freq, 0, ev->data, dlen, 0);
 
        return 0;
 }
@@ -1093,7 +1092,6 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
        u8 *buf;
        struct ieee80211_channel *channel;
        struct ath6kl *ar = wmi->parent_dev;
-       struct ieee80211_mgmt *mgmt;
        struct cfg80211_bss *bss;
 
        if (len <= sizeof(struct wmi_bss_info_hdr2))
@@ -1139,39 +1137,15 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
                }
        }
 
-       /*
-        * In theory, use of cfg80211_inform_bss() would be more natural here
-        * since we do not have the full frame. However, at least for now,
-        * cfg80211 can only distinguish Beacon and Probe Response frames from
-        * each other when using cfg80211_inform_bss_frame(), so let's build a
-        * fake IEEE 802.11 header to be able to take benefit of this.
-        */
-       mgmt = kmalloc(24 + len, GFP_ATOMIC);
-       if (mgmt == NULL)
-               return -EINVAL;
-
-       if (bih->frame_type == BEACON_FTYPE) {
-               mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-                                                 IEEE80211_STYPE_BEACON);
-               memset(mgmt->da, 0xff, ETH_ALEN);
-       } else {
-               struct net_device *dev = vif->ndev;
-
-               mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-                                                 IEEE80211_STYPE_PROBE_RESP);
-               memcpy(mgmt->da, dev->dev_addr, ETH_ALEN);
-       }
-       mgmt->duration = cpu_to_le16(0);
-       memcpy(mgmt->sa, bih->bssid, ETH_ALEN);
-       memcpy(mgmt->bssid, bih->bssid, ETH_ALEN);
-       mgmt->seq_ctrl = cpu_to_le16(0);
-
-       memcpy(&mgmt->u.beacon, buf, len);
-
-       bss = cfg80211_inform_bss_frame(ar->wiphy, channel, mgmt,
-                                       24 + len, (bih->snr - 95) * 100,
-                                       GFP_ATOMIC);
-       kfree(mgmt);
+       bss = cfg80211_inform_bss(ar->wiphy, channel,
+                                 bih->frame_type == BEACON_FTYPE ?
+                                       CFG80211_BSS_FTYPE_BEACON :
+                                       CFG80211_BSS_FTYPE_PRESP,
+                                 bih->bssid, get_unaligned_le64((__le64 *)buf),
+                                 get_unaligned_le16(((__le16 *)buf) + 5),
+                                 get_unaligned_le16(((__le16 *)buf) + 4),
+                                 buf + 8 + 2 + 2, len - 8 - 2 - 2,
+                                 (bih->snr - 95) * 100, GFP_ATOMIC);
        if (bss == NULL)
                return -ENOMEM;
        cfg80211_put_bss(ar->wiphy, bss);
index 1b64823544ebc9d10a0d4a052849d7aa0510832d..b1aaaee997d515c92beb08e14ac8bcb611547cc6 100644 (file)
@@ -351,11 +351,11 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
                                    rx_mgmt_frame->bssid);
                        cfg80211_put_bss(wiphy, bss);
                } else {
-                       wil_err(wil, "cfg80211_inform_bss() failed\n");
+                       wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
                }
        } else {
                cfg80211_rx_mgmt(wil->wdev, freq, signal,
-                                (void *)rx_mgmt_frame, d_len, 0, GFP_ATOMIC);
+                                (void *)rx_mgmt_frame, d_len, 0);
        }
 }
 
index 057b982ea8b37f90792fc53ca9337a9f13897e32..1d78a91db59428a137bb829cbd3203bac69fea36 100644 (file)
@@ -1431,8 +1431,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
                                              IEEE80211_BAND_5GHZ);
 
        wdev = &ifp->vif->wdev;
-       cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, 0,
-                        GFP_ATOMIC);
+       cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, 0);
 
        kfree(mgmt_frame);
        return 0;
@@ -1896,8 +1895,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
                                              IEEE80211_BAND_2GHZ :
                                              IEEE80211_BAND_5GHZ);
 
-       cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, 0,
-                        GFP_ATOMIC);
+       cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
 
        brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n",
                  mgmt_frame_len, e->datalen, chanspec, freq);
index 02fe706fc9ec8cbeed88baacc377c33e6892dd6d..12a60ca1462a24106fe2da3b9629b3ab91201ccb 100644 (file)
@@ -2394,9 +2394,13 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
        brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);
        brcmf_dbg(CONN, "Signal: %d\n", notify_signal);
 
-       bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
-               0, notify_capability, notify_interval, notify_ie,
-               notify_ielen, notify_signal, GFP_KERNEL);
+       bss = cfg80211_inform_bss(wiphy, notify_channel,
+                                 CFG80211_BSS_FTYPE_UNKNOWN,
+                                 (const u8 *)bi->BSSID,
+                                 0, notify_capability,
+                                 notify_interval, notify_ie,
+                                 notify_ielen, notify_signal,
+                                 GFP_KERNEL);
 
        if (!bss)
                return -ENOMEM;
@@ -2498,9 +2502,11 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
        brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
        brcmf_dbg(CONN, "signal: %d\n", notify_signal);
 
-       bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
-               0, notify_capability, notify_interval,
-               notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
+       bss = cfg80211_inform_bss(wiphy, notify_channel,
+                                 CFG80211_BSS_FTYPE_UNKNOWN, bssid, 0,
+                                 notify_capability, notify_interval,
+                                 notify_ie, notify_ielen, notify_signal,
+                                 GFP_KERNEL);
 
        if (!bss) {
                err = -ENOMEM;
index 47a998d8f99e75bd5f59521a6593ca183cebb77a..22884ba7d6ccdab5c316fd1c4ed895716a628ca2 100644 (file)
@@ -653,6 +653,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                        if (channel &&
                            !(channel->flags & IEEE80211_CHAN_DISABLED)) {
                                bss = cfg80211_inform_bss(wiphy, channel,
+                                       CFG80211_BSS_FTYPE_UNKNOWN,
                                        bssid, get_unaligned_le64(tsfdesc),
                                        capa, intvl, ie, ielen,
                                        LBS_SCAN_RSSI_TO_MBM(rssi),
@@ -1754,6 +1755,7 @@ static void lbs_join_post(struct lbs_private *priv,
 
        bss = cfg80211_inform_bss(priv->wdev->wiphy,
                                  params->chandef.chan,
+                                 CFG80211_BSS_FTYPE_UNKNOWN,
                                  bssid,
                                  0,
                                  capability,
index 2856f0ecb8fc98f1906b0e4913ede484bebe981b..c4723b0f5757eba4f1db0b6b3f98bf9f82e38a4a 100644 (file)
@@ -1557,6 +1557,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
                                                       band));
 
        bss = cfg80211_inform_bss(priv->wdev->wiphy, chan,
+                                 CFG80211_BSS_FTYPE_UNKNOWN,
                                  bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
                                  0, ie_buf, ie_len, 0, GFP_KERNEL);
        cfg80211_put_bss(priv->wdev->wiphy, bss);
index dee717a19ddb560956175c43789b2c802f029554..195ef0ca343f1f451f4c039259f64fde5f0f86b1 100644 (file)
@@ -1719,7 +1719,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
 
                if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
                        bss = cfg80211_inform_bss(priv->wdev->wiphy,
-                                           chan, bssid, timestamp,
+                                           chan, CFG80211_BSS_FTYPE_UNKNOWN,
+                                           bssid, timestamp,
                                            cap_info_bitmap, beacon_period,
                                            ie_buf, ie_len, rssi, GFP_KERNEL);
                        bss_priv = (struct mwifiex_bss_priv *)bss->priv;
index cee028321a9ab73eac65ced1048e21fed2ce8e7e..ec79c49de0975651a5e2cdebdd058fc312308537 100644 (file)
@@ -172,7 +172,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
 
        cfg80211_rx_mgmt(priv->wdev, priv->roc_cfg.chan.center_freq,
                         CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len,
-                        0, GFP_ATOMIC);
+                        0);
 
        return 0;
 }
index e175b9b8561b594299d69d237624e3604932d22f..2c66166add705ca64b0390cfe4602d2d15c70fdd 100644 (file)
@@ -123,9 +123,10 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv,
        beacon_interval = le16_to_cpu(bss->a.beacon_interv);
        signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level));
 
-       cbss = cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp,
-                                  capability, beacon_interval, ie_buf, ie_len,
-                                  signal, GFP_KERNEL);
+       cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
+                                  bss->a.bssid, timestamp, capability,
+                                  beacon_interval, ie_buf, ie_len, signal,
+                                  GFP_KERNEL);
        cfg80211_put_bss(wiphy, cbss);
 }
 
@@ -156,9 +157,10 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
        ie = bss->data;
        signal = SIGNAL_TO_MBM(bss->level);
 
-       cbss = cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp,
-                                  capability, beacon_interval, ie, ie_len,
-                                  signal, GFP_KERNEL);
+       cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
+                                  bss->bssid, timestamp, capability,
+                                  beacon_interval, ie, ie_len, signal,
+                                  GFP_KERNEL);
        cfg80211_put_bss(wiphy, cbss);
 }
 
index d2a9a08210be1379b4e56ad266c1695ca6486d17..1a4facd1fbf335625ff092064b3dfa58f4e869d1 100644 (file)
@@ -2022,9 +2022,10 @@ static bool rndis_bss_info_update(struct usbnet *usbdev,
        capability = le16_to_cpu(fixed->capabilities);
        beacon_interval = le16_to_cpu(fixed->beacon_interval);
 
-       bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac,
-               timestamp, capability, beacon_interval, ie, ie_len, signal,
-               GFP_KERNEL);
+       bss = cfg80211_inform_bss(priv->wdev.wiphy, channel,
+                                 CFG80211_BSS_FTYPE_UNKNOWN, bssid->mac,
+                                 timestamp, capability, beacon_interval,
+                                 ie, ie_len, signal, GFP_KERNEL);
        cfg80211_put_bss(priv->wdev.wiphy, bss);
 
        return (bss != NULL);
@@ -2711,9 +2712,10 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
                bssid, (u32)timestamp, capability, beacon_period, ie_len,
                ssid.essid, signal);
 
-       bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid,
-               timestamp, capability, beacon_period, ie_buf, ie_len,
-               signal, GFP_KERNEL);
+       bss = cfg80211_inform_bss(priv->wdev.wiphy, channel,
+                                 CFG80211_BSS_FTYPE_UNKNOWN, bssid,
+                                 timestamp, capability, beacon_period,
+                                 ie_buf, ie_len, signal, GFP_KERNEL);
        cfg80211_put_bss(priv->wdev.wiphy, bss);
 }
 
index c5fdcb89dacd0b3a11054e98785c2336f94a87d0..2a1502f351f8f1d9ceb8e01ff8add8557a2757cb 100644 (file)
@@ -2128,7 +2128,7 @@ static int on_action_public23a(struct rtw_adapter *padapter,
                                                      IEEE80211_BAND_5GHZ);
 
        if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
-                            skb->len, 0, GFP_ATOMIC))
+                            skb->len, 0))
                return _SUCCESS;
 
        return _FAIL;
index 93dc844a10b35dcebaf05b8c94d53c66715d0e88..8b0ccb5c5fc4fb4d7b095f1fe8d05174c6cc8cf4 100644 (file)
@@ -279,6 +279,7 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
        }
 
        bss = cfg80211_inform_bss(wiphy, notify_channel,
+                                 CFG80211_BSS_FTYPE_UNKNOWN,
                                  pnetwork->network.MacAddress,
                                  pnetwork->network.tsf,
                                  pnetwork->network.capability,
@@ -2379,7 +2380,7 @@ void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
                                                      IEEE80211_BAND_5GHZ);
 
        cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len,
-                        0, GFP_ATOMIC);
+                        0);
 #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
 }
 
@@ -2425,7 +2426,7 @@ void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
        frame_len = sizeof(struct ieee80211_hdr_3addr) + 2;
 
        cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len,
-                        0, GFP_ATOMIC);
+                        0);
 #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
 }
 
index 3727f6d25cf1af074ce35f1336453e6b7312a965..8942dcb44180339ffb9cd6318a3b29d3aef06241 100644 (file)
@@ -422,6 +422,7 @@ static int prism2_scan(struct wiphy *wiphy,
                                                      IEEE80211_BAND_2GHZ);
                bss = cfg80211_inform_bss(wiphy,
                        ieee80211_get_channel(wiphy, freq),
+                       CFG80211_BSS_FTYPE_UNKNOWN,
                        (const u8 *) &(msg2.bssid.data.data),
                        msg2.timestamp.data, msg2.capinfo.data,
                        msg2.beaconperiod.data,
index 63ab3873c5ed00ac6fa36e73892d4db709c13bf0..8018c915ee632d90b5076b49325d59760de3ab34 100644 (file)
@@ -838,6 +838,16 @@ enum ieee80211_vht_opmode_bits {
 
 #define WLAN_SA_QUERY_TR_ID_LEN 2
 
+/**
+ * struct ieee80211_tpc_report_ie
+ *
+ * This structure refers to "TPC Report element"
+ */
+struct ieee80211_tpc_report_ie {
+       u8 tx_power;
+       u8 link_margin;
+} __packed;
+
 struct ieee80211_mgmt {
        __le16 frame_control;
        __le16 duration;
@@ -973,6 +983,13 @@ struct ieee80211_mgmt {
                                        u8 action_code;
                                        u8 operating_mode;
                                } __packed vht_opmode_notif;
+                               struct {
+                                       u8 action_code;
+                                       u8 dialog_token;
+                                       u8 tpc_elem_id;
+                                       u8 tpc_elem_length;
+                                       struct ieee80211_tpc_report_ie tpc;
+                               } __packed tpc_report;
                        } u;
                } __packed action;
        } u;
@@ -1865,6 +1882,7 @@ enum ieee80211_category {
        WLAN_CATEGORY_DLS = 2,
        WLAN_CATEGORY_BACK = 3,
        WLAN_CATEGORY_PUBLIC = 4,
+       WLAN_CATEGORY_RADIO_MEASUREMENT = 5,
        WLAN_CATEGORY_HT = 7,
        WLAN_CATEGORY_SA_QUERY = 8,
        WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9,
@@ -2378,4 +2396,51 @@ static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim,
 #define TU_TO_JIFFIES(x)       (usecs_to_jiffies((x) * 1024))
 #define TU_TO_EXP_TIME(x)      (jiffies + TU_TO_JIFFIES(x))
 
+/**
+ * ieee80211_action_contains_tpc - checks if the frame contains TPC element
+ * @skb: the skb containing the frame, length will be checked
+ *
+ * This function checks if it's either TPC report action frame or Link
+ * Measurement report action frame as defined in IEEE Std. 802.11-2012 8.5.2.5
+ * and 8.5.7.5 accordingly.
+ */
+static inline bool ieee80211_action_contains_tpc(struct sk_buff *skb)
+{
+       struct ieee80211_mgmt *mgmt = (void *)skb->data;
+
+       if (!ieee80211_is_action(mgmt->frame_control))
+               return false;
+
+       if (skb->len < IEEE80211_MIN_ACTION_SIZE +
+                      sizeof(mgmt->u.action.u.tpc_report))
+               return false;
+
+       /*
+        * TPC report - check that:
+        * category = 0 (Spectrum Management) or 5 (Radio Measurement)
+        * spectrum management action = 3 (TPC/Link Measurement report)
+        * TPC report EID = 35
+        * TPC report element length = 2
+        *
+        * The spectrum management's tpc_report struct is used here both for
+        * parsing tpc_report and radio measurement's link measurement report
+        * frame, since the relevant part is identical in both frames.
+        */
+       if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT &&
+           mgmt->u.action.category != WLAN_CATEGORY_RADIO_MEASUREMENT)
+               return false;
+
+       /* both spectrum mgmt and link measurement have same action code */
+       if (mgmt->u.action.u.tpc_report.action_code !=
+           WLAN_ACTION_SPCT_TPC_RPRT)
+               return false;
+
+       if (mgmt->u.action.u.tpc_report.tpc_elem_id != WLAN_EID_TPC_REPORT ||
+           mgmt->u.action.u.tpc_report.tpc_elem_length !=
+           sizeof(struct ieee80211_tpc_report_ie))
+               return false;
+
+       return true;
+}
+
 #endif /* LINUX_IEEE80211_H */
index 0a080c4de2754d0b9fc64ecf54e8dc4bcb477cf3..ab21299c8f4dfc13a50a9f23043b19df25f87a69 100644 (file)
@@ -1503,12 +1503,14 @@ enum cfg80211_signal_type {
  * @tsf: TSF contained in the frame that carried these IEs
  * @rcu_head: internal use, for freeing
  * @len: length of the IEs
+ * @from_beacon: these IEs are known to come from a beacon
  * @data: IE data
  */
 struct cfg80211_bss_ies {
        u64 tsf;
        struct rcu_head rcu_head;
        int len;
+       bool from_beacon;
        u8 data[];
 };
 
@@ -3765,11 +3767,25 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
 }
 
 /**
- * cfg80211_inform_bss - inform cfg80211 of a new BSS
+ * enum cfg80211_bss_frame_type - frame type that the BSS data came from
+ * @CFG80211_BSS_FTYPE_UNKNOWN: driver doesn't know whether the data is
+ *     from a beacon or probe response
+ * @CFG80211_BSS_FTYPE_BEACON: data comes from a beacon
+ * @CFG80211_BSS_FTYPE_PRESP: data comes from a probe response
+ */
+enum cfg80211_bss_frame_type {
+       CFG80211_BSS_FTYPE_UNKNOWN,
+       CFG80211_BSS_FTYPE_BEACON,
+       CFG80211_BSS_FTYPE_PRESP,
+};
+
+/**
+ * cfg80211_inform_bss_width - inform cfg80211 of a new BSS
  *
  * @wiphy: the wiphy reporting the BSS
  * @rx_channel: The channel the frame was received on
  * @scan_width: width of the control channel
+ * @ftype: frame type (if known)
  * @bssid: the BSSID of the BSS
  * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
  * @capability: the capability field sent by the peer
@@ -3789,6 +3805,7 @@ struct cfg80211_bss * __must_check
 cfg80211_inform_bss_width(struct wiphy *wiphy,
                          struct ieee80211_channel *rx_channel,
                          enum nl80211_bss_scan_width scan_width,
+                         enum cfg80211_bss_frame_type ftype,
                          const u8 *bssid, u64 tsf, u16 capability,
                          u16 beacon_interval, const u8 *ie, size_t ielen,
                          s32 signal, gfp_t gfp);
@@ -3796,12 +3813,13 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
 static inline struct cfg80211_bss * __must_check
 cfg80211_inform_bss(struct wiphy *wiphy,
                    struct ieee80211_channel *rx_channel,
+                   enum cfg80211_bss_frame_type ftype,
                    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, rx_channel,
-                                        NL80211_BSS_CHAN_WIDTH_20,
+                                        NL80211_BSS_CHAN_WIDTH_20, ftype,
                                         bssid, tsf, capability,
                                         beacon_interval, ie, ielen, signal,
                                         gfp);
@@ -4412,7 +4430,6 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
  * @buf: Management frame (header + body)
  * @len: length of the frame data
  * @flags: flags, as defined in enum nl80211_rxmgmt_flags
- * @gfp: context flags
  *
  * This function is called whenever an Action frame is received for a station
  * mode interface, but is not processed in kernel.
@@ -4423,7 +4440,7 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
  * driver is responsible for rejecting the frame.
  */
 bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm,
-                     const u8 *buf, size_t len, u32 flags, gfp_t gfp);
+                     const u8 *buf, size_t len, u32 flags);
 
 /**
  * cfg80211_mgmt_tx_status - notification of TX status for management frame
index dae2e24616e16bf3051af3dd31414f91f4220af9..c9b2bec8db47bc5fa661772f6891fe7e4a21f960 100644 (file)
@@ -1226,7 +1226,8 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
  *
  * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
  *     driver to indicate that it requires IV generation for this
- *     particular key.
+ *     particular key. Setting this flag does not necessarily mean that SKBs
+ *     will have sufficient tailroom for ICV or MIC.
  * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by
  *     the driver for a TKIP key if it requires Michael MIC
  *     generation in software.
@@ -1238,7 +1239,9 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
  * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
  *     if space should be prepared for the IV, but the IV
  *     itself should not be generated. Do not set together with
- *     @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
+ *     @IEEE80211_KEY_FLAG_GENERATE_IV on the same key. Setting this flag does
+ *     not necessarily mean that SKBs will have sufficient tailroom for ICV or
+ *     MIC.
  * @IEEE80211_KEY_FLAG_RX_MGMT: This key will be used to decrypt received
  *     management frames. The flag can help drivers that have a hardware
  *     crypto implementation that doesn't deal with management frames
@@ -1405,7 +1408,7 @@ struct ieee80211_sta_rates {
  * @supp_rates: Bitmap of supported rates (per band)
  * @ht_cap: HT capabilities of this STA; restricted to our own capabilities
  * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities
- * @wme: indicates whether the STA supports WME. Only valid during AP-mode.
+ * @wme: indicates whether the STA supports QoS/WME.
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void *), size is determined in hw information.
  * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
@@ -1606,6 +1609,9 @@ struct ieee80211_tx_control {
  *     is not enabled the default action is to disconnect when getting the
  *     CSA frame.
  *
+ * @IEEE80211_HW_SUPPORTS_CLONED_SKBS: The driver will never modify the payload
+ *     or tailroom of TX skbs without copying them first.
+ *
  * @IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands
  *     in one command, mac80211 doesn't have to run separate scans per band.
  */
@@ -1639,7 +1645,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_TIMING_BEACON_ONLY                 = 1<<26,
        IEEE80211_HW_SUPPORTS_HT_CCK_RATES              = 1<<27,
        IEEE80211_HW_CHANCTX_STA_CSA                    = 1<<28,
-       /* bit 29 unused */
+       IEEE80211_HW_SUPPORTS_CLONED_SKBS               = 1<<29,
        IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS           = 1<<30,
 };
 
index f1db15b9c041ccad0f13a4206e73245b59e7c236..d097568da6908c8c9053aa64ef9fafafa2b11308 100644 (file)
@@ -3055,14 +3055,20 @@ enum nl80211_bss_scan_width {
  * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets)
  * @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
  * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
+ *     (if @NL80211_BSS_PRESP_DATA is present then this is known to be
+ *     from a probe response, otherwise it may be from the same beacon
+ *     that the NL80211_BSS_BEACON_TSF will be from)
  * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
  * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
  * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
  *     raw information elements from the probe response/beacon (bin);
- *     if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are
- *     from a Probe Response frame; otherwise they are from a Beacon frame.
+ *     if the %NL80211_BSS_BEACON_IES attribute is present and the data is
+ *     different then the IEs here are from a Probe Response frame; otherwise
+ *     they are from a Beacon frame.
  *     However, if the driver does not indicate the source of the IEs, these
  *     IEs may be from either frame subtype.
+ *     If present, the @NL80211_BSS_PRESP_DATA attribute indicates that the
+ *     data here is known to be from a probe response, without any heuristics.
  * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
  *     in mBm (100 * dBm) (s32)
  * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
@@ -3074,6 +3080,10 @@ enum nl80211_bss_scan_width {
  *     yet been received
  * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
  *     (u32, enum nl80211_bss_scan_width)
+ * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64)
+ *     (not present if no beacon frame has been received yet)
+ * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
+ *     @NL80211_BSS_TSF is known to be from a probe response (flag attribute)
  * @__NL80211_BSS_AFTER_LAST: internal
  * @NL80211_BSS_MAX: highest BSS attribute
  */
@@ -3091,6 +3101,8 @@ enum nl80211_bss {
        NL80211_BSS_SEEN_MS_AGO,
        NL80211_BSS_BEACON_IES,
        NL80211_BSS_CHAN_WIDTH,
+       NL80211_BSS_BEACON_TSF,
+       NL80211_BSS_PRESP_DATA,
 
        /* keep last */
        __NL80211_BSS_AFTER_LAST,
index 927b4ea0128bbc365a9692302ba299d5da16b2c4..4d8989b8796067898b3318b08576b32bb6a4d346 100644 (file)
@@ -1011,15 +1011,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                        clear_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
        }
 
-       if (mask & BIT(NL80211_STA_FLAG_WME)) {
-               if (set & BIT(NL80211_STA_FLAG_WME)) {
-                       set_sta_flag(sta, WLAN_STA_WME);
-                       sta->sta.wme = true;
-               } else {
-                       clear_sta_flag(sta, WLAN_STA_WME);
-                       sta->sta.wme = false;
-               }
-       }
+       if (mask & BIT(NL80211_STA_FLAG_WME))
+               sta->sta.wme = set & BIT(NL80211_STA_FLAG_WME);
 
        if (mask & BIT(NL80211_STA_FLAG_MFP)) {
                if (set & BIT(NL80211_STA_FLAG_MFP))
@@ -3352,7 +3345,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        band = chanctx_conf->def.chan->band;
        sta = sta_info_get_bss(sdata, peer);
        if (sta) {
-               qos = test_sta_flag(sta, WLAN_STA_WME);
+               qos = sta->sta.wme;
        } else {
                rcu_read_unlock();
                return -ENOLINK;
index 0375009ddc0db39fd5a365db8cb5e4122219d864..0da6f3a027e7e9cf18163238c4017972c31d246a 100644 (file)
@@ -547,12 +547,12 @@ static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
 
                compat = cfg80211_chandef_compatible(
                                &sdata->vif.bss_conf.chandef, compat);
-               if (!compat)
+               if (WARN_ON_ONCE(!compat))
                        break;
        }
        rcu_read_unlock();
 
-       if (WARN_ON_ONCE(!compat))
+       if (!compat)
                return;
 
        ieee80211_change_chanctx(local, ctx, compat);
@@ -637,41 +637,6 @@ out:
        return ret;
 }
 
-static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
-{
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_chanctx_conf *conf;
-       struct ieee80211_chanctx *ctx;
-       bool use_reserved_switch = false;
-
-       lockdep_assert_held(&local->chanctx_mtx);
-
-       conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
-                                        lockdep_is_held(&local->chanctx_mtx));
-       if (!conf)
-               return;
-
-       ctx = container_of(conf, struct ieee80211_chanctx, conf);
-
-       if (sdata->reserved_chanctx) {
-               if (sdata->reserved_chanctx->replace_state ==
-                   IEEE80211_CHANCTX_REPLACES_OTHER &&
-                   ieee80211_chanctx_num_reserved(local,
-                                                  sdata->reserved_chanctx) > 1)
-                       use_reserved_switch = true;
-
-               ieee80211_vif_unreserve_chanctx(sdata);
-       }
-
-       ieee80211_assign_vif_chanctx(sdata, NULL);
-       if (ieee80211_chanctx_refcount(local, ctx) == 0)
-               ieee80211_free_chanctx(local, ctx);
-
-       /* Unreserving may ready an in-place reservation. */
-       if (use_reserved_switch)
-               ieee80211_vif_use_reserved_switch(local);
-}
-
 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *chanctx)
 {
@@ -762,63 +727,6 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
        drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
 }
 
-int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
-                             const struct cfg80211_chan_def *chandef,
-                             enum ieee80211_chanctx_mode mode)
-{
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_chanctx *ctx;
-       u8 radar_detect_width = 0;
-       int ret;
-
-       lockdep_assert_held(&local->mtx);
-
-       WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
-
-       mutex_lock(&local->chanctx_mtx);
-
-       ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
-                                           chandef,
-                                           sdata->wdev.iftype);
-       if (ret < 0)
-               goto out;
-       if (ret > 0)
-               radar_detect_width = BIT(chandef->width);
-
-       sdata->radar_required = ret;
-
-       ret = ieee80211_check_combinations(sdata, chandef, mode,
-                                          radar_detect_width);
-       if (ret < 0)
-               goto out;
-
-       __ieee80211_vif_release_channel(sdata);
-
-       ctx = ieee80211_find_chanctx(local, chandef, mode);
-       if (!ctx)
-               ctx = ieee80211_new_chanctx(local, chandef, mode);
-       if (IS_ERR(ctx)) {
-               ret = PTR_ERR(ctx);
-               goto out;
-       }
-
-       sdata->vif.bss_conf.chandef = *chandef;
-
-       ret = ieee80211_assign_vif_chanctx(sdata, ctx);
-       if (ret) {
-               /* if assign fails refcount stays the same */
-               if (ieee80211_chanctx_refcount(local, ctx) == 0)
-                       ieee80211_free_chanctx(local, ctx);
-               goto out;
-       }
-
-       ieee80211_recalc_smps_chanctx(local, ctx);
-       ieee80211_recalc_radar_chanctx(local, ctx);
- out:
-       mutex_unlock(&local->chanctx_mtx);
-       return ret;
-}
-
 static void
 __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
                                      bool clear)
@@ -1267,8 +1175,7 @@ err:
        return err;
 }
 
-int
-ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
+static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata, *sdata_tmp;
        struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
@@ -1520,6 +1427,98 @@ err:
        return err;
 }
 
+static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *conf;
+       struct ieee80211_chanctx *ctx;
+       bool use_reserved_switch = false;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+                                        lockdep_is_held(&local->chanctx_mtx));
+       if (!conf)
+               return;
+
+       ctx = container_of(conf, struct ieee80211_chanctx, conf);
+
+       if (sdata->reserved_chanctx) {
+               if (sdata->reserved_chanctx->replace_state ==
+                   IEEE80211_CHANCTX_REPLACES_OTHER &&
+                   ieee80211_chanctx_num_reserved(local,
+                                                  sdata->reserved_chanctx) > 1)
+                       use_reserved_switch = true;
+
+               ieee80211_vif_unreserve_chanctx(sdata);
+       }
+
+       ieee80211_assign_vif_chanctx(sdata, NULL);
+       if (ieee80211_chanctx_refcount(local, ctx) == 0)
+               ieee80211_free_chanctx(local, ctx);
+
+       /* Unreserving may ready an in-place reservation. */
+       if (use_reserved_switch)
+               ieee80211_vif_use_reserved_switch(local);
+}
+
+int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
+                             const struct cfg80211_chan_def *chandef,
+                             enum ieee80211_chanctx_mode mode)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx *ctx;
+       u8 radar_detect_width = 0;
+       int ret;
+
+       lockdep_assert_held(&local->mtx);
+
+       WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
+
+       mutex_lock(&local->chanctx_mtx);
+
+       ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
+                                           chandef,
+                                           sdata->wdev.iftype);
+       if (ret < 0)
+               goto out;
+       if (ret > 0)
+               radar_detect_width = BIT(chandef->width);
+
+       sdata->radar_required = ret;
+
+       ret = ieee80211_check_combinations(sdata, chandef, mode,
+                                          radar_detect_width);
+       if (ret < 0)
+               goto out;
+
+       __ieee80211_vif_release_channel(sdata);
+
+       ctx = ieee80211_find_chanctx(local, chandef, mode);
+       if (!ctx)
+               ctx = ieee80211_new_chanctx(local, chandef, mode);
+       if (IS_ERR(ctx)) {
+               ret = PTR_ERR(ctx);
+               goto out;
+       }
+
+       sdata->vif.bss_conf.chandef = *chandef;
+
+       ret = ieee80211_assign_vif_chanctx(sdata, ctx);
+       if (ret) {
+               /* if assign fails refcount stays the same */
+               if (ieee80211_chanctx_refcount(local, ctx) == 0)
+                       ieee80211_free_chanctx(local, ctx);
+               goto out;
+       }
+
+       ieee80211_recalc_smps_chanctx(local, ctx);
+       ieee80211_recalc_radar_chanctx(local, ctx);
+ out:
+       mutex_unlock(&local->chanctx_mtx);
+       return ret;
+}
+
 int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
index 3db96648b45a02c0e0235b724210a15ba32747b7..4a20fb8f1e23f767139247133e605dbc00cc1997 100644 (file)
@@ -77,7 +77,8 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
                            TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
                            TEST(PS_DRIVER), TEST(AUTHORIZED),
                            TEST(SHORT_PREAMBLE),
-                           TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
+                           sta->sta.wme ? "WME\n" : "",
+                           TEST(WDS), TEST(CLEAR_PS_FILT),
                            TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
                            TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
                            TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
index 9713dc54ea4bb385abf1d48ae891ff5fceb7440f..5f9654d31a8d3c302e6a9508f693be0a5efb41bc 100644 (file)
@@ -1038,7 +1038,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                }
 
                if (sta && elems->wmm_info)
-                       set_sta_flag(sta, WLAN_STA_WME);
+                       sta->sta.wme = true;
 
                if (sta && elems->ht_operation && elems->ht_cap_elem &&
                    sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
index ef7a089ac54647eb763b8bbb0793bef98454b48d..ffb20e5e6cf3f5fe51e45f4236ea4bf35151e460 100644 (file)
@@ -1869,7 +1869,6 @@ ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
 int __must_check
 ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata);
 int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata);
-int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local);
 
 int __must_check
 ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
index d808cff8015374ddfb927d5695a3d3973bcc0428..6429d0e1d4a1461dd8ca1ea14498f36e3f087301 100644 (file)
@@ -130,9 +130,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
        if (!ret) {
                key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
 
-               if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-                     (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
-                     (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
+               if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
                        sdata->crypto_tx_tailroom_needed_cnt--;
 
                WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
@@ -180,9 +178,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
        sta = key->sta;
        sdata = key->sdata;
 
-       if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-             (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
-             (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
+       if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
                increment_tailroom_need_count(sdata);
 
        ret = drv_set_key(key->local, DISABLE_KEY, sdata,
@@ -878,9 +874,7 @@ void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
        if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
                key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
 
-               if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-                     (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
-                     (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
+               if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
                        increment_tailroom_need_count(key->sdata);
        }
 
index cf032a8db9d78e9c13fe9df1ee2f2c35dbe8ec62..a6699dceae7c8aeeff4419d8cc2815f9d86adf5e 100644 (file)
@@ -729,7 +729,7 @@ void mesh_plink_broken(struct sta_info *sta)
        tbl = rcu_dereference(mesh_paths);
        for_each_mesh_entry(tbl, node, i) {
                mpath = node->mpath;
-               if (rcu_dereference(mpath->next_hop) == sta &&
+               if (rcu_access_pointer(mpath->next_hop) == sta &&
                    mpath->flags & MESH_PATH_ACTIVE &&
                    !(mpath->flags & MESH_PATH_FIXED)) {
                        spin_lock_bh(&mpath->state_lock);
@@ -794,7 +794,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
        tbl = resize_dereference_mesh_paths();
        for_each_mesh_entry(tbl, node, i) {
                mpath = node->mpath;
-               if (rcu_dereference(mpath->next_hop) == sta) {
+               if (rcu_access_pointer(mpath->next_hop) == sta) {
                        spin_lock(&tbl->hashwlock[i]);
                        __mesh_path_del(tbl, node);
                        spin_unlock(&tbl->hashwlock[i]);
index 63b874101b2763d5997dc561073e96807596c11a..8f0887fc7128c4e04e0e7b4d5e4f1dd7445a40f5 100644 (file)
@@ -431,14 +431,12 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
                return NULL;
 
        sta->plink_state = NL80211_PLINK_LISTEN;
+       sta->sta.wme = true;
 
        sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
        sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
        sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
 
-       set_sta_flag(sta, WLAN_STA_WME);
-       sta->sta.wme = true;
-
        return sta;
 }
 
@@ -1003,7 +1001,6 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
        enum ieee80211_self_protected_actioncode ftype;
        u32 changed = 0;
        u8 ie_len = elems->peering_len;
-       __le16 _plid, _llid;
        u16 plid, llid = 0;
 
        if (!elems->peering) {
@@ -1038,13 +1035,10 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
        /* Note the lines below are correct, the llid in the frame is the plid
         * from the point of view of this host.
         */
-       memcpy(&_plid, PLINK_GET_LLID(elems->peering), sizeof(__le16));
-       plid = le16_to_cpu(_plid);
+       plid = get_unaligned_le16(PLINK_GET_LLID(elems->peering));
        if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
-           (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) {
-               memcpy(&_llid, PLINK_GET_PLID(elems->peering), sizeof(__le16));
-               llid = le16_to_cpu(_llid);
-       }
+           (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
+               llid = get_unaligned_le16(PLINK_GET_PLID(elems->peering));
 
        /* WARNING: Only for sta pointer, is dropped & re-acquired */
        rcu_read_lock();
index 31a8afaf73323bc09fb99f8e960b17c3fa2e31fd..29fe91d6a094fc72a54ccba3bbe3d377416672a7 100644 (file)
@@ -149,6 +149,7 @@ static u32
 ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                             struct ieee80211_supported_band *sband,
                             struct ieee80211_channel *channel,
+                            const struct ieee80211_ht_cap *ht_cap,
                             const struct ieee80211_ht_operation *ht_oper,
                             const struct ieee80211_vht_operation *vht_oper,
                             struct cfg80211_chan_def *chandef, bool tracking)
@@ -162,13 +163,19 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        chandef->center_freq1 = channel->center_freq;
        chandef->center_freq2 = 0;
 
-       if (!ht_oper || !sband->ht_cap.ht_supported) {
+       if (!ht_cap || !ht_oper || !sband->ht_cap.ht_supported) {
                ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
                goto out;
        }
 
        chandef->width = NL80211_CHAN_WIDTH_20;
 
+       if (!(ht_cap->cap_info &
+             cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40))) {
+               ret = IEEE80211_STA_DISABLE_40MHZ | IEEE80211_STA_DISABLE_VHT;
+               goto out;
+       }
+
        ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
                                                  channel->band);
        /* check that channel matches the right operating channel */
@@ -328,6 +335,7 @@ out:
 
 static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
                               struct sta_info *sta,
+                              const struct ieee80211_ht_cap *ht_cap,
                               const struct ieee80211_ht_operation *ht_oper,
                               const struct ieee80211_vht_operation *vht_oper,
                               const u8 *bssid, u32 *changed)
@@ -367,8 +375,9 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
        sband = local->hw.wiphy->bands[chan->band];
 
        /* calculate new channel (type) based on HT/VHT operation IEs */
-       flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
-                                            vht_oper, &chandef, true);
+       flags = ieee80211_determine_chantype(sdata, sband, chan,
+                                            ht_cap, ht_oper, vht_oper,
+                                            &chandef, true);
 
        /*
         * Downgrade the new channel if we associated with restricted
@@ -2677,8 +2686,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
                set_sta_flag(sta, WLAN_STA_MFP);
 
-       if (elems.wmm_param)
-               set_sta_flag(sta, WLAN_STA_WME);
+       sta->sta.wme = elems.wmm_param;
 
        err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
        if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
@@ -3174,7 +3182,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        mutex_lock(&local->sta_mtx);
        sta = sta_info_get(sdata, bssid);
 
-       if (ieee80211_config_bw(sdata, sta, elems.ht_operation,
+       if (ieee80211_config_bw(sdata, sta,
+                               elems.ht_cap_elem, elems.ht_operation,
                                elems.vht_operation, bssid, &changed)) {
                mutex_unlock(&local->sta_mtx);
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
@@ -3808,6 +3817,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       const struct ieee80211_ht_cap *ht_cap = NULL;
        const struct ieee80211_ht_operation *ht_oper = NULL;
        const struct ieee80211_vht_operation *vht_oper = NULL;
        struct ieee80211_supported_band *sband;
@@ -3824,14 +3834,17 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
 
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
            sband->ht_cap.ht_supported) {
-               const u8 *ht_oper_ie, *ht_cap;
+               const u8 *ht_oper_ie, *ht_cap_ie;
 
                ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
                if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
                        ht_oper = (void *)(ht_oper_ie + 2);
 
-               ht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
-               if (!ht_cap || ht_cap[1] < sizeof(struct ieee80211_ht_cap)) {
+               ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
+               if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap))
+                       ht_cap = (void *)(ht_cap_ie + 2);
+
+               if (!ht_cap) {
                        ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
                        ht_oper = NULL;
                }
@@ -3862,7 +3875,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
 
        ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
                                                     cbss->channel,
-                                                    ht_oper, vht_oper,
+                                                    ht_cap, ht_oper, vht_oper,
                                                     &chandef, false);
 
        sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
index bd2c9b22c945669f8ec1d48e3959101fd9ce6754..a8d862f9183c9785158465748e344ce9113aba00 100644 (file)
@@ -2725,7 +2725,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
                sig = status->signal;
 
        if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
-                            rx->skb->data, rx->skb->len, 0, GFP_ATOMIC)) {
+                            rx->skb->data, rx->skb->len, 0)) {
                if (rx->sta)
                        rx->sta->rx_packets++;
                dev_kfree_skb(rx->skb);
index a0a938145dcc87397cb4ecfad5f59b1c5fb28dbc..a9bb6eb8c3e0f8c3f3b8e623a91817f2579e74fe 100644 (file)
@@ -1094,7 +1094,7 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *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);
+                       RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
        }
 out:
        mutex_unlock(&local->mtx);
index c6ee2139fbc579bab35e8cc5bfb6f3b4994930d2..e1f957d5935e0e5dc113a8570a4ac8d08acaa1a4 100644 (file)
@@ -1179,7 +1179,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
        struct sk_buff *skb;
        int size = sizeof(*nullfunc);
        __le16 fc;
-       bool qos = test_sta_flag(sta, WLAN_STA_WME);
+       bool qos = sta->sta.wme;
        struct ieee80211_tx_info *info;
        struct ieee80211_chanctx_conf *chanctx_conf;
 
@@ -1834,7 +1834,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
        if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
-       if (test_sta_flag(sta, WLAN_STA_WME))
+       if (sta->sta.wme)
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
        if (test_sta_flag(sta, WLAN_STA_MFP))
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
index d411bcc8ef085215b8369fc0f066a49fd65fc6eb..89c40d5c0633921649982787d8f6fc3756261eaa 100644 (file)
@@ -31,7 +31,6 @@
  *     when virtual port control is not in use.
  * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
  *     frames.
- * @WLAN_STA_WME: Station is a QoS-STA.
  * @WLAN_STA_WDS: Station is one of our WDS peers.
  * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
  *     IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
@@ -69,7 +68,6 @@ enum ieee80211_sta_info_flags {
        WLAN_STA_PS_STA,
        WLAN_STA_AUTHORIZED,
        WLAN_STA_SHORT_PREAMBLE,
-       WLAN_STA_WME,
        WLAN_STA_WDS,
        WLAN_STA_CLEAR_PS_FILT,
        WLAN_STA_MFP,
index 1b21050be174b29539a954991d0376dab76fc78f..f2cb3b6c1871e6b67f418b04f091af5609b117a8 100644 (file)
@@ -316,8 +316,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
        }
 
        /* add the QoS param IE if both the peer and we support it */
-       if (local->hw.queues >= IEEE80211_NUM_ACS &&
-           test_sta_flag(sta, WLAN_STA_WME))
+       if (local->hw.queues >= IEEE80211_NUM_ACS && sta->sta.wme)
                ieee80211_tdls_add_wmm_param_ie(sdata, skb);
 
        /* add any custom IEs that go before HT operation */
index 464106c023d8c7d9cb1bd65b39ad642bd1090bc1..925c39f4099eadfa4744263d1485fe0611a16e69 100644 (file)
@@ -1478,7 +1478,10 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
                tail_need = max_t(int, tail_need, 0);
        }
 
-       if (skb_cloned(skb))
+       if (skb_cloned(skb) &&
+           (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CLONED_SKBS) ||
+            !skb_clone_writable(skb, ETH_HLEN) ||
+            sdata->crypto_tx_tailroom_needed_cnt))
                I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
        else if (head_need || tail_need)
                I802_DEBUG_INC(local->tx_expand_skb_head);
@@ -1844,7 +1847,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                        memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
                        hdrlen = 30;
                        authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
-                       wme_sta = test_sta_flag(sta, WLAN_STA_WME);
+                       wme_sta = sta->sta.wme;
                }
                ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
                                        u.ap);
@@ -1957,7 +1960,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                        if (sta) {
                                authorized = test_sta_flag(sta,
                                                        WLAN_STA_AUTHORIZED);
-                               wme_sta = test_sta_flag(sta, WLAN_STA_WME);
+                               wme_sta = sta->sta.wme;
                                tdls_peer = test_sta_flag(sta,
                                                          WLAN_STA_TDLS_PEER);
                                tdls_auth = test_sta_flag(sta,
@@ -2035,7 +2038,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                sta = sta_info_get(sdata, hdr.addr1);
                if (sta) {
                        authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
-                       wme_sta = test_sta_flag(sta, WLAN_STA_WME);
+                       wme_sta = sta->sta.wme;
                }
        }
 
index d51422c778dee359bec450c75b77bfb24ca712f4..6459946f0b741cbfd05dca843ae06380435601d6 100644 (file)
@@ -118,7 +118,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
        case NL80211_IFTYPE_AP_VLAN:
                sta = rcu_dereference(sdata->u.vlan.sta);
                if (sta) {
-                       qos = test_sta_flag(sta, WLAN_STA_WME);
+                       qos = sta->sta.wme;
                        break;
                }
        case NL80211_IFTYPE_AP:
@@ -145,7 +145,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
        if (!sta && ra && !is_multicast_ether_addr(ra)) {
                sta = sta_info_get(sdata, ra);
                if (sta)
-                       qos = test_sta_flag(sta, WLAN_STA_WME);
+                       qos = sta->sta.wme;
        }
        rcu_read_unlock();
 
index 14c98e48f261ee49656eabb198d62648890b63b3..02a86a27fd846602dd0c9aafd0a045f196e246b4 100644 (file)
@@ -158,6 +158,7 @@ static const struct acpi_device_id rfkill_acpi_match[] = {
        { "BCM2E1A", RFKILL_TYPE_BLUETOOTH },
        { "BCM2E39", RFKILL_TYPE_BLUETOOTH },
        { "BCM2E3D", RFKILL_TYPE_BLUETOOTH },
+       { "BCM2E64", RFKILL_TYPE_BLUETOOTH },
        { "BCM4752", RFKILL_TYPE_GPS },
        { "LNV4752", RFKILL_TYPE_GPS },
        { },
index 682babde4aa5b00a70c50a1574f1f2233a0ed77b..c6620aa679e079bcf6693ac92cf4760435212081 100644 (file)
@@ -492,12 +492,6 @@ int wiphy_register(struct wiphy *wiphy)
        int i;
        u16 ifmodes = wiphy->interface_modes;
 
-       /*
-        * There are major locking problems in nl80211/mac80211 for CSA,
-        * disable for all drivers until this has been reworked.
-        */
-       wiphy->flags &= ~WIPHY_FLAG_HAS_CHANNEL_SWITCH;
-
 #ifdef CONFIG_PM
        if (WARN_ON(wiphy->wowlan &&
                    (wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
index 266766b8d80b61455565cc43779a6e229ed7710d..369fc334fdadede142c86f9676dd752761d4f4c4 100644 (file)
@@ -605,7 +605,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
 }
 
 bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
-                     const u8 *buf, size_t len, u32 flags, gfp_t gfp)
+                     const u8 *buf, size_t len, u32 flags)
 {
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -648,7 +648,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
                /* Indicate the received Action frame to user space */
                if (nl80211_send_mgmt(rdev, wdev, reg->nlportid,
                                      freq, sig_mbm,
-                                     buf, len, flags, gfp))
+                                     buf, len, flags, GFP_ATOMIC))
                        continue;
 
                result = true;
index df7b1332a1ec2fa80834b94c233f38a427a0f350..3011401f52c0a34317b2310dfa59912d4afe760c 100644 (file)
@@ -6033,7 +6033,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
        const struct cfg80211_bss_ies *ies;
        void *hdr;
        struct nlattr *bss;
-       bool tsf = false;
 
        ASSERT_WDEV_LOCK(wdev);
 
@@ -6060,18 +6059,27 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
                goto nla_put_failure;
 
        rcu_read_lock();
+       /* indicate whether we have probe response data or not */
+       if (rcu_access_pointer(res->proberesp_ies) &&
+           nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
+               goto fail_unlock_rcu;
+
+       /* this pointer prefers to be pointed to probe response data
+        * but is always valid
+        */
        ies = rcu_dereference(res->ies);
        if (ies) {
                if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf))
                        goto fail_unlock_rcu;
-               tsf = true;
                if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
                                        ies->len, ies->data))
                        goto fail_unlock_rcu;
        }
+
+       /* and this pointer is always (unless driver didn't know) beacon data */
        ies = rcu_dereference(res->beacon_ies);
-       if (ies) {
-               if (!tsf && nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf))
+       if (ies && ies->from_beacon) {
+               if (nla_put_u64(msg, NL80211_BSS_BEACON_TSF, ies->tsf))
                        goto fail_unlock_rcu;
                if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
                                        ies->len, ies->data))
index 0798c62e60858cb81d1df3d4829414665808268b..620a4b40d4662f8f5718da6b28aeeb281c573224 100644 (file)
@@ -884,6 +884,7 @@ struct cfg80211_bss*
 cfg80211_inform_bss_width(struct wiphy *wiphy,
                          struct ieee80211_channel *rx_channel,
                          enum nl80211_bss_scan_width scan_width,
+                         enum cfg80211_bss_frame_type ftype,
                          const u8 *bssid, u64 tsf, u16 capability,
                          u16 beacon_interval, const u8 *ie, size_t ielen,
                          s32 signal, gfp_t gfp)
@@ -911,21 +912,32 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
        tmp.pub.beacon_interval = beacon_interval;
        tmp.pub.capability = capability;
        /*
-        * Since we do not know here whether the IEs are from a Beacon or Probe
+        * If we do not know here whether the IEs are from a Beacon or Probe
         * Response frame, we need to pick one of the options and only use it
         * with the driver that does not provide the full Beacon/Probe Response
         * frame. Use Beacon frame pointer to avoid indicating that this should
         * override the IEs pointer should we have received an earlier
         * indication of Probe Response data.
         */
-       ies = kmalloc(sizeof(*ies) + ielen, gfp);
+       ies = kzalloc(sizeof(*ies) + ielen, gfp);
        if (!ies)
                return NULL;
        ies->len = ielen;
        ies->tsf = tsf;
+       ies->from_beacon = false;
        memcpy(ies->data, ie, ielen);
 
-       rcu_assign_pointer(tmp.pub.beacon_ies, ies);
+       switch (ftype) {
+       case CFG80211_BSS_FTYPE_BEACON:
+               ies->from_beacon = true;
+               /* fall through to assign */
+       case CFG80211_BSS_FTYPE_UNKNOWN:
+               rcu_assign_pointer(tmp.pub.beacon_ies, ies);
+               break;
+       case CFG80211_BSS_FTYPE_PRESP:
+               rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
+               break;
+       }
        rcu_assign_pointer(tmp.pub.ies, ies);
 
        signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
@@ -982,11 +994,12 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
        if (!channel)
                return NULL;
 
-       ies = kmalloc(sizeof(*ies) + ielen, gfp);
+       ies = kzalloc(sizeof(*ies) + ielen, gfp);
        if (!ies)
                return NULL;
        ies->len = ielen;
        ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
+       ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
        memcpy(ies->data, mgmt->u.probe_resp.variable, ielen);
 
        if (ieee80211_is_probe_resp(mgmt->frame_control))