aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2500pci.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/rt2500pci.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/rt2500pci.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c165
1 files changed, 90 insertions, 75 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index e8d63aaab7bc..892baa907a6b 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -277,59 +277,14 @@ static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
277 rt2x00pci_register_multiwrite(rt2x00dev, CSR5, &reg, sizeof(reg)); 277 rt2x00pci_register_multiwrite(rt2x00dev, CSR5, &reg, sizeof(reg));
278} 278}
279 279
280static void rt2500pci_config_packet_filter(struct rt2x00_dev *rt2x00dev,
281 const unsigned int filter)
282{
283 int promisc = !!(filter & IFF_PROMISC);
284 int multicast = !!(filter & IFF_MULTICAST);
285 int broadcast = !!(filter & IFF_BROADCAST);
286 u32 reg;
287
288 rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
289 rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME, !promisc);
290 rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST, !multicast);
291 rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, !broadcast);
292 rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
293}
294
295static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type) 280static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type)
296{ 281{
282 struct interface *intf = &rt2x00dev->interface;
297 u32 reg; 283 u32 reg;
298 284
299 rt2x00pci_register_write(rt2x00dev, CSR14, 0); 285 rt2x00pci_register_write(rt2x00dev, CSR14, 0);
300 286
301 /* 287 /*
302 * Apply hardware packet filter.
303 */
304 rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
305
306 if (!is_monitor_present(&rt2x00dev->interface) &&
307 (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA))
308 rt2x00_set_field32(&reg, RXCSR0_DROP_TODS, 1);
309 else
310 rt2x00_set_field32(&reg, RXCSR0_DROP_TODS, 0);
311
312 /*
313 * If there is a non-monitor interface present
314 * the packet should be strict (even if a monitor interface is present!).
315 * When there is only 1 interface present which is in monitor mode
316 * we should start accepting _all_ frames.
317 */
318 if (is_interface_present(&rt2x00dev->interface)) {
319 rt2x00_set_field32(&reg, RXCSR0_DROP_CRC, 1);
320 rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL, 1);
321 rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL, 1);
322 rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
323 } else if (is_monitor_present(&rt2x00dev->interface)) {
324 rt2x00_set_field32(&reg, RXCSR0_DROP_CRC, 0);
325 rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL, 0);
326 rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL, 0);
327 rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 0);
328 }
329
330 rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
331
332 /*
333 * Enable beacon config 288 * Enable beacon config
334 */ 289 */
335 rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg); 290 rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
@@ -345,20 +300,16 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type)
345 * Enable synchronisation. 300 * Enable synchronisation.
346 */ 301 */
347 rt2x00pci_register_read(rt2x00dev, CSR14, &reg); 302 rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
348 if (is_interface_present(&rt2x00dev->interface)) { 303 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
349 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1); 304 rt2x00_set_field32(&reg, CSR14_TBCN, 1);
350 rt2x00_set_field32(&reg, CSR14_TBCN, 1);
351 }
352
353 rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0); 305 rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
354 if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) 306 if (is_interface_type(intf, IEEE80211_IF_TYPE_IBSS) ||
307 is_interface_type(intf, IEEE80211_IF_TYPE_AP))
355 rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 2); 308 rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 2);
356 else if (type == IEEE80211_IF_TYPE_STA) 309 else if (is_interface_type(intf, IEEE80211_IF_TYPE_STA))
357 rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 1); 310 rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 1);
358 else if (is_monitor_present(&rt2x00dev->interface) && 311 else
359 !is_interface_present(&rt2x00dev->interface))
360 rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0); 312 rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
361
362 rt2x00pci_register_write(rt2x00dev, CSR14, reg); 313 rt2x00pci_register_write(rt2x00dev, CSR14, reg);
363} 314}
364 315
@@ -1269,7 +1220,7 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
1269 */ 1220 */
1270static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, 1221static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
1271 struct data_desc *txd, 1222 struct data_desc *txd,
1272 struct data_entry_desc *desc, 1223 struct txdata_entry_desc *desc,
1273 struct ieee80211_hdr *ieee80211hdr, 1224 struct ieee80211_hdr *ieee80211hdr,
1274 unsigned int length, 1225 unsigned int length,
1275 struct ieee80211_tx_control *control) 1226 struct ieee80211_tx_control *control)
@@ -1349,8 +1300,8 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
1349/* 1300/*
1350 * RX control handlers 1301 * RX control handlers
1351 */ 1302 */
1352static int rt2500pci_fill_rxdone(struct data_entry *entry, 1303static void rt2500pci_fill_rxdone(struct data_entry *entry,
1353 int *signal, int *rssi, int *ofdm, int *size) 1304 struct rxdata_entry_desc *desc)
1354{ 1305{
1355 struct data_desc *rxd = entry->priv; 1306 struct data_desc *rxd = entry->priv;
1356 u32 word0; 1307 u32 word0;
@@ -1359,18 +1310,17 @@ static int rt2500pci_fill_rxdone(struct data_entry *entry,
1359 rt2x00_desc_read(rxd, 0, &word0); 1310 rt2x00_desc_read(rxd, 0, &word0);
1360 rt2x00_desc_read(rxd, 2, &word2); 1311 rt2x00_desc_read(rxd, 2, &word2);
1361 1312
1362 if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR) || 1313 desc->flags = 0;
1363 rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR) || 1314 if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
1364 rt2x00_get_field32(word0, RXD_W0_ICV_ERROR)) 1315 desc->flags |= RX_FLAG_FAILED_FCS_CRC;
1365 return -EINVAL; 1316 if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
1317 desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
1366 1318
1367 *signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); 1319 desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
1368 *rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - 1320 desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
1369 entry->ring->rt2x00dev->rssi_offset; 1321 entry->ring->rt2x00dev->rssi_offset;
1370 *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); 1322 desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
1371 *size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); 1323 desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
1372
1373 return 0;
1374} 1324}
1375 1325
1376/* 1326/*
@@ -1779,10 +1729,7 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
1779 /* 1729 /*
1780 * Initialize all hw fields. 1730 * Initialize all hw fields.
1781 */ 1731 */
1782 rt2x00dev->hw->flags = 1732 rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
1783 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
1784 IEEE80211_HW_MONITOR_DURING_OPER |
1785 IEEE80211_HW_NO_PROBE_FILTERING;
1786 rt2x00dev->hw->extra_tx_headroom = 0; 1733 rt2x00dev->hw->extra_tx_headroom = 0;
1787 rt2x00dev->hw->max_signal = MAX_SIGNAL; 1734 rt2x00dev->hw->max_signal = MAX_SIGNAL;
1788 rt2x00dev->hw->max_rssi = MAX_RX_SSI; 1735 rt2x00dev->hw->max_rssi = MAX_RX_SSI;
@@ -1867,6 +1814,73 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
1867/* 1814/*
1868 * IEEE80211 stack callback functions. 1815 * IEEE80211 stack callback functions.
1869 */ 1816 */
1817static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
1818 unsigned int changed_flags,
1819 unsigned int *total_flags,
1820 int mc_count,
1821 struct dev_addr_list *mc_list)
1822{
1823 struct rt2x00_dev *rt2x00dev = hw->priv;
1824 struct interface *intf = &rt2x00dev->interface;
1825 u32 reg;
1826
1827 /*
1828 * Mask off any flags we are going to ignore from
1829 * the total_flags field.
1830 */
1831 *total_flags &=
1832 FIF_ALLMULTI |
1833 FIF_FCSFAIL |
1834 FIF_PLCPFAIL |
1835 FIF_CONTROL |
1836 FIF_OTHER_BSS |
1837 FIF_PROMISC_IN_BSS;
1838
1839 /*
1840 * Apply some rules to the filters:
1841 * - Some filters imply different filters to be set.
1842 * - Some things we can't filter out at all.
1843 * - Some filters are set based on interface type.
1844 */
1845 if (mc_count)
1846 *total_flags |= FIF_ALLMULTI;
1847 if (changed_flags & FIF_OTHER_BSS ||
1848 changed_flags & FIF_PROMISC_IN_BSS)
1849 *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
1850 if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
1851 *total_flags |= FIF_PROMISC_IN_BSS;
1852
1853 /*
1854 * Check if there is any work left for us.
1855 */
1856 if (intf->filter == *total_flags)
1857 return;
1858 intf->filter = *total_flags;
1859
1860 /*
1861 * Start configuration steps.
1862 * Note that the version error will always be dropped
1863 * and broadcast frames will always be accepted since
1864 * there is no filter for it at this time.
1865 */
1866 rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
1867 rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
1868 !(*total_flags & FIF_FCSFAIL));
1869 rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
1870 !(*total_flags & FIF_PLCPFAIL));
1871 rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
1872 !(*total_flags & FIF_CONTROL));
1873 rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
1874 !(*total_flags & FIF_PROMISC_IN_BSS));
1875 rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
1876 !(*total_flags & FIF_PROMISC_IN_BSS));
1877 rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
1878 rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
1879 !(*total_flags & FIF_ALLMULTI));
1880 rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
1881 rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
1882}
1883
1870static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw, 1884static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw,
1871 u32 short_retry, u32 long_retry) 1885 u32 short_retry, u32 long_retry)
1872{ 1886{
@@ -1914,11 +1928,13 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
1914 1928
1915static const struct ieee80211_ops rt2500pci_mac80211_ops = { 1929static const struct ieee80211_ops rt2500pci_mac80211_ops = {
1916 .tx = rt2x00mac_tx, 1930 .tx = rt2x00mac_tx,
1931 .start = rt2x00mac_start,
1932 .stop = rt2x00mac_stop,
1917 .add_interface = rt2x00mac_add_interface, 1933 .add_interface = rt2x00mac_add_interface,
1918 .remove_interface = rt2x00mac_remove_interface, 1934 .remove_interface = rt2x00mac_remove_interface,
1919 .config = rt2x00mac_config, 1935 .config = rt2x00mac_config,
1920 .config_interface = rt2x00mac_config_interface, 1936 .config_interface = rt2x00mac_config_interface,
1921 .set_multicast_list = rt2x00mac_set_multicast_list, 1937 .configure_filter = rt2500pci_configure_filter,
1922 .get_stats = rt2x00mac_get_stats, 1938 .get_stats = rt2x00mac_get_stats,
1923 .set_retry_limit = rt2500pci_set_retry_limit, 1939 .set_retry_limit = rt2500pci_set_retry_limit,
1924 .conf_tx = rt2x00mac_conf_tx, 1940 .conf_tx = rt2x00mac_conf_tx,
@@ -1947,7 +1963,6 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
1947 .fill_rxdone = rt2500pci_fill_rxdone, 1963 .fill_rxdone = rt2500pci_fill_rxdone,
1948 .config_mac_addr = rt2500pci_config_mac_addr, 1964 .config_mac_addr = rt2500pci_config_mac_addr,
1949 .config_bssid = rt2500pci_config_bssid, 1965 .config_bssid = rt2500pci_config_bssid,
1950 .config_packet_filter = rt2500pci_config_packet_filter,
1951 .config_type = rt2500pci_config_type, 1966 .config_type = rt2500pci_config_type,
1952 .config = rt2500pci_config, 1967 .config = rt2500pci_config,
1953}; 1968};