diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 107 |
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 | ||
1030 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1036 | void 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, | |||
1277 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1285 | void 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 | ||
1866 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1887 | u8 *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 | ||
1928 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, | 1949 | void 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 | |||
2139 | void 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 | |||
2157 | void 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 | |||
2175 | void 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 | } | ||
2183 | EXPORT_SYMBOL(ieee80211_radar_detected); | ||