diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 20 | ||||
-rw-r--r-- | net/wireless/ethtool.c | 33 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 62 | ||||
-rw-r--r-- | net/wireless/reg.c | 49 | ||||
-rw-r--r-- | net/wireless/reg.h | 1 | ||||
-rw-r--r-- | net/wireless/scan.c | 31 | ||||
-rw-r--r-- | net/wireless/util.c | 47 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 9 |
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 | ||
5 | static void cfg80211_get_drvinfo(struct net_device *dev, | 6 | static 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 | ||
41 | static 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 | |||
55 | static 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 | |||
40 | const struct ethtool_ops cfg80211_ethtool_ops = { | 71 | const 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 | ||
1971 | static 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 | |||
1996 | nla_put_failure: | ||
1997 | return false; | ||
1998 | } | ||
1999 | |||
1971 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | 2000 | static 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 | ||
3002 | nla_put_failure: | 3021 | nla_put_failure: |
3003 | genlmsg_cancel(msg, hdr); | 3022 | genlmsg_cancel(msg, hdr); |
3023 | put_failure: | ||
3004 | nlmsg_free(msg); | 3024 | nlmsg_free(msg); |
3005 | err = -EMSGSIZE; | 3025 | err = -EMSGSIZE; |
3006 | out: | 3026 | out: |
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 */ |
64 | static struct platform_device *reg_pdev; | 64 | static struct platform_device *reg_pdev; |
65 | 65 | ||
66 | static 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 | */ |
367 | static int call_crda(const char *alpha2) | 372 | static 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(®_pdev->dev.kobj, KOBJ_CHANGE); |
385 | country_env[9] = alpha2[1]; | ||
386 | |||
387 | return kobject_uevent_env(®_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 | ||
1802 | static bool freq_is_chan_12_13_14(u16 freq) | 1798 | static 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 | ||
2087 | int 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 | ||
2099 | int 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 */ |
2091 | void reg_device_remove(struct wiphy *wiphy) | 2106 | void 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 = ®_device_type; | ||
2137 | |||
2121 | spin_lock_init(®_requests_lock); | 2138 | spin_lock_init(®_requests_lock); |
2122 | spin_lock_init(®_pending_beacons_lock); | 2139 | spin_lock_init(®_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 | ||
9 | int regulatory_hint_user(const char *alpha2); | 9 | int regulatory_hint_user(const char *alpha2); |
10 | 10 | ||
11 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env); | ||
11 | void reg_device_remove(struct wiphy *wiphy); | 12 | void reg_device_remove(struct wiphy *wiphy); |
12 | 13 | ||
13 | int __init regulatory_init(void); | 14 | int __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! */ |
127 | static 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! */ | ||
127 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev) | 136 | void 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 | } |
30 | EXPORT_SYMBOL(ieee80211_get_response_rate); | 30 | EXPORT_SYMBOL(ieee80211_get_response_rate); |
31 | 31 | ||
32 | int ieee80211_channel_to_frequency(int chan) | 32 | int 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 | } |
43 | EXPORT_SYMBOL(ieee80211_channel_to_frequency); | 50 | EXPORT_SYMBOL(ieee80211_channel_to_frequency); |
44 | 51 | ||
45 | int ieee80211_frequency_to_channel(int freq) | 52 | int 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 | } |
56 | EXPORT_SYMBOL(ieee80211_frequency_to_channel); | 64 | EXPORT_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; |