aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2500usb.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/rt2500usb.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/rt2500usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c179
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, &reg, sizeof(reg)); 282 rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, &reg, sizeof(reg));
283} 283}
284 284
285static 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, &reg);
294 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME, !promisc);
295 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST, !multicast);
296 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, !broadcast);
297 rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
298}
299
300static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type) 285static 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, &reg);
310
311 if (!is_monitor_present(&rt2x00dev->interface) &&
312 (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA))
313 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS, 1);
314 else
315 rt2x00_set_field16(&reg, 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(&reg, TXRX_CSR2_DROP_CRC, 1);
325 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL, 1);
326 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL, 1);
327 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
328 } else if (is_monitor_present(&rt2x00dev->interface)) {
329 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC, 0);
330 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL, 0);
331 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL, 0);
332 rt2x00_set_field16(&reg, 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, &reg); 295 rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
341 rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, 296 rt2x00_set_field16(&reg, 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(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0); 299 rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
345 else 300 else
346 rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 2); 301 rt2x00_set_field16(&reg, 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, &reg); 311 rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
357 if (is_interface_present(&rt2x00dev->interface)) { 312 rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
358 rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1); 313 rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
359 rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
360 }
361
362 rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0); 314 rt2x00_set_field16(&reg, 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(&reg, TXRX_CSR19_TSF_SYNC, 2); 317 rt2x00_set_field16(&reg, 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(&reg, TXRX_CSR19_TSF_SYNC, 1); 319 rt2x00_set_field16(&reg, 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(&reg, TXRX_CSR19_TSF_SYNC, 0); 321 rt2x00_set_field16(&reg, 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 */
1085static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, 1036static 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 */
1159static int rt2500usb_fill_rxdone(struct data_entry *entry, 1110static 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 */
1589static 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, &reg);
1648 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
1649 !(*total_flags & FIF_FCSFAIL));
1650 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
1651 !(*total_flags & FIF_PLCPFAIL));
1652 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
1653 !(*total_flags & FIF_CONTROL));
1654 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
1655 !(*total_flags & FIF_PROMISC_IN_BSS));
1656 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
1657 !(*total_flags & FIF_PROMISC_IN_BSS));
1658 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
1659 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
1660 !(*total_flags & FIF_ALLMULTI));
1661 rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
1662 rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
1663}
1664
1641static int rt2500usb_beacon_update(struct ieee80211_hw *hw, 1665static 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
1715static const struct ieee80211_ops rt2500usb_mac80211_ops = { 1739static 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};