aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00mac.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-17 01:29:23 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:57 -0400
commit4150c57212ad134765dd78c654a4b9906252b66d (patch)
treec37ab7a3f75532a623ed00339782d769514422d2 /drivers/net/wireless/rt2x00/rt2x00mac.c
parent070ac3a2651e3c1c4d277c5f1981517427c386a7 (diff)
[PATCH] mac80211: revamp interface and filter configuration
Drivers are currently supposed to keep track of monitor interfaces if they allow so-called "hard" monitor, and they are also supposed to keep track of multicast etc. This patch changes that, replaces the set_multicast_list() callback with a new configure_filter() callback that takes filter flags (FIF_*) instead of interface flags (IFF_*). For a driver, this means it should open the filter as much as necessary to get all frames requested by the filter flags. Accordingly, the filter flags are named "positively", e.g. FIF_ALLMULTI. Multicast filtering is a bit special in that drivers that have no multicast address filters need to allow multicast frames through when either the FIF_ALLMULTI flag is set or when the mc_count value is positive. At the same time, drivers are no longer notified about monitor interfaces at all, this means they now need to implement the start() and stop() callbacks and the new change_filter_flags() callback. Also, the start()/stop() ordering changed, start() is now called *before* any add_interface() as it really should be, and stop() after any remove_interface(). The patch also changes the behaviour of setting the bssid to multicast for scanning when IEEE80211_HW_NO_PROBE_FILTERING is set; the IEEE80211_HW_NO_PROBE_FILTERING flag is removed and the filter flag FIF_BCN_PRBRESP_PROMISC introduced. This is a lot more efficient for hardware like b43 that supports it and other hardware can still set the BSSID to all-ones. Driver modifications by Johannes Berg (b43 & iwlwifi), Michael Wu (rtl8187, adm8211, and p54), Larry Finger (b43legacy), and Ivo van Doorn (rt2x00). Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c104
1 files changed, 14 insertions, 90 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 778ed41e21ef..17802f6d3d6d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -176,46 +176,26 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
176{ 176{
177 struct rt2x00_dev *rt2x00dev = hw->priv; 177 struct rt2x00_dev *rt2x00dev = hw->priv;
178 struct interface *intf = &rt2x00dev->interface; 178 struct interface *intf = &rt2x00dev->interface;
179 int retval;
180 179
181 /* 180 /*
182 * We only support 1 non-monitor interface. 181 * We only support 1 non-monitor interface.
183 */ 182 */
184 if (conf->type != IEEE80211_IF_TYPE_MNTR && is_interface_present(intf)) 183 if (is_interface_present(intf))
185 return -ENOBUFS; 184 return -ENOBUFS;
186 185
187 /* 186 intf->id = conf->if_id;
188 * HACK: Placeholder until start/stop handler has been 187 intf->type = conf->type;
189 * added to the mac80211 callback functions structure. 188 if (conf->type == IEEE80211_IF_TYPE_AP)
190 */ 189 memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
191 retval = rt2x00mac_start(hw); 190 memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
192 if (retval)
193 return retval;
194
195 /*
196 * We support muliple monitor mode interfaces.
197 * All we need to do is increase the monitor_count.
198 */
199 if (conf->type == IEEE80211_IF_TYPE_MNTR) {
200 intf->monitor_count++;
201 } else {
202 intf->id = conf->if_id;
203 intf->type = conf->type;
204 if (conf->type == IEEE80211_IF_TYPE_AP)
205 memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
206 memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
207 intf->filter = 0;
208 }
209 191
210 /* 192 /*
211 * Configure interface.
212 * The MAC adddress must be configured after the device 193 * The MAC adddress must be configured after the device
213 * has been initialized. Else the device can reset the 194 * has been initialized. Otherwise the device can reset
214 * MAC registers. 195 * the MAC registers.
215 */ 196 */
216 rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); 197 rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
217 rt2x00lib_config_type(rt2x00dev, conf->type); 198 rt2x00lib_config_type(rt2x00dev, conf->type);
218 rt2x00lib_config_packet_filter(rt2x00dev, intf->filter);
219 199
220 return 0; 200 return 0;
221} 201}
@@ -230,22 +210,13 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
230 /* 210 /*
231 * We only support 1 non-monitor interface. 211 * We only support 1 non-monitor interface.
232 */ 212 */
233 if (conf->type != IEEE80211_IF_TYPE_MNTR && !is_interface_present(intf)) 213 if (!is_interface_present(intf))
234 return; 214 return;
235 215
236 /* 216 intf->id = 0;
237 * When removing an monitor interface, decrease monitor_count. 217 intf->type = INVALID_INTERFACE;
238 * For non-monitor interfaces, all interface data needs to be reset. 218 memset(&intf->bssid, 0x00, ETH_ALEN);
239 */ 219 memset(&intf->mac, 0x00, ETH_ALEN);
240 if (conf->type == IEEE80211_IF_TYPE_MNTR) {
241 intf->monitor_count--;
242 } else if (intf->type == conf->type) {
243 intf->id = 0;
244 intf->type = INVALID_INTERFACE;
245 memset(&intf->bssid, 0x00, ETH_ALEN);
246 memset(&intf->mac, 0x00, ETH_ALEN);
247 intf->filter = 0;
248 }
249 220
250 /* 221 /*
251 * Make sure the bssid and mac address registers 222 * Make sure the bssid and mac address registers
@@ -254,12 +225,6 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
254 rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); 225 rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
255 rt2x00lib_config_bssid(rt2x00dev, intf->bssid); 226 rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
256 rt2x00lib_config_type(rt2x00dev, intf->type); 227 rt2x00lib_config_type(rt2x00dev, intf->type);
257
258 /*
259 * HACK: Placeholder untill start/stop handler has been
260 * added to the mac80211 callback functions structure.
261 */
262 rt2x00mac_stop(hw);
263} 228}
264EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); 229EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
265 230
@@ -290,14 +255,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
290 rt2x00lib_config(rt2x00dev, conf); 255 rt2x00lib_config(rt2x00dev, conf);
291 256
292 /* 257 /*
293 * If promisc mode cannot be configured in irq context,
294 * then it is now the time to configure it.
295 */
296 if (test_bit(PACKET_FILTER_SCHEDULED, &rt2x00dev->flags))
297 rt2x00lib_config_packet_filter(rt2x00dev,
298 rt2x00dev->interface.filter);
299
300 /*
301 * Reenable RX only if the radio should be on. 258 * Reenable RX only if the radio should be on.
302 */ 259 */
303 if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) 260 if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
@@ -326,13 +283,10 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id,
326 return 0; 283 return 0;
327 284
328 /* 285 /*
329 * Monitor mode does not need configuring.
330 * If the given type does not match the configured type, 286 * If the given type does not match the configured type,
331 * there has been a problem. 287 * there has been a problem.
332 */ 288 */
333 if (conf->type == IEEE80211_IF_TYPE_MNTR) 289 if (conf->type != intf->type)
334 return 0;
335 else if (conf->type != intf->type)
336 return -EINVAL; 290 return -EINVAL;
337 291
338 /* 292 /*
@@ -360,36 +314,6 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id,
360} 314}
361EXPORT_SYMBOL_GPL(rt2x00mac_config_interface); 315EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
362 316
363void rt2x00mac_set_multicast_list(struct ieee80211_hw *hw,
364 unsigned short flags, int mc_count)
365{
366 struct rt2x00_dev *rt2x00dev = hw->priv;
367
368 /*
369 * Check if the new state is different then the old state.
370 */
371 if (rt2x00dev->interface.filter == flags)
372 return;
373
374 rt2x00dev->interface.filter = flags;
375
376 /*
377 * Raise the pending bit to indicate the
378 * packet filter should be updated.
379 */
380 __set_bit(PACKET_FILTER_PENDING, &rt2x00dev->flags);
381
382 /*
383 * Check if Packet filter actions are allowed in
384 * atomic context. If not, raise the pending flag and
385 * let it be.
386 */
387 if (!test_bit(PACKET_FILTER_SCHEDULED, &rt2x00dev->flags) ||
388 !in_atomic())
389 rt2x00lib_config_packet_filter(rt2x00dev, flags);
390}
391EXPORT_SYMBOL_GPL(rt2x00mac_set_multicast_list);
392
393int rt2x00mac_get_stats(struct ieee80211_hw *hw, 317int rt2x00mac_get_stats(struct ieee80211_hw *hw,
394 struct ieee80211_low_level_stats *stats) 318 struct ieee80211_low_level_stats *stats)
395{ 319{