diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-06-12 14:25:04 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-12 14:25:04 -0400 |
commit | 0440507bbc44149e63bbfb9df730ba3820371904 (patch) | |
tree | 7275e41aa1aa7e4d19d0503f1c15f07991c1a120 /net/wireless/mesh.c | |
parent | 8d242488ce4627dd7e6333caab56df11ea25e239 (diff) | |
parent | 7f0d9f430dc99303558adc30a75eef10c43f7bec (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/wireless/mesh.c')
-rw-r--r-- | net/wireless/mesh.c | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 2749cb86b462..b44c736bf9cf 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 | ||
67 | const struct mesh_setup default_mesh_setup = { | 67 | const 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 | ||
76 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 79 | int __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 | ||
113 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 161 | int 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 | ||
176 | int 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 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | ||
183 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
184 | channel, | ||
185 | channel_type)) { | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Workaround for libertas (only!), it puts the interface | ||
191 | * into mesh mode but doesn't implement join_mesh. Instead, | ||
192 | * it is configured via sysfs and then joins the mesh when | ||
193 | * you set the channel. Note that the libertas mesh isn't | ||
194 | * compatible with 802.11 mesh. | ||
195 | */ | ||
196 | if (rdev->ops->libertas_set_mesh_channel) { | ||
197 | if (channel_type != NL80211_CHAN_NO_HT) | ||
198 | return -EINVAL; | ||
199 | |||
200 | if (!netif_running(wdev->netdev)) | ||
201 | return -ENETDOWN; | ||
202 | return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, | ||
203 | wdev->netdev, | ||
204 | channel); | ||
205 | } | ||
206 | |||
207 | if (wdev->mesh_id_len) | ||
208 | return -EBUSY; | ||
209 | |||
210 | wdev->preset_chan = channel; | ||
211 | wdev->preset_chantype = channel_type; | ||
212 | return 0; | ||
213 | } | ||
214 | |||
128 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, | 215 | void 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 | { |