diff options
| -rw-r--r-- | net/wireless/chan.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index d0c92dddb26b..c8d190d911e4 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,28 @@ 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 | wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | ||
| 107 | switch (channel_type) { | ||
| 108 | case NL80211_CHAN_HT40PLUS: | ||
| 109 | case NL80211_CHAN_HT40MINUS: | ||
| 110 | if (!can_beacon_sec_chan(&rdev->wiphy, chan, | ||
| 111 | channel_type)) { | ||
| 112 | printk(KERN_DEBUG | ||
| 113 | "cfg80211: Secondary channel not " | ||
| 114 | "allowed to initiate communication\n"); | ||
| 115 | return -EINVAL; | ||
| 116 | } | ||
| 117 | break; | ||
| 118 | default: | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 71 | result = rdev->ops->set_channel(&rdev->wiphy, | 123 | result = rdev->ops->set_channel(&rdev->wiphy, |
| 72 | wdev ? wdev->netdev : NULL, | 124 | wdev ? wdev->netdev : NULL, |
| 73 | chan, channel_type); | 125 | chan, channel_type); |
