diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt61pci.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 164 |
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, ®, sizeof(reg)); | 312 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, ®, sizeof(reg)); |
313 | } | 313 | } |
314 | 314 | ||
315 | static 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, ®); | ||
324 | rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, !promisc); | ||
325 | rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !multicast); | ||
326 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, !broadcast); | ||
327 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | ||
328 | } | ||
329 | |||
330 | static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type) | 315 | static 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, ®); | ||
350 | |||
351 | if (!is_monitor_present(&rt2x00dev->interface) && | ||
352 | (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) | ||
353 | rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 1); | ||
354 | else | ||
355 | rt2x00_set_field32(®, 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(®, TXRX_CSR0_DROP_CRC, 1); | ||
365 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 1); | ||
366 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 1); | ||
367 | rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); | ||
368 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); | ||
369 | } else if (is_monitor_present(&rt2x00dev->interface)) { | ||
370 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, 0); | ||
371 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 0); | ||
372 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 0); | ||
373 | rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 0); | ||
374 | rt2x00_set_field32(®, 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, ®); | 335 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); |
383 | if (is_interface_present(&rt2x00dev->interface)) { | 336 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); |
384 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | 337 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); |
385 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
386 | } | ||
387 | |||
388 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 338 | rt2x00_set_field32(®, 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(®, TXRX_CSR9_TSF_SYNC, 2); | 341 | rt2x00_set_field32(®, 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(®, TXRX_CSR9_TSF_SYNC, 1); | 343 | rt2x00_set_field32(®, 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(®, TXRX_CSR9_TSF_SYNC, 0); | 345 | rt2x00_set_field32(®, 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 | */ |
1687 | static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 1636 | static 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 | ||
1829 | static int rt61pci_fill_rxdone(struct data_entry *entry, | 1778 | static 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 | */ |
2376 | static 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, ®); | ||
2426 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, | ||
2427 | !(*total_flags & FIF_FCSFAIL)); | ||
2428 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, | ||
2429 | !(*total_flags & FIF_PLCPFAIL)); | ||
2430 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, | ||
2431 | !(*total_flags & FIF_CONTROL)); | ||
2432 | rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, | ||
2433 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
2434 | rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, | ||
2435 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
2436 | rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); | ||
2437 | rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, | ||
2438 | !(*total_flags & FIF_ALLMULTI)); | ||
2439 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0); | ||
2440 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); | ||
2441 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | ||
2442 | } | ||
2443 | |||
2429 | static int rt61pci_set_retry_limit(struct ieee80211_hw *hw, | 2444 | static 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 | ||
2507 | static const struct ieee80211_ops rt61pci_mac80211_ops = { | 2522 | static 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 | }; |