diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/Kconfig | 1 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 70 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 16 | ||||
-rw-r--r-- | net/mac80211/iface.c | 30 | ||||
-rw-r--r-- | net/mac80211/main.c | 5 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 36 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 23 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 9 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 7 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 104 | ||||
-rw-r--r-- | net/mac80211/rx.c | 1 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 3 | ||||
-rw-r--r-- | net/mac80211/status.c | 18 | ||||
-rw-r--r-- | net/mac80211/tx.c | 28 | ||||
-rw-r--r-- | net/mac80211/work.c | 5 |
17 files changed, 200 insertions, 160 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 4d6f8653ec88..798d9b9462e2 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. |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index db134b500caa..c30b8b72eedb 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); |
@@ -343,8 +342,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
343 | 342 | ||
344 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 343 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
345 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 344 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
346 | sinfo->filled |= STATION_INFO_SIGNAL; | 345 | sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; |
347 | sinfo->signal = (s8)sta->last_signal; | 346 | sinfo->signal = (s8)sta->last_signal; |
347 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | ||
348 | } | 348 | } |
349 | 349 | ||
350 | sinfo->txrate.flags = 0; | 350 | sinfo->txrate.flags = 0; |
@@ -999,9 +999,9 @@ static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) | |||
999 | return (mask >> (parm-1)) & 0x1; | 999 | return (mask >> (parm-1)) & 0x1; |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | static int ieee80211_set_mesh_params(struct wiphy *wiphy, | 1002 | static int ieee80211_update_mesh_params(struct wiphy *wiphy, |
1003 | struct net_device *dev, | 1003 | struct net_device *dev, u32 mask, |
1004 | const struct mesh_config *nconf, u32 mask) | 1004 | const struct mesh_config *nconf) |
1005 | { | 1005 | { |
1006 | struct mesh_config *conf; | 1006 | struct mesh_config *conf; |
1007 | struct ieee80211_sub_if_data *sdata; | 1007 | struct ieee80211_sub_if_data *sdata; |
@@ -1024,6 +1024,8 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy, | |||
1024 | conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; | 1024 | conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; |
1025 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) | 1025 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) |
1026 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | 1026 | conf->dot11MeshTTL = nconf->dot11MeshTTL; |
1027 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) | ||
1028 | conf->dot11MeshTTL = nconf->element_ttl; | ||
1027 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1029 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) |
1028 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1030 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1029 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) | 1031 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) |
@@ -1050,6 +1052,30 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy, | |||
1050 | return 0; | 1052 | return 0; |
1051 | } | 1053 | } |
1052 | 1054 | ||
1055 | static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | ||
1056 | const struct mesh_config *conf, | ||
1057 | const struct mesh_setup *setup) | ||
1058 | { | ||
1059 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1060 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1061 | |||
1062 | memcpy(&sdata->u.mesh.mshcfg, conf, sizeof(struct mesh_config)); | ||
1063 | ifmsh->mesh_id_len = setup->mesh_id_len; | ||
1064 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | ||
1065 | |||
1066 | ieee80211_start_mesh(sdata); | ||
1067 | |||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) | ||
1072 | { | ||
1073 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1074 | |||
1075 | ieee80211_stop_mesh(sdata); | ||
1076 | |||
1077 | return 0; | ||
1078 | } | ||
1053 | #endif | 1079 | #endif |
1054 | 1080 | ||
1055 | static int ieee80211_change_bss(struct wiphy *wiphy, | 1081 | static int ieee80211_change_bss(struct wiphy *wiphy, |
@@ -1108,6 +1134,12 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1108 | sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; | 1134 | sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; |
1109 | } | 1135 | } |
1110 | 1136 | ||
1137 | if (params->ht_opmode >= 0) { | ||
1138 | sdata->vif.bss_conf.ht_operation_mode = | ||
1139 | (u16) params->ht_opmode; | ||
1140 | changed |= BSS_CHANGED_HT; | ||
1141 | } | ||
1142 | |||
1111 | ieee80211_bss_info_change_notify(sdata, changed); | 1143 | ieee80211_bss_info_change_notify(sdata, changed); |
1112 | 1144 | ||
1113 | return 0; | 1145 | return 0; |
@@ -1754,8 +1786,10 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1754 | .change_mpath = ieee80211_change_mpath, | 1786 | .change_mpath = ieee80211_change_mpath, |
1755 | .get_mpath = ieee80211_get_mpath, | 1787 | .get_mpath = ieee80211_get_mpath, |
1756 | .dump_mpath = ieee80211_dump_mpath, | 1788 | .dump_mpath = ieee80211_dump_mpath, |
1757 | .set_mesh_params = ieee80211_set_mesh_params, | 1789 | .update_mesh_params = ieee80211_update_mesh_params, |
1758 | .get_mesh_params = ieee80211_get_mesh_params, | 1790 | .get_mesh_params = ieee80211_get_mesh_params, |
1791 | .join_mesh = ieee80211_join_mesh, | ||
1792 | .leave_mesh = ieee80211_leave_mesh, | ||
1759 | #endif | 1793 | #endif |
1760 | .change_bss = ieee80211_change_bss, | 1794 | .change_bss = ieee80211_change_bss, |
1761 | .set_txq_params = ieee80211_set_txq_params, | 1795 | .set_txq_params = ieee80211_set_txq_params, |
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/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 66b0b52b828d..72499fe5fc36 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -357,6 +357,7 @@ struct ieee80211_if_managed { | |||
357 | unsigned long beacon_timeout; | 357 | unsigned long beacon_timeout; |
358 | unsigned long probe_timeout; | 358 | unsigned long probe_timeout; |
359 | int probe_send_count; | 359 | int probe_send_count; |
360 | bool nullfunc_failed; | ||
360 | 361 | ||
361 | struct mutex mtx; | 362 | struct mutex mtx; |
362 | struct cfg80211_bss *associated; | 363 | struct cfg80211_bss *associated; |
@@ -608,19 +609,6 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
608 | return container_of(p, struct ieee80211_sub_if_data, vif); | 609 | return container_of(p, struct ieee80211_sub_if_data, vif); |
609 | } | 610 | } |
610 | 611 | ||
611 | static inline void | ||
612 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | ||
613 | u8 mesh_id_len, u8 *mesh_id) | ||
614 | { | ||
615 | #ifdef CONFIG_MAC80211_MESH | ||
616 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
617 | ifmsh->mesh_id_len = mesh_id_len; | ||
618 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); | ||
619 | #else | ||
620 | WARN_ON(1); | ||
621 | #endif | ||
622 | } | ||
623 | |||
624 | enum sdata_queue_type { | 612 | enum sdata_queue_type { |
625 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, | 613 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, |
626 | IEEE80211_SDATA_QUEUE_AGG_START = 1, | 614 | IEEE80211_SDATA_QUEUE_AGG_START = 1, |
@@ -1271,7 +1259,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
1271 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1259 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1272 | struct ieee80211_hdr *hdr); | 1260 | struct ieee80211_hdr *hdr); |
1273 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | 1261 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
1274 | struct ieee80211_hdr *hdr); | 1262 | struct ieee80211_hdr *hdr, bool ack); |
1275 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); | 1263 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); |
1276 | 1264 | ||
1277 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1265 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7aa85591dbe7..f0f11bb794af 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: |
@@ -273,12 +268,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
273 | goto err_stop; | 268 | goto err_stop; |
274 | } | 269 | } |
275 | 270 | ||
276 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 271 | 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++; | 272 | local->fif_pspoll++; |
283 | local->fif_probe_req++; | 273 | local->fif_probe_req++; |
284 | 274 | ||
@@ -503,18 +493,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
503 | ieee80211_adjust_monitor_flags(sdata, -1); | 493 | ieee80211_adjust_monitor_flags(sdata, -1); |
504 | ieee80211_configure_filter(local); | 494 | ieee80211_configure_filter(local); |
505 | break; | 495 | break; |
506 | case NL80211_IFTYPE_MESH_POINT: | ||
507 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
508 | /* other_bss and allmulti are always set on mesh | ||
509 | * ifaces */ | ||
510 | local->fif_other_bss--; | ||
511 | atomic_dec(&local->iff_allmultis); | ||
512 | |||
513 | ieee80211_configure_filter(local); | ||
514 | |||
515 | ieee80211_stop_mesh(sdata); | ||
516 | } | ||
517 | /* fall through */ | ||
518 | default: | 496 | default: |
519 | flush_work(&sdata->work); | 497 | flush_work(&sdata->work); |
520 | /* | 498 | /* |
@@ -1204,12 +1182,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1204 | if (ret) | 1182 | if (ret) |
1205 | goto fail; | 1183 | goto fail; |
1206 | 1184 | ||
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); | 1185 | mutex_lock(&local->iflist_mtx); |
1214 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1186 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
1215 | mutex_unlock(&local->iflist_mtx); | 1187 | mutex_unlock(&local->iflist_mtx); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 107a0cbe52ac..973fee9f7d69 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); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c8a4f19ed13b..63e1188d5062 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -513,6 +513,11 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
513 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 513 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
514 | struct ieee80211_local *local = sdata->local; | 514 | struct ieee80211_local *local = sdata->local; |
515 | 515 | ||
516 | local->fif_other_bss++; | ||
517 | /* mesh ifaces must set allmulti to forward mcast traffic */ | ||
518 | atomic_inc(&local->iff_allmultis); | ||
519 | ieee80211_configure_filter(local); | ||
520 | |||
516 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 521 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
517 | ieee80211_mesh_root_setup(ifmsh); | 522 | ieee80211_mesh_root_setup(ifmsh); |
518 | ieee80211_queue_work(&local->hw, &sdata->work); | 523 | ieee80211_queue_work(&local->hw, &sdata->work); |
@@ -524,6 +529,13 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
524 | 529 | ||
525 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 530 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
526 | { | 531 | { |
532 | struct ieee80211_local *local = sdata->local; | ||
533 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
534 | |||
535 | ifmsh->mesh_id_len = 0; | ||
536 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | ||
537 | sta_info_flush(local, NULL); | ||
538 | |||
527 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 539 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
528 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); | 540 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); |
529 | /* | 541 | /* |
@@ -534,6 +546,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
534 | * it no longer is. | 546 | * it no longer is. |
535 | */ | 547 | */ |
536 | cancel_work_sync(&sdata->work); | 548 | cancel_work_sync(&sdata->work); |
549 | |||
550 | local->fif_other_bss--; | ||
551 | atomic_dec(&local->iff_allmultis); | ||
552 | ieee80211_configure_filter(local); | ||
537 | } | 553 | } |
538 | 554 | ||
539 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | 555 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, |
@@ -663,26 +679,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
663 | ieee80211_mesh_housekeeping_timer, | 679 | ieee80211_mesh_housekeeping_timer, |
664 | (unsigned long) sdata); | 680 | (unsigned long) sdata); |
665 | 681 | ||
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; | 682 | ifmsh->accepting_plinks = true; |
687 | ifmsh->preq_id = 0; | 683 | ifmsh->preq_id = 0; |
688 | ifmsh->sn = 0; | 684 | ifmsh->sn = 0; |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 58e741128968..039d7fa0af74 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -175,33 +175,10 @@ struct mesh_rmc { | |||
175 | */ | 175 | */ |
176 | #define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2) | 176 | #define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2) |
177 | 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 */ | 178 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ |
198 | 179 | ||
199 | #define MESH_MAX_PREQ_RETRIES 4 | ||
200 | #define MESH_PATH_EXPIRE (600 * HZ) | 180 | #define MESH_PATH_EXPIRE (600 * HZ) |
201 | 181 | ||
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 */ | 182 | /* Default maximum number of plinks per interface */ |
206 | #define MESH_MAX_PLINKS 256 | 183 | #define MESH_MAX_PLINKS 256 |
207 | 184 | ||
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/mlme.c b/net/mac80211/mlme.c index 794807914940..45fbb9e33746 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -625,11 +625,12 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
625 | /* | 625 | /* |
626 | * Go to full PSM if the user configures a very low | 626 | * Go to full PSM if the user configures a very low |
627 | * latency requirement. | 627 | * latency requirement. |
628 | * The 2 second value is there for compatibility until | 628 | * The 2000 second value is there for compatibility |
629 | * the PM_QOS_NETWORK_LATENCY is configured with real | 629 | * until the PM_QOS_NETWORK_LATENCY is configured |
630 | * values. | 630 | * with real values. |
631 | */ | 631 | */ |
632 | if (latency > 1900000000 && latency != 2000000000) | 632 | if (latency > (1900 * USEC_PER_MSEC) && |
633 | latency != (2000 * USEC_PER_SEC)) | ||
633 | timeout = 0; | 634 | timeout = 0; |
634 | else | 635 | else |
635 | timeout = 100; | 636 | timeout = 100; |
@@ -1065,17 +1066,20 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | |||
1065 | } | 1066 | } |
1066 | 1067 | ||
1067 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | 1068 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
1068 | struct ieee80211_hdr *hdr) | 1069 | struct ieee80211_hdr *hdr, bool ack) |
1069 | { | 1070 | { |
1070 | if (!ieee80211_is_data(hdr->frame_control) && | 1071 | if (!ieee80211_is_data(hdr->frame_control)) |
1071 | !ieee80211_is_nullfunc(hdr->frame_control)) | ||
1072 | return; | 1072 | return; |
1073 | 1073 | ||
1074 | ieee80211_sta_reset_conn_monitor(sdata); | 1074 | if (ack) |
1075 | ieee80211_sta_reset_conn_monitor(sdata); | ||
1075 | 1076 | ||
1076 | if (ieee80211_is_nullfunc(hdr->frame_control) && | 1077 | if (ieee80211_is_nullfunc(hdr->frame_control) && |
1077 | sdata->u.mgd.probe_send_count > 0) { | 1078 | sdata->u.mgd.probe_send_count > 0) { |
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; | ||
1079 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 1083 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
1080 | } | 1084 | } |
1081 | } | 1085 | } |
@@ -1102,9 +1106,10 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1102 | * anymore. The timeout will be reset if the frame is ACKed by | 1106 | * anymore. The timeout will be reset if the frame is ACKed by |
1103 | * the AP. | 1107 | * the AP. |
1104 | */ | 1108 | */ |
1105 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 1109 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { |
1110 | ifmgd->nullfunc_failed = false; | ||
1106 | ieee80211_send_nullfunc(sdata->local, sdata, 0); | 1111 | ieee80211_send_nullfunc(sdata->local, sdata, 0); |
1107 | else { | 1112 | } else { |
1108 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1113 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1109 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); | 1114 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); |
1110 | } | 1115 | } |
@@ -1913,6 +1918,31 @@ static void ieee80211_sta_timer(unsigned long data) | |||
1913 | ieee80211_queue_work(&local->hw, &sdata->work); | 1918 | ieee80211_queue_work(&local->hw, &sdata->work); |
1914 | } | 1919 | } |
1915 | 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 | |||
1916 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | 1946 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
1917 | { | 1947 | { |
1918 | struct ieee80211_local *local = sdata->local; | 1948 | struct ieee80211_local *local = sdata->local; |
@@ -1937,11 +1967,37 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1937 | /* ACK received for nullfunc probing frame */ | 1967 | /* ACK received for nullfunc probing frame */ |
1938 | if (!ifmgd->probe_send_count) | 1968 | if (!ifmgd->probe_send_count) |
1939 | ieee80211_reset_ap_probe(sdata); | 1969 | ieee80211_reset_ap_probe(sdata); |
1940 | 1970 | else if (ifmgd->nullfunc_failed) { | |
1941 | else if (time_is_after_jiffies(ifmgd->probe_timeout)) | 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)) | ||
1942 | run_again(ifmgd, ifmgd->probe_timeout); | 1990 | run_again(ifmgd, ifmgd->probe_timeout); |
1943 | 1991 | else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | |
1944 | else if (ifmgd->probe_send_count < max_tries) { | 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) { | ||
1945 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2001 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1946 | wiphy_debug(local->hw.wiphy, | 2002 | wiphy_debug(local->hw.wiphy, |
1947 | "%s: No probe response from AP %pM" | 2003 | "%s: No probe response from AP %pM" |
@@ -1956,27 +2012,13 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1956 | * We actually lost the connection ... or did we? | 2012 | * We actually lost the connection ... or did we? |
1957 | * Let's make sure! | 2013 | * Let's make sure! |
1958 | */ | 2014 | */ |
1959 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1960 | IEEE80211_STA_BEACON_POLL); | ||
1961 | wiphy_debug(local->hw.wiphy, | 2015 | wiphy_debug(local->hw.wiphy, |
1962 | "%s: No probe response from AP %pM" | 2016 | "%s: No probe response from AP %pM" |
1963 | " after %dms, disconnecting.\n", | 2017 | " after %dms, disconnecting.\n", |
1964 | sdata->name, | 2018 | sdata->name, |
1965 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2019 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1966 | ieee80211_set_disassoc(sdata, true, true); | 2020 | |
1967 | mutex_unlock(&ifmgd->mtx); | 2021 | ieee80211_sta_connection_lost(sdata, bssid); |
1968 | mutex_lock(&local->mtx); | ||
1969 | ieee80211_recalc_idle(local); | ||
1970 | mutex_unlock(&local->mtx); | ||
1971 | /* | ||
1972 | * must be outside lock due to cfg80211, | ||
1973 | * but that's not a problem. | ||
1974 | */ | ||
1975 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
1976 | IEEE80211_STYPE_DEAUTH, | ||
1977 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
1978 | NULL, true); | ||
1979 | mutex_lock(&ifmgd->mtx); | ||
1980 | } | 2022 | } |
1981 | } | 2023 | } |
1982 | 2024 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6289525c0998..2fe8f5f86499 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1163,6 +1163,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1163 | sta->rx_fragments++; | 1163 | sta->rx_fragments++; |
1164 | sta->rx_bytes += rx->skb->len; | 1164 | sta->rx_bytes += rx->skb->len; |
1165 | sta->last_signal = status->signal; | 1165 | sta->last_signal = status->signal; |
1166 | ewma_add(&sta->avg_signal, -status->signal); | ||
1166 | 1167 | ||
1167 | /* | 1168 | /* |
1168 | * Change STA power saving mode only at the end of a frame | 1169 | * Change STA power saving mode only at the end of a frame |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index eff58571fd7e..c426504ed1cf 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -244,6 +244,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
244 | sta->local = local; | 244 | sta->local = local; |
245 | sta->sdata = sdata; | 245 | sta->sdata = sdata; |
246 | 246 | ||
247 | ewma_init(&sta->avg_signal, 1024, 8); | ||
248 | |||
247 | if (sta_prepare_rate_control(local, sta, gfp)) { | 249 | if (sta_prepare_rate_control(local, sta, gfp)) { |
248 | kfree(sta); | 250 | kfree(sta); |
249 | return NULL; | 251 | return NULL; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 05f11302443b..fdca52cf88de 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 | /** |
@@ -223,6 +224,7 @@ enum plink_state { | |||
223 | * @rx_fragments: number of received MPDUs | 224 | * @rx_fragments: number of received MPDUs |
224 | * @rx_dropped: number of dropped MPDUs from this STA | 225 | * @rx_dropped: number of dropped MPDUs from this STA |
225 | * @last_signal: signal of last received frame from this STA | 226 | * @last_signal: signal of last received frame from this STA |
227 | * @avg_signal: moving average of signal of received frames from this STA | ||
226 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | 228 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) |
227 | * @tx_filtered_count: number of frames the hardware filtered for this STA | 229 | * @tx_filtered_count: number of frames the hardware filtered for this STA |
228 | * @tx_retry_failed: number of frames that failed retry | 230 | * @tx_retry_failed: number of frames that failed retry |
@@ -291,6 +293,7 @@ struct sta_info { | |||
291 | unsigned long rx_fragments; | 293 | unsigned long rx_fragments; |
292 | unsigned long rx_dropped; | 294 | unsigned long rx_dropped; |
293 | int last_signal; | 295 | int last_signal; |
296 | struct ewma avg_signal; | ||
294 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 297 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
295 | 298 | ||
296 | /* Updated from TX status path only, no locking requirements */ | 299 | /* Updated from TX status path only, no locking requirements */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 4958710a7d92..38a797217a91 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -155,10 +155,6 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | |||
155 | 155 | ||
156 | ieee80211_queue_work(&local->hw, &local->recalc_smps); | 156 | ieee80211_queue_work(&local->hw, &local->recalc_smps); |
157 | } | 157 | } |
158 | |||
159 | if ((sdata->vif.type == NL80211_IFTYPE_STATION) && | ||
160 | (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) | ||
161 | ieee80211_sta_tx_notify(sdata, (void *) skb->data); | ||
162 | } | 158 | } |
163 | 159 | ||
164 | /* | 160 | /* |
@@ -186,6 +182,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
186 | int retry_count = -1, i; | 182 | int retry_count = -1, i; |
187 | int rates_idx = -1; | 183 | int rates_idx = -1; |
188 | bool send_to_cooked; | 184 | bool send_to_cooked; |
185 | bool acked; | ||
189 | 186 | ||
190 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 187 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
191 | /* the HW cannot have attempted that rate */ | 188 | /* the HW cannot have attempted that rate */ |
@@ -211,8 +208,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
211 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | 208 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) |
212 | continue; | 209 | continue; |
213 | 210 | ||
214 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 211 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); |
215 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | 212 | if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { |
216 | /* | 213 | /* |
217 | * The STA is in power save mode, so assume | 214 | * The STA is in power save mode, so assume |
218 | * that this TX packet failed because of that. | 215 | * that this TX packet failed because of that. |
@@ -244,7 +241,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
244 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
245 | return; | 242 | return; |
246 | } else { | 243 | } else { |
247 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) | 244 | if (!acked) |
248 | sta->tx_retry_failed++; | 245 | sta->tx_retry_failed++; |
249 | sta->tx_retry_count += retry_count; | 246 | sta->tx_retry_count += retry_count; |
250 | } | 247 | } |
@@ -253,10 +250,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
253 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 250 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
254 | ieee80211s_update_metric(local, sta, skb); | 251 | ieee80211s_update_metric(local, sta, skb); |
255 | 252 | ||
256 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && | 253 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked) |
257 | (info->flags & IEEE80211_TX_STAT_ACK)) | ||
258 | ieee80211_frame_acked(sta, skb); | 254 | ieee80211_frame_acked(sta, skb); |
259 | 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) { | 260 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { |
261 | if (info->flags & IEEE80211_TX_STAT_ACK) { | 261 | if (info->flags & IEEE80211_TX_STAT_ACK) { |
262 | if (sta->lost_packets) | 262 | if (sta->lost_packets) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 2ba742656825..0ee56bb0ea7e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -666,10 +666,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
666 | if (unlikely(info->control.rates[0].idx < 0)) | 666 | if (unlikely(info->control.rates[0].idx < 0)) |
667 | return TX_DROP; | 667 | return TX_DROP; |
668 | 668 | ||
669 | if (txrc.reported_rate.idx < 0) | 669 | if (txrc.reported_rate.idx < 0) { |
670 | txrc.reported_rate = info->control.rates[0]; | 670 | txrc.reported_rate = info->control.rates[0]; |
671 | 671 | if (tx->sta && ieee80211_is_data(hdr->frame_control)) | |
672 | if (tx->sta) | 672 | tx->sta->last_tx_rate = txrc.reported_rate; |
673 | } else if (tx->sta) | ||
673 | tx->sta->last_tx_rate = txrc.reported_rate; | 674 | tx->sta->last_tx_rate = txrc.reported_rate; |
674 | 675 | ||
675 | if (unlikely(!info->control.rates[0].count)) | 676 | if (unlikely(!info->control.rates[0].count)) |
@@ -1745,15 +1746,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1745 | int nh_pos, h_pos; | 1746 | int nh_pos, h_pos; |
1746 | struct sta_info *sta = NULL; | 1747 | struct sta_info *sta = NULL; |
1747 | u32 sta_flags = 0; | 1748 | u32 sta_flags = 0; |
1749 | struct sk_buff *tmp_skb; | ||
1748 | 1750 | ||
1749 | if (unlikely(skb->len < ETH_HLEN)) { | 1751 | if (unlikely(skb->len < ETH_HLEN)) { |
1750 | ret = NETDEV_TX_OK; | 1752 | ret = NETDEV_TX_OK; |
1751 | goto fail; | 1753 | goto fail; |
1752 | } | 1754 | } |
1753 | 1755 | ||
1754 | nh_pos = skb_network_header(skb) - skb->data; | ||
1755 | h_pos = skb_transport_header(skb) - skb->data; | ||
1756 | |||
1757 | /* convert Ethernet header to proper 802.11 header (based on | 1756 | /* convert Ethernet header to proper 802.11 header (based on |
1758 | * operation mode) */ | 1757 | * operation mode) */ |
1759 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1758 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
@@ -1926,6 +1925,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1926 | goto fail; | 1925 | goto fail; |
1927 | } | 1926 | } |
1928 | 1927 | ||
1928 | /* | ||
1929 | * If the skb is shared we need to obtain our own copy. | ||
1930 | */ | ||
1931 | if (skb_shared(skb)) { | ||
1932 | tmp_skb = skb; | ||
1933 | skb = skb_copy(skb, GFP_ATOMIC); | ||
1934 | kfree_skb(tmp_skb); | ||
1935 | |||
1936 | if (!skb) { | ||
1937 | ret = NETDEV_TX_OK; | ||
1938 | goto fail; | ||
1939 | } | ||
1940 | } | ||
1941 | |||
1929 | hdr.frame_control = fc; | 1942 | hdr.frame_control = fc; |
1930 | hdr.duration_id = 0; | 1943 | hdr.duration_id = 0; |
1931 | hdr.seq_ctrl = 0; | 1944 | hdr.seq_ctrl = 0; |
@@ -1944,6 +1957,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1944 | encaps_len = 0; | 1957 | encaps_len = 0; |
1945 | } | 1958 | } |
1946 | 1959 | ||
1960 | nh_pos = skb_network_header(skb) - skb->data; | ||
1961 | h_pos = skb_transport_header(skb) - skb->data; | ||
1962 | |||
1947 | skb_pull(skb, skip_header_bytes); | 1963 | skb_pull(skb, skip_header_bytes); |
1948 | nh_pos -= skip_header_bytes; | 1964 | nh_pos -= skip_header_bytes; |
1949 | h_pos -= skip_header_bytes; | 1965 | h_pos -= skip_header_bytes; |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 2b5c3f267198..de43753076d2 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 |