diff options
Diffstat (limited to 'net/wireless/chan.c')
-rw-r--r-- | net/wireless/chan.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index d0c92dddb26b..d8f443b70b08 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -44,6 +44,36 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | |||
44 | return chan; | 44 | return chan; |
45 | } | 45 | } |
46 | 46 | ||
47 | static bool can_beacon_sec_chan(struct wiphy *wiphy, | ||
48 | struct ieee80211_channel *chan, | ||
49 | enum nl80211_channel_type channel_type) | ||
50 | { | ||
51 | struct ieee80211_channel *sec_chan; | ||
52 | int diff; | ||
53 | |||
54 | switch (channel_type) { | ||
55 | case NL80211_CHAN_HT40PLUS: | ||
56 | diff = 20; | ||
57 | case NL80211_CHAN_HT40MINUS: | ||
58 | diff = -20; | ||
59 | default: | ||
60 | return false; | ||
61 | } | ||
62 | |||
63 | sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); | ||
64 | if (!sec_chan) | ||
65 | return false; | ||
66 | |||
67 | /* we'll need a DFS capability later */ | ||
68 | if (sec_chan->flags & (IEEE80211_CHAN_DISABLED | | ||
69 | IEEE80211_CHAN_PASSIVE_SCAN | | ||
70 | IEEE80211_CHAN_NO_IBSS | | ||
71 | IEEE80211_CHAN_RADAR)) | ||
72 | return false; | ||
73 | |||
74 | return true; | ||
75 | } | ||
76 | |||
47 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | 77 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, |
48 | struct wireless_dev *wdev, int freq, | 78 | struct wireless_dev *wdev, int freq, |
49 | enum nl80211_channel_type channel_type) | 79 | enum nl80211_channel_type channel_type) |
@@ -68,6 +98,27 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | |||
68 | if (!chan) | 98 | if (!chan) |
69 | return -EINVAL; | 99 | return -EINVAL; |
70 | 100 | ||
101 | /* Both channels should be able to initiate communication */ | ||
102 | if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC || | ||
103 | wdev->iftype == NL80211_IFTYPE_AP || | ||
104 | wdev->iftype == NL80211_IFTYPE_AP_VLAN || | ||
105 | wdev->iftype == NL80211_IFTYPE_MESH_POINT)) { | ||
106 | switch (channel_type) { | ||
107 | case NL80211_CHAN_HT40PLUS: | ||
108 | case NL80211_CHAN_HT40MINUS: | ||
109 | if (!can_beacon_sec_chan(&rdev->wiphy, chan, | ||
110 | channel_type)) { | ||
111 | printk(KERN_DEBUG | ||
112 | "cfg80211: Secondary channel not " | ||
113 | "allowed to initiate communication\n"); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | break; | ||
117 | default: | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | |||
71 | result = rdev->ops->set_channel(&rdev->wiphy, | 122 | result = rdev->ops->set_channel(&rdev->wiphy, |
72 | wdev ? wdev->netdev : NULL, | 123 | wdev ? wdev->netdev : NULL, |
73 | chan, channel_type); | 124 | chan, channel_type); |