diff options
Diffstat (limited to 'net/mac80211')
39 files changed, 1738 insertions, 562 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 4d6f8653ec88..9109262abd24 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -6,6 +6,7 @@ config MAC80211 | |||
6 | select CRYPTO_ARC4 | 6 | select CRYPTO_ARC4 |
7 | select CRYPTO_AES | 7 | select CRYPTO_AES |
8 | select CRC32 | 8 | select CRC32 |
9 | select AVERAGE | ||
9 | ---help--- | 10 | ---help--- |
10 | This option enables the hardware independent IEEE 802.11 | 11 | This option enables the hardware independent IEEE 802.11 |
11 | networking stack. | 12 | networking stack. |
@@ -92,7 +93,7 @@ config MAC80211_MESH | |||
92 | config MAC80211_LEDS | 93 | config MAC80211_LEDS |
93 | bool "Enable LED triggers" | 94 | bool "Enable LED triggers" |
94 | depends on MAC80211 | 95 | depends on MAC80211 |
95 | select NEW_LEDS | 96 | depends on LEDS_CLASS |
96 | select LEDS_TRIGGERS | 97 | select LEDS_TRIGGERS |
97 | ---help--- | 98 | ---help--- |
98 | This option enables a few LED triggers for different | 99 | This option enables a few LED triggers for different |
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index d2b03e0851ef..4bd6ef0be380 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -147,6 +147,5 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) | |||
147 | 147 | ||
148 | void ieee80211_aes_key_free(struct crypto_cipher *tfm) | 148 | void ieee80211_aes_key_free(struct crypto_cipher *tfm) |
149 | { | 149 | { |
150 | if (tfm) | 150 | crypto_free_cipher(tfm); |
151 | crypto_free_cipher(tfm); | ||
152 | } | 151 | } |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index b4d66cca76d6..d502b2684a66 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -128,6 +128,5 @@ struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) | |||
128 | 128 | ||
129 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) | 129 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) |
130 | { | 130 | { |
131 | if (tfm) | 131 | crypto_free_cipher(tfm); |
132 | crypto_free_cipher(tfm); | ||
133 | } | 132 | } |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 720b7a84af59..f138b195d657 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -129,9 +129,7 @@ static void sta_rx_agg_reorder_timer_expired(unsigned long data) | |||
129 | timer_to_tid[0]); | 129 | timer_to_tid[0]); |
130 | 130 | ||
131 | rcu_read_lock(); | 131 | rcu_read_lock(); |
132 | spin_lock(&sta->lock); | ||
133 | ieee80211_release_reorder_timeout(sta, *ptid); | 132 | ieee80211_release_reorder_timeout(sta, *ptid); |
134 | spin_unlock(&sta->lock); | ||
135 | rcu_read_unlock(); | 133 | rcu_read_unlock(); |
136 | } | 134 | } |
137 | 135 | ||
@@ -256,7 +254,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
256 | } | 254 | } |
257 | 255 | ||
258 | /* prepare A-MPDU MLME for Rx aggregation */ | 256 | /* prepare A-MPDU MLME for Rx aggregation */ |
259 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | 257 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); |
260 | if (!tid_agg_rx) { | 258 | if (!tid_agg_rx) { |
261 | #ifdef CONFIG_MAC80211_HT_DEBUG | 259 | #ifdef CONFIG_MAC80211_HT_DEBUG |
262 | if (net_ratelimit()) | 260 | if (net_ratelimit()) |
@@ -280,9 +278,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
280 | 278 | ||
281 | /* prepare reordering buffer */ | 279 | /* prepare reordering buffer */ |
282 | tid_agg_rx->reorder_buf = | 280 | tid_agg_rx->reorder_buf = |
283 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); | 281 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL); |
284 | tid_agg_rx->reorder_time = | 282 | tid_agg_rx->reorder_time = |
285 | kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC); | 283 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); |
286 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { | 284 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { |
287 | #ifdef CONFIG_MAC80211_HT_DEBUG | 285 | #ifdef CONFIG_MAC80211_HT_DEBUG |
288 | if (net_ratelimit()) | 286 | if (net_ratelimit()) |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index d4679b265ba8..9cc472c6a6a5 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -342,10 +342,11 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
342 | /* send AddBA request */ | 342 | /* send AddBA request */ |
343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
344 | tid_tx->dialog_token, start_seq_num, | 344 | tid_tx->dialog_token, start_seq_num, |
345 | 0x40, 5000); | 345 | 0x40, tid_tx->timeout); |
346 | } | 346 | } |
347 | 347 | ||
348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | 348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, |
349 | u16 timeout) | ||
349 | { | 350 | { |
350 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 351 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
351 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 352 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -420,6 +421,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
420 | skb_queue_head_init(&tid_tx->pending); | 421 | skb_queue_head_init(&tid_tx->pending); |
421 | __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | 422 | __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
422 | 423 | ||
424 | tid_tx->timeout = timeout; | ||
425 | |||
423 | /* Tx timer */ | 426 | /* Tx timer */ |
424 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; | 427 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; |
425 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 428 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 18bd0e550600..4bc8a9250cfd 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -19,9 +19,10 @@ | |||
19 | #include "rate.h" | 19 | #include "rate.h" |
20 | #include "mesh.h" | 20 | #include "mesh.h" |
21 | 21 | ||
22 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | 22 | static struct net_device *ieee80211_add_iface(struct wiphy *wiphy, char *name, |
23 | enum nl80211_iftype type, u32 *flags, | 23 | enum nl80211_iftype type, |
24 | struct vif_params *params) | 24 | u32 *flags, |
25 | struct vif_params *params) | ||
25 | { | 26 | { |
26 | struct ieee80211_local *local = wiphy_priv(wiphy); | 27 | struct ieee80211_local *local = wiphy_priv(wiphy); |
27 | struct net_device *dev; | 28 | struct net_device *dev; |
@@ -29,12 +30,15 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
29 | int err; | 30 | int err; |
30 | 31 | ||
31 | err = ieee80211_if_add(local, name, &dev, type, params); | 32 | err = ieee80211_if_add(local, name, &dev, type, params); |
32 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) | 33 | if (err) |
33 | return err; | 34 | return ERR_PTR(err); |
34 | 35 | ||
35 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 36 | if (type == NL80211_IFTYPE_MONITOR && flags) { |
36 | sdata->u.mntr_flags = *flags; | 37 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
37 | return 0; | 38 | sdata->u.mntr_flags = *flags; |
39 | } | ||
40 | |||
41 | return dev; | ||
38 | } | 42 | } |
39 | 43 | ||
40 | static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev) | 44 | static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev) |
@@ -56,11 +60,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
56 | if (ret) | 60 | if (ret) |
57 | return ret; | 61 | return ret; |
58 | 62 | ||
59 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | ||
60 | ieee80211_sdata_set_mesh_id(sdata, | ||
61 | params->mesh_id_len, | ||
62 | params->mesh_id); | ||
63 | |||
64 | if (type == NL80211_IFTYPE_AP_VLAN && | 63 | if (type == NL80211_IFTYPE_AP_VLAN && |
65 | params && params->use_4addr == 0) | 64 | params && params->use_4addr == 0) |
66 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | 65 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); |
@@ -296,11 +295,12 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
296 | 295 | ||
297 | static int ieee80211_config_default_key(struct wiphy *wiphy, | 296 | static int ieee80211_config_default_key(struct wiphy *wiphy, |
298 | struct net_device *dev, | 297 | struct net_device *dev, |
299 | u8 key_idx) | 298 | u8 key_idx, bool uni, |
299 | bool multi) | ||
300 | { | 300 | { |
301 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 301 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
302 | 302 | ||
303 | ieee80211_set_default_key(sdata, key_idx); | 303 | ieee80211_set_default_key(sdata, key_idx, uni, multi); |
304 | 304 | ||
305 | return 0; | 305 | return 0; |
306 | } | 306 | } |
@@ -343,8 +343,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
343 | 343 | ||
344 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 344 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
345 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 345 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
346 | sinfo->filled |= STATION_INFO_SIGNAL; | 346 | sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; |
347 | sinfo->signal = (s8)sta->last_signal; | 347 | sinfo->signal = (s8)sta->last_signal; |
348 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | ||
348 | } | 349 | } |
349 | 350 | ||
350 | sinfo->txrate.flags = 0; | 351 | sinfo->txrate.flags = 0; |
@@ -983,7 +984,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
983 | return 0; | 984 | return 0; |
984 | } | 985 | } |
985 | 986 | ||
986 | static int ieee80211_get_mesh_params(struct wiphy *wiphy, | 987 | static int ieee80211_get_mesh_config(struct wiphy *wiphy, |
987 | struct net_device *dev, | 988 | struct net_device *dev, |
988 | struct mesh_config *conf) | 989 | struct mesh_config *conf) |
989 | { | 990 | { |
@@ -999,9 +1000,39 @@ static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) | |||
999 | return (mask >> (parm-1)) & 0x1; | 1000 | return (mask >> (parm-1)) & 0x1; |
1000 | } | 1001 | } |
1001 | 1002 | ||
1002 | static int ieee80211_set_mesh_params(struct wiphy *wiphy, | 1003 | static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, |
1003 | struct net_device *dev, | 1004 | const struct mesh_setup *setup) |
1004 | const struct mesh_config *nconf, u32 mask) | 1005 | { |
1006 | u8 *new_ie; | ||
1007 | const u8 *old_ie; | ||
1008 | |||
1009 | /* first allocate the new vendor information element */ | ||
1010 | new_ie = NULL; | ||
1011 | old_ie = ifmsh->vendor_ie; | ||
1012 | |||
1013 | ifmsh->vendor_ie_len = setup->vendor_ie_len; | ||
1014 | if (setup->vendor_ie_len) { | ||
1015 | new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len, | ||
1016 | GFP_KERNEL); | ||
1017 | if (!new_ie) | ||
1018 | return -ENOMEM; | ||
1019 | } | ||
1020 | |||
1021 | /* now copy the rest of the setup parameters */ | ||
1022 | ifmsh->mesh_id_len = setup->mesh_id_len; | ||
1023 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | ||
1024 | ifmsh->mesh_pp_id = setup->path_sel_proto; | ||
1025 | ifmsh->mesh_pm_id = setup->path_metric; | ||
1026 | ifmsh->vendor_ie = new_ie; | ||
1027 | |||
1028 | kfree(old_ie); | ||
1029 | |||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | static int ieee80211_update_mesh_config(struct wiphy *wiphy, | ||
1034 | struct net_device *dev, u32 mask, | ||
1035 | const struct mesh_config *nconf) | ||
1005 | { | 1036 | { |
1006 | struct mesh_config *conf; | 1037 | struct mesh_config *conf; |
1007 | struct ieee80211_sub_if_data *sdata; | 1038 | struct ieee80211_sub_if_data *sdata; |
@@ -1024,6 +1055,8 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy, | |||
1024 | conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; | 1055 | conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; |
1025 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) | 1056 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) |
1026 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | 1057 | conf->dot11MeshTTL = nconf->dot11MeshTTL; |
1058 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) | ||
1059 | conf->dot11MeshTTL = nconf->element_ttl; | ||
1027 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1060 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) |
1028 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1061 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1029 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) | 1062 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) |
@@ -1050,6 +1083,31 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy, | |||
1050 | return 0; | 1083 | return 0; |
1051 | } | 1084 | } |
1052 | 1085 | ||
1086 | static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | ||
1087 | const struct mesh_config *conf, | ||
1088 | const struct mesh_setup *setup) | ||
1089 | { | ||
1090 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1091 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1092 | int err; | ||
1093 | |||
1094 | memcpy(&ifmsh->mshcfg, conf, sizeof(struct mesh_config)); | ||
1095 | err = copy_mesh_setup(ifmsh, setup); | ||
1096 | if (err) | ||
1097 | return err; | ||
1098 | ieee80211_start_mesh(sdata); | ||
1099 | |||
1100 | return 0; | ||
1101 | } | ||
1102 | |||
1103 | static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) | ||
1104 | { | ||
1105 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1106 | |||
1107 | ieee80211_stop_mesh(sdata); | ||
1108 | |||
1109 | return 0; | ||
1110 | } | ||
1053 | #endif | 1111 | #endif |
1054 | 1112 | ||
1055 | static int ieee80211_change_bss(struct wiphy *wiphy, | 1113 | static int ieee80211_change_bss(struct wiphy *wiphy, |
@@ -1108,6 +1166,12 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1108 | sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; | 1166 | sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; |
1109 | } | 1167 | } |
1110 | 1168 | ||
1169 | if (params->ht_opmode >= 0) { | ||
1170 | sdata->vif.bss_conf.ht_operation_mode = | ||
1171 | (u16) params->ht_opmode; | ||
1172 | changed |= BSS_CHANGED_HT; | ||
1173 | } | ||
1174 | |||
1111 | ieee80211_bss_info_change_notify(sdata, changed); | 1175 | ieee80211_bss_info_change_notify(sdata, changed); |
1112 | 1176 | ||
1113 | return 0; | 1177 | return 0; |
@@ -1299,6 +1363,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1299 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1363 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1300 | int err; | 1364 | int err; |
1301 | 1365 | ||
1366 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { | ||
1367 | err = drv_set_frag_threshold(local, wiphy->frag_threshold); | ||
1368 | |||
1369 | if (err) | ||
1370 | return err; | ||
1371 | } | ||
1372 | |||
1302 | if (changed & WIPHY_PARAM_COVERAGE_CLASS) { | 1373 | if (changed & WIPHY_PARAM_COVERAGE_CLASS) { |
1303 | err = drv_set_coverage_class(local, wiphy->coverage_class); | 1374 | err = drv_set_coverage_class(local, wiphy->coverage_class); |
1304 | 1375 | ||
@@ -1522,6 +1593,37 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1522 | return 0; | 1593 | return 0; |
1523 | } | 1594 | } |
1524 | 1595 | ||
1596 | static int ieee80211_remain_on_channel_hw(struct ieee80211_local *local, | ||
1597 | struct net_device *dev, | ||
1598 | struct ieee80211_channel *chan, | ||
1599 | enum nl80211_channel_type chantype, | ||
1600 | unsigned int duration, u64 *cookie) | ||
1601 | { | ||
1602 | int ret; | ||
1603 | u32 random_cookie; | ||
1604 | |||
1605 | lockdep_assert_held(&local->mtx); | ||
1606 | |||
1607 | if (local->hw_roc_cookie) | ||
1608 | return -EBUSY; | ||
1609 | /* must be nonzero */ | ||
1610 | random_cookie = random32() | 1; | ||
1611 | |||
1612 | *cookie = random_cookie; | ||
1613 | local->hw_roc_dev = dev; | ||
1614 | local->hw_roc_cookie = random_cookie; | ||
1615 | local->hw_roc_channel = chan; | ||
1616 | local->hw_roc_channel_type = chantype; | ||
1617 | local->hw_roc_duration = duration; | ||
1618 | ret = drv_remain_on_channel(local, chan, chantype, duration); | ||
1619 | if (ret) { | ||
1620 | local->hw_roc_channel = NULL; | ||
1621 | local->hw_roc_cookie = 0; | ||
1622 | } | ||
1623 | |||
1624 | return ret; | ||
1625 | } | ||
1626 | |||
1525 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 1627 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
1526 | struct net_device *dev, | 1628 | struct net_device *dev, |
1527 | struct ieee80211_channel *chan, | 1629 | struct ieee80211_channel *chan, |
@@ -1530,41 +1632,121 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
1530 | u64 *cookie) | 1632 | u64 *cookie) |
1531 | { | 1633 | { |
1532 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1634 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1635 | struct ieee80211_local *local = sdata->local; | ||
1636 | |||
1637 | if (local->ops->remain_on_channel) { | ||
1638 | int ret; | ||
1639 | |||
1640 | mutex_lock(&local->mtx); | ||
1641 | ret = ieee80211_remain_on_channel_hw(local, dev, | ||
1642 | chan, channel_type, | ||
1643 | duration, cookie); | ||
1644 | local->hw_roc_for_tx = false; | ||
1645 | mutex_unlock(&local->mtx); | ||
1646 | |||
1647 | return ret; | ||
1648 | } | ||
1533 | 1649 | ||
1534 | return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, | 1650 | return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, |
1535 | duration, cookie); | 1651 | duration, cookie); |
1536 | } | 1652 | } |
1537 | 1653 | ||
1654 | static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local, | ||
1655 | u64 cookie) | ||
1656 | { | ||
1657 | int ret; | ||
1658 | |||
1659 | lockdep_assert_held(&local->mtx); | ||
1660 | |||
1661 | if (local->hw_roc_cookie != cookie) | ||
1662 | return -ENOENT; | ||
1663 | |||
1664 | ret = drv_cancel_remain_on_channel(local); | ||
1665 | if (ret) | ||
1666 | return ret; | ||
1667 | |||
1668 | local->hw_roc_cookie = 0; | ||
1669 | local->hw_roc_channel = NULL; | ||
1670 | |||
1671 | ieee80211_recalc_idle(local); | ||
1672 | |||
1673 | return 0; | ||
1674 | } | ||
1675 | |||
1538 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | 1676 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, |
1539 | struct net_device *dev, | 1677 | struct net_device *dev, |
1540 | u64 cookie) | 1678 | u64 cookie) |
1541 | { | 1679 | { |
1542 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1680 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1681 | struct ieee80211_local *local = sdata->local; | ||
1682 | |||
1683 | if (local->ops->cancel_remain_on_channel) { | ||
1684 | int ret; | ||
1685 | |||
1686 | mutex_lock(&local->mtx); | ||
1687 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | ||
1688 | mutex_unlock(&local->mtx); | ||
1689 | |||
1690 | return ret; | ||
1691 | } | ||
1543 | 1692 | ||
1544 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1693 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1545 | } | 1694 | } |
1546 | 1695 | ||
1696 | static enum work_done_result | ||
1697 | ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | ||
1698 | { | ||
1699 | /* | ||
1700 | * Use the data embedded in the work struct for reporting | ||
1701 | * here so if the driver mangled the SKB before dropping | ||
1702 | * it (which is the only way we really should get here) | ||
1703 | * then we don't report mangled data. | ||
1704 | * | ||
1705 | * If there was no wait time, then by the time we get here | ||
1706 | * the driver will likely not have reported the status yet, | ||
1707 | * so in that case userspace will have to deal with it. | ||
1708 | */ | ||
1709 | |||
1710 | if (wk->offchan_tx.wait && wk->offchan_tx.frame) | ||
1711 | cfg80211_mgmt_tx_status(wk->sdata->dev, | ||
1712 | (unsigned long) wk->offchan_tx.frame, | ||
1713 | wk->ie, wk->ie_len, false, GFP_KERNEL); | ||
1714 | |||
1715 | return WORK_DONE_DESTROY; | ||
1716 | } | ||
1717 | |||
1547 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | 1718 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
1548 | struct ieee80211_channel *chan, | 1719 | struct ieee80211_channel *chan, bool offchan, |
1549 | enum nl80211_channel_type channel_type, | 1720 | enum nl80211_channel_type channel_type, |
1550 | bool channel_type_valid, | 1721 | bool channel_type_valid, unsigned int wait, |
1551 | const u8 *buf, size_t len, u64 *cookie) | 1722 | const u8 *buf, size_t len, u64 *cookie) |
1552 | { | 1723 | { |
1553 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1724 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1554 | struct ieee80211_local *local = sdata->local; | 1725 | struct ieee80211_local *local = sdata->local; |
1555 | struct sk_buff *skb; | 1726 | struct sk_buff *skb; |
1556 | struct sta_info *sta; | 1727 | struct sta_info *sta; |
1728 | struct ieee80211_work *wk; | ||
1557 | const struct ieee80211_mgmt *mgmt = (void *)buf; | 1729 | const struct ieee80211_mgmt *mgmt = (void *)buf; |
1558 | u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | 1730 | u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | |
1559 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 1731 | IEEE80211_TX_CTL_REQ_TX_STATUS; |
1732 | bool is_offchan = false; | ||
1560 | 1733 | ||
1561 | /* Check that we are on the requested channel for transmission */ | 1734 | /* Check that we are on the requested channel for transmission */ |
1562 | if (chan != local->tmp_channel && | 1735 | if (chan != local->tmp_channel && |
1563 | chan != local->oper_channel) | 1736 | chan != local->oper_channel) |
1564 | return -EBUSY; | 1737 | is_offchan = true; |
1565 | if (channel_type_valid && | 1738 | if (channel_type_valid && |
1566 | (channel_type != local->tmp_channel_type && | 1739 | (channel_type != local->tmp_channel_type && |
1567 | channel_type != local->_oper_channel_type)) | 1740 | channel_type != local->_oper_channel_type)) |
1741 | is_offchan = true; | ||
1742 | |||
1743 | if (chan == local->hw_roc_channel) { | ||
1744 | /* TODO: check channel type? */ | ||
1745 | is_offchan = false; | ||
1746 | flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | ||
1747 | } | ||
1748 | |||
1749 | if (is_offchan && !offchan) | ||
1568 | return -EBUSY; | 1750 | return -EBUSY; |
1569 | 1751 | ||
1570 | switch (sdata->vif.type) { | 1752 | switch (sdata->vif.type) { |
@@ -1572,6 +1754,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1572 | case NL80211_IFTYPE_AP: | 1754 | case NL80211_IFTYPE_AP: |
1573 | case NL80211_IFTYPE_AP_VLAN: | 1755 | case NL80211_IFTYPE_AP_VLAN: |
1574 | case NL80211_IFTYPE_P2P_GO: | 1756 | case NL80211_IFTYPE_P2P_GO: |
1757 | case NL80211_IFTYPE_MESH_POINT: | ||
1575 | if (!ieee80211_is_action(mgmt->frame_control) || | 1758 | if (!ieee80211_is_action(mgmt->frame_control) || |
1576 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 1759 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) |
1577 | break; | 1760 | break; |
@@ -1598,12 +1781,128 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1598 | IEEE80211_SKB_CB(skb)->flags = flags; | 1781 | IEEE80211_SKB_CB(skb)->flags = flags; |
1599 | 1782 | ||
1600 | skb->dev = sdata->dev; | 1783 | skb->dev = sdata->dev; |
1601 | ieee80211_tx_skb(sdata, skb); | ||
1602 | 1784 | ||
1603 | *cookie = (unsigned long) skb; | 1785 | *cookie = (unsigned long) skb; |
1786 | |||
1787 | if (is_offchan && local->ops->remain_on_channel) { | ||
1788 | unsigned int duration; | ||
1789 | int ret; | ||
1790 | |||
1791 | mutex_lock(&local->mtx); | ||
1792 | /* | ||
1793 | * If the duration is zero, then the driver | ||
1794 | * wouldn't actually do anything. Set it to | ||
1795 | * 100 for now. | ||
1796 | * | ||
1797 | * TODO: cancel the off-channel operation | ||
1798 | * when we get the SKB's TX status and | ||
1799 | * the wait time was zero before. | ||
1800 | */ | ||
1801 | duration = 100; | ||
1802 | if (wait) | ||
1803 | duration = wait; | ||
1804 | ret = ieee80211_remain_on_channel_hw(local, dev, chan, | ||
1805 | channel_type, | ||
1806 | duration, cookie); | ||
1807 | if (ret) { | ||
1808 | kfree_skb(skb); | ||
1809 | mutex_unlock(&local->mtx); | ||
1810 | return ret; | ||
1811 | } | ||
1812 | |||
1813 | local->hw_roc_for_tx = true; | ||
1814 | local->hw_roc_duration = wait; | ||
1815 | |||
1816 | /* | ||
1817 | * queue up frame for transmission after | ||
1818 | * ieee80211_ready_on_channel call | ||
1819 | */ | ||
1820 | |||
1821 | /* modify cookie to prevent API mismatches */ | ||
1822 | *cookie ^= 2; | ||
1823 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | ||
1824 | local->hw_roc_skb = skb; | ||
1825 | mutex_unlock(&local->mtx); | ||
1826 | |||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | /* | ||
1831 | * Can transmit right away if the channel was the | ||
1832 | * right one and there's no wait involved... If a | ||
1833 | * wait is involved, we might otherwise not be on | ||
1834 | * the right channel for long enough! | ||
1835 | */ | ||
1836 | if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) { | ||
1837 | ieee80211_tx_skb(sdata, skb); | ||
1838 | return 0; | ||
1839 | } | ||
1840 | |||
1841 | wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL); | ||
1842 | if (!wk) { | ||
1843 | kfree_skb(skb); | ||
1844 | return -ENOMEM; | ||
1845 | } | ||
1846 | |||
1847 | wk->type = IEEE80211_WORK_OFFCHANNEL_TX; | ||
1848 | wk->chan = chan; | ||
1849 | wk->sdata = sdata; | ||
1850 | wk->done = ieee80211_offchan_tx_done; | ||
1851 | wk->offchan_tx.frame = skb; | ||
1852 | wk->offchan_tx.wait = wait; | ||
1853 | wk->ie_len = len; | ||
1854 | memcpy(wk->ie, buf, len); | ||
1855 | |||
1856 | ieee80211_add_work(wk); | ||
1604 | return 0; | 1857 | return 0; |
1605 | } | 1858 | } |
1606 | 1859 | ||
1860 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | ||
1861 | struct net_device *dev, | ||
1862 | u64 cookie) | ||
1863 | { | ||
1864 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1865 | struct ieee80211_local *local = sdata->local; | ||
1866 | struct ieee80211_work *wk; | ||
1867 | int ret = -ENOENT; | ||
1868 | |||
1869 | mutex_lock(&local->mtx); | ||
1870 | |||
1871 | if (local->ops->cancel_remain_on_channel) { | ||
1872 | cookie ^= 2; | ||
1873 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | ||
1874 | |||
1875 | if (ret == 0) { | ||
1876 | kfree_skb(local->hw_roc_skb); | ||
1877 | local->hw_roc_skb = NULL; | ||
1878 | } | ||
1879 | |||
1880 | mutex_unlock(&local->mtx); | ||
1881 | |||
1882 | return ret; | ||
1883 | } | ||
1884 | |||
1885 | list_for_each_entry(wk, &local->work_list, list) { | ||
1886 | if (wk->sdata != sdata) | ||
1887 | continue; | ||
1888 | |||
1889 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
1890 | continue; | ||
1891 | |||
1892 | if (cookie != (unsigned long) wk->offchan_tx.frame) | ||
1893 | continue; | ||
1894 | |||
1895 | wk->timeout = jiffies; | ||
1896 | |||
1897 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
1898 | ret = 0; | ||
1899 | break; | ||
1900 | } | ||
1901 | mutex_unlock(&local->mtx); | ||
1902 | |||
1903 | return ret; | ||
1904 | } | ||
1905 | |||
1607 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | 1906 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
1608 | struct net_device *dev, | 1907 | struct net_device *dev, |
1609 | u16 frame_type, bool reg) | 1908 | u16 frame_type, bool reg) |
@@ -1621,6 +1920,23 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | |||
1621 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | 1920 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); |
1622 | } | 1921 | } |
1623 | 1922 | ||
1923 | static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) | ||
1924 | { | ||
1925 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1926 | |||
1927 | if (local->started) | ||
1928 | return -EOPNOTSUPP; | ||
1929 | |||
1930 | return drv_set_antenna(local, tx_ant, rx_ant); | ||
1931 | } | ||
1932 | |||
1933 | static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant) | ||
1934 | { | ||
1935 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1936 | |||
1937 | return drv_get_antenna(local, tx_ant, rx_ant); | ||
1938 | } | ||
1939 | |||
1624 | struct cfg80211_ops mac80211_config_ops = { | 1940 | struct cfg80211_ops mac80211_config_ops = { |
1625 | .add_virtual_intf = ieee80211_add_iface, | 1941 | .add_virtual_intf = ieee80211_add_iface, |
1626 | .del_virtual_intf = ieee80211_del_iface, | 1942 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1645,8 +1961,10 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1645 | .change_mpath = ieee80211_change_mpath, | 1961 | .change_mpath = ieee80211_change_mpath, |
1646 | .get_mpath = ieee80211_get_mpath, | 1962 | .get_mpath = ieee80211_get_mpath, |
1647 | .dump_mpath = ieee80211_dump_mpath, | 1963 | .dump_mpath = ieee80211_dump_mpath, |
1648 | .set_mesh_params = ieee80211_set_mesh_params, | 1964 | .update_mesh_config = ieee80211_update_mesh_config, |
1649 | .get_mesh_params = ieee80211_get_mesh_params, | 1965 | .get_mesh_config = ieee80211_get_mesh_config, |
1966 | .join_mesh = ieee80211_join_mesh, | ||
1967 | .leave_mesh = ieee80211_leave_mesh, | ||
1650 | #endif | 1968 | #endif |
1651 | .change_bss = ieee80211_change_bss, | 1969 | .change_bss = ieee80211_change_bss, |
1652 | .set_txq_params = ieee80211_set_txq_params, | 1970 | .set_txq_params = ieee80211_set_txq_params, |
@@ -1671,6 +1989,9 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1671 | .remain_on_channel = ieee80211_remain_on_channel, | 1989 | .remain_on_channel = ieee80211_remain_on_channel, |
1672 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1990 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1673 | .mgmt_tx = ieee80211_mgmt_tx, | 1991 | .mgmt_tx = ieee80211_mgmt_tx, |
1992 | .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait, | ||
1674 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 1993 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
1675 | .mgmt_frame_register = ieee80211_mgmt_frame_register, | 1994 | .mgmt_frame_register = ieee80211_mgmt_frame_register, |
1995 | .set_antenna = ieee80211_set_antenna, | ||
1996 | .get_antenna = ieee80211_get_antenna, | ||
1676 | }; | 1997 | }; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 18260aa99c56..1f02e599a318 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -21,16 +21,30 @@ int mac80211_open_file_generic(struct inode *inode, struct file *file) | |||
21 | return 0; | 21 | return 0; |
22 | } | 22 | } |
23 | 23 | ||
24 | #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ | 24 | #define DEBUGFS_FORMAT_BUFFER_SIZE 100 |
25 | |||
26 | int mac80211_format_buffer(char __user *userbuf, size_t count, | ||
27 | loff_t *ppos, char *fmt, ...) | ||
28 | { | ||
29 | va_list args; | ||
30 | char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; | ||
31 | int res; | ||
32 | |||
33 | va_start(args, fmt); | ||
34 | res = vscnprintf(buf, sizeof(buf), fmt, args); | ||
35 | va_end(args); | ||
36 | |||
37 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | ||
38 | } | ||
39 | |||
40 | #define DEBUGFS_READONLY_FILE(name, fmt, value...) \ | ||
25 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ | 41 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ |
26 | size_t count, loff_t *ppos) \ | 42 | size_t count, loff_t *ppos) \ |
27 | { \ | 43 | { \ |
28 | struct ieee80211_local *local = file->private_data; \ | 44 | struct ieee80211_local *local = file->private_data; \ |
29 | char buf[buflen]; \ | ||
30 | int res; \ | ||
31 | \ | 45 | \ |
32 | res = scnprintf(buf, buflen, fmt "\n", ##value); \ | 46 | return mac80211_format_buffer(userbuf, count, ppos, \ |
33 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ | 47 | fmt "\n", ##value); \ |
34 | } \ | 48 | } \ |
35 | \ | 49 | \ |
36 | static const struct file_operations name## _ops = { \ | 50 | static const struct file_operations name## _ops = { \ |
@@ -46,13 +60,13 @@ static const struct file_operations name## _ops = { \ | |||
46 | debugfs_create_file(#name, mode, phyd, local, &name## _ops); | 60 | debugfs_create_file(#name, mode, phyd, local, &name## _ops); |
47 | 61 | ||
48 | 62 | ||
49 | DEBUGFS_READONLY_FILE(frequency, 20, "%d", | 63 | DEBUGFS_READONLY_FILE(frequency, "%d", |
50 | local->hw.conf.channel->center_freq); | 64 | local->hw.conf.channel->center_freq); |
51 | DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", | 65 | DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", |
52 | local->total_ps_buffered); | 66 | local->total_ps_buffered); |
53 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", | 67 | DEBUGFS_READONLY_FILE(wep_iv, "%#08x", |
54 | local->wep_iv & 0xffffff); | 68 | local->wep_iv & 0xffffff); |
55 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", | 69 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", |
56 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); | 70 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); |
57 | 71 | ||
58 | static ssize_t tsf_read(struct file *file, char __user *user_buf, | 72 | static ssize_t tsf_read(struct file *file, char __user *user_buf, |
@@ -60,13 +74,11 @@ static ssize_t tsf_read(struct file *file, char __user *user_buf, | |||
60 | { | 74 | { |
61 | struct ieee80211_local *local = file->private_data; | 75 | struct ieee80211_local *local = file->private_data; |
62 | u64 tsf; | 76 | u64 tsf; |
63 | char buf[100]; | ||
64 | 77 | ||
65 | tsf = drv_get_tsf(local); | 78 | tsf = drv_get_tsf(local); |
66 | 79 | ||
67 | snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); | 80 | return mac80211_format_buffer(user_buf, count, ppos, "0x%016llx\n", |
68 | 81 | (unsigned long long) tsf); | |
69 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); | ||
70 | } | 82 | } |
71 | 83 | ||
72 | static ssize_t tsf_write(struct file *file, | 84 | static ssize_t tsf_write(struct file *file, |
@@ -131,12 +143,9 @@ static ssize_t noack_read(struct file *file, char __user *user_buf, | |||
131 | size_t count, loff_t *ppos) | 143 | size_t count, loff_t *ppos) |
132 | { | 144 | { |
133 | struct ieee80211_local *local = file->private_data; | 145 | struct ieee80211_local *local = file->private_data; |
134 | int res; | ||
135 | char buf[10]; | ||
136 | 146 | ||
137 | res = scnprintf(buf, sizeof(buf), "%d\n", local->wifi_wme_noack_test); | 147 | return mac80211_format_buffer(user_buf, count, ppos, "%d\n", |
138 | 148 | local->wifi_wme_noack_test); | |
139 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
140 | } | 149 | } |
141 | 150 | ||
142 | static ssize_t noack_write(struct file *file, | 151 | static ssize_t noack_write(struct file *file, |
@@ -168,12 +177,8 @@ static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, | |||
168 | size_t count, loff_t *ppos) | 177 | size_t count, loff_t *ppos) |
169 | { | 178 | { |
170 | struct ieee80211_local *local = file->private_data; | 179 | struct ieee80211_local *local = file->private_data; |
171 | int res; | 180 | return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n", |
172 | char buf[10]; | 181 | local->uapsd_queues); |
173 | |||
174 | res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_queues); | ||
175 | |||
176 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
177 | } | 182 | } |
178 | 183 | ||
179 | static ssize_t uapsd_queues_write(struct file *file, | 184 | static ssize_t uapsd_queues_write(struct file *file, |
@@ -215,12 +220,9 @@ static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf, | |||
215 | size_t count, loff_t *ppos) | 220 | size_t count, loff_t *ppos) |
216 | { | 221 | { |
217 | struct ieee80211_local *local = file->private_data; | 222 | struct ieee80211_local *local = file->private_data; |
218 | int res; | ||
219 | char buf[10]; | ||
220 | 223 | ||
221 | res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_max_sp_len); | 224 | return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n", |
222 | 225 | local->uapsd_max_sp_len); | |
223 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
224 | } | 226 | } |
225 | 227 | ||
226 | static ssize_t uapsd_max_sp_len_write(struct file *file, | 228 | static ssize_t uapsd_max_sp_len_write(struct file *file, |
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h index 09cc9be34796..7c87529630f5 100644 --- a/net/mac80211/debugfs.h +++ b/net/mac80211/debugfs.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #ifdef CONFIG_MAC80211_DEBUGFS | 4 | #ifdef CONFIG_MAC80211_DEBUGFS |
5 | extern void debugfs_hw_add(struct ieee80211_local *local); | 5 | extern void debugfs_hw_add(struct ieee80211_local *local); |
6 | extern int mac80211_open_file_generic(struct inode *inode, struct file *file); | 6 | extern int mac80211_open_file_generic(struct inode *inode, struct file *file); |
7 | extern int mac80211_format_buffer(char __user *userbuf, size_t count, | ||
8 | loff_t *ppos, char *fmt, ...); | ||
7 | #else | 9 | #else |
8 | static inline void debugfs_hw_add(struct ieee80211_local *local) | 10 | static inline void debugfs_hw_add(struct ieee80211_local *local) |
9 | { | 11 | { |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 1243d1db5c59..f7ef3477c24a 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -15,18 +15,17 @@ | |||
15 | #include "debugfs.h" | 15 | #include "debugfs.h" |
16 | #include "debugfs_key.h" | 16 | #include "debugfs_key.h" |
17 | 17 | ||
18 | #define KEY_READ(name, prop, buflen, format_string) \ | 18 | #define KEY_READ(name, prop, format_string) \ |
19 | static ssize_t key_##name##_read(struct file *file, \ | 19 | static ssize_t key_##name##_read(struct file *file, \ |
20 | char __user *userbuf, \ | 20 | char __user *userbuf, \ |
21 | size_t count, loff_t *ppos) \ | 21 | size_t count, loff_t *ppos) \ |
22 | { \ | 22 | { \ |
23 | char buf[buflen]; \ | ||
24 | struct ieee80211_key *key = file->private_data; \ | 23 | struct ieee80211_key *key = file->private_data; \ |
25 | int res = scnprintf(buf, buflen, format_string, key->prop); \ | 24 | return mac80211_format_buffer(userbuf, count, ppos, \ |
26 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ | 25 | format_string, key->prop); \ |
27 | } | 26 | } |
28 | #define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n") | 27 | #define KEY_READ_D(name) KEY_READ(name, name, "%d\n") |
29 | #define KEY_READ_X(name) KEY_READ(name, name, 20, "0x%x\n") | 28 | #define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n") |
30 | 29 | ||
31 | #define KEY_OPS(name) \ | 30 | #define KEY_OPS(name) \ |
32 | static const struct file_operations key_ ##name## _ops = { \ | 31 | static const struct file_operations key_ ##name## _ops = { \ |
@@ -39,9 +38,9 @@ static const struct file_operations key_ ##name## _ops = { \ | |||
39 | KEY_READ_##format(name) \ | 38 | KEY_READ_##format(name) \ |
40 | KEY_OPS(name) | 39 | KEY_OPS(name) |
41 | 40 | ||
42 | #define KEY_CONF_READ(name, buflen, format_string) \ | 41 | #define KEY_CONF_READ(name, format_string) \ |
43 | KEY_READ(conf_##name, conf.name, buflen, format_string) | 42 | KEY_READ(conf_##name, conf.name, format_string) |
44 | #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n") | 43 | #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n") |
45 | 44 | ||
46 | #define KEY_CONF_OPS(name) \ | 45 | #define KEY_CONF_OPS(name) \ |
47 | static const struct file_operations key_ ##name## _ops = { \ | 46 | static const struct file_operations key_ ##name## _ops = { \ |
@@ -59,7 +58,7 @@ KEY_CONF_FILE(keyidx, D); | |||
59 | KEY_CONF_FILE(hw_key_idx, D); | 58 | KEY_CONF_FILE(hw_key_idx, D); |
60 | KEY_FILE(flags, X); | 59 | KEY_FILE(flags, X); |
61 | KEY_FILE(tx_rx_count, D); | 60 | KEY_FILE(tx_rx_count, D); |
62 | KEY_READ(ifindex, sdata->name, IFNAMSIZ + 2, "%s\n"); | 61 | KEY_READ(ifindex, sdata->name, "%s\n"); |
63 | KEY_OPS(ifindex); | 62 | KEY_OPS(ifindex); |
64 | 63 | ||
65 | static ssize_t key_algorithm_read(struct file *file, | 64 | static ssize_t key_algorithm_read(struct file *file, |
@@ -275,7 +274,8 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | |||
275 | debugfs_remove_recursive(key->debugfs.dir); | 274 | debugfs_remove_recursive(key->debugfs.dir); |
276 | key->debugfs.dir = NULL; | 275 | key->debugfs.dir = NULL; |
277 | } | 276 | } |
278 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | 277 | |
278 | void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | ||
279 | { | 279 | { |
280 | char buf[50]; | 280 | char buf[50]; |
281 | struct ieee80211_key *key; | 281 | struct ieee80211_key *key; |
@@ -283,25 +283,29 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | |||
283 | if (!sdata->debugfs.dir) | 283 | if (!sdata->debugfs.dir) |
284 | return; | 284 | return; |
285 | 285 | ||
286 | /* this is running under the key lock */ | 286 | lockdep_assert_held(&sdata->local->key_mtx); |
287 | 287 | ||
288 | key = sdata->default_key; | 288 | if (sdata->default_unicast_key) { |
289 | if (key) { | 289 | key = sdata->default_unicast_key; |
290 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 290 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
291 | sdata->debugfs.default_key = | 291 | sdata->debugfs.default_unicast_key = |
292 | debugfs_create_symlink("default_key", | 292 | debugfs_create_symlink("default_unicast_key", |
293 | sdata->debugfs.dir, buf); | 293 | sdata->debugfs.dir, buf); |
294 | } else | 294 | } else { |
295 | ieee80211_debugfs_key_remove_default(sdata); | 295 | debugfs_remove(sdata->debugfs.default_unicast_key); |
296 | } | 296 | sdata->debugfs.default_unicast_key = NULL; |
297 | 297 | } | |
298 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) | ||
299 | { | ||
300 | if (!sdata) | ||
301 | return; | ||
302 | 298 | ||
303 | debugfs_remove(sdata->debugfs.default_key); | 299 | if (sdata->default_multicast_key) { |
304 | sdata->debugfs.default_key = NULL; | 300 | key = sdata->default_multicast_key; |
301 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | ||
302 | sdata->debugfs.default_multicast_key = | ||
303 | debugfs_create_symlink("default_multicast_key", | ||
304 | sdata->debugfs.dir, buf); | ||
305 | } else { | ||
306 | debugfs_remove(sdata->debugfs.default_multicast_key); | ||
307 | sdata->debugfs.default_multicast_key = NULL; | ||
308 | } | ||
305 | } | 309 | } |
306 | 310 | ||
307 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | 311 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h index 54717b4e1371..32adc77e9c77 100644 --- a/net/mac80211/debugfs_key.h +++ b/net/mac80211/debugfs_key.h | |||
@@ -4,8 +4,7 @@ | |||
4 | #ifdef CONFIG_MAC80211_DEBUGFS | 4 | #ifdef CONFIG_MAC80211_DEBUGFS |
5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); | 5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); |
6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); | 6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); |
7 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); | ||
9 | void ieee80211_debugfs_key_add_mgmt_default( | 8 | void ieee80211_debugfs_key_add_mgmt_default( |
10 | struct ieee80211_sub_if_data *sdata); | 9 | struct ieee80211_sub_if_data *sdata); |
11 | void ieee80211_debugfs_key_remove_mgmt_default( | 10 | void ieee80211_debugfs_key_remove_mgmt_default( |
@@ -17,10 +16,7 @@ static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
17 | {} | 16 | {} |
18 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | 17 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) |
19 | {} | 18 | {} |
20 | static inline void ieee80211_debugfs_key_add_default( | 19 | static inline void ieee80211_debugfs_key_update_default( |
21 | struct ieee80211_sub_if_data *sdata) | ||
22 | {} | ||
23 | static inline void ieee80211_debugfs_key_remove_default( | ||
24 | struct ieee80211_sub_if_data *sdata) | 20 | struct ieee80211_sub_if_data *sdata) |
25 | {} | 21 | {} |
26 | static inline void ieee80211_debugfs_key_add_mgmt_default( | 22 | static inline void ieee80211_debugfs_key_add_mgmt_default( |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index cbdf36d7841c..2dabdf7680d0 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -251,6 +251,7 @@ IEEE80211_IF_FILE(dot11MeshConfirmTimeout, | |||
251 | IEEE80211_IF_FILE(dot11MeshHoldingTimeout, | 251 | IEEE80211_IF_FILE(dot11MeshHoldingTimeout, |
252 | u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC); | 252 | u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC); |
253 | IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC); | 253 | IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC); |
254 | IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC); | ||
254 | IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC); | 255 | IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC); |
255 | IEEE80211_IF_FILE(dot11MeshMaxPeerLinks, | 256 | IEEE80211_IF_FILE(dot11MeshMaxPeerLinks, |
256 | u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC); | 257 | u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC); |
@@ -355,6 +356,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
355 | MESHPARAMS_ADD(dot11MeshConfirmTimeout); | 356 | MESHPARAMS_ADD(dot11MeshConfirmTimeout); |
356 | MESHPARAMS_ADD(dot11MeshHoldingTimeout); | 357 | MESHPARAMS_ADD(dot11MeshHoldingTimeout); |
357 | MESHPARAMS_ADD(dot11MeshTTL); | 358 | MESHPARAMS_ADD(dot11MeshTTL); |
359 | MESHPARAMS_ADD(element_ttl); | ||
358 | MESHPARAMS_ADD(auto_open_plinks); | 360 | MESHPARAMS_ADD(auto_open_plinks); |
359 | MESHPARAMS_ADD(dot11MeshMaxPeerLinks); | 361 | MESHPARAMS_ADD(dot11MeshMaxPeerLinks); |
360 | MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout); | 362 | MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 4601fea1784d..c04a1396cf8d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -17,20 +17,18 @@ | |||
17 | 17 | ||
18 | /* sta attributtes */ | 18 | /* sta attributtes */ |
19 | 19 | ||
20 | #define STA_READ(name, buflen, field, format_string) \ | 20 | #define STA_READ(name, field, format_string) \ |
21 | static ssize_t sta_ ##name## _read(struct file *file, \ | 21 | static ssize_t sta_ ##name## _read(struct file *file, \ |
22 | char __user *userbuf, \ | 22 | char __user *userbuf, \ |
23 | size_t count, loff_t *ppos) \ | 23 | size_t count, loff_t *ppos) \ |
24 | { \ | 24 | { \ |
25 | int res; \ | ||
26 | struct sta_info *sta = file->private_data; \ | 25 | struct sta_info *sta = file->private_data; \ |
27 | char buf[buflen]; \ | 26 | return mac80211_format_buffer(userbuf, count, ppos, \ |
28 | res = scnprintf(buf, buflen, format_string, sta->field); \ | 27 | format_string, sta->field); \ |
29 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ | ||
30 | } | 28 | } |
31 | #define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n") | 29 | #define STA_READ_D(name, field) STA_READ(name, field, "%d\n") |
32 | #define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n") | 30 | #define STA_READ_U(name, field) STA_READ(name, field, "%u\n") |
33 | #define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n") | 31 | #define STA_READ_S(name, field) STA_READ(name, field, "%s\n") |
34 | 32 | ||
35 | #define STA_OPS(name) \ | 33 | #define STA_OPS(name) \ |
36 | static const struct file_operations sta_ ##name## _ops = { \ | 34 | static const struct file_operations sta_ ##name## _ops = { \ |
@@ -79,22 +77,18 @@ static ssize_t sta_num_ps_buf_frames_read(struct file *file, | |||
79 | char __user *userbuf, | 77 | char __user *userbuf, |
80 | size_t count, loff_t *ppos) | 78 | size_t count, loff_t *ppos) |
81 | { | 79 | { |
82 | char buf[20]; | ||
83 | struct sta_info *sta = file->private_data; | 80 | struct sta_info *sta = file->private_data; |
84 | int res = scnprintf(buf, sizeof(buf), "%u\n", | 81 | return mac80211_format_buffer(userbuf, count, ppos, "%u\n", |
85 | skb_queue_len(&sta->ps_tx_buf)); | 82 | skb_queue_len(&sta->ps_tx_buf)); |
86 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | ||
87 | } | 83 | } |
88 | STA_OPS(num_ps_buf_frames); | 84 | STA_OPS(num_ps_buf_frames); |
89 | 85 | ||
90 | static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf, | 86 | static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf, |
91 | size_t count, loff_t *ppos) | 87 | size_t count, loff_t *ppos) |
92 | { | 88 | { |
93 | char buf[20]; | ||
94 | struct sta_info *sta = file->private_data; | 89 | struct sta_info *sta = file->private_data; |
95 | int res = scnprintf(buf, sizeof(buf), "%d\n", | 90 | return mac80211_format_buffer(userbuf, count, ppos, "%d\n", |
96 | jiffies_to_msecs(jiffies - sta->last_rx)); | 91 | jiffies_to_msecs(jiffies - sta->last_rx)); |
97 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | ||
98 | } | 92 | } |
99 | STA_OPS(inactive_ms); | 93 | STA_OPS(inactive_ms); |
100 | 94 | ||
@@ -118,34 +112,35 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
118 | char buf[71 + STA_TID_NUM * 40], *p = buf; | 112 | char buf[71 + STA_TID_NUM * 40], *p = buf; |
119 | int i; | 113 | int i; |
120 | struct sta_info *sta = file->private_data; | 114 | struct sta_info *sta = file->private_data; |
115 | struct tid_ampdu_rx *tid_rx; | ||
116 | struct tid_ampdu_tx *tid_tx; | ||
117 | |||
118 | rcu_read_lock(); | ||
121 | 119 | ||
122 | spin_lock_bh(&sta->lock); | ||
123 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", | 120 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
124 | sta->ampdu_mlme.dialog_token_allocator + 1); | 121 | sta->ampdu_mlme.dialog_token_allocator + 1); |
125 | p += scnprintf(p, sizeof(buf) + buf - p, | 122 | p += scnprintf(p, sizeof(buf) + buf - p, |
126 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); | 123 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); |
124 | |||
127 | for (i = 0; i < STA_TID_NUM; i++) { | 125 | for (i = 0; i < STA_TID_NUM; i++) { |
126 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); | ||
127 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]); | ||
128 | |||
128 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); | 129 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); |
129 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 130 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_rx); |
130 | !!sta->ampdu_mlme.tid_rx[i]); | ||
131 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 131 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
132 | sta->ampdu_mlme.tid_rx[i] ? | 132 | tid_rx ? tid_rx->dialog_token : 0); |
133 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | ||
134 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", | 133 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
135 | sta->ampdu_mlme.tid_rx[i] ? | 134 | tid_rx ? tid_rx->ssn : 0); |
136 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); | ||
137 | 135 | ||
138 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 136 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_tx); |
139 | !!sta->ampdu_mlme.tid_tx[i]); | ||
140 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 137 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
141 | sta->ampdu_mlme.tid_tx[i] ? | 138 | tid_tx ? tid_tx->dialog_token : 0); |
142 | sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); | ||
143 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", | 139 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", |
144 | sta->ampdu_mlme.tid_tx[i] ? | 140 | tid_tx ? skb_queue_len(&tid_tx->pending) : 0); |
145 | skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); | ||
146 | p += scnprintf(p, sizeof(buf) + buf - p, "\n"); | 141 | p += scnprintf(p, sizeof(buf) + buf - p, "\n"); |
147 | } | 142 | } |
148 | spin_unlock_bh(&sta->lock); | 143 | rcu_read_unlock(); |
149 | 144 | ||
150 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | 145 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); |
151 | } | 146 | } |
@@ -194,7 +189,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu | |||
194 | 189 | ||
195 | if (tx) { | 190 | if (tx) { |
196 | if (start) | 191 | if (start) |
197 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid); | 192 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid, 5000); |
198 | else | 193 | else |
199 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); | 194 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); |
200 | } else { | 195 | } else { |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 16983825f8e8..98d589960a49 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -233,6 +233,20 @@ static inline void drv_get_tkip_seq(struct ieee80211_local *local, | |||
233 | trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16); | 233 | trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16); |
234 | } | 234 | } |
235 | 235 | ||
236 | static inline int drv_set_frag_threshold(struct ieee80211_local *local, | ||
237 | u32 value) | ||
238 | { | ||
239 | int ret = 0; | ||
240 | |||
241 | might_sleep(); | ||
242 | |||
243 | trace_drv_set_frag_threshold(local, value); | ||
244 | if (local->ops->set_frag_threshold) | ||
245 | ret = local->ops->set_frag_threshold(&local->hw, value); | ||
246 | trace_drv_return_int(local, ret); | ||
247 | return ret; | ||
248 | } | ||
249 | |||
236 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, | 250 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, |
237 | u32 value) | 251 | u32 value) |
238 | { | 252 | { |
@@ -353,7 +367,7 @@ static inline void drv_reset_tsf(struct ieee80211_local *local) | |||
353 | 367 | ||
354 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 368 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
355 | { | 369 | { |
356 | int ret = 1; | 370 | int ret = 0; /* default unsuported op for less congestion */ |
357 | 371 | ||
358 | might_sleep(); | 372 | might_sleep(); |
359 | 373 | ||
@@ -428,4 +442,57 @@ static inline void drv_channel_switch(struct ieee80211_local *local, | |||
428 | trace_drv_return_void(local); | 442 | trace_drv_return_void(local); |
429 | } | 443 | } |
430 | 444 | ||
445 | |||
446 | static inline int drv_set_antenna(struct ieee80211_local *local, | ||
447 | u32 tx_ant, u32 rx_ant) | ||
448 | { | ||
449 | int ret = -EOPNOTSUPP; | ||
450 | might_sleep(); | ||
451 | if (local->ops->set_antenna) | ||
452 | ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant); | ||
453 | trace_drv_set_antenna(local, tx_ant, rx_ant, ret); | ||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | static inline int drv_get_antenna(struct ieee80211_local *local, | ||
458 | u32 *tx_ant, u32 *rx_ant) | ||
459 | { | ||
460 | int ret = -EOPNOTSUPP; | ||
461 | might_sleep(); | ||
462 | if (local->ops->get_antenna) | ||
463 | ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant); | ||
464 | trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret); | ||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | static inline int drv_remain_on_channel(struct ieee80211_local *local, | ||
469 | struct ieee80211_channel *chan, | ||
470 | enum nl80211_channel_type chantype, | ||
471 | unsigned int duration) | ||
472 | { | ||
473 | int ret; | ||
474 | |||
475 | might_sleep(); | ||
476 | |||
477 | trace_drv_remain_on_channel(local, chan, chantype, duration); | ||
478 | ret = local->ops->remain_on_channel(&local->hw, chan, chantype, | ||
479 | duration); | ||
480 | trace_drv_return_int(local, ret); | ||
481 | |||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local) | ||
486 | { | ||
487 | int ret; | ||
488 | |||
489 | might_sleep(); | ||
490 | |||
491 | trace_drv_cancel_remain_on_channel(local); | ||
492 | ret = local->ops->cancel_remain_on_channel(&local->hw); | ||
493 | trace_drv_return_int(local, ret); | ||
494 | |||
495 | return ret; | ||
496 | } | ||
497 | |||
431 | #endif /* __MAC80211_DRIVER_OPS */ | 498 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 6831fb1641c8..49c84218b2f4 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -531,6 +531,27 @@ TRACE_EVENT(drv_get_tkip_seq, | |||
531 | ) | 531 | ) |
532 | ); | 532 | ); |
533 | 533 | ||
534 | TRACE_EVENT(drv_set_frag_threshold, | ||
535 | TP_PROTO(struct ieee80211_local *local, u32 value), | ||
536 | |||
537 | TP_ARGS(local, value), | ||
538 | |||
539 | TP_STRUCT__entry( | ||
540 | LOCAL_ENTRY | ||
541 | __field(u32, value) | ||
542 | ), | ||
543 | |||
544 | TP_fast_assign( | ||
545 | LOCAL_ASSIGN; | ||
546 | __entry->value = value; | ||
547 | ), | ||
548 | |||
549 | TP_printk( | ||
550 | LOCAL_PR_FMT " value:%d", | ||
551 | LOCAL_PR_ARG, __entry->value | ||
552 | ) | ||
553 | ); | ||
554 | |||
534 | TRACE_EVENT(drv_set_rts_threshold, | 555 | TRACE_EVENT(drv_set_rts_threshold, |
535 | TP_PROTO(struct ieee80211_local *local, u32 value), | 556 | TP_PROTO(struct ieee80211_local *local, u32 value), |
536 | 557 | ||
@@ -862,6 +883,100 @@ TRACE_EVENT(drv_channel_switch, | |||
862 | ) | 883 | ) |
863 | ); | 884 | ); |
864 | 885 | ||
886 | TRACE_EVENT(drv_set_antenna, | ||
887 | TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret), | ||
888 | |||
889 | TP_ARGS(local, tx_ant, rx_ant, ret), | ||
890 | |||
891 | TP_STRUCT__entry( | ||
892 | LOCAL_ENTRY | ||
893 | __field(u32, tx_ant) | ||
894 | __field(u32, rx_ant) | ||
895 | __field(int, ret) | ||
896 | ), | ||
897 | |||
898 | TP_fast_assign( | ||
899 | LOCAL_ASSIGN; | ||
900 | __entry->tx_ant = tx_ant; | ||
901 | __entry->rx_ant = rx_ant; | ||
902 | __entry->ret = ret; | ||
903 | ), | ||
904 | |||
905 | TP_printk( | ||
906 | LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d", | ||
907 | LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret | ||
908 | ) | ||
909 | ); | ||
910 | |||
911 | TRACE_EVENT(drv_get_antenna, | ||
912 | TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret), | ||
913 | |||
914 | TP_ARGS(local, tx_ant, rx_ant, ret), | ||
915 | |||
916 | TP_STRUCT__entry( | ||
917 | LOCAL_ENTRY | ||
918 | __field(u32, tx_ant) | ||
919 | __field(u32, rx_ant) | ||
920 | __field(int, ret) | ||
921 | ), | ||
922 | |||
923 | TP_fast_assign( | ||
924 | LOCAL_ASSIGN; | ||
925 | __entry->tx_ant = tx_ant; | ||
926 | __entry->rx_ant = rx_ant; | ||
927 | __entry->ret = ret; | ||
928 | ), | ||
929 | |||
930 | TP_printk( | ||
931 | LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d", | ||
932 | LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret | ||
933 | ) | ||
934 | ); | ||
935 | |||
936 | TRACE_EVENT(drv_remain_on_channel, | ||
937 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_channel *chan, | ||
938 | enum nl80211_channel_type chantype, unsigned int duration), | ||
939 | |||
940 | TP_ARGS(local, chan, chantype, duration), | ||
941 | |||
942 | TP_STRUCT__entry( | ||
943 | LOCAL_ENTRY | ||
944 | __field(int, center_freq) | ||
945 | __field(int, channel_type) | ||
946 | __field(unsigned int, duration) | ||
947 | ), | ||
948 | |||
949 | TP_fast_assign( | ||
950 | LOCAL_ASSIGN; | ||
951 | __entry->center_freq = chan->center_freq; | ||
952 | __entry->channel_type = chantype; | ||
953 | __entry->duration = duration; | ||
954 | ), | ||
955 | |||
956 | TP_printk( | ||
957 | LOCAL_PR_FMT " freq:%dMHz duration:%dms", | ||
958 | LOCAL_PR_ARG, __entry->center_freq, __entry->duration | ||
959 | ) | ||
960 | ); | ||
961 | |||
962 | TRACE_EVENT(drv_cancel_remain_on_channel, | ||
963 | TP_PROTO(struct ieee80211_local *local), | ||
964 | |||
965 | TP_ARGS(local), | ||
966 | |||
967 | TP_STRUCT__entry( | ||
968 | LOCAL_ENTRY | ||
969 | ), | ||
970 | |||
971 | TP_fast_assign( | ||
972 | LOCAL_ASSIGN; | ||
973 | ), | ||
974 | |||
975 | TP_printk( | ||
976 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
977 | ) | ||
978 | ); | ||
979 | |||
865 | /* | 980 | /* |
866 | * Tracing for API calls that drivers call. | 981 | * Tracing for API calls that drivers call. |
867 | */ | 982 | */ |
@@ -1099,6 +1214,42 @@ TRACE_EVENT(api_chswitch_done, | |||
1099 | ) | 1214 | ) |
1100 | ); | 1215 | ); |
1101 | 1216 | ||
1217 | TRACE_EVENT(api_ready_on_channel, | ||
1218 | TP_PROTO(struct ieee80211_local *local), | ||
1219 | |||
1220 | TP_ARGS(local), | ||
1221 | |||
1222 | TP_STRUCT__entry( | ||
1223 | LOCAL_ENTRY | ||
1224 | ), | ||
1225 | |||
1226 | TP_fast_assign( | ||
1227 | LOCAL_ASSIGN; | ||
1228 | ), | ||
1229 | |||
1230 | TP_printk( | ||
1231 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1232 | ) | ||
1233 | ); | ||
1234 | |||
1235 | TRACE_EVENT(api_remain_on_channel_expired, | ||
1236 | TP_PROTO(struct ieee80211_local *local), | ||
1237 | |||
1238 | TP_ARGS(local), | ||
1239 | |||
1240 | TP_STRUCT__entry( | ||
1241 | LOCAL_ENTRY | ||
1242 | ), | ||
1243 | |||
1244 | TP_fast_assign( | ||
1245 | LOCAL_ASSIGN; | ||
1246 | ), | ||
1247 | |||
1248 | TP_printk( | ||
1249 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1250 | ) | ||
1251 | ); | ||
1252 | |||
1102 | /* | 1253 | /* |
1103 | * Tracing for internal functions | 1254 | * Tracing for internal functions |
1104 | * (which may also be called in response to driver calls) | 1255 | * (which may also be called in response to driver calls) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 239c4836a946..53c7077ffd4f 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -780,6 +780,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
780 | 780 | ||
781 | mutex_lock(&sdata->u.ibss.mtx); | 781 | mutex_lock(&sdata->u.ibss.mtx); |
782 | 782 | ||
783 | if (!sdata->u.ibss.ssid_len) | ||
784 | goto mgmt_out; /* not ready to merge yet */ | ||
785 | |||
783 | switch (fc & IEEE80211_FCTL_STYPE) { | 786 | switch (fc & IEEE80211_FCTL_STYPE) { |
784 | case IEEE80211_STYPE_PROBE_REQ: | 787 | case IEEE80211_STYPE_PROBE_REQ: |
785 | ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); | 788 | ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); |
@@ -797,6 +800,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
797 | break; | 800 | break; |
798 | } | 801 | } |
799 | 802 | ||
803 | mgmt_out: | ||
800 | mutex_unlock(&sdata->u.ibss.mtx); | 804 | mutex_unlock(&sdata->u.ibss.mtx); |
801 | } | 805 | } |
802 | 806 | ||
@@ -915,6 +919,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
915 | 919 | ||
916 | sdata->u.ibss.privacy = params->privacy; | 920 | sdata->u.ibss.privacy = params->privacy; |
917 | sdata->u.ibss.basic_rates = params->basic_rates; | 921 | sdata->u.ibss.basic_rates = params->basic_rates; |
922 | memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, | ||
923 | sizeof(params->mcast_rate)); | ||
918 | 924 | ||
919 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 925 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
920 | 926 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b80c38689927..c47d7c0e48a4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <linux/leds.h> | ||
26 | #include <net/ieee80211_radiotap.h> | 27 | #include <net/ieee80211_radiotap.h> |
27 | #include <net/cfg80211.h> | 28 | #include <net/cfg80211.h> |
28 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
@@ -167,6 +168,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
167 | * @IEEE80211_RX_FRAGMENTED: fragmented frame | 168 | * @IEEE80211_RX_FRAGMENTED: fragmented frame |
168 | * @IEEE80211_RX_AMSDU: a-MSDU packet | 169 | * @IEEE80211_RX_AMSDU: a-MSDU packet |
169 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed | 170 | * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed |
171 | * @IEEE80211_RX_DEFERRED_RELEASE: frame was subjected to receive reordering | ||
170 | * | 172 | * |
171 | * These are per-frame flags that are attached to a frame in the | 173 | * These are per-frame flags that are attached to a frame in the |
172 | * @rx_flags field of &struct ieee80211_rx_status. | 174 | * @rx_flags field of &struct ieee80211_rx_status. |
@@ -177,6 +179,7 @@ enum ieee80211_packet_rx_flags { | |||
177 | IEEE80211_RX_FRAGMENTED = BIT(2), | 179 | IEEE80211_RX_FRAGMENTED = BIT(2), |
178 | IEEE80211_RX_AMSDU = BIT(3), | 180 | IEEE80211_RX_AMSDU = BIT(3), |
179 | IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4), | 181 | IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4), |
182 | IEEE80211_RX_DEFERRED_RELEASE = BIT(5), | ||
180 | }; | 183 | }; |
181 | 184 | ||
182 | /** | 185 | /** |
@@ -260,6 +263,7 @@ enum ieee80211_work_type { | |||
260 | IEEE80211_WORK_ASSOC_BEACON_WAIT, | 263 | IEEE80211_WORK_ASSOC_BEACON_WAIT, |
261 | IEEE80211_WORK_ASSOC, | 264 | IEEE80211_WORK_ASSOC, |
262 | IEEE80211_WORK_REMAIN_ON_CHANNEL, | 265 | IEEE80211_WORK_REMAIN_ON_CHANNEL, |
266 | IEEE80211_WORK_OFFCHANNEL_TX, | ||
263 | }; | 267 | }; |
264 | 268 | ||
265 | /** | 269 | /** |
@@ -320,6 +324,10 @@ struct ieee80211_work { | |||
320 | struct { | 324 | struct { |
321 | u32 duration; | 325 | u32 duration; |
322 | } remain; | 326 | } remain; |
327 | struct { | ||
328 | struct sk_buff *frame; | ||
329 | u32 wait; | ||
330 | } offchan_tx; | ||
323 | }; | 331 | }; |
324 | 332 | ||
325 | int ie_len; | 333 | int ie_len; |
@@ -349,8 +357,10 @@ struct ieee80211_if_managed { | |||
349 | struct work_struct chswitch_work; | 357 | struct work_struct chswitch_work; |
350 | struct work_struct beacon_connection_loss_work; | 358 | struct work_struct beacon_connection_loss_work; |
351 | 359 | ||
360 | unsigned long beacon_timeout; | ||
352 | unsigned long probe_timeout; | 361 | unsigned long probe_timeout; |
353 | int probe_send_count; | 362 | int probe_send_count; |
363 | bool nullfunc_failed; | ||
354 | 364 | ||
355 | struct mutex mtx; | 365 | struct mutex mtx; |
356 | struct cfg80211_bss *associated; | 366 | struct cfg80211_bss *associated; |
@@ -477,6 +487,8 @@ struct ieee80211_if_mesh { | |||
477 | struct mesh_config mshcfg; | 487 | struct mesh_config mshcfg; |
478 | u32 mesh_seqnum; | 488 | u32 mesh_seqnum; |
479 | bool accepting_plinks; | 489 | bool accepting_plinks; |
490 | const u8 *vendor_ie; | ||
491 | u8 vendor_ie_len; | ||
480 | }; | 492 | }; |
481 | 493 | ||
482 | #ifdef CONFIG_MAC80211_MESH | 494 | #ifdef CONFIG_MAC80211_MESH |
@@ -550,7 +562,7 @@ struct ieee80211_sub_if_data { | |||
550 | unsigned int fragment_next; | 562 | unsigned int fragment_next; |
551 | 563 | ||
552 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 564 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
553 | struct ieee80211_key *default_key; | 565 | struct ieee80211_key *default_unicast_key, *default_multicast_key; |
554 | struct ieee80211_key *default_mgmt_key; | 566 | struct ieee80211_key *default_mgmt_key; |
555 | 567 | ||
556 | u16 sequence_number; | 568 | u16 sequence_number; |
@@ -578,9 +590,7 @@ struct ieee80211_sub_if_data { | |||
578 | struct ieee80211_if_vlan vlan; | 590 | struct ieee80211_if_vlan vlan; |
579 | struct ieee80211_if_managed mgd; | 591 | struct ieee80211_if_managed mgd; |
580 | struct ieee80211_if_ibss ibss; | 592 | struct ieee80211_if_ibss ibss; |
581 | #ifdef CONFIG_MAC80211_MESH | ||
582 | struct ieee80211_if_mesh mesh; | 593 | struct ieee80211_if_mesh mesh; |
583 | #endif | ||
584 | u32 mntr_flags; | 594 | u32 mntr_flags; |
585 | } u; | 595 | } u; |
586 | 596 | ||
@@ -588,7 +598,8 @@ struct ieee80211_sub_if_data { | |||
588 | struct { | 598 | struct { |
589 | struct dentry *dir; | 599 | struct dentry *dir; |
590 | struct dentry *subdir_stations; | 600 | struct dentry *subdir_stations; |
591 | struct dentry *default_key; | 601 | struct dentry *default_unicast_key; |
602 | struct dentry *default_multicast_key; | ||
592 | struct dentry *default_mgmt_key; | 603 | struct dentry *default_mgmt_key; |
593 | } debugfs; | 604 | } debugfs; |
594 | #endif | 605 | #endif |
@@ -602,19 +613,6 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
602 | return container_of(p, struct ieee80211_sub_if_data, vif); | 613 | return container_of(p, struct ieee80211_sub_if_data, vif); |
603 | } | 614 | } |
604 | 615 | ||
605 | static inline void | ||
606 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | ||
607 | u8 mesh_id_len, u8 *mesh_id) | ||
608 | { | ||
609 | #ifdef CONFIG_MAC80211_MESH | ||
610 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
611 | ifmsh->mesh_id_len = mesh_id_len; | ||
612 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); | ||
613 | #else | ||
614 | WARN_ON(1); | ||
615 | #endif | ||
616 | } | ||
617 | |||
618 | enum sdata_queue_type { | 616 | enum sdata_queue_type { |
619 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, | 617 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, |
620 | IEEE80211_SDATA_QUEUE_AGG_START = 1, | 618 | IEEE80211_SDATA_QUEUE_AGG_START = 1, |
@@ -635,6 +633,20 @@ enum queue_stop_reason { | |||
635 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 633 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
636 | }; | 634 | }; |
637 | 635 | ||
636 | #ifdef CONFIG_MAC80211_LEDS | ||
637 | struct tpt_led_trigger { | ||
638 | struct led_trigger trig; | ||
639 | char name[32]; | ||
640 | const struct ieee80211_tpt_blink *blink_table; | ||
641 | unsigned int blink_table_len; | ||
642 | struct timer_list timer; | ||
643 | unsigned long prev_traffic; | ||
644 | unsigned long tx_bytes, rx_bytes; | ||
645 | unsigned int active, want; | ||
646 | bool running; | ||
647 | }; | ||
648 | #endif | ||
649 | |||
638 | /** | 650 | /** |
639 | * mac80211 scan flags - currently active scan mode | 651 | * mac80211 scan flags - currently active scan mode |
640 | * | 652 | * |
@@ -764,6 +776,15 @@ struct ieee80211_local { | |||
764 | struct sk_buff_head skb_queue; | 776 | struct sk_buff_head skb_queue; |
765 | struct sk_buff_head skb_queue_unreliable; | 777 | struct sk_buff_head skb_queue_unreliable; |
766 | 778 | ||
779 | /* | ||
780 | * Internal FIFO queue which is shared between multiple rx path | ||
781 | * stages. Its main task is to provide a serialization mechanism, | ||
782 | * so all rx handlers can enjoy having exclusive access to their | ||
783 | * private data structures. | ||
784 | */ | ||
785 | struct sk_buff_head rx_skb_queue; | ||
786 | bool running_rx_handler; /* protected by rx_skb_queue.lock */ | ||
787 | |||
767 | /* Station data */ | 788 | /* Station data */ |
768 | /* | 789 | /* |
769 | * The mutex only protects the list and counter, | 790 | * The mutex only protects the list and counter, |
@@ -843,6 +864,7 @@ struct ieee80211_local { | |||
843 | #ifdef CONFIG_MAC80211_LEDS | 864 | #ifdef CONFIG_MAC80211_LEDS |
844 | int tx_led_counter, rx_led_counter; | 865 | int tx_led_counter, rx_led_counter; |
845 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; | 866 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; |
867 | struct tpt_led_trigger *tpt_led_trigger; | ||
846 | char tx_led_name[32], rx_led_name[32], | 868 | char tx_led_name[32], rx_led_name[32], |
847 | assoc_led_name[32], radio_led_name[32]; | 869 | assoc_led_name[32], radio_led_name[32]; |
848 | #endif | 870 | #endif |
@@ -929,6 +951,15 @@ struct ieee80211_local { | |||
929 | } debugfs; | 951 | } debugfs; |
930 | #endif | 952 | #endif |
931 | 953 | ||
954 | struct ieee80211_channel *hw_roc_channel; | ||
955 | struct net_device *hw_roc_dev; | ||
956 | struct sk_buff *hw_roc_skb; | ||
957 | struct work_struct hw_roc_start, hw_roc_done; | ||
958 | enum nl80211_channel_type hw_roc_channel_type; | ||
959 | unsigned int hw_roc_duration; | ||
960 | u32 hw_roc_cookie; | ||
961 | bool hw_roc_for_tx; | ||
962 | |||
932 | /* dummy netdev for use w/ NAPI */ | 963 | /* dummy netdev for use w/ NAPI */ |
933 | struct net_device napi_dev; | 964 | struct net_device napi_dev; |
934 | 965 | ||
@@ -1120,6 +1151,7 @@ void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); | |||
1120 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local); | 1151 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local); |
1121 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 1152 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
1122 | bool enable_beaconing); | 1153 | bool enable_beaconing); |
1154 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); | ||
1123 | 1155 | ||
1124 | /* interface handling */ | 1156 | /* interface handling */ |
1125 | int ieee80211_iface_init(void); | 1157 | int ieee80211_iface_init(void); |
@@ -1264,6 +1296,8 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
1264 | int powersave); | 1296 | int powersave); |
1265 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1297 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1266 | struct ieee80211_hdr *hdr); | 1298 | struct ieee80211_hdr *hdr); |
1299 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | ||
1300 | struct ieee80211_hdr *hdr, bool ack); | ||
1267 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); | 1301 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); |
1268 | 1302 | ||
1269 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1303 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
@@ -1278,6 +1312,9 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
1278 | struct sk_buff *skb); | 1312 | struct sk_buff *skb); |
1279 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | 1313 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, |
1280 | struct sk_buff_head *skbs); | 1314 | struct sk_buff_head *skbs); |
1315 | int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | ||
1316 | struct sk_buff_head *skbs, | ||
1317 | void (*fn)(void *data), void *data); | ||
1281 | 1318 | ||
1282 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1319 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1283 | u16 transaction, u16 auth_alg, | 1320 | u16 transaction, u16 auth_alg, |
@@ -1287,6 +1324,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1287 | const u8 *ie, size_t ie_len, | 1324 | const u8 *ie, size_t ie_len, |
1288 | enum ieee80211_band band, u32 rate_mask, | 1325 | enum ieee80211_band band, u32 rate_mask, |
1289 | u8 channel); | 1326 | u8 channel); |
1327 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | ||
1328 | u8 *dst, | ||
1329 | const u8 *ssid, size_t ssid_len, | ||
1330 | const u8 *ie, size_t ie_len); | ||
1290 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1331 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1291 | const u8 *ssid, size_t ssid_len, | 1332 | const u8 *ssid, size_t ssid_len, |
1292 | const u8 *ie, size_t ie_len); | 1333 | const u8 *ie, size_t ie_len); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index f9163b12c7f1..8acba456744e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -197,11 +197,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
197 | sdata->bss = &sdata->u.ap; | 197 | sdata->bss = &sdata->u.ap; |
198 | break; | 198 | break; |
199 | case NL80211_IFTYPE_MESH_POINT: | 199 | case NL80211_IFTYPE_MESH_POINT: |
200 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
201 | break; | ||
202 | /* mesh ifaces must set allmulti to forward mcast traffic */ | ||
203 | atomic_inc(&local->iff_allmultis); | ||
204 | break; | ||
205 | case NL80211_IFTYPE_STATION: | 200 | case NL80211_IFTYPE_STATION: |
206 | case NL80211_IFTYPE_MONITOR: | 201 | case NL80211_IFTYPE_MONITOR: |
207 | case NL80211_IFTYPE_ADHOC: | 202 | case NL80211_IFTYPE_ADHOC: |
@@ -225,6 +220,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
225 | /* we're brought up, everything changes */ | 220 | /* we're brought up, everything changes */ |
226 | hw_reconf_flags = ~0; | 221 | hw_reconf_flags = ~0; |
227 | ieee80211_led_radio(local, true); | 222 | ieee80211_led_radio(local, true); |
223 | ieee80211_mod_tpt_led_trig(local, | ||
224 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | ||
228 | } | 225 | } |
229 | 226 | ||
230 | /* | 227 | /* |
@@ -273,12 +270,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
273 | goto err_stop; | 270 | goto err_stop; |
274 | } | 271 | } |
275 | 272 | ||
276 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 273 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
277 | local->fif_other_bss++; | ||
278 | ieee80211_configure_filter(local); | ||
279 | |||
280 | ieee80211_start_mesh(sdata); | ||
281 | } else if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
282 | local->fif_pspoll++; | 274 | local->fif_pspoll++; |
283 | local->fif_probe_req++; | 275 | local->fif_probe_req++; |
284 | 276 | ||
@@ -391,6 +383,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
391 | u32 hw_reconf_flags = 0; | 383 | u32 hw_reconf_flags = 0; |
392 | int i; | 384 | int i; |
393 | 385 | ||
386 | if (local->scan_sdata == sdata) | ||
387 | ieee80211_scan_cancel(local); | ||
388 | |||
394 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 389 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
395 | 390 | ||
396 | /* | 391 | /* |
@@ -500,18 +495,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
500 | ieee80211_adjust_monitor_flags(sdata, -1); | 495 | ieee80211_adjust_monitor_flags(sdata, -1); |
501 | ieee80211_configure_filter(local); | 496 | ieee80211_configure_filter(local); |
502 | break; | 497 | break; |
503 | case NL80211_IFTYPE_MESH_POINT: | ||
504 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
505 | /* other_bss and allmulti are always set on mesh | ||
506 | * ifaces */ | ||
507 | local->fif_other_bss--; | ||
508 | atomic_dec(&local->iff_allmultis); | ||
509 | |||
510 | ieee80211_configure_filter(local); | ||
511 | |||
512 | ieee80211_stop_mesh(sdata); | ||
513 | } | ||
514 | /* fall through */ | ||
515 | default: | 498 | default: |
516 | flush_work(&sdata->work); | 499 | flush_work(&sdata->work); |
517 | /* | 500 | /* |
@@ -523,9 +506,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
523 | synchronize_rcu(); | 506 | synchronize_rcu(); |
524 | skb_queue_purge(&sdata->skb_queue); | 507 | skb_queue_purge(&sdata->skb_queue); |
525 | 508 | ||
526 | if (local->scan_sdata == sdata) | ||
527 | ieee80211_scan_cancel(local); | ||
528 | |||
529 | /* | 509 | /* |
530 | * Disable beaconing here for mesh only, AP and IBSS | 510 | * Disable beaconing here for mesh only, AP and IBSS |
531 | * are already taken care of. | 511 | * are already taken care of. |
@@ -1204,12 +1184,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1204 | if (ret) | 1184 | if (ret) |
1205 | goto fail; | 1185 | goto fail; |
1206 | 1186 | ||
1207 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
1208 | params && params->mesh_id_len) | ||
1209 | ieee80211_sdata_set_mesh_id(sdata, | ||
1210 | params->mesh_id_len, | ||
1211 | params->mesh_id); | ||
1212 | |||
1213 | mutex_lock(&local->iflist_mtx); | 1187 | mutex_lock(&local->iflist_mtx); |
1214 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1188 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
1215 | mutex_unlock(&local->iflist_mtx); | 1189 | mutex_unlock(&local->iflist_mtx); |
@@ -1290,8 +1264,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1290 | { | 1264 | { |
1291 | struct ieee80211_sub_if_data *sdata; | 1265 | struct ieee80211_sub_if_data *sdata; |
1292 | int count = 0; | 1266 | int count = 0; |
1293 | bool working = false, scanning = false; | 1267 | bool working = false, scanning = false, hw_roc = false; |
1294 | struct ieee80211_work *wk; | 1268 | struct ieee80211_work *wk; |
1269 | unsigned int led_trig_start = 0, led_trig_stop = 0; | ||
1295 | 1270 | ||
1296 | #ifdef CONFIG_PROVE_LOCKING | 1271 | #ifdef CONFIG_PROVE_LOCKING |
1297 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | 1272 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && |
@@ -1333,6 +1308,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1333 | local->scan_sdata->vif.bss_conf.idle = false; | 1308 | local->scan_sdata->vif.bss_conf.idle = false; |
1334 | } | 1309 | } |
1335 | 1310 | ||
1311 | if (local->hw_roc_channel) | ||
1312 | hw_roc = true; | ||
1313 | |||
1336 | list_for_each_entry(sdata, &local->interfaces, list) { | 1314 | list_for_each_entry(sdata, &local->interfaces, list) { |
1337 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | 1315 | if (sdata->old_idle == sdata->vif.bss_conf.idle) |
1338 | continue; | 1316 | continue; |
@@ -1341,6 +1319,20 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1341 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | 1319 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); |
1342 | } | 1320 | } |
1343 | 1321 | ||
1322 | if (working || scanning || hw_roc) | ||
1323 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1324 | else | ||
1325 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1326 | |||
1327 | if (count) | ||
1328 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1329 | else | ||
1330 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1331 | |||
1332 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | ||
1333 | |||
1334 | if (hw_roc) | ||
1335 | return ieee80211_idle_off(local, "hw remain-on-channel"); | ||
1344 | if (working) | 1336 | if (working) |
1345 | return ieee80211_idle_off(local, "working"); | 1337 | return ieee80211_idle_off(local, "working"); |
1346 | if (scanning) | 1338 | if (scanning) |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index ccd676b2f599..8c02469b7176 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -30,19 +30,20 @@ | |||
30 | * keys and per-station keys. Since each station belongs to an interface, | 30 | * keys and per-station keys. Since each station belongs to an interface, |
31 | * each station key also belongs to that interface. | 31 | * each station key also belongs to that interface. |
32 | * | 32 | * |
33 | * Hardware acceleration is done on a best-effort basis, for each key | 33 | * Hardware acceleration is done on a best-effort basis for algorithms |
34 | * that is eligible the hardware is asked to enable that key but if | 34 | * that are implemented in software, for each key the hardware is asked |
35 | * it cannot do that they key is simply kept for software encryption. | 35 | * to enable that key for offloading but if it cannot do that the key is |
36 | * There is currently no way of knowing this except by looking into | 36 | * simply kept for software encryption (unless it is for an algorithm |
37 | * debugfs. | 37 | * that isn't implemented in software). |
38 | * There is currently no way of knowing whether a key is handled in SW | ||
39 | * or HW except by looking into debugfs. | ||
38 | * | 40 | * |
39 | * All key operations are protected internally. | 41 | * All key management is internally protected by a mutex. Within all |
40 | * | 42 | * other parts of mac80211, key references are, just as STA structure |
41 | * Within mac80211, key references are, just as STA structure references, | 43 | * references, protected by RCU. Note, however, that some things are |
42 | * protected by RCU. Note, however, that some things are unprotected, | 44 | * unprotected, namely the key->sta dereferences within the hardware |
43 | * namely the key->sta dereferences within the hardware acceleration | 45 | * acceleration functions. This means that sta_info_destroy() must |
44 | * functions. This means that sta_info_destroy() must remove the key | 46 | * remove the key which waits for an RCU grace period. |
45 | * which waits for an RCU grace period. | ||
46 | */ | 47 | */ |
47 | 48 | ||
48 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 49 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
@@ -84,10 +85,17 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
84 | goto out_unsupported; | 85 | goto out_unsupported; |
85 | 86 | ||
86 | sdata = key->sdata; | 87 | sdata = key->sdata; |
87 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 88 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
89 | /* | ||
90 | * The driver doesn't know anything about VLAN interfaces. | ||
91 | * Hence, don't send GTKs for VLAN interfaces to the driver. | ||
92 | */ | ||
93 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
94 | goto out_unsupported; | ||
88 | sdata = container_of(sdata->bss, | 95 | sdata = container_of(sdata->bss, |
89 | struct ieee80211_sub_if_data, | 96 | struct ieee80211_sub_if_data, |
90 | u.ap); | 97 | u.ap); |
98 | } | ||
91 | 99 | ||
92 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); | 100 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); |
93 | 101 | ||
@@ -171,7 +179,7 @@ void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) | |||
171 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); | 179 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); |
172 | 180 | ||
173 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 181 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
174 | int idx) | 182 | int idx, bool uni, bool multi) |
175 | { | 183 | { |
176 | struct ieee80211_key *key = NULL; | 184 | struct ieee80211_key *key = NULL; |
177 | 185 | ||
@@ -180,18 +188,19 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | |||
180 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) | 188 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) |
181 | key = sdata->keys[idx]; | 189 | key = sdata->keys[idx]; |
182 | 190 | ||
183 | rcu_assign_pointer(sdata->default_key, key); | 191 | if (uni) |
192 | rcu_assign_pointer(sdata->default_unicast_key, key); | ||
193 | if (multi) | ||
194 | rcu_assign_pointer(sdata->default_multicast_key, key); | ||
184 | 195 | ||
185 | if (key) { | 196 | ieee80211_debugfs_key_update_default(sdata); |
186 | ieee80211_debugfs_key_remove_default(key->sdata); | ||
187 | ieee80211_debugfs_key_add_default(key->sdata); | ||
188 | } | ||
189 | } | 197 | } |
190 | 198 | ||
191 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) | 199 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
200 | bool uni, bool multi) | ||
192 | { | 201 | { |
193 | mutex_lock(&sdata->local->key_mtx); | 202 | mutex_lock(&sdata->local->key_mtx); |
194 | __ieee80211_set_default_key(sdata, idx); | 203 | __ieee80211_set_default_key(sdata, idx, uni, multi); |
195 | mutex_unlock(&sdata->local->key_mtx); | 204 | mutex_unlock(&sdata->local->key_mtx); |
196 | } | 205 | } |
197 | 206 | ||
@@ -208,10 +217,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) | |||
208 | 217 | ||
209 | rcu_assign_pointer(sdata->default_mgmt_key, key); | 218 | rcu_assign_pointer(sdata->default_mgmt_key, key); |
210 | 219 | ||
211 | if (key) { | 220 | ieee80211_debugfs_key_update_default(sdata); |
212 | ieee80211_debugfs_key_remove_mgmt_default(key->sdata); | ||
213 | ieee80211_debugfs_key_add_mgmt_default(key->sdata); | ||
214 | } | ||
215 | } | 221 | } |
216 | 222 | ||
217 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 223 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
@@ -229,7 +235,8 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
229 | struct ieee80211_key *old, | 235 | struct ieee80211_key *old, |
230 | struct ieee80211_key *new) | 236 | struct ieee80211_key *new) |
231 | { | 237 | { |
232 | int idx, defkey, defmgmtkey; | 238 | int idx; |
239 | bool defunikey, defmultikey, defmgmtkey; | ||
233 | 240 | ||
234 | if (new) | 241 | if (new) |
235 | list_add(&new->list, &sdata->key_list); | 242 | list_add(&new->list, &sdata->key_list); |
@@ -250,29 +257,31 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
250 | else | 257 | else |
251 | idx = new->conf.keyidx; | 258 | idx = new->conf.keyidx; |
252 | 259 | ||
253 | defkey = old && sdata->default_key == old; | 260 | defunikey = old && sdata->default_unicast_key == old; |
261 | defmultikey = old && sdata->default_multicast_key == old; | ||
254 | defmgmtkey = old && sdata->default_mgmt_key == old; | 262 | defmgmtkey = old && sdata->default_mgmt_key == old; |
255 | 263 | ||
256 | if (defkey && !new) | 264 | if (defunikey && !new) |
257 | __ieee80211_set_default_key(sdata, -1); | 265 | __ieee80211_set_default_key(sdata, -1, true, false); |
266 | if (defmultikey && !new) | ||
267 | __ieee80211_set_default_key(sdata, -1, false, true); | ||
258 | if (defmgmtkey && !new) | 268 | if (defmgmtkey && !new) |
259 | __ieee80211_set_default_mgmt_key(sdata, -1); | 269 | __ieee80211_set_default_mgmt_key(sdata, -1); |
260 | 270 | ||
261 | rcu_assign_pointer(sdata->keys[idx], new); | 271 | rcu_assign_pointer(sdata->keys[idx], new); |
262 | if (defkey && new) | 272 | if (defunikey && new) |
263 | __ieee80211_set_default_key(sdata, new->conf.keyidx); | 273 | __ieee80211_set_default_key(sdata, new->conf.keyidx, |
274 | true, false); | ||
275 | if (defmultikey && new) | ||
276 | __ieee80211_set_default_key(sdata, new->conf.keyidx, | ||
277 | false, true); | ||
264 | if (defmgmtkey && new) | 278 | if (defmgmtkey && new) |
265 | __ieee80211_set_default_mgmt_key(sdata, | 279 | __ieee80211_set_default_mgmt_key(sdata, |
266 | new->conf.keyidx); | 280 | new->conf.keyidx); |
267 | } | 281 | } |
268 | 282 | ||
269 | if (old) { | 283 | if (old) |
270 | /* | 284 | list_del(&old->list); |
271 | * We'll use an empty list to indicate that the key | ||
272 | * has already been removed. | ||
273 | */ | ||
274 | list_del_init(&old->list); | ||
275 | } | ||
276 | } | 285 | } |
277 | 286 | ||
278 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | 287 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
@@ -366,6 +375,12 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
366 | if (!key) | 375 | if (!key) |
367 | return; | 376 | return; |
368 | 377 | ||
378 | /* | ||
379 | * Synchronize so the TX path can no longer be using | ||
380 | * this key before we free/remove it. | ||
381 | */ | ||
382 | synchronize_rcu(); | ||
383 | |||
369 | if (key->local) | 384 | if (key->local) |
370 | ieee80211_key_disable_hw_accel(key); | 385 | ieee80211_key_disable_hw_accel(key); |
371 | 386 | ||
@@ -407,8 +422,8 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
407 | struct sta_info *ap; | 422 | struct sta_info *ap; |
408 | 423 | ||
409 | /* | 424 | /* |
410 | * We're getting a sta pointer in, | 425 | * We're getting a sta pointer in, so must be under |
411 | * so must be under RCU read lock. | 426 | * appropriate locking for sta_info_get(). |
412 | */ | 427 | */ |
413 | 428 | ||
414 | /* same here, the AP could be using QoS */ | 429 | /* same here, the AP could be using QoS */ |
@@ -502,11 +517,12 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
502 | 517 | ||
503 | mutex_lock(&sdata->local->key_mtx); | 518 | mutex_lock(&sdata->local->key_mtx); |
504 | 519 | ||
505 | ieee80211_debugfs_key_remove_default(sdata); | ||
506 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 520 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
507 | 521 | ||
508 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 522 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
509 | __ieee80211_key_free(key); | 523 | __ieee80211_key_free(key); |
510 | 524 | ||
525 | ieee80211_debugfs_key_update_default(sdata); | ||
526 | |||
511 | mutex_unlock(&sdata->local->key_mtx); | 527 | mutex_unlock(&sdata->local->key_mtx); |
512 | } | 528 | } |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 0db1c0f5f697..8106aa1b7466 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -138,7 +138,8 @@ int __must_check ieee80211_key_link(struct ieee80211_key *key, | |||
138 | struct sta_info *sta); | 138 | struct sta_info *sta); |
139 | void ieee80211_key_free(struct ieee80211_local *local, | 139 | void ieee80211_key_free(struct ieee80211_local *local, |
140 | struct ieee80211_key *key); | 140 | struct ieee80211_key *key); |
141 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); | 141 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
142 | bool uni, bool multi); | ||
142 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 143 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
143 | int idx); | 144 | int idx); |
144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 145 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/led.c b/net/mac80211/led.c index 063aad944246..14590332c81c 100644 --- a/net/mac80211/led.c +++ b/net/mac80211/led.c | |||
@@ -54,12 +54,22 @@ void ieee80211_led_radio(struct ieee80211_local *local, bool enabled) | |||
54 | led_trigger_event(local->radio_led, LED_OFF); | 54 | led_trigger_event(local->radio_led, LED_OFF); |
55 | } | 55 | } |
56 | 56 | ||
57 | void ieee80211_led_names(struct ieee80211_local *local) | ||
58 | { | ||
59 | snprintf(local->rx_led_name, sizeof(local->rx_led_name), | ||
60 | "%srx", wiphy_name(local->hw.wiphy)); | ||
61 | snprintf(local->tx_led_name, sizeof(local->tx_led_name), | ||
62 | "%stx", wiphy_name(local->hw.wiphy)); | ||
63 | snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), | ||
64 | "%sassoc", wiphy_name(local->hw.wiphy)); | ||
65 | snprintf(local->radio_led_name, sizeof(local->radio_led_name), | ||
66 | "%sradio", wiphy_name(local->hw.wiphy)); | ||
67 | } | ||
68 | |||
57 | void ieee80211_led_init(struct ieee80211_local *local) | 69 | void ieee80211_led_init(struct ieee80211_local *local) |
58 | { | 70 | { |
59 | local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 71 | local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
60 | if (local->rx_led) { | 72 | if (local->rx_led) { |
61 | snprintf(local->rx_led_name, sizeof(local->rx_led_name), | ||
62 | "%srx", wiphy_name(local->hw.wiphy)); | ||
63 | local->rx_led->name = local->rx_led_name; | 73 | local->rx_led->name = local->rx_led_name; |
64 | if (led_trigger_register(local->rx_led)) { | 74 | if (led_trigger_register(local->rx_led)) { |
65 | kfree(local->rx_led); | 75 | kfree(local->rx_led); |
@@ -69,8 +79,6 @@ void ieee80211_led_init(struct ieee80211_local *local) | |||
69 | 79 | ||
70 | local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 80 | local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
71 | if (local->tx_led) { | 81 | if (local->tx_led) { |
72 | snprintf(local->tx_led_name, sizeof(local->tx_led_name), | ||
73 | "%stx", wiphy_name(local->hw.wiphy)); | ||
74 | local->tx_led->name = local->tx_led_name; | 82 | local->tx_led->name = local->tx_led_name; |
75 | if (led_trigger_register(local->tx_led)) { | 83 | if (led_trigger_register(local->tx_led)) { |
76 | kfree(local->tx_led); | 84 | kfree(local->tx_led); |
@@ -80,8 +88,6 @@ void ieee80211_led_init(struct ieee80211_local *local) | |||
80 | 88 | ||
81 | local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 89 | local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
82 | if (local->assoc_led) { | 90 | if (local->assoc_led) { |
83 | snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), | ||
84 | "%sassoc", wiphy_name(local->hw.wiphy)); | ||
85 | local->assoc_led->name = local->assoc_led_name; | 91 | local->assoc_led->name = local->assoc_led_name; |
86 | if (led_trigger_register(local->assoc_led)) { | 92 | if (led_trigger_register(local->assoc_led)) { |
87 | kfree(local->assoc_led); | 93 | kfree(local->assoc_led); |
@@ -91,14 +97,19 @@ void ieee80211_led_init(struct ieee80211_local *local) | |||
91 | 97 | ||
92 | local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 98 | local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
93 | if (local->radio_led) { | 99 | if (local->radio_led) { |
94 | snprintf(local->radio_led_name, sizeof(local->radio_led_name), | ||
95 | "%sradio", wiphy_name(local->hw.wiphy)); | ||
96 | local->radio_led->name = local->radio_led_name; | 100 | local->radio_led->name = local->radio_led_name; |
97 | if (led_trigger_register(local->radio_led)) { | 101 | if (led_trigger_register(local->radio_led)) { |
98 | kfree(local->radio_led); | 102 | kfree(local->radio_led); |
99 | local->radio_led = NULL; | 103 | local->radio_led = NULL; |
100 | } | 104 | } |
101 | } | 105 | } |
106 | |||
107 | if (local->tpt_led_trigger) { | ||
108 | if (led_trigger_register(&local->tpt_led_trigger->trig)) { | ||
109 | kfree(local->tpt_led_trigger); | ||
110 | local->tpt_led_trigger = NULL; | ||
111 | } | ||
112 | } | ||
102 | } | 113 | } |
103 | 114 | ||
104 | void ieee80211_led_exit(struct ieee80211_local *local) | 115 | void ieee80211_led_exit(struct ieee80211_local *local) |
@@ -119,15 +130,18 @@ void ieee80211_led_exit(struct ieee80211_local *local) | |||
119 | led_trigger_unregister(local->rx_led); | 130 | led_trigger_unregister(local->rx_led); |
120 | kfree(local->rx_led); | 131 | kfree(local->rx_led); |
121 | } | 132 | } |
133 | |||
134 | if (local->tpt_led_trigger) { | ||
135 | led_trigger_unregister(&local->tpt_led_trigger->trig); | ||
136 | kfree(local->tpt_led_trigger); | ||
137 | } | ||
122 | } | 138 | } |
123 | 139 | ||
124 | char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) | 140 | char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) |
125 | { | 141 | { |
126 | struct ieee80211_local *local = hw_to_local(hw); | 142 | struct ieee80211_local *local = hw_to_local(hw); |
127 | 143 | ||
128 | if (local->radio_led) | 144 | return local->radio_led_name; |
129 | return local->radio_led_name; | ||
130 | return NULL; | ||
131 | } | 145 | } |
132 | EXPORT_SYMBOL(__ieee80211_get_radio_led_name); | 146 | EXPORT_SYMBOL(__ieee80211_get_radio_led_name); |
133 | 147 | ||
@@ -135,9 +149,7 @@ char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) | |||
135 | { | 149 | { |
136 | struct ieee80211_local *local = hw_to_local(hw); | 150 | struct ieee80211_local *local = hw_to_local(hw); |
137 | 151 | ||
138 | if (local->assoc_led) | 152 | return local->assoc_led_name; |
139 | return local->assoc_led_name; | ||
140 | return NULL; | ||
141 | } | 153 | } |
142 | EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); | 154 | EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); |
143 | 155 | ||
@@ -145,9 +157,7 @@ char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw) | |||
145 | { | 157 | { |
146 | struct ieee80211_local *local = hw_to_local(hw); | 158 | struct ieee80211_local *local = hw_to_local(hw); |
147 | 159 | ||
148 | if (local->tx_led) | 160 | return local->tx_led_name; |
149 | return local->tx_led_name; | ||
150 | return NULL; | ||
151 | } | 161 | } |
152 | EXPORT_SYMBOL(__ieee80211_get_tx_led_name); | 162 | EXPORT_SYMBOL(__ieee80211_get_tx_led_name); |
153 | 163 | ||
@@ -155,8 +165,144 @@ char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw) | |||
155 | { | 165 | { |
156 | struct ieee80211_local *local = hw_to_local(hw); | 166 | struct ieee80211_local *local = hw_to_local(hw); |
157 | 167 | ||
158 | if (local->rx_led) | 168 | return local->rx_led_name; |
159 | return local->rx_led_name; | ||
160 | return NULL; | ||
161 | } | 169 | } |
162 | EXPORT_SYMBOL(__ieee80211_get_rx_led_name); | 170 | EXPORT_SYMBOL(__ieee80211_get_rx_led_name); |
171 | |||
172 | static unsigned long tpt_trig_traffic(struct ieee80211_local *local, | ||
173 | struct tpt_led_trigger *tpt_trig) | ||
174 | { | ||
175 | unsigned long traffic, delta; | ||
176 | |||
177 | traffic = tpt_trig->tx_bytes + tpt_trig->rx_bytes; | ||
178 | |||
179 | delta = traffic - tpt_trig->prev_traffic; | ||
180 | tpt_trig->prev_traffic = traffic; | ||
181 | return DIV_ROUND_UP(delta, 1024 / 8); | ||
182 | } | ||
183 | |||
184 | static void tpt_trig_timer(unsigned long data) | ||
185 | { | ||
186 | struct ieee80211_local *local = (void *)data; | ||
187 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
188 | struct led_classdev *led_cdev; | ||
189 | unsigned long on, off, tpt; | ||
190 | int i; | ||
191 | |||
192 | if (!tpt_trig->running) | ||
193 | return; | ||
194 | |||
195 | mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); | ||
196 | |||
197 | tpt = tpt_trig_traffic(local, tpt_trig); | ||
198 | |||
199 | /* default to just solid on */ | ||
200 | on = 1; | ||
201 | off = 0; | ||
202 | |||
203 | for (i = tpt_trig->blink_table_len - 1; i >= 0; i--) { | ||
204 | if (tpt_trig->blink_table[i].throughput < 0 || | ||
205 | tpt > tpt_trig->blink_table[i].throughput) { | ||
206 | off = tpt_trig->blink_table[i].blink_time / 2; | ||
207 | on = tpt_trig->blink_table[i].blink_time - off; | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | read_lock(&tpt_trig->trig.leddev_list_lock); | ||
213 | list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) | ||
214 | led_blink_set(led_cdev, &on, &off); | ||
215 | read_unlock(&tpt_trig->trig.leddev_list_lock); | ||
216 | } | ||
217 | |||
218 | char *__ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, | ||
219 | unsigned int flags, | ||
220 | const struct ieee80211_tpt_blink *blink_table, | ||
221 | unsigned int blink_table_len) | ||
222 | { | ||
223 | struct ieee80211_local *local = hw_to_local(hw); | ||
224 | struct tpt_led_trigger *tpt_trig; | ||
225 | |||
226 | if (WARN_ON(local->tpt_led_trigger)) | ||
227 | return NULL; | ||
228 | |||
229 | tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL); | ||
230 | if (!tpt_trig) | ||
231 | return NULL; | ||
232 | |||
233 | snprintf(tpt_trig->name, sizeof(tpt_trig->name), | ||
234 | "%stpt", wiphy_name(local->hw.wiphy)); | ||
235 | |||
236 | tpt_trig->trig.name = tpt_trig->name; | ||
237 | |||
238 | tpt_trig->blink_table = blink_table; | ||
239 | tpt_trig->blink_table_len = blink_table_len; | ||
240 | tpt_trig->want = flags; | ||
241 | |||
242 | setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local); | ||
243 | |||
244 | local->tpt_led_trigger = tpt_trig; | ||
245 | |||
246 | return tpt_trig->name; | ||
247 | } | ||
248 | EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger); | ||
249 | |||
250 | static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local) | ||
251 | { | ||
252 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
253 | |||
254 | if (tpt_trig->running) | ||
255 | return; | ||
256 | |||
257 | /* reset traffic */ | ||
258 | tpt_trig_traffic(local, tpt_trig); | ||
259 | tpt_trig->running = true; | ||
260 | |||
261 | tpt_trig_timer((unsigned long)local); | ||
262 | mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); | ||
263 | } | ||
264 | |||
265 | static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local) | ||
266 | { | ||
267 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
268 | struct led_classdev *led_cdev; | ||
269 | |||
270 | if (!tpt_trig->running) | ||
271 | return; | ||
272 | |||
273 | tpt_trig->running = false; | ||
274 | del_timer_sync(&tpt_trig->timer); | ||
275 | |||
276 | read_lock(&tpt_trig->trig.leddev_list_lock); | ||
277 | list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) | ||
278 | led_brightness_set(led_cdev, LED_OFF); | ||
279 | read_unlock(&tpt_trig->trig.leddev_list_lock); | ||
280 | } | ||
281 | |||
282 | void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, | ||
283 | unsigned int types_on, unsigned int types_off) | ||
284 | { | ||
285 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
286 | bool allowed; | ||
287 | |||
288 | WARN_ON(types_on & types_off); | ||
289 | |||
290 | if (!tpt_trig) | ||
291 | return; | ||
292 | |||
293 | tpt_trig->active &= ~types_off; | ||
294 | tpt_trig->active |= types_on; | ||
295 | |||
296 | /* | ||
297 | * Regardless of wanted state, we shouldn't blink when | ||
298 | * the radio is disabled -- this can happen due to some | ||
299 | * code ordering issues with __ieee80211_recalc_idle() | ||
300 | * being called before the radio is started. | ||
301 | */ | ||
302 | allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO; | ||
303 | |||
304 | if (!allowed || !(tpt_trig->active & tpt_trig->want)) | ||
305 | ieee80211_stop_tpt_led_trig(local); | ||
306 | else | ||
307 | ieee80211_start_tpt_led_trig(local); | ||
308 | } | ||
diff --git a/net/mac80211/led.h b/net/mac80211/led.h index 77b1e1ba6039..e0275d9befa8 100644 --- a/net/mac80211/led.h +++ b/net/mac80211/led.h | |||
@@ -12,14 +12,17 @@ | |||
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | 13 | ||
14 | #ifdef CONFIG_MAC80211_LEDS | 14 | #ifdef CONFIG_MAC80211_LEDS |
15 | extern void ieee80211_led_rx(struct ieee80211_local *local); | 15 | void ieee80211_led_rx(struct ieee80211_local *local); |
16 | extern void ieee80211_led_tx(struct ieee80211_local *local, int q); | 16 | void ieee80211_led_tx(struct ieee80211_local *local, int q); |
17 | extern void ieee80211_led_assoc(struct ieee80211_local *local, | 17 | void ieee80211_led_assoc(struct ieee80211_local *local, |
18 | bool associated); | 18 | bool associated); |
19 | extern void ieee80211_led_radio(struct ieee80211_local *local, | 19 | void ieee80211_led_radio(struct ieee80211_local *local, |
20 | bool enabled); | 20 | bool enabled); |
21 | extern void ieee80211_led_init(struct ieee80211_local *local); | 21 | void ieee80211_led_names(struct ieee80211_local *local); |
22 | extern void ieee80211_led_exit(struct ieee80211_local *local); | 22 | void ieee80211_led_init(struct ieee80211_local *local); |
23 | void ieee80211_led_exit(struct ieee80211_local *local); | ||
24 | void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, | ||
25 | unsigned int types_on, unsigned int types_off); | ||
23 | #else | 26 | #else |
24 | static inline void ieee80211_led_rx(struct ieee80211_local *local) | 27 | static inline void ieee80211_led_rx(struct ieee80211_local *local) |
25 | { | 28 | { |
@@ -35,10 +38,36 @@ static inline void ieee80211_led_radio(struct ieee80211_local *local, | |||
35 | bool enabled) | 38 | bool enabled) |
36 | { | 39 | { |
37 | } | 40 | } |
41 | static inline void ieee80211_led_names(struct ieee80211_local *local) | ||
42 | { | ||
43 | } | ||
38 | static inline void ieee80211_led_init(struct ieee80211_local *local) | 44 | static inline void ieee80211_led_init(struct ieee80211_local *local) |
39 | { | 45 | { |
40 | } | 46 | } |
41 | static inline void ieee80211_led_exit(struct ieee80211_local *local) | 47 | static inline void ieee80211_led_exit(struct ieee80211_local *local) |
42 | { | 48 | { |
43 | } | 49 | } |
50 | static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, | ||
51 | unsigned int types_on, | ||
52 | unsigned int types_off) | ||
53 | { | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | static inline void | ||
58 | ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) | ||
59 | { | ||
60 | #ifdef CONFIG_MAC80211_LEDS | ||
61 | if (local->tpt_led_trigger && ieee80211_is_data(fc)) | ||
62 | local->tpt_led_trigger->tx_bytes += bytes; | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | static inline void | ||
67 | ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) | ||
68 | { | ||
69 | #ifdef CONFIG_MAC80211_LEDS | ||
70 | if (local->tpt_led_trigger && ieee80211_is_data(fc)) | ||
71 | local->tpt_led_trigger->rx_bytes += bytes; | ||
44 | #endif | 72 | #endif |
73 | } | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 107a0cbe52ac..485d36bc9a46 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -245,9 +245,12 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
245 | sdata->vif.bss_conf.enable_beacon = | 245 | sdata->vif.bss_conf.enable_beacon = |
246 | !!sdata->u.ibss.presp; | 246 | !!sdata->u.ibss.presp; |
247 | break; | 247 | break; |
248 | #ifdef CONFIG_MAC80211_MESH | ||
248 | case NL80211_IFTYPE_MESH_POINT: | 249 | case NL80211_IFTYPE_MESH_POINT: |
249 | sdata->vif.bss_conf.enable_beacon = true; | 250 | sdata->vif.bss_conf.enable_beacon = |
251 | !!sdata->u.mesh.mesh_id_len; | ||
250 | break; | 252 | break; |
253 | #endif | ||
251 | default: | 254 | default: |
252 | /* not reached */ | 255 | /* not reached */ |
253 | WARN_ON(1); | 256 | WARN_ON(1); |
@@ -481,6 +484,10 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
481 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | 484 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
482 | BIT(IEEE80211_STYPE_ACTION >> 4), | 485 | BIT(IEEE80211_STYPE_ACTION >> 4), |
483 | }, | 486 | }, |
487 | [NL80211_IFTYPE_MESH_POINT] = { | ||
488 | .tx = 0xffff, | ||
489 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4), | ||
490 | }, | ||
484 | }; | 491 | }; |
485 | 492 | ||
486 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 493 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
@@ -514,10 +521,15 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
514 | 521 | ||
515 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; | 522 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; |
516 | 523 | ||
524 | wiphy->privid = mac80211_wiphy_privid; | ||
525 | |||
517 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 526 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
518 | WIPHY_FLAG_4ADDR_AP | | 527 | WIPHY_FLAG_4ADDR_AP | |
519 | WIPHY_FLAG_4ADDR_STATION; | 528 | WIPHY_FLAG_4ADDR_STATION | |
520 | wiphy->privid = mac80211_wiphy_privid; | 529 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS; |
530 | |||
531 | if (!ops->set_key) | ||
532 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
521 | 533 | ||
522 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); | 534 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); |
523 | 535 | ||
@@ -557,6 +569,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
557 | spin_lock_init(&local->filter_lock); | 569 | spin_lock_init(&local->filter_lock); |
558 | spin_lock_init(&local->queue_stop_reason_lock); | 570 | spin_lock_init(&local->queue_stop_reason_lock); |
559 | 571 | ||
572 | skb_queue_head_init(&local->rx_skb_queue); | ||
573 | |||
560 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 574 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
561 | 575 | ||
562 | ieee80211_work_init(local); | 576 | ieee80211_work_init(local); |
@@ -593,6 +607,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
593 | /* init dummy netdev for use w/ NAPI */ | 607 | /* init dummy netdev for use w/ NAPI */ |
594 | init_dummy_netdev(&local->napi_dev); | 608 | init_dummy_netdev(&local->napi_dev); |
595 | 609 | ||
610 | ieee80211_led_names(local); | ||
611 | |||
612 | ieee80211_hw_roc_setup(local); | ||
613 | |||
596 | return local_to_hw(local); | 614 | return local_to_hw(local); |
597 | } | 615 | } |
598 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 616 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -737,6 +755,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
737 | } | 755 | } |
738 | } | 756 | } |
739 | 757 | ||
758 | if (!local->ops->remain_on_channel) | ||
759 | local->hw.wiphy->max_remain_on_channel_duration = 5000; | ||
760 | |||
740 | result = wiphy_register(local->hw.wiphy); | 761 | result = wiphy_register(local->hw.wiphy); |
741 | if (result < 0) | 762 | if (result < 0) |
742 | goto fail_wiphy_register; | 763 | goto fail_wiphy_register; |
@@ -898,6 +919,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
898 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); | 919 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); |
899 | skb_queue_purge(&local->skb_queue); | 920 | skb_queue_purge(&local->skb_queue); |
900 | skb_queue_purge(&local->skb_queue_unreliable); | 921 | skb_queue_purge(&local->skb_queue_unreliable); |
922 | skb_queue_purge(&local->rx_skb_queue); | ||
901 | 923 | ||
902 | destroy_workqueue(local->workqueue); | 924 | destroy_workqueue(local->workqueue); |
903 | wiphy_unregister(local->hw.wiphy); | 925 | wiphy_unregister(local->hw.wiphy); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c8a4f19ed13b..ca3af4685b0a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -124,15 +124,6 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
124 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); | 124 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
125 | } | 125 | } |
126 | 126 | ||
127 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) | ||
128 | { | ||
129 | sta->mesh_pp_id = 0; /* HWMP */ | ||
130 | sta->mesh_pm_id = 0; /* Airtime */ | ||
131 | sta->mesh_cc_id = 0; /* Disabled */ | ||
132 | sta->mesh_sp_id = 0; /* Neighbor Offset */ | ||
133 | sta->mesh_auth_id = 0; /* Disabled */ | ||
134 | } | ||
135 | |||
136 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 127 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
137 | { | 128 | { |
138 | int i; | 129 | int i; |
@@ -287,6 +278,13 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
287 | *pos++ |= sdata->u.mesh.accepting_plinks ? | 278 | *pos++ |= sdata->u.mesh.accepting_plinks ? |
288 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 279 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
289 | *pos++ = 0x00; | 280 | *pos++ = 0x00; |
281 | |||
282 | if (sdata->u.mesh.vendor_ie) { | ||
283 | int len = sdata->u.mesh.vendor_ie_len; | ||
284 | const u8 *data = sdata->u.mesh.vendor_ie; | ||
285 | if (skb_tailroom(skb) > len) | ||
286 | memcpy(skb_put(skb, len), data, len); | ||
287 | } | ||
290 | } | 288 | } |
291 | 289 | ||
292 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) | 290 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) |
@@ -412,39 +410,33 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
412 | * ieee80211_new_mesh_header - create a new mesh header | 410 | * ieee80211_new_mesh_header - create a new mesh header |
413 | * @meshhdr: uninitialized mesh header | 411 | * @meshhdr: uninitialized mesh header |
414 | * @sdata: mesh interface to be used | 412 | * @sdata: mesh interface to be used |
415 | * @addr4: addr4 of the mesh frame (1st in ae header) | 413 | * @addr4or5: 1st address in the ae header, which may correspond to address 4 |
416 | * may be NULL | 414 | * (if addr6 is NULL) or address 5 (if addr6 is present). It may |
417 | * @addr5: addr5 of the mesh frame (1st or 2nd in ae header) | 415 | * be NULL. |
418 | * may be NULL unless addr6 is present | 416 | * @addr6: 2nd address in the ae header, which corresponds to addr6 of the |
419 | * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header) | 417 | * mesh frame |
420 | * may be NULL unless addr5 is present | ||
421 | * | 418 | * |
422 | * Return the header length. | 419 | * Return the header length. |
423 | */ | 420 | */ |
424 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 421 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
425 | struct ieee80211_sub_if_data *sdata, char *addr4, | 422 | struct ieee80211_sub_if_data *sdata, char *addr4or5, |
426 | char *addr5, char *addr6) | 423 | char *addr6) |
427 | { | 424 | { |
428 | int aelen = 0; | 425 | int aelen = 0; |
426 | BUG_ON(!addr4or5 && addr6); | ||
429 | memset(meshhdr, 0, sizeof(*meshhdr)); | 427 | memset(meshhdr, 0, sizeof(*meshhdr)); |
430 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 428 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
431 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); | 429 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
432 | sdata->u.mesh.mesh_seqnum++; | 430 | sdata->u.mesh.mesh_seqnum++; |
433 | if (addr4) { | 431 | if (addr4or5 && !addr6) { |
434 | meshhdr->flags |= MESH_FLAGS_AE_A4; | 432 | meshhdr->flags |= MESH_FLAGS_AE_A4; |
435 | aelen += ETH_ALEN; | 433 | aelen += ETH_ALEN; |
436 | memcpy(meshhdr->eaddr1, addr4, ETH_ALEN); | 434 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
437 | } | 435 | } else if (addr4or5 && addr6) { |
438 | if (addr5 && addr6) { | ||
439 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; | 436 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; |
440 | aelen += 2 * ETH_ALEN; | 437 | aelen += 2 * ETH_ALEN; |
441 | if (!addr4) { | 438 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
442 | memcpy(meshhdr->eaddr1, addr5, ETH_ALEN); | 439 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); |
443 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); | ||
444 | } else { | ||
445 | memcpy(meshhdr->eaddr2, addr5, ETH_ALEN); | ||
446 | memcpy(meshhdr->eaddr3, addr6, ETH_ALEN); | ||
447 | } | ||
448 | } | 440 | } |
449 | return 6 + aelen; | 441 | return 6 + aelen; |
450 | } | 442 | } |
@@ -513,6 +505,14 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
513 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 505 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
514 | struct ieee80211_local *local = sdata->local; | 506 | struct ieee80211_local *local = sdata->local; |
515 | 507 | ||
508 | local->fif_other_bss++; | ||
509 | /* mesh ifaces must set allmulti to forward mcast traffic */ | ||
510 | atomic_inc(&local->iff_allmultis); | ||
511 | ieee80211_configure_filter(local); | ||
512 | |||
513 | ifmsh->mesh_cc_id = 0; /* Disabled */ | ||
514 | ifmsh->mesh_sp_id = 0; /* Neighbor Offset */ | ||
515 | ifmsh->mesh_auth_id = 0; /* Disabled */ | ||
516 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 516 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
517 | ieee80211_mesh_root_setup(ifmsh); | 517 | ieee80211_mesh_root_setup(ifmsh); |
518 | ieee80211_queue_work(&local->hw, &sdata->work); | 518 | ieee80211_queue_work(&local->hw, &sdata->work); |
@@ -524,6 +524,13 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
524 | 524 | ||
525 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 525 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
526 | { | 526 | { |
527 | struct ieee80211_local *local = sdata->local; | ||
528 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
529 | |||
530 | ifmsh->mesh_id_len = 0; | ||
531 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | ||
532 | sta_info_flush(local, NULL); | ||
533 | |||
527 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 534 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
528 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); | 535 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); |
529 | /* | 536 | /* |
@@ -534,6 +541,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
534 | * it no longer is. | 541 | * it no longer is. |
535 | */ | 542 | */ |
536 | cancel_work_sync(&sdata->work); | 543 | cancel_work_sync(&sdata->work); |
544 | |||
545 | local->fif_other_bss--; | ||
546 | atomic_dec(&local->iff_allmultis); | ||
547 | ieee80211_configure_filter(local); | ||
537 | } | 548 | } |
538 | 549 | ||
539 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | 550 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, |
@@ -663,26 +674,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
663 | ieee80211_mesh_housekeeping_timer, | 674 | ieee80211_mesh_housekeeping_timer, |
664 | (unsigned long) sdata); | 675 | (unsigned long) sdata); |
665 | 676 | ||
666 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; | ||
667 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | ||
668 | ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | ||
669 | ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | ||
670 | ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; | ||
671 | ifmsh->mshcfg.auto_open_plinks = true; | ||
672 | ifmsh->mshcfg.dot11MeshMaxPeerLinks = | ||
673 | MESH_MAX_ESTAB_PLINKS; | ||
674 | ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = | ||
675 | MESH_PATH_TIMEOUT; | ||
676 | ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = | ||
677 | MESH_PREQ_MIN_INT; | ||
678 | ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = | ||
679 | MESH_DIAM_TRAVERSAL_TIME; | ||
680 | ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = | ||
681 | MESH_MAX_PREQ_RETRIES; | ||
682 | ifmsh->mshcfg.path_refresh_time = | ||
683 | MESH_PATH_REFRESH_TIME; | ||
684 | ifmsh->mshcfg.min_discovery_timeout = | ||
685 | MESH_MIN_DISCOVERY_TIMEOUT; | ||
686 | ifmsh->accepting_plinks = true; | 677 | ifmsh->accepting_plinks = true; |
687 | ifmsh->preq_id = 0; | 678 | ifmsh->preq_id = 0; |
688 | ifmsh->sn = 0; | 679 | ifmsh->sn = 0; |
@@ -692,7 +683,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
692 | /* Allocate all mesh structures when creating the first mesh interface. */ | 683 | /* Allocate all mesh structures when creating the first mesh interface. */ |
693 | if (!mesh_allocated) | 684 | if (!mesh_allocated) |
694 | ieee80211s_init(); | 685 | ieee80211s_init(); |
695 | mesh_ids_set_default(ifmsh); | ||
696 | setup_timer(&ifmsh->mesh_path_timer, | 686 | setup_timer(&ifmsh->mesh_path_timer, |
697 | ieee80211_mesh_path_timer, | 687 | ieee80211_mesh_path_timer, |
698 | (unsigned long) sdata); | 688 | (unsigned long) sdata); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 58e741128968..b99e230fe31c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -164,44 +164,10 @@ struct mesh_rmc { | |||
164 | }; | 164 | }; |
165 | 165 | ||
166 | 166 | ||
167 | /* | ||
168 | * MESH_CFG_COMP_LEN Includes: | ||
169 | * - Active path selection protocol ID. | ||
170 | * - Active path selection metric ID. | ||
171 | * - Congestion control mode identifier. | ||
172 | * - Channel precedence. | ||
173 | * Does not include mesh capabilities, which may vary across nodes in the same | ||
174 | * mesh | ||
175 | */ | ||
176 | #define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2) | ||
177 | |||
178 | /* Default values, timeouts in ms */ | ||
179 | #define MESH_TTL 31 | ||
180 | #define MESH_MAX_RETR 3 | ||
181 | #define MESH_RET_T 100 | ||
182 | #define MESH_CONF_T 100 | ||
183 | #define MESH_HOLD_T 100 | ||
184 | |||
185 | #define MESH_PATH_TIMEOUT 5000 | ||
186 | /* Minimum interval between two consecutive PREQs originated by the same | ||
187 | * interface | ||
188 | */ | ||
189 | #define MESH_PREQ_MIN_INT 10 | ||
190 | #define MESH_DIAM_TRAVERSAL_TIME 50 | ||
191 | /* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds before | ||
192 | * timing out. This way it will remain ACTIVE and no data frames will be | ||
193 | * unnecesarily held in the pending queue. | ||
194 | */ | ||
195 | #define MESH_PATH_REFRESH_TIME 1000 | ||
196 | #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME) | ||
197 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ | 167 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ |
198 | 168 | ||
199 | #define MESH_MAX_PREQ_RETRIES 4 | ||
200 | #define MESH_PATH_EXPIRE (600 * HZ) | 169 | #define MESH_PATH_EXPIRE (600 * HZ) |
201 | 170 | ||
202 | /* Default maximum number of established plinks per interface */ | ||
203 | #define MESH_MAX_ESTAB_PLINKS 32 | ||
204 | |||
205 | /* Default maximum number of plinks per interface */ | 171 | /* Default maximum number of plinks per interface */ |
206 | #define MESH_MAX_PLINKS 256 | 172 | #define MESH_MAX_PLINKS 256 |
207 | 173 | ||
@@ -221,8 +187,8 @@ struct mesh_rmc { | |||
221 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 187 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
222 | const u8 *da, const u8 *sa); | 188 | const u8 *da, const u8 *sa); |
223 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 189 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
224 | struct ieee80211_sub_if_data *sdata, char *addr4, | 190 | struct ieee80211_sub_if_data *sdata, char *addr4or5, |
225 | char *addr5, char *addr6); | 191 | char *addr6); |
226 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 192 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, |
227 | struct ieee80211_sub_if_data *sdata); | 193 | struct ieee80211_sub_if_data *sdata); |
228 | bool mesh_matches_local(struct ieee802_11_elems *ie, | 194 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
@@ -318,6 +284,11 @@ static inline void mesh_path_activate(struct mesh_path *mpath) | |||
318 | mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED; | 284 | mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED; |
319 | } | 285 | } |
320 | 286 | ||
287 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | ||
288 | { | ||
289 | return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; | ||
290 | } | ||
291 | |||
321 | #define for_each_mesh_entry(x, p, node, i) \ | 292 | #define for_each_mesh_entry(x, p, node, i) \ |
322 | for (i = 0; i <= x->hash_mask; i++) \ | 293 | for (i = 0; i <= x->hash_mask; i++) \ |
323 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) | 294 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) |
@@ -338,6 +309,8 @@ static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | |||
338 | {} | 309 | {} |
339 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} | 310 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} |
340 | static inline void mesh_plink_restart(struct sta_info *sta) {} | 311 | static inline void mesh_plink_restart(struct sta_info *sta) {} |
312 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | ||
313 | { return false; } | ||
341 | #endif | 314 | #endif |
342 | 315 | ||
343 | #endif /* IEEE80211S_H */ | 316 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 829e08a657d0..5bf64d7112b3 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -232,7 +232,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
232 | *pos++ = WLAN_EID_PERR; | 232 | *pos++ = WLAN_EID_PERR; |
233 | *pos++ = ie_len; | 233 | *pos++ = ie_len; |
234 | /* ttl */ | 234 | /* ttl */ |
235 | *pos++ = MESH_TTL; | 235 | *pos++ = ttl; |
236 | /* number of destinations */ | 236 | /* number of destinations */ |
237 | *pos++ = 1; | 237 | *pos++ = 1; |
238 | /* | 238 | /* |
@@ -522,7 +522,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
522 | 522 | ||
523 | if (reply) { | 523 | if (reply) { |
524 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 524 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
525 | ttl = ifmsh->mshcfg.dot11MeshTTL; | 525 | ttl = ifmsh->mshcfg.element_ttl; |
526 | if (ttl != 0) { | 526 | if (ttl != 0) { |
527 | mhwmp_dbg("replying to the PREQ\n"); | 527 | mhwmp_dbg("replying to the PREQ\n"); |
528 | mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, | 528 | mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, |
@@ -877,7 +877,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
877 | sdata->u.mesh.last_sn_update = jiffies; | 877 | sdata->u.mesh.last_sn_update = jiffies; |
878 | } | 878 | } |
879 | lifetime = default_lifetime(sdata); | 879 | lifetime = default_lifetime(sdata); |
880 | ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 880 | ttl = sdata->u.mesh.mshcfg.element_ttl; |
881 | if (ttl == 0) { | 881 | if (ttl == 0) { |
882 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 882 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
883 | spin_unlock_bh(&mpath->state_lock); | 883 | spin_unlock_bh(&mpath->state_lock); |
@@ -1013,5 +1013,6 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | |||
1013 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, | 1013 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, |
1014 | cpu_to_le32(++ifmsh->sn), | 1014 | cpu_to_le32(++ifmsh->sn), |
1015 | 0, NULL, 0, broadcast_addr, | 1015 | 0, NULL, 0, broadcast_addr, |
1016 | 0, MESH_TTL, 0, 0, 0, sdata); | 1016 | 0, sdata->u.mesh.mshcfg.element_ttl, |
1017 | 0, 0, 0, sdata); | ||
1017 | } | 1018 | } |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 349e466cf08b..8d65b47d9837 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -467,8 +467,8 @@ void mesh_plink_broken(struct sta_info *sta) | |||
467 | mpath->flags &= ~MESH_PATH_ACTIVE; | 467 | mpath->flags &= ~MESH_PATH_ACTIVE; |
468 | ++mpath->sn; | 468 | ++mpath->sn; |
469 | spin_unlock_bh(&mpath->state_lock); | 469 | spin_unlock_bh(&mpath->state_lock); |
470 | mesh_path_error_tx(MESH_TTL, mpath->dst, | 470 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, |
471 | cpu_to_le32(mpath->sn), | 471 | mpath->dst, cpu_to_le32(mpath->sn), |
472 | cpu_to_le16(PERR_RCODE_DEST_UNREACH), | 472 | cpu_to_le16(PERR_RCODE_DEST_UNREACH), |
473 | bcast, sdata); | 473 | bcast, sdata); |
474 | } else | 474 | } else |
@@ -614,7 +614,8 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
614 | mpath = mesh_path_lookup(da, sdata); | 614 | mpath = mesh_path_lookup(da, sdata); |
615 | if (mpath) | 615 | if (mpath) |
616 | sn = ++mpath->sn; | 616 | sn = ++mpath->sn; |
617 | mesh_path_error_tx(MESH_TTL, skb->data, cpu_to_le32(sn), | 617 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, |
618 | cpu_to_le32(sn), | ||
618 | cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata); | 619 | cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata); |
619 | } | 620 | } |
620 | 621 | ||
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 1c91f0f3c307..44b53931ba5e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -160,7 +160,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
160 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, | 160 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, |
161 | __le16 reason) { | 161 | __le16 reason) { |
162 | struct ieee80211_local *local = sdata->local; | 162 | struct ieee80211_local *local = sdata->local; |
163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
164 | sdata->u.mesh.vendor_ie_len); | ||
164 | struct ieee80211_mgmt *mgmt; | 165 | struct ieee80211_mgmt *mgmt; |
165 | bool include_plid = false; | 166 | bool include_plid = false; |
166 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; | 167 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a3a9421555af..45fbb9e33746 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -28,13 +28,19 @@ | |||
28 | #include "rate.h" | 28 | #include "rate.h" |
29 | #include "led.h" | 29 | #include "led.h" |
30 | 30 | ||
31 | #define IEEE80211_MAX_NULLFUNC_TRIES 2 | ||
31 | #define IEEE80211_MAX_PROBE_TRIES 5 | 32 | #define IEEE80211_MAX_PROBE_TRIES 5 |
32 | 33 | ||
33 | /* | 34 | /* |
34 | * beacon loss detection timeout | 35 | * Beacon loss timeout is calculated as N frames times the |
35 | * XXX: should depend on beacon interval | 36 | * advertised beacon interval. This may need to be somewhat |
37 | * higher than what hardware might detect to account for | ||
38 | * delays in the host processing frames. But since we also | ||
39 | * probe on beacon miss before declaring the connection lost | ||
40 | * default to what we want. | ||
36 | */ | 41 | */ |
37 | #define IEEE80211_BEACON_LOSS_TIME (2 * HZ) | 42 | #define IEEE80211_BEACON_LOSS_COUNT 7 |
43 | |||
38 | /* | 44 | /* |
39 | * Time the connection can be idle before we probe | 45 | * Time the connection can be idle before we probe |
40 | * it to see if we can still talk to the AP. | 46 | * it to see if we can still talk to the AP. |
@@ -121,7 +127,7 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) | |||
121 | return; | 127 | return; |
122 | 128 | ||
123 | mod_timer(&sdata->u.mgd.bcn_mon_timer, | 129 | mod_timer(&sdata->u.mgd.bcn_mon_timer, |
124 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); | 130 | round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); |
125 | } | 131 | } |
126 | 132 | ||
127 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) | 133 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) |
@@ -619,11 +625,12 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
619 | /* | 625 | /* |
620 | * Go to full PSM if the user configures a very low | 626 | * Go to full PSM if the user configures a very low |
621 | * latency requirement. | 627 | * latency requirement. |
622 | * The 2 second value is there for compatibility until | 628 | * The 2000 second value is there for compatibility |
623 | * the PM_QOS_NETWORK_LATENCY is configured with real | 629 | * until the PM_QOS_NETWORK_LATENCY is configured |
624 | * values. | 630 | * with real values. |
625 | */ | 631 | */ |
626 | if (latency > 1900000000 && latency != 2000000000) | 632 | if (latency > (1900 * USEC_PER_MSEC) && |
633 | latency != (2000 * USEC_PER_SEC)) | ||
627 | timeout = 0; | 634 | timeout = 0; |
628 | else | 635 | else |
629 | timeout = 100; | 636 | timeout = 100; |
@@ -871,6 +878,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
871 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 878 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
872 | cbss->capability, bss->has_erp_value, bss->erp_value); | 879 | cbss->capability, bss->has_erp_value, bss->erp_value); |
873 | 880 | ||
881 | sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( | ||
882 | IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); | ||
883 | |||
874 | sdata->u.mgd.associated = cbss; | 884 | sdata->u.mgd.associated = cbss; |
875 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); | 885 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
876 | 886 | ||
@@ -1026,6 +1036,54 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1026 | ieee80211_sta_reset_conn_monitor(sdata); | 1036 | ieee80211_sta_reset_conn_monitor(sdata); |
1027 | } | 1037 | } |
1028 | 1038 | ||
1039 | static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | ||
1040 | { | ||
1041 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1042 | |||
1043 | if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | ||
1044 | IEEE80211_STA_CONNECTION_POLL))) | ||
1045 | return; | ||
1046 | |||
1047 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1048 | IEEE80211_STA_BEACON_POLL); | ||
1049 | mutex_lock(&sdata->local->iflist_mtx); | ||
1050 | ieee80211_recalc_ps(sdata->local, -1); | ||
1051 | mutex_unlock(&sdata->local->iflist_mtx); | ||
1052 | |||
1053 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
1054 | return; | ||
1055 | |||
1056 | /* | ||
1057 | * We've received a probe response, but are not sure whether | ||
1058 | * we have or will be receiving any beacons or data, so let's | ||
1059 | * schedule the timers again, just in case. | ||
1060 | */ | ||
1061 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
1062 | |||
1063 | mod_timer(&ifmgd->conn_mon_timer, | ||
1064 | round_jiffies_up(jiffies + | ||
1065 | IEEE80211_CONNECTION_IDLE_TIME)); | ||
1066 | } | ||
1067 | |||
1068 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | ||
1069 | struct ieee80211_hdr *hdr, bool ack) | ||
1070 | { | ||
1071 | if (!ieee80211_is_data(hdr->frame_control)) | ||
1072 | return; | ||
1073 | |||
1074 | if (ack) | ||
1075 | ieee80211_sta_reset_conn_monitor(sdata); | ||
1076 | |||
1077 | if (ieee80211_is_nullfunc(hdr->frame_control) && | ||
1078 | sdata->u.mgd.probe_send_count > 0) { | ||
1079 | if (ack) | ||
1080 | sdata->u.mgd.probe_send_count = 0; | ||
1081 | else | ||
1082 | sdata->u.mgd.nullfunc_failed = true; | ||
1083 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1029 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | 1087 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) |
1030 | { | 1088 | { |
1031 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1089 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1041,8 +1099,20 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1041 | if (ifmgd->probe_send_count >= unicast_limit) | 1099 | if (ifmgd->probe_send_count >= unicast_limit) |
1042 | dst = NULL; | 1100 | dst = NULL; |
1043 | 1101 | ||
1044 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1102 | /* |
1045 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); | 1103 | * When the hardware reports an accurate Tx ACK status, it's |
1104 | * better to send a nullfunc frame instead of a probe request, | ||
1105 | * as it will kick us off the AP quickly if we aren't associated | ||
1106 | * anymore. The timeout will be reset if the frame is ACKed by | ||
1107 | * the AP. | ||
1108 | */ | ||
1109 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | ||
1110 | ifmgd->nullfunc_failed = false; | ||
1111 | ieee80211_send_nullfunc(sdata->local, sdata, 0); | ||
1112 | } else { | ||
1113 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | ||
1114 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); | ||
1115 | } | ||
1046 | 1116 | ||
1047 | ifmgd->probe_send_count++; | 1117 | ifmgd->probe_send_count++; |
1048 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | 1118 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; |
@@ -1108,6 +1178,30 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1108 | mutex_unlock(&ifmgd->mtx); | 1178 | mutex_unlock(&ifmgd->mtx); |
1109 | } | 1179 | } |
1110 | 1180 | ||
1181 | struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | ||
1182 | struct ieee80211_vif *vif) | ||
1183 | { | ||
1184 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1185 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1186 | struct sk_buff *skb; | ||
1187 | const u8 *ssid; | ||
1188 | |||
1189 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | ||
1190 | return NULL; | ||
1191 | |||
1192 | ASSERT_MGD_MTX(ifmgd); | ||
1193 | |||
1194 | if (!ifmgd->associated) | ||
1195 | return NULL; | ||
1196 | |||
1197 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | ||
1198 | skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, | ||
1199 | ssid + 2, ssid[1], NULL, 0); | ||
1200 | |||
1201 | return skb; | ||
1202 | } | ||
1203 | EXPORT_SYMBOL(ieee80211_ap_probereq_get); | ||
1204 | |||
1111 | static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | 1205 | static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) |
1112 | { | 1206 | { |
1113 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1207 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1485,29 +1579,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1485 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 1579 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
1486 | 1580 | ||
1487 | if (ifmgd->associated && | 1581 | if (ifmgd->associated && |
1488 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && | 1582 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) |
1489 | ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 1583 | ieee80211_reset_ap_probe(sdata); |
1490 | IEEE80211_STA_CONNECTION_POLL)) { | ||
1491 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1492 | IEEE80211_STA_BEACON_POLL); | ||
1493 | mutex_lock(&sdata->local->iflist_mtx); | ||
1494 | ieee80211_recalc_ps(sdata->local, -1); | ||
1495 | mutex_unlock(&sdata->local->iflist_mtx); | ||
1496 | |||
1497 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
1498 | return; | ||
1499 | |||
1500 | /* | ||
1501 | * We've received a probe response, but are not sure whether | ||
1502 | * we have or will be receiving any beacons or data, so let's | ||
1503 | * schedule the timers again, just in case. | ||
1504 | */ | ||
1505 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
1506 | |||
1507 | mod_timer(&ifmgd->conn_mon_timer, | ||
1508 | round_jiffies_up(jiffies + | ||
1509 | IEEE80211_CONNECTION_IDLE_TIME)); | ||
1510 | } | ||
1511 | } | 1584 | } |
1512 | 1585 | ||
1513 | /* | 1586 | /* |
@@ -1845,6 +1918,31 @@ static void ieee80211_sta_timer(unsigned long data) | |||
1845 | ieee80211_queue_work(&local->hw, &sdata->work); | 1918 | ieee80211_queue_work(&local->hw, &sdata->work); |
1846 | } | 1919 | } |
1847 | 1920 | ||
1921 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | ||
1922 | u8 *bssid) | ||
1923 | { | ||
1924 | struct ieee80211_local *local = sdata->local; | ||
1925 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1926 | |||
1927 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1928 | IEEE80211_STA_BEACON_POLL); | ||
1929 | |||
1930 | ieee80211_set_disassoc(sdata, true, true); | ||
1931 | mutex_unlock(&ifmgd->mtx); | ||
1932 | mutex_lock(&local->mtx); | ||
1933 | ieee80211_recalc_idle(local); | ||
1934 | mutex_unlock(&local->mtx); | ||
1935 | /* | ||
1936 | * must be outside lock due to cfg80211, | ||
1937 | * but that's not a problem. | ||
1938 | */ | ||
1939 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
1940 | IEEE80211_STYPE_DEAUTH, | ||
1941 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
1942 | NULL, true); | ||
1943 | mutex_lock(&ifmgd->mtx); | ||
1944 | } | ||
1945 | |||
1848 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | 1946 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
1849 | { | 1947 | { |
1850 | struct ieee80211_local *local = sdata->local; | 1948 | struct ieee80211_local *local = sdata->local; |
@@ -1857,12 +1955,49 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1857 | IEEE80211_STA_CONNECTION_POLL) && | 1955 | IEEE80211_STA_CONNECTION_POLL) && |
1858 | ifmgd->associated) { | 1956 | ifmgd->associated) { |
1859 | u8 bssid[ETH_ALEN]; | 1957 | u8 bssid[ETH_ALEN]; |
1958 | int max_tries; | ||
1860 | 1959 | ||
1861 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1960 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1862 | if (time_is_after_jiffies(ifmgd->probe_timeout)) | ||
1863 | run_again(ifmgd, ifmgd->probe_timeout); | ||
1864 | 1961 | ||
1865 | else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { | 1962 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
1963 | max_tries = IEEE80211_MAX_NULLFUNC_TRIES; | ||
1964 | else | ||
1965 | max_tries = IEEE80211_MAX_PROBE_TRIES; | ||
1966 | |||
1967 | /* ACK received for nullfunc probing frame */ | ||
1968 | if (!ifmgd->probe_send_count) | ||
1969 | ieee80211_reset_ap_probe(sdata); | ||
1970 | else if (ifmgd->nullfunc_failed) { | ||
1971 | if (ifmgd->probe_send_count < max_tries) { | ||
1972 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1973 | wiphy_debug(local->hw.wiphy, | ||
1974 | "%s: No ack for nullfunc frame to" | ||
1975 | " AP %pM, try %d\n", | ||
1976 | sdata->name, bssid, | ||
1977 | ifmgd->probe_send_count); | ||
1978 | #endif | ||
1979 | ieee80211_mgd_probe_ap_send(sdata); | ||
1980 | } else { | ||
1981 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1982 | wiphy_debug(local->hw.wiphy, | ||
1983 | "%s: No ack for nullfunc frame to" | ||
1984 | " AP %pM, disconnecting.\n", | ||
1985 | sdata->name, bssid); | ||
1986 | #endif | ||
1987 | ieee80211_sta_connection_lost(sdata, bssid); | ||
1988 | } | ||
1989 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) | ||
1990 | run_again(ifmgd, ifmgd->probe_timeout); | ||
1991 | else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | ||
1992 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1993 | wiphy_debug(local->hw.wiphy, | ||
1994 | "%s: Failed to send nullfunc to AP %pM" | ||
1995 | " after %dms, disconnecting.\n", | ||
1996 | sdata->name, | ||
1997 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | ||
1998 | #endif | ||
1999 | ieee80211_sta_connection_lost(sdata, bssid); | ||
2000 | } else if (ifmgd->probe_send_count < max_tries) { | ||
1866 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2001 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1867 | wiphy_debug(local->hw.wiphy, | 2002 | wiphy_debug(local->hw.wiphy, |
1868 | "%s: No probe response from AP %pM" | 2003 | "%s: No probe response from AP %pM" |
@@ -1877,27 +2012,13 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1877 | * We actually lost the connection ... or did we? | 2012 | * We actually lost the connection ... or did we? |
1878 | * Let's make sure! | 2013 | * Let's make sure! |
1879 | */ | 2014 | */ |
1880 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1881 | IEEE80211_STA_BEACON_POLL); | ||
1882 | wiphy_debug(local->hw.wiphy, | 2015 | wiphy_debug(local->hw.wiphy, |
1883 | "%s: No probe response from AP %pM" | 2016 | "%s: No probe response from AP %pM" |
1884 | " after %dms, disconnecting.\n", | 2017 | " after %dms, disconnecting.\n", |
1885 | sdata->name, | 2018 | sdata->name, |
1886 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2019 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1887 | ieee80211_set_disassoc(sdata, true, true); | 2020 | |
1888 | mutex_unlock(&ifmgd->mtx); | 2021 | ieee80211_sta_connection_lost(sdata, bssid); |
1889 | mutex_lock(&local->mtx); | ||
1890 | ieee80211_recalc_idle(local); | ||
1891 | mutex_unlock(&local->mtx); | ||
1892 | /* | ||
1893 | * must be outside lock due to cfg80211, | ||
1894 | * but that's not a problem. | ||
1895 | */ | ||
1896 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
1897 | IEEE80211_STYPE_DEAUTH, | ||
1898 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
1899 | NULL, true); | ||
1900 | mutex_lock(&ifmgd->mtx); | ||
1901 | } | 2022 | } |
1902 | } | 2023 | } |
1903 | 2024 | ||
@@ -1988,6 +2109,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | |||
1988 | add_timer(&ifmgd->timer); | 2109 | add_timer(&ifmgd->timer); |
1989 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) | 2110 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) |
1990 | add_timer(&ifmgd->chswitch_timer); | 2111 | add_timer(&ifmgd->chswitch_timer); |
2112 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
2113 | ieee80211_restart_sta_timer(sdata); | ||
1991 | } | 2114 | } |
1992 | #endif | 2115 | #endif |
1993 | 2116 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 4b564091e51d..b4e52676f3fb 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | #include <net/mac80211.h> | 15 | #include <net/mac80211.h> |
16 | #include "ieee80211_i.h" | 16 | #include "ieee80211_i.h" |
17 | #include "driver-trace.h" | ||
17 | 18 | ||
18 | /* | 19 | /* |
19 | * inform AP that we will go to sleep so that it will buffer the frames | 20 | * inform AP that we will go to sleep so that it will buffer the frames |
@@ -190,3 +191,87 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
190 | } | 191 | } |
191 | mutex_unlock(&local->iflist_mtx); | 192 | mutex_unlock(&local->iflist_mtx); |
192 | } | 193 | } |
194 | |||
195 | static void ieee80211_hw_roc_start(struct work_struct *work) | ||
196 | { | ||
197 | struct ieee80211_local *local = | ||
198 | container_of(work, struct ieee80211_local, hw_roc_start); | ||
199 | struct ieee80211_sub_if_data *sdata; | ||
200 | |||
201 | mutex_lock(&local->mtx); | ||
202 | |||
203 | if (!local->hw_roc_channel) { | ||
204 | mutex_unlock(&local->mtx); | ||
205 | return; | ||
206 | } | ||
207 | |||
208 | ieee80211_recalc_idle(local); | ||
209 | |||
210 | if (local->hw_roc_skb) { | ||
211 | sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev); | ||
212 | ieee80211_tx_skb(sdata, local->hw_roc_skb); | ||
213 | local->hw_roc_skb = NULL; | ||
214 | } else { | ||
215 | cfg80211_ready_on_channel(local->hw_roc_dev, | ||
216 | local->hw_roc_cookie, | ||
217 | local->hw_roc_channel, | ||
218 | local->hw_roc_channel_type, | ||
219 | local->hw_roc_duration, | ||
220 | GFP_KERNEL); | ||
221 | } | ||
222 | |||
223 | mutex_unlock(&local->mtx); | ||
224 | } | ||
225 | |||
226 | void ieee80211_ready_on_channel(struct ieee80211_hw *hw) | ||
227 | { | ||
228 | struct ieee80211_local *local = hw_to_local(hw); | ||
229 | |||
230 | trace_api_ready_on_channel(local); | ||
231 | |||
232 | ieee80211_queue_work(hw, &local->hw_roc_start); | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); | ||
235 | |||
236 | static void ieee80211_hw_roc_done(struct work_struct *work) | ||
237 | { | ||
238 | struct ieee80211_local *local = | ||
239 | container_of(work, struct ieee80211_local, hw_roc_done); | ||
240 | |||
241 | mutex_lock(&local->mtx); | ||
242 | |||
243 | if (!local->hw_roc_channel) { | ||
244 | mutex_unlock(&local->mtx); | ||
245 | return; | ||
246 | } | ||
247 | |||
248 | if (!local->hw_roc_for_tx) | ||
249 | cfg80211_remain_on_channel_expired(local->hw_roc_dev, | ||
250 | local->hw_roc_cookie, | ||
251 | local->hw_roc_channel, | ||
252 | local->hw_roc_channel_type, | ||
253 | GFP_KERNEL); | ||
254 | |||
255 | local->hw_roc_channel = NULL; | ||
256 | local->hw_roc_cookie = 0; | ||
257 | |||
258 | ieee80211_recalc_idle(local); | ||
259 | |||
260 | mutex_unlock(&local->mtx); | ||
261 | } | ||
262 | |||
263 | void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw) | ||
264 | { | ||
265 | struct ieee80211_local *local = hw_to_local(hw); | ||
266 | |||
267 | trace_api_remain_on_channel_expired(local); | ||
268 | |||
269 | ieee80211_queue_work(hw, &local->hw_roc_done); | ||
270 | } | ||
271 | EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); | ||
272 | |||
273 | void ieee80211_hw_roc_setup(struct ieee80211_local *local) | ||
274 | { | ||
275 | INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); | ||
276 | INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); | ||
277 | } | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 33f76993da08..3d5a2cb835c4 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -211,7 +211,8 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) | |||
211 | return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc); | 211 | return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc); |
212 | } | 212 | } |
213 | 213 | ||
214 | static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx) | 214 | static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, |
215 | struct ieee80211_supported_band *sband) | ||
215 | { | 216 | { |
216 | u8 i; | 217 | u8 i; |
217 | 218 | ||
@@ -222,7 +223,7 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx) | |||
222 | if (basic_rates & (1 << *idx)) | 223 | if (basic_rates & (1 << *idx)) |
223 | return; /* selected rate is a basic rate */ | 224 | return; /* selected rate is a basic rate */ |
224 | 225 | ||
225 | for (i = *idx + 1; i <= max_rate_idx; i++) { | 226 | for (i = *idx + 1; i <= sband->n_bitrates; i++) { |
226 | if (basic_rates & (1 << i)) { | 227 | if (basic_rates & (1 << i)) { |
227 | *idx = i; | 228 | *idx = i; |
228 | return; | 229 | return; |
@@ -237,16 +238,25 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
237 | struct ieee80211_tx_rate_control *txrc) | 238 | struct ieee80211_tx_rate_control *txrc) |
238 | { | 239 | { |
239 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | 240 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
241 | struct ieee80211_supported_band *sband = txrc->sband; | ||
242 | int mcast_rate; | ||
240 | 243 | ||
241 | if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { | 244 | if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { |
242 | info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); | 245 | info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); |
243 | info->control.rates[0].count = | 246 | info->control.rates[0].count = |
244 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 247 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
245 | 1 : txrc->hw->max_rate_tries; | 248 | 1 : txrc->hw->max_rate_tries; |
246 | if (!sta && txrc->ap) | 249 | if (!sta && txrc->bss) { |
250 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; | ||
251 | if (mcast_rate > 0) { | ||
252 | info->control.rates[0].idx = mcast_rate - 1; | ||
253 | return true; | ||
254 | } | ||
255 | |||
247 | rc_send_low_broadcast(&info->control.rates[0].idx, | 256 | rc_send_low_broadcast(&info->control.rates[0].idx, |
248 | txrc->bss_conf->basic_rates, | 257 | txrc->bss_conf->basic_rates, |
249 | txrc->sband->n_bitrates); | 258 | sband); |
259 | } | ||
250 | return true; | 260 | return true; |
251 | } | 261 | } |
252 | return false; | 262 | return false; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 2a18d6602d4a..165a4518bb48 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -371,7 +371,10 @@ minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, stru | |||
371 | if (likely(sta->ampdu_mlme.tid_tx[tid])) | 371 | if (likely(sta->ampdu_mlme.tid_tx[tid])) |
372 | return; | 372 | return; |
373 | 373 | ||
374 | ieee80211_start_tx_ba_session(pubsta, tid); | 374 | if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) |
375 | return; | ||
376 | |||
377 | ieee80211_start_tx_ba_session(pubsta, tid, 5000); | ||
375 | } | 378 | } |
376 | 379 | ||
377 | static void | 380 | static void |
@@ -407,8 +410,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
407 | mi->ampdu_len += info->status.ampdu_len; | 410 | mi->ampdu_len += info->status.ampdu_len; |
408 | 411 | ||
409 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { | 412 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { |
410 | mi->sample_wait = 4 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); | 413 | mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); |
411 | mi->sample_tries = 3; | 414 | mi->sample_tries = 2; |
412 | mi->sample_count--; | 415 | mi->sample_count--; |
413 | } | 416 | } |
414 | 417 | ||
@@ -506,7 +509,9 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
506 | if (!mr->retry_updated) | 509 | if (!mr->retry_updated) |
507 | minstrel_calc_retransmit(mp, mi, index); | 510 | minstrel_calc_retransmit(mp, mi, index); |
508 | 511 | ||
509 | if (mr->probability < MINSTREL_FRAC(20, 100)) | 512 | if (sample) |
513 | rate->count = 1; | ||
514 | else if (mr->probability < MINSTREL_FRAC(20, 100)) | ||
510 | rate->count = 2; | 515 | rate->count = 2; |
511 | else if (rtscts) | 516 | else if (rtscts) |
512 | rate->count = mr->retry_count_rtscts; | 517 | rate->count = mr->retry_count_rtscts; |
@@ -562,7 +567,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
562 | */ | 567 | */ |
563 | if (minstrel_get_duration(sample_idx) > | 568 | if (minstrel_get_duration(sample_idx) > |
564 | minstrel_get_duration(mi->max_tp_rate)) { | 569 | minstrel_get_duration(mi->max_tp_rate)) { |
565 | if (mr->sample_skipped < 10) | 570 | if (mr->sample_skipped < 20) |
566 | goto next; | 571 | goto next; |
567 | 572 | ||
568 | if (mi->sample_slow++ > 2) | 573 | if (mi->sample_slow++ > 2) |
@@ -586,6 +591,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
586 | struct minstrel_ht_sta *mi = &msp->ht; | 591 | struct minstrel_ht_sta *mi = &msp->ht; |
587 | struct minstrel_priv *mp = priv; | 592 | struct minstrel_priv *mp = priv; |
588 | int sample_idx; | 593 | int sample_idx; |
594 | bool sample = false; | ||
589 | 595 | ||
590 | if (rate_control_send_low(sta, priv_sta, txrc)) | 596 | if (rate_control_send_low(sta, priv_sta, txrc)) |
591 | return; | 597 | return; |
@@ -596,10 +602,11 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
596 | info->flags |= mi->tx_flags; | 602 | info->flags |= mi->tx_flags; |
597 | sample_idx = minstrel_get_sample_rate(mp, mi); | 603 | sample_idx = minstrel_get_sample_rate(mp, mi); |
598 | if (sample_idx >= 0) { | 604 | if (sample_idx >= 0) { |
605 | sample = true; | ||
599 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, | 606 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, |
600 | txrc, true, false); | 607 | txrc, true, false); |
601 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, | 608 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, |
602 | txrc, false, true); | 609 | txrc, false, false); |
603 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 610 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
604 | } else { | 611 | } else { |
605 | minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, | 612 | minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, |
@@ -607,7 +614,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
607 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2, | 614 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2, |
608 | txrc, false, true); | 615 | txrc, false, true); |
609 | } | 616 | } |
610 | minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, true); | 617 | minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, !sample); |
611 | 618 | ||
612 | ar[3].count = 0; | 619 | ar[3].count = 0; |
613 | ar[3].idx = -1; | 620 | ar[3].idx = -1; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 902b03ee8f60..a6701ed87f0d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -533,10 +533,13 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
533 | 533 | ||
534 | static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | 534 | static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, |
535 | struct tid_ampdu_rx *tid_agg_rx, | 535 | struct tid_ampdu_rx *tid_agg_rx, |
536 | int index, | 536 | int index) |
537 | struct sk_buff_head *frames) | ||
538 | { | 537 | { |
538 | struct ieee80211_local *local = hw_to_local(hw); | ||
539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
540 | struct ieee80211_rx_status *status; | ||
541 | |||
542 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
540 | 543 | ||
541 | if (!skb) | 544 | if (!skb) |
542 | goto no_frame; | 545 | goto no_frame; |
@@ -544,7 +547,9 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
544 | /* release the frame from the reorder ring buffer */ | 547 | /* release the frame from the reorder ring buffer */ |
545 | tid_agg_rx->stored_mpdu_num--; | 548 | tid_agg_rx->stored_mpdu_num--; |
546 | tid_agg_rx->reorder_buf[index] = NULL; | 549 | tid_agg_rx->reorder_buf[index] = NULL; |
547 | __skb_queue_tail(frames, skb); | 550 | status = IEEE80211_SKB_RXCB(skb); |
551 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; | ||
552 | skb_queue_tail(&local->rx_skb_queue, skb); | ||
548 | 553 | ||
549 | no_frame: | 554 | no_frame: |
550 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 555 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
@@ -552,15 +557,16 @@ no_frame: | |||
552 | 557 | ||
553 | static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | 558 | static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, |
554 | struct tid_ampdu_rx *tid_agg_rx, | 559 | struct tid_ampdu_rx *tid_agg_rx, |
555 | u16 head_seq_num, | 560 | u16 head_seq_num) |
556 | struct sk_buff_head *frames) | ||
557 | { | 561 | { |
558 | int index; | 562 | int index; |
559 | 563 | ||
564 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
565 | |||
560 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 566 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
561 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 567 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
562 | tid_agg_rx->buf_size; | 568 | tid_agg_rx->buf_size; |
563 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | 569 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); |
564 | } | 570 | } |
565 | } | 571 | } |
566 | 572 | ||
@@ -576,11 +582,12 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
576 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 582 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
577 | 583 | ||
578 | static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | 584 | static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, |
579 | struct tid_ampdu_rx *tid_agg_rx, | 585 | struct tid_ampdu_rx *tid_agg_rx) |
580 | struct sk_buff_head *frames) | ||
581 | { | 586 | { |
582 | int index, j; | 587 | int index, j; |
583 | 588 | ||
589 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
590 | |||
584 | /* release the buffer until next missing frame */ | 591 | /* release the buffer until next missing frame */ |
585 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 592 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
586 | tid_agg_rx->buf_size; | 593 | tid_agg_rx->buf_size; |
@@ -606,8 +613,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
606 | wiphy_debug(hw->wiphy, | 613 | wiphy_debug(hw->wiphy, |
607 | "release an RX reorder frame due to timeout on earlier frames\n"); | 614 | "release an RX reorder frame due to timeout on earlier frames\n"); |
608 | #endif | 615 | #endif |
609 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | 616 | ieee80211_release_reorder_frame(hw, tid_agg_rx, j); |
610 | j, frames); | ||
611 | 617 | ||
612 | /* | 618 | /* |
613 | * Increment the head seq# also for the skipped slots. | 619 | * Increment the head seq# also for the skipped slots. |
@@ -617,31 +623,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
617 | skipped = 0; | 623 | skipped = 0; |
618 | } | 624 | } |
619 | } else while (tid_agg_rx->reorder_buf[index]) { | 625 | } else while (tid_agg_rx->reorder_buf[index]) { |
620 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | 626 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); |
621 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 627 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
622 | tid_agg_rx->buf_size; | 628 | tid_agg_rx->buf_size; |
623 | } | 629 | } |
624 | 630 | ||
625 | /* | ||
626 | * Disable the reorder release timer for now. | ||
627 | * | ||
628 | * The current implementation lacks a proper locking scheme | ||
629 | * which would protect vital statistic and debug counters | ||
630 | * from being updated by two different but concurrent BHs. | ||
631 | * | ||
632 | * More information about the topic is available from: | ||
633 | * - thread: http://marc.info/?t=128635927000001 | ||
634 | * | ||
635 | * What was wrong: | ||
636 | * => http://marc.info/?l=linux-wireless&m=128636170811964 | ||
637 | * "Basically the thing is that until your patch, the data | ||
638 | * in the struct didn't actually need locking because it | ||
639 | * was accessed by the RX path only which is not concurrent." | ||
640 | * | ||
641 | * List of what needs to be fixed: | ||
642 | * => http://marc.info/?l=linux-wireless&m=128656352920957 | ||
643 | * | ||
644 | |||
645 | if (tid_agg_rx->stored_mpdu_num) { | 631 | if (tid_agg_rx->stored_mpdu_num) { |
646 | j = index = seq_sub(tid_agg_rx->head_seq_num, | 632 | j = index = seq_sub(tid_agg_rx->head_seq_num, |
647 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 633 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
@@ -660,10 +646,6 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
660 | } else { | 646 | } else { |
661 | del_timer(&tid_agg_rx->reorder_timer); | 647 | del_timer(&tid_agg_rx->reorder_timer); |
662 | } | 648 | } |
663 | */ | ||
664 | |||
665 | set_release_timer: | ||
666 | return; | ||
667 | } | 649 | } |
668 | 650 | ||
669 | /* | 651 | /* |
@@ -673,8 +655,7 @@ set_release_timer: | |||
673 | */ | 655 | */ |
674 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 656 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, |
675 | struct tid_ampdu_rx *tid_agg_rx, | 657 | struct tid_ampdu_rx *tid_agg_rx, |
676 | struct sk_buff *skb, | 658 | struct sk_buff *skb) |
677 | struct sk_buff_head *frames) | ||
678 | { | 659 | { |
679 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 660 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
680 | u16 sc = le16_to_cpu(hdr->seq_ctrl); | 661 | u16 sc = le16_to_cpu(hdr->seq_ctrl); |
@@ -683,10 +664,11 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
683 | int index; | 664 | int index; |
684 | bool ret = true; | 665 | bool ret = true; |
685 | 666 | ||
667 | spin_lock(&tid_agg_rx->reorder_lock); | ||
668 | |||
686 | buf_size = tid_agg_rx->buf_size; | 669 | buf_size = tid_agg_rx->buf_size; |
687 | head_seq_num = tid_agg_rx->head_seq_num; | 670 | head_seq_num = tid_agg_rx->head_seq_num; |
688 | 671 | ||
689 | spin_lock(&tid_agg_rx->reorder_lock); | ||
690 | /* frame with out of date sequence number */ | 672 | /* frame with out of date sequence number */ |
691 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 673 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
692 | dev_kfree_skb(skb); | 674 | dev_kfree_skb(skb); |
@@ -700,8 +682,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
700 | if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { | 682 | if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { |
701 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); | 683 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); |
702 | /* release stored frames up to new head to stack */ | 684 | /* release stored frames up to new head to stack */ |
703 | ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num, | 685 | ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num); |
704 | frames); | ||
705 | } | 686 | } |
706 | 687 | ||
707 | /* Now the new frame is always in the range of the reordering buffer */ | 688 | /* Now the new frame is always in the range of the reordering buffer */ |
@@ -729,7 +710,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
729 | tid_agg_rx->reorder_buf[index] = skb; | 710 | tid_agg_rx->reorder_buf[index] = skb; |
730 | tid_agg_rx->reorder_time[index] = jiffies; | 711 | tid_agg_rx->reorder_time[index] = jiffies; |
731 | tid_agg_rx->stored_mpdu_num++; | 712 | tid_agg_rx->stored_mpdu_num++; |
732 | ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); | 713 | ieee80211_sta_reorder_release(hw, tid_agg_rx); |
733 | 714 | ||
734 | out: | 715 | out: |
735 | spin_unlock(&tid_agg_rx->reorder_lock); | 716 | spin_unlock(&tid_agg_rx->reorder_lock); |
@@ -740,8 +721,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
740 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns | 721 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns |
741 | * true if the MPDU was buffered, false if it should be processed. | 722 | * true if the MPDU was buffered, false if it should be processed. |
742 | */ | 723 | */ |
743 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | 724 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) |
744 | struct sk_buff_head *frames) | ||
745 | { | 725 | { |
746 | struct sk_buff *skb = rx->skb; | 726 | struct sk_buff *skb = rx->skb; |
747 | struct ieee80211_local *local = rx->local; | 727 | struct ieee80211_local *local = rx->local; |
@@ -796,11 +776,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
796 | * sure that we cannot get to it any more before doing | 776 | * sure that we cannot get to it any more before doing |
797 | * anything with it. | 777 | * anything with it. |
798 | */ | 778 | */ |
799 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) | 779 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb)) |
800 | return; | 780 | return; |
801 | 781 | ||
802 | dont_reorder: | 782 | dont_reorder: |
803 | __skb_queue_tail(frames, skb); | 783 | skb_queue_tail(&local->rx_skb_queue, skb); |
804 | } | 784 | } |
805 | 785 | ||
806 | static ieee80211_rx_result debug_noinline | 786 | static ieee80211_rx_result debug_noinline |
@@ -948,12 +928,31 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
948 | * have been expected. | 928 | * have been expected. |
949 | */ | 929 | */ |
950 | struct ieee80211_key *key = NULL; | 930 | struct ieee80211_key *key = NULL; |
931 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
932 | int i; | ||
933 | |||
951 | if (ieee80211_is_mgmt(fc) && | 934 | if (ieee80211_is_mgmt(fc) && |
952 | is_multicast_ether_addr(hdr->addr1) && | 935 | is_multicast_ether_addr(hdr->addr1) && |
953 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) | 936 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) |
954 | rx->key = key; | 937 | rx->key = key; |
955 | else if ((key = rcu_dereference(rx->sdata->default_key))) | 938 | else { |
956 | rx->key = key; | 939 | if (rx->sta) { |
940 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
941 | key = rcu_dereference(rx->sta->gtk[i]); | ||
942 | if (key) | ||
943 | break; | ||
944 | } | ||
945 | } | ||
946 | if (!key) { | ||
947 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
948 | key = rcu_dereference(sdata->keys[i]); | ||
949 | if (key) | ||
950 | break; | ||
951 | } | ||
952 | } | ||
953 | if (key) | ||
954 | rx->key = key; | ||
955 | } | ||
957 | return RX_CONTINUE; | 956 | return RX_CONTINUE; |
958 | } else { | 957 | } else { |
959 | u8 keyid; | 958 | u8 keyid; |
@@ -1102,8 +1101,6 @@ static void ap_sta_ps_end(struct sta_info *sta) | |||
1102 | 1101 | ||
1103 | atomic_dec(&sdata->bss->num_sta_ps); | 1102 | atomic_dec(&sdata->bss->num_sta_ps); |
1104 | 1103 | ||
1105 | clear_sta_flags(sta, WLAN_STA_PS_STA); | ||
1106 | |||
1107 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1104 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1108 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 1105 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", |
1109 | sdata->name, sta->sta.addr, sta->sta.aid); | 1106 | sdata->name, sta->sta.addr, sta->sta.aid); |
@@ -1158,12 +1155,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1158 | sta->rx_fragments++; | 1155 | sta->rx_fragments++; |
1159 | sta->rx_bytes += rx->skb->len; | 1156 | sta->rx_bytes += rx->skb->len; |
1160 | sta->last_signal = status->signal; | 1157 | sta->last_signal = status->signal; |
1158 | ewma_add(&sta->avg_signal, -status->signal); | ||
1161 | 1159 | ||
1162 | /* | 1160 | /* |
1163 | * Change STA power saving mode only at the end of a frame | 1161 | * Change STA power saving mode only at the end of a frame |
1164 | * exchange sequence. | 1162 | * exchange sequence. |
1165 | */ | 1163 | */ |
1166 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 1164 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
1165 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | ||
1167 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1166 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1168 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1167 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
1169 | if (test_sta_flags(sta, WLAN_STA_PS_STA)) { | 1168 | if (test_sta_flags(sta, WLAN_STA_PS_STA)) { |
@@ -1515,12 +1514,30 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | |||
1515 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1514 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1516 | if (unlikely(!ieee80211_has_protected(fc) && | 1515 | if (unlikely(!ieee80211_has_protected(fc) && |
1517 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1516 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && |
1518 | rx->key)) | 1517 | rx->key)) { |
1518 | if (ieee80211_is_deauth(fc)) | ||
1519 | cfg80211_send_unprot_deauth(rx->sdata->dev, | ||
1520 | rx->skb->data, | ||
1521 | rx->skb->len); | ||
1522 | else if (ieee80211_is_disassoc(fc)) | ||
1523 | cfg80211_send_unprot_disassoc(rx->sdata->dev, | ||
1524 | rx->skb->data, | ||
1525 | rx->skb->len); | ||
1519 | return -EACCES; | 1526 | return -EACCES; |
1527 | } | ||
1520 | /* BIP does not use Protected field, so need to check MMIE */ | 1528 | /* BIP does not use Protected field, so need to check MMIE */ |
1521 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | 1529 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && |
1522 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) | 1530 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) { |
1531 | if (ieee80211_is_deauth(fc)) | ||
1532 | cfg80211_send_unprot_deauth(rx->sdata->dev, | ||
1533 | rx->skb->data, | ||
1534 | rx->skb->len); | ||
1535 | else if (ieee80211_is_disassoc(fc)) | ||
1536 | cfg80211_send_unprot_disassoc(rx->sdata->dev, | ||
1537 | rx->skb->data, | ||
1538 | rx->skb->len); | ||
1523 | return -EACCES; | 1539 | return -EACCES; |
1540 | } | ||
1524 | /* | 1541 | /* |
1525 | * When using MFP, Action frames are not allowed prior to | 1542 | * When using MFP, Action frames are not allowed prior to |
1526 | * having configured keys. | 1543 | * having configured keys. |
@@ -1791,6 +1808,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1791 | if (!fwd_skb && net_ratelimit()) | 1808 | if (!fwd_skb && net_ratelimit()) |
1792 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1809 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1793 | sdata->name); | 1810 | sdata->name); |
1811 | if (!fwd_skb) | ||
1812 | goto out; | ||
1794 | 1813 | ||
1795 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1814 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1796 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | 1815 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); |
@@ -1828,6 +1847,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1828 | } | 1847 | } |
1829 | } | 1848 | } |
1830 | 1849 | ||
1850 | out: | ||
1831 | if (is_multicast_ether_addr(hdr->addr1) || | 1851 | if (is_multicast_ether_addr(hdr->addr1) || |
1832 | sdata->dev->flags & IFF_PROMISC) | 1852 | sdata->dev->flags & IFF_PROMISC) |
1833 | return RX_CONTINUE; | 1853 | return RX_CONTINUE; |
@@ -1872,9 +1892,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1872 | dev->stats.rx_packets++; | 1892 | dev->stats.rx_packets++; |
1873 | dev->stats.rx_bytes += rx->skb->len; | 1893 | dev->stats.rx_bytes += rx->skb->len; |
1874 | 1894 | ||
1875 | if (ieee80211_is_data(hdr->frame_control) && | 1895 | if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && |
1876 | !is_multicast_ether_addr(hdr->addr1) && | 1896 | !is_multicast_ether_addr(((struct ethhdr *)rx->skb->data)->h_dest)) { |
1877 | local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) { | ||
1878 | mod_timer(&local->dynamic_ps_timer, jiffies + | 1897 | mod_timer(&local->dynamic_ps_timer, jiffies + |
1879 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1898 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1880 | } | 1899 | } |
@@ -1885,7 +1904,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1885 | } | 1904 | } |
1886 | 1905 | ||
1887 | static ieee80211_rx_result debug_noinline | 1906 | static ieee80211_rx_result debug_noinline |
1888 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | 1907 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) |
1889 | { | 1908 | { |
1890 | struct ieee80211_local *local = rx->local; | 1909 | struct ieee80211_local *local = rx->local; |
1891 | struct ieee80211_hw *hw = &local->hw; | 1910 | struct ieee80211_hw *hw = &local->hw; |
@@ -1923,9 +1942,11 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1923 | mod_timer(&tid_agg_rx->session_timer, | 1942 | mod_timer(&tid_agg_rx->session_timer, |
1924 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); | 1943 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); |
1925 | 1944 | ||
1945 | spin_lock(&tid_agg_rx->reorder_lock); | ||
1926 | /* release stored frames up to start of BAR */ | 1946 | /* release stored frames up to start of BAR */ |
1927 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1947 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num); |
1928 | frames); | 1948 | spin_unlock(&tid_agg_rx->reorder_lock); |
1949 | |||
1929 | kfree_skb(skb); | 1950 | kfree_skb(skb); |
1930 | return RX_QUEUED; | 1951 | return RX_QUEUED; |
1931 | } | 1952 | } |
@@ -2116,10 +2137,13 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2116 | } | 2137 | } |
2117 | break; | 2138 | break; |
2118 | case WLAN_CATEGORY_MESH_PLINK: | 2139 | case WLAN_CATEGORY_MESH_PLINK: |
2119 | case WLAN_CATEGORY_MESH_PATH_SEL: | ||
2120 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2140 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2121 | break; | 2141 | break; |
2122 | goto queue; | 2142 | goto queue; |
2143 | case WLAN_CATEGORY_MESH_PATH_SEL: | ||
2144 | if (!mesh_path_sel_is_hwmp(sdata)) | ||
2145 | break; | ||
2146 | goto queue; | ||
2123 | } | 2147 | } |
2124 | 2148 | ||
2125 | return RX_CONTINUE; | 2149 | return RX_CONTINUE; |
@@ -2247,6 +2271,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2247 | break; | 2271 | break; |
2248 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | 2272 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): |
2249 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): | 2273 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): |
2274 | if (is_multicast_ether_addr(mgmt->da) && | ||
2275 | !is_broadcast_ether_addr(mgmt->da)) | ||
2276 | return RX_DROP_MONITOR; | ||
2277 | |||
2250 | /* process only for station */ | 2278 | /* process only for station */ |
2251 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2279 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
2252 | return RX_DROP_MONITOR; | 2280 | return RX_DROP_MONITOR; |
@@ -2433,8 +2461,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
2433 | } | 2461 | } |
2434 | } | 2462 | } |
2435 | 2463 | ||
2436 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | 2464 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) |
2437 | struct sk_buff_head *frames) | ||
2438 | { | 2465 | { |
2439 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2466 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2440 | struct sk_buff *skb; | 2467 | struct sk_buff *skb; |
@@ -2446,7 +2473,15 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2446 | goto rxh_next; \ | 2473 | goto rxh_next; \ |
2447 | } while (0); | 2474 | } while (0); |
2448 | 2475 | ||
2449 | while ((skb = __skb_dequeue(frames))) { | 2476 | spin_lock(&rx->local->rx_skb_queue.lock); |
2477 | if (rx->local->running_rx_handler) | ||
2478 | goto unlock; | ||
2479 | |||
2480 | rx->local->running_rx_handler = true; | ||
2481 | |||
2482 | while ((skb = __skb_dequeue(&rx->local->rx_skb_queue))) { | ||
2483 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2484 | |||
2450 | /* | 2485 | /* |
2451 | * all the other fields are valid across frames | 2486 | * all the other fields are valid across frames |
2452 | * that belong to an aMPDU since they are on the | 2487 | * that belong to an aMPDU since they are on the |
@@ -2469,12 +2504,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2469 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2504 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2470 | #endif | 2505 | #endif |
2471 | CALL_RXH(ieee80211_rx_h_data) | 2506 | CALL_RXH(ieee80211_rx_h_data) |
2472 | 2507 | CALL_RXH(ieee80211_rx_h_ctrl); | |
2473 | /* special treatment -- needs the queue */ | ||
2474 | res = ieee80211_rx_h_ctrl(rx, frames); | ||
2475 | if (res != RX_CONTINUE) | ||
2476 | goto rxh_next; | ||
2477 | |||
2478 | CALL_RXH(ieee80211_rx_h_mgmt_check) | 2508 | CALL_RXH(ieee80211_rx_h_mgmt_check) |
2479 | CALL_RXH(ieee80211_rx_h_action) | 2509 | CALL_RXH(ieee80211_rx_h_action) |
2480 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) | 2510 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) |
@@ -2483,18 +2513,20 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2483 | 2513 | ||
2484 | rxh_next: | 2514 | rxh_next: |
2485 | ieee80211_rx_handlers_result(rx, res); | 2515 | ieee80211_rx_handlers_result(rx, res); |
2486 | 2516 | spin_lock(&rx->local->rx_skb_queue.lock); | |
2487 | #undef CALL_RXH | 2517 | #undef CALL_RXH |
2488 | } | 2518 | } |
2519 | |||
2520 | rx->local->running_rx_handler = false; | ||
2521 | |||
2522 | unlock: | ||
2523 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2489 | } | 2524 | } |
2490 | 2525 | ||
2491 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | 2526 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) |
2492 | { | 2527 | { |
2493 | struct sk_buff_head reorder_release; | ||
2494 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2528 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2495 | 2529 | ||
2496 | __skb_queue_head_init(&reorder_release); | ||
2497 | |||
2498 | #define CALL_RXH(rxh) \ | 2530 | #define CALL_RXH(rxh) \ |
2499 | do { \ | 2531 | do { \ |
2500 | res = rxh(rx); \ | 2532 | res = rxh(rx); \ |
@@ -2505,9 +2537,9 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2505 | CALL_RXH(ieee80211_rx_h_passive_scan) | 2537 | CALL_RXH(ieee80211_rx_h_passive_scan) |
2506 | CALL_RXH(ieee80211_rx_h_check) | 2538 | CALL_RXH(ieee80211_rx_h_check) |
2507 | 2539 | ||
2508 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | 2540 | ieee80211_rx_reorder_ampdu(rx); |
2509 | 2541 | ||
2510 | ieee80211_rx_handlers(rx, &reorder_release); | 2542 | ieee80211_rx_handlers(rx); |
2511 | return; | 2543 | return; |
2512 | 2544 | ||
2513 | rxh_next: | 2545 | rxh_next: |
@@ -2517,13 +2549,11 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2517 | } | 2549 | } |
2518 | 2550 | ||
2519 | /* | 2551 | /* |
2520 | * This function makes calls into the RX path. Therefore the | 2552 | * This function makes calls into the RX path, therefore |
2521 | * caller must hold the sta_info->lock and everything has to | 2553 | * it has to be invoked under RCU read lock. |
2522 | * be under rcu_read_lock protection as well. | ||
2523 | */ | 2554 | */ |
2524 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | 2555 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2525 | { | 2556 | { |
2526 | struct sk_buff_head frames; | ||
2527 | struct ieee80211_rx_data rx = { | 2557 | struct ieee80211_rx_data rx = { |
2528 | .sta = sta, | 2558 | .sta = sta, |
2529 | .sdata = sta->sdata, | 2559 | .sdata = sta->sdata, |
@@ -2536,13 +2566,11 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2536 | if (!tid_agg_rx) | 2566 | if (!tid_agg_rx) |
2537 | return; | 2567 | return; |
2538 | 2568 | ||
2539 | __skb_queue_head_init(&frames); | ||
2540 | |||
2541 | spin_lock(&tid_agg_rx->reorder_lock); | 2569 | spin_lock(&tid_agg_rx->reorder_lock); |
2542 | ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames); | 2570 | ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx); |
2543 | spin_unlock(&tid_agg_rx->reorder_lock); | 2571 | spin_unlock(&tid_agg_rx->reorder_lock); |
2544 | 2572 | ||
2545 | ieee80211_rx_handlers(&rx, &frames); | 2573 | ieee80211_rx_handlers(&rx); |
2546 | } | 2574 | } |
2547 | 2575 | ||
2548 | /* main receive path */ | 2576 | /* main receive path */ |
@@ -2741,6 +2769,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2741 | 2769 | ||
2742 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) | 2770 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) |
2743 | return; | 2771 | return; |
2772 | goto out; | ||
2744 | } | 2773 | } |
2745 | } | 2774 | } |
2746 | 2775 | ||
@@ -2780,6 +2809,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2780 | return; | 2809 | return; |
2781 | } | 2810 | } |
2782 | 2811 | ||
2812 | out: | ||
2783 | dev_kfree_skb(skb); | 2813 | dev_kfree_skb(skb); |
2784 | } | 2814 | } |
2785 | 2815 | ||
@@ -2875,6 +2905,9 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2875 | return; | 2905 | return; |
2876 | } | 2906 | } |
2877 | 2907 | ||
2908 | ieee80211_tpt_led_trig_rx(local, | ||
2909 | ((struct ieee80211_hdr *)skb->data)->frame_control, | ||
2910 | skb->len); | ||
2878 | __ieee80211_rx_handle_packet(hw, skb); | 2911 | __ieee80211_rx_handle_packet(hw, skb); |
2879 | 2912 | ||
2880 | rcu_read_unlock(); | 2913 | rcu_read_unlock(); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 6d8f897d8763..c426504ed1cf 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -199,8 +199,11 @@ static void sta_unblock(struct work_struct *wk) | |||
199 | 199 | ||
200 | if (!test_sta_flags(sta, WLAN_STA_PS_STA)) | 200 | if (!test_sta_flags(sta, WLAN_STA_PS_STA)) |
201 | ieee80211_sta_ps_deliver_wakeup(sta); | 201 | ieee80211_sta_ps_deliver_wakeup(sta); |
202 | else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) | 202 | else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { |
203 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); | ||
203 | ieee80211_sta_ps_deliver_poll_response(sta); | 204 | ieee80211_sta_ps_deliver_poll_response(sta); |
205 | } else | ||
206 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); | ||
204 | } | 207 | } |
205 | 208 | ||
206 | static int sta_prepare_rate_control(struct ieee80211_local *local, | 209 | static int sta_prepare_rate_control(struct ieee80211_local *local, |
@@ -241,6 +244,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
241 | sta->local = local; | 244 | sta->local = local; |
242 | sta->sdata = sdata; | 245 | sta->sdata = sdata; |
243 | 246 | ||
247 | ewma_init(&sta->avg_signal, 1024, 8); | ||
248 | |||
244 | if (sta_prepare_rate_control(local, sta, gfp)) { | 249 | if (sta_prepare_rate_control(local, sta, gfp)) { |
245 | kfree(sta); | 250 | kfree(sta); |
246 | return NULL; | 251 | return NULL; |
@@ -880,6 +885,13 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | |||
880 | } | 885 | } |
881 | EXPORT_SYMBOL(ieee80211_find_sta); | 886 | EXPORT_SYMBOL(ieee80211_find_sta); |
882 | 887 | ||
888 | static void clear_sta_ps_flags(void *_sta) | ||
889 | { | ||
890 | struct sta_info *sta = _sta; | ||
891 | |||
892 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER | WLAN_STA_PS_STA); | ||
893 | } | ||
894 | |||
883 | /* powersave support code */ | 895 | /* powersave support code */ |
884 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | 896 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) |
885 | { | 897 | { |
@@ -894,7 +906,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
894 | 906 | ||
895 | /* Send all buffered frames to the station */ | 907 | /* Send all buffered frames to the station */ |
896 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); | 908 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); |
897 | buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf); | 909 | buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf, |
910 | clear_sta_ps_flags, sta); | ||
898 | sent += buffered; | 911 | sent += buffered; |
899 | local->total_ps_buffered -= buffered; | 912 | local->total_ps_buffered -= buffered; |
900 | 913 | ||
@@ -973,7 +986,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
973 | 986 | ||
974 | if (block) | 987 | if (block) |
975 | set_sta_flags(sta, WLAN_STA_PS_DRIVER); | 988 | set_sta_flags(sta, WLAN_STA_PS_DRIVER); |
976 | else | 989 | else if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) |
977 | ieee80211_queue_work(hw, &sta->drv_unblock_wk); | 990 | ieee80211_queue_work(hw, &sta->drv_unblock_wk); |
978 | } | 991 | } |
979 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 992 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 9265acadef32..bbdd2a86a94b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/if_ether.h> | 14 | #include <linux/if_ether.h> |
15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
16 | #include <linux/average.h> | ||
16 | #include "key.h" | 17 | #include "key.h" |
17 | 18 | ||
18 | /** | 19 | /** |
@@ -77,23 +78,26 @@ enum ieee80211_sta_info_flags { | |||
77 | * @addba_resp_timer: timer for peer's response to addba request | 78 | * @addba_resp_timer: timer for peer's response to addba request |
78 | * @pending: pending frames queue -- use sta's spinlock to protect | 79 | * @pending: pending frames queue -- use sta's spinlock to protect |
79 | * @dialog_token: dialog token for aggregation session | 80 | * @dialog_token: dialog token for aggregation session |
81 | * @timeout: session timeout value to be filled in ADDBA requests | ||
80 | * @state: session state (see above) | 82 | * @state: session state (see above) |
81 | * @stop_initiator: initiator of a session stop | 83 | * @stop_initiator: initiator of a session stop |
82 | * @tx_stop: TX DelBA frame when stopping | 84 | * @tx_stop: TX DelBA frame when stopping |
83 | * | 85 | * |
84 | * This structure is protected by RCU and the per-station | 86 | * This structure's lifetime is managed by RCU, assignments to |
85 | * spinlock. Assignments to the array holding it must hold | 87 | * the array holding it must hold the aggregation mutex. |
86 | * the spinlock, only the TX path can access it under RCU | 88 | * |
87 | * lock-free if, and only if, the state has the flag | 89 | * The TX path can access it under RCU lock-free if, and |
88 | * %HT_AGG_STATE_OPERATIONAL set. Otherwise, the TX path | 90 | * only if, the state has the flag %HT_AGG_STATE_OPERATIONAL |
89 | * must also acquire the spinlock and re-check the state, | 91 | * set. Otherwise, the TX path must also acquire the spinlock |
90 | * see comments in the tx code touching it. | 92 | * and re-check the state, see comments in the tx code |
93 | * touching it. | ||
91 | */ | 94 | */ |
92 | struct tid_ampdu_tx { | 95 | struct tid_ampdu_tx { |
93 | struct rcu_head rcu_head; | 96 | struct rcu_head rcu_head; |
94 | struct timer_list addba_resp_timer; | 97 | struct timer_list addba_resp_timer; |
95 | struct sk_buff_head pending; | 98 | struct sk_buff_head pending; |
96 | unsigned long state; | 99 | unsigned long state; |
100 | u16 timeout; | ||
97 | u8 dialog_token; | 101 | u8 dialog_token; |
98 | u8 stop_initiator; | 102 | u8 stop_initiator; |
99 | bool tx_stop; | 103 | bool tx_stop; |
@@ -115,15 +119,13 @@ struct tid_ampdu_tx { | |||
115 | * @rcu_head: RCU head used for freeing this struct | 119 | * @rcu_head: RCU head used for freeing this struct |
116 | * @reorder_lock: serializes access to reorder buffer, see below. | 120 | * @reorder_lock: serializes access to reorder buffer, see below. |
117 | * | 121 | * |
118 | * This structure is protected by RCU and the per-station | 122 | * This structure's lifetime is managed by RCU, assignments to |
119 | * spinlock. Assignments to the array holding it must hold | 123 | * the array holding it must hold the aggregation mutex. |
120 | * the spinlock. | ||
121 | * | 124 | * |
122 | * The @reorder_lock is used to protect the variables and | 125 | * The @reorder_lock is used to protect the members of this |
123 | * arrays such as @reorder_buf, @reorder_time, @head_seq_num, | 126 | * struct, except for @timeout, @buf_size and @dialog_token, |
124 | * @stored_mpdu_num and @reorder_time from being corrupted by | 127 | * which are constant across the lifetime of the struct (the |
125 | * concurrent access of the RX path and the expired frame | 128 | * dialog token being used only for debugging). |
126 | * release timer. | ||
127 | */ | 129 | */ |
128 | struct tid_ampdu_rx { | 130 | struct tid_ampdu_rx { |
129 | struct rcu_head rcu_head; | 131 | struct rcu_head rcu_head; |
@@ -224,6 +226,7 @@ enum plink_state { | |||
224 | * @rx_fragments: number of received MPDUs | 226 | * @rx_fragments: number of received MPDUs |
225 | * @rx_dropped: number of dropped MPDUs from this STA | 227 | * @rx_dropped: number of dropped MPDUs from this STA |
226 | * @last_signal: signal of last received frame from this STA | 228 | * @last_signal: signal of last received frame from this STA |
229 | * @avg_signal: moving average of signal of received frames from this STA | ||
227 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | 230 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) |
228 | * @tx_filtered_count: number of frames the hardware filtered for this STA | 231 | * @tx_filtered_count: number of frames the hardware filtered for this STA |
229 | * @tx_retry_failed: number of frames that failed retry | 232 | * @tx_retry_failed: number of frames that failed retry |
@@ -248,6 +251,7 @@ enum plink_state { | |||
248 | * @sta: station information we share with the driver | 251 | * @sta: station information we share with the driver |
249 | * @dead: set to true when sta is unlinked | 252 | * @dead: set to true when sta is unlinked |
250 | * @uploaded: set to true when sta is uploaded to the driver | 253 | * @uploaded: set to true when sta is uploaded to the driver |
254 | * @lost_packets: number of consecutive lost packets | ||
251 | */ | 255 | */ |
252 | struct sta_info { | 256 | struct sta_info { |
253 | /* General information, mostly static */ | 257 | /* General information, mostly static */ |
@@ -291,6 +295,7 @@ struct sta_info { | |||
291 | unsigned long rx_fragments; | 295 | unsigned long rx_fragments; |
292 | unsigned long rx_dropped; | 296 | unsigned long rx_dropped; |
293 | int last_signal; | 297 | int last_signal; |
298 | struct ewma avg_signal; | ||
294 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 299 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
295 | 300 | ||
296 | /* Updated from TX status path only, no locking requirements */ | 301 | /* Updated from TX status path only, no locking requirements */ |
@@ -335,6 +340,8 @@ struct sta_info { | |||
335 | } debugfs; | 340 | } debugfs; |
336 | #endif | 341 | #endif |
337 | 342 | ||
343 | unsigned int lost_packets; | ||
344 | |||
338 | /* keep last! */ | 345 | /* keep last! */ |
339 | struct ieee80211_sta sta; | 346 | struct ieee80211_sta sta; |
340 | }; | 347 | }; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 3153c19893b8..38a797217a91 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -157,6 +157,15 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | |||
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
160 | /* | ||
161 | * Use a static threshold for now, best value to be determined | ||
162 | * by testing ... | ||
163 | * Should it depend on: | ||
164 | * - on # of retransmissions | ||
165 | * - current throughput (higher value for higher tpt)? | ||
166 | */ | ||
167 | #define STA_LOST_PKT_THRESHOLD 50 | ||
168 | |||
160 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 169 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
161 | { | 170 | { |
162 | struct sk_buff *skb2; | 171 | struct sk_buff *skb2; |
@@ -173,6 +182,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
173 | int retry_count = -1, i; | 182 | int retry_count = -1, i; |
174 | int rates_idx = -1; | 183 | int rates_idx = -1; |
175 | bool send_to_cooked; | 184 | bool send_to_cooked; |
185 | bool acked; | ||
176 | 186 | ||
177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 187 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
178 | /* the HW cannot have attempted that rate */ | 188 | /* the HW cannot have attempted that rate */ |
@@ -198,8 +208,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
198 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | 208 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) |
199 | continue; | 209 | continue; |
200 | 210 | ||
201 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 211 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); |
202 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | 212 | if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { |
203 | /* | 213 | /* |
204 | * The STA is in power save mode, so assume | 214 | * The STA is in power save mode, so assume |
205 | * that this TX packet failed because of that. | 215 | * that this TX packet failed because of that. |
@@ -231,7 +241,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
231 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
232 | return; | 242 | return; |
233 | } else { | 243 | } else { |
234 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) | 244 | if (!acked) |
235 | sta->tx_retry_failed++; | 245 | sta->tx_retry_failed++; |
236 | sta->tx_retry_count += retry_count; | 246 | sta->tx_retry_count += retry_count; |
237 | } | 247 | } |
@@ -240,9 +250,25 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
240 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 250 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
241 | ieee80211s_update_metric(local, sta, skb); | 251 | ieee80211s_update_metric(local, sta, skb); |
242 | 252 | ||
243 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && | 253 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked) |
244 | (info->flags & IEEE80211_TX_STAT_ACK)) | ||
245 | ieee80211_frame_acked(sta, skb); | 254 | ieee80211_frame_acked(sta, skb); |
255 | |||
256 | if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) && | ||
257 | (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) | ||
258 | ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, acked); | ||
259 | |||
260 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | ||
261 | if (info->flags & IEEE80211_TX_STAT_ACK) { | ||
262 | if (sta->lost_packets) | ||
263 | sta->lost_packets = 0; | ||
264 | } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) { | ||
265 | cfg80211_cqm_pktloss_notify(sta->sdata->dev, | ||
266 | sta->sta.addr, | ||
267 | sta->lost_packets, | ||
268 | GFP_ATOMIC); | ||
269 | sta->lost_packets = 0; | ||
270 | } | ||
271 | } | ||
246 | } | 272 | } |
247 | 273 | ||
248 | rcu_read_unlock(); | 274 | rcu_read_unlock(); |
@@ -295,10 +321,23 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
295 | msecs_to_jiffies(10)); | 321 | msecs_to_jiffies(10)); |
296 | } | 322 | } |
297 | 323 | ||
298 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) | 324 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { |
325 | struct ieee80211_work *wk; | ||
326 | |||
327 | rcu_read_lock(); | ||
328 | list_for_each_entry_rcu(wk, &local->work_list, list) { | ||
329 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
330 | continue; | ||
331 | if (wk->offchan_tx.frame != skb) | ||
332 | continue; | ||
333 | wk->offchan_tx.frame = NULL; | ||
334 | break; | ||
335 | } | ||
336 | rcu_read_unlock(); | ||
299 | cfg80211_mgmt_tx_status( | 337 | cfg80211_mgmt_tx_status( |
300 | skb->dev, (unsigned long) skb, skb->data, skb->len, | 338 | skb->dev, (unsigned long) skb, skb->data, skb->len, |
301 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | 339 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); |
340 | } | ||
302 | 341 | ||
303 | /* this was a transmitted frame, but now we want to reuse it */ | 342 | /* this was a transmitted frame, but now we want to reuse it */ |
304 | skb_orphan(skb); | 343 | skb_orphan(skb); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 96c594309506..5950e3abead9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -539,7 +539,11 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
539 | ieee80211_is_robust_mgmt_frame(hdr) && | 539 | ieee80211_is_robust_mgmt_frame(hdr) && |
540 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 540 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
541 | tx->key = key; | 541 | tx->key = key; |
542 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 542 | else if (is_multicast_ether_addr(hdr->addr1) && |
543 | (key = rcu_dereference(tx->sdata->default_multicast_key))) | ||
544 | tx->key = key; | ||
545 | else if (!is_multicast_ether_addr(hdr->addr1) && | ||
546 | (key = rcu_dereference(tx->sdata->default_unicast_key))) | ||
543 | tx->key = key; | 547 | tx->key = key; |
544 | else if (tx->sdata->drop_unencrypted && | 548 | else if (tx->sdata->drop_unencrypted && |
545 | (tx->skb->protocol != tx->sdata->control_port_protocol) && | 549 | (tx->skb->protocol != tx->sdata->control_port_protocol) && |
@@ -622,7 +626,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
622 | txrc.max_rate_idx = -1; | 626 | txrc.max_rate_idx = -1; |
623 | else | 627 | else |
624 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 628 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
625 | txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP; | 629 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || |
630 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); | ||
626 | 631 | ||
627 | /* set up RTS protection if desired */ | 632 | /* set up RTS protection if desired */ |
628 | if (len > tx->local->hw.wiphy->rts_threshold) { | 633 | if (len > tx->local->hw.wiphy->rts_threshold) { |
@@ -665,10 +670,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
665 | if (unlikely(info->control.rates[0].idx < 0)) | 670 | if (unlikely(info->control.rates[0].idx < 0)) |
666 | return TX_DROP; | 671 | return TX_DROP; |
667 | 672 | ||
668 | if (txrc.reported_rate.idx < 0) | 673 | if (txrc.reported_rate.idx < 0) { |
669 | txrc.reported_rate = info->control.rates[0]; | 674 | txrc.reported_rate = info->control.rates[0]; |
670 | 675 | if (tx->sta && ieee80211_is_data(hdr->frame_control)) | |
671 | if (tx->sta) | 676 | tx->sta->last_tx_rate = txrc.reported_rate; |
677 | } else if (tx->sta) | ||
672 | tx->sta->last_tx_rate = txrc.reported_rate; | 678 | tx->sta->last_tx_rate = txrc.reported_rate; |
673 | 679 | ||
674 | if (unlikely(!info->control.rates[0].count)) | 680 | if (unlikely(!info->control.rates[0].count)) |
@@ -1033,6 +1039,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
1033 | struct ieee80211_radiotap_header *rthdr = | 1039 | struct ieee80211_radiotap_header *rthdr = |
1034 | (struct ieee80211_radiotap_header *) skb->data; | 1040 | (struct ieee80211_radiotap_header *) skb->data; |
1035 | struct ieee80211_supported_band *sband; | 1041 | struct ieee80211_supported_band *sband; |
1042 | bool hw_frag; | ||
1036 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1043 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1037 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, | 1044 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, |
1038 | NULL); | 1045 | NULL); |
@@ -1042,6 +1049,9 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
1042 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1049 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1043 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 1050 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
1044 | 1051 | ||
1052 | /* packet is fragmented in HW if we have a non-NULL driver callback */ | ||
1053 | hw_frag = (tx->local->ops->set_frag_threshold != NULL); | ||
1054 | |||
1045 | /* | 1055 | /* |
1046 | * for every radiotap entry that is present | 1056 | * for every radiotap entry that is present |
1047 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | 1057 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more |
@@ -1078,7 +1088,8 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
1078 | } | 1088 | } |
1079 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | 1089 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) |
1080 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1090 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1081 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | 1091 | if ((*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) && |
1092 | !hw_frag) | ||
1082 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1093 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
1083 | break; | 1094 | break; |
1084 | 1095 | ||
@@ -1181,8 +1192,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1181 | /* | 1192 | /* |
1182 | * Set this flag (used below to indicate "automatic fragmentation"), | 1193 | * Set this flag (used below to indicate "automatic fragmentation"), |
1183 | * it will be cleared/left by radiotap as desired. | 1194 | * it will be cleared/left by radiotap as desired. |
1195 | * Only valid when fragmentation is done by the stack. | ||
1184 | */ | 1196 | */ |
1185 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1197 | if (!local->ops->set_frag_threshold) |
1198 | tx->flags |= IEEE80211_TX_FRAGMENTED; | ||
1186 | 1199 | ||
1187 | /* process and remove the injection radiotap header */ | 1200 | /* process and remove the injection radiotap header */ |
1188 | if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { | 1201 | if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { |
@@ -1284,6 +1297,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1284 | 1297 | ||
1285 | while (skb) { | 1298 | while (skb) { |
1286 | int q = skb_get_queue_mapping(skb); | 1299 | int q = skb_get_queue_mapping(skb); |
1300 | __le16 fc; | ||
1287 | 1301 | ||
1288 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1302 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1289 | ret = IEEE80211_TX_OK; | 1303 | ret = IEEE80211_TX_OK; |
@@ -1326,6 +1340,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1326 | else | 1340 | else |
1327 | info->control.sta = NULL; | 1341 | info->control.sta = NULL; |
1328 | 1342 | ||
1343 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; | ||
1329 | ret = drv_tx(local, skb); | 1344 | ret = drv_tx(local, skb); |
1330 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { | 1345 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { |
1331 | dev_kfree_skb(skb); | 1346 | dev_kfree_skb(skb); |
@@ -1336,6 +1351,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1336 | return IEEE80211_TX_AGAIN; | 1351 | return IEEE80211_TX_AGAIN; |
1337 | } | 1352 | } |
1338 | 1353 | ||
1354 | ieee80211_tpt_led_trig_tx(local, fc, len); | ||
1339 | *skbp = skb = next; | 1355 | *skbp = skb = next; |
1340 | ieee80211_led_tx(local, 1); | 1356 | ieee80211_led_tx(local, 1); |
1341 | fragm = true; | 1357 | fragm = true; |
@@ -1533,8 +1549,10 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1533 | 1549 | ||
1534 | if (skb_header_cloned(skb)) | 1550 | if (skb_header_cloned(skb)) |
1535 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1551 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
1536 | else | 1552 | else if (head_need || tail_need) |
1537 | I802_DEBUG_INC(local->tx_expand_skb_head); | 1553 | I802_DEBUG_INC(local->tx_expand_skb_head); |
1554 | else | ||
1555 | return 0; | ||
1538 | 1556 | ||
1539 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { | 1557 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { |
1540 | wiphy_debug(local->hw.wiphy, | 1558 | wiphy_debug(local->hw.wiphy, |
@@ -1587,7 +1605,12 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1587 | list) { | 1605 | list) { |
1588 | if (!ieee80211_sdata_running(tmp_sdata)) | 1606 | if (!ieee80211_sdata_running(tmp_sdata)) |
1589 | continue; | 1607 | continue; |
1590 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) | 1608 | if (tmp_sdata->vif.type == |
1609 | NL80211_IFTYPE_MONITOR || | ||
1610 | tmp_sdata->vif.type == | ||
1611 | NL80211_IFTYPE_AP_VLAN || | ||
1612 | tmp_sdata->vif.type == | ||
1613 | NL80211_IFTYPE_WDS) | ||
1591 | continue; | 1614 | continue; |
1592 | if (compare_ether_addr(tmp_sdata->vif.addr, | 1615 | if (compare_ether_addr(tmp_sdata->vif.addr, |
1593 | hdr->addr2) == 0) { | 1616 | hdr->addr2) == 0) { |
@@ -1721,26 +1744,25 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1721 | { | 1744 | { |
1722 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1745 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1723 | struct ieee80211_local *local = sdata->local; | 1746 | struct ieee80211_local *local = sdata->local; |
1724 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1747 | struct ieee80211_tx_info *info; |
1725 | int ret = NETDEV_TX_BUSY, head_need; | 1748 | int ret = NETDEV_TX_BUSY, head_need; |
1726 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1749 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1727 | __le16 fc; | 1750 | __le16 fc; |
1728 | struct ieee80211_hdr hdr; | 1751 | struct ieee80211_hdr hdr; |
1729 | struct ieee80211s_hdr mesh_hdr __maybe_unused; | 1752 | struct ieee80211s_hdr mesh_hdr __maybe_unused; |
1753 | struct mesh_path *mppath = NULL; | ||
1730 | const u8 *encaps_data; | 1754 | const u8 *encaps_data; |
1731 | int encaps_len, skip_header_bytes; | 1755 | int encaps_len, skip_header_bytes; |
1732 | int nh_pos, h_pos; | 1756 | int nh_pos, h_pos; |
1733 | struct sta_info *sta = NULL; | 1757 | struct sta_info *sta = NULL; |
1734 | u32 sta_flags = 0; | 1758 | u32 sta_flags = 0; |
1759 | struct sk_buff *tmp_skb; | ||
1735 | 1760 | ||
1736 | if (unlikely(skb->len < ETH_HLEN)) { | 1761 | if (unlikely(skb->len < ETH_HLEN)) { |
1737 | ret = NETDEV_TX_OK; | 1762 | ret = NETDEV_TX_OK; |
1738 | goto fail; | 1763 | goto fail; |
1739 | } | 1764 | } |
1740 | 1765 | ||
1741 | nh_pos = skb_network_header(skb) - skb->data; | ||
1742 | h_pos = skb_transport_header(skb) - skb->data; | ||
1743 | |||
1744 | /* convert Ethernet header to proper 802.11 header (based on | 1766 | /* convert Ethernet header to proper 802.11 header (based on |
1745 | * operation mode) */ | 1767 | * operation mode) */ |
1746 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1768 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
@@ -1789,16 +1811,23 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1789 | ret = NETDEV_TX_OK; | 1811 | ret = NETDEV_TX_OK; |
1790 | goto fail; | 1812 | goto fail; |
1791 | } | 1813 | } |
1814 | if (!is_multicast_ether_addr(skb->data)) | ||
1815 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1792 | 1816 | ||
1817 | /* | ||
1818 | * Do not use address extension, if it is a packet from | ||
1819 | * the same interface and the destination is not being | ||
1820 | * proxied by any other mest point. | ||
1821 | */ | ||
1793 | if (compare_ether_addr(sdata->vif.addr, | 1822 | if (compare_ether_addr(sdata->vif.addr, |
1794 | skb->data + ETH_ALEN) == 0) { | 1823 | skb->data + ETH_ALEN) == 0 && |
1824 | (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) { | ||
1795 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1825 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1796 | skb->data, skb->data + ETH_ALEN); | 1826 | skb->data, skb->data + ETH_ALEN); |
1797 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1827 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1798 | sdata, NULL, NULL, NULL); | 1828 | sdata, NULL, NULL); |
1799 | } else { | 1829 | } else { |
1800 | /* packet from other interface */ | 1830 | /* packet from other interface */ |
1801 | struct mesh_path *mppath; | ||
1802 | int is_mesh_mcast = 1; | 1831 | int is_mesh_mcast = 1; |
1803 | const u8 *mesh_da; | 1832 | const u8 *mesh_da; |
1804 | 1833 | ||
@@ -1809,8 +1838,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1809 | else { | 1838 | else { |
1810 | static const u8 bcast[ETH_ALEN] = | 1839 | static const u8 bcast[ETH_ALEN] = |
1811 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 1840 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
1812 | |||
1813 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1814 | if (mppath) { | 1841 | if (mppath) { |
1815 | /* RA TA mDA mSA AE:DA SA */ | 1842 | /* RA TA mDA mSA AE:DA SA */ |
1816 | mesh_da = mppath->mpp; | 1843 | mesh_da = mppath->mpp; |
@@ -1828,13 +1855,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1828 | ieee80211_new_mesh_header(&mesh_hdr, | 1855 | ieee80211_new_mesh_header(&mesh_hdr, |
1829 | sdata, | 1856 | sdata, |
1830 | skb->data + ETH_ALEN, | 1857 | skb->data + ETH_ALEN, |
1831 | NULL, | ||
1832 | NULL); | 1858 | NULL); |
1833 | else | 1859 | else |
1834 | meshhdrlen = | 1860 | meshhdrlen = |
1835 | ieee80211_new_mesh_header(&mesh_hdr, | 1861 | ieee80211_new_mesh_header(&mesh_hdr, |
1836 | sdata, | 1862 | sdata, |
1837 | NULL, | ||
1838 | skb->data, | 1863 | skb->data, |
1839 | skb->data + ETH_ALEN); | 1864 | skb->data + ETH_ALEN); |
1840 | 1865 | ||
@@ -1913,6 +1938,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1913 | goto fail; | 1938 | goto fail; |
1914 | } | 1939 | } |
1915 | 1940 | ||
1941 | /* | ||
1942 | * If the skb is shared we need to obtain our own copy. | ||
1943 | */ | ||
1944 | if (skb_shared(skb)) { | ||
1945 | tmp_skb = skb; | ||
1946 | skb = skb_clone(skb, GFP_ATOMIC); | ||
1947 | kfree_skb(tmp_skb); | ||
1948 | |||
1949 | if (!skb) { | ||
1950 | ret = NETDEV_TX_OK; | ||
1951 | goto fail; | ||
1952 | } | ||
1953 | } | ||
1954 | |||
1916 | hdr.frame_control = fc; | 1955 | hdr.frame_control = fc; |
1917 | hdr.duration_id = 0; | 1956 | hdr.duration_id = 0; |
1918 | hdr.seq_ctrl = 0; | 1957 | hdr.seq_ctrl = 0; |
@@ -1931,6 +1970,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1931 | encaps_len = 0; | 1970 | encaps_len = 0; |
1932 | } | 1971 | } |
1933 | 1972 | ||
1973 | nh_pos = skb_network_header(skb) - skb->data; | ||
1974 | h_pos = skb_transport_header(skb) - skb->data; | ||
1975 | |||
1934 | skb_pull(skb, skip_header_bytes); | 1976 | skb_pull(skb, skip_header_bytes); |
1935 | nh_pos -= skip_header_bytes; | 1977 | nh_pos -= skip_header_bytes; |
1936 | h_pos -= skip_header_bytes; | 1978 | h_pos -= skip_header_bytes; |
@@ -1997,6 +2039,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1997 | skb_set_network_header(skb, nh_pos); | 2039 | skb_set_network_header(skb, nh_pos); |
1998 | skb_set_transport_header(skb, h_pos); | 2040 | skb_set_transport_header(skb, h_pos); |
1999 | 2041 | ||
2042 | info = IEEE80211_SKB_CB(skb); | ||
2000 | memset(info, 0, sizeof(*info)); | 2043 | memset(info, 0, sizeof(*info)); |
2001 | 2044 | ||
2002 | dev->trans_start = jiffies; | 2045 | dev->trans_start = jiffies; |
@@ -2257,7 +2300,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2257 | u8 *pos; | 2300 | u8 *pos; |
2258 | 2301 | ||
2259 | /* headroom, head length, tail length and maximum TIM length */ | 2302 | /* headroom, head length, tail length and maximum TIM length */ |
2260 | skb = dev_alloc_skb(local->tx_headroom + 400); | 2303 | skb = dev_alloc_skb(local->tx_headroom + 400 + |
2304 | sdata->u.mesh.vendor_ie_len); | ||
2261 | if (!skb) | 2305 | if (!skb) |
2262 | goto out; | 2306 | goto out; |
2263 | 2307 | ||
@@ -2301,7 +2345,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2301 | txrc.max_rate_idx = -1; | 2345 | txrc.max_rate_idx = -1; |
2302 | else | 2346 | else |
2303 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 2347 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
2304 | txrc.ap = true; | 2348 | txrc.bss = true; |
2305 | rate_control_get_rate(sdata, NULL, &txrc); | 2349 | rate_control_get_rate(sdata, NULL, &txrc); |
2306 | 2350 | ||
2307 | info->control.vif = vif; | 2351 | info->control.vif = vif; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0b6fc92bc0d7..cf68700abffa 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -368,8 +368,9 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
368 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 368 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
369 | } | 369 | } |
370 | 370 | ||
371 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | 371 | int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, |
372 | struct sk_buff_head *skbs) | 372 | struct sk_buff_head *skbs, |
373 | void (*fn)(void *data), void *data) | ||
373 | { | 374 | { |
374 | struct ieee80211_hw *hw = &local->hw; | 375 | struct ieee80211_hw *hw = &local->hw; |
375 | struct sk_buff *skb; | 376 | struct sk_buff *skb; |
@@ -394,6 +395,9 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
394 | __skb_queue_tail(&local->pending[queue], skb); | 395 | __skb_queue_tail(&local->pending[queue], skb); |
395 | } | 396 | } |
396 | 397 | ||
398 | if (fn) | ||
399 | fn(data); | ||
400 | |||
397 | for (i = 0; i < hw->queues; i++) | 401 | for (i = 0; i < hw->queues; i++) |
398 | __ieee80211_wake_queue(hw, i, | 402 | __ieee80211_wake_queue(hw, i, |
399 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 403 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
@@ -402,6 +406,12 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
402 | return ret; | 406 | return ret; |
403 | } | 407 | } |
404 | 408 | ||
409 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
410 | struct sk_buff_head *skbs) | ||
411 | { | ||
412 | return ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | ||
413 | } | ||
414 | |||
405 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 415 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
406 | enum queue_stop_reason reason) | 416 | enum queue_stop_reason reason) |
407 | { | 417 | { |
@@ -1011,9 +1021,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1011 | return pos - buffer; | 1021 | return pos - buffer; |
1012 | } | 1022 | } |
1013 | 1023 | ||
1014 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1024 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1015 | const u8 *ssid, size_t ssid_len, | 1025 | u8 *dst, |
1016 | const u8 *ie, size_t ie_len) | 1026 | const u8 *ssid, size_t ssid_len, |
1027 | const u8 *ie, size_t ie_len) | ||
1017 | { | 1028 | { |
1018 | struct ieee80211_local *local = sdata->local; | 1029 | struct ieee80211_local *local = sdata->local; |
1019 | struct sk_buff *skb; | 1030 | struct sk_buff *skb; |
@@ -1027,7 +1038,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1027 | if (!buf) { | 1038 | if (!buf) { |
1028 | printk(KERN_DEBUG "%s: failed to allocate temporary IE " | 1039 | printk(KERN_DEBUG "%s: failed to allocate temporary IE " |
1029 | "buffer\n", sdata->name); | 1040 | "buffer\n", sdata->name); |
1030 | return; | 1041 | return NULL; |
1031 | } | 1042 | } |
1032 | 1043 | ||
1033 | chan = ieee80211_frequency_to_channel( | 1044 | chan = ieee80211_frequency_to_channel( |
@@ -1050,8 +1061,20 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1050 | } | 1061 | } |
1051 | 1062 | ||
1052 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1063 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1053 | ieee80211_tx_skb(sdata, skb); | ||
1054 | kfree(buf); | 1064 | kfree(buf); |
1065 | |||
1066 | return skb; | ||
1067 | } | ||
1068 | |||
1069 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | ||
1070 | const u8 *ssid, size_t ssid_len, | ||
1071 | const u8 *ie, size_t ie_len) | ||
1072 | { | ||
1073 | struct sk_buff *skb; | ||
1074 | |||
1075 | skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len); | ||
1076 | if (skb) | ||
1077 | ieee80211_tx_skb(sdata, skb); | ||
1055 | } | 1078 | } |
1056 | 1079 | ||
1057 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1080 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
@@ -1093,6 +1116,7 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
1093 | void ieee80211_stop_device(struct ieee80211_local *local) | 1116 | void ieee80211_stop_device(struct ieee80211_local *local) |
1094 | { | 1117 | { |
1095 | ieee80211_led_radio(local, false); | 1118 | ieee80211_led_radio(local, false); |
1119 | ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO); | ||
1096 | 1120 | ||
1097 | cancel_work_sync(&local->reconfig_filter); | 1121 | cancel_work_sync(&local->reconfig_filter); |
1098 | 1122 | ||
@@ -1127,6 +1151,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1127 | } | 1151 | } |
1128 | 1152 | ||
1129 | ieee80211_led_radio(local, true); | 1153 | ieee80211_led_radio(local, true); |
1154 | ieee80211_mod_tpt_led_trig(local, | ||
1155 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | ||
1130 | } | 1156 | } |
1131 | 1157 | ||
1132 | /* add interfaces */ | 1158 | /* add interfaces */ |
@@ -1152,6 +1178,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1152 | } | 1178 | } |
1153 | mutex_unlock(&local->sta_mtx); | 1179 | mutex_unlock(&local->sta_mtx); |
1154 | 1180 | ||
1181 | /* setup fragmentation threshold */ | ||
1182 | drv_set_frag_threshold(local, hw->wiphy->frag_threshold); | ||
1183 | |||
1155 | /* setup RTS threshold */ | 1184 | /* setup RTS threshold */ |
1156 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); | 1185 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); |
1157 | 1186 | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 34e6d02da779..28bc084dbfb9 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -21,7 +21,16 @@ | |||
21 | /* Default mapping in classifier to work with default | 21 | /* Default mapping in classifier to work with default |
22 | * queue setup. | 22 | * queue setup. |
23 | */ | 23 | */ |
24 | const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; | 24 | const int ieee802_1d_to_ac[8] = { |
25 | IEEE80211_AC_BE, | ||
26 | IEEE80211_AC_BK, | ||
27 | IEEE80211_AC_BK, | ||
28 | IEEE80211_AC_BE, | ||
29 | IEEE80211_AC_VI, | ||
30 | IEEE80211_AC_VI, | ||
31 | IEEE80211_AC_VO, | ||
32 | IEEE80211_AC_VO | ||
33 | }; | ||
25 | 34 | ||
26 | static int wme_downgrade_ac(struct sk_buff *skb) | 35 | static int wme_downgrade_ac(struct sk_buff *skb) |
27 | { | 36 | { |
@@ -50,26 +59,22 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
50 | { | 59 | { |
51 | struct ieee80211_local *local = sdata->local; | 60 | struct ieee80211_local *local = sdata->local; |
52 | struct sta_info *sta = NULL; | 61 | struct sta_info *sta = NULL; |
53 | u32 sta_flags = 0; | ||
54 | const u8 *ra = NULL; | 62 | const u8 *ra = NULL; |
55 | bool qos = false; | 63 | bool qos = false; |
56 | 64 | ||
57 | if (local->hw.queues < 4 || skb->len < 6) { | 65 | if (local->hw.queues < 4 || skb->len < 6) { |
58 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 66 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
59 | return min_t(u16, local->hw.queues - 1, | 67 | return min_t(u16, local->hw.queues - 1, IEEE80211_AC_BE); |
60 | ieee802_1d_to_ac[skb->priority]); | ||
61 | } | 68 | } |
62 | 69 | ||
63 | rcu_read_lock(); | 70 | rcu_read_lock(); |
64 | switch (sdata->vif.type) { | 71 | switch (sdata->vif.type) { |
65 | case NL80211_IFTYPE_AP_VLAN: | 72 | case NL80211_IFTYPE_AP_VLAN: |
66 | rcu_read_lock(); | ||
67 | sta = rcu_dereference(sdata->u.vlan.sta); | 73 | sta = rcu_dereference(sdata->u.vlan.sta); |
68 | if (sta) | 74 | if (sta) { |
69 | sta_flags = get_sta_flags(sta); | 75 | qos = get_sta_flags(sta) & WLAN_STA_WME; |
70 | rcu_read_unlock(); | ||
71 | if (sta) | ||
72 | break; | 76 | break; |
77 | } | ||
73 | case NL80211_IFTYPE_AP: | 78 | case NL80211_IFTYPE_AP: |
74 | ra = skb->data; | 79 | ra = skb->data; |
75 | break; | 80 | break; |
@@ -98,17 +103,13 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
98 | if (!sta && ra && !is_multicast_ether_addr(ra)) { | 103 | if (!sta && ra && !is_multicast_ether_addr(ra)) { |
99 | sta = sta_info_get(sdata, ra); | 104 | sta = sta_info_get(sdata, ra); |
100 | if (sta) | 105 | if (sta) |
101 | sta_flags = get_sta_flags(sta); | 106 | qos = get_sta_flags(sta) & WLAN_STA_WME; |
102 | } | 107 | } |
103 | |||
104 | if (sta_flags & WLAN_STA_WME) | ||
105 | qos = true; | ||
106 | |||
107 | rcu_read_unlock(); | 108 | rcu_read_unlock(); |
108 | 109 | ||
109 | if (!qos) { | 110 | if (!qos) { |
110 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 111 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
111 | return ieee802_1d_to_ac[skb->priority]; | 112 | return IEEE80211_AC_BE; |
112 | } | 113 | } |
113 | 114 | ||
114 | /* use the data classifier to determine what 802.1d tag the | 115 | /* use the data classifier to determine what 802.1d tag the |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index ae344d1ba056..36305e0d06ef 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -458,8 +458,9 @@ ieee80211_direct_probe(struct ieee80211_work *wk) | |||
458 | return WORK_ACT_TIMEOUT; | 458 | return WORK_ACT_TIMEOUT; |
459 | } | 459 | } |
460 | 460 | ||
461 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d)\n", | 461 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", |
462 | sdata->name, wk->filter_ta, wk->probe_auth.tries); | 462 | sdata->name, wk->filter_ta, wk->probe_auth.tries, |
463 | IEEE80211_AUTH_MAX_TRIES); | ||
463 | 464 | ||
464 | /* | 465 | /* |
465 | * Direct probe is sent to broadcast address as some APs | 466 | * Direct probe is sent to broadcast address as some APs |
@@ -561,6 +562,25 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | |||
561 | } | 562 | } |
562 | 563 | ||
563 | static enum work_action __must_check | 564 | static enum work_action __must_check |
565 | ieee80211_offchannel_tx(struct ieee80211_work *wk) | ||
566 | { | ||
567 | if (!wk->started) { | ||
568 | wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait); | ||
569 | |||
570 | /* | ||
571 | * After this, offchan_tx.frame remains but now is no | ||
572 | * longer a valid pointer -- we still need it as the | ||
573 | * cookie for canceling this work. | ||
574 | */ | ||
575 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); | ||
576 | |||
577 | return WORK_ACT_NONE; | ||
578 | } | ||
579 | |||
580 | return WORK_ACT_TIMEOUT; | ||
581 | } | ||
582 | |||
583 | static enum work_action __must_check | ||
564 | ieee80211_assoc_beacon_wait(struct ieee80211_work *wk) | 584 | ieee80211_assoc_beacon_wait(struct ieee80211_work *wk) |
565 | { | 585 | { |
566 | if (wk->started) | 586 | if (wk->started) |
@@ -955,6 +975,9 @@ static void ieee80211_work_work(struct work_struct *work) | |||
955 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | 975 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: |
956 | rma = ieee80211_remain_on_channel_timeout(wk); | 976 | rma = ieee80211_remain_on_channel_timeout(wk); |
957 | break; | 977 | break; |
978 | case IEEE80211_WORK_OFFCHANNEL_TX: | ||
979 | rma = ieee80211_offchannel_tx(wk); | ||
980 | break; | ||
958 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: | 981 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: |
959 | rma = ieee80211_assoc_beacon_wait(wk); | 982 | rma = ieee80211_assoc_beacon_wait(wk); |
960 | break; | 983 | break; |
@@ -1051,11 +1074,13 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1051 | { | 1074 | { |
1052 | struct ieee80211_local *local = sdata->local; | 1075 | struct ieee80211_local *local = sdata->local; |
1053 | struct ieee80211_work *wk; | 1076 | struct ieee80211_work *wk; |
1077 | bool cleanup = false; | ||
1054 | 1078 | ||
1055 | mutex_lock(&local->mtx); | 1079 | mutex_lock(&local->mtx); |
1056 | list_for_each_entry(wk, &local->work_list, list) { | 1080 | list_for_each_entry(wk, &local->work_list, list) { |
1057 | if (wk->sdata != sdata) | 1081 | if (wk->sdata != sdata) |
1058 | continue; | 1082 | continue; |
1083 | cleanup = true; | ||
1059 | wk->type = IEEE80211_WORK_ABORT; | 1084 | wk->type = IEEE80211_WORK_ABORT; |
1060 | wk->started = true; | 1085 | wk->started = true; |
1061 | wk->timeout = jiffies; | 1086 | wk->timeout = jiffies; |
@@ -1063,7 +1088,8 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1063 | mutex_unlock(&local->mtx); | 1088 | mutex_unlock(&local->mtx); |
1064 | 1089 | ||
1065 | /* run cleanups etc. */ | 1090 | /* run cleanups etc. */ |
1066 | ieee80211_work_work(&local->work_work); | 1091 | if (cleanup) |
1092 | ieee80211_work_work(&local->work_work); | ||
1067 | 1093 | ||
1068 | mutex_lock(&local->mtx); | 1094 | mutex_lock(&local->mtx); |
1069 | list_for_each_entry(wk, &local->work_list, list) { | 1095 | list_for_each_entry(wk, &local->work_list, list) { |