diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2500usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 179 |
1 files changed, 102 insertions, 77 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 614600c5510d..f4e6f6eb7fb5 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -282,65 +282,20 @@ static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) | |||
282 | rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, ®, sizeof(reg)); | 282 | rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, ®, sizeof(reg)); |
283 | } | 283 | } |
284 | 284 | ||
285 | static void rt2500usb_config_packet_filter(struct rt2x00_dev *rt2x00dev, | ||
286 | const unsigned int filter) | ||
287 | { | ||
288 | int promisc = !!(filter & IFF_PROMISC); | ||
289 | int multicast = !!(filter & IFF_MULTICAST); | ||
290 | int broadcast = !!(filter & IFF_BROADCAST); | ||
291 | u16 reg; | ||
292 | |||
293 | rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); | ||
294 | rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, !promisc); | ||
295 | rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, !multicast); | ||
296 | rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, !broadcast); | ||
297 | rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); | ||
298 | } | ||
299 | |||
300 | static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type) | 285 | static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type) |
301 | { | 286 | { |
287 | struct interface *intf = &rt2x00dev->interface; | ||
302 | u16 reg; | 288 | u16 reg; |
303 | 289 | ||
304 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); | 290 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); |
305 | 291 | ||
306 | /* | 292 | /* |
307 | * Apply hardware packet filter. | ||
308 | */ | ||
309 | rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); | ||
310 | |||
311 | if (!is_monitor_present(&rt2x00dev->interface) && | ||
312 | (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) | ||
313 | rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, 1); | ||
314 | else | ||
315 | rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, 0); | ||
316 | |||
317 | /* | ||
318 | * If there is a non-monitor interface present | ||
319 | * the packet should be strict (even if a monitor interface is present!). | ||
320 | * When there is only 1 interface present which is in monitor mode | ||
321 | * we should start accepting _all_ frames. | ||
322 | */ | ||
323 | if (is_interface_present(&rt2x00dev->interface)) { | ||
324 | rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, 1); | ||
325 | rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, 1); | ||
326 | rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, 1); | ||
327 | rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); | ||
328 | } else if (is_monitor_present(&rt2x00dev->interface)) { | ||
329 | rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, 0); | ||
330 | rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, 0); | ||
331 | rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, 0); | ||
332 | rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 0); | ||
333 | } | ||
334 | |||
335 | rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); | ||
336 | |||
337 | /* | ||
338 | * Enable beacon config | 293 | * Enable beacon config |
339 | */ | 294 | */ |
340 | rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); | 295 | rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); |
341 | rt2x00_set_field16(®, TXRX_CSR20_OFFSET, | 296 | rt2x00_set_field16(®, TXRX_CSR20_OFFSET, |
342 | (PREAMBLE + get_duration(IEEE80211_HEADER, 2)) >> 6); | 297 | (PREAMBLE + get_duration(IEEE80211_HEADER, 2)) >> 6); |
343 | if (type == IEEE80211_IF_TYPE_STA) | 298 | if (is_interface_type(intf, IEEE80211_IF_TYPE_STA)) |
344 | rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0); | 299 | rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0); |
345 | else | 300 | else |
346 | rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 2); | 301 | rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 2); |
@@ -354,20 +309,16 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type) | |||
354 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); | 309 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); |
355 | 310 | ||
356 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); | 311 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); |
357 | if (is_interface_present(&rt2x00dev->interface)) { | 312 | rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); |
358 | rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); | 313 | rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); |
359 | rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); | ||
360 | } | ||
361 | |||
362 | rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); | 314 | rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); |
363 | if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) | 315 | if (is_interface_type(intf, IEEE80211_IF_TYPE_IBSS) || |
316 | is_interface_type(intf, IEEE80211_IF_TYPE_AP)) | ||
364 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 2); | 317 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 2); |
365 | else if (type == IEEE80211_IF_TYPE_STA) | 318 | else if (is_interface_type(intf, IEEE80211_IF_TYPE_STA)) |
366 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 1); | 319 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 1); |
367 | else if (is_monitor_present(&rt2x00dev->interface) && | 320 | else |
368 | !is_interface_present(&rt2x00dev->interface)) | ||
369 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 0); | 321 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 0); |
370 | |||
371 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); | 322 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); |
372 | } | 323 | } |
373 | 324 | ||
@@ -1084,7 +1035,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1084 | */ | 1035 | */ |
1085 | static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 1036 | static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
1086 | struct data_desc *txd, | 1037 | struct data_desc *txd, |
1087 | struct data_entry_desc *desc, | 1038 | struct txdata_entry_desc *desc, |
1088 | struct ieee80211_hdr *ieee80211hdr, | 1039 | struct ieee80211_hdr *ieee80211hdr, |
1089 | unsigned int length, | 1040 | unsigned int length, |
1090 | struct ieee80211_tx_control *control) | 1041 | struct ieee80211_tx_control *control) |
@@ -1156,8 +1107,8 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1156 | /* | 1107 | /* |
1157 | * RX control handlers | 1108 | * RX control handlers |
1158 | */ | 1109 | */ |
1159 | static int rt2500usb_fill_rxdone(struct data_entry *entry, | 1110 | static void rt2500usb_fill_rxdone(struct data_entry *entry, |
1160 | int *signal, int *rssi, int *ofdm, int *size) | 1111 | struct rxdata_entry_desc *desc) |
1161 | { | 1112 | { |
1162 | struct urb *urb = entry->priv; | 1113 | struct urb *urb = entry->priv; |
1163 | struct data_desc *rxd = (struct data_desc *)(entry->skb->data + | 1114 | struct data_desc *rxd = (struct data_desc *)(entry->skb->data + |
@@ -1169,21 +1120,22 @@ static int rt2500usb_fill_rxdone(struct data_entry *entry, | |||
1169 | rt2x00_desc_read(rxd, 0, &word0); | 1120 | rt2x00_desc_read(rxd, 0, &word0); |
1170 | rt2x00_desc_read(rxd, 1, &word1); | 1121 | rt2x00_desc_read(rxd, 1, &word1); |
1171 | 1122 | ||
1172 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR) || | 1123 | desc->flags = 0; |
1173 | rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR) || | 1124 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) |
1174 | rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) | 1125 | desc->flags |= RX_FLAG_FAILED_FCS_CRC; |
1175 | return -EINVAL; | 1126 | if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) |
1127 | desc->flags |= RX_FLAG_FAILED_PLCP_CRC; | ||
1176 | 1128 | ||
1177 | /* | 1129 | /* |
1178 | * Obtain the status about this packet. | 1130 | * Obtain the status about this packet. |
1179 | */ | 1131 | */ |
1180 | *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); | 1132 | desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); |
1181 | *rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - | 1133 | desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - |
1182 | entry->ring->rt2x00dev->rssi_offset; | 1134 | entry->ring->rt2x00dev->rssi_offset; |
1183 | *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); | 1135 | desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); |
1184 | *size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); | 1136 | desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); |
1185 | 1137 | ||
1186 | return 0; | 1138 | return; |
1187 | } | 1139 | } |
1188 | 1140 | ||
1189 | /* | 1141 | /* |
@@ -1549,9 +1501,7 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1549 | rt2x00dev->hw->flags = | 1501 | rt2x00dev->hw->flags = |
1550 | IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | | 1502 | IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | |
1551 | IEEE80211_HW_RX_INCLUDES_FCS | | 1503 | IEEE80211_HW_RX_INCLUDES_FCS | |
1552 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1504 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; |
1553 | IEEE80211_HW_MONITOR_DURING_OPER | | ||
1554 | IEEE80211_HW_NO_PROBE_FILTERING; | ||
1555 | rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; | 1505 | rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; |
1556 | rt2x00dev->hw->max_signal = MAX_SIGNAL; | 1506 | rt2x00dev->hw->max_signal = MAX_SIGNAL; |
1557 | rt2x00dev->hw->max_rssi = MAX_RX_SSI; | 1507 | rt2x00dev->hw->max_rssi = MAX_RX_SSI; |
@@ -1621,10 +1571,8 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1621 | rt2500usb_probe_hw_mode(rt2x00dev); | 1571 | rt2500usb_probe_hw_mode(rt2x00dev); |
1622 | 1572 | ||
1623 | /* | 1573 | /* |
1624 | * USB devices require scheduled packet filter toggling | 1574 | * This device requires the beacon ring |
1625 | *This device requires the beacon ring | ||
1626 | */ | 1575 | */ |
1627 | __set_bit(PACKET_FILTER_SCHEDULED, &rt2x00dev->flags); | ||
1628 | __set_bit(REQUIRE_BEACON_RING, &rt2x00dev->flags); | 1576 | __set_bit(REQUIRE_BEACON_RING, &rt2x00dev->flags); |
1629 | 1577 | ||
1630 | /* | 1578 | /* |
@@ -1638,6 +1586,82 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1638 | /* | 1586 | /* |
1639 | * IEEE80211 stack callback functions. | 1587 | * IEEE80211 stack callback functions. |
1640 | */ | 1588 | */ |
1589 | static void rt2500usb_configure_filter(struct ieee80211_hw *hw, | ||
1590 | unsigned int changed_flags, | ||
1591 | unsigned int *total_flags, | ||
1592 | int mc_count, | ||
1593 | struct dev_addr_list *mc_list) | ||
1594 | { | ||
1595 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1596 | struct interface *intf = &rt2x00dev->interface; | ||
1597 | u16 reg; | ||
1598 | |||
1599 | /* | ||
1600 | * Mask off any flags we are going to ignore from | ||
1601 | * the total_flags field. | ||
1602 | */ | ||
1603 | *total_flags &= | ||
1604 | FIF_ALLMULTI | | ||
1605 | FIF_FCSFAIL | | ||
1606 | FIF_PLCPFAIL | | ||
1607 | FIF_CONTROL | | ||
1608 | FIF_OTHER_BSS | | ||
1609 | FIF_PROMISC_IN_BSS; | ||
1610 | |||
1611 | /* | ||
1612 | * Apply some rules to the filters: | ||
1613 | * - Some filters imply different filters to be set. | ||
1614 | * - Some things we can't filter out at all. | ||
1615 | * - Some filters are set based on interface type. | ||
1616 | */ | ||
1617 | if (mc_count) | ||
1618 | *total_flags |= FIF_ALLMULTI; | ||
1619 | if (changed_flags & FIF_OTHER_BSS || | ||
1620 | changed_flags & FIF_PROMISC_IN_BSS) | ||
1621 | *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; | ||
1622 | if (is_interface_type(intf, IEEE80211_IF_TYPE_AP)) | ||
1623 | *total_flags |= FIF_PROMISC_IN_BSS; | ||
1624 | |||
1625 | /* | ||
1626 | * Check if there is any work left for us. | ||
1627 | */ | ||
1628 | if (intf->filter == *total_flags) | ||
1629 | return; | ||
1630 | intf->filter = *total_flags; | ||
1631 | |||
1632 | /* | ||
1633 | * When in atomic context, reschedule and let rt2x00lib | ||
1634 | * call this function again. | ||
1635 | */ | ||
1636 | if (in_atomic()) { | ||
1637 | queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); | ||
1638 | return; | ||
1639 | } | ||
1640 | |||
1641 | /* | ||
1642 | * Start configuration steps. | ||
1643 | * Note that the version error will always be dropped | ||
1644 | * and broadcast frames will always be accepted since | ||
1645 | * there is no filter for it at this time. | ||
1646 | */ | ||
1647 | rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); | ||
1648 | rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, | ||
1649 | !(*total_flags & FIF_FCSFAIL)); | ||
1650 | rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, | ||
1651 | !(*total_flags & FIF_PLCPFAIL)); | ||
1652 | rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, | ||
1653 | !(*total_flags & FIF_CONTROL)); | ||
1654 | rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, | ||
1655 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1656 | rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, | ||
1657 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1658 | rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); | ||
1659 | rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, | ||
1660 | !(*total_flags & FIF_ALLMULTI)); | ||
1661 | rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); | ||
1662 | rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); | ||
1663 | } | ||
1664 | |||
1641 | static int rt2500usb_beacon_update(struct ieee80211_hw *hw, | 1665 | static int rt2500usb_beacon_update(struct ieee80211_hw *hw, |
1642 | struct sk_buff *skb, | 1666 | struct sk_buff *skb, |
1643 | struct ieee80211_tx_control *control) | 1667 | struct ieee80211_tx_control *control) |
@@ -1714,11 +1738,13 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, | |||
1714 | 1738 | ||
1715 | static const struct ieee80211_ops rt2500usb_mac80211_ops = { | 1739 | static const struct ieee80211_ops rt2500usb_mac80211_ops = { |
1716 | .tx = rt2x00mac_tx, | 1740 | .tx = rt2x00mac_tx, |
1741 | .start = rt2x00mac_start, | ||
1742 | .stop = rt2x00mac_stop, | ||
1717 | .add_interface = rt2x00mac_add_interface, | 1743 | .add_interface = rt2x00mac_add_interface, |
1718 | .remove_interface = rt2x00mac_remove_interface, | 1744 | .remove_interface = rt2x00mac_remove_interface, |
1719 | .config = rt2x00mac_config, | 1745 | .config = rt2x00mac_config, |
1720 | .config_interface = rt2x00mac_config_interface, | 1746 | .config_interface = rt2x00mac_config_interface, |
1721 | .set_multicast_list = rt2x00mac_set_multicast_list, | 1747 | .configure_filter = rt2500usb_configure_filter, |
1722 | .get_stats = rt2x00mac_get_stats, | 1748 | .get_stats = rt2x00mac_get_stats, |
1723 | .conf_tx = rt2x00mac_conf_tx, | 1749 | .conf_tx = rt2x00mac_conf_tx, |
1724 | .get_tx_stats = rt2x00mac_get_tx_stats, | 1750 | .get_tx_stats = rt2x00mac_get_tx_stats, |
@@ -1739,7 +1765,6 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { | |||
1739 | .fill_rxdone = rt2500usb_fill_rxdone, | 1765 | .fill_rxdone = rt2500usb_fill_rxdone, |
1740 | .config_mac_addr = rt2500usb_config_mac_addr, | 1766 | .config_mac_addr = rt2500usb_config_mac_addr, |
1741 | .config_bssid = rt2500usb_config_bssid, | 1767 | .config_bssid = rt2500usb_config_bssid, |
1742 | .config_packet_filter = rt2500usb_config_packet_filter, | ||
1743 | .config_type = rt2500usb_config_type, | 1768 | .config_type = rt2500usb_config_type, |
1744 | .config = rt2500usb_config, | 1769 | .config = rt2500usb_config, |
1745 | }; | 1770 | }; |