aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-12-13 15:20:45 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-13 15:20:45 -0500
commit1d212aa96e1b63459486f729af9a3fa38768b801 (patch)
treee91e74db57a5bb7884b4681cdb788d405ec8f10f /net
parent8c4877a4128e7931077b024a891a4b284d8756a3 (diff)
parentb7613370db5ba66ad81e41cd3a5417fde4d5e03c (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/Kconfig1
-rw-r--r--net/mac80211/cfg.c70
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/ieee80211_i.h16
-rw-r--r--net/mac80211/iface.c30
-rw-r--r--net/mac80211/main.c5
-rw-r--r--net/mac80211/mesh.c36
-rw-r--r--net/mac80211/mesh.h23
-rw-r--r--net/mac80211/mesh_hwmp.c9
-rw-r--r--net/mac80211/mesh_pathtbl.c7
-rw-r--r--net/mac80211/mlme.c104
-rw-r--r--net/mac80211/rx.c1
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/sta_info.h3
-rw-r--r--net/mac80211/status.c18
-rw-r--r--net/mac80211/tx.c28
-rw-r--r--net/mac80211/work.c5
-rw-r--r--net/wireless/Makefile2
-rw-r--r--net/wireless/core.c15
-rw-r--r--net/wireless/core.h13
-rw-r--r--net/wireless/mesh.c140
-rw-r--r--net/wireless/nl80211.c212
-rw-r--r--net/wireless/util.c1
23 files changed, 537 insertions, 206 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
22static int ieee80211_add_iface(struct wiphy *wiphy, char *name, 22static 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
40static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev) 44static 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
1002static int ieee80211_set_mesh_params(struct wiphy *wiphy, 1002static 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
1055static 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
1071static 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
1055static int ieee80211_change_bss(struct wiphy *wiphy, 1081static 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,
251IEEE80211_IF_FILE(dot11MeshHoldingTimeout, 251IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
252 u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC); 252 u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
253IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC); 253IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
254IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC);
254IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC); 255IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
255IEEE80211_IF_FILE(dot11MeshMaxPeerLinks, 256IEEE80211_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
611static inline void
612ieee80211_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
624enum sdata_queue_type { 612enum 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,
1271void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1259void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1272 struct ieee80211_hdr *hdr); 1260 struct ieee80211_hdr *hdr);
1273void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, 1261void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1274 struct ieee80211_hdr *hdr); 1262 struct ieee80211_hdr *hdr, bool ack);
1275void ieee80211_beacon_connection_loss_work(struct work_struct *work); 1263void ieee80211_beacon_connection_loss_work(struct work_struct *work);
1276 1264
1277void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 1265void 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
525void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) 530void 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
539static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, 555static 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
1067void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, 1068void 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
1921static 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
1916void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) 1946void 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
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index e77e508126fa..55a28ab21db9 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
10obj-$(CONFIG_WEXT_PRIV) += wext-priv.o 10obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
11 11
12cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o 12cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
13cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o 13cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o
14cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o 14cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
15cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o 15cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
16cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o 16cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 630bcf0a2f04..79772fcc37bc 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -332,6 +332,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
332 WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf); 332 WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf);
333 WARN_ON(ops->add_station && !ops->del_station); 333 WARN_ON(ops->add_station && !ops->del_station);
334 WARN_ON(ops->add_mpath && !ops->del_mpath); 334 WARN_ON(ops->add_mpath && !ops->del_mpath);
335 WARN_ON(ops->join_mesh && !ops->leave_mesh);
335 336
336 alloc_size = sizeof(*rdev) + sizeof_priv; 337 alloc_size = sizeof(*rdev) + sizeof_priv;
337 338
@@ -752,6 +753,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
752 cfg80211_mlme_down(rdev, dev); 753 cfg80211_mlme_down(rdev, dev);
753 wdev_unlock(wdev); 754 wdev_unlock(wdev);
754 break; 755 break;
756 case NL80211_IFTYPE_MESH_POINT:
757 cfg80211_leave_mesh(rdev, dev);
758 break;
755 default: 759 default:
756 break; 760 break;
757 } 761 }
@@ -775,20 +779,27 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
775 } 779 }
776 cfg80211_lock_rdev(rdev); 780 cfg80211_lock_rdev(rdev);
777 mutex_lock(&rdev->devlist_mtx); 781 mutex_lock(&rdev->devlist_mtx);
778#ifdef CONFIG_CFG80211_WEXT
779 wdev_lock(wdev); 782 wdev_lock(wdev);
780 switch (wdev->iftype) { 783 switch (wdev->iftype) {
784#ifdef CONFIG_CFG80211_WEXT
781 case NL80211_IFTYPE_ADHOC: 785 case NL80211_IFTYPE_ADHOC:
782 cfg80211_ibss_wext_join(rdev, wdev); 786 cfg80211_ibss_wext_join(rdev, wdev);
783 break; 787 break;
784 case NL80211_IFTYPE_STATION: 788 case NL80211_IFTYPE_STATION:
785 cfg80211_mgd_wext_connect(rdev, wdev); 789 cfg80211_mgd_wext_connect(rdev, wdev);
786 break; 790 break;
791#endif
792 case NL80211_IFTYPE_MESH_POINT:
793 /* backward compat code ... */
794 if (wdev->mesh_id_up_len)
795 __cfg80211_join_mesh(rdev, dev, wdev->ssid,
796 wdev->mesh_id_up_len,
797 &default_mesh_config);
798 break;
787 default: 799 default:
788 break; 800 break;
789 } 801 }
790 wdev_unlock(wdev); 802 wdev_unlock(wdev);
791#endif
792 rdev->opencount++; 803 rdev->opencount++;
793 mutex_unlock(&rdev->devlist_mtx); 804 mutex_unlock(&rdev->devlist_mtx);
794 cfg80211_unlock_rdev(rdev); 805 cfg80211_unlock_rdev(rdev);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index ee80ad8dc655..743203bb61ac 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -285,6 +285,19 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
285int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 285int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
286 struct wireless_dev *wdev); 286 struct wireless_dev *wdev);
287 287
288/* mesh */
289extern const struct mesh_config default_mesh_config;
290int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
291 struct net_device *dev,
292 const u8 *mesh_id, u8 mesh_id_len,
293 const struct mesh_config *conf);
294int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
295 struct net_device *dev,
296 const u8 *mesh_id, u8 mesh_id_len,
297 const struct mesh_config *conf);
298int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
299 struct net_device *dev);
300
288/* MLME */ 301/* MLME */
289int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 302int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
290 struct net_device *dev, 303 struct net_device *dev,
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
new file mode 100644
index 000000000000..e0b9747fe50a
--- /dev/null
+++ b/net/wireless/mesh.c
@@ -0,0 +1,140 @@
1#include <linux/ieee80211.h>
2#include <net/cfg80211.h>
3#include "core.h"
4
5/* Default values, timeouts in ms */
6#define MESH_TTL 31
7#define MESH_DEFAULT_ELEMENT_TTL 31
8#define MESH_MAX_RETR 3
9#define MESH_RET_T 100
10#define MESH_CONF_T 100
11#define MESH_HOLD_T 100
12
13#define MESH_PATH_TIMEOUT 5000
14
15/*
16 * Minimum interval between two consecutive PREQs originated by the same
17 * interface
18 */
19#define MESH_PREQ_MIN_INT 10
20#define MESH_DIAM_TRAVERSAL_TIME 50
21
22/*
23 * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
24 * before timing out. This way it will remain ACTIVE and no data frames
25 * will be unnecessarily held in the pending queue.
26 */
27#define MESH_PATH_REFRESH_TIME 1000
28#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
29
30/* Default maximum number of established plinks per interface */
31#define MESH_MAX_ESTAB_PLINKS 32
32
33#define MESH_MAX_PREQ_RETRIES 4
34
35
36const struct mesh_config default_mesh_config = {
37 .dot11MeshRetryTimeout = MESH_RET_T,
38 .dot11MeshConfirmTimeout = MESH_CONF_T,
39 .dot11MeshHoldingTimeout = MESH_HOLD_T,
40 .dot11MeshMaxRetries = MESH_MAX_RETR,
41 .dot11MeshTTL = MESH_TTL,
42 .element_ttl = MESH_DEFAULT_ELEMENT_TTL,
43 .auto_open_plinks = true,
44 .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS,
45 .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT,
46 .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT,
47 .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME,
48 .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
49 .path_refresh_time = MESH_PATH_REFRESH_TIME,
50 .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
51};
52
53
54int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
55 struct net_device *dev,
56 const u8 *mesh_id, u8 mesh_id_len,
57 const struct mesh_config *conf)
58{
59 struct wireless_dev *wdev = dev->ieee80211_ptr;
60 struct mesh_setup setup = {
61 .mesh_id = mesh_id,
62 .mesh_id_len = mesh_id_len,
63 };
64 int err;
65
66 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
67
68 ASSERT_WDEV_LOCK(wdev);
69
70 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
71 return -EOPNOTSUPP;
72
73 if (wdev->mesh_id_len)
74 return -EALREADY;
75
76 if (!mesh_id_len)
77 return -EINVAL;
78
79 if (!rdev->ops->join_mesh)
80 return -EOPNOTSUPP;
81
82 err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, &setup);
83 if (!err) {
84 memcpy(wdev->ssid, mesh_id, mesh_id_len);
85 wdev->mesh_id_len = mesh_id_len;
86 }
87
88 return err;
89}
90
91int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
92 struct net_device *dev,
93 const u8 *mesh_id, u8 mesh_id_len,
94 const struct mesh_config *conf)
95{
96 struct wireless_dev *wdev = dev->ieee80211_ptr;
97 int err;
98
99 wdev_lock(wdev);
100 err = __cfg80211_join_mesh(rdev, dev, mesh_id, mesh_id_len, conf);
101 wdev_unlock(wdev);
102
103 return err;
104}
105
106static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
107 struct net_device *dev)
108{
109 struct wireless_dev *wdev = dev->ieee80211_ptr;
110 int err;
111
112 ASSERT_WDEV_LOCK(wdev);
113
114 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
115 return -EOPNOTSUPP;
116
117 if (!rdev->ops->leave_mesh)
118 return -EOPNOTSUPP;
119
120 if (!wdev->mesh_id_len)
121 return -ENOTCONN;
122
123 err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
124 if (!err)
125 wdev->mesh_id_len = 0;
126 return err;
127}
128
129int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
130 struct net_device *dev)
131{
132 struct wireless_dev *wdev = dev->ieee80211_ptr;
133 int err;
134
135 wdev_lock(wdev);
136 err = __cfg80211_leave_mesh(rdev, dev);
137 wdev_unlock(wdev);
138
139 return err;
140}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 960be4e650f0..c3f80e565365 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -121,6 +121,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
121 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, 121 [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
122 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY, 122 [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
123 .len = NL80211_MAX_SUPP_RATES }, 123 .len = NL80211_MAX_SUPP_RATES },
124 [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
124 125
125 [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, 126 [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED },
126 127
@@ -661,13 +662,14 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
661 CMD(add_beacon, NEW_BEACON); 662 CMD(add_beacon, NEW_BEACON);
662 CMD(add_station, NEW_STATION); 663 CMD(add_station, NEW_STATION);
663 CMD(add_mpath, NEW_MPATH); 664 CMD(add_mpath, NEW_MPATH);
664 CMD(set_mesh_params, SET_MESH_PARAMS); 665 CMD(update_mesh_params, SET_MESH_PARAMS);
665 CMD(change_bss, SET_BSS); 666 CMD(change_bss, SET_BSS);
666 CMD(auth, AUTHENTICATE); 667 CMD(auth, AUTHENTICATE);
667 CMD(assoc, ASSOCIATE); 668 CMD(assoc, ASSOCIATE);
668 CMD(deauth, DEAUTHENTICATE); 669 CMD(deauth, DEAUTHENTICATE);
669 CMD(disassoc, DISASSOCIATE); 670 CMD(disassoc, DISASSOCIATE);
670 CMD(join_ibss, JOIN_IBSS); 671 CMD(join_ibss, JOIN_IBSS);
672 CMD(join_mesh, JOIN_MESH);
671 CMD(set_pmksa, SET_PMKSA); 673 CMD(set_pmksa, SET_PMKSA);
672 CMD(del_pmksa, DEL_PMKSA); 674 CMD(del_pmksa, DEL_PMKSA);
673 CMD(flush_pmksa, FLUSH_PMKSA); 675 CMD(flush_pmksa, FLUSH_PMKSA);
@@ -1324,11 +1326,21 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1324 } 1326 }
1325 1327
1326 if (info->attrs[NL80211_ATTR_MESH_ID]) { 1328 if (info->attrs[NL80211_ATTR_MESH_ID]) {
1329 struct wireless_dev *wdev = dev->ieee80211_ptr;
1330
1327 if (ntype != NL80211_IFTYPE_MESH_POINT) 1331 if (ntype != NL80211_IFTYPE_MESH_POINT)
1328 return -EINVAL; 1332 return -EINVAL;
1329 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); 1333 if (netif_running(dev))
1330 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 1334 return -EBUSY;
1331 change = true; 1335
1336 wdev_lock(wdev);
1337 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
1338 IEEE80211_MAX_MESH_ID_LEN);
1339 wdev->mesh_id_up_len =
1340 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1341 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
1342 wdev->mesh_id_up_len);
1343 wdev_unlock(wdev);
1332 } 1344 }
1333 1345
1334 if (info->attrs[NL80211_ATTR_4ADDR]) { 1346 if (info->attrs[NL80211_ATTR_4ADDR]) {
@@ -1368,6 +1380,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1368{ 1380{
1369 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 1381 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1370 struct vif_params params; 1382 struct vif_params params;
1383 struct net_device *dev;
1371 int err; 1384 int err;
1372 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; 1385 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
1373 u32 flags; 1386 u32 flags;
@@ -1387,12 +1400,6 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1387 !(rdev->wiphy.interface_modes & (1 << type))) 1400 !(rdev->wiphy.interface_modes & (1 << type)))
1388 return -EOPNOTSUPP; 1401 return -EOPNOTSUPP;
1389 1402
1390 if (type == NL80211_IFTYPE_MESH_POINT &&
1391 info->attrs[NL80211_ATTR_MESH_ID]) {
1392 params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
1393 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1394 }
1395
1396 if (info->attrs[NL80211_ATTR_4ADDR]) { 1403 if (info->attrs[NL80211_ATTR_4ADDR]) {
1397 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1404 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1398 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); 1405 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
@@ -1403,11 +1410,27 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1403 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1410 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
1404 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 1411 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
1405 &flags); 1412 &flags);
1406 err = rdev->ops->add_virtual_intf(&rdev->wiphy, 1413 dev = rdev->ops->add_virtual_intf(&rdev->wiphy,
1407 nla_data(info->attrs[NL80211_ATTR_IFNAME]), 1414 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
1408 type, err ? NULL : &flags, &params); 1415 type, err ? NULL : &flags, &params);
1416 if (IS_ERR(dev))
1417 return PTR_ERR(dev);
1409 1418
1410 return err; 1419 if (type == NL80211_IFTYPE_MESH_POINT &&
1420 info->attrs[NL80211_ATTR_MESH_ID]) {
1421 struct wireless_dev *wdev = dev->ieee80211_ptr;
1422
1423 wdev_lock(wdev);
1424 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
1425 IEEE80211_MAX_MESH_ID_LEN);
1426 wdev->mesh_id_up_len =
1427 nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1428 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
1429 wdev->mesh_id_up_len);
1430 wdev_unlock(wdev);
1431 }
1432
1433 return 0;
1411} 1434}
1412 1435
1413static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) 1436static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
@@ -1874,6 +1897,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1874 if (sinfo->filled & STATION_INFO_SIGNAL) 1897 if (sinfo->filled & STATION_INFO_SIGNAL)
1875 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, 1898 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
1876 sinfo->signal); 1899 sinfo->signal);
1900 if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
1901 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
1902 sinfo->signal_avg);
1877 if (sinfo->filled & STATION_INFO_TX_BITRATE) { 1903 if (sinfo->filled & STATION_INFO_TX_BITRATE) {
1878 txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); 1904 txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
1879 if (!txrate) 1905 if (!txrate)
@@ -2437,6 +2463,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
2437 params.use_short_preamble = -1; 2463 params.use_short_preamble = -1;
2438 params.use_short_slot_time = -1; 2464 params.use_short_slot_time = -1;
2439 params.ap_isolate = -1; 2465 params.ap_isolate = -1;
2466 params.ht_opmode = -1;
2440 2467
2441 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) 2468 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
2442 params.use_cts_prot = 2469 params.use_cts_prot =
@@ -2455,6 +2482,9 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
2455 } 2482 }
2456 if (info->attrs[NL80211_ATTR_AP_ISOLATE]) 2483 if (info->attrs[NL80211_ATTR_AP_ISOLATE])
2457 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); 2484 params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
2485 if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
2486 params.ht_opmode =
2487 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
2458 2488
2459 if (!rdev->ops->change_bss) 2489 if (!rdev->ops->change_bss)
2460 return -EOPNOTSUPP; 2490 return -EOPNOTSUPP;
@@ -2540,21 +2570,32 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
2540} 2570}
2541 2571
2542static int nl80211_get_mesh_params(struct sk_buff *skb, 2572static int nl80211_get_mesh_params(struct sk_buff *skb,
2543 struct genl_info *info) 2573 struct genl_info *info)
2544{ 2574{
2545 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 2575 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2546 struct mesh_config cur_params;
2547 int err;
2548 struct net_device *dev = info->user_ptr[1]; 2576 struct net_device *dev = info->user_ptr[1];
2577 struct wireless_dev *wdev = dev->ieee80211_ptr;
2578 struct mesh_config cur_params;
2579 int err = 0;
2549 void *hdr; 2580 void *hdr;
2550 struct nlattr *pinfoattr; 2581 struct nlattr *pinfoattr;
2551 struct sk_buff *msg; 2582 struct sk_buff *msg;
2552 2583
2584 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
2585 return -EOPNOTSUPP;
2586
2553 if (!rdev->ops->get_mesh_params) 2587 if (!rdev->ops->get_mesh_params)
2554 return -EOPNOTSUPP; 2588 return -EOPNOTSUPP;
2555 2589
2556 /* Get the mesh params */ 2590 wdev_lock(wdev);
2557 err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params); 2591 /* If not connected, get default parameters */
2592 if (!wdev->mesh_id_len)
2593 memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
2594 else
2595 err = rdev->ops->get_mesh_params(&rdev->wiphy, dev,
2596 &cur_params);
2597 wdev_unlock(wdev);
2598
2558 if (err) 2599 if (err)
2559 return err; 2600 return err;
2560 2601
@@ -2582,6 +2623,8 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2582 cur_params.dot11MeshMaxRetries); 2623 cur_params.dot11MeshMaxRetries);
2583 NLA_PUT_U8(msg, NL80211_MESHCONF_TTL, 2624 NLA_PUT_U8(msg, NL80211_MESHCONF_TTL,
2584 cur_params.dot11MeshTTL); 2625 cur_params.dot11MeshTTL);
2626 NLA_PUT_U8(msg, NL80211_MESHCONF_ELEMENT_TTL,
2627 cur_params.element_ttl);
2585 NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 2628 NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
2586 cur_params.auto_open_plinks); 2629 cur_params.auto_open_plinks);
2587 NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, 2630 NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
@@ -2608,14 +2651,6 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2608 return -ENOBUFS; 2651 return -ENOBUFS;
2609} 2652}
2610 2653
2611#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
2612do {\
2613 if (table[attr_num]) {\
2614 cfg.param = nla_fn(table[attr_num]); \
2615 mask |= (1 << (attr_num - 1)); \
2616 } \
2617} while (0);\
2618
2619static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = { 2654static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
2620 [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, 2655 [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
2621 [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 }, 2656 [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
@@ -2623,6 +2658,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
2623 [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 }, 2658 [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
2624 [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 }, 2659 [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
2625 [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, 2660 [NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
2661 [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 },
2626 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, 2662 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
2627 2663
2628 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, 2664 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
@@ -2633,31 +2669,34 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
2633 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, 2669 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
2634}; 2670};
2635 2671
2636static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) 2672static int nl80211_parse_mesh_params(struct genl_info *info,
2673 struct mesh_config *cfg,
2674 u32 *mask_out)
2637{ 2675{
2638 u32 mask;
2639 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2640 struct net_device *dev = info->user_ptr[1];
2641 struct mesh_config cfg;
2642 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; 2676 struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
2643 struct nlattr *parent_attr; 2677 u32 mask = 0;
2678
2679#define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
2680do {\
2681 if (table[attr_num]) {\
2682 cfg->param = nla_fn(table[attr_num]); \
2683 mask |= (1 << (attr_num - 1)); \
2684 } \
2685} while (0);\
2686
2644 2687
2645 parent_attr = info->attrs[NL80211_ATTR_MESH_PARAMS]; 2688 if (!info->attrs[NL80211_ATTR_MESH_PARAMS])
2646 if (!parent_attr)
2647 return -EINVAL; 2689 return -EINVAL;
2648 if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, 2690 if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
2649 parent_attr, nl80211_meshconf_params_policy)) 2691 info->attrs[NL80211_ATTR_MESH_PARAMS],
2692 nl80211_meshconf_params_policy))
2650 return -EINVAL; 2693 return -EINVAL;
2651 2694
2652 if (!rdev->ops->set_mesh_params)
2653 return -EOPNOTSUPP;
2654
2655 /* This makes sure that there aren't more than 32 mesh config 2695 /* This makes sure that there aren't more than 32 mesh config
2656 * parameters (otherwise our bitfield scheme would not work.) */ 2696 * parameters (otherwise our bitfield scheme would not work.) */
2657 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); 2697 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
2658 2698
2659 /* Fill in the params struct */ 2699 /* Fill in the params struct */
2660 mask = 0;
2661 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 2700 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout,
2662 mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16); 2701 mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
2663 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 2702 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout,
@@ -2670,6 +2709,8 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2670 mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8); 2709 mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
2671 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 2710 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL,
2672 mask, NL80211_MESHCONF_TTL, nla_get_u8); 2711 mask, NL80211_MESHCONF_TTL, nla_get_u8);
2712 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl,
2713 mask, NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
2673 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 2714 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks,
2674 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); 2715 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8);
2675 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 2716 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries,
@@ -2695,11 +2736,45 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2695 NL80211_MESHCONF_HWMP_ROOTMODE, 2736 NL80211_MESHCONF_HWMP_ROOTMODE,
2696 nla_get_u8); 2737 nla_get_u8);
2697 2738
2698 /* Apply changes */ 2739 if (mask_out)
2699 return rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask); 2740 *mask_out = mask;
2700} 2741 return 0;
2701 2742
2702#undef FILL_IN_MESH_PARAM_IF_SET 2743#undef FILL_IN_MESH_PARAM_IF_SET
2744}
2745
2746static int nl80211_update_mesh_params(struct sk_buff *skb,
2747 struct genl_info *info)
2748{
2749 struct cfg80211_registered_device *rdev = info->user_ptr[0];
2750 struct net_device *dev = info->user_ptr[1];
2751 struct wireless_dev *wdev = dev->ieee80211_ptr;
2752 struct mesh_config cfg;
2753 u32 mask;
2754 int err;
2755
2756 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
2757 return -EOPNOTSUPP;
2758
2759 if (!rdev->ops->update_mesh_params)
2760 return -EOPNOTSUPP;
2761
2762 err = nl80211_parse_mesh_params(info, &cfg, &mask);
2763 if (err)
2764 return err;
2765
2766 wdev_lock(wdev);
2767 if (!wdev->mesh_id_len)
2768 err = -ENOLINK;
2769
2770 if (!err)
2771 err = rdev->ops->update_mesh_params(&rdev->wiphy, dev,
2772 mask, &cfg);
2773
2774 wdev_unlock(wdev);
2775
2776 return err;
2777}
2703 2778
2704static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) 2779static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
2705{ 2780{
@@ -4482,6 +4557,41 @@ out:
4482 return err; 4557 return err;
4483} 4558}
4484 4559
4560static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
4561{
4562 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4563 struct net_device *dev = info->user_ptr[1];
4564 struct mesh_config cfg;
4565 int err;
4566
4567 /* start with default */
4568 memcpy(&cfg, &default_mesh_config, sizeof(cfg));
4569
4570 if (info->attrs[NL80211_ATTR_MESH_PARAMS]) {
4571 /* and parse parameters if given */
4572 err = nl80211_parse_mesh_params(info, &cfg, NULL);
4573 if (err)
4574 return err;
4575 }
4576
4577 if (!info->attrs[NL80211_ATTR_MESH_ID] ||
4578 !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
4579 return -EINVAL;
4580
4581 return cfg80211_join_mesh(rdev, dev,
4582 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
4583 nla_len(info->attrs[NL80211_ATTR_MESH_ID]),
4584 &cfg);
4585}
4586
4587static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
4588{
4589 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4590 struct net_device *dev = info->user_ptr[1];
4591
4592 return cfg80211_leave_mesh(rdev, dev);
4593}
4594
4485#define NL80211_FLAG_NEED_WIPHY 0x01 4595#define NL80211_FLAG_NEED_WIPHY 0x01
4486#define NL80211_FLAG_NEED_NETDEV 0x02 4596#define NL80211_FLAG_NEED_NETDEV 0x02
4487#define NL80211_FLAG_NEED_RTNL 0x04 4597#define NL80211_FLAG_NEED_RTNL 0x04
@@ -4746,10 +4856,10 @@ static struct genl_ops nl80211_ops[] = {
4746 }, 4856 },
4747 { 4857 {
4748 .cmd = NL80211_CMD_SET_MESH_PARAMS, 4858 .cmd = NL80211_CMD_SET_MESH_PARAMS,
4749 .doit = nl80211_set_mesh_params, 4859 .doit = nl80211_update_mesh_params,
4750 .policy = nl80211_policy, 4860 .policy = nl80211_policy,
4751 .flags = GENL_ADMIN_PERM, 4861 .flags = GENL_ADMIN_PERM,
4752 .internal_flags = NL80211_FLAG_NEED_NETDEV | 4862 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
4753 NL80211_FLAG_NEED_RTNL, 4863 NL80211_FLAG_NEED_RTNL,
4754 }, 4864 },
4755 { 4865 {
@@ -4964,6 +5074,22 @@ static struct genl_ops nl80211_ops[] = {
4964 .internal_flags = NL80211_FLAG_NEED_NETDEV | 5074 .internal_flags = NL80211_FLAG_NEED_NETDEV |
4965 NL80211_FLAG_NEED_RTNL, 5075 NL80211_FLAG_NEED_RTNL,
4966 }, 5076 },
5077 {
5078 .cmd = NL80211_CMD_JOIN_MESH,
5079 .doit = nl80211_join_mesh,
5080 .policy = nl80211_policy,
5081 .flags = GENL_ADMIN_PERM,
5082 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5083 NL80211_FLAG_NEED_RTNL,
5084 },
5085 {
5086 .cmd = NL80211_CMD_LEAVE_MESH,
5087 .doit = nl80211_leave_mesh,
5088 .policy = nl80211_policy,
5089 .flags = GENL_ADMIN_PERM,
5090 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
5091 NL80211_FLAG_NEED_RTNL,
5092 },
4967}; 5093};
4968 5094
4969static struct genl_multicast_group nl80211_mlme_mcgrp = { 5095static struct genl_multicast_group nl80211_mlme_mcgrp = {
diff --git a/net/wireless/util.c b/net/wireless/util.c
index fee020b15a4e..4de624ca4c63 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -792,6 +792,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
792 792
793 if (ntype != otype) { 793 if (ntype != otype) {
794 dev->ieee80211_ptr->use_4addr = false; 794 dev->ieee80211_ptr->use_4addr = false;
795 dev->ieee80211_ptr->mesh_id_up_len = 0;
795 796
796 switch (otype) { 797 switch (otype) {
797 case NL80211_IFTYPE_ADHOC: 798 case NL80211_IFTYPE_ADHOC: