aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c107
1 files changed, 87 insertions, 20 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index f11e8c540db4..0f38f43ac62e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -739,11 +739,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
739 if (calc_crc) 739 if (calc_crc)
740 crc = crc32_be(crc, pos - 2, elen + 2); 740 crc = crc32_be(crc, pos - 2, elen + 2);
741 741
742 if (pos[3] == 1) { 742 if (elen >= 5 && pos[3] == 2) {
743 /* OUI Type 1 - WPA IE */
744 elems->wpa = pos;
745 elems->wpa_len = elen;
746 } else if (elen >= 5 && pos[3] == 2) {
747 /* OUI Type 2 - WMM IE */ 743 /* OUI Type 2 - WMM IE */
748 if (pos[4] == 0) { 744 if (pos[4] == 0) {
749 elems->wmm_info = pos; 745 elems->wmm_info = pos;
@@ -791,6 +787,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
791 else 787 else
792 elem_parse_failed = true; 788 elem_parse_failed = true;
793 break; 789 break;
790 case WLAN_EID_OPMODE_NOTIF:
791 if (elen > 0)
792 elems->opmode_notif = pos;
793 else
794 elem_parse_failed = true;
795 break;
794 case WLAN_EID_MESH_ID: 796 case WLAN_EID_MESH_ID:
795 elems->mesh_id = pos; 797 elems->mesh_id = pos;
796 elems->mesh_id_len = elen; 798 elems->mesh_id_len = elen;
@@ -805,6 +807,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
805 elems->peering = pos; 807 elems->peering = pos;
806 elems->peering_len = elen; 808 elems->peering_len = elen;
807 break; 809 break;
810 case WLAN_EID_MESH_AWAKE_WINDOW:
811 if (elen >= 2)
812 elems->awake_window = (void *)pos;
813 break;
808 case WLAN_EID_PREQ: 814 case WLAN_EID_PREQ:
809 elems->preq = pos; 815 elems->preq = pos;
810 elems->preq_len = elen; 816 elems->preq_len = elen;
@@ -1029,8 +1035,9 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
1029 1035
1030void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 1036void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1031 u16 transaction, u16 auth_alg, u16 status, 1037 u16 transaction, u16 auth_alg, u16 status,
1032 u8 *extra, size_t extra_len, const u8 *da, 1038 const u8 *extra, size_t extra_len, const u8 *da,
1033 const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx) 1039 const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx,
1040 u32 tx_flags)
1034{ 1041{
1035 struct ieee80211_local *local = sdata->local; 1042 struct ieee80211_local *local = sdata->local;
1036 struct sk_buff *skb; 1043 struct sk_buff *skb;
@@ -1063,7 +1070,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1063 WARN_ON(err); 1070 WARN_ON(err);
1064 } 1071 }
1065 1072
1066 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 1073 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
1074 tx_flags;
1067 ieee80211_tx_skb(sdata, skb); 1075 ieee80211_tx_skb(sdata, skb);
1068} 1076}
1069 1077
@@ -1277,7 +1285,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1277void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 1285void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1278 const u8 *ssid, size_t ssid_len, 1286 const u8 *ssid, size_t ssid_len,
1279 const u8 *ie, size_t ie_len, 1287 const u8 *ie, size_t ie_len,
1280 u32 ratemask, bool directed, bool no_cck, 1288 u32 ratemask, bool directed, u32 tx_flags,
1281 struct ieee80211_channel *channel, bool scan) 1289 struct ieee80211_channel *channel, bool scan)
1282{ 1290{
1283 struct sk_buff *skb; 1291 struct sk_buff *skb;
@@ -1286,9 +1294,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1286 ssid, ssid_len, 1294 ssid, ssid_len,
1287 ie, ie_len, directed); 1295 ie, ie_len, directed);
1288 if (skb) { 1296 if (skb) {
1289 if (no_cck) 1297 IEEE80211_SKB_CB(skb)->flags |= tx_flags;
1290 IEEE80211_SKB_CB(skb)->flags |=
1291 IEEE80211_TX_CTL_NO_CCK_RATE;
1292 if (scan) 1298 if (scan)
1293 ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); 1299 ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
1294 else 1300 else
@@ -1358,6 +1364,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1358 struct ieee80211_chanctx *ctx; 1364 struct ieee80211_chanctx *ctx;
1359 struct sta_info *sta; 1365 struct sta_info *sta;
1360 int res, i; 1366 int res, i;
1367 bool reconfig_due_to_wowlan = false;
1361 1368
1362#ifdef CONFIG_PM 1369#ifdef CONFIG_PM
1363 if (local->suspended) 1370 if (local->suspended)
@@ -1377,6 +1384,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1377 * res is 1, which means the driver requested 1384 * res is 1, which means the driver requested
1378 * to go through a regular reset on wakeup. 1385 * to go through a regular reset on wakeup.
1379 */ 1386 */
1387 reconfig_due_to_wowlan = true;
1380 } 1388 }
1381#endif 1389#endif
1382 /* everything else happens only if HW was up & running */ 1390 /* everything else happens only if HW was up & running */
@@ -1526,11 +1534,20 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1526 BSS_CHANGED_IDLE | 1534 BSS_CHANGED_IDLE |
1527 BSS_CHANGED_TXPOWER; 1535 BSS_CHANGED_TXPOWER;
1528 1536
1537#ifdef CONFIG_PM
1538 if (local->resuming && !reconfig_due_to_wowlan)
1539 sdata->vif.bss_conf = sdata->suspend_bss_conf;
1540#endif
1541
1529 switch (sdata->vif.type) { 1542 switch (sdata->vif.type) {
1530 case NL80211_IFTYPE_STATION: 1543 case NL80211_IFTYPE_STATION:
1531 changed |= BSS_CHANGED_ASSOC | 1544 changed |= BSS_CHANGED_ASSOC |
1532 BSS_CHANGED_ARP_FILTER | 1545 BSS_CHANGED_ARP_FILTER |
1533 BSS_CHANGED_PS; 1546 BSS_CHANGED_PS;
1547
1548 if (sdata->u.mgd.dtim_period)
1549 changed |= BSS_CHANGED_DTIM_PERIOD;
1550
1534 mutex_lock(&sdata->u.mgd.mtx); 1551 mutex_lock(&sdata->u.mgd.mtx);
1535 ieee80211_bss_info_change_notify(sdata, changed); 1552 ieee80211_bss_info_change_notify(sdata, changed);
1536 mutex_unlock(&sdata->u.mgd.mtx); 1553 mutex_unlock(&sdata->u.mgd.mtx);
@@ -1550,9 +1567,11 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1550 1567
1551 /* fall through */ 1568 /* fall through */
1552 case NL80211_IFTYPE_MESH_POINT: 1569 case NL80211_IFTYPE_MESH_POINT:
1553 changed |= BSS_CHANGED_BEACON | 1570 if (sdata->vif.bss_conf.enable_beacon) {
1554 BSS_CHANGED_BEACON_ENABLED; 1571 changed |= BSS_CHANGED_BEACON |
1555 ieee80211_bss_info_change_notify(sdata, changed); 1572 BSS_CHANGED_BEACON_ENABLED;
1573 ieee80211_bss_info_change_notify(sdata, changed);
1574 }
1556 break; 1575 break;
1557 case NL80211_IFTYPE_WDS: 1576 case NL80211_IFTYPE_WDS:
1558 break; 1577 break;
@@ -1632,7 +1651,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1632 mutex_lock(&local->sta_mtx); 1651 mutex_lock(&local->sta_mtx);
1633 1652
1634 list_for_each_entry(sta, &local->sta_list, list) { 1653 list_for_each_entry(sta, &local->sta_list, list) {
1635 ieee80211_sta_tear_down_BA_sessions(sta, true); 1654 ieee80211_sta_tear_down_BA_sessions(
1655 sta, AGG_STOP_LOCAL_REQUEST);
1636 clear_sta_flag(sta, WLAN_STA_BLOCK_BA); 1656 clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
1637 } 1657 }
1638 1658
@@ -1646,10 +1666,11 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1646 * If this is for hw restart things are still running. 1666 * If this is for hw restart things are still running.
1647 * We may want to change that later, however. 1667 * We may want to change that later, however.
1648 */ 1668 */
1649 if (!local->suspended) { 1669 if (!local->suspended || reconfig_due_to_wowlan)
1650 drv_restart_complete(local); 1670 drv_restart_complete(local);
1671
1672 if (!local->suspended)
1651 return 0; 1673 return 0;
1652 }
1653 1674
1654#ifdef CONFIG_PM 1675#ifdef CONFIG_PM
1655 /* first set suspended false, then resuming */ 1676 /* first set suspended false, then resuming */
@@ -1864,7 +1885,7 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1864} 1885}
1865 1886
1866u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, 1887u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
1867 u32 cap) 1888 u32 cap)
1868{ 1889{
1869 __le32 tmp; 1890 __le32 tmp;
1870 1891
@@ -1926,7 +1947,7 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1926} 1947}
1927 1948
1928void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, 1949void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
1929 struct ieee80211_ht_operation *ht_oper, 1950 const struct ieee80211_ht_operation *ht_oper,
1930 struct cfg80211_chan_def *chandef) 1951 struct cfg80211_chan_def *chandef)
1931{ 1952{
1932 enum nl80211_channel_type channel_type; 1953 enum nl80211_channel_type channel_type;
@@ -2114,3 +2135,49 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
2114 2135
2115 return ts; 2136 return ts;
2116} 2137}
2138
2139void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
2140{
2141 struct ieee80211_sub_if_data *sdata;
2142
2143 mutex_lock(&local->iflist_mtx);
2144 list_for_each_entry(sdata, &local->interfaces, list) {
2145 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
2146
2147 if (sdata->wdev.cac_started) {
2148 ieee80211_vif_release_channel(sdata);
2149 cfg80211_cac_event(sdata->dev,
2150 NL80211_RADAR_CAC_ABORTED,
2151 GFP_KERNEL);
2152 }
2153 }
2154 mutex_unlock(&local->iflist_mtx);
2155}
2156
2157void ieee80211_dfs_radar_detected_work(struct work_struct *work)
2158{
2159 struct ieee80211_local *local =
2160 container_of(work, struct ieee80211_local, radar_detected_work);
2161 struct cfg80211_chan_def chandef;
2162
2163 ieee80211_dfs_cac_cancel(local);
2164
2165 if (local->use_chanctx)
2166 /* currently not handled */
2167 WARN_ON(1);
2168 else {
2169 cfg80211_chandef_create(&chandef, local->hw.conf.channel,
2170 local->hw.conf.channel_type);
2171 cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
2172 }
2173}
2174
2175void ieee80211_radar_detected(struct ieee80211_hw *hw)
2176{
2177 struct ieee80211_local *local = hw_to_local(hw);
2178
2179 trace_api_radar_detected(local);
2180
2181 ieee80211_queue_work(hw, &local->radar_detected_work);
2182}
2183EXPORT_SYMBOL(ieee80211_radar_detected);