diff options
author | David S. Miller <davem@davemloft.net> | 2008-09-25 16:16:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-25 16:16:16 -0400 |
commit | db4148da2cc84c31419b5e3ae3115ac6e11817a1 (patch) | |
tree | 72d7d99cd7a4903e017169e0ae8e2b37027129c6 /net | |
parent | ef40a685311bef053dedd833a72dffaf25669dda (diff) | |
parent | 8d09a5e1c36d0dec5728e6c8b0bb5412de09b27b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 64 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/iface.c | 1 | ||||
-rw-r--r-- | net/mac80211/main.c | 23 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 4 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 127 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 10 | ||||
-rw-r--r-- | net/mac80211/rate.c | 71 | ||||
-rw-r--r-- | net/mac80211/rate.h | 102 | ||||
-rw-r--r-- | net/mac80211/rc80211_pid.h | 2 | ||||
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 158 | ||||
-rw-r--r-- | net/mac80211/rx.c | 59 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 17 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 75 | ||||
-rw-r--r-- | net/wireless/core.c | 162 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 45 | ||||
-rw-r--r-- | net/wireless/reg.c | 311 | ||||
-rw-r--r-- | net/wireless/reg.h | 39 |
21 files changed, 658 insertions, 625 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e2574885db4a..855126a3039d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -82,7 +82,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
82 | enum nl80211_iftype type, u32 *flags, | 82 | enum nl80211_iftype type, u32 *flags, |
83 | struct vif_params *params) | 83 | struct vif_params *params) |
84 | { | 84 | { |
85 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
86 | struct net_device *dev; | 85 | struct net_device *dev; |
87 | struct ieee80211_sub_if_data *sdata; | 86 | struct ieee80211_sub_if_data *sdata; |
88 | int ret; | 87 | int ret; |
@@ -95,15 +94,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
95 | if (!nl80211_type_check(type)) | 94 | if (!nl80211_type_check(type)) |
96 | return -EINVAL; | 95 | return -EINVAL; |
97 | 96 | ||
98 | if (dev == local->mdev) | ||
99 | return -EOPNOTSUPP; | ||
100 | |||
101 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 97 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
102 | 98 | ||
103 | ret = ieee80211_if_change_type(sdata, type); | 99 | ret = ieee80211_if_change_type(sdata, type); |
104 | if (ret) | 100 | if (ret) |
105 | return ret; | 101 | return ret; |
106 | 102 | ||
103 | if (netif_running(sdata->dev)) | ||
104 | return -EBUSY; | ||
105 | |||
107 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 106 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
108 | ieee80211_sdata_set_mesh_id(sdata, | 107 | ieee80211_sdata_set_mesh_id(sdata, |
109 | params->mesh_id_len, | 108 | params->mesh_id_len, |
@@ -120,16 +119,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
120 | u8 key_idx, u8 *mac_addr, | 119 | u8 key_idx, u8 *mac_addr, |
121 | struct key_params *params) | 120 | struct key_params *params) |
122 | { | 121 | { |
123 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
124 | struct ieee80211_sub_if_data *sdata; | 122 | struct ieee80211_sub_if_data *sdata; |
125 | struct sta_info *sta = NULL; | 123 | struct sta_info *sta = NULL; |
126 | enum ieee80211_key_alg alg; | 124 | enum ieee80211_key_alg alg; |
127 | struct ieee80211_key *key; | 125 | struct ieee80211_key *key; |
128 | int err; | 126 | int err; |
129 | 127 | ||
130 | if (dev == local->mdev) | ||
131 | return -EOPNOTSUPP; | ||
132 | |||
133 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 128 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
134 | 129 | ||
135 | switch (params->cipher) { | 130 | switch (params->cipher) { |
@@ -174,14 +169,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
174 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 169 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
175 | u8 key_idx, u8 *mac_addr) | 170 | u8 key_idx, u8 *mac_addr) |
176 | { | 171 | { |
177 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
178 | struct ieee80211_sub_if_data *sdata; | 172 | struct ieee80211_sub_if_data *sdata; |
179 | struct sta_info *sta; | 173 | struct sta_info *sta; |
180 | int ret; | 174 | int ret; |
181 | 175 | ||
182 | if (dev == local->mdev) | ||
183 | return -EOPNOTSUPP; | ||
184 | |||
185 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 176 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
186 | 177 | ||
187 | rcu_read_lock(); | 178 | rcu_read_lock(); |
@@ -222,7 +213,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
222 | void (*callback)(void *cookie, | 213 | void (*callback)(void *cookie, |
223 | struct key_params *params)) | 214 | struct key_params *params)) |
224 | { | 215 | { |
225 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
226 | struct ieee80211_sub_if_data *sdata; | 216 | struct ieee80211_sub_if_data *sdata; |
227 | struct sta_info *sta = NULL; | 217 | struct sta_info *sta = NULL; |
228 | u8 seq[6] = {0}; | 218 | u8 seq[6] = {0}; |
@@ -232,9 +222,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
232 | u16 iv16; | 222 | u16 iv16; |
233 | int err = -ENOENT; | 223 | int err = -ENOENT; |
234 | 224 | ||
235 | if (dev == local->mdev) | ||
236 | return -EOPNOTSUPP; | ||
237 | |||
238 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 225 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
239 | 226 | ||
240 | rcu_read_lock(); | 227 | rcu_read_lock(); |
@@ -310,12 +297,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
310 | struct net_device *dev, | 297 | struct net_device *dev, |
311 | u8 key_idx) | 298 | u8 key_idx) |
312 | { | 299 | { |
313 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
314 | struct ieee80211_sub_if_data *sdata; | 300 | struct ieee80211_sub_if_data *sdata; |
315 | 301 | ||
316 | if (dev == local->mdev) | ||
317 | return -EOPNOTSUPP; | ||
318 | |||
319 | rcu_read_lock(); | 302 | rcu_read_lock(); |
320 | 303 | ||
321 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 304 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -496,13 +479,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
496 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 479 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
497 | struct beacon_parameters *params) | 480 | struct beacon_parameters *params) |
498 | { | 481 | { |
499 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
500 | struct ieee80211_sub_if_data *sdata; | 482 | struct ieee80211_sub_if_data *sdata; |
501 | struct beacon_data *old; | 483 | struct beacon_data *old; |
502 | 484 | ||
503 | if (dev == local->mdev) | ||
504 | return -EOPNOTSUPP; | ||
505 | |||
506 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 485 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
507 | 486 | ||
508 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 487 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -519,13 +498,9 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
519 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | 498 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, |
520 | struct beacon_parameters *params) | 499 | struct beacon_parameters *params) |
521 | { | 500 | { |
522 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
523 | struct ieee80211_sub_if_data *sdata; | 501 | struct ieee80211_sub_if_data *sdata; |
524 | struct beacon_data *old; | 502 | struct beacon_data *old; |
525 | 503 | ||
526 | if (dev == local->mdev) | ||
527 | return -EOPNOTSUPP; | ||
528 | |||
529 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 504 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
530 | 505 | ||
531 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 506 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -541,13 +516,9 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
541 | 516 | ||
542 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | 517 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) |
543 | { | 518 | { |
544 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
545 | struct ieee80211_sub_if_data *sdata; | 519 | struct ieee80211_sub_if_data *sdata; |
546 | struct beacon_data *old; | 520 | struct beacon_data *old; |
547 | 521 | ||
548 | if (dev == local->mdev) | ||
549 | return -EOPNOTSUPP; | ||
550 | |||
551 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 522 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
552 | 523 | ||
553 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 524 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -695,9 +666,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
695 | struct ieee80211_sub_if_data *sdata; | 666 | struct ieee80211_sub_if_data *sdata; |
696 | int err; | 667 | int err; |
697 | 668 | ||
698 | if (dev == local->mdev || params->vlan == local->mdev) | ||
699 | return -EOPNOTSUPP; | ||
700 | |||
701 | /* Prevent a race with changing the rate control algorithm */ | 669 | /* Prevent a race with changing the rate control algorithm */ |
702 | if (!netif_running(dev)) | 670 | if (!netif_running(dev)) |
703 | return -ENETDOWN; | 671 | return -ENETDOWN; |
@@ -725,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
725 | 693 | ||
726 | sta_apply_parameters(local, sta, params); | 694 | sta_apply_parameters(local, sta, params); |
727 | 695 | ||
728 | rate_control_rate_init(sta, local); | 696 | rate_control_rate_init(sta); |
729 | 697 | ||
730 | rcu_read_lock(); | 698 | rcu_read_lock(); |
731 | 699 | ||
@@ -752,9 +720,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
752 | struct ieee80211_sub_if_data *sdata; | 720 | struct ieee80211_sub_if_data *sdata; |
753 | struct sta_info *sta; | 721 | struct sta_info *sta; |
754 | 722 | ||
755 | if (dev == local->mdev) | ||
756 | return -EOPNOTSUPP; | ||
757 | |||
758 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 723 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
759 | 724 | ||
760 | if (mac) { | 725 | if (mac) { |
@@ -786,9 +751,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
786 | struct sta_info *sta; | 751 | struct sta_info *sta; |
787 | struct ieee80211_sub_if_data *vlansdata; | 752 | struct ieee80211_sub_if_data *vlansdata; |
788 | 753 | ||
789 | if (dev == local->mdev || params->vlan == local->mdev) | ||
790 | return -EOPNOTSUPP; | ||
791 | |||
792 | rcu_read_lock(); | 754 | rcu_read_lock(); |
793 | 755 | ||
794 | /* XXX: get sta belonging to dev */ | 756 | /* XXX: get sta belonging to dev */ |
@@ -828,9 +790,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
828 | struct sta_info *sta; | 790 | struct sta_info *sta; |
829 | int err; | 791 | int err; |
830 | 792 | ||
831 | if (dev == local->mdev) | ||
832 | return -EOPNOTSUPP; | ||
833 | |||
834 | if (!netif_running(dev)) | 793 | if (!netif_running(dev)) |
835 | return -ENETDOWN; | 794 | return -ENETDOWN; |
836 | 795 | ||
@@ -884,9 +843,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
884 | struct mesh_path *mpath; | 843 | struct mesh_path *mpath; |
885 | struct sta_info *sta; | 844 | struct sta_info *sta; |
886 | 845 | ||
887 | if (dev == local->mdev) | ||
888 | return -EOPNOTSUPP; | ||
889 | |||
890 | if (!netif_running(dev)) | 846 | if (!netif_running(dev)) |
891 | return -ENETDOWN; | 847 | return -ENETDOWN; |
892 | 848 | ||
@@ -958,13 +914,9 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
958 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) | 914 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) |
959 | 915 | ||
960 | { | 916 | { |
961 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
962 | struct ieee80211_sub_if_data *sdata; | 917 | struct ieee80211_sub_if_data *sdata; |
963 | struct mesh_path *mpath; | 918 | struct mesh_path *mpath; |
964 | 919 | ||
965 | if (dev == local->mdev) | ||
966 | return -EOPNOTSUPP; | ||
967 | |||
968 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 920 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
969 | 921 | ||
970 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 922 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
@@ -986,13 +938,9 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
986 | int idx, u8 *dst, u8 *next_hop, | 938 | int idx, u8 *dst, u8 *next_hop, |
987 | struct mpath_info *pinfo) | 939 | struct mpath_info *pinfo) |
988 | { | 940 | { |
989 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
990 | struct ieee80211_sub_if_data *sdata; | 941 | struct ieee80211_sub_if_data *sdata; |
991 | struct mesh_path *mpath; | 942 | struct mesh_path *mpath; |
992 | 943 | ||
993 | if (dev == local->mdev) | ||
994 | return -EOPNOTSUPP; | ||
995 | |||
996 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 944 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
997 | 945 | ||
998 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 946 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
@@ -1015,13 +963,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1015 | struct net_device *dev, | 963 | struct net_device *dev, |
1016 | struct bss_parameters *params) | 964 | struct bss_parameters *params) |
1017 | { | 965 | { |
1018 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1019 | struct ieee80211_sub_if_data *sdata; | 966 | struct ieee80211_sub_if_data *sdata; |
1020 | u32 changed = 0; | 967 | u32 changed = 0; |
1021 | 968 | ||
1022 | if (dev == local->mdev) | ||
1023 | return -EOPNOTSUPP; | ||
1024 | |||
1025 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 969 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1026 | 970 | ||
1027 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 971 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 81f350eaf8a3..b9902e425f09 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -173,8 +173,7 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
173 | const char __user *user_buf, size_t count, loff_t *ppos) | 173 | const char __user *user_buf, size_t count, loff_t *ppos) |
174 | { | 174 | { |
175 | struct sta_info *sta = file->private_data; | 175 | struct sta_info *sta = file->private_data; |
176 | struct net_device *dev = sta->sdata->dev; | 176 | struct ieee80211_local *local = sta->sdata->local; |
177 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
178 | struct ieee80211_hw *hw = &local->hw; | 177 | struct ieee80211_hw *hw = &local->hw; |
179 | u8 *da = sta->sta.addr; | 178 | u8 *da = sta->sta.addr; |
180 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, | 179 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3912fba6d3d0..8025b294588b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -573,6 +573,10 @@ enum { | |||
573 | /* maximum number of hardware queues we support. */ | 573 | /* maximum number of hardware queues we support. */ |
574 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) | 574 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) |
575 | 575 | ||
576 | struct ieee80211_master_priv { | ||
577 | struct ieee80211_local *local; | ||
578 | }; | ||
579 | |||
576 | struct ieee80211_local { | 580 | struct ieee80211_local { |
577 | /* embed the driver visible part. | 581 | /* embed the driver visible part. |
578 | * don't cast (use the static inlines below), but we keep | 582 | * don't cast (use the static inlines below), but we keep |
@@ -720,6 +724,8 @@ struct ieee80211_local { | |||
720 | 724 | ||
721 | #ifdef CONFIG_MAC80211_DEBUGFS | 725 | #ifdef CONFIG_MAC80211_DEBUGFS |
722 | struct local_debugfsdentries { | 726 | struct local_debugfsdentries { |
727 | struct dentry *rcdir; | ||
728 | struct dentry *rcname; | ||
723 | struct dentry *frequency; | 729 | struct dentry *frequency; |
724 | struct dentry *antenna_sel_tx; | 730 | struct dentry *antenna_sel_tx; |
725 | struct dentry *antenna_sel_rx; | 731 | struct dentry *antenna_sel_rx; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a72fbebb8ea2..b5cd91e89712 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -625,6 +625,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
625 | /* and set some type-dependent values */ | 625 | /* and set some type-dependent values */ |
626 | sdata->vif.type = type; | 626 | sdata->vif.type = type; |
627 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; | 627 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; |
628 | sdata->wdev.iftype = type; | ||
628 | 629 | ||
629 | /* only monitor differs */ | 630 | /* only monitor differs */ |
630 | sdata->dev->type = ARPHRD_ETHER; | 631 | sdata->dev->type = ARPHRD_ETHER; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c307dba7ec03..d608c44047c0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -106,7 +106,8 @@ static const struct header_ops ieee80211_header_ops = { | |||
106 | 106 | ||
107 | static int ieee80211_master_open(struct net_device *dev) | 107 | static int ieee80211_master_open(struct net_device *dev) |
108 | { | 108 | { |
109 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 109 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
110 | struct ieee80211_local *local = mpriv->local; | ||
110 | struct ieee80211_sub_if_data *sdata; | 111 | struct ieee80211_sub_if_data *sdata; |
111 | int res = -EOPNOTSUPP; | 112 | int res = -EOPNOTSUPP; |
112 | 113 | ||
@@ -128,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev) | |||
128 | 129 | ||
129 | static int ieee80211_master_stop(struct net_device *dev) | 130 | static int ieee80211_master_stop(struct net_device *dev) |
130 | { | 131 | { |
131 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 132 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
133 | struct ieee80211_local *local = mpriv->local; | ||
132 | struct ieee80211_sub_if_data *sdata; | 134 | struct ieee80211_sub_if_data *sdata; |
133 | 135 | ||
134 | /* we hold the RTNL here so can safely walk the list */ | 136 | /* we hold the RTNL here so can safely walk the list */ |
@@ -141,7 +143,8 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
141 | 143 | ||
142 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | 144 | static void ieee80211_master_set_multicast_list(struct net_device *dev) |
143 | { | 145 | { |
144 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 146 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
147 | struct ieee80211_local *local = mpriv->local; | ||
145 | 148 | ||
146 | ieee80211_configure_filter(local); | 149 | ieee80211_configure_filter(local); |
147 | } | 150 | } |
@@ -539,6 +542,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
539 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 542 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
540 | u16 frag, type; | 543 | u16 frag, type; |
541 | __le16 fc; | 544 | __le16 fc; |
545 | struct ieee80211_supported_band *sband; | ||
542 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 546 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
543 | struct ieee80211_sub_if_data *sdata; | 547 | struct ieee80211_sub_if_data *sdata; |
544 | struct net_device *prev_dev = NULL; | 548 | struct net_device *prev_dev = NULL; |
@@ -585,7 +589,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
585 | sta->tx_retry_count += info->status.retry_count; | 589 | sta->tx_retry_count += info->status.retry_count; |
586 | } | 590 | } |
587 | 591 | ||
588 | rate_control_tx_status(local->mdev, skb); | 592 | sband = local->hw.wiphy->bands[info->band]; |
593 | rate_control_tx_status(local, sband, sta, skb); | ||
589 | } | 594 | } |
590 | 595 | ||
591 | rcu_read_unlock(); | 596 | rcu_read_unlock(); |
@@ -787,7 +792,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
787 | int result; | 792 | int result; |
788 | enum ieee80211_band band; | 793 | enum ieee80211_band band; |
789 | struct net_device *mdev; | 794 | struct net_device *mdev; |
790 | struct wireless_dev *mwdev; | 795 | struct ieee80211_master_priv *mpriv; |
791 | 796 | ||
792 | /* | 797 | /* |
793 | * generic code guarantees at least one band, | 798 | * generic code guarantees at least one band, |
@@ -829,16 +834,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
829 | if (hw->queues < 4) | 834 | if (hw->queues < 4) |
830 | hw->ampdu_queues = 0; | 835 | hw->ampdu_queues = 0; |
831 | 836 | ||
832 | mdev = alloc_netdev_mq(sizeof(struct wireless_dev), | 837 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), |
833 | "wmaster%d", ether_setup, | 838 | "wmaster%d", ether_setup, |
834 | ieee80211_num_queues(hw)); | 839 | ieee80211_num_queues(hw)); |
835 | if (!mdev) | 840 | if (!mdev) |
836 | goto fail_mdev_alloc; | 841 | goto fail_mdev_alloc; |
837 | 842 | ||
838 | mwdev = netdev_priv(mdev); | 843 | mpriv = netdev_priv(mdev); |
839 | mdev->ieee80211_ptr = mwdev; | 844 | mpriv->local = local; |
840 | mwdev->wiphy = local->hw.wiphy; | ||
841 | |||
842 | local->mdev = mdev; | 845 | local->mdev = mdev; |
843 | 846 | ||
844 | ieee80211_rx_bss_list_init(local); | 847 | ieee80211_rx_bss_list_init(local); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 30cf891fd3a8..8013277924f2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -351,7 +351,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
351 | struct ieee80211_sub_if_data *sdata = | 351 | struct ieee80211_sub_if_data *sdata = |
352 | (struct ieee80211_sub_if_data *) data; | 352 | (struct ieee80211_sub_if_data *) data; |
353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
354 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 354 | struct ieee80211_local *local = sdata->local; |
355 | 355 | ||
356 | queue_work(local->hw.workqueue, &ifmsh->work); | 356 | queue_work(local->hw.workqueue, &ifmsh->work); |
357 | } | 357 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8ee414a0447c..e10471c6ba42 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -71,6 +71,7 @@ enum mesh_path_flags { | |||
71 | */ | 71 | */ |
72 | struct mesh_path { | 72 | struct mesh_path { |
73 | u8 dst[ETH_ALEN]; | 73 | u8 dst[ETH_ALEN]; |
74 | u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ | ||
74 | struct ieee80211_sub_if_data *sdata; | 75 | struct ieee80211_sub_if_data *sdata; |
75 | struct sta_info *next_hop; | 76 | struct sta_info *next_hop; |
76 | struct timer_list timer; | 77 | struct timer_list timer; |
@@ -226,6 +227,9 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
226 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); | 227 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
227 | struct mesh_path *mesh_path_lookup(u8 *dst, | 228 | struct mesh_path *mesh_path_lookup(u8 *dst, |
228 | struct ieee80211_sub_if_data *sdata); | 229 | struct ieee80211_sub_if_data *sdata); |
230 | struct mesh_path *mpp_path_lookup(u8 *dst, | ||
231 | struct ieee80211_sub_if_data *sdata); | ||
232 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); | ||
229 | struct mesh_path *mesh_path_lookup_by_idx(int idx, | 233 | struct mesh_path *mesh_path_lookup_by_idx(int idx, |
230 | struct ieee80211_sub_if_data *sdata); | 234 | struct ieee80211_sub_if_data *sdata); |
231 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 235 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index e4fa2905fadc..3c72557df45a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -36,6 +36,7 @@ struct mpath_node { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct mesh_table *mesh_paths; | 38 | static struct mesh_table *mesh_paths; |
39 | static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ | ||
39 | 40 | ||
40 | /* This lock will have the grow table function as writer and add / delete nodes | 41 | /* This lock will have the grow table function as writer and add / delete nodes |
41 | * as readers. When reading the table (i.e. doing lookups) we are well protected | 42 | * as readers. When reading the table (i.e. doing lookups) we are well protected |
@@ -94,6 +95,34 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
94 | return NULL; | 95 | return NULL; |
95 | } | 96 | } |
96 | 97 | ||
98 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | ||
99 | { | ||
100 | struct mesh_path *mpath; | ||
101 | struct hlist_node *n; | ||
102 | struct hlist_head *bucket; | ||
103 | struct mesh_table *tbl; | ||
104 | struct mpath_node *node; | ||
105 | |||
106 | tbl = rcu_dereference(mpp_paths); | ||
107 | |||
108 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; | ||
109 | hlist_for_each_entry_rcu(node, n, bucket, list) { | ||
110 | mpath = node->mpath; | ||
111 | if (mpath->sdata == sdata && | ||
112 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | ||
113 | if (MPATH_EXPIRED(mpath)) { | ||
114 | spin_lock_bh(&mpath->state_lock); | ||
115 | if (MPATH_EXPIRED(mpath)) | ||
116 | mpath->flags &= ~MESH_PATH_ACTIVE; | ||
117 | spin_unlock_bh(&mpath->state_lock); | ||
118 | } | ||
119 | return mpath; | ||
120 | } | ||
121 | } | ||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | |||
97 | /** | 126 | /** |
98 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index | 127 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index |
99 | * @idx: index | 128 | * @idx: index |
@@ -226,6 +255,91 @@ err_path_alloc: | |||
226 | } | 255 | } |
227 | 256 | ||
228 | 257 | ||
258 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | ||
259 | { | ||
260 | struct mesh_path *mpath, *new_mpath; | ||
261 | struct mpath_node *node, *new_node; | ||
262 | struct hlist_head *bucket; | ||
263 | struct hlist_node *n; | ||
264 | int grow = 0; | ||
265 | int err = 0; | ||
266 | u32 hash_idx; | ||
267 | |||
268 | |||
269 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | ||
270 | /* never add ourselves as neighbours */ | ||
271 | return -ENOTSUPP; | ||
272 | |||
273 | if (is_multicast_ether_addr(dst)) | ||
274 | return -ENOTSUPP; | ||
275 | |||
276 | err = -ENOMEM; | ||
277 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); | ||
278 | if (!new_mpath) | ||
279 | goto err_path_alloc; | ||
280 | |||
281 | new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); | ||
282 | if (!new_node) | ||
283 | goto err_node_alloc; | ||
284 | |||
285 | read_lock(&pathtbl_resize_lock); | ||
286 | memcpy(new_mpath->dst, dst, ETH_ALEN); | ||
287 | memcpy(new_mpath->mpp, mpp, ETH_ALEN); | ||
288 | new_mpath->sdata = sdata; | ||
289 | new_mpath->flags = 0; | ||
290 | skb_queue_head_init(&new_mpath->frame_queue); | ||
291 | new_node->mpath = new_mpath; | ||
292 | new_mpath->exp_time = jiffies; | ||
293 | spin_lock_init(&new_mpath->state_lock); | ||
294 | |||
295 | hash_idx = mesh_table_hash(dst, sdata, mpp_paths); | ||
296 | bucket = &mpp_paths->hash_buckets[hash_idx]; | ||
297 | |||
298 | spin_lock(&mpp_paths->hashwlock[hash_idx]); | ||
299 | |||
300 | err = -EEXIST; | ||
301 | hlist_for_each_entry(node, n, bucket, list) { | ||
302 | mpath = node->mpath; | ||
303 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | ||
304 | goto err_exists; | ||
305 | } | ||
306 | |||
307 | hlist_add_head_rcu(&new_node->list, bucket); | ||
308 | if (atomic_inc_return(&mpp_paths->entries) >= | ||
309 | mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) | ||
310 | grow = 1; | ||
311 | |||
312 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
313 | read_unlock(&pathtbl_resize_lock); | ||
314 | if (grow) { | ||
315 | struct mesh_table *oldtbl, *newtbl; | ||
316 | |||
317 | write_lock(&pathtbl_resize_lock); | ||
318 | oldtbl = mpp_paths; | ||
319 | newtbl = mesh_table_grow(mpp_paths); | ||
320 | if (!newtbl) { | ||
321 | write_unlock(&pathtbl_resize_lock); | ||
322 | return 0; | ||
323 | } | ||
324 | rcu_assign_pointer(mpp_paths, newtbl); | ||
325 | write_unlock(&pathtbl_resize_lock); | ||
326 | |||
327 | synchronize_rcu(); | ||
328 | mesh_table_free(oldtbl, false); | ||
329 | } | ||
330 | return 0; | ||
331 | |||
332 | err_exists: | ||
333 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
334 | read_unlock(&pathtbl_resize_lock); | ||
335 | kfree(new_node); | ||
336 | err_node_alloc: | ||
337 | kfree(new_mpath); | ||
338 | err_path_alloc: | ||
339 | return err; | ||
340 | } | ||
341 | |||
342 | |||
229 | /** | 343 | /** |
230 | * mesh_plink_broken - deactivates paths and sends perr when a link breaks | 344 | * mesh_plink_broken - deactivates paths and sends perr when a link breaks |
231 | * | 345 | * |
@@ -475,11 +589,21 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
475 | int mesh_pathtbl_init(void) | 589 | int mesh_pathtbl_init(void) |
476 | { | 590 | { |
477 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | 591 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); |
592 | if (!mesh_paths) | ||
593 | return -ENOMEM; | ||
478 | mesh_paths->free_node = &mesh_path_node_free; | 594 | mesh_paths->free_node = &mesh_path_node_free; |
479 | mesh_paths->copy_node = &mesh_path_node_copy; | 595 | mesh_paths->copy_node = &mesh_path_node_copy; |
480 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; | 596 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; |
481 | if (!mesh_paths) | 597 | |
598 | mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | ||
599 | if (!mpp_paths) { | ||
600 | mesh_table_free(mesh_paths, true); | ||
482 | return -ENOMEM; | 601 | return -ENOMEM; |
602 | } | ||
603 | mpp_paths->free_node = &mesh_path_node_free; | ||
604 | mpp_paths->copy_node = &mesh_path_node_copy; | ||
605 | mpp_paths->mean_chain_len = MEAN_CHAIN_LEN; | ||
606 | |||
483 | return 0; | 607 | return 0; |
484 | } | 608 | } |
485 | 609 | ||
@@ -511,4 +635,5 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
511 | void mesh_pathtbl_unregister(void) | 635 | void mesh_pathtbl_unregister(void) |
512 | { | 636 | { |
513 | mesh_table_free(mesh_paths, true); | 637 | mesh_table_free(mesh_paths, true); |
638 | mesh_table_free(mpp_paths, true); | ||
514 | } | 639 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8611a8318c9c..e859a0ab6162 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -942,8 +942,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
942 | disassoc = 1; | 942 | disassoc = 1; |
943 | } else | 943 | } else |
944 | ieee80211_send_probe_req(sdata, ifsta->bssid, | 944 | ieee80211_send_probe_req(sdata, ifsta->bssid, |
945 | local->scan_ssid, | 945 | ifsta->ssid, |
946 | local->scan_ssid_len); | 946 | ifsta->ssid_len); |
947 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; | 947 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; |
948 | } else { | 948 | } else { |
949 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | 949 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; |
@@ -1323,7 +1323,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1323 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); | 1323 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | rate_control_rate_init(sta, local); | 1326 | rate_control_rate_init(sta); |
1327 | 1327 | ||
1328 | if (elems.wmm_param) { | 1328 | if (elems.wmm_param) { |
1329 | set_sta_flags(sta, WLAN_STA_WME); | 1329 | set_sta_flags(sta, WLAN_STA_WME); |
@@ -1452,6 +1452,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1452 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; | 1452 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; |
1453 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1453 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
1454 | 1454 | ||
1455 | ieee80211_led_assoc(local, true); | ||
1456 | |||
1455 | memset(&wrqu, 0, sizeof(wrqu)); | 1457 | memset(&wrqu, 0, sizeof(wrqu)); |
1456 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 1458 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
1457 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | 1459 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); |
@@ -2342,7 +2344,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
2342 | sta->sta.supp_rates[band] = supp_rates | | 2344 | sta->sta.supp_rates[band] = supp_rates | |
2343 | ieee80211_mandatory_rates(local, band); | 2345 | ieee80211_mandatory_rates(local, band); |
2344 | 2346 | ||
2345 | rate_control_rate_init(sta, local); | 2347 | rate_control_rate_init(sta); |
2346 | 2348 | ||
2347 | if (sta_info_insert(sta)) | 2349 | if (sta_info_insert(sta)) |
2348 | return NULL; | 2350 | return NULL; |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0388c090dfe9..5d786720d935 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
13 | #include "rate.h" | 13 | #include "rate.h" |
14 | #include "ieee80211_i.h" | 14 | #include "ieee80211_i.h" |
15 | #include "debugfs.h" | ||
15 | 16 | ||
16 | struct rate_control_alg { | 17 | struct rate_control_alg { |
17 | struct list_head list; | 18 | struct list_head list; |
@@ -127,19 +128,46 @@ static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) | |||
127 | module_put(ops->module); | 128 | module_put(ops->module); |
128 | } | 129 | } |
129 | 130 | ||
131 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
132 | static ssize_t rcname_read(struct file *file, char __user *userbuf, | ||
133 | size_t count, loff_t *ppos) | ||
134 | { | ||
135 | struct rate_control_ref *ref = file->private_data; | ||
136 | int len = strlen(ref->ops->name); | ||
137 | |||
138 | return simple_read_from_buffer(userbuf, count, ppos, | ||
139 | ref->ops->name, len); | ||
140 | } | ||
141 | |||
142 | static const struct file_operations rcname_ops = { | ||
143 | .read = rcname_read, | ||
144 | .open = mac80211_open_file_generic, | ||
145 | }; | ||
146 | #endif | ||
147 | |||
130 | struct rate_control_ref *rate_control_alloc(const char *name, | 148 | struct rate_control_ref *rate_control_alloc(const char *name, |
131 | struct ieee80211_local *local) | 149 | struct ieee80211_local *local) |
132 | { | 150 | { |
151 | struct dentry *debugfsdir = NULL; | ||
133 | struct rate_control_ref *ref; | 152 | struct rate_control_ref *ref; |
134 | 153 | ||
135 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 154 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
136 | if (!ref) | 155 | if (!ref) |
137 | goto fail_ref; | 156 | goto fail_ref; |
138 | kref_init(&ref->kref); | 157 | kref_init(&ref->kref); |
158 | ref->local = local; | ||
139 | ref->ops = ieee80211_rate_control_ops_get(name); | 159 | ref->ops = ieee80211_rate_control_ops_get(name); |
140 | if (!ref->ops) | 160 | if (!ref->ops) |
141 | goto fail_ops; | 161 | goto fail_ops; |
142 | ref->priv = ref->ops->alloc(local); | 162 | |
163 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
164 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | ||
165 | local->debugfs.rcdir = debugfsdir; | ||
166 | local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, | ||
167 | ref, &rcname_ops); | ||
168 | #endif | ||
169 | |||
170 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | ||
143 | if (!ref->priv) | 171 | if (!ref->priv) |
144 | goto fail_priv; | 172 | goto fail_priv; |
145 | return ref; | 173 | return ref; |
@@ -158,29 +186,46 @@ static void rate_control_release(struct kref *kref) | |||
158 | 186 | ||
159 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); | 187 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); |
160 | ctrl_ref->ops->free(ctrl_ref->priv); | 188 | ctrl_ref->ops->free(ctrl_ref->priv); |
189 | |||
190 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
191 | debugfs_remove(ctrl_ref->local->debugfs.rcname); | ||
192 | ctrl_ref->local->debugfs.rcname = NULL; | ||
193 | debugfs_remove(ctrl_ref->local->debugfs.rcdir); | ||
194 | ctrl_ref->local->debugfs.rcdir = NULL; | ||
195 | #endif | ||
196 | |||
161 | ieee80211_rate_control_ops_put(ctrl_ref->ops); | 197 | ieee80211_rate_control_ops_put(ctrl_ref->ops); |
162 | kfree(ctrl_ref); | 198 | kfree(ctrl_ref); |
163 | } | 199 | } |
164 | 200 | ||
165 | void rate_control_get_rate(struct net_device *dev, | 201 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
166 | struct ieee80211_supported_band *sband, | 202 | struct ieee80211_supported_band *sband, |
167 | struct sk_buff *skb, | 203 | struct sta_info *sta, struct sk_buff *skb, |
168 | struct rate_selection *sel) | 204 | struct rate_selection *sel) |
169 | { | 205 | { |
170 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 206 | struct rate_control_ref *ref = sdata->local->rate_ctrl; |
171 | struct rate_control_ref *ref = local->rate_ctrl; | 207 | void *priv_sta = NULL; |
172 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 208 | struct ieee80211_sta *ista = NULL; |
173 | struct sta_info *sta; | ||
174 | int i; | 209 | int i; |
175 | 210 | ||
176 | rcu_read_lock(); | ||
177 | sta = sta_info_get(local, hdr->addr1); | ||
178 | |||
179 | sel->rate_idx = -1; | 211 | sel->rate_idx = -1; |
180 | sel->nonerp_idx = -1; | 212 | sel->nonerp_idx = -1; |
181 | sel->probe_idx = -1; | 213 | sel->probe_idx = -1; |
214 | sel->max_rate_idx = sdata->max_ratectrl_rateidx; | ||
215 | |||
216 | if (sta) { | ||
217 | ista = &sta->sta; | ||
218 | priv_sta = sta->rate_ctrl_priv; | ||
219 | } | ||
220 | |||
221 | if (sta && sdata->force_unicast_rateidx > -1) | ||
222 | sel->rate_idx = sdata->force_unicast_rateidx; | ||
223 | else | ||
224 | ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); | ||
182 | 225 | ||
183 | ref->ops->get_rate(ref->priv, dev, sband, skb, sel); | 226 | if (sdata->max_ratectrl_rateidx > -1 && |
227 | sel->rate_idx > sdata->max_ratectrl_rateidx) | ||
228 | sel->rate_idx = sdata->max_ratectrl_rateidx; | ||
184 | 229 | ||
185 | BUG_ON(sel->rate_idx < 0); | 230 | BUG_ON(sel->rate_idx < 0); |
186 | 231 | ||
@@ -191,13 +236,11 @@ void rate_control_get_rate(struct net_device *dev, | |||
191 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) | 236 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) |
192 | break; | 237 | break; |
193 | 238 | ||
194 | if (rate_supported(sta, sband->band, i) && | 239 | if (rate_supported(ista, sband->band, i) && |
195 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 240 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
196 | sel->nonerp_idx = i; | 241 | sel->nonerp_idx = i; |
197 | } | 242 | } |
198 | } | 243 | } |
199 | |||
200 | rcu_read_unlock(); | ||
201 | } | 244 | } |
202 | 245 | ||
203 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) | 246 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5f18c27eb900..eb94e584d24e 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -19,77 +19,48 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | 20 | #include "sta_info.h" |
21 | 21 | ||
22 | /** | ||
23 | * struct rate_selection - rate selection for rate control algos | ||
24 | * @rate: selected transmission rate index | ||
25 | * @nonerp: Non-ERP rate to use instead if ERP cannot be used | ||
26 | * @probe: rate for probing (or -1) | ||
27 | * | ||
28 | */ | ||
29 | struct rate_selection { | ||
30 | s8 rate_idx, nonerp_idx, probe_idx; | ||
31 | }; | ||
32 | |||
33 | struct rate_control_ops { | ||
34 | struct module *module; | ||
35 | const char *name; | ||
36 | void (*tx_status)(void *priv, struct net_device *dev, | ||
37 | struct sk_buff *skb); | ||
38 | void (*get_rate)(void *priv, struct net_device *dev, | ||
39 | struct ieee80211_supported_band *band, | ||
40 | struct sk_buff *skb, | ||
41 | struct rate_selection *sel); | ||
42 | void (*rate_init)(void *priv, void *priv_sta, | ||
43 | struct ieee80211_local *local, struct sta_info *sta); | ||
44 | void (*clear)(void *priv); | ||
45 | |||
46 | void *(*alloc)(struct ieee80211_local *local); | ||
47 | void (*free)(void *priv); | ||
48 | void *(*alloc_sta)(void *priv, gfp_t gfp); | ||
49 | void (*free_sta)(void *priv, void *priv_sta); | ||
50 | |||
51 | int (*add_attrs)(void *priv, struct kobject *kobj); | ||
52 | void (*remove_attrs)(void *priv, struct kobject *kobj); | ||
53 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | ||
54 | struct dentry *dir); | ||
55 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | ||
56 | }; | ||
57 | |||
58 | struct rate_control_ref { | 22 | struct rate_control_ref { |
23 | struct ieee80211_local *local; | ||
59 | struct rate_control_ops *ops; | 24 | struct rate_control_ops *ops; |
60 | void *priv; | 25 | void *priv; |
61 | struct kref kref; | 26 | struct kref kref; |
62 | }; | 27 | }; |
63 | 28 | ||
64 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | ||
65 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | ||
66 | |||
67 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | 29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
68 | * first available algorithm. */ | 30 | * first available algorithm. */ |
69 | struct rate_control_ref *rate_control_alloc(const char *name, | 31 | struct rate_control_ref *rate_control_alloc(const char *name, |
70 | struct ieee80211_local *local); | 32 | struct ieee80211_local *local); |
71 | void rate_control_get_rate(struct net_device *dev, | 33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
72 | struct ieee80211_supported_band *sband, | 34 | struct ieee80211_supported_band *sband, |
73 | struct sk_buff *skb, | 35 | struct sta_info *sta, struct sk_buff *skb, |
74 | struct rate_selection *sel); | 36 | struct rate_selection *sel); |
75 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | 37 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); |
76 | void rate_control_put(struct rate_control_ref *ref); | 38 | void rate_control_put(struct rate_control_ref *ref); |
77 | 39 | ||
78 | static inline void rate_control_tx_status(struct net_device *dev, | 40 | static inline void rate_control_tx_status(struct ieee80211_local *local, |
41 | struct ieee80211_supported_band *sband, | ||
42 | struct sta_info *sta, | ||
79 | struct sk_buff *skb) | 43 | struct sk_buff *skb) |
80 | { | 44 | { |
81 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
82 | struct rate_control_ref *ref = local->rate_ctrl; | 45 | struct rate_control_ref *ref = local->rate_ctrl; |
46 | struct ieee80211_sta *ista = &sta->sta; | ||
47 | void *priv_sta = sta->rate_ctrl_priv; | ||
83 | 48 | ||
84 | ref->ops->tx_status(ref->priv, dev, skb); | 49 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
85 | } | 50 | } |
86 | 51 | ||
87 | 52 | ||
88 | static inline void rate_control_rate_init(struct sta_info *sta, | 53 | static inline void rate_control_rate_init(struct sta_info *sta) |
89 | struct ieee80211_local *local) | ||
90 | { | 54 | { |
55 | struct ieee80211_local *local = sta->sdata->local; | ||
91 | struct rate_control_ref *ref = sta->rate_ctrl; | 56 | struct rate_control_ref *ref = sta->rate_ctrl; |
92 | ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta); | 57 | struct ieee80211_sta *ista = &sta->sta; |
58 | void *priv_sta = sta->rate_ctrl_priv; | ||
59 | struct ieee80211_supported_band *sband; | ||
60 | |||
61 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
62 | |||
63 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | ||
93 | } | 64 | } |
94 | 65 | ||
95 | 66 | ||
@@ -100,15 +71,19 @@ static inline void rate_control_clear(struct ieee80211_local *local) | |||
100 | } | 71 | } |
101 | 72 | ||
102 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 73 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
74 | struct ieee80211_sta *sta, | ||
103 | gfp_t gfp) | 75 | gfp_t gfp) |
104 | { | 76 | { |
105 | return ref->ops->alloc_sta(ref->priv, gfp); | 77 | return ref->ops->alloc_sta(ref->priv, sta, gfp); |
106 | } | 78 | } |
107 | 79 | ||
108 | static inline void rate_control_free_sta(struct rate_control_ref *ref, | 80 | static inline void rate_control_free_sta(struct sta_info *sta) |
109 | void *priv) | ||
110 | { | 81 | { |
111 | ref->ops->free_sta(ref->priv, priv); | 82 | struct rate_control_ref *ref = sta->rate_ctrl; |
83 | struct ieee80211_sta *ista = &sta->sta; | ||
84 | void *priv_sta = sta->rate_ctrl_priv; | ||
85 | |||
86 | ref->ops->free_sta(ref->priv, ista, priv_sta); | ||
112 | } | 87 | } |
113 | 88 | ||
114 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) | 89 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) |
@@ -130,31 +105,6 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
130 | #endif | 105 | #endif |
131 | } | 106 | } |
132 | 107 | ||
133 | static inline int rate_supported(struct sta_info *sta, | ||
134 | enum ieee80211_band band, | ||
135 | int index) | ||
136 | { | ||
137 | return (sta == NULL || sta->sta.supp_rates[band] & BIT(index)); | ||
138 | } | ||
139 | |||
140 | static inline s8 | ||
141 | rate_lowest_index(struct ieee80211_local *local, | ||
142 | struct ieee80211_supported_band *sband, | ||
143 | struct sta_info *sta) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i < sband->n_bitrates; i++) | ||
148 | if (rate_supported(sta, sband->band, i)) | ||
149 | return i; | ||
150 | |||
151 | /* warn when we cannot find a rate. */ | ||
152 | WARN_ON(1); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | /* functions for rate control related to a device */ | 108 | /* functions for rate control related to a device */ |
159 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 109 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
160 | const char *name); | 110 | const char *name); |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index ffafc5da572e..01d64d53f3b9 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -124,7 +124,6 @@ struct rc_pid_events_file_info { | |||
124 | * struct rc_pid_debugfs_entries - tunable parameters | 124 | * struct rc_pid_debugfs_entries - tunable parameters |
125 | * | 125 | * |
126 | * Algorithm parameters, tunable via debugfs. | 126 | * Algorithm parameters, tunable via debugfs. |
127 | * @dir: the debugfs directory for a specific phy | ||
128 | * @target: target percentage for failed frames | 127 | * @target: target percentage for failed frames |
129 | * @sampling_period: error sampling interval in milliseconds | 128 | * @sampling_period: error sampling interval in milliseconds |
130 | * @coeff_p: absolute value of the proportional coefficient | 129 | * @coeff_p: absolute value of the proportional coefficient |
@@ -143,7 +142,6 @@ struct rc_pid_events_file_info { | |||
143 | * ordering of rates) | 142 | * ordering of rates) |
144 | */ | 143 | */ |
145 | struct rc_pid_debugfs_entries { | 144 | struct rc_pid_debugfs_entries { |
146 | struct dentry *dir; | ||
147 | struct dentry *target; | 145 | struct dentry *target; |
148 | struct dentry *sampling_period; | 146 | struct dentry *sampling_period; |
149 | struct dentry *coeff_p; | 147 | struct dentry *coeff_p; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index bc1c4569caa1..86eb374e3b87 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -68,18 +68,14 @@ | |||
68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate | 68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate |
69 | * whose failed frames behaviour is not worse than the one of the original rate | 69 | * whose failed frames behaviour is not worse than the one of the original rate |
70 | * target. While at it, check that the new rate is valid. */ | 70 | * target. While at it, check that the new rate is valid. */ |
71 | static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | 71 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, |
72 | struct sta_info *sta, int adj, | 72 | struct ieee80211_sta *sta, |
73 | struct rc_pid_sta_info *spinfo, int adj, | ||
73 | struct rc_pid_rateinfo *rinfo) | 74 | struct rc_pid_rateinfo *rinfo) |
74 | { | 75 | { |
75 | struct ieee80211_sub_if_data *sdata; | ||
76 | struct ieee80211_supported_band *sband; | ||
77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | 76 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; |
78 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
79 | int cur = spinfo->txrate_idx; | 77 | int cur = spinfo->txrate_idx; |
80 | 78 | ||
81 | sdata = sta->sdata; | ||
82 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
83 | band = sband->band; | 79 | band = sband->band; |
84 | n_bitrates = sband->n_bitrates; | 80 | n_bitrates = sband->n_bitrates; |
85 | 81 | ||
@@ -146,13 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) | |||
146 | } | 142 | } |
147 | 143 | ||
148 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | 144 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, |
149 | struct ieee80211_local *local, | 145 | struct ieee80211_supported_band *sband, |
150 | struct sta_info *sta) | 146 | struct ieee80211_sta *sta, |
147 | struct rc_pid_sta_info *spinfo) | ||
151 | { | 148 | { |
152 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
153 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | ||
154 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 149 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
155 | struct ieee80211_supported_band *sband; | ||
156 | u32 pf; | 150 | u32 pf; |
157 | s32 err_avg; | 151 | s32 err_avg; |
158 | u32 err_prop; | 152 | u32 err_prop; |
@@ -161,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
161 | int adj, i, j, tmp; | 155 | int adj, i, j, tmp; |
162 | unsigned long period; | 156 | unsigned long period; |
163 | 157 | ||
164 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
165 | spinfo = sta->rate_ctrl_priv; | ||
166 | |||
167 | /* In case nothing happened during the previous control interval, turn | 158 | /* In case nothing happened during the previous control interval, turn |
168 | * the sharpening factor on. */ | 159 | * the sharpening factor on. */ |
169 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 160 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
@@ -179,11 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
179 | if (unlikely(spinfo->tx_num_xmit == 0)) | 170 | if (unlikely(spinfo->tx_num_xmit == 0)) |
180 | pf = spinfo->last_pf; | 171 | pf = spinfo->last_pf; |
181 | else { | 172 | else { |
173 | /* XXX: BAD HACK!!! */ | ||
174 | struct sta_info *si = container_of(sta, struct sta_info, sta); | ||
175 | |||
182 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
183 | if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) | 177 | |
184 | mesh_plink_broken(sta); | 178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) |
179 | mesh_plink_broken(si); | ||
185 | pf <<= RC_PID_ARITH_SHIFT; | 180 | pf <<= RC_PID_ARITH_SHIFT; |
186 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
187 | >> RC_PID_ARITH_SHIFT; | 182 | >> RC_PID_ARITH_SHIFT; |
188 | } | 183 | } |
189 | 184 | ||
@@ -229,43 +224,25 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
229 | 224 | ||
230 | /* Change rate. */ | 225 | /* Change rate. */ |
231 | if (adj) | 226 | if (adj) |
232 | rate_control_pid_adjust_rate(local, sta, adj, rinfo); | 227 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); |
233 | } | 228 | } |
234 | 229 | ||
235 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | 230 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, |
231 | struct ieee80211_sta *sta, void *priv_sta, | ||
236 | struct sk_buff *skb) | 232 | struct sk_buff *skb) |
237 | { | 233 | { |
238 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
239 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
240 | struct ieee80211_sub_if_data *sdata; | ||
241 | struct rc_pid_info *pinfo = priv; | 234 | struct rc_pid_info *pinfo = priv; |
242 | struct sta_info *sta; | 235 | struct rc_pid_sta_info *spinfo = priv_sta; |
243 | struct rc_pid_sta_info *spinfo; | ||
244 | unsigned long period; | 236 | unsigned long period; |
245 | struct ieee80211_supported_band *sband; | ||
246 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
247 | 238 | ||
248 | rcu_read_lock(); | 239 | if (!spinfo) |
249 | 240 | return; | |
250 | sta = sta_info_get(local, hdr->addr1); | ||
251 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
252 | |||
253 | if (!sta) | ||
254 | goto unlock; | ||
255 | |||
256 | spinfo = sta->rate_ctrl_priv; | ||
257 | |||
258 | /* Don't update the state if we're not controlling the rate. */ | ||
259 | sdata = sta->sdata; | ||
260 | if (sdata->force_unicast_rateidx > -1) { | ||
261 | spinfo->txrate_idx = sdata->max_ratectrl_rateidx; | ||
262 | goto unlock; | ||
263 | } | ||
264 | 241 | ||
265 | /* Ignore all frames that were sent with a different rate than the rate | 242 | /* Ignore all frames that were sent with a different rate than the rate |
266 | * we currently advise mac80211 to use. */ | 243 | * we currently advise mac80211 to use. */ |
267 | if (info->tx_rate_idx != spinfo->txrate_idx) | 244 | if (info->tx_rate_idx != spinfo->txrate_idx) |
268 | goto unlock; | 245 | return; |
269 | 246 | ||
270 | spinfo->tx_num_xmit++; | 247 | spinfo->tx_num_xmit++; |
271 | 248 | ||
@@ -289,78 +266,63 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
289 | if (!period) | 266 | if (!period) |
290 | period = 1; | 267 | period = 1; |
291 | if (time_after(jiffies, spinfo->last_sample + period)) | 268 | if (time_after(jiffies, spinfo->last_sample + period)) |
292 | rate_control_pid_sample(pinfo, local, sta); | 269 | rate_control_pid_sample(pinfo, sband, sta, spinfo); |
293 | |||
294 | unlock: | ||
295 | rcu_read_unlock(); | ||
296 | } | 270 | } |
297 | 271 | ||
298 | static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | 272 | static void |
299 | struct ieee80211_supported_band *sband, | 273 | rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, |
300 | struct sk_buff *skb, | 274 | struct ieee80211_sta *sta, void *priv_sta, |
301 | struct rate_selection *sel) | 275 | struct sk_buff *skb, |
276 | struct rate_selection *sel) | ||
302 | { | 277 | { |
303 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 278 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
305 | struct ieee80211_sub_if_data *sdata; | 279 | struct rc_pid_sta_info *spinfo = priv_sta; |
306 | struct rc_pid_sta_info *spinfo; | ||
307 | struct sta_info *sta; | ||
308 | int rateidx; | 280 | int rateidx; |
309 | u16 fc; | 281 | u16 fc; |
310 | 282 | ||
311 | rcu_read_lock(); | ||
312 | |||
313 | sta = sta_info_get(local, hdr->addr1); | ||
314 | |||
315 | /* Send management frames and broadcast/multicast data using lowest | 283 | /* Send management frames and broadcast/multicast data using lowest |
316 | * rate. */ | 284 | * rate. */ |
317 | fc = le16_to_cpu(hdr->frame_control); | 285 | fc = le16_to_cpu(hdr->frame_control); |
318 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 286 | if (!sta || !spinfo || |
319 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 287 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
320 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 288 | is_multicast_ether_addr(hdr->addr1)) { |
321 | rcu_read_unlock(); | 289 | sel->rate_idx = rate_lowest_index(sband, sta); |
322 | return; | 290 | return; |
323 | } | 291 | } |
324 | 292 | ||
325 | /* If a forced rate is in effect, select it. */ | ||
326 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
327 | spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; | ||
328 | if (sdata->force_unicast_rateidx > -1) | ||
329 | spinfo->txrate_idx = sdata->force_unicast_rateidx; | ||
330 | |||
331 | rateidx = spinfo->txrate_idx; | 293 | rateidx = spinfo->txrate_idx; |
332 | 294 | ||
333 | if (rateidx >= sband->n_bitrates) | 295 | if (rateidx >= sband->n_bitrates) |
334 | rateidx = sband->n_bitrates - 1; | 296 | rateidx = sband->n_bitrates - 1; |
335 | 297 | ||
336 | rcu_read_unlock(); | ||
337 | |||
338 | sel->rate_idx = rateidx; | 298 | sel->rate_idx = rateidx; |
339 | 299 | ||
340 | #ifdef CONFIG_MAC80211_DEBUGFS | 300 | #ifdef CONFIG_MAC80211_DEBUGFS |
341 | rate_control_pid_event_tx_rate( | 301 | rate_control_pid_event_tx_rate(&spinfo->events, |
342 | &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, | ||
343 | rateidx, sband->bitrates[rateidx].bitrate); | 302 | rateidx, sband->bitrates[rateidx].bitrate); |
344 | #endif | 303 | #endif |
345 | } | 304 | } |
346 | 305 | ||
347 | static void rate_control_pid_rate_init(void *priv, void *priv_sta, | 306 | static void |
348 | struct ieee80211_local *local, | 307 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, |
349 | struct sta_info *sta) | 308 | struct ieee80211_sta *sta, void *priv_sta) |
350 | { | 309 | { |
310 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
311 | struct sta_info *si; | ||
312 | |||
351 | /* TODO: This routine should consider using RSSI from previous packets | 313 | /* TODO: This routine should consider using RSSI from previous packets |
352 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | 314 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. |
353 | * Until that method is implemented, we will use the lowest supported | 315 | * Until that method is implemented, we will use the lowest supported |
354 | * rate as a workaround. */ | 316 | * rate as a workaround. */ |
355 | struct ieee80211_supported_band *sband; | ||
356 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
357 | 317 | ||
358 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 318 | spinfo->txrate_idx = rate_lowest_index(sband, sta); |
359 | spinfo->txrate_idx = rate_lowest_index(local, sband, sta); | 319 | /* HACK */ |
360 | sta->fail_avg = 0; | 320 | si = container_of(sta, struct sta_info, sta); |
321 | si->fail_avg = 0; | ||
361 | } | 322 | } |
362 | 323 | ||
363 | static void *rate_control_pid_alloc(struct ieee80211_local *local) | 324 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, |
325 | struct dentry *debugfsdir) | ||
364 | { | 326 | { |
365 | struct rc_pid_info *pinfo; | 327 | struct rc_pid_info *pinfo; |
366 | struct rc_pid_rateinfo *rinfo; | 328 | struct rc_pid_rateinfo *rinfo; |
@@ -371,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
371 | struct rc_pid_debugfs_entries *de; | 333 | struct rc_pid_debugfs_entries *de; |
372 | #endif | 334 | #endif |
373 | 335 | ||
374 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 336 | sband = hw->wiphy->bands[hw->conf.channel->band]; |
375 | 337 | ||
376 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | 338 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); |
377 | if (!pinfo) | 339 | if (!pinfo) |
@@ -426,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
426 | 388 | ||
427 | #ifdef CONFIG_MAC80211_DEBUGFS | 389 | #ifdef CONFIG_MAC80211_DEBUGFS |
428 | de = &pinfo->dentries; | 390 | de = &pinfo->dentries; |
429 | de->dir = debugfs_create_dir("rc80211_pid", | ||
430 | local->hw.wiphy->debugfsdir); | ||
431 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, | 391 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, |
432 | de->dir, &pinfo->target); | 392 | debugfsdir, &pinfo->target); |
433 | de->sampling_period = debugfs_create_u32("sampling_period", | 393 | de->sampling_period = debugfs_create_u32("sampling_period", |
434 | S_IRUSR | S_IWUSR, de->dir, | 394 | S_IRUSR | S_IWUSR, debugfsdir, |
435 | &pinfo->sampling_period); | 395 | &pinfo->sampling_period); |
436 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, | 396 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, |
437 | de->dir, &pinfo->coeff_p); | 397 | debugfsdir, &pinfo->coeff_p); |
438 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, | 398 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, |
439 | de->dir, &pinfo->coeff_i); | 399 | debugfsdir, &pinfo->coeff_i); |
440 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, | 400 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, |
441 | de->dir, &pinfo->coeff_d); | 401 | debugfsdir, &pinfo->coeff_d); |
442 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", | 402 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", |
443 | S_IRUSR | S_IWUSR, de->dir, | 403 | S_IRUSR | S_IWUSR, debugfsdir, |
444 | &pinfo->smoothing_shift); | 404 | &pinfo->smoothing_shift); |
445 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", | 405 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", |
446 | S_IRUSR | S_IWUSR, de->dir, | 406 | S_IRUSR | S_IWUSR, debugfsdir, |
447 | &pinfo->sharpen_factor); | 407 | &pinfo->sharpen_factor); |
448 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", | 408 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", |
449 | S_IRUSR | S_IWUSR, de->dir, | 409 | S_IRUSR | S_IWUSR, debugfsdir, |
450 | &pinfo->sharpen_duration); | 410 | &pinfo->sharpen_duration); |
451 | de->norm_offset = debugfs_create_u32("norm_offset", | 411 | de->norm_offset = debugfs_create_u32("norm_offset", |
452 | S_IRUSR | S_IWUSR, de->dir, | 412 | S_IRUSR | S_IWUSR, debugfsdir, |
453 | &pinfo->norm_offset); | 413 | &pinfo->norm_offset); |
454 | #endif | 414 | #endif |
455 | 415 | ||
@@ -471,7 +431,6 @@ static void rate_control_pid_free(void *priv) | |||
471 | debugfs_remove(de->coeff_p); | 431 | debugfs_remove(de->coeff_p); |
472 | debugfs_remove(de->sampling_period); | 432 | debugfs_remove(de->sampling_period); |
473 | debugfs_remove(de->target); | 433 | debugfs_remove(de->target); |
474 | debugfs_remove(de->dir); | ||
475 | #endif | 434 | #endif |
476 | 435 | ||
477 | kfree(pinfo->rinfo); | 436 | kfree(pinfo->rinfo); |
@@ -482,7 +441,8 @@ static void rate_control_pid_clear(void *priv) | |||
482 | { | 441 | { |
483 | } | 442 | } |
484 | 443 | ||
485 | static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | 444 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, |
445 | gfp_t gfp) | ||
486 | { | 446 | { |
487 | struct rc_pid_sta_info *spinfo; | 447 | struct rc_pid_sta_info *spinfo; |
488 | 448 | ||
@@ -500,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | |||
500 | return spinfo; | 460 | return spinfo; |
501 | } | 461 | } |
502 | 462 | ||
503 | static void rate_control_pid_free_sta(void *priv, void *priv_sta) | 463 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, |
464 | void *priv_sta) | ||
504 | { | 465 | { |
505 | struct rc_pid_sta_info *spinfo = priv_sta; | 466 | kfree(priv_sta); |
506 | kfree(spinfo); | ||
507 | } | 467 | } |
508 | 468 | ||
509 | static struct rate_control_ops mac80211_rcpid = { | 469 | static struct rate_control_ops mac80211_rcpid = { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 92d898b901e9..c489865761bc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -650,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
650 | return result; | 650 | return result; |
651 | } | 651 | } |
652 | 652 | ||
653 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | 653 | static void ap_sta_ps_start(struct sta_info *sta) |
654 | { | 654 | { |
655 | struct ieee80211_sub_if_data *sdata; | 655 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
656 | DECLARE_MAC_BUF(mac); | 656 | DECLARE_MAC_BUF(mac); |
657 | 657 | ||
658 | sdata = sta->sdata; | ||
659 | |||
660 | atomic_inc(&sdata->bss->num_sta_ps); | 658 | atomic_inc(&sdata->bss->num_sta_ps); |
661 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 659 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
662 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 660 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
663 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 661 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
664 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); | 662 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
665 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 663 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
666 | } | 664 | } |
667 | 665 | ||
668 | static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | 666 | static int ap_sta_ps_end(struct sta_info *sta) |
669 | { | 667 | { |
670 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 668 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
669 | struct ieee80211_local *local = sdata->local; | ||
671 | struct sk_buff *skb; | 670 | struct sk_buff *skb; |
672 | int sent = 0; | 671 | int sent = 0; |
673 | struct ieee80211_sub_if_data *sdata; | ||
674 | struct ieee80211_tx_info *info; | 672 | struct ieee80211_tx_info *info; |
675 | DECLARE_MAC_BUF(mac); | 673 | DECLARE_MAC_BUF(mac); |
676 | 674 | ||
677 | sdata = sta->sdata; | ||
678 | |||
679 | atomic_dec(&sdata->bss->num_sta_ps); | 675 | atomic_dec(&sdata->bss->num_sta_ps); |
680 | 676 | ||
681 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 677 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
@@ -685,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
685 | 681 | ||
686 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 682 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
687 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", | 683 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", |
688 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); | 684 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
689 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 685 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
690 | 686 | ||
691 | /* Send all buffered frames to the station */ | 687 | /* Send all buffered frames to the station */ |
@@ -701,7 +697,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
701 | sent++; | 697 | sent++; |
702 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 698 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
703 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " | 699 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " |
704 | "since STA not sleeping anymore\n", dev->name, | 700 | "since STA not sleeping anymore\n", sdata->dev->name, |
705 | print_mac(mac, sta->sta.addr), sta->sta.aid); | 701 | print_mac(mac, sta->sta.addr), sta->sta.aid); |
706 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 702 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
707 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 703 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
@@ -715,7 +711,6 @@ static ieee80211_rx_result debug_noinline | |||
715 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 711 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
716 | { | 712 | { |
717 | struct sta_info *sta = rx->sta; | 713 | struct sta_info *sta = rx->sta; |
718 | struct net_device *dev = rx->dev; | ||
719 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 714 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
720 | 715 | ||
721 | if (!sta) | 716 | if (!sta) |
@@ -757,10 +752,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
757 | * exchange sequence */ | 752 | * exchange sequence */ |
758 | if (test_sta_flags(sta, WLAN_STA_PS) && | 753 | if (test_sta_flags(sta, WLAN_STA_PS) && |
759 | !ieee80211_has_pm(hdr->frame_control)) | 754 | !ieee80211_has_pm(hdr->frame_control)) |
760 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); | 755 | rx->sent_ps_buffered += ap_sta_ps_end(sta); |
761 | else if (!test_sta_flags(sta, WLAN_STA_PS) && | 756 | else if (!test_sta_flags(sta, WLAN_STA_PS) && |
762 | ieee80211_has_pm(hdr->frame_control)) | 757 | ieee80211_has_pm(hdr->frame_control)) |
763 | ap_sta_ps_start(dev, sta); | 758 | ap_sta_ps_start(sta); |
764 | } | 759 | } |
765 | 760 | ||
766 | /* Drop data::nullfunc frames silently, since they are used only to | 761 | /* Drop data::nullfunc frames silently, since they are used only to |
@@ -1112,10 +1107,6 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1112 | 1107 | ||
1113 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1108 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1114 | 1109 | ||
1115 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1116 | hdrlen += ieee80211_get_mesh_hdrlen( | ||
1117 | (struct ieee80211s_hdr *) (skb->data + hdrlen)); | ||
1118 | |||
1119 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | 1110 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet |
1120 | * header | 1111 | * header |
1121 | * IEEE 802.11 address fields: | 1112 | * IEEE 802.11 address fields: |
@@ -1139,6 +1130,15 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1139 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | 1130 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1140 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | 1131 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1141 | return -1; | 1132 | return -1; |
1133 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1134 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) | ||
1135 | (skb->data + hdrlen); | ||
1136 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
1137 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | ||
1138 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | ||
1139 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | ||
1140 | } | ||
1141 | } | ||
1142 | break; | 1142 | break; |
1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): | 1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | 1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
@@ -1398,6 +1398,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1398 | /* illegal frame */ | 1398 | /* illegal frame */ |
1399 | return RX_DROP_MONITOR; | 1399 | return RX_DROP_MONITOR; |
1400 | 1400 | ||
1401 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | ||
1402 | struct ieee80211_sub_if_data *sdata; | ||
1403 | struct mesh_path *mppath; | ||
1404 | |||
1405 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1406 | rcu_read_lock(); | ||
1407 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | ||
1408 | if (!mppath) { | ||
1409 | mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); | ||
1410 | } else { | ||
1411 | spin_lock_bh(&mppath->state_lock); | ||
1412 | mppath->exp_time = jiffies; | ||
1413 | if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) | ||
1414 | memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); | ||
1415 | spin_unlock_bh(&mppath->state_lock); | ||
1416 | } | ||
1417 | rcu_read_unlock(); | ||
1418 | } | ||
1419 | |||
1401 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1420 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) |
1402 | return RX_CONTINUE; | 1421 | return RX_CONTINUE; |
1403 | 1422 | ||
@@ -1538,7 +1557,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1538 | */ | 1557 | */ |
1539 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1558 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1540 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1559 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1541 | return RX_DROP_MONITOR; | 1560 | return RX_CONTINUE; |
1542 | 1561 | ||
1543 | switch (mgmt->u.action.category) { | 1562 | switch (mgmt->u.action.category) { |
1544 | case WLAN_CATEGORY_BACK: | 1563 | case WLAN_CATEGORY_BACK: |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d9774ac2e0f7..9b72d15bc8dc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -93,8 +93,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /* protected by RCU */ | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | 96 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) |
97 | const u8 *addr) | ||
98 | { | 97 | { |
99 | struct sta_info *sta; | 98 | struct sta_info *sta; |
100 | 99 | ||
@@ -107,12 +106,6 @@ static struct sta_info *__sta_info_find(struct ieee80211_local *local, | |||
107 | return sta; | 106 | return sta; |
108 | } | 107 | } |
109 | 108 | ||
110 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) | ||
111 | { | ||
112 | return __sta_info_find(local, addr); | ||
113 | } | ||
114 | EXPORT_SYMBOL(sta_info_get); | ||
115 | |||
116 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 109 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, |
117 | struct net_device *dev) | 110 | struct net_device *dev) |
118 | { | 111 | { |
@@ -146,7 +139,7 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
146 | { | 139 | { |
147 | DECLARE_MAC_BUF(mbuf); | 140 | DECLARE_MAC_BUF(mbuf); |
148 | 141 | ||
149 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | 142 | rate_control_free_sta(sta); |
150 | rate_control_put(sta->rate_ctrl); | 143 | rate_control_put(sta->rate_ctrl); |
151 | 144 | ||
152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 145 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -244,7 +237,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
244 | 237 | ||
245 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 238 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); |
246 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | 239 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
247 | gfp); | 240 | &sta->sta, gfp); |
248 | if (!sta->rate_ctrl_priv) { | 241 | if (!sta->rate_ctrl_priv) { |
249 | rate_control_put(sta->rate_ctrl); | 242 | rate_control_put(sta->rate_ctrl); |
250 | kfree(sta); | 243 | kfree(sta); |
@@ -308,7 +301,7 @@ int sta_info_insert(struct sta_info *sta) | |||
308 | 301 | ||
309 | spin_lock_irqsave(&local->sta_lock, flags); | 302 | spin_lock_irqsave(&local->sta_lock, flags); |
310 | /* check if STA exists already */ | 303 | /* check if STA exists already */ |
311 | if (__sta_info_find(local, sta->sta.addr)) { | 304 | if (sta_info_get(local, sta->sta.addr)) { |
312 | spin_unlock_irqrestore(&local->sta_lock, flags); | 305 | spin_unlock_irqrestore(&local->sta_lock, flags); |
313 | err = -EEXIST; | 306 | err = -EEXIST; |
314 | goto out_free; | 307 | goto out_free; |
@@ -834,7 +827,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
834 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | 827 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, |
835 | const u8 *addr) | 828 | const u8 *addr) |
836 | { | 829 | { |
837 | struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); | 830 | struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); |
838 | 831 | ||
839 | if (!sta) | 832 | if (!sta) |
840 | return NULL; | 833 | return NULL; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index daedfa9e1c63..c3f436964621 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -416,7 +416,7 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
416 | /* | 416 | /* |
417 | * Get a STA info, must have be under RCU read lock. | 417 | * Get a STA info, must have be under RCU read lock. |
418 | */ | 418 | */ |
419 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr); | 419 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); |
420 | /* | 420 | /* |
421 | * Get STA info by index, BROKEN! | 421 | * Get STA info by index, BROKEN! |
422 | */ | 422 | */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 20d683641b42..0cc2e23f082c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
165 | return cpu_to_le16(dur); | 165 | return cpu_to_le16(dur); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int inline is_ieee80211_device(struct net_device *dev, | 168 | static int inline is_ieee80211_device(struct ieee80211_local *local, |
169 | struct net_device *master) | 169 | struct net_device *dev) |
170 | { | 170 | { |
171 | return (wdev_priv(dev->ieee80211_ptr) == | 171 | return local == wdev_priv(dev->ieee80211_ptr); |
172 | wdev_priv(master->ieee80211_ptr)); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | /* tx handlers */ | 174 | /* tx handlers */ |
@@ -447,7 +446,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
447 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 446 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
448 | 447 | ||
449 | if (likely(tx->rate_idx < 0)) { | 448 | if (likely(tx->rate_idx < 0)) { |
450 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | 449 | rate_control_get_rate(tx->sdata, sband, tx->sta, |
450 | tx->skb, &rsel); | ||
451 | if (tx->sta) | 451 | if (tx->sta) |
452 | tx->sta->last_txrate_idx = rsel.rate_idx; | 452 | tx->sta->last_txrate_idx = rsel.rate_idx; |
453 | tx->rate_idx = rsel.rate_idx; | 453 | tx->rate_idx = rsel.rate_idx; |
@@ -1001,14 +1001,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1001 | /* | 1001 | /* |
1002 | * NB: @tx is uninitialised when passed in here | 1002 | * NB: @tx is uninitialised when passed in here |
1003 | */ | 1003 | */ |
1004 | static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1004 | static int ieee80211_tx_prepare(struct ieee80211_local *local, |
1005 | struct sk_buff *skb, | 1005 | struct ieee80211_tx_data *tx, |
1006 | struct net_device *mdev) | 1006 | struct sk_buff *skb) |
1007 | { | 1007 | { |
1008 | struct net_device *dev; | 1008 | struct net_device *dev; |
1009 | 1009 | ||
1010 | dev = dev_get_by_index(&init_net, skb->iif); | 1010 | dev = dev_get_by_index(&init_net, skb->iif); |
1011 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { | 1011 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { |
1012 | dev_put(dev); | 1012 | dev_put(dev); |
1013 | dev = NULL; | 1013 | dev = NULL; |
1014 | } | 1014 | } |
@@ -1258,6 +1258,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, | 1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, |
1259 | struct net_device *dev) | 1259 | struct net_device *dev) |
1260 | { | 1260 | { |
1261 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
1262 | struct ieee80211_local *local = mpriv->local; | ||
1261 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1263 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1262 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1264 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1263 | struct net_device *odev = NULL; | 1265 | struct net_device *odev = NULL; |
@@ -1273,7 +1275,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1273 | 1275 | ||
1274 | if (skb->iif) | 1276 | if (skb->iif) |
1275 | odev = dev_get_by_index(&init_net, skb->iif); | 1277 | odev = dev_get_by_index(&init_net, skb->iif); |
1276 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { | 1278 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { |
1277 | dev_put(odev); | 1279 | dev_put(odev); |
1278 | odev = NULL; | 1280 | odev = NULL; |
1279 | } | 1281 | } |
@@ -1449,8 +1451,8 @@ fail: | |||
1449 | int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1451 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1450 | struct net_device *dev) | 1452 | struct net_device *dev) |
1451 | { | 1453 | { |
1452 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1454 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1453 | struct ieee80211_sub_if_data *sdata; | 1455 | struct ieee80211_local *local = sdata->local; |
1454 | int ret = 1, head_need; | 1456 | int ret = 1, head_need; |
1455 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1457 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1456 | __le16 fc; | 1458 | __le16 fc; |
@@ -1462,7 +1464,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1462 | struct sta_info *sta; | 1464 | struct sta_info *sta; |
1463 | u32 sta_flags = 0; | 1465 | u32 sta_flags = 0; |
1464 | 1466 | ||
1465 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1466 | if (unlikely(skb->len < ETH_HLEN)) { | 1467 | if (unlikely(skb->len < ETH_HLEN)) { |
1467 | ret = 0; | 1468 | ret = 0; |
1468 | goto fail; | 1469 | goto fail; |
@@ -1498,18 +1499,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1498 | #ifdef CONFIG_MAC80211_MESH | 1499 | #ifdef CONFIG_MAC80211_MESH |
1499 | case NL80211_IFTYPE_MESH_POINT: | 1500 | case NL80211_IFTYPE_MESH_POINT: |
1500 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1501 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1501 | /* RA TA DA SA */ | ||
1502 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1503 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1504 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1505 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1506 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1502 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1507 | /* Do not send frames with mesh_ttl == 0 */ | 1503 | /* Do not send frames with mesh_ttl == 0 */ |
1508 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1504 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1509 | ret = 0; | 1505 | ret = 0; |
1510 | goto fail; | 1506 | goto fail; |
1511 | } | 1507 | } |
1512 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | 1508 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); |
1509 | |||
1510 | if (compare_ether_addr(dev->dev_addr, | ||
1511 | skb->data + ETH_ALEN) == 0) { | ||
1512 | /* RA TA DA SA */ | ||
1513 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1514 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1515 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1516 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1517 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
1518 | } else { | ||
1519 | /* packet from other interface */ | ||
1520 | struct mesh_path *mppath; | ||
1521 | |||
1522 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1523 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1524 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | ||
1525 | |||
1526 | if (is_multicast_ether_addr(skb->data)) | ||
1527 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1528 | else { | ||
1529 | rcu_read_lock(); | ||
1530 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1531 | if (mppath) | ||
1532 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | ||
1533 | else | ||
1534 | memset(hdr.addr3, 0xff, ETH_ALEN); | ||
1535 | rcu_read_unlock(); | ||
1536 | } | ||
1537 | |||
1538 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | ||
1539 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | ||
1540 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | ||
1541 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | ||
1542 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1543 | sdata->u.mesh.mesh_seqnum++; | ||
1544 | meshhdrlen = 18; | ||
1545 | } | ||
1513 | hdrlen = 30; | 1546 | hdrlen = 30; |
1514 | break; | 1547 | break; |
1515 | #endif | 1548 | #endif |
@@ -1923,7 +1956,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1923 | skb->do_not_encrypt = 1; | 1956 | skb->do_not_encrypt = 1; |
1924 | 1957 | ||
1925 | info->band = band; | 1958 | info->band = band; |
1926 | rate_control_get_rate(local->mdev, sband, skb, &rsel); | 1959 | rate_control_get_rate(sdata, sband, NULL, skb, &rsel); |
1927 | 1960 | ||
1928 | if (unlikely(rsel.rate_idx < 0)) { | 1961 | if (unlikely(rsel.rate_idx < 0)) { |
1929 | if (net_ratelimit()) { | 1962 | if (net_ratelimit()) { |
@@ -2032,7 +2065,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2032 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2065 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2033 | } | 2066 | } |
2034 | 2067 | ||
2035 | if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) | 2068 | if (!ieee80211_tx_prepare(local, &tx, skb)) |
2036 | break; | 2069 | break; |
2037 | dev_kfree_skb_any(skb); | 2070 | dev_kfree_skb_any(skb); |
2038 | } | 2071 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index a910cd2d0fd1..5cadbeb76a14 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -29,113 +29,11 @@ MODULE_AUTHOR("Johannes Berg"); | |||
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | MODULE_DESCRIPTION("wireless configuration support"); | 30 | MODULE_DESCRIPTION("wireless configuration support"); |
31 | 31 | ||
32 | struct list_head regulatory_requests; | ||
33 | |||
34 | /* Central wireless core regulatory domains, we only need two, | ||
35 | * the current one and a world regulatory domain in case we have no | ||
36 | * information to give us an alpha2 */ | ||
37 | struct ieee80211_regdomain *cfg80211_regdomain; | ||
38 | |||
39 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
40 | const struct ieee80211_regdomain world_regdom = { | ||
41 | .n_reg_rules = 1, | ||
42 | .alpha2 = "00", | ||
43 | .reg_rules = { | ||
44 | REG_RULE(2402, 2472, 40, 6, 20, | ||
45 | NL80211_RRF_PASSIVE_SCAN | | ||
46 | NL80211_RRF_NO_IBSS), | ||
47 | } | ||
48 | }; | ||
49 | |||
50 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
51 | /* All this fucking static junk will be removed soon, so | ||
52 | * don't fucking count on it !@#$ */ | ||
53 | |||
54 | static char *ieee80211_regdom = "US"; | ||
55 | module_param(ieee80211_regdom, charp, 0444); | ||
56 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
57 | |||
58 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
59 | * We make emphasis we are using the exact same frequencies | ||
60 | * as before */ | ||
61 | |||
62 | const struct ieee80211_regdomain us_regdom = { | ||
63 | .n_reg_rules = 6, | ||
64 | .alpha2 = "US", | ||
65 | .reg_rules = { | ||
66 | /* IEEE 802.11b/g, channels 1..11 */ | ||
67 | REG_RULE(2412-20, 2462+20, 40, 6, 27, 0), | ||
68 | /* IEEE 802.11a, channel 36 */ | ||
69 | REG_RULE(5180-20, 5180+20, 40, 6, 23, 0), | ||
70 | /* IEEE 802.11a, channel 40 */ | ||
71 | REG_RULE(5200-20, 5200+20, 40, 6, 23, 0), | ||
72 | /* IEEE 802.11a, channel 44 */ | ||
73 | REG_RULE(5220-20, 5220+20, 40, 6, 23, 0), | ||
74 | /* IEEE 802.11a, channels 48..64 */ | ||
75 | REG_RULE(5240-20, 5320+20, 40, 6, 23, 0), | ||
76 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
77 | REG_RULE(5745-20, 5825+20, 40, 6, 30, 0), | ||
78 | } | ||
79 | }; | ||
80 | |||
81 | const struct ieee80211_regdomain jp_regdom = { | ||
82 | .n_reg_rules = 3, | ||
83 | .alpha2 = "JP", | ||
84 | .reg_rules = { | ||
85 | /* IEEE 802.11b/g, channels 1..14 */ | ||
86 | REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), | ||
87 | /* IEEE 802.11a, channels 34..48 */ | ||
88 | REG_RULE(5170-20, 5240+20, 40, 6, 20, | ||
89 | NL80211_RRF_PASSIVE_SCAN), | ||
90 | /* IEEE 802.11a, channels 52..64 */ | ||
91 | REG_RULE(5260-20, 5320+20, 40, 6, 20, | ||
92 | NL80211_RRF_NO_IBSS | | ||
93 | NL80211_RRF_DFS), | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | const struct ieee80211_regdomain eu_regdom = { | ||
98 | .n_reg_rules = 6, | ||
99 | /* This alpha2 is bogus, we leave it here just for stupid | ||
100 | * backward compatibility */ | ||
101 | .alpha2 = "EU", | ||
102 | .reg_rules = { | ||
103 | /* IEEE 802.11b/g, channels 1..13 */ | ||
104 | REG_RULE(2412-20, 2472+20, 40, 6, 20, 0), | ||
105 | /* IEEE 802.11a, channel 36 */ | ||
106 | REG_RULE(5180-20, 5180+20, 40, 6, 23, | ||
107 | NL80211_RRF_PASSIVE_SCAN), | ||
108 | /* IEEE 802.11a, channel 40 */ | ||
109 | REG_RULE(5200-20, 5200+20, 40, 6, 23, | ||
110 | NL80211_RRF_PASSIVE_SCAN), | ||
111 | /* IEEE 802.11a, channel 44 */ | ||
112 | REG_RULE(5220-20, 5220+20, 40, 6, 23, | ||
113 | NL80211_RRF_PASSIVE_SCAN), | ||
114 | /* IEEE 802.11a, channels 48..64 */ | ||
115 | REG_RULE(5240-20, 5320+20, 40, 6, 20, | ||
116 | NL80211_RRF_NO_IBSS | | ||
117 | NL80211_RRF_DFS), | ||
118 | /* IEEE 802.11a, channels 100..140 */ | ||
119 | REG_RULE(5500-20, 5700+20, 40, 6, 30, | ||
120 | NL80211_RRF_NO_IBSS | | ||
121 | NL80211_RRF_DFS), | ||
122 | } | ||
123 | }; | ||
124 | |||
125 | #endif | ||
126 | |||
127 | struct ieee80211_regdomain *cfg80211_world_regdom = | ||
128 | (struct ieee80211_regdomain *) &world_regdom; | ||
129 | |||
130 | LIST_HEAD(regulatory_requests); | ||
131 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
132 | |||
133 | /* RCU might be appropriate here since we usually | 32 | /* RCU might be appropriate here since we usually |
134 | * only read the list, and that can happen quite | 33 | * only read the list, and that can happen quite |
135 | * often because we need to do it for each command */ | 34 | * often because we need to do it for each command */ |
136 | LIST_HEAD(cfg80211_drv_list); | 35 | LIST_HEAD(cfg80211_drv_list); |
137 | DEFINE_MUTEX(cfg80211_drv_mutex); | 36 | DEFINE_MUTEX(cfg80211_drv_mutex); |
138 | static int wiphy_counter; | ||
139 | 37 | ||
140 | /* for debugfs */ | 38 | /* for debugfs */ |
141 | static struct dentry *ieee80211_debugfs_dir; | 39 | static struct dentry *ieee80211_debugfs_dir; |
@@ -307,6 +205,8 @@ out_unlock: | |||
307 | 205 | ||
308 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | 206 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) |
309 | { | 207 | { |
208 | static int wiphy_counter; | ||
209 | |||
310 | struct cfg80211_registered_device *drv; | 210 | struct cfg80211_registered_device *drv; |
311 | int alloc_size; | 211 | int alloc_size; |
312 | 212 | ||
@@ -323,21 +223,18 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | |||
323 | 223 | ||
324 | mutex_lock(&cfg80211_drv_mutex); | 224 | mutex_lock(&cfg80211_drv_mutex); |
325 | 225 | ||
326 | drv->idx = wiphy_counter; | 226 | drv->idx = wiphy_counter++; |
327 | |||
328 | /* now increase counter for the next device unless | ||
329 | * it has wrapped previously */ | ||
330 | if (wiphy_counter >= 0) | ||
331 | wiphy_counter++; | ||
332 | |||
333 | mutex_unlock(&cfg80211_drv_mutex); | ||
334 | 227 | ||
335 | if (unlikely(drv->idx < 0)) { | 228 | if (unlikely(drv->idx < 0)) { |
229 | wiphy_counter--; | ||
230 | mutex_unlock(&cfg80211_drv_mutex); | ||
336 | /* ugh, wrapped! */ | 231 | /* ugh, wrapped! */ |
337 | kfree(drv); | 232 | kfree(drv); |
338 | return NULL; | 233 | return NULL; |
339 | } | 234 | } |
340 | 235 | ||
236 | mutex_unlock(&cfg80211_drv_mutex); | ||
237 | |||
341 | /* give it a proper name */ | 238 | /* give it a proper name */ |
342 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, | 239 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, |
343 | PHY_NAME "%d", drv->idx); | 240 | PHY_NAME "%d", drv->idx); |
@@ -485,6 +382,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
485 | 382 | ||
486 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); | 383 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); |
487 | 384 | ||
385 | WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED); | ||
386 | |||
488 | switch (state) { | 387 | switch (state) { |
489 | case NETDEV_REGISTER: | 388 | case NETDEV_REGISTER: |
490 | mutex_lock(&rdev->devlist_mtx); | 389 | mutex_lock(&rdev->devlist_mtx); |
@@ -514,34 +413,10 @@ static struct notifier_block cfg80211_netdev_notifier = { | |||
514 | .notifier_call = cfg80211_netdev_notifier_call, | 413 | .notifier_call = cfg80211_netdev_notifier_call, |
515 | }; | 414 | }; |
516 | 415 | ||
517 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
518 | const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
519 | { | ||
520 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
521 | return &us_regdom; | ||
522 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
523 | return &jp_regdom; | ||
524 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
525 | return &eu_regdom; | ||
526 | /* Default, as per the old rules */ | ||
527 | return &us_regdom; | ||
528 | } | ||
529 | #endif | ||
530 | |||
531 | static int cfg80211_init(void) | 416 | static int cfg80211_init(void) |
532 | { | 417 | { |
533 | int err; | 418 | int err; |
534 | 419 | ||
535 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
536 | cfg80211_regdomain = | ||
537 | (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); | ||
538 | /* Used during reset_regdomains_static() */ | ||
539 | cfg80211_world_regdom = cfg80211_regdomain; | ||
540 | #else | ||
541 | cfg80211_regdomain = | ||
542 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
543 | #endif | ||
544 | |||
545 | err = wiphy_sysfs_init(); | 420 | err = wiphy_sysfs_init(); |
546 | if (err) | 421 | if (err) |
547 | goto out_fail_sysfs; | 422 | goto out_fail_sysfs; |
@@ -560,25 +435,6 @@ static int cfg80211_init(void) | |||
560 | if (err) | 435 | if (err) |
561 | goto out_fail_reg; | 436 | goto out_fail_reg; |
562 | 437 | ||
563 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
564 | printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); | ||
565 | print_regdomain_info(cfg80211_regdomain); | ||
566 | /* The old code still requests for a new regdomain and if | ||
567 | * you have CRDA you get it updated, otherwise you get | ||
568 | * stuck with the static values. We ignore "EU" code as | ||
569 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
570 | if (ieee80211_regdom[0] != 'E' && | ||
571 | ieee80211_regdom[1] != 'U') | ||
572 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
573 | ieee80211_regdom, NULL); | ||
574 | #else | ||
575 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
576 | if (err) | ||
577 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
578 | "unable to update world regulatory domain, " | ||
579 | "using static definition\n"); | ||
580 | #endif | ||
581 | |||
582 | return 0; | 438 | return 0; |
583 | 439 | ||
584 | out_fail_reg: | 440 | out_fail_reg: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1221d726ed50..572793c8c7ab 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -299,7 +299,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
299 | 299 | ||
300 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 300 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
301 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); | 301 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); |
302 | /* TODO: interface type */ | 302 | NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); |
303 | return genlmsg_end(msg, hdr); | 303 | return genlmsg_end(msg, hdr); |
304 | 304 | ||
305 | nla_put_failure: | 305 | nla_put_failure: |
@@ -418,41 +418,56 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
418 | int err, ifindex; | 418 | int err, ifindex; |
419 | enum nl80211_iftype type; | 419 | enum nl80211_iftype type; |
420 | struct net_device *dev; | 420 | struct net_device *dev; |
421 | u32 flags; | 421 | u32 _flags, *flags = NULL; |
422 | 422 | ||
423 | memset(¶ms, 0, sizeof(params)); | 423 | memset(¶ms, 0, sizeof(params)); |
424 | 424 | ||
425 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | ||
426 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | ||
427 | if (type > NL80211_IFTYPE_MAX) | ||
428 | return -EINVAL; | ||
429 | } else | ||
430 | return -EINVAL; | ||
431 | |||
432 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 425 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
433 | if (err) | 426 | if (err) |
434 | return err; | 427 | return err; |
435 | ifindex = dev->ifindex; | 428 | ifindex = dev->ifindex; |
429 | type = dev->ieee80211_ptr->iftype; | ||
436 | dev_put(dev); | 430 | dev_put(dev); |
437 | 431 | ||
432 | err = -EINVAL; | ||
433 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | ||
434 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | ||
435 | if (type > NL80211_IFTYPE_MAX) | ||
436 | goto unlock; | ||
437 | } | ||
438 | |||
438 | if (!drv->ops->change_virtual_intf || | 439 | if (!drv->ops->change_virtual_intf || |
439 | !(drv->wiphy.interface_modes & (1 << type))) { | 440 | !(drv->wiphy.interface_modes & (1 << type))) { |
440 | err = -EOPNOTSUPP; | 441 | err = -EOPNOTSUPP; |
441 | goto unlock; | 442 | goto unlock; |
442 | } | 443 | } |
443 | 444 | ||
444 | if (type == NL80211_IFTYPE_MESH_POINT && | 445 | if (info->attrs[NL80211_ATTR_MESH_ID]) { |
445 | info->attrs[NL80211_ATTR_MESH_ID]) { | 446 | if (type != NL80211_IFTYPE_MESH_POINT) { |
447 | err = -EINVAL; | ||
448 | goto unlock; | ||
449 | } | ||
446 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 450 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
447 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 451 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
448 | } | 452 | } |
449 | 453 | ||
454 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | ||
455 | if (type != NL80211_IFTYPE_MONITOR) { | ||
456 | err = -EINVAL; | ||
457 | goto unlock; | ||
458 | } | ||
459 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | ||
460 | &_flags); | ||
461 | if (!err) | ||
462 | flags = &_flags; | ||
463 | } | ||
450 | rtnl_lock(); | 464 | rtnl_lock(); |
451 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | ||
452 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | ||
453 | &flags); | ||
454 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, | 465 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, |
455 | type, err ? NULL : &flags, ¶ms); | 466 | type, flags, ¶ms); |
467 | |||
468 | dev = __dev_get_by_index(&init_net, ifindex); | ||
469 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); | ||
470 | |||
456 | rtnl_unlock(); | 471 | rtnl_unlock(); |
457 | 472 | ||
458 | unlock: | 473 | unlock: |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 592b2e391d42..626dbb688499 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -42,6 +42,18 @@ | |||
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "reg.h" | 43 | #include "reg.h" |
44 | 44 | ||
45 | /* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ | ||
46 | struct regulatory_request { | ||
47 | struct list_head list; | ||
48 | struct wiphy *wiphy; | ||
49 | int granted; | ||
50 | enum reg_set_by initiator; | ||
51 | char alpha2[2]; | ||
52 | }; | ||
53 | |||
54 | static LIST_HEAD(regulatory_requests); | ||
55 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
56 | |||
45 | /* To trigger userspace events */ | 57 | /* To trigger userspace events */ |
46 | static struct platform_device *reg_pdev; | 58 | static struct platform_device *reg_pdev; |
47 | 59 | ||
@@ -51,7 +63,156 @@ static u32 supported_bandwidths[] = { | |||
51 | MHZ_TO_KHZ(20), | 63 | MHZ_TO_KHZ(20), |
52 | }; | 64 | }; |
53 | 65 | ||
54 | bool is_world_regdom(char *alpha2) | 66 | static struct list_head regulatory_requests; |
67 | |||
68 | /* Central wireless core regulatory domains, we only need two, | ||
69 | * the current one and a world regulatory domain in case we have no | ||
70 | * information to give us an alpha2 */ | ||
71 | static const struct ieee80211_regdomain *cfg80211_regdomain; | ||
72 | |||
73 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
74 | static const struct ieee80211_regdomain world_regdom = { | ||
75 | .n_reg_rules = 1, | ||
76 | .alpha2 = "00", | ||
77 | .reg_rules = { | ||
78 | REG_RULE(2412-10, 2462+10, 40, 6, 20, | ||
79 | NL80211_RRF_PASSIVE_SCAN | | ||
80 | NL80211_RRF_NO_IBSS), | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static const struct ieee80211_regdomain *cfg80211_world_regdom = | ||
85 | &world_regdom; | ||
86 | |||
87 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
88 | static char *ieee80211_regdom = "US"; | ||
89 | module_param(ieee80211_regdom, charp, 0444); | ||
90 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
91 | |||
92 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
93 | * We make emphasis we are using the exact same frequencies | ||
94 | * as before */ | ||
95 | |||
96 | static const struct ieee80211_regdomain us_regdom = { | ||
97 | .n_reg_rules = 6, | ||
98 | .alpha2 = "US", | ||
99 | .reg_rules = { | ||
100 | /* IEEE 802.11b/g, channels 1..11 */ | ||
101 | REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), | ||
102 | /* IEEE 802.11a, channel 36 */ | ||
103 | REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), | ||
104 | /* IEEE 802.11a, channel 40 */ | ||
105 | REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), | ||
106 | /* IEEE 802.11a, channel 44 */ | ||
107 | REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), | ||
108 | /* IEEE 802.11a, channels 48..64 */ | ||
109 | REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), | ||
110 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
111 | REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | static const struct ieee80211_regdomain jp_regdom = { | ||
116 | .n_reg_rules = 3, | ||
117 | .alpha2 = "JP", | ||
118 | .reg_rules = { | ||
119 | /* IEEE 802.11b/g, channels 1..14 */ | ||
120 | REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), | ||
121 | /* IEEE 802.11a, channels 34..48 */ | ||
122 | REG_RULE(5170-10, 5240+10, 40, 6, 20, | ||
123 | NL80211_RRF_PASSIVE_SCAN), | ||
124 | /* IEEE 802.11a, channels 52..64 */ | ||
125 | REG_RULE(5260-10, 5320+10, 40, 6, 20, | ||
126 | NL80211_RRF_NO_IBSS | | ||
127 | NL80211_RRF_DFS), | ||
128 | } | ||
129 | }; | ||
130 | |||
131 | static const struct ieee80211_regdomain eu_regdom = { | ||
132 | .n_reg_rules = 6, | ||
133 | /* This alpha2 is bogus, we leave it here just for stupid | ||
134 | * backward compatibility */ | ||
135 | .alpha2 = "EU", | ||
136 | .reg_rules = { | ||
137 | /* IEEE 802.11b/g, channels 1..13 */ | ||
138 | REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), | ||
139 | /* IEEE 802.11a, channel 36 */ | ||
140 | REG_RULE(5180-10, 5180+10, 40, 6, 23, | ||
141 | NL80211_RRF_PASSIVE_SCAN), | ||
142 | /* IEEE 802.11a, channel 40 */ | ||
143 | REG_RULE(5200-10, 5200+10, 40, 6, 23, | ||
144 | NL80211_RRF_PASSIVE_SCAN), | ||
145 | /* IEEE 802.11a, channel 44 */ | ||
146 | REG_RULE(5220-10, 5220+10, 40, 6, 23, | ||
147 | NL80211_RRF_PASSIVE_SCAN), | ||
148 | /* IEEE 802.11a, channels 48..64 */ | ||
149 | REG_RULE(5240-10, 5320+10, 40, 6, 20, | ||
150 | NL80211_RRF_NO_IBSS | | ||
151 | NL80211_RRF_DFS), | ||
152 | /* IEEE 802.11a, channels 100..140 */ | ||
153 | REG_RULE(5500-10, 5700+10, 40, 6, 30, | ||
154 | NL80211_RRF_NO_IBSS | | ||
155 | NL80211_RRF_DFS), | ||
156 | } | ||
157 | }; | ||
158 | |||
159 | static const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
160 | { | ||
161 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
162 | return &us_regdom; | ||
163 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
164 | return &jp_regdom; | ||
165 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
166 | return &eu_regdom; | ||
167 | /* Default, as per the old rules */ | ||
168 | return &us_regdom; | ||
169 | } | ||
170 | |||
171 | static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
172 | { | ||
173 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
174 | return true; | ||
175 | return false; | ||
176 | } | ||
177 | #else | ||
178 | static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
179 | { | ||
180 | return false; | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | static void reset_regdomains(void) | ||
185 | { | ||
186 | /* avoid freeing static information or freeing something twice */ | ||
187 | if (cfg80211_regdomain == cfg80211_world_regdom) | ||
188 | cfg80211_regdomain = NULL; | ||
189 | if (cfg80211_world_regdom == &world_regdom) | ||
190 | cfg80211_world_regdom = NULL; | ||
191 | if (cfg80211_regdomain == &world_regdom) | ||
192 | cfg80211_regdomain = NULL; | ||
193 | if (is_old_static_regdom(cfg80211_regdomain)) | ||
194 | cfg80211_regdomain = NULL; | ||
195 | |||
196 | kfree(cfg80211_regdomain); | ||
197 | kfree(cfg80211_world_regdom); | ||
198 | |||
199 | cfg80211_world_regdom = &world_regdom; | ||
200 | cfg80211_regdomain = NULL; | ||
201 | } | ||
202 | |||
203 | /* Dynamic world regulatory domain requested by the wireless | ||
204 | * core upon initialization */ | ||
205 | static void update_world_regdomain(const struct ieee80211_regdomain *rd) | ||
206 | { | ||
207 | BUG_ON(list_empty(®ulatory_requests)); | ||
208 | |||
209 | reset_regdomains(); | ||
210 | |||
211 | cfg80211_world_regdom = rd; | ||
212 | cfg80211_regdomain = rd; | ||
213 | } | ||
214 | |||
215 | bool is_world_regdom(const char *alpha2) | ||
55 | { | 216 | { |
56 | if (!alpha2) | 217 | if (!alpha2) |
57 | return false; | 218 | return false; |
@@ -60,7 +221,7 @@ bool is_world_regdom(char *alpha2) | |||
60 | return false; | 221 | return false; |
61 | } | 222 | } |
62 | 223 | ||
63 | static bool is_alpha2_set(char *alpha2) | 224 | static bool is_alpha2_set(const char *alpha2) |
64 | { | 225 | { |
65 | if (!alpha2) | 226 | if (!alpha2) |
66 | return false; | 227 | return false; |
@@ -77,7 +238,7 @@ static bool is_alpha_upper(char letter) | |||
77 | return false; | 238 | return false; |
78 | } | 239 | } |
79 | 240 | ||
80 | static bool is_unknown_alpha2(char *alpha2) | 241 | static bool is_unknown_alpha2(const char *alpha2) |
81 | { | 242 | { |
82 | if (!alpha2) | 243 | if (!alpha2) |
83 | return false; | 244 | return false; |
@@ -88,7 +249,7 @@ static bool is_unknown_alpha2(char *alpha2) | |||
88 | return false; | 249 | return false; |
89 | } | 250 | } |
90 | 251 | ||
91 | static bool is_an_alpha2(char *alpha2) | 252 | static bool is_an_alpha2(const char *alpha2) |
92 | { | 253 | { |
93 | if (!alpha2) | 254 | if (!alpha2) |
94 | return false; | 255 | return false; |
@@ -97,7 +258,7 @@ static bool is_an_alpha2(char *alpha2) | |||
97 | return false; | 258 | return false; |
98 | } | 259 | } |
99 | 260 | ||
100 | static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | 261 | static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) |
101 | { | 262 | { |
102 | if (!alpha2_x || !alpha2_y) | 263 | if (!alpha2_x || !alpha2_y) |
103 | return false; | 264 | return false; |
@@ -107,7 +268,7 @@ static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | |||
107 | return false; | 268 | return false; |
108 | } | 269 | } |
109 | 270 | ||
110 | static bool regdom_changed(char *alpha2) | 271 | static bool regdom_changed(const char *alpha2) |
111 | { | 272 | { |
112 | if (!cfg80211_regdomain) | 273 | if (!cfg80211_regdomain) |
113 | return true; | 274 | return true; |
@@ -130,12 +291,8 @@ static int call_crda(const char *alpha2) | |||
130 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", | 291 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", |
131 | alpha2[0], alpha2[1]); | 292 | alpha2[0], alpha2[1]); |
132 | else | 293 | else |
133 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
134 | return -EINVAL; | ||
135 | #else | ||
136 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " | 294 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " |
137 | "regulatory domain\n"); | 295 | "regulatory domain\n"); |
138 | #endif | ||
139 | 296 | ||
140 | country_env[8] = alpha2[0]; | 297 | country_env[8] = alpha2[0]; |
141 | country_env[9] = alpha2[1]; | 298 | country_env[9] = alpha2[1]; |
@@ -238,7 +395,7 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
238 | } | 395 | } |
239 | } | 396 | } |
240 | 397 | ||
241 | static bool __reg_is_valid_request(char *alpha2, | 398 | static bool __reg_is_valid_request(const char *alpha2, |
242 | struct regulatory_request **request) | 399 | struct regulatory_request **request) |
243 | { | 400 | { |
244 | struct regulatory_request *req; | 401 | struct regulatory_request *req; |
@@ -254,16 +411,16 @@ static bool __reg_is_valid_request(char *alpha2, | |||
254 | } | 411 | } |
255 | 412 | ||
256 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ | 413 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ |
257 | bool reg_is_valid_request(char *alpha2) | 414 | bool reg_is_valid_request(const char *alpha2) |
258 | { | 415 | { |
259 | struct regulatory_request *request = NULL; | 416 | struct regulatory_request *request = NULL; |
260 | return __reg_is_valid_request(alpha2, &request); | 417 | return __reg_is_valid_request(alpha2, &request); |
261 | } | 418 | } |
262 | 419 | ||
263 | /* Sanity check on a regulatory rule */ | 420 | /* Sanity check on a regulatory rule */ |
264 | static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | 421 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) |
265 | { | 422 | { |
266 | struct ieee80211_freq_range *freq_range = &rule->freq_range; | 423 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; |
267 | u32 freq_diff; | 424 | u32 freq_diff; |
268 | 425 | ||
269 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) | 426 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) |
@@ -280,9 +437,9 @@ static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | |||
280 | return true; | 437 | return true; |
281 | } | 438 | } |
282 | 439 | ||
283 | static bool is_valid_rd(struct ieee80211_regdomain *rd) | 440 | static bool is_valid_rd(const struct ieee80211_regdomain *rd) |
284 | { | 441 | { |
285 | struct ieee80211_reg_rule *reg_rule = NULL; | 442 | const struct ieee80211_reg_rule *reg_rule = NULL; |
286 | unsigned int i; | 443 | unsigned int i; |
287 | 444 | ||
288 | if (!rd->n_reg_rules) | 445 | if (!rd->n_reg_rules) |
@@ -494,12 +651,12 @@ unlock_and_exit: | |||
494 | EXPORT_SYMBOL(regulatory_hint); | 651 | EXPORT_SYMBOL(regulatory_hint); |
495 | 652 | ||
496 | 653 | ||
497 | static void print_rd_rules(struct ieee80211_regdomain *rd) | 654 | static void print_rd_rules(const struct ieee80211_regdomain *rd) |
498 | { | 655 | { |
499 | unsigned int i; | 656 | unsigned int i; |
500 | struct ieee80211_reg_rule *reg_rule = NULL; | 657 | const struct ieee80211_reg_rule *reg_rule = NULL; |
501 | struct ieee80211_freq_range *freq_range = NULL; | 658 | const struct ieee80211_freq_range *freq_range = NULL; |
502 | struct ieee80211_power_rule *power_rule = NULL; | 659 | const struct ieee80211_power_rule *power_rule = NULL; |
503 | 660 | ||
504 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " | 661 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " |
505 | "(max_antenna_gain, max_eirp)\n"); | 662 | "(max_antenna_gain, max_eirp)\n"); |
@@ -529,7 +686,7 @@ static void print_rd_rules(struct ieee80211_regdomain *rd) | |||
529 | } | 686 | } |
530 | } | 687 | } |
531 | 688 | ||
532 | static void print_regdomain(struct ieee80211_regdomain *rd) | 689 | static void print_regdomain(const struct ieee80211_regdomain *rd) |
533 | { | 690 | { |
534 | 691 | ||
535 | if (is_world_regdom(rd->alpha2)) | 692 | if (is_world_regdom(rd->alpha2)) |
@@ -548,85 +705,25 @@ static void print_regdomain(struct ieee80211_regdomain *rd) | |||
548 | print_rd_rules(rd); | 705 | print_rd_rules(rd); |
549 | } | 706 | } |
550 | 707 | ||
551 | void print_regdomain_info(struct ieee80211_regdomain *rd) | 708 | void print_regdomain_info(const struct ieee80211_regdomain *rd) |
552 | { | 709 | { |
553 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", | 710 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", |
554 | rd->alpha2[0], rd->alpha2[1]); | 711 | rd->alpha2[0], rd->alpha2[1]); |
555 | print_rd_rules(rd); | 712 | print_rd_rules(rd); |
556 | } | 713 | } |
557 | 714 | ||
558 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 715 | static int __set_regdom(const struct ieee80211_regdomain *rd) |
559 | |||
560 | static bool is_old_static_regdom(struct ieee80211_regdomain *rd) | ||
561 | { | ||
562 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
563 | return true; | ||
564 | return false; | ||
565 | } | ||
566 | |||
567 | /* The old crap never deals with a world regulatory domain, it only | ||
568 | * deals with the static regulatory domain passed and if possible | ||
569 | * an updated "US" or "JP" regulatory domain. We do however store the | ||
570 | * old static regulatory domain in cfg80211_world_regdom for convenience | ||
571 | * of use here */ | ||
572 | static void reset_regdomains_static(void) | ||
573 | { | ||
574 | if (!is_old_static_regdom(cfg80211_regdomain)) | ||
575 | kfree(cfg80211_regdomain); | ||
576 | /* This is setting the regdom to the old static regdom */ | ||
577 | cfg80211_regdomain = | ||
578 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
579 | } | ||
580 | #else | ||
581 | static void reset_regdomains(void) | ||
582 | { | ||
583 | if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { | ||
584 | if (cfg80211_world_regdom == cfg80211_regdomain) { | ||
585 | kfree(cfg80211_regdomain); | ||
586 | } else { | ||
587 | kfree(cfg80211_world_regdom); | ||
588 | kfree(cfg80211_regdomain); | ||
589 | } | ||
590 | } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) | ||
591 | kfree(cfg80211_regdomain); | ||
592 | |||
593 | cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; | ||
594 | cfg80211_regdomain = NULL; | ||
595 | } | ||
596 | |||
597 | /* Dynamic world regulatory domain requested by the wireless | ||
598 | * core upon initialization */ | ||
599 | static void update_world_regdomain(struct ieee80211_regdomain *rd) | ||
600 | { | ||
601 | BUG_ON(list_empty(®ulatory_requests)); | ||
602 | |||
603 | reset_regdomains(); | ||
604 | |||
605 | cfg80211_world_regdom = rd; | ||
606 | cfg80211_regdomain = rd; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | static int __set_regdom(struct ieee80211_regdomain *rd) | ||
611 | { | 716 | { |
612 | struct regulatory_request *request = NULL; | 717 | struct regulatory_request *request = NULL; |
613 | 718 | ||
614 | /* Some basic sanity checks first */ | 719 | /* Some basic sanity checks first */ |
615 | 720 | ||
616 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
617 | /* We ignore the world regdom with the old static regdomains setup | ||
618 | * as there is no point to it with satic regulatory definitions :( | ||
619 | * Don't worry this shit will be removed soon... */ | ||
620 | if (is_world_regdom(rd->alpha2)) | ||
621 | return -EINVAL; | ||
622 | #else | ||
623 | if (is_world_regdom(rd->alpha2)) { | 721 | if (is_world_regdom(rd->alpha2)) { |
624 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 722 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
625 | return -EINVAL; | 723 | return -EINVAL; |
626 | update_world_regdomain(rd); | 724 | update_world_regdomain(rd); |
627 | return 0; | 725 | return 0; |
628 | } | 726 | } |
629 | #endif | ||
630 | 727 | ||
631 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && | 728 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && |
632 | !is_unknown_alpha2(rd->alpha2)) | 729 | !is_unknown_alpha2(rd->alpha2)) |
@@ -635,15 +732,10 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
635 | if (list_empty(®ulatory_requests)) | 732 | if (list_empty(®ulatory_requests)) |
636 | return -EINVAL; | 733 | return -EINVAL; |
637 | 734 | ||
638 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 735 | /* allow overriding the static definitions if CRDA is present */ |
639 | /* Static "US" and "JP" will be overridden, but just once */ | ||
640 | if (!is_old_static_regdom(cfg80211_regdomain) && | 736 | if (!is_old_static_regdom(cfg80211_regdomain) && |
641 | !regdom_changed(rd->alpha2)) | 737 | !regdom_changed(rd->alpha2)) |
642 | return -EINVAL; | ||
643 | #else | ||
644 | if (!regdom_changed(rd->alpha2)) | ||
645 | return -EINVAL; | 738 | return -EINVAL; |
646 | #endif | ||
647 | 739 | ||
648 | /* Now lets set the regulatory domain, update all driver channels | 740 | /* Now lets set the regulatory domain, update all driver channels |
649 | * and finally inform them of what we have done, in case they want | 741 | * and finally inform them of what we have done, in case they want |
@@ -653,11 +745,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
653 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 745 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
654 | return -EINVAL; | 746 | return -EINVAL; |
655 | 747 | ||
656 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
657 | reset_regdomains_static(); | ||
658 | #else | ||
659 | reset_regdomains(); | 748 | reset_regdomains(); |
660 | #endif | ||
661 | 749 | ||
662 | /* Country IE parsing coming soon */ | 750 | /* Country IE parsing coming soon */ |
663 | switch (request->initiator) { | 751 | switch (request->initiator) { |
@@ -689,7 +777,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
689 | * multiple drivers can be ironed out later. Caller must've already | 777 | * multiple drivers can be ironed out later. Caller must've already |
690 | * kmalloc'd the rd structure. If this calls fails you should kfree() | 778 | * kmalloc'd the rd structure. If this calls fails you should kfree() |
691 | * the passed rd. Caller must hold cfg80211_drv_mutex */ | 779 | * the passed rd. Caller must hold cfg80211_drv_mutex */ |
692 | int set_regdom(struct ieee80211_regdomain *rd) | 780 | int set_regdom(const struct ieee80211_regdomain *rd) |
693 | { | 781 | { |
694 | struct regulatory_request *this_request = NULL, *prev_request = NULL; | 782 | struct regulatory_request *this_request = NULL, *prev_request = NULL; |
695 | int r; | 783 | int r; |
@@ -735,25 +823,50 @@ int set_regdom(struct ieee80211_regdomain *rd) | |||
735 | 823 | ||
736 | int regulatory_init(void) | 824 | int regulatory_init(void) |
737 | { | 825 | { |
826 | int err; | ||
827 | |||
738 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); | 828 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); |
739 | if (IS_ERR(reg_pdev)) | 829 | if (IS_ERR(reg_pdev)) |
740 | return PTR_ERR(reg_pdev); | 830 | return PTR_ERR(reg_pdev); |
831 | |||
832 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
833 | cfg80211_regdomain = static_regdom(ieee80211_regdom); | ||
834 | |||
835 | printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); | ||
836 | print_regdomain_info(cfg80211_regdomain); | ||
837 | /* The old code still requests for a new regdomain and if | ||
838 | * you have CRDA you get it updated, otherwise you get | ||
839 | * stuck with the static values. We ignore "EU" code as | ||
840 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
841 | if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U') | ||
842 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
843 | ieee80211_regdom, NULL); | ||
844 | #else | ||
845 | cfg80211_regdomain = cfg80211_world_regdom; | ||
846 | |||
847 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
848 | if (err) | ||
849 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
850 | "unable to update world regulatory domain, " | ||
851 | "using static definition\n"); | ||
852 | #endif | ||
853 | |||
741 | return 0; | 854 | return 0; |
742 | } | 855 | } |
743 | 856 | ||
744 | void regulatory_exit(void) | 857 | void regulatory_exit(void) |
745 | { | 858 | { |
746 | struct regulatory_request *req, *req_tmp; | 859 | struct regulatory_request *req, *req_tmp; |
860 | |||
747 | mutex_lock(&cfg80211_drv_mutex); | 861 | mutex_lock(&cfg80211_drv_mutex); |
748 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 862 | |
749 | reset_regdomains_static(); | ||
750 | #else | ||
751 | reset_regdomains(); | 863 | reset_regdomains(); |
752 | #endif | 864 | |
753 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { | 865 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { |
754 | list_del(&req->list); | 866 | list_del(&req->list); |
755 | kfree(req); | 867 | kfree(req); |
756 | } | 868 | } |
757 | platform_device_unregister(reg_pdev); | 869 | platform_device_unregister(reg_pdev); |
870 | |||
758 | mutex_unlock(&cfg80211_drv_mutex); | 871 | mutex_unlock(&cfg80211_drv_mutex); |
759 | } | 872 | } |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index d75fd0232972..a33362872f3c 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -1,44 +1,13 @@ | |||
1 | #ifndef __NET_WIRELESS_REG_H | 1 | #ifndef __NET_WIRELESS_REG_H |
2 | #define __NET_WIRELESS_REG_H | 2 | #define __NET_WIRELESS_REG_H |
3 | 3 | ||
4 | extern const struct ieee80211_regdomain world_regdom; | 4 | extern struct mutex cfg80211_reg_mutex; |
5 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 5 | bool is_world_regdom(const char *alpha2); |
6 | extern const struct ieee80211_regdomain us_regdom; | 6 | bool reg_is_valid_request(const char *alpha2); |
7 | extern const struct ieee80211_regdomain jp_regdom; | ||
8 | extern const struct ieee80211_regdomain eu_regdom; | ||
9 | #endif | ||
10 | |||
11 | extern struct ieee80211_regdomain *cfg80211_regdomain; | ||
12 | extern struct ieee80211_regdomain *cfg80211_world_regdom; | ||
13 | extern struct list_head regulatory_requests; | ||
14 | |||
15 | struct regdom_last_setby { | ||
16 | struct wiphy *wiphy; | ||
17 | u8 initiator; | ||
18 | }; | ||
19 | |||
20 | /* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ | ||
21 | struct regulatory_request { | ||
22 | struct list_head list; | ||
23 | struct wiphy *wiphy; | ||
24 | int granted; | ||
25 | enum reg_set_by initiator; | ||
26 | char alpha2[2]; | ||
27 | }; | ||
28 | |||
29 | bool is_world_regdom(char *alpha2); | ||
30 | bool reg_is_valid_request(char *alpha2); | ||
31 | |||
32 | int set_regdom(struct ieee80211_regdomain *rd); | ||
33 | int __regulatory_hint_alpha2(struct wiphy *wiphy, enum reg_set_by set_by, | ||
34 | const char *alpha2); | ||
35 | 7 | ||
36 | int regulatory_init(void); | 8 | int regulatory_init(void); |
37 | void regulatory_exit(void); | 9 | void regulatory_exit(void); |
38 | 10 | ||
39 | void print_regdomain_info(struct ieee80211_regdomain *); | 11 | int set_regdom(const struct ieee80211_regdomain *rd); |
40 | |||
41 | /* If a char is A-Z */ | ||
42 | #define IS_ALPHA(letter) (letter >= 65 && letter <= 90) | ||
43 | 12 | ||
44 | #endif /* __NET_WIRELESS_REG_H */ | 13 | #endif /* __NET_WIRELESS_REG_H */ |