aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c20
-rw-r--r--net/wireless/ethtool.c33
-rw-r--r--net/wireless/nl80211.c62
-rw-r--r--net/wireless/reg.c49
-rw-r--r--net/wireless/reg.h1
-rw-r--r--net/wireless/scan.c31
-rw-r--r--net/wireless/util.c47
-rw-r--r--net/wireless/wext-compat.c9
8 files changed, 177 insertions, 75 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index e9a5f8ca4c27..fe01de29bfe8 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -718,13 +718,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
718 wdev->ps = false; 718 wdev->ps = false;
719 /* allow mac80211 to determine the timeout */ 719 /* allow mac80211 to determine the timeout */
720 wdev->ps_timeout = -1; 720 wdev->ps_timeout = -1;
721 if (rdev->ops->set_power_mgmt)
722 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
723 wdev->ps,
724 wdev->ps_timeout)) {
725 /* assume this means it's off */
726 wdev->ps = false;
727 }
728 721
729 if (!dev->ethtool_ops) 722 if (!dev->ethtool_ops)
730 dev->ethtool_ops = &cfg80211_ethtool_ops; 723 dev->ethtool_ops = &cfg80211_ethtool_ops;
@@ -813,6 +806,19 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
813 rdev->opencount++; 806 rdev->opencount++;
814 mutex_unlock(&rdev->devlist_mtx); 807 mutex_unlock(&rdev->devlist_mtx);
815 cfg80211_unlock_rdev(rdev); 808 cfg80211_unlock_rdev(rdev);
809
810 /*
811 * Configure power management to the driver here so that its
812 * correctly set also after interface type changes etc.
813 */
814 if (wdev->iftype == NL80211_IFTYPE_STATION &&
815 rdev->ops->set_power_mgmt)
816 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
817 wdev->ps,
818 wdev->ps_timeout)) {
819 /* assume this means it's off */
820 wdev->ps = false;
821 }
816 break; 822 break;
817 case NETDEV_UNREGISTER: 823 case NETDEV_UNREGISTER:
818 /* 824 /*
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c
index ca4c825be93d..9bde4d1d3e9b 100644
--- a/net/wireless/ethtool.c
+++ b/net/wireless/ethtool.c
@@ -1,5 +1,6 @@
1#include <linux/utsname.h> 1#include <linux/utsname.h>
2#include <net/cfg80211.h> 2#include <net/cfg80211.h>
3#include "core.h"
3#include "ethtool.h" 4#include "ethtool.h"
4 5
5static void cfg80211_get_drvinfo(struct net_device *dev, 6static void cfg80211_get_drvinfo(struct net_device *dev,
@@ -37,9 +38,41 @@ static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs,
37 regs->len = 0; 38 regs->len = 0;
38} 39}
39 40
41static void cfg80211_get_ringparam(struct net_device *dev,
42 struct ethtool_ringparam *rp)
43{
44 struct wireless_dev *wdev = dev->ieee80211_ptr;
45 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
46
47 memset(rp, 0, sizeof(*rp));
48
49 if (rdev->ops->get_ringparam)
50 rdev->ops->get_ringparam(wdev->wiphy,
51 &rp->tx_pending, &rp->tx_max_pending,
52 &rp->rx_pending, &rp->rx_max_pending);
53}
54
55static int cfg80211_set_ringparam(struct net_device *dev,
56 struct ethtool_ringparam *rp)
57{
58 struct wireless_dev *wdev = dev->ieee80211_ptr;
59 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
60
61 if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
62 return -EINVAL;
63
64 if (rdev->ops->set_ringparam)
65 return rdev->ops->set_ringparam(wdev->wiphy,
66 rp->tx_pending, rp->rx_pending);
67
68 return -ENOTSUPP;
69}
70
40const struct ethtool_ops cfg80211_ethtool_ops = { 71const struct ethtool_ops cfg80211_ethtool_ops = {
41 .get_drvinfo = cfg80211_get_drvinfo, 72 .get_drvinfo = cfg80211_get_drvinfo,
42 .get_regs_len = cfg80211_get_regs_len, 73 .get_regs_len = cfg80211_get_regs_len,
43 .get_regs = cfg80211_get_regs, 74 .get_regs = cfg80211_get_regs,
44 .get_link = ethtool_op_get_link, 75 .get_link = ethtool_op_get_link,
76 .get_ringparam = cfg80211_get_ringparam,
77 .set_ringparam = cfg80211_set_ringparam,
45}; 78};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9b62710891a2..4ebce4284e9d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct genl_info *info,
1968 return 0; 1968 return 0;
1969} 1969}
1970 1970
1971static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
1972 int attr)
1973{
1974 struct nlattr *rate;
1975 u16 bitrate;
1976
1977 rate = nla_nest_start(msg, attr);
1978 if (!rate)
1979 goto nla_put_failure;
1980
1981 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
1982 bitrate = cfg80211_calculate_bitrate(info);
1983 if (bitrate > 0)
1984 NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
1985
1986 if (info->flags & RATE_INFO_FLAGS_MCS)
1987 NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs);
1988 if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
1989 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
1990 if (info->flags & RATE_INFO_FLAGS_SHORT_GI)
1991 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
1992
1993 nla_nest_end(msg, rate);
1994 return true;
1995
1996nla_put_failure:
1997 return false;
1998}
1999
1971static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, 2000static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1972 int flags, struct net_device *dev, 2001 int flags, struct net_device *dev,
1973 const u8 *mac_addr, struct station_info *sinfo) 2002 const u8 *mac_addr, struct station_info *sinfo)
1974{ 2003{
1975 void *hdr; 2004 void *hdr;
1976 struct nlattr *sinfoattr, *txrate; 2005 struct nlattr *sinfoattr;
1977 u16 bitrate;
1978 2006
1979 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); 2007 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
1980 if (!hdr) 2008 if (!hdr)
@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
2013 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, 2041 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
2014 sinfo->signal_avg); 2042 sinfo->signal_avg);
2015 if (sinfo->filled & STATION_INFO_TX_BITRATE) { 2043 if (sinfo->filled & STATION_INFO_TX_BITRATE) {
2016 txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); 2044 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
2017 if (!txrate) 2045 NL80211_STA_INFO_TX_BITRATE))
2046 goto nla_put_failure;
2047 }
2048 if (sinfo->filled & STATION_INFO_RX_BITRATE) {
2049 if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
2050 NL80211_STA_INFO_RX_BITRATE))
2018 goto nla_put_failure; 2051 goto nla_put_failure;
2019
2020 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
2021 bitrate = cfg80211_calculate_bitrate(&sinfo->txrate);
2022 if (bitrate > 0)
2023 NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
2024
2025 if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
2026 NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
2027 sinfo->txrate.mcs);
2028 if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
2029 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
2030 if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
2031 NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
2032
2033 nla_nest_end(msg, txrate);
2034 } 2052 }
2035 if (sinfo->filled & STATION_INFO_RX_PACKETS) 2053 if (sinfo->filled & STATION_INFO_RX_PACKETS)
2036 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS, 2054 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
@@ -2718,7 +2736,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
2718 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 2736 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2719 NL80211_CMD_GET_MESH_CONFIG); 2737 NL80211_CMD_GET_MESH_CONFIG);
2720 if (!hdr) 2738 if (!hdr)
2721 goto nla_put_failure; 2739 goto out;
2722 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); 2740 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
2723 if (!pinfoattr) 2741 if (!pinfoattr)
2724 goto nla_put_failure; 2742 goto nla_put_failure;
@@ -2759,6 +2777,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
2759 2777
2760 nla_put_failure: 2778 nla_put_failure:
2761 genlmsg_cancel(msg, hdr); 2779 genlmsg_cancel(msg, hdr);
2780 out:
2762 nlmsg_free(msg); 2781 nlmsg_free(msg);
2763 return -ENOBUFS; 2782 return -ENOBUFS;
2764} 2783}
@@ -2954,7 +2973,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
2954 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 2973 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2955 NL80211_CMD_GET_REG); 2974 NL80211_CMD_GET_REG);
2956 if (!hdr) 2975 if (!hdr)
2957 goto nla_put_failure; 2976 goto put_failure;
2958 2977
2959 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, 2978 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
2960 cfg80211_regdomain->alpha2); 2979 cfg80211_regdomain->alpha2);
@@ -3001,6 +3020,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
3001 3020
3002nla_put_failure: 3021nla_put_failure:
3003 genlmsg_cancel(msg, hdr); 3022 genlmsg_cancel(msg, hdr);
3023put_failure:
3004 nlmsg_free(msg); 3024 nlmsg_free(msg);
3005 err = -EMSGSIZE; 3025 err = -EMSGSIZE;
3006out: 3026out:
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 37693b6ef23a..ab801a1097b2 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -63,6 +63,10 @@ static struct regulatory_request *last_request;
63/* To trigger userspace events */ 63/* To trigger userspace events */
64static struct platform_device *reg_pdev; 64static struct platform_device *reg_pdev;
65 65
66static struct device_type reg_device_type = {
67 .uevent = reg_device_uevent,
68};
69
66/* 70/*
67 * Central wireless core regulatory domains, we only need two, 71 * Central wireless core regulatory domains, we only need two,
68 * the current one and a world regulatory domain in case we have no 72 * the current one and a world regulatory domain in case we have no
@@ -362,16 +366,11 @@ static inline void reg_regdb_query(const char *alpha2) {}
362 366
363/* 367/*
364 * This lets us keep regulatory code which is updated on a regulatory 368 * This lets us keep regulatory code which is updated on a regulatory
365 * basis in userspace. 369 * basis in userspace. Country information is filled in by
370 * reg_device_uevent
366 */ 371 */
367static int call_crda(const char *alpha2) 372static int call_crda(const char *alpha2)
368{ 373{
369 char country_env[9 + 2] = "COUNTRY=";
370 char *envp[] = {
371 country_env,
372 NULL
373 };
374
375 if (!is_world_regdom((char *) alpha2)) 374 if (!is_world_regdom((char *) alpha2))
376 pr_info("Calling CRDA for country: %c%c\n", 375 pr_info("Calling CRDA for country: %c%c\n",
377 alpha2[0], alpha2[1]); 376 alpha2[0], alpha2[1]);
@@ -381,10 +380,7 @@ static int call_crda(const char *alpha2)
381 /* query internal regulatory database (if it exists) */ 380 /* query internal regulatory database (if it exists) */
382 reg_regdb_query(alpha2); 381 reg_regdb_query(alpha2);
383 382
384 country_env[8] = alpha2[0]; 383 return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
385 country_env[9] = alpha2[1];
386
387 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp);
388} 384}
389 385
390/* Used by nl80211 before kmalloc'ing our regulatory domain */ 386/* Used by nl80211 before kmalloc'ing our regulatory domain */
@@ -813,7 +809,7 @@ static void handle_channel(struct wiphy *wiphy,
813 if (r) { 809 if (r) {
814 /* 810 /*
815 * We will disable all channels that do not match our 811 * We will disable all channels that do not match our
816 * recieved regulatory rule unless the hint is coming 812 * received regulatory rule unless the hint is coming
817 * from a Country IE and the Country IE had no information 813 * from a Country IE and the Country IE had no information
818 * about a band. The IEEE 802.11 spec allows for an AP 814 * about a band. The IEEE 802.11 spec allows for an AP
819 * to send only a subset of the regulatory rules allowed, 815 * to send only a subset of the regulatory rules allowed,
@@ -842,7 +838,7 @@ static void handle_channel(struct wiphy *wiphy,
842 request_wiphy && request_wiphy == wiphy && 838 request_wiphy && request_wiphy == wiphy &&
843 request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { 839 request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
844 /* 840 /*
845 * This gaurantees the driver's requested regulatory domain 841 * This guarantees the driver's requested regulatory domain
846 * will always be used as a base for further regulatory 842 * will always be used as a base for further regulatory
847 * settings 843 * settings
848 */ 844 */
@@ -1801,9 +1797,9 @@ void regulatory_hint_disconnect(void)
1801 1797
1802static bool freq_is_chan_12_13_14(u16 freq) 1798static bool freq_is_chan_12_13_14(u16 freq)
1803{ 1799{
1804 if (freq == ieee80211_channel_to_frequency(12) || 1800 if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) ||
1805 freq == ieee80211_channel_to_frequency(13) || 1801 freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) ||
1806 freq == ieee80211_channel_to_frequency(14)) 1802 freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ))
1807 return true; 1803 return true;
1808 return false; 1804 return false;
1809} 1805}
@@ -2087,6 +2083,25 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2087 return r; 2083 return r;
2088} 2084}
2089 2085
2086#ifdef CONFIG_HOTPLUG
2087int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
2088{
2089 if (last_request && !last_request->processed) {
2090 if (add_uevent_var(env, "COUNTRY=%c%c",
2091 last_request->alpha2[0],
2092 last_request->alpha2[1]))
2093 return -ENOMEM;
2094 }
2095
2096 return 0;
2097}
2098#else
2099int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
2100{
2101 return -ENODEV;
2102}
2103#endif /* CONFIG_HOTPLUG */
2104
2090/* Caller must hold cfg80211_mutex */ 2105/* Caller must hold cfg80211_mutex */
2091void reg_device_remove(struct wiphy *wiphy) 2106void reg_device_remove(struct wiphy *wiphy)
2092{ 2107{
@@ -2118,6 +2133,8 @@ int __init regulatory_init(void)
2118 if (IS_ERR(reg_pdev)) 2133 if (IS_ERR(reg_pdev))
2119 return PTR_ERR(reg_pdev); 2134 return PTR_ERR(reg_pdev);
2120 2135
2136 reg_pdev->dev.type = &reg_device_type;
2137
2121 spin_lock_init(&reg_requests_lock); 2138 spin_lock_init(&reg_requests_lock);
2122 spin_lock_init(&reg_pending_beacons_lock); 2139 spin_lock_init(&reg_pending_beacons_lock);
2123 2140
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index c4695d07af23..b67d1c3a2fb9 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -8,6 +8,7 @@ bool reg_is_valid_request(const char *alpha2);
8 8
9int regulatory_hint_user(const char *alpha2); 9int regulatory_hint_user(const char *alpha2);
10 10
11int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
11void reg_device_remove(struct wiphy *wiphy); 12void reg_device_remove(struct wiphy *wiphy);
12 13
13int __init regulatory_init(void); 14int __init regulatory_init(void);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ea427f418f64..fbf6f33ae4d0 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -124,6 +124,15 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
124} 124}
125 125
126/* must hold dev->bss_lock! */ 126/* must hold dev->bss_lock! */
127static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
128 struct cfg80211_internal_bss *bss)
129{
130 list_del_init(&bss->list);
131 rb_erase(&bss->rbn, &dev->bss_tree);
132 kref_put(&bss->ref, bss_release);
133}
134
135/* must hold dev->bss_lock! */
127void cfg80211_bss_expire(struct cfg80211_registered_device *dev) 136void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
128{ 137{
129 struct cfg80211_internal_bss *bss, *tmp; 138 struct cfg80211_internal_bss *bss, *tmp;
@@ -134,9 +143,7 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
134 continue; 143 continue;
135 if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) 144 if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
136 continue; 145 continue;
137 list_del(&bss->list); 146 __cfg80211_unlink_bss(dev, bss);
138 rb_erase(&bss->rbn, &dev->bss_tree);
139 kref_put(&bss->ref, bss_release);
140 expired = true; 147 expired = true;
141 } 148 }
142 149
@@ -585,16 +592,23 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
585 struct cfg80211_internal_bss *res; 592 struct cfg80211_internal_bss *res;
586 size_t ielen = len - offsetof(struct ieee80211_mgmt, 593 size_t ielen = len - offsetof(struct ieee80211_mgmt,
587 u.probe_resp.variable); 594 u.probe_resp.variable);
588 size_t privsz = wiphy->bss_priv_size; 595 size_t privsz;
596
597 if (WARN_ON(!mgmt))
598 return NULL;
599
600 if (WARN_ON(!wiphy))
601 return NULL;
589 602
590 if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && 603 if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
591 (signal < 0 || signal > 100))) 604 (signal < 0 || signal > 100)))
592 return NULL; 605 return NULL;
593 606
594 if (WARN_ON(!mgmt || !wiphy || 607 if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
595 len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
596 return NULL; 608 return NULL;
597 609
610 privsz = wiphy->bss_priv_size;
611
598 res = kzalloc(sizeof(*res) + privsz + ielen, gfp); 612 res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
599 if (!res) 613 if (!res)
600 return NULL; 614 return NULL;
@@ -662,11 +676,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
662 676
663 spin_lock_bh(&dev->bss_lock); 677 spin_lock_bh(&dev->bss_lock);
664 if (!list_empty(&bss->list)) { 678 if (!list_empty(&bss->list)) {
665 list_del_init(&bss->list); 679 __cfg80211_unlink_bss(dev, bss);
666 dev->bss_generation++; 680 dev->bss_generation++;
667 rb_erase(&bss->rbn, &dev->bss_tree);
668
669 kref_put(&bss->ref, bss_release);
670 } 681 }
671 spin_unlock_bh(&dev->bss_lock); 682 spin_unlock_bh(&dev->bss_lock);
672} 683}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 7620ae2fcf18..6a750bc6bcfe 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -29,29 +29,37 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
29} 29}
30EXPORT_SYMBOL(ieee80211_get_response_rate); 30EXPORT_SYMBOL(ieee80211_get_response_rate);
31 31
32int ieee80211_channel_to_frequency(int chan) 32int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
33{ 33{
34 if (chan < 14) 34 /* see 802.11 17.3.8.3.2 and Annex J
35 return 2407 + chan * 5; 35 * there are overlapping channel numbers in 5GHz and 2GHz bands */
36 36 if (band == IEEE80211_BAND_5GHZ) {
37 if (chan == 14) 37 if (chan >= 182 && chan <= 196)
38 return 2484; 38 return 4000 + chan * 5;
39 39 else
40 /* FIXME: 802.11j 17.3.8.3.2 */ 40 return 5000 + chan * 5;
41 return (chan + 1000) * 5; 41 } else { /* IEEE80211_BAND_2GHZ */
42 if (chan == 14)
43 return 2484;
44 else if (chan < 14)
45 return 2407 + chan * 5;
46 else
47 return 0; /* not supported */
48 }
42} 49}
43EXPORT_SYMBOL(ieee80211_channel_to_frequency); 50EXPORT_SYMBOL(ieee80211_channel_to_frequency);
44 51
45int ieee80211_frequency_to_channel(int freq) 52int ieee80211_frequency_to_channel(int freq)
46{ 53{
54 /* see 802.11 17.3.8.3.2 and Annex J */
47 if (freq == 2484) 55 if (freq == 2484)
48 return 14; 56 return 14;
49 57 else if (freq < 2484)
50 if (freq < 2484)
51 return (freq - 2407) / 5; 58 return (freq - 2407) / 5;
52 59 else if (freq >= 4910 && freq <= 4980)
53 /* FIXME: 802.11j 17.3.8.3.2 */ 60 return (freq - 4000) / 5;
54 return freq/5 - 1000; 61 else
62 return (freq - 5000) / 5;
55} 63}
56EXPORT_SYMBOL(ieee80211_frequency_to_channel); 64EXPORT_SYMBOL(ieee80211_frequency_to_channel);
57 65
@@ -159,12 +167,15 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
159 167
160 /* 168 /*
161 * Disallow pairwise keys with non-zero index unless it's WEP 169 * Disallow pairwise keys with non-zero index unless it's WEP
162 * (because current deployments use pairwise WEP keys with 170 * or a vendor specific cipher (because current deployments use
163 * non-zero indizes but 802.11i clearly specifies to use zero) 171 * pairwise WEP keys with non-zero indices and for vendor specific
172 * ciphers this should be validated in the driver or hardware level
173 * - but 802.11i clearly specifies to use zero)
164 */ 174 */
165 if (pairwise && key_idx && 175 if (pairwise && key_idx &&
166 params->cipher != WLAN_CIPHER_SUITE_WEP40 && 176 ((params->cipher == WLAN_CIPHER_SUITE_TKIP) ||
167 params->cipher != WLAN_CIPHER_SUITE_WEP104) 177 (params->cipher == WLAN_CIPHER_SUITE_CCMP) ||
178 (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC)))
168 return -EINVAL; 179 return -EINVAL;
169 180
170 switch (params->cipher) { 181 switch (params->cipher) {
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 3e5dbd4e4cd5..0bf169bb770e 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -267,9 +267,12 @@ int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
267 * -EINVAL for impossible things. 267 * -EINVAL for impossible things.
268 */ 268 */
269 if (freq->e == 0) { 269 if (freq->e == 0) {
270 enum ieee80211_band band = IEEE80211_BAND_2GHZ;
270 if (freq->m < 0) 271 if (freq->m < 0)
271 return 0; 272 return 0;
272 return ieee80211_channel_to_frequency(freq->m); 273 if (freq->m > 14)
274 band = IEEE80211_BAND_5GHZ;
275 return ieee80211_channel_to_frequency(freq->m, band);
273 } else { 276 } else {
274 int i, div = 1000000; 277 int i, div = 1000000;
275 for (i = 0; i < freq->e; i++) 278 for (i = 0; i < freq->e; i++)
@@ -802,11 +805,11 @@ int cfg80211_wext_siwfreq(struct net_device *dev,
802 return freq; 805 return freq;
803 if (freq == 0) 806 if (freq == 0)
804 return -EINVAL; 807 return -EINVAL;
805 wdev_lock(wdev);
806 mutex_lock(&rdev->devlist_mtx); 808 mutex_lock(&rdev->devlist_mtx);
809 wdev_lock(wdev);
807 err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); 810 err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
808 mutex_unlock(&rdev->devlist_mtx);
809 wdev_unlock(wdev); 811 wdev_unlock(wdev);
812 mutex_unlock(&rdev->devlist_mtx);
810 return err; 813 return err;
811 default: 814 default:
812 return -EOPNOTSUPP; 815 return -EOPNOTSUPP;