aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/mesh.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-05-16 17:50:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-05 15:32:18 -0400
commitcc1d2806bf06ab92268343d26eb3d8d8f00f8bc9 (patch)
treeb14ffa920d616470715e715df49f990bfdcf12ae /net/wireless/mesh.c
parent685d12a1929f274bd91497e33b4255fe164ac8ec (diff)
cfg80211: provide channel to join_mesh function
Just like the AP mode patch, instead of setting the channel and then joining the mesh network, provide the channel to join the network on to the join_mesh() function. Like in AP mode, you can also give the channel to the join-mesh nl80211 command now. Unlike AP mode, it picks a default channel if none was given. As libertas uses mesh mode interfaces but has no join_mesh callback and we can't simply break it, keep some compatibility code for that case and configure the channel directly for it. In the non-libertas case, where we store the channel until join, allow setting it while the interface is down. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/mesh.c')
-rw-r--r--net/wireless/mesh.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 2749cb86b46..2e3b700eba3 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -65,6 +65,9 @@ const struct mesh_config default_mesh_config = {
65}; 65};
66 66
67const struct mesh_setup default_mesh_setup = { 67const struct mesh_setup default_mesh_setup = {
68 /* cfg80211_join_mesh() will pick a channel if needed */
69 .channel = NULL,
70 .channel_type = NL80211_CHAN_NO_HT,
68 .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, 71 .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
69 .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, 72 .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
70 .path_metric = IEEE80211_PATH_METRIC_AIRTIME, 73 .path_metric = IEEE80211_PATH_METRIC_AIRTIME,
@@ -75,7 +78,7 @@ const struct mesh_setup default_mesh_setup = {
75 78
76int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, 79int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
77 struct net_device *dev, 80 struct net_device *dev,
78 const struct mesh_setup *setup, 81 struct mesh_setup *setup,
79 const struct mesh_config *conf) 82 const struct mesh_config *conf)
80{ 83{
81 struct wireless_dev *wdev = dev->ieee80211_ptr; 84 struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -101,6 +104,51 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
101 if (!rdev->ops->join_mesh) 104 if (!rdev->ops->join_mesh)
102 return -EOPNOTSUPP; 105 return -EOPNOTSUPP;
103 106
107 if (!setup->channel) {
108 /* if no channel explicitly given, use preset channel */
109 setup->channel = wdev->preset_chan;
110 setup->channel_type = wdev->preset_chantype;
111 }
112
113 if (!setup->channel) {
114 /* if we don't have that either, use the first usable channel */
115 enum ieee80211_band band;
116
117 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
118 struct ieee80211_supported_band *sband;
119 struct ieee80211_channel *chan;
120 int i;
121
122 sband = rdev->wiphy.bands[band];
123 if (!sband)
124 continue;
125
126 for (i = 0; i < sband->n_channels; i++) {
127 chan = &sband->channels[i];
128 if (chan->flags & (IEEE80211_CHAN_NO_IBSS |
129 IEEE80211_CHAN_PASSIVE_SCAN |
130 IEEE80211_CHAN_DISABLED |
131 IEEE80211_CHAN_RADAR))
132 continue;
133 setup->channel = chan;
134 break;
135 }
136
137 if (setup->channel)
138 break;
139 }
140
141 /* no usable channel ... */
142 if (!setup->channel)
143 return -EINVAL;
144
145 setup->channel_type = NL80211_CHAN_NO_HT;
146 }
147
148 if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel,
149 setup->channel_type))
150 return -EINVAL;
151
104 err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); 152 err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
105 if (!err) { 153 if (!err) {
106 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); 154 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
@@ -112,7 +160,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
112 160
113int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, 161int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
114 struct net_device *dev, 162 struct net_device *dev,
115 const struct mesh_setup *setup, 163 struct mesh_setup *setup,
116 const struct mesh_config *conf) 164 const struct mesh_config *conf)
117{ 165{
118 struct wireless_dev *wdev = dev->ieee80211_ptr; 166 struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -125,6 +173,45 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
125 return err; 173 return err;
126} 174}
127 175
176int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
177 struct wireless_dev *wdev, int freq,
178 enum nl80211_channel_type channel_type)
179{
180 struct ieee80211_channel *channel;
181
182 /*
183 * Workaround for libertas (only!), it puts the interface
184 * into mesh mode but doesn't implement join_mesh. Instead,
185 * it is configured via sysfs and then joins the mesh when
186 * you set the channel. Note that the libertas mesh isn't
187 * compatible with 802.11 mesh.
188 */
189 if (!rdev->ops->join_mesh) {
190 int err;
191
192 if (!netif_running(wdev->netdev))
193 return -ENETDOWN;
194 wdev_lock(wdev);
195 err = cfg80211_set_freq(rdev, wdev, freq, channel_type);
196 wdev_unlock(wdev);
197
198 return err;
199 }
200
201 if (wdev->mesh_id_len)
202 return -EBUSY;
203
204 channel = rdev_freq_to_chan(rdev, freq, channel_type);
205 if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
206 channel,
207 channel_type)) {
208 return -EINVAL;
209 }
210 wdev->preset_chan = channel;
211 wdev->preset_chantype = channel_type;
212 return 0;
213}
214
128void cfg80211_notify_new_peer_candidate(struct net_device *dev, 215void cfg80211_notify_new_peer_candidate(struct net_device *dev,
129 const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) 216 const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp)
130{ 217{