aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt61pci.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/rt61pci.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/rt61pci.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c164
1 files changed, 90 insertions, 74 deletions
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 09c8c96e2f83..dea7a8a4fa00 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -312,23 +312,9 @@ static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
312 rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, &reg, sizeof(reg)); 312 rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, &reg, sizeof(reg));
313} 313}
314 314
315static void rt61pci_config_packet_filter(struct rt2x00_dev *rt2x00dev,
316 const unsigned int filter)
317{
318 int promisc = !!(filter & IFF_PROMISC);
319 int multicast = !!(filter & IFF_MULTICAST);
320 int broadcast = !!(filter & IFF_BROADCAST);
321 u32 reg;
322
323 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
324 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, !promisc);
325 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST, !multicast);
326 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BORADCAST, !broadcast);
327 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
328}
329
330static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type) 315static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type)
331{ 316{
317 struct interface *intf = &rt2x00dev->interface;
332 u32 reg; 318 u32 reg;
333 319
334 /* 320 /*
@@ -344,56 +330,19 @@ static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type)
344 rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); 330 rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
345 331
346 /* 332 /*
347 * Apply hardware packet filter.
348 */
349 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
350
351 if (!is_monitor_present(&rt2x00dev->interface) &&
352 (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA))
353 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS, 1);
354 else
355 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS, 0);
356
357 /*
358 * If there is a non-monitor interface present
359 * the packet should be strict (even if a monitor interface is present!).
360 * When there is only 1 interface present which is in monitor mode
361 * we should start accepting _all_ frames.
362 */
363 if (is_interface_present(&rt2x00dev->interface)) {
364 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC, 1);
365 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL, 1);
366 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL, 1);
367 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
368 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
369 } else if (is_monitor_present(&rt2x00dev->interface)) {
370 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC, 0);
371 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL, 0);
372 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL, 0);
373 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 0);
374 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 0);
375 }
376
377 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
378
379 /*
380 * Enable synchronisation. 333 * Enable synchronisation.
381 */ 334 */
382 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg); 335 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
383 if (is_interface_present(&rt2x00dev->interface)) { 336 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
384 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1); 337 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
385 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
386 }
387
388 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0); 338 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
389 if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) 339 if (is_interface_type(intf, IEEE80211_IF_TYPE_IBSS) ||
340 is_interface_type(intf, IEEE80211_IF_TYPE_AP))
390 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 2); 341 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 2);
391 else if (type == IEEE80211_IF_TYPE_STA) 342 else if (is_interface_type(intf, IEEE80211_IF_TYPE_STA))
392 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 1); 343 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 1);
393 else if (is_monitor_present(&rt2x00dev->interface) && 344 else
394 !is_interface_present(&rt2x00dev->interface))
395 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0); 345 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
396
397 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); 346 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
398} 347}
399 348
@@ -1686,7 +1635,7 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
1686 */ 1635 */
1687static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, 1636static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
1688 struct data_desc *txd, 1637 struct data_desc *txd,
1689 struct data_entry_desc *desc, 1638 struct txdata_entry_desc *desc,
1690 struct ieee80211_hdr *ieee80211hdr, 1639 struct ieee80211_hdr *ieee80211hdr,
1691 unsigned int length, 1640 unsigned int length,
1692 struct ieee80211_tx_control *control) 1641 struct ieee80211_tx_control *control)
@@ -1826,8 +1775,8 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
1826 return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; 1775 return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
1827} 1776}
1828 1777
1829static int rt61pci_fill_rxdone(struct data_entry *entry, 1778static void rt61pci_fill_rxdone(struct data_entry *entry,
1830 int *signal, int *rssi, int *ofdm, int *size) 1779 struct rxdata_entry_desc *desc)
1831{ 1780{
1832 struct data_desc *rxd = entry->priv; 1781 struct data_desc *rxd = entry->priv;
1833 u32 word0; 1782 u32 word0;
@@ -1836,19 +1785,19 @@ static int rt61pci_fill_rxdone(struct data_entry *entry,
1836 rt2x00_desc_read(rxd, 0, &word0); 1785 rt2x00_desc_read(rxd, 0, &word0);
1837 rt2x00_desc_read(rxd, 1, &word1); 1786 rt2x00_desc_read(rxd, 1, &word1);
1838 1787
1839 if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR) || 1788 desc->flags = 0;
1840 rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) 1789 if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
1841 return -EINVAL; 1790 desc->flags |= RX_FLAG_FAILED_FCS_CRC;
1842 1791
1843 /* 1792 /*
1844 * Obtain the status about this packet. 1793 * Obtain the status about this packet.
1845 */ 1794 */
1846 *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); 1795 desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
1847 *rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1); 1796 desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
1848 *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); 1797 desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
1849 *size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); 1798 desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
1850 1799
1851 return 0; 1800 return;
1852} 1801}
1853 1802
1854/* 1803/*
@@ -2340,9 +2289,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2340 */ 2289 */
2341 rt2x00dev->hw->flags = 2290 rt2x00dev->hw->flags =
2342 IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | 2291 IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
2343 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 2292 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
2344 IEEE80211_HW_MONITOR_DURING_OPER |
2345 IEEE80211_HW_NO_PROBE_FILTERING;
2346 rt2x00dev->hw->extra_tx_headroom = 0; 2293 rt2x00dev->hw->extra_tx_headroom = 0;
2347 rt2x00dev->hw->max_signal = MAX_SIGNAL; 2294 rt2x00dev->hw->max_signal = MAX_SIGNAL;
2348 rt2x00dev->hw->max_rssi = MAX_RX_SSI; 2295 rt2x00dev->hw->max_rssi = MAX_RX_SSI;
@@ -2426,6 +2373,74 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
2426/* 2373/*
2427 * IEEE80211 stack callback functions. 2374 * IEEE80211 stack callback functions.
2428 */ 2375 */
2376static void rt61pci_configure_filter(struct ieee80211_hw *hw,
2377 unsigned int changed_flags,
2378 unsigned int *total_flags,
2379 int mc_count,
2380 struct dev_addr_list *mc_list)
2381{
2382 struct rt2x00_dev *rt2x00dev = hw->priv;
2383 struct interface *intf = &rt2x00dev->interface;
2384 u32 reg;
2385
2386 /*
2387 * Mask off any flags we are going to ignore from
2388 * the total_flags field.
2389 */
2390 *total_flags &=
2391 FIF_ALLMULTI |
2392 FIF_FCSFAIL |
2393 FIF_PLCPFAIL |
2394 FIF_CONTROL |
2395 FIF_OTHER_BSS |
2396 FIF_PROMISC_IN_BSS;
2397
2398 /*
2399 * Apply some rules to the filters:
2400 * - Some filters imply different filters to be set.
2401 * - Some things we can't filter out at all.
2402 * - Some filters are set based on interface type.
2403 */
2404 if (mc_count)
2405 *total_flags |= FIF_ALLMULTI;
2406 if (changed_flags & FIF_OTHER_BSS ||
2407 changed_flags & FIF_PROMISC_IN_BSS)
2408 *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
2409 if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
2410 *total_flags |= FIF_PROMISC_IN_BSS;
2411
2412 /*
2413 * Check if there is any work left for us.
2414 */
2415 if (intf->filter == *total_flags)
2416 return;
2417 intf->filter = *total_flags;
2418
2419 /*
2420 * Start configuration steps.
2421 * Note that the version error will always be dropped
2422 * and broadcast frames will always be accepted since
2423 * there is no filter for it at this time.
2424 */
2425 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
2426 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
2427 !(*total_flags & FIF_FCSFAIL));
2428 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
2429 !(*total_flags & FIF_PLCPFAIL));
2430 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
2431 !(*total_flags & FIF_CONTROL));
2432 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
2433 !(*total_flags & FIF_PROMISC_IN_BSS));
2434 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
2435 !(*total_flags & FIF_PROMISC_IN_BSS));
2436 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
2437 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
2438 !(*total_flags & FIF_ALLMULTI));
2439 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BORADCAST, 0);
2440 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
2441 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
2442}
2443
2429static int rt61pci_set_retry_limit(struct ieee80211_hw *hw, 2444static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
2430 u32 short_retry, u32 long_retry) 2445 u32 short_retry, u32 long_retry)
2431{ 2446{
@@ -2506,11 +2521,13 @@ int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
2506 2521
2507static const struct ieee80211_ops rt61pci_mac80211_ops = { 2522static const struct ieee80211_ops rt61pci_mac80211_ops = {
2508 .tx = rt2x00mac_tx, 2523 .tx = rt2x00mac_tx,
2524 .start = rt2x00mac_start,
2525 .stop = rt2x00mac_stop,
2509 .add_interface = rt2x00mac_add_interface, 2526 .add_interface = rt2x00mac_add_interface,
2510 .remove_interface = rt2x00mac_remove_interface, 2527 .remove_interface = rt2x00mac_remove_interface,
2511 .config = rt2x00mac_config, 2528 .config = rt2x00mac_config,
2512 .config_interface = rt2x00mac_config_interface, 2529 .config_interface = rt2x00mac_config_interface,
2513 .set_multicast_list = rt2x00mac_set_multicast_list, 2530 .configure_filter = rt61pci_configure_filter,
2514 .get_stats = rt2x00mac_get_stats, 2531 .get_stats = rt2x00mac_get_stats,
2515 .set_retry_limit = rt61pci_set_retry_limit, 2532 .set_retry_limit = rt61pci_set_retry_limit,
2516 .conf_tx = rt2x00mac_conf_tx, 2533 .conf_tx = rt2x00mac_conf_tx,
@@ -2540,7 +2557,6 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
2540 .fill_rxdone = rt61pci_fill_rxdone, 2557 .fill_rxdone = rt61pci_fill_rxdone,
2541 .config_mac_addr = rt61pci_config_mac_addr, 2558 .config_mac_addr = rt61pci_config_mac_addr,
2542 .config_bssid = rt61pci_config_bssid, 2559 .config_bssid = rt61pci_config_bssid,
2543 .config_packet_filter = rt61pci_config_packet_filter,
2544 .config_type = rt61pci_config_type, 2560 .config_type = rt61pci_config_type,
2545 .config = rt61pci_config, 2561 .config = rt61pci_config,
2546}; 2562};