diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt73usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 175 |
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, ®, sizeof(reg)); | 293 | rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, ®, sizeof(reg)); |
294 | } | 294 | } |
295 | 295 | ||
296 | static 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, ®); | ||
305 | rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, !promisc); | ||
306 | rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !multicast); | ||
307 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, !broadcast); | ||
308 | rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); | ||
309 | } | ||
310 | |||
311 | static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type) | 296 | static 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, ®); | ||
331 | |||
332 | if (!is_monitor_present(&rt2x00dev->interface) && | ||
333 | (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) | ||
334 | rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 1); | ||
335 | else | ||
336 | rt2x00_set_field32(®, 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(®, TXRX_CSR0_DROP_CRC, 1); | ||
346 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 1); | ||
347 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 1); | ||
348 | rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); | ||
349 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); | ||
350 | } else if (is_monitor_present(&rt2x00dev->interface)) { | ||
351 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, 0); | ||
352 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 0); | ||
353 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 0); | ||
354 | rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 0); | ||
355 | rt2x00_set_field32(®, 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, ®); | 316 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
364 | if (is_interface_present(&rt2x00dev->interface)) { | 317 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); |
365 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | 318 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); |
366 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
367 | } | ||
368 | |||
369 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 319 | rt2x00_set_field32(®, 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(®, TXRX_CSR9_TSF_SYNC, 2); | 322 | rt2x00_set_field32(®, 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(®, TXRX_CSR9_TSF_SYNC, 1); | 324 | rt2x00_set_field32(®, 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(®, TXRX_CSR9_TSF_SYNC, 0); | 326 | rt2x00_set_field32(®, 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 | */ |
1302 | static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 1251 | static 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 | ||
1432 | static int rt73usb_fill_rxdone(struct data_entry *entry, | 1381 | static 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 | */ |
1843 | static 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, ®); | ||
1902 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, | ||
1903 | !(*total_flags & FIF_FCSFAIL)); | ||
1904 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, | ||
1905 | !(*total_flags & FIF_PLCPFAIL)); | ||
1906 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, | ||
1907 | !(*total_flags & FIF_CONTROL)); | ||
1908 | rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, | ||
1909 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1910 | rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, | ||
1911 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1912 | rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); | ||
1913 | rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, | ||
1914 | !(*total_flags & FIF_ALLMULTI)); | ||
1915 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); | ||
1916 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); | ||
1917 | rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); | ||
1918 | } | ||
1919 | |||
1898 | static int rt73usb_set_retry_limit(struct ieee80211_hw *hw, | 1920 | static 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 | ||
1978 | static const struct ieee80211_ops rt73usb_mac80211_ops = { | 2000 | static 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 | }; |