aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt73usb.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/rt73usb.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/rt73usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c175
1 files changed, 99 insertions, 76 deletions
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 3397881bd63d..aac13aa4039c 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -293,23 +293,9 @@ static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
293 rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, &reg, sizeof(reg)); 293 rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, &reg, sizeof(reg));
294} 294}
295 295
296static void rt73usb_config_packet_filter(struct rt2x00_dev *rt2x00dev,
297 const unsigned int filter)
298{
299 int promisc = !!(filter & IFF_PROMISC);
300 int multicast = !!(filter & IFF_MULTICAST);
301 int broadcast = !!(filter & IFF_BROADCAST);
302 u32 reg;
303
304 rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
305 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, !promisc);
306 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST, !multicast);
307 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BORADCAST, !broadcast);
308 rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
309}
310
311static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type) 296static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type)
312{ 297{
298 struct interface *intf = &rt2x00dev->interface;
313 u32 reg; 299 u32 reg;
314 300
315 /* 301 /*
@@ -325,56 +311,19 @@ static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type)
325 rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); 311 rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
326 312
327 /* 313 /*
328 * Apply hardware packet filter.
329 */
330 rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
331
332 if (!is_monitor_present(&rt2x00dev->interface) &&
333 (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA))
334 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS, 1);
335 else
336 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS, 0);
337
338 /*
339 * If there is a non-monitor interface present
340 * the packet should be strict (even if a monitor interface is present!).
341 * When there is only 1 interface present which is in monitor mode
342 * we should start accepting _all_ frames.
343 */
344 if (is_interface_present(&rt2x00dev->interface)) {
345 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC, 1);
346 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL, 1);
347 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL, 1);
348 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
349 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
350 } else if (is_monitor_present(&rt2x00dev->interface)) {
351 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC, 0);
352 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL, 0);
353 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL, 0);
354 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 0);
355 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 0);
356 }
357
358 rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
359
360 /*
361 * Enable synchronisation. 314 * Enable synchronisation.
362 */ 315 */
363 rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg); 316 rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
364 if (is_interface_present(&rt2x00dev->interface)) { 317 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
365 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1); 318 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
366 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
367 }
368
369 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0); 319 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
370 if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) 320 if (is_interface_type(intf, IEEE80211_IF_TYPE_IBSS) ||
321 is_interface_type(intf, IEEE80211_IF_TYPE_AP))
371 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 2); 322 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 2);
372 else if (type == IEEE80211_IF_TYPE_STA) 323 else if (is_interface_type(intf, IEEE80211_IF_TYPE_STA))
373 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 1); 324 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 1);
374 else if (is_monitor_present(&rt2x00dev->interface) && 325 else
375 !is_interface_present(&rt2x00dev->interface))
376 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0); 326 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
377
378 rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); 327 rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
379} 328}
380 329
@@ -1301,7 +1250,7 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
1301 */ 1250 */
1302static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, 1251static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
1303 struct data_desc *txd, 1252 struct data_desc *txd,
1304 struct data_entry_desc *desc, 1253 struct txdata_entry_desc *desc,
1305 struct ieee80211_hdr *ieee80211hdr, 1254 struct ieee80211_hdr *ieee80211hdr,
1306 unsigned int length, 1255 unsigned int length,
1307 struct ieee80211_tx_control *control) 1256 struct ieee80211_tx_control *control)
@@ -1429,8 +1378,8 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
1429 return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; 1378 return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
1430} 1379}
1431 1380
1432static int rt73usb_fill_rxdone(struct data_entry *entry, 1381static void rt73usb_fill_rxdone(struct data_entry *entry,
1433 int *signal, int *rssi, int *ofdm, int *size) 1382 struct rxdata_entry_desc *desc)
1434{ 1383{
1435 struct data_desc *rxd = (struct data_desc *)entry->skb->data; 1384 struct data_desc *rxd = (struct data_desc *)entry->skb->data;
1436 u32 word0; 1385 u32 word0;
@@ -1439,24 +1388,24 @@ static int rt73usb_fill_rxdone(struct data_entry *entry,
1439 rt2x00_desc_read(rxd, 0, &word0); 1388 rt2x00_desc_read(rxd, 0, &word0);
1440 rt2x00_desc_read(rxd, 1, &word1); 1389 rt2x00_desc_read(rxd, 1, &word1);
1441 1390
1442 if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR) || 1391 desc->flags = 0;
1443 rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) 1392 if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
1444 return -EINVAL; 1393 desc->flags |= RX_FLAG_FAILED_FCS_CRC;
1445 1394
1446 /* 1395 /*
1447 * Obtain the status about this packet. 1396 * Obtain the status about this packet.
1448 */ 1397 */
1449 *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); 1398 desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
1450 *rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1); 1399 desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
1451 *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); 1400 desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
1452 *size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); 1401 desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
1453 1402
1454 /* 1403 /*
1455 * Pull the skb to clear the descriptor area. 1404 * Pull the skb to clear the descriptor area.
1456 */ 1405 */
1457 skb_pull(entry->skb, entry->ring->desc_size); 1406 skb_pull(entry->skb, entry->ring->desc_size);
1458 1407
1459 return 0; 1408 return;
1460} 1409}
1461 1410
1462/* 1411/*
@@ -1802,9 +1751,7 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
1802 */ 1751 */
1803 rt2x00dev->hw->flags = 1752 rt2x00dev->hw->flags =
1804 IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | 1753 IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
1805 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 1754 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
1806 IEEE80211_HW_MONITOR_DURING_OPER |
1807 IEEE80211_HW_NO_PROBE_FILTERING;
1808 rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; 1755 rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
1809 rt2x00dev->hw->max_signal = MAX_SIGNAL; 1756 rt2x00dev->hw->max_signal = MAX_SIGNAL;
1810 rt2x00dev->hw->max_rssi = MAX_RX_SSI; 1757 rt2x00dev->hw->max_rssi = MAX_RX_SSI;
@@ -1878,11 +1825,9 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
1878 rt73usb_probe_hw_mode(rt2x00dev); 1825 rt73usb_probe_hw_mode(rt2x00dev);
1879 1826
1880 /* 1827 /*
1881 * USB devices require scheduled packet filter toggling
1882 * This device requires firmware 1828 * This device requires firmware
1883 */ 1829 */
1884 __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->flags); 1830 __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->flags);
1885 __set_bit(PACKET_FILTER_SCHEDULED, &rt2x00dev->flags);
1886 1831
1887 /* 1832 /*
1888 * Set the rssi offset. 1833 * Set the rssi offset.
@@ -1895,6 +1840,83 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
1895/* 1840/*
1896 * IEEE80211 stack callback functions. 1841 * IEEE80211 stack callback functions.
1897 */ 1842 */
1843static void rt73usb_configure_filter(struct ieee80211_hw *hw,
1844 unsigned int changed_flags,
1845 unsigned int *total_flags,
1846 int mc_count,
1847 struct dev_addr_list *mc_list)
1848{
1849 struct rt2x00_dev *rt2x00dev = hw->priv;
1850 struct interface *intf = &rt2x00dev->interface;
1851 u32 reg;
1852
1853 /*
1854 * Mask off any flags we are going to ignore from
1855 * the total_flags field.
1856 */
1857 *total_flags &=
1858 FIF_ALLMULTI |
1859 FIF_FCSFAIL |
1860 FIF_PLCPFAIL |
1861 FIF_CONTROL |
1862 FIF_OTHER_BSS |
1863 FIF_PROMISC_IN_BSS;
1864
1865 /*
1866 * Apply some rules to the filters:
1867 * - Some filters imply different filters to be set.
1868 * - Some things we can't filter out at all.
1869 * - Some filters are set based on interface type.
1870 */
1871 if (mc_count)
1872 *total_flags |= FIF_ALLMULTI;
1873 if (changed_flags & FIF_OTHER_BSS ||
1874 changed_flags & FIF_PROMISC_IN_BSS)
1875 *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
1876 if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
1877 *total_flags |= FIF_PROMISC_IN_BSS;
1878
1879 /*
1880 * Check if there is any work left for us.
1881 */
1882 if (intf->filter == *total_flags)
1883 return;
1884 intf->filter = *total_flags;
1885
1886 /*
1887 * When in atomic context, reschedule and let rt2x00lib
1888 * call this function again.
1889 */
1890 if (in_atomic()) {
1891 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
1892 return;
1893 }
1894
1895 /*
1896 * Start configuration steps.
1897 * Note that the version error will always be dropped
1898 * and broadcast frames will always be accepted since
1899 * there is no filter for it at this time.
1900 */
1901 rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
1902 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
1903 !(*total_flags & FIF_FCSFAIL));
1904 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
1905 !(*total_flags & FIF_PLCPFAIL));
1906 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
1907 !(*total_flags & FIF_CONTROL));
1908 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
1909 !(*total_flags & FIF_PROMISC_IN_BSS));
1910 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
1911 !(*total_flags & FIF_PROMISC_IN_BSS));
1912 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
1913 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
1914 !(*total_flags & FIF_ALLMULTI));
1915 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
1916 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
1917 rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
1918}
1919
1898static int rt73usb_set_retry_limit(struct ieee80211_hw *hw, 1920static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
1899 u32 short_retry, u32 long_retry) 1921 u32 short_retry, u32 long_retry)
1900{ 1922{
@@ -1977,11 +1999,13 @@ int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
1977 1999
1978static const struct ieee80211_ops rt73usb_mac80211_ops = { 2000static const struct ieee80211_ops rt73usb_mac80211_ops = {
1979 .tx = rt2x00mac_tx, 2001 .tx = rt2x00mac_tx,
2002 .start = rt2x00mac_start,
2003 .stop = rt2x00mac_stop,
1980 .add_interface = rt2x00mac_add_interface, 2004 .add_interface = rt2x00mac_add_interface,
1981 .remove_interface = rt2x00mac_remove_interface, 2005 .remove_interface = rt2x00mac_remove_interface,
1982 .config = rt2x00mac_config, 2006 .config = rt2x00mac_config,
1983 .config_interface = rt2x00mac_config_interface, 2007 .config_interface = rt2x00mac_config_interface,
1984 .set_multicast_list = rt2x00mac_set_multicast_list, 2008 .configure_filter = rt73usb_configure_filter,
1985 .get_stats = rt2x00mac_get_stats, 2009 .get_stats = rt2x00mac_get_stats,
1986 .set_retry_limit = rt73usb_set_retry_limit, 2010 .set_retry_limit = rt73usb_set_retry_limit,
1987 .conf_tx = rt2x00mac_conf_tx, 2011 .conf_tx = rt2x00mac_conf_tx,
@@ -2012,7 +2036,6 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
2012 .fill_rxdone = rt73usb_fill_rxdone, 2036 .fill_rxdone = rt73usb_fill_rxdone,
2013 .config_mac_addr = rt73usb_config_mac_addr, 2037 .config_mac_addr = rt73usb_config_mac_addr,
2014 .config_bssid = rt73usb_config_bssid, 2038 .config_bssid = rt73usb_config_bssid,
2015 .config_packet_filter = rt73usb_config_packet_filter,
2016 .config_type = rt73usb_config_type, 2039 .config_type = rt73usb_config_type,
2017 .config = rt73usb_config, 2040 .config = rt73usb_config,
2018}; 2041};