diff options
34 files changed, 1383 insertions, 1267 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index ac2ea237019d..49a6b9eda4ea 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -281,49 +281,6 @@ static int adm8211_get_stats(struct ieee80211_hw *dev, | |||
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | ||
284 | static void adm8211_set_rx_mode(struct ieee80211_hw *dev, | ||
285 | unsigned short flags, int mc_count) | ||
286 | { | ||
287 | struct adm8211_priv *priv = dev->priv; | ||
288 | unsigned int bit_nr; | ||
289 | u32 mc_filter[2]; | ||
290 | struct dev_mc_list *mclist; | ||
291 | void *tmp; | ||
292 | |||
293 | if (flags & IFF_PROMISC) { | ||
294 | priv->nar |= ADM8211_NAR_PR; | ||
295 | priv->nar &= ~ADM8211_NAR_MM; | ||
296 | mc_filter[1] = mc_filter[0] = ~0; | ||
297 | } else if ((flags & IFF_ALLMULTI) || (mc_count > -1)) { | ||
298 | priv->nar &= ~ADM8211_NAR_PR; | ||
299 | priv->nar |= ADM8211_NAR_MM; | ||
300 | mc_filter[1] = mc_filter[0] = ~0; | ||
301 | } else { | ||
302 | priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); | ||
303 | mc_filter[1] = mc_filter[0] = 0; | ||
304 | mclist = NULL; | ||
305 | while ((mclist = ieee80211_get_mc_list_item(dev, mclist, &tmp))) { | ||
306 | bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; | ||
307 | |||
308 | bit_nr &= 0x3F; | ||
309 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | ADM8211_IDLE_RX(); | ||
314 | |||
315 | ADM8211_CSR_WRITE(MAR0, mc_filter[0]); | ||
316 | ADM8211_CSR_WRITE(MAR1, mc_filter[1]); | ||
317 | ADM8211_CSR_READ(NAR); | ||
318 | |||
319 | if (flags & IFF_PROMISC) | ||
320 | dev->flags |= IEEE80211_HW_RX_INCLUDES_FCS; | ||
321 | else | ||
322 | dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; | ||
323 | |||
324 | ADM8211_RESTORE(); | ||
325 | } | ||
326 | |||
327 | static int adm8211_get_tx_stats(struct ieee80211_hw *dev, | 284 | static int adm8211_get_tx_stats(struct ieee80211_hw *dev, |
328 | struct ieee80211_tx_queue_stats *stats) | 285 | struct ieee80211_tx_queue_stats *stats) |
329 | { | 286 | { |
@@ -1254,13 +1211,6 @@ static void adm8211_hw_init(struct ieee80211_hw *dev) | |||
1254 | 1211 | ||
1255 | /* Clear the missed-packet counter. */ | 1212 | /* Clear the missed-packet counter. */ |
1256 | ADM8211_CSR_READ(LPC); | 1213 | ADM8211_CSR_READ(LPC); |
1257 | |||
1258 | if (!priv->mac_addr) | ||
1259 | return; | ||
1260 | |||
1261 | /* set mac address */ | ||
1262 | ADM8211_CSR_WRITE(PAR0, *(u32 *)priv->mac_addr); | ||
1263 | ADM8211_CSR_WRITE(PAR1, *(u16 *)&priv->mac_addr[4]); | ||
1264 | } | 1214 | } |
1265 | 1215 | ||
1266 | static int adm8211_hw_reset(struct ieee80211_hw *dev) | 1216 | static int adm8211_hw_reset(struct ieee80211_hw *dev) |
@@ -1334,7 +1284,7 @@ static void adm8211_set_interval(struct ieee80211_hw *dev, | |||
1334 | ADM8211_CSR_WRITE(BPLI, reg); | 1284 | ADM8211_CSR_WRITE(BPLI, reg); |
1335 | } | 1285 | } |
1336 | 1286 | ||
1337 | static void adm8211_set_bssid(struct ieee80211_hw *dev, u8 *bssid) | 1287 | static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid) |
1338 | { | 1288 | { |
1339 | struct adm8211_priv *priv = dev->priv; | 1289 | struct adm8211_priv *priv = dev->priv; |
1340 | u32 reg; | 1290 | u32 reg; |
@@ -1395,24 +1345,87 @@ static int adm8211_config_interface(struct ieee80211_hw *dev, int if_id, | |||
1395 | return 0; | 1345 | return 0; |
1396 | } | 1346 | } |
1397 | 1347 | ||
1348 | static void adm8211_configure_filter(struct ieee80211_hw *dev, | ||
1349 | unsigned int changed_flags, | ||
1350 | unsigned int *total_flags, | ||
1351 | int mc_count, struct dev_mc_list *mclist) | ||
1352 | { | ||
1353 | static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||
1354 | struct adm8211_priv *priv = dev->priv; | ||
1355 | unsigned int bit_nr, new_flags; | ||
1356 | u32 mc_filter[2]; | ||
1357 | int i; | ||
1358 | |||
1359 | new_flags = 0; | ||
1360 | |||
1361 | if (*total_flags & FIF_PROMISC_IN_BSS) { | ||
1362 | new_flags |= FIF_PROMISC_IN_BSS; | ||
1363 | priv->nar |= ADM8211_NAR_PR; | ||
1364 | priv->nar &= ~ADM8211_NAR_MM; | ||
1365 | mc_filter[1] = mc_filter[0] = ~0; | ||
1366 | } else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) { | ||
1367 | new_flags |= FIF_ALLMULTI; | ||
1368 | priv->nar &= ~ADM8211_NAR_PR; | ||
1369 | priv->nar |= ADM8211_NAR_MM; | ||
1370 | mc_filter[1] = mc_filter[0] = ~0; | ||
1371 | } else { | ||
1372 | priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); | ||
1373 | mc_filter[1] = mc_filter[0] = 0; | ||
1374 | for (i = 0; i < mc_count; i++) { | ||
1375 | if (!mclist) | ||
1376 | break; | ||
1377 | bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; | ||
1378 | |||
1379 | bit_nr &= 0x3F; | ||
1380 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
1381 | mclist = mclist->next; | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | ADM8211_IDLE_RX(); | ||
1386 | |||
1387 | ADM8211_CSR_WRITE(MAR0, mc_filter[0]); | ||
1388 | ADM8211_CSR_WRITE(MAR1, mc_filter[1]); | ||
1389 | ADM8211_CSR_READ(NAR); | ||
1390 | |||
1391 | if (priv->nar & ADM8211_NAR_PR) | ||
1392 | dev->flags |= IEEE80211_HW_RX_INCLUDES_FCS; | ||
1393 | else | ||
1394 | dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; | ||
1395 | |||
1396 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
1397 | adm8211_set_bssid(dev, bcast); | ||
1398 | else | ||
1399 | adm8211_set_bssid(dev, priv->bssid); | ||
1400 | |||
1401 | ADM8211_RESTORE(); | ||
1402 | |||
1403 | *total_flags = new_flags; | ||
1404 | } | ||
1405 | |||
1398 | static int adm8211_add_interface(struct ieee80211_hw *dev, | 1406 | static int adm8211_add_interface(struct ieee80211_hw *dev, |
1399 | struct ieee80211_if_init_conf *conf) | 1407 | struct ieee80211_if_init_conf *conf) |
1400 | { | 1408 | { |
1401 | struct adm8211_priv *priv = dev->priv; | 1409 | struct adm8211_priv *priv = dev->priv; |
1402 | /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */ | 1410 | if (priv->mode != IEEE80211_IF_TYPE_MNTR) |
1403 | if (priv->mode != IEEE80211_IF_TYPE_MGMT) | 1411 | return -EOPNOTSUPP; |
1404 | return -1; | ||
1405 | 1412 | ||
1406 | switch (conf->type) { | 1413 | switch (conf->type) { |
1407 | case IEEE80211_IF_TYPE_STA: | 1414 | case IEEE80211_IF_TYPE_STA: |
1408 | case IEEE80211_IF_TYPE_MNTR: | ||
1409 | priv->mode = conf->type; | 1415 | priv->mode = conf->type; |
1410 | break; | 1416 | break; |
1411 | default: | 1417 | default: |
1412 | return -EOPNOTSUPP; | 1418 | return -EOPNOTSUPP; |
1413 | } | 1419 | } |
1414 | 1420 | ||
1415 | priv->mac_addr = conf->mac_addr; | 1421 | ADM8211_IDLE(); |
1422 | |||
1423 | ADM8211_CSR_WRITE(PAR0, *(u32 *)conf->mac_addr); | ||
1424 | ADM8211_CSR_WRITE(PAR1, *(u16 *)(conf->mac_addr + 4)); | ||
1425 | |||
1426 | adm8211_update_mode(dev); | ||
1427 | |||
1428 | ADM8211_RESTORE(); | ||
1416 | 1429 | ||
1417 | return 0; | 1430 | return 0; |
1418 | } | 1431 | } |
@@ -1421,7 +1434,7 @@ static void adm8211_remove_interface(struct ieee80211_hw *dev, | |||
1421 | struct ieee80211_if_init_conf *conf) | 1434 | struct ieee80211_if_init_conf *conf) |
1422 | { | 1435 | { |
1423 | struct adm8211_priv *priv = dev->priv; | 1436 | struct adm8211_priv *priv = dev->priv; |
1424 | priv->mode = IEEE80211_IF_TYPE_MGMT; | 1437 | priv->mode = IEEE80211_IF_TYPE_MNTR; |
1425 | } | 1438 | } |
1426 | 1439 | ||
1427 | static int adm8211_init_rings(struct ieee80211_hw *dev) | 1440 | static int adm8211_init_rings(struct ieee80211_hw *dev) |
@@ -1505,7 +1518,7 @@ static void adm8211_free_rings(struct ieee80211_hw *dev) | |||
1505 | } | 1518 | } |
1506 | } | 1519 | } |
1507 | 1520 | ||
1508 | static int adm8211_open(struct ieee80211_hw *dev) | 1521 | static int adm8211_start(struct ieee80211_hw *dev) |
1509 | { | 1522 | { |
1510 | struct adm8211_priv *priv = dev->priv; | 1523 | struct adm8211_priv *priv = dev->priv; |
1511 | int retval; | 1524 | int retval; |
@@ -1550,7 +1563,7 @@ fail: | |||
1550 | return retval; | 1563 | return retval; |
1551 | } | 1564 | } |
1552 | 1565 | ||
1553 | static int adm8211_stop(struct ieee80211_hw *dev) | 1566 | static void adm8211_stop(struct ieee80211_hw *dev) |
1554 | { | 1567 | { |
1555 | struct adm8211_priv *priv = dev->priv; | 1568 | struct adm8211_priv *priv = dev->priv; |
1556 | 1569 | ||
@@ -1562,7 +1575,6 @@ static int adm8211_stop(struct ieee80211_hw *dev) | |||
1562 | free_irq(priv->pdev->irq, dev); | 1575 | free_irq(priv->pdev->irq, dev); |
1563 | 1576 | ||
1564 | adm8211_free_rings(dev); | 1577 | adm8211_free_rings(dev); |
1565 | return 0; | ||
1566 | } | 1578 | } |
1567 | 1579 | ||
1568 | static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int len, | 1580 | static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int len, |
@@ -1765,13 +1777,13 @@ static int adm8211_alloc_rings(struct ieee80211_hw *dev) | |||
1765 | 1777 | ||
1766 | static const struct ieee80211_ops adm8211_ops = { | 1778 | static const struct ieee80211_ops adm8211_ops = { |
1767 | .tx = adm8211_tx, | 1779 | .tx = adm8211_tx, |
1768 | .open = adm8211_open, | 1780 | .start = adm8211_start, |
1769 | .stop = adm8211_stop, | 1781 | .stop = adm8211_stop, |
1770 | .add_interface = adm8211_add_interface, | 1782 | .add_interface = adm8211_add_interface, |
1771 | .remove_interface = adm8211_remove_interface, | 1783 | .remove_interface = adm8211_remove_interface, |
1772 | .config = adm8211_config, | 1784 | .config = adm8211_config, |
1773 | .config_interface = adm8211_config_interface, | 1785 | .config_interface = adm8211_config_interface, |
1774 | .set_multicast_list = adm8211_set_rx_mode, | 1786 | .configure_filter = adm8211_configure_filter, |
1775 | .get_stats = adm8211_get_stats, | 1787 | .get_stats = adm8211_get_stats, |
1776 | .get_tx_stats = adm8211_get_tx_stats, | 1788 | .get_tx_stats = adm8211_get_tx_stats, |
1777 | .get_tsf = adm8211_get_tsft | 1789 | .get_tsf = adm8211_get_tsft |
@@ -1905,7 +1917,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, | |||
1905 | priv->tx_power = 0x40; | 1917 | priv->tx_power = 0x40; |
1906 | priv->lpf_cutoff = 0xFF; | 1918 | priv->lpf_cutoff = 0xFF; |
1907 | priv->lnags_threshold = 0xFF; | 1919 | priv->lnags_threshold = 0xFF; |
1908 | priv->mode = IEEE80211_IF_TYPE_MGMT; | 1920 | priv->mode = IEEE80211_IF_TYPE_MNTR; |
1909 | 1921 | ||
1910 | /* Power-on issue. EEPROM won't read correctly without */ | 1922 | /* Power-on issue. EEPROM won't read correctly without */ |
1911 | if (priv->revid >= ADM8211_REV_BA) { | 1923 | if (priv->revid >= ADM8211_REV_BA) { |
@@ -2000,7 +2012,7 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2000 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); | 2012 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); |
2001 | struct adm8211_priv *priv = dev->priv; | 2013 | struct adm8211_priv *priv = dev->priv; |
2002 | 2014 | ||
2003 | if (priv->mode != IEEE80211_IF_TYPE_MGMT) { | 2015 | if (priv->mode != IEEE80211_IF_TYPE_MNTR) { |
2004 | ieee80211_stop_queues(dev); | 2016 | ieee80211_stop_queues(dev); |
2005 | adm8211_stop(dev); | 2017 | adm8211_stop(dev); |
2006 | } | 2018 | } |
@@ -2018,8 +2030,8 @@ static int adm8211_resume(struct pci_dev *pdev) | |||
2018 | pci_set_power_state(pdev, PCI_D0); | 2030 | pci_set_power_state(pdev, PCI_D0); |
2019 | pci_restore_state(pdev); | 2031 | pci_restore_state(pdev); |
2020 | 2032 | ||
2021 | if (priv->mode != IEEE80211_IF_TYPE_MGMT) { | 2033 | if (priv->mode != IEEE80211_IF_TYPE_MNTR) { |
2022 | adm8211_open(dev); | 2034 | adm8211_start(dev); |
2023 | ieee80211_start_queues(dev); | 2035 | ieee80211_start_queues(dev); |
2024 | } | 2036 | } |
2025 | 2037 | ||
diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h index 795d895f5c99..5991b17c4a7b 100644 --- a/drivers/net/wireless/adm8211.h +++ b/drivers/net/wireless/adm8211.h | |||
@@ -612,7 +612,6 @@ struct adm8211_priv { | |||
612 | u8 bssid[ETH_ALEN]; | 612 | u8 bssid[ETH_ALEN]; |
613 | u8 ssid[32]; | 613 | u8 ssid[32]; |
614 | size_t ssid_len; | 614 | size_t ssid_len; |
615 | u8 *mac_addr; | ||
616 | 615 | ||
617 | u8 soft_rx_crc; | 616 | u8 soft_rx_crc; |
618 | u8 retry_limit; | 617 | u8 retry_limit; |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index a22435ade8ca..2c8fa1c3465e 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -604,9 +604,8 @@ struct b43_wl { | |||
604 | * at a time. General information about this interface follows. | 604 | * at a time. General information about this interface follows. |
605 | */ | 605 | */ |
606 | 606 | ||
607 | /* Opaque ID of the operating interface (!= monitor | 607 | /* Opaque ID of the operating interface from the ieee80211 |
608 | * interface) from the ieee80211 subsystem. | 608 | * subsystem. Do not modify. |
609 | * Do not modify. | ||
610 | */ | 609 | */ |
611 | int if_id; | 610 | int if_id; |
612 | /* The MAC address of the operating interface. */ | 611 | /* The MAC address of the operating interface. */ |
@@ -615,14 +614,10 @@ struct b43_wl { | |||
615 | u8 bssid[ETH_ALEN]; | 614 | u8 bssid[ETH_ALEN]; |
616 | /* Interface type. (IEEE80211_IF_TYPE_XXX) */ | 615 | /* Interface type. (IEEE80211_IF_TYPE_XXX) */ |
617 | int if_type; | 616 | int if_type; |
618 | /* Counter of active monitor interfaces. */ | ||
619 | int monitor; | ||
620 | /* Is the card operating in AP, STA or IBSS mode? */ | 617 | /* Is the card operating in AP, STA or IBSS mode? */ |
621 | bool operating; | 618 | bool operating; |
622 | /* Promisc mode active? | 619 | /* filter flags */ |
623 | * Note that (monitor != 0) implies promisc. | 620 | unsigned int filter_flags; |
624 | */ | ||
625 | bool promisc; | ||
626 | /* Stats about the wireless interface */ | 621 | /* Stats about the wireless interface */ |
627 | struct ieee80211_low_level_stats ieee_stats; | 622 | struct ieee80211_low_level_stats ieee_stats; |
628 | 623 | ||
@@ -779,8 +774,6 @@ static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev) | |||
779 | /* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */ | 774 | /* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */ |
780 | static inline int b43_is_mode(struct b43_wl *wl, int type) | 775 | static inline int b43_is_mode(struct b43_wl *wl, int type) |
781 | { | 776 | { |
782 | if (type == IEEE80211_IF_TYPE_MNTR) | ||
783 | return !!(wl->monitor); | ||
784 | return (wl->operating && wl->if_type == type); | 777 | return (wl->operating && wl->if_type == type); |
785 | } | 778 | } |
786 | 779 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b44c9f928848..72467c86f8d4 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -92,14 +92,6 @@ static char modparam_fwpostfix[16]; | |||
92 | module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); | 92 | module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); |
93 | MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load."); | 93 | MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load."); |
94 | 94 | ||
95 | static int modparam_mon_keep_bad; | ||
96 | module_param_named(mon_keep_bad, modparam_mon_keep_bad, int, 0444); | ||
97 | MODULE_PARM_DESC(mon_keep_bad, "Keep bad frames in monitor mode"); | ||
98 | |||
99 | static int modparam_mon_keep_badplcp; | ||
100 | module_param_named(mon_keep_badplcp, modparam_mon_keep_bad, int, 0444); | ||
101 | MODULE_PARM_DESC(mon_keep_badplcp, "Keep frames with bad PLCP in monitor mode"); | ||
102 | |||
103 | static int modparam_hwpctl; | 95 | static int modparam_hwpctl; |
104 | module_param_named(hwpctl, modparam_hwpctl, int, 0444); | 96 | module_param_named(hwpctl, modparam_hwpctl, int, 0444); |
105 | MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)"); | 97 | MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)"); |
@@ -561,15 +553,10 @@ static void b43_write_mac_bssid_templates(struct b43_wldev *dev) | |||
561 | } | 553 | } |
562 | } | 554 | } |
563 | 555 | ||
564 | static void b43_upload_card_macaddress(struct b43_wldev *dev, | 556 | static void b43_upload_card_macaddress(struct b43_wldev *dev) |
565 | const u8 * mac_addr) | ||
566 | { | 557 | { |
567 | if (mac_addr) | ||
568 | memcpy(dev->wl->mac_addr, mac_addr, ETH_ALEN); | ||
569 | else | ||
570 | memset(dev->wl->mac_addr, 0, ETH_ALEN); | ||
571 | b43_write_mac_bssid_templates(dev); | 558 | b43_write_mac_bssid_templates(dev); |
572 | b43_macfilter_set(dev, B43_MACFILTER_SELF, mac_addr); | 559 | b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr); |
573 | } | 560 | } |
574 | 561 | ||
575 | static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) | 562 | static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) |
@@ -2052,33 +2039,25 @@ static void b43_adjust_opmode(struct b43_wldev *dev) | |||
2052 | ctl &= ~B43_MACCTL_KEEP_BADPLCP; | 2039 | ctl &= ~B43_MACCTL_KEEP_BADPLCP; |
2053 | ctl &= ~B43_MACCTL_KEEP_BAD; | 2040 | ctl &= ~B43_MACCTL_KEEP_BAD; |
2054 | ctl &= ~B43_MACCTL_PROMISC; | 2041 | ctl &= ~B43_MACCTL_PROMISC; |
2042 | ctl &= ~B43_MACCTL_BEACPROMISC; | ||
2055 | ctl |= B43_MACCTL_INFRA; | 2043 | ctl |= B43_MACCTL_INFRA; |
2056 | 2044 | ||
2057 | if (wl->operating) { | 2045 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) |
2058 | switch (wl->if_type) { | 2046 | ctl |= B43_MACCTL_AP; |
2059 | case IEEE80211_IF_TYPE_AP: | 2047 | else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) |
2060 | ctl |= B43_MACCTL_AP; | 2048 | ctl &= ~B43_MACCTL_INFRA; |
2061 | break; | 2049 | |
2062 | case IEEE80211_IF_TYPE_IBSS: | 2050 | if (wl->filter_flags & FIF_CONTROL) |
2063 | ctl &= ~B43_MACCTL_INFRA; | ||
2064 | break; | ||
2065 | case IEEE80211_IF_TYPE_STA: | ||
2066 | case IEEE80211_IF_TYPE_MNTR: | ||
2067 | case IEEE80211_IF_TYPE_WDS: | ||
2068 | break; | ||
2069 | default: | ||
2070 | B43_WARN_ON(1); | ||
2071 | } | ||
2072 | } | ||
2073 | if (wl->monitor) { | ||
2074 | ctl |= B43_MACCTL_KEEP_CTL; | 2051 | ctl |= B43_MACCTL_KEEP_CTL; |
2075 | if (modparam_mon_keep_bad) | 2052 | if (wl->filter_flags & FIF_FCSFAIL) |
2076 | ctl |= B43_MACCTL_KEEP_BAD; | 2053 | ctl |= B43_MACCTL_KEEP_BAD; |
2077 | if (modparam_mon_keep_badplcp) | 2054 | if (wl->filter_flags & FIF_PLCPFAIL) |
2078 | ctl |= B43_MACCTL_KEEP_BADPLCP; | 2055 | ctl |= B43_MACCTL_KEEP_BADPLCP; |
2079 | } | 2056 | if (wl->filter_flags & FIF_PROMISC_IN_BSS) |
2080 | if (wl->promisc) | ||
2081 | ctl |= B43_MACCTL_PROMISC; | 2057 | ctl |= B43_MACCTL_PROMISC; |
2058 | if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC) | ||
2059 | ctl |= B43_MACCTL_BEACPROMISC; | ||
2060 | |||
2082 | /* Workaround: On old hardware the HW-MAC-address-filter | 2061 | /* Workaround: On old hardware the HW-MAC-address-filter |
2083 | * doesn't work properly, so always run promisc in filter | 2062 | * doesn't work properly, so always run promisc in filter |
2084 | * it in software. */ | 2063 | * it in software. */ |
@@ -2254,9 +2233,6 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
2254 | & ~B43_MACCTL_INFRA); | 2233 | & ~B43_MACCTL_INFRA); |
2255 | b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) | 2234 | b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) |
2256 | | B43_MACCTL_INFRA); | 2235 | | B43_MACCTL_INFRA); |
2257 | /* Let beacons come through */ | ||
2258 | b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) | ||
2259 | | B43_MACCTL_BEACPROMISC); | ||
2260 | 2236 | ||
2261 | if (b43_using_pio(dev)) { | 2237 | if (b43_using_pio(dev)) { |
2262 | b43_write32(dev, 0x0210, 0x00000100); | 2238 | b43_write32(dev, 0x0210, 0x00000100); |
@@ -2899,9 +2875,9 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
2899 | return err; | 2875 | return err; |
2900 | } | 2876 | } |
2901 | 2877 | ||
2902 | static int b43_dev_set_key(struct ieee80211_hw *hw, | 2878 | static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
2903 | set_key_cmd cmd, const u8 *local_addr, | 2879 | const u8 *local_addr, const u8 *addr, |
2904 | const u8 *addr, struct ieee80211_key_conf *key) | 2880 | struct ieee80211_key_conf *key) |
2905 | { | 2881 | { |
2906 | struct b43_wl *wl = hw_to_b43_wl(hw); | 2882 | struct b43_wl *wl = hw_to_b43_wl(hw); |
2907 | struct b43_wldev *dev = wl->current_dev; | 2883 | struct b43_wldev *dev = wl->current_dev; |
@@ -3003,21 +2979,40 @@ out: | |||
3003 | return err; | 2979 | return err; |
3004 | } | 2980 | } |
3005 | 2981 | ||
3006 | static void b43_set_multicast_list(struct ieee80211_hw *hw, | 2982 | static void b43_configure_filter(struct ieee80211_hw *hw, |
3007 | unsigned short netflags, int mc_count) | 2983 | unsigned int changed, unsigned int *fflags, |
2984 | int mc_count, struct dev_addr_list *mc_list) | ||
3008 | { | 2985 | { |
3009 | struct b43_wl *wl = hw_to_b43_wl(hw); | 2986 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3010 | struct b43_wldev *dev = wl->current_dev; | 2987 | struct b43_wldev *dev = wl->current_dev; |
3011 | unsigned long flags; | 2988 | unsigned long flags; |
3012 | 2989 | ||
3013 | if (!dev) | 2990 | if (!dev) { |
2991 | *fflags = 0; | ||
3014 | return; | 2992 | return; |
3015 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3016 | if (wl->promisc != !!(netflags & IFF_PROMISC)) { | ||
3017 | wl->promisc = !!(netflags & IFF_PROMISC); | ||
3018 | if (b43_status(dev) >= B43_STAT_INITIALIZED) | ||
3019 | b43_adjust_opmode(dev); | ||
3020 | } | 2993 | } |
2994 | |||
2995 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2996 | *fflags &= FIF_PROMISC_IN_BSS | | ||
2997 | FIF_ALLMULTI | | ||
2998 | FIF_FCSFAIL | | ||
2999 | FIF_PLCPFAIL | | ||
3000 | FIF_CONTROL | | ||
3001 | FIF_OTHER_BSS | | ||
3002 | FIF_BCN_PRBRESP_PROMISC; | ||
3003 | |||
3004 | changed &= FIF_PROMISC_IN_BSS | | ||
3005 | FIF_ALLMULTI | | ||
3006 | FIF_FCSFAIL | | ||
3007 | FIF_PLCPFAIL | | ||
3008 | FIF_CONTROL | | ||
3009 | FIF_OTHER_BSS | | ||
3010 | FIF_BCN_PRBRESP_PROMISC; | ||
3011 | |||
3012 | wl->filter_flags = *fflags; | ||
3013 | |||
3014 | if (changed && b43_status(dev) >= B43_STAT_INITIALIZED) | ||
3015 | b43_adjust_opmode(dev); | ||
3021 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 3016 | spin_unlock_irqrestore(&wl->irq_lock, flags); |
3022 | } | 3017 | } |
3023 | 3018 | ||
@@ -3032,21 +3027,19 @@ static int b43_config_interface(struct ieee80211_hw *hw, | |||
3032 | return -ENODEV; | 3027 | return -ENODEV; |
3033 | mutex_lock(&wl->mutex); | 3028 | mutex_lock(&wl->mutex); |
3034 | spin_lock_irqsave(&wl->irq_lock, flags); | 3029 | spin_lock_irqsave(&wl->irq_lock, flags); |
3035 | if (conf->type != IEEE80211_IF_TYPE_MNTR) { | 3030 | B43_WARN_ON(wl->if_id != if_id); |
3036 | B43_WARN_ON(wl->if_id != if_id); | 3031 | if (conf->bssid) |
3037 | if (conf->bssid) | 3032 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); |
3038 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | 3033 | else |
3039 | else | 3034 | memset(wl->bssid, 0, ETH_ALEN); |
3040 | memset(wl->bssid, 0, ETH_ALEN); | 3035 | if (b43_status(dev) >= B43_STAT_INITIALIZED) { |
3041 | if (b43_status(dev) >= B43_STAT_INITIALIZED) { | 3036 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { |
3042 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { | 3037 | B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); |
3043 | B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); | 3038 | b43_set_ssid(dev, conf->ssid, conf->ssid_len); |
3044 | b43_set_ssid(dev, conf->ssid, conf->ssid_len); | 3039 | if (conf->beacon) |
3045 | if (conf->beacon) | 3040 | b43_refresh_templates(dev, conf->beacon); |
3046 | b43_refresh_templates(dev, conf->beacon); | ||
3047 | } | ||
3048 | b43_write_mac_bssid_templates(dev); | ||
3049 | } | 3041 | } |
3042 | b43_write_mac_bssid_templates(dev); | ||
3050 | } | 3043 | } |
3051 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 3044 | spin_unlock_irqrestore(&wl->irq_lock, flags); |
3052 | mutex_unlock(&wl->mutex); | 3045 | mutex_unlock(&wl->mutex); |
@@ -3472,7 +3465,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
3472 | 3465 | ||
3473 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ | 3466 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ |
3474 | memset(wl->bssid, 0, ETH_ALEN); | 3467 | memset(wl->bssid, 0, ETH_ALEN); |
3475 | b43_upload_card_macaddress(dev, NULL); | 3468 | memset(wl->mac_addr, 0, ETH_ALEN); |
3469 | b43_upload_card_macaddress(dev); | ||
3476 | b43_security_init(dev); | 3470 | b43_security_init(dev); |
3477 | b43_rng_init(wl); | 3471 | b43_rng_init(wl); |
3478 | 3472 | ||
@@ -3502,21 +3496,80 @@ static int b43_add_interface(struct ieee80211_hw *hw, | |||
3502 | struct b43_wldev *dev; | 3496 | struct b43_wldev *dev; |
3503 | unsigned long flags; | 3497 | unsigned long flags; |
3504 | int err = -EOPNOTSUPP; | 3498 | int err = -EOPNOTSUPP; |
3505 | int did_init = 0; | 3499 | |
3500 | /* TODO: allow WDS/AP devices to coexist */ | ||
3501 | |||
3502 | if (conf->type != IEEE80211_IF_TYPE_AP && | ||
3503 | conf->type != IEEE80211_IF_TYPE_STA && | ||
3504 | conf->type != IEEE80211_IF_TYPE_WDS && | ||
3505 | conf->type != IEEE80211_IF_TYPE_IBSS) | ||
3506 | return -EOPNOTSUPP; | ||
3506 | 3507 | ||
3507 | mutex_lock(&wl->mutex); | 3508 | mutex_lock(&wl->mutex); |
3508 | if ((conf->type != IEEE80211_IF_TYPE_MNTR) && wl->operating) | 3509 | if (wl->operating) |
3509 | goto out_mutex_unlock; | 3510 | goto out_mutex_unlock; |
3510 | 3511 | ||
3511 | b43dbg(wl, "Adding Interface type %d\n", conf->type); | 3512 | b43dbg(wl, "Adding Interface type %d\n", conf->type); |
3512 | 3513 | ||
3513 | dev = wl->current_dev; | 3514 | dev = wl->current_dev; |
3515 | wl->operating = 1; | ||
3516 | wl->if_id = conf->if_id; | ||
3517 | wl->if_type = conf->type; | ||
3518 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | ||
3519 | |||
3520 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3521 | b43_adjust_opmode(dev); | ||
3522 | b43_upload_card_macaddress(dev); | ||
3523 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3524 | |||
3525 | err = 0; | ||
3526 | out_mutex_unlock: | ||
3527 | mutex_unlock(&wl->mutex); | ||
3528 | |||
3529 | return err; | ||
3530 | } | ||
3531 | |||
3532 | static void b43_remove_interface(struct ieee80211_hw *hw, | ||
3533 | struct ieee80211_if_init_conf *conf) | ||
3534 | { | ||
3535 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
3536 | struct b43_wldev *dev = wl->current_dev; | ||
3537 | unsigned long flags; | ||
3538 | |||
3539 | b43dbg(wl, "Removing Interface type %d\n", conf->type); | ||
3540 | |||
3541 | mutex_lock(&wl->mutex); | ||
3542 | |||
3543 | B43_WARN_ON(!wl->operating); | ||
3544 | B43_WARN_ON(wl->if_id != conf->if_id); | ||
3545 | |||
3546 | wl->operating = 0; | ||
3547 | |||
3548 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3549 | b43_adjust_opmode(dev); | ||
3550 | memset(wl->mac_addr, 0, ETH_ALEN); | ||
3551 | b43_upload_card_macaddress(dev); | ||
3552 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3553 | |||
3554 | mutex_unlock(&wl->mutex); | ||
3555 | } | ||
3556 | |||
3557 | static int b43_start(struct ieee80211_hw *hw) | ||
3558 | { | ||
3559 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
3560 | struct b43_wldev *dev = wl->current_dev; | ||
3561 | int did_init = 0; | ||
3562 | int err; | ||
3563 | |||
3564 | mutex_lock(&wl->mutex); | ||
3565 | |||
3514 | if (b43_status(dev) < B43_STAT_INITIALIZED) { | 3566 | if (b43_status(dev) < B43_STAT_INITIALIZED) { |
3515 | err = b43_wireless_core_init(dev); | 3567 | err = b43_wireless_core_init(dev); |
3516 | if (err) | 3568 | if (err) |
3517 | goto out_mutex_unlock; | 3569 | goto out_mutex_unlock; |
3518 | did_init = 1; | 3570 | did_init = 1; |
3519 | } | 3571 | } |
3572 | |||
3520 | if (b43_status(dev) < B43_STAT_STARTED) { | 3573 | if (b43_status(dev) < B43_STAT_STARTED) { |
3521 | err = b43_wireless_core_start(dev); | 3574 | err = b43_wireless_core_start(dev); |
3522 | if (err) { | 3575 | if (err) { |
@@ -3526,59 +3579,21 @@ static int b43_add_interface(struct ieee80211_hw *hw, | |||
3526 | } | 3579 | } |
3527 | } | 3580 | } |
3528 | 3581 | ||
3529 | spin_lock_irqsave(&wl->irq_lock, flags); | 3582 | out_mutex_unlock: |
3530 | switch (conf->type) { | ||
3531 | case IEEE80211_IF_TYPE_MNTR: | ||
3532 | wl->monitor++; | ||
3533 | break; | ||
3534 | default: | ||
3535 | wl->operating = 1; | ||
3536 | wl->if_id = conf->if_id; | ||
3537 | wl->if_type = conf->type; | ||
3538 | b43_upload_card_macaddress(dev, conf->mac_addr); | ||
3539 | } | ||
3540 | b43_adjust_opmode(dev); | ||
3541 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3542 | |||
3543 | err = 0; | ||
3544 | out_mutex_unlock: | ||
3545 | mutex_unlock(&wl->mutex); | 3583 | mutex_unlock(&wl->mutex); |
3546 | 3584 | ||
3547 | return err; | 3585 | return err; |
3548 | } | 3586 | } |
3549 | 3587 | ||
3550 | static void b43_remove_interface(struct ieee80211_hw *hw, | 3588 | void b43_stop(struct ieee80211_hw *hw) |
3551 | struct ieee80211_if_init_conf *conf) | ||
3552 | { | 3589 | { |
3553 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3590 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3554 | struct b43_wldev *dev; | 3591 | struct b43_wldev *dev = wl->current_dev; |
3555 | unsigned long flags; | ||
3556 | |||
3557 | b43dbg(wl, "Removing Interface type %d\n", conf->type); | ||
3558 | 3592 | ||
3559 | mutex_lock(&wl->mutex); | 3593 | mutex_lock(&wl->mutex); |
3560 | if (conf->type == IEEE80211_IF_TYPE_MNTR) { | 3594 | if (b43_status(dev) >= B43_STAT_STARTED) |
3561 | wl->monitor--; | 3595 | b43_wireless_core_stop(dev); |
3562 | B43_WARN_ON(wl->monitor < 0); | 3596 | b43_wireless_core_exit(dev); |
3563 | } else { | ||
3564 | B43_WARN_ON(!wl->operating); | ||
3565 | wl->operating = 0; | ||
3566 | } | ||
3567 | |||
3568 | dev = wl->current_dev; | ||
3569 | if (!wl->operating && wl->monitor == 0) { | ||
3570 | /* No interface left. */ | ||
3571 | if (b43_status(dev) >= B43_STAT_STARTED) | ||
3572 | b43_wireless_core_stop(dev); | ||
3573 | b43_wireless_core_exit(dev); | ||
3574 | } else { | ||
3575 | /* Just monitor interfaces left. */ | ||
3576 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3577 | b43_adjust_opmode(dev); | ||
3578 | if (!wl->operating) | ||
3579 | b43_upload_card_macaddress(dev, NULL); | ||
3580 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3581 | } | ||
3582 | mutex_unlock(&wl->mutex); | 3597 | mutex_unlock(&wl->mutex); |
3583 | } | 3598 | } |
3584 | 3599 | ||
@@ -3589,10 +3604,12 @@ static const struct ieee80211_ops b43_hw_ops = { | |||
3589 | .remove_interface = b43_remove_interface, | 3604 | .remove_interface = b43_remove_interface, |
3590 | .config = b43_dev_config, | 3605 | .config = b43_dev_config, |
3591 | .config_interface = b43_config_interface, | 3606 | .config_interface = b43_config_interface, |
3592 | .set_multicast_list = b43_set_multicast_list, | 3607 | .configure_filter = b43_configure_filter, |
3593 | .set_key = b43_dev_set_key, | 3608 | .set_key = b43_dev_set_key, |
3594 | .get_stats = b43_get_stats, | 3609 | .get_stats = b43_get_stats, |
3595 | .get_tx_stats = b43_get_tx_stats, | 3610 | .get_tx_stats = b43_get_tx_stats, |
3611 | .start = b43_start, | ||
3612 | .stop = b43_stop, | ||
3596 | }; | 3613 | }; |
3597 | 3614 | ||
3598 | /* Hard-reset the chip. Do not call this directly. | 3615 | /* Hard-reset the chip. Do not call this directly. |
@@ -3930,8 +3947,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
3930 | } | 3947 | } |
3931 | 3948 | ||
3932 | /* fill hw info */ | 3949 | /* fill hw info */ |
3933 | hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | | 3950 | hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; |
3934 | IEEE80211_HW_MONITOR_DURING_OPER; | ||
3935 | hw->max_signal = 100; | 3951 | hw->max_signal = 100; |
3936 | hw->max_rssi = -110; | 3952 | hw->max_rssi = -110; |
3937 | hw->max_noise = -110; | 3953 | hw->max_noise = -110; |
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 746de2ff498c..afe145cec067 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h | |||
@@ -179,6 +179,7 @@ | |||
179 | #define B43legacy_MACCTL_IHR_ENABLED 0x00000400 /* IHR Region Enabled */ | 179 | #define B43legacy_MACCTL_IHR_ENABLED 0x00000400 /* IHR Region Enabled */ |
180 | #define B43legacy_MACCTL_INFRA 0x00020000 /* Infrastructure mode */ | 180 | #define B43legacy_MACCTL_INFRA 0x00020000 /* Infrastructure mode */ |
181 | #define B43legacy_MACCTL_AP 0x00040000 /* AccessPoint mode */ | 181 | #define B43legacy_MACCTL_AP 0x00040000 /* AccessPoint mode */ |
182 | #define B43legacy_MACCTL_BEACPROMISC 0x00100000 /* Beacon Promiscuous */ | ||
182 | #define B43legacy_MACCTL_KEEP_BADPLCP 0x00200000 /* Keep bad PLCP frames */ | 183 | #define B43legacy_MACCTL_KEEP_BADPLCP 0x00200000 /* Keep bad PLCP frames */ |
183 | #define B43legacy_MACCTL_KEEP_CTL 0x00400000 /* Keep control frames */ | 184 | #define B43legacy_MACCTL_KEEP_CTL 0x00400000 /* Keep control frames */ |
184 | #define B43legacy_MACCTL_KEEP_BAD 0x00800000 /* Keep bad frames (FCS) */ | 185 | #define B43legacy_MACCTL_KEEP_BAD 0x00800000 /* Keep bad frames (FCS) */ |
@@ -570,25 +571,20 @@ struct b43legacy_wl { | |||
570 | * at a time. General information about this interface follows. | 571 | * at a time. General information about this interface follows. |
571 | */ | 572 | */ |
572 | 573 | ||
573 | /* Opaque ID of the operating interface (!= monitor | 574 | /* Opaque ID of the operating interface from the ieee80211 |
574 | * interface) from the ieee80211 subsystem. | 575 | * subsystem. Do not modify. |
575 | * Do not modify. | ||
576 | */ | 576 | */ |
577 | int if_id; | 577 | int if_id; |
578 | /* MAC address (can be NULL). */ | 578 | /* MAC address (can be NULL). */ |
579 | const u8 *mac_addr; | 579 | u8 mac_addr[ETH_ALEN]; |
580 | /* Current BSSID (can be NULL). */ | 580 | /* Current BSSID (can be NULL). */ |
581 | const u8 *bssid; | 581 | u8 bssid[ETH_ALEN]; |
582 | /* Interface type. (IEEE80211_IF_TYPE_XXX) */ | 582 | /* Interface type. (IEEE80211_IF_TYPE_XXX) */ |
583 | int if_type; | 583 | int if_type; |
584 | /* Counter of active monitor interfaces. */ | ||
585 | int monitor; | ||
586 | /* Is the card operating in AP, STA or IBSS mode? */ | 584 | /* Is the card operating in AP, STA or IBSS mode? */ |
587 | bool operating; | 585 | bool operating; |
588 | /* Promisc mode active? | 586 | /* filter flags */ |
589 | * Note that (monitor != 0) implies promisc. | 587 | unsigned int filter_flags; |
590 | */ | ||
591 | bool promisc; | ||
592 | /* Stats about the wireless interface */ | 588 | /* Stats about the wireless interface */ |
593 | struct ieee80211_low_level_stats ieee_stats; | 589 | struct ieee80211_low_level_stats ieee_stats; |
594 | 590 | ||
@@ -753,8 +749,6 @@ struct b43legacy_wldev *dev_to_b43legacy_wldev(struct device *dev) | |||
753 | static inline | 749 | static inline |
754 | int b43legacy_is_mode(struct b43legacy_wl *wl, int type) | 750 | int b43legacy_is_mode(struct b43legacy_wl *wl, int type) |
755 | { | 751 | { |
756 | if (type == IEEE80211_IF_TYPE_MNTR) | ||
757 | return !!(wl->monitor); | ||
758 | return (wl->operating && | 752 | return (wl->operating && |
759 | wl->if_type == type); | 753 | wl->if_type == type); |
760 | } | 754 | } |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index a793f183a2c0..f0749510bcd7 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -91,14 +91,6 @@ static char modparam_fwpostfix[16]; | |||
91 | module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); | 91 | module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); |
92 | MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load."); | 92 | MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load."); |
93 | 93 | ||
94 | static int modparam_mon_keep_bad; | ||
95 | module_param_named(mon_keep_bad, modparam_mon_keep_bad, int, 0444); | ||
96 | MODULE_PARM_DESC(mon_keep_bad, "Keep bad frames in monitor mode"); | ||
97 | |||
98 | static int modparam_mon_keep_badplcp; | ||
99 | module_param_named(mon_keep_badplcp, modparam_mon_keep_bad, int, 0444); | ||
100 | MODULE_PARM_DESC(mon_keep_badplcp, "Keep frames with bad PLCP in monitor mode"); | ||
101 | |||
102 | /* The following table supports BCM4301, BCM4303 and BCM4306/2 devices. */ | 94 | /* The following table supports BCM4301, BCM4303 and BCM4306/2 devices. */ |
103 | static const struct ssb_device_id b43legacy_ssb_tbl[] = { | 95 | static const struct ssb_device_id b43legacy_ssb_tbl[] = { |
104 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2), | 96 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2), |
@@ -566,12 +558,11 @@ static void b43legacy_write_mac_bssid_templates(struct b43legacy_wldev *dev) | |||
566 | } | 558 | } |
567 | } | 559 | } |
568 | 560 | ||
569 | static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev, | 561 | static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev) |
570 | const u8 *mac_addr) | ||
571 | { | 562 | { |
572 | dev->wl->mac_addr = mac_addr; | ||
573 | b43legacy_write_mac_bssid_templates(dev); | 563 | b43legacy_write_mac_bssid_templates(dev); |
574 | b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF, mac_addr); | 564 | b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF, |
565 | dev->wl->mac_addr); | ||
575 | } | 566 | } |
576 | 567 | ||
577 | static void b43legacy_set_slot_time(struct b43legacy_wldev *dev, | 568 | static void b43legacy_set_slot_time(struct b43legacy_wldev *dev, |
@@ -1874,34 +1865,25 @@ static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev) | |||
1874 | ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP; | 1865 | ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP; |
1875 | ctl &= ~B43legacy_MACCTL_KEEP_BAD; | 1866 | ctl &= ~B43legacy_MACCTL_KEEP_BAD; |
1876 | ctl &= ~B43legacy_MACCTL_PROMISC; | 1867 | ctl &= ~B43legacy_MACCTL_PROMISC; |
1868 | ctl &= ~B43legacy_MACCTL_BEACPROMISC; | ||
1877 | ctl |= B43legacy_MACCTL_INFRA; | 1869 | ctl |= B43legacy_MACCTL_INFRA; |
1878 | 1870 | ||
1879 | if (wl->operating) { | 1871 | if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) |
1880 | switch (wl->if_type) { | 1872 | ctl |= B43legacy_MACCTL_AP; |
1881 | case IEEE80211_IF_TYPE_AP: | 1873 | else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) |
1882 | ctl |= B43legacy_MACCTL_AP; | 1874 | ctl &= ~B43legacy_MACCTL_INFRA; |
1883 | break; | 1875 | |
1884 | case IEEE80211_IF_TYPE_IBSS: | 1876 | if (wl->filter_flags & FIF_CONTROL) |
1885 | ctl &= ~B43legacy_MACCTL_INFRA; | ||
1886 | break; | ||
1887 | case IEEE80211_IF_TYPE_STA: | ||
1888 | case IEEE80211_IF_TYPE_MNTR: | ||
1889 | case IEEE80211_IF_TYPE_WDS: | ||
1890 | break; | ||
1891 | default: | ||
1892 | b43legacyerr(wl, "Improper value of %d for" | ||
1893 | " wl->if_type\n", wl->if_type); | ||
1894 | } | ||
1895 | } | ||
1896 | if (wl->monitor) { | ||
1897 | ctl |= B43legacy_MACCTL_KEEP_CTL; | 1877 | ctl |= B43legacy_MACCTL_KEEP_CTL; |
1898 | if (modparam_mon_keep_bad) | 1878 | if (wl->filter_flags & FIF_FCSFAIL) |
1899 | ctl |= B43legacy_MACCTL_KEEP_BAD; | 1879 | ctl |= B43legacy_MACCTL_KEEP_BAD; |
1900 | if (modparam_mon_keep_badplcp) | 1880 | if (wl->filter_flags & FIF_PLCPFAIL) |
1901 | ctl |= B43legacy_MACCTL_KEEP_BADPLCP; | 1881 | ctl |= B43legacy_MACCTL_KEEP_BADPLCP; |
1902 | } | 1882 | if (wl->filter_flags & FIF_PROMISC_IN_BSS) |
1903 | if (wl->promisc) | ||
1904 | ctl |= B43legacy_MACCTL_PROMISC; | 1883 | ctl |= B43legacy_MACCTL_PROMISC; |
1884 | if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC) | ||
1885 | ctl |= B43legacy_MACCTL_BEACPROMISC; | ||
1886 | |||
1905 | /* Workaround: On old hardware the HW-MAC-address-filter | 1887 | /* Workaround: On old hardware the HW-MAC-address-filter |
1906 | * doesn't work properly, so always run promisc in filter | 1888 | * doesn't work properly, so always run promisc in filter |
1907 | * it in software. */ | 1889 | * it in software. */ |
@@ -2091,10 +2073,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) | |||
2091 | value32 |= B43legacy_SBF_MODE_NOTADHOC; | 2073 | value32 |= B43legacy_SBF_MODE_NOTADHOC; |
2092 | b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); | 2074 | b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); |
2093 | 2075 | ||
2094 | value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); | ||
2095 | value32 |= 0x100000; | ||
2096 | b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); | ||
2097 | |||
2098 | if (b43legacy_using_pio(dev)) { | 2076 | if (b43legacy_using_pio(dev)) { |
2099 | b43legacy_write32(dev, 0x0210, 0x00000100); | 2077 | b43legacy_write32(dev, 0x0210, 0x00000100); |
2100 | b43legacy_write32(dev, 0x0230, 0x00000100); | 2078 | b43legacy_write32(dev, 0x0230, 0x00000100); |
@@ -2699,7 +2677,7 @@ out_unlock_mutex: | |||
2699 | } | 2677 | } |
2700 | 2678 | ||
2701 | static int b43legacy_dev_set_key(struct ieee80211_hw *hw, | 2679 | static int b43legacy_dev_set_key(struct ieee80211_hw *hw, |
2702 | set_key_cmd cmd, | 2680 | enum set_key_cmd cmd, |
2703 | const u8 *local_addr, const u8 *addr, | 2681 | const u8 *local_addr, const u8 *addr, |
2704 | struct ieee80211_key_conf *key) | 2682 | struct ieee80211_key_conf *key) |
2705 | { | 2683 | { |
@@ -2724,22 +2702,42 @@ static int b43legacy_dev_set_key(struct ieee80211_hw *hw, | |||
2724 | return err; | 2702 | return err; |
2725 | } | 2703 | } |
2726 | 2704 | ||
2727 | static void b43legacy_set_multicast_list(struct ieee80211_hw *hw, | 2705 | static void b43legacy_configure_filter(struct ieee80211_hw *hw, |
2728 | unsigned short netflags, | 2706 | unsigned int changed, |
2729 | int mc_count) | 2707 | unsigned int *fflags, |
2708 | int mc_count, | ||
2709 | struct dev_addr_list *mc_list) | ||
2730 | { | 2710 | { |
2731 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 2711 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
2732 | struct b43legacy_wldev *dev = wl->current_dev; | 2712 | struct b43legacy_wldev *dev = wl->current_dev; |
2733 | unsigned long flags; | 2713 | unsigned long flags; |
2734 | 2714 | ||
2735 | if (!dev) | 2715 | if (!dev) { |
2716 | *fflags = 0; | ||
2736 | return; | 2717 | return; |
2737 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2738 | if (wl->promisc != !!(netflags & IFF_PROMISC)) { | ||
2739 | wl->promisc = !!(netflags & IFF_PROMISC); | ||
2740 | if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) | ||
2741 | b43legacy_adjust_opmode(dev); | ||
2742 | } | 2718 | } |
2719 | |||
2720 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2721 | *fflags &= FIF_PROMISC_IN_BSS | | ||
2722 | FIF_ALLMULTI | | ||
2723 | FIF_FCSFAIL | | ||
2724 | FIF_PLCPFAIL | | ||
2725 | FIF_CONTROL | | ||
2726 | FIF_OTHER_BSS | | ||
2727 | FIF_BCN_PRBRESP_PROMISC; | ||
2728 | |||
2729 | changed &= FIF_PROMISC_IN_BSS | | ||
2730 | FIF_ALLMULTI | | ||
2731 | FIF_FCSFAIL | | ||
2732 | FIF_PLCPFAIL | | ||
2733 | FIF_CONTROL | | ||
2734 | FIF_OTHER_BSS | | ||
2735 | FIF_BCN_PRBRESP_PROMISC; | ||
2736 | |||
2737 | wl->filter_flags = *fflags; | ||
2738 | |||
2739 | if (changed && b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) | ||
2740 | b43legacy_adjust_opmode(dev); | ||
2743 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 2741 | spin_unlock_irqrestore(&wl->irq_lock, flags); |
2744 | } | 2742 | } |
2745 | 2743 | ||
@@ -2755,21 +2753,19 @@ static int b43legacy_config_interface(struct ieee80211_hw *hw, | |||
2755 | return -ENODEV; | 2753 | return -ENODEV; |
2756 | mutex_lock(&wl->mutex); | 2754 | mutex_lock(&wl->mutex); |
2757 | spin_lock_irqsave(&wl->irq_lock, flags); | 2755 | spin_lock_irqsave(&wl->irq_lock, flags); |
2758 | if (conf->type != IEEE80211_IF_TYPE_MNTR) { | 2756 | B43legacy_WARN_ON(wl->if_id != if_id); |
2759 | B43legacy_WARN_ON(wl->if_id != if_id); | 2757 | if (conf->bssid) |
2760 | wl->bssid = conf->bssid; | 2758 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); |
2761 | if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { | 2759 | else |
2762 | if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) { | 2760 | memset(wl->bssid, 0, ETH_ALEN); |
2763 | B43legacy_WARN_ON(conf->type != | 2761 | if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { |
2764 | IEEE80211_IF_TYPE_AP); | 2762 | if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) { |
2765 | b43legacy_set_ssid(dev, conf->ssid, | 2763 | B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); |
2766 | conf->ssid_len); | 2764 | b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len); |
2767 | if (conf->beacon) | 2765 | if (conf->beacon) |
2768 | b43legacy_refresh_templates(dev, | 2766 | b43legacy_refresh_templates(dev, conf->beacon); |
2769 | conf->beacon); | ||
2770 | } | ||
2771 | b43legacy_write_mac_bssid_templates(dev); | ||
2772 | } | 2767 | } |
2768 | b43legacy_write_mac_bssid_templates(dev); | ||
2773 | } | 2769 | } |
2774 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 2770 | spin_unlock_irqrestore(&wl->irq_lock, flags); |
2775 | mutex_unlock(&wl->mutex); | 2771 | mutex_unlock(&wl->mutex); |
@@ -3216,8 +3212,9 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) | |||
3216 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); | 3212 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); |
3217 | 3213 | ||
3218 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ | 3214 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ |
3219 | wl->bssid = NULL; | 3215 | memset(wl->bssid, 0, ETH_ALEN); |
3220 | b43legacy_upload_card_macaddress(dev, NULL); | 3216 | memset(wl->mac_addr, 0, ETH_ALEN); |
3217 | b43legacy_upload_card_macaddress(dev); | ||
3221 | b43legacy_security_init(dev); | 3218 | b43legacy_security_init(dev); |
3222 | b43legacy_rng_init(wl); | 3219 | b43legacy_rng_init(wl); |
3223 | 3220 | ||
@@ -3246,22 +3243,80 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw, | |||
3246 | struct b43legacy_wldev *dev; | 3243 | struct b43legacy_wldev *dev; |
3247 | unsigned long flags; | 3244 | unsigned long flags; |
3248 | int err = -EOPNOTSUPP; | 3245 | int err = -EOPNOTSUPP; |
3249 | int did_init = 0; | 3246 | |
3247 | /* TODO: allow WDS/AP devices to coexist */ | ||
3248 | |||
3249 | if (conf->type != IEEE80211_IF_TYPE_AP && | ||
3250 | conf->type != IEEE80211_IF_TYPE_STA && | ||
3251 | conf->type != IEEE80211_IF_TYPE_WDS && | ||
3252 | conf->type != IEEE80211_IF_TYPE_IBSS) | ||
3253 | return -EOPNOTSUPP; | ||
3250 | 3254 | ||
3251 | mutex_lock(&wl->mutex); | 3255 | mutex_lock(&wl->mutex); |
3252 | if ((conf->type != IEEE80211_IF_TYPE_MNTR) && | 3256 | if (wl->operating) |
3253 | wl->operating) | ||
3254 | goto out_mutex_unlock; | 3257 | goto out_mutex_unlock; |
3255 | 3258 | ||
3256 | b43legacydbg(wl, "Adding Interface type %d\n", conf->type); | 3259 | b43legacydbg(wl, "Adding Interface type %d\n", conf->type); |
3257 | 3260 | ||
3258 | dev = wl->current_dev; | 3261 | dev = wl->current_dev; |
3262 | wl->operating = 1; | ||
3263 | wl->if_id = conf->if_id; | ||
3264 | wl->if_type = conf->type; | ||
3265 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | ||
3266 | |||
3267 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3268 | b43legacy_adjust_opmode(dev); | ||
3269 | b43legacy_upload_card_macaddress(dev); | ||
3270 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3271 | |||
3272 | err = 0; | ||
3273 | out_mutex_unlock: | ||
3274 | mutex_unlock(&wl->mutex); | ||
3275 | |||
3276 | return err; | ||
3277 | } | ||
3278 | |||
3279 | static void b43legacy_remove_interface(struct ieee80211_hw *hw, | ||
3280 | struct ieee80211_if_init_conf *conf) | ||
3281 | { | ||
3282 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | ||
3283 | struct b43legacy_wldev *dev = wl->current_dev; | ||
3284 | unsigned long flags; | ||
3285 | |||
3286 | b43legacydbg(wl, "Removing Interface type %d\n", conf->type); | ||
3287 | |||
3288 | mutex_lock(&wl->mutex); | ||
3289 | |||
3290 | B43legacy_WARN_ON(!wl->operating); | ||
3291 | B43legacy_WARN_ON(wl->if_id != conf->if_id); | ||
3292 | |||
3293 | wl->operating = 0; | ||
3294 | |||
3295 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3296 | b43legacy_adjust_opmode(dev); | ||
3297 | memset(wl->mac_addr, 0, ETH_ALEN); | ||
3298 | b43legacy_upload_card_macaddress(dev); | ||
3299 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3300 | |||
3301 | mutex_unlock(&wl->mutex); | ||
3302 | } | ||
3303 | |||
3304 | static int b43legacy_start(struct ieee80211_hw *hw) | ||
3305 | { | ||
3306 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | ||
3307 | struct b43legacy_wldev *dev = wl->current_dev; | ||
3308 | int did_init = 0; | ||
3309 | int err; | ||
3310 | |||
3311 | mutex_lock(&wl->mutex); | ||
3312 | |||
3259 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { | 3313 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { |
3260 | err = b43legacy_wireless_core_init(dev); | 3314 | err = b43legacy_wireless_core_init(dev); |
3261 | if (err) | 3315 | if (err) |
3262 | goto out_mutex_unlock; | 3316 | goto out_mutex_unlock; |
3263 | did_init = 1; | 3317 | did_init = 1; |
3264 | } | 3318 | } |
3319 | |||
3265 | if (b43legacy_status(dev) < B43legacy_STAT_STARTED) { | 3320 | if (b43legacy_status(dev) < B43legacy_STAT_STARTED) { |
3266 | err = b43legacy_wireless_core_start(dev); | 3321 | err = b43legacy_wireless_core_start(dev); |
3267 | if (err) { | 3322 | if (err) { |
@@ -3271,59 +3326,21 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw, | |||
3271 | } | 3326 | } |
3272 | } | 3327 | } |
3273 | 3328 | ||
3274 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3275 | switch (conf->type) { | ||
3276 | case IEEE80211_IF_TYPE_MNTR: | ||
3277 | wl->monitor++; | ||
3278 | break; | ||
3279 | default: | ||
3280 | wl->operating = 1; | ||
3281 | wl->if_id = conf->if_id; | ||
3282 | wl->if_type = conf->type; | ||
3283 | b43legacy_upload_card_macaddress(dev, conf->mac_addr); | ||
3284 | } | ||
3285 | b43legacy_adjust_opmode(dev); | ||
3286 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3287 | |||
3288 | err = 0; | ||
3289 | out_mutex_unlock: | 3329 | out_mutex_unlock: |
3290 | mutex_unlock(&wl->mutex); | 3330 | mutex_unlock(&wl->mutex); |
3291 | 3331 | ||
3292 | return err; | 3332 | return err; |
3293 | } | 3333 | } |
3294 | 3334 | ||
3295 | static void b43legacy_remove_interface(struct ieee80211_hw *hw, | 3335 | void b43legacy_stop(struct ieee80211_hw *hw) |
3296 | struct ieee80211_if_init_conf *conf) | ||
3297 | { | 3336 | { |
3298 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 3337 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
3299 | struct b43legacy_wldev *dev; | 3338 | struct b43legacy_wldev *dev = wl->current_dev; |
3300 | unsigned long flags; | ||
3301 | |||
3302 | b43legacydbg(wl, "Removing Interface type %d\n", conf->type); | ||
3303 | 3339 | ||
3304 | mutex_lock(&wl->mutex); | 3340 | mutex_lock(&wl->mutex); |
3305 | if (conf->type == IEEE80211_IF_TYPE_MNTR) { | 3341 | if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) |
3306 | wl->monitor--; | 3342 | b43legacy_wireless_core_stop(dev); |
3307 | B43legacy_WARN_ON(wl->monitor < 0); | 3343 | b43legacy_wireless_core_exit(dev); |
3308 | } else { | ||
3309 | B43legacy_WARN_ON(!wl->operating); | ||
3310 | wl->operating = 0; | ||
3311 | } | ||
3312 | |||
3313 | dev = wl->current_dev; | ||
3314 | if (!wl->operating && wl->monitor == 0) { | ||
3315 | /* No interface left. */ | ||
3316 | if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) | ||
3317 | b43legacy_wireless_core_stop(dev); | ||
3318 | b43legacy_wireless_core_exit(dev); | ||
3319 | } else { | ||
3320 | /* Just monitor interfaces left. */ | ||
3321 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3322 | b43legacy_adjust_opmode(dev); | ||
3323 | if (!wl->operating) | ||
3324 | b43legacy_upload_card_macaddress(dev, NULL); | ||
3325 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3326 | } | ||
3327 | mutex_unlock(&wl->mutex); | 3344 | mutex_unlock(&wl->mutex); |
3328 | } | 3345 | } |
3329 | 3346 | ||
@@ -3336,9 +3353,11 @@ static const struct ieee80211_ops b43legacy_hw_ops = { | |||
3336 | .config = b43legacy_dev_config, | 3353 | .config = b43legacy_dev_config, |
3337 | .config_interface = b43legacy_config_interface, | 3354 | .config_interface = b43legacy_config_interface, |
3338 | .set_key = b43legacy_dev_set_key, | 3355 | .set_key = b43legacy_dev_set_key, |
3339 | .set_multicast_list = b43legacy_set_multicast_list, | 3356 | .configure_filter = b43legacy_configure_filter, |
3340 | .get_stats = b43legacy_get_stats, | 3357 | .get_stats = b43legacy_get_stats, |
3341 | .get_tx_stats = b43legacy_get_tx_stats, | 3358 | .get_tx_stats = b43legacy_get_tx_stats, |
3359 | .start = b43legacy_start, | ||
3360 | .stop = b43legacy_stop, | ||
3342 | }; | 3361 | }; |
3343 | 3362 | ||
3344 | /* Hard-reset the chip. Do not call this directly. | 3363 | /* Hard-reset the chip. Do not call this directly. |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 44f983b6d39b..8acda640df25 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -6870,7 +6870,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
6870 | * | 6870 | * |
6871 | *****************************************************************************/ | 6871 | *****************************************************************************/ |
6872 | 6872 | ||
6873 | static int iwl_mac_open(struct ieee80211_hw *hw) | 6873 | static int iwl_mac_start(struct ieee80211_hw *hw) |
6874 | { | 6874 | { |
6875 | struct iwl_priv *priv = hw->priv; | 6875 | struct iwl_priv *priv = hw->priv; |
6876 | 6876 | ||
@@ -6889,7 +6889,7 @@ static int iwl_mac_open(struct ieee80211_hw *hw) | |||
6889 | return 0; | 6889 | return 0; |
6890 | } | 6890 | } |
6891 | 6891 | ||
6892 | static int iwl_mac_stop(struct ieee80211_hw *hw) | 6892 | static void iwl_mac_stop(struct ieee80211_hw *hw) |
6893 | { | 6893 | { |
6894 | struct iwl_priv *priv = hw->priv; | 6894 | struct iwl_priv *priv = hw->priv; |
6895 | 6895 | ||
@@ -6898,8 +6898,6 @@ static int iwl_mac_stop(struct ieee80211_hw *hw) | |||
6898 | /*netif_stop_queue(dev); */ | 6898 | /*netif_stop_queue(dev); */ |
6899 | flush_workqueue(priv->workqueue); | 6899 | flush_workqueue(priv->workqueue); |
6900 | IWL_DEBUG_MAC80211("leave\n"); | 6900 | IWL_DEBUG_MAC80211("leave\n"); |
6901 | |||
6902 | return 0; | ||
6903 | } | 6901 | } |
6904 | 6902 | ||
6905 | static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | 6903 | static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, |
@@ -7115,6 +7113,8 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, | |||
7115 | if (conf == NULL) | 7113 | if (conf == NULL) |
7116 | return -EIO; | 7114 | return -EIO; |
7117 | 7115 | ||
7116 | /* XXX: this MUST use conf->mac_addr */ | ||
7117 | |||
7118 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && | 7118 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && |
7119 | (!conf->beacon || !conf->ssid_len)) { | 7119 | (!conf->beacon || !conf->ssid_len)) { |
7120 | IWL_DEBUG_MAC80211 | 7120 | IWL_DEBUG_MAC80211 |
@@ -7129,8 +7129,13 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, | |||
7129 | IWL_DEBUG_MAC80211("bssid: %s\n", | 7129 | IWL_DEBUG_MAC80211("bssid: %s\n", |
7130 | print_mac(mac, conf->bssid)); | 7130 | print_mac(mac, conf->bssid)); |
7131 | 7131 | ||
7132 | /* | ||
7133 | * very dubious code was here; the probe filtering flag is never set: | ||
7134 | * | ||
7132 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && | 7135 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && |
7133 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { | 7136 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { |
7137 | */ | ||
7138 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { | ||
7134 | IWL_DEBUG_MAC80211("leave - scanning\n"); | 7139 | IWL_DEBUG_MAC80211("leave - scanning\n"); |
7135 | mutex_unlock(&priv->mutex); | 7140 | mutex_unlock(&priv->mutex); |
7136 | return 0; | 7141 | return 0; |
@@ -7205,6 +7210,18 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, | |||
7205 | return 0; | 7210 | return 0; |
7206 | } | 7211 | } |
7207 | 7212 | ||
7213 | static void iwl_configure_filter(struct ieee80211_hw *hw, | ||
7214 | unsigned int changed_flags, | ||
7215 | unsigned int *total_flags, | ||
7216 | int mc_count, struct dev_addr_list *mc_list) | ||
7217 | { | ||
7218 | /* | ||
7219 | * XXX: dummy | ||
7220 | * see also iwl_connection_init_rx_config | ||
7221 | */ | ||
7222 | *total_flags = 0; | ||
7223 | } | ||
7224 | |||
7208 | static void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 7225 | static void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
7209 | struct ieee80211_if_init_conf *conf) | 7226 | struct ieee80211_if_init_conf *conf) |
7210 | { | 7227 | { |
@@ -8265,12 +8282,13 @@ static struct attribute_group iwl_attribute_group = { | |||
8265 | 8282 | ||
8266 | static struct ieee80211_ops iwl_hw_ops = { | 8283 | static struct ieee80211_ops iwl_hw_ops = { |
8267 | .tx = iwl_mac_tx, | 8284 | .tx = iwl_mac_tx, |
8268 | .open = iwl_mac_open, | 8285 | .start = iwl_mac_start, |
8269 | .stop = iwl_mac_stop, | 8286 | .stop = iwl_mac_stop, |
8270 | .add_interface = iwl_mac_add_interface, | 8287 | .add_interface = iwl_mac_add_interface, |
8271 | .remove_interface = iwl_mac_remove_interface, | 8288 | .remove_interface = iwl_mac_remove_interface, |
8272 | .config = iwl_mac_config, | 8289 | .config = iwl_mac_config, |
8273 | .config_interface = iwl_mac_config_interface, | 8290 | .config_interface = iwl_mac_config_interface, |
8291 | .configure_filter = iwl_configure_filter, | ||
8274 | .set_key = iwl_mac_set_key, | 8292 | .set_key = iwl_mac_set_key, |
8275 | .get_stats = iwl_mac_get_stats, | 8293 | .get_stats = iwl_mac_get_stats, |
8276 | .get_tx_stats = iwl_mac_get_tx_stats, | 8294 | .get_tx_stats = iwl_mac_get_tx_stats, |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 61500a209297..7b9227c562b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -7252,7 +7252,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
7252 | * | 7252 | * |
7253 | *****************************************************************************/ | 7253 | *****************************************************************************/ |
7254 | 7254 | ||
7255 | static int iwl_mac_open(struct ieee80211_hw *hw) | 7255 | static int iwl_mac_start(struct ieee80211_hw *hw) |
7256 | { | 7256 | { |
7257 | struct iwl_priv *priv = hw->priv; | 7257 | struct iwl_priv *priv = hw->priv; |
7258 | 7258 | ||
@@ -7271,7 +7271,7 @@ static int iwl_mac_open(struct ieee80211_hw *hw) | |||
7271 | return 0; | 7271 | return 0; |
7272 | } | 7272 | } |
7273 | 7273 | ||
7274 | static int iwl_mac_stop(struct ieee80211_hw *hw) | 7274 | static void iwl_mac_stop(struct ieee80211_hw *hw) |
7275 | { | 7275 | { |
7276 | struct iwl_priv *priv = hw->priv; | 7276 | struct iwl_priv *priv = hw->priv; |
7277 | 7277 | ||
@@ -7280,8 +7280,6 @@ static int iwl_mac_stop(struct ieee80211_hw *hw) | |||
7280 | /*netif_stop_queue(dev); */ | 7280 | /*netif_stop_queue(dev); */ |
7281 | flush_workqueue(priv->workqueue); | 7281 | flush_workqueue(priv->workqueue); |
7282 | IWL_DEBUG_MAC80211("leave\n"); | 7282 | IWL_DEBUG_MAC80211("leave\n"); |
7283 | |||
7284 | return 0; | ||
7285 | } | 7283 | } |
7286 | 7284 | ||
7287 | static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | 7285 | static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, |
@@ -7528,8 +7526,13 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, | |||
7528 | IWL_DEBUG_MAC80211("bssid: %s\n", | 7526 | IWL_DEBUG_MAC80211("bssid: %s\n", |
7529 | print_mac(mac, conf->bssid)); | 7527 | print_mac(mac, conf->bssid)); |
7530 | 7528 | ||
7529 | /* | ||
7530 | * very dubious code was here; the probe filtering flag is never set: | ||
7531 | * | ||
7531 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && | 7532 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && |
7532 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { | 7533 | !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { |
7534 | */ | ||
7535 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { | ||
7533 | IWL_DEBUG_MAC80211("leave - scanning\n"); | 7536 | IWL_DEBUG_MAC80211("leave - scanning\n"); |
7534 | mutex_unlock(&priv->mutex); | 7537 | mutex_unlock(&priv->mutex); |
7535 | return 0; | 7538 | return 0; |
@@ -7604,6 +7607,18 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, | |||
7604 | return 0; | 7607 | return 0; |
7605 | } | 7608 | } |
7606 | 7609 | ||
7610 | static void iwl_configure_filter(struct ieee80211_hw *hw, | ||
7611 | unsigned int changed_flags, | ||
7612 | unsigned int *total_flags, | ||
7613 | int mc_count, struct dev_addr_list *mc_list) | ||
7614 | { | ||
7615 | /* | ||
7616 | * XXX: dummy | ||
7617 | * see also iwl_connection_init_rx_config | ||
7618 | */ | ||
7619 | *total_flags = 0; | ||
7620 | } | ||
7621 | |||
7607 | static void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 7622 | static void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
7608 | struct ieee80211_if_init_conf *conf) | 7623 | struct ieee80211_if_init_conf *conf) |
7609 | { | 7624 | { |
@@ -8852,12 +8867,13 @@ static struct attribute_group iwl_attribute_group = { | |||
8852 | 8867 | ||
8853 | static struct ieee80211_ops iwl_hw_ops = { | 8868 | static struct ieee80211_ops iwl_hw_ops = { |
8854 | .tx = iwl_mac_tx, | 8869 | .tx = iwl_mac_tx, |
8855 | .open = iwl_mac_open, | 8870 | .start = iwl_mac_start, |
8856 | .stop = iwl_mac_stop, | 8871 | .stop = iwl_mac_stop, |
8857 | .add_interface = iwl_mac_add_interface, | 8872 | .add_interface = iwl_mac_add_interface, |
8858 | .remove_interface = iwl_mac_remove_interface, | 8873 | .remove_interface = iwl_mac_remove_interface, |
8859 | .config = iwl_mac_config, | 8874 | .config = iwl_mac_config, |
8860 | .config_interface = iwl_mac_config_interface, | 8875 | .config_interface = iwl_mac_config_interface, |
8876 | .configure_filter = iwl_configure_filter, | ||
8861 | .set_key = iwl_mac_set_key, | 8877 | .set_key = iwl_mac_set_key, |
8862 | .get_stats = iwl_mac_get_stats, | 8878 | .get_stats = iwl_mac_get_stats, |
8863 | .get_tx_stats = iwl_mac_get_tx_stats, | 8879 | .get_tx_stats = iwl_mac_get_tx_stats, |
diff --git a/drivers/net/wireless/p54.h b/drivers/net/wireless/p54.h index e558d697d9e5..744c866066c5 100644 --- a/drivers/net/wireless/p54.h +++ b/drivers/net/wireless/p54.h | |||
@@ -52,7 +52,8 @@ struct p54_common { | |||
52 | int (*open)(struct ieee80211_hw *dev); | 52 | int (*open)(struct ieee80211_hw *dev); |
53 | void (*stop)(struct ieee80211_hw *dev); | 53 | void (*stop)(struct ieee80211_hw *dev); |
54 | int mode; | 54 | int mode; |
55 | u8 *mac_addr; | 55 | u8 mac_addr[ETH_ALEN]; |
56 | u8 bssid[ETH_ALEN]; | ||
56 | struct pda_iq_autocal_entry *iq_autocal; | 57 | struct pda_iq_autocal_entry *iq_autocal; |
57 | unsigned int iq_autocal_len; | 58 | unsigned int iq_autocal_len; |
58 | struct pda_channel_output_limit *output_limit; | 59 | struct pda_channel_output_limit *output_limit; |
diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index b05b5c5b4c04..9befd6cc7911 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c | |||
@@ -774,15 +774,39 @@ static void p54_set_vdcf(struct ieee80211_hw *dev) | |||
774 | priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0); | 774 | priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0); |
775 | } | 775 | } |
776 | 776 | ||
777 | static int p54_start(struct ieee80211_hw *dev) | ||
778 | { | ||
779 | struct p54_common *priv = dev->priv; | ||
780 | int err; | ||
781 | |||
782 | err = priv->open(dev); | ||
783 | if (!err) | ||
784 | priv->mode = IEEE80211_IF_TYPE_MNTR; | ||
785 | |||
786 | return err; | ||
787 | } | ||
788 | |||
789 | static void p54_stop(struct ieee80211_hw *dev) | ||
790 | { | ||
791 | struct p54_common *priv = dev->priv; | ||
792 | struct sk_buff *skb; | ||
793 | while ((skb = skb_dequeue(&priv->tx_queue))) { | ||
794 | struct memrecord *range = (struct memrecord *)&skb->cb; | ||
795 | if (range->control) | ||
796 | kfree(range->control); | ||
797 | kfree_skb(skb); | ||
798 | } | ||
799 | priv->stop(dev); | ||
800 | priv->mode = IEEE80211_IF_TYPE_MGMT; | ||
801 | } | ||
802 | |||
777 | static int p54_add_interface(struct ieee80211_hw *dev, | 803 | static int p54_add_interface(struct ieee80211_hw *dev, |
778 | struct ieee80211_if_init_conf *conf) | 804 | struct ieee80211_if_init_conf *conf) |
779 | { | 805 | { |
780 | struct p54_common *priv = dev->priv; | 806 | struct p54_common *priv = dev->priv; |
781 | int err; | ||
782 | 807 | ||
783 | /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */ | 808 | if (priv->mode != IEEE80211_IF_TYPE_MNTR) |
784 | if (priv->mode != IEEE80211_IF_TYPE_MGMT) | 809 | return -EOPNOTSUPP; |
785 | return -1; | ||
786 | 810 | ||
787 | switch (conf->type) { | 811 | switch (conf->type) { |
788 | case IEEE80211_IF_TYPE_STA: | 812 | case IEEE80211_IF_TYPE_STA: |
@@ -792,23 +816,18 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
792 | return -EOPNOTSUPP; | 816 | return -EOPNOTSUPP; |
793 | } | 817 | } |
794 | 818 | ||
795 | priv->mac_addr = conf->mac_addr; | 819 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); |
796 | |||
797 | err = priv->open(dev); | ||
798 | if (err) { | ||
799 | priv->mode = IEEE80211_IF_TYPE_MGMT; | ||
800 | skb_queue_purge(&priv->tx_queue); | ||
801 | return err; | ||
802 | } | ||
803 | 820 | ||
804 | p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642); | 821 | p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642); |
805 | p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642); | 822 | p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642); |
806 | p54_set_vdcf(dev); | ||
807 | 823 | ||
808 | switch (conf->type) { | 824 | switch (conf->type) { |
809 | case IEEE80211_IF_TYPE_STA: | 825 | case IEEE80211_IF_TYPE_STA: |
810 | p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0); | 826 | p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0); |
811 | break; | 827 | break; |
828 | default: | ||
829 | BUG(); /* impossible */ | ||
830 | break; | ||
812 | } | 831 | } |
813 | 832 | ||
814 | p54_set_leds(dev, 1, 0, 0); | 833 | p54_set_leds(dev, 1, 0, 0); |
@@ -820,15 +839,9 @@ static void p54_remove_interface(struct ieee80211_hw *dev, | |||
820 | struct ieee80211_if_init_conf *conf) | 839 | struct ieee80211_if_init_conf *conf) |
821 | { | 840 | { |
822 | struct p54_common *priv = dev->priv; | 841 | struct p54_common *priv = dev->priv; |
823 | struct sk_buff *skb; | 842 | priv->mode = IEEE80211_IF_TYPE_MNTR; |
824 | while ((skb = skb_dequeue(&priv->tx_queue))) { | 843 | memset(priv->mac_addr, 0, ETH_ALEN); |
825 | struct memrecord *range = (struct memrecord *)&skb->cb; | 844 | p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0); |
826 | if (range->control) | ||
827 | kfree(range->control); | ||
828 | kfree_skb(skb); | ||
829 | } | ||
830 | priv->mode = IEEE80211_IF_TYPE_MGMT; | ||
831 | priv->stop(dev); | ||
832 | } | 845 | } |
833 | 846 | ||
834 | static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) | 847 | static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) |
@@ -848,9 +861,29 @@ static int p54_config_interface(struct ieee80211_hw *dev, int if_id, | |||
848 | p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642); | 861 | p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642); |
849 | p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0); | 862 | p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0); |
850 | p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); | 863 | p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); |
864 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); | ||
851 | return 0; | 865 | return 0; |
852 | } | 866 | } |
853 | 867 | ||
868 | static void p54_configure_filter(struct ieee80211_hw *dev, | ||
869 | unsigned int changed_flags, | ||
870 | unsigned int *total_flags, | ||
871 | int mc_count, struct dev_mc_list *mclist) | ||
872 | { | ||
873 | struct p54_common *priv = dev->priv; | ||
874 | |||
875 | *total_flags &= FIF_BCN_PRBRESP_PROMISC; | ||
876 | |||
877 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | ||
878 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
879 | p54_set_filter(dev, 0, priv->mac_addr, | ||
880 | NULL, 2, 0, 0, 0); | ||
881 | else | ||
882 | p54_set_filter(dev, 0, priv->mac_addr, | ||
883 | priv->bssid, 2, 0, 0, 0); | ||
884 | } | ||
885 | } | ||
886 | |||
854 | static int p54_conf_tx(struct ieee80211_hw *dev, int queue, | 887 | static int p54_conf_tx(struct ieee80211_hw *dev, int queue, |
855 | const struct ieee80211_tx_queue_params *params) | 888 | const struct ieee80211_tx_queue_params *params) |
856 | { | 889 | { |
@@ -893,10 +926,13 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev, | |||
893 | 926 | ||
894 | static const struct ieee80211_ops p54_ops = { | 927 | static const struct ieee80211_ops p54_ops = { |
895 | .tx = p54_tx, | 928 | .tx = p54_tx, |
929 | .start = p54_start, | ||
930 | .stop = p54_stop, | ||
896 | .add_interface = p54_add_interface, | 931 | .add_interface = p54_add_interface, |
897 | .remove_interface = p54_remove_interface, | 932 | .remove_interface = p54_remove_interface, |
898 | .config = p54_config, | 933 | .config = p54_config, |
899 | .config_interface = p54_config_interface, | 934 | .config_interface = p54_config_interface, |
935 | .configure_filter = p54_configure_filter, | ||
900 | .conf_tx = p54_conf_tx, | 936 | .conf_tx = p54_conf_tx, |
901 | .get_stats = p54_get_stats, | 937 | .get_stats = p54_get_stats, |
902 | .get_tx_stats = p54_get_tx_stats | 938 | .get_tx_stats = p54_get_tx_stats |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 398c20105c81..03a94a33e6bd 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -277,55 +277,14 @@ static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) | |||
277 | rt2x00pci_register_multiwrite(rt2x00dev, CSR5, ®, sizeof(reg)); | 277 | rt2x00pci_register_multiwrite(rt2x00dev, CSR5, ®, sizeof(reg)); |
278 | } | 278 | } |
279 | 279 | ||
280 | static void rt2400pci_config_packet_filter(struct rt2x00_dev *rt2x00dev, | ||
281 | const unsigned int filter) | ||
282 | { | ||
283 | int promisc = !!(filter & IFF_PROMISC); | ||
284 | u32 reg; | ||
285 | |||
286 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | ||
287 | rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, !promisc); | ||
288 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | ||
289 | } | ||
290 | |||
291 | static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, int type) | 280 | static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, int type) |
292 | { | 281 | { |
282 | struct interface *intf = &rt2x00dev->interface; | ||
293 | u32 reg; | 283 | u32 reg; |
294 | 284 | ||
295 | rt2x00pci_register_write(rt2x00dev, CSR14, 0); | 285 | rt2x00pci_register_write(rt2x00dev, CSR14, 0); |
296 | 286 | ||
297 | /* | 287 | /* |
298 | * Apply hardware packet filter. | ||
299 | */ | ||
300 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | ||
301 | |||
302 | if (!is_monitor_present(&rt2x00dev->interface) && | ||
303 | (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) | ||
304 | rt2x00_set_field32(®, RXCSR0_DROP_TODS, 1); | ||
305 | else | ||
306 | rt2x00_set_field32(®, RXCSR0_DROP_TODS, 0); | ||
307 | |||
308 | /* | ||
309 | * If there is a non-monitor interface present | ||
310 | * the packet should be strict (even if a monitor interface is present!). | ||
311 | * When there is only 1 interface present which is in monitor mode | ||
312 | * we should start accepting _all_ frames. | ||
313 | */ | ||
314 | if (is_interface_present(&rt2x00dev->interface)) { | ||
315 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, 1); | ||
316 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 1); | ||
317 | rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 1); | ||
318 | rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); | ||
319 | } else if (is_monitor_present(&rt2x00dev->interface)) { | ||
320 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, 0); | ||
321 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0); | ||
322 | rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0); | ||
323 | rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 0); | ||
324 | } | ||
325 | |||
326 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | ||
327 | |||
328 | /* | ||
329 | * Enable beacon config | 288 | * Enable beacon config |
330 | */ | 289 | */ |
331 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); | 290 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); |
@@ -337,20 +296,16 @@ static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, int type) | |||
337 | * Enable synchronisation. | 296 | * Enable synchronisation. |
338 | */ | 297 | */ |
339 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 298 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
340 | if (is_interface_present(&rt2x00dev->interface)) { | 299 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
341 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 300 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
342 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
343 | } | ||
344 | |||
345 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 301 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
346 | if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) | 302 | if (is_interface_type(intf, IEEE80211_IF_TYPE_IBSS) || |
303 | is_interface_type(intf, IEEE80211_IF_TYPE_AP)) | ||
347 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 2); | 304 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 2); |
348 | else if (type == IEEE80211_IF_TYPE_STA) | 305 | else if (is_interface_type(intf, IEEE80211_IF_TYPE_STA)) |
349 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 1); | 306 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 1); |
350 | else if (is_monitor_present(&rt2x00dev->interface) && | 307 | else |
351 | !is_interface_present(&rt2x00dev->interface)) | ||
352 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); | 308 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); |
353 | |||
354 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 309 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
355 | } | 310 | } |
356 | 311 | ||
@@ -1104,7 +1059,7 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1104 | */ | 1059 | */ |
1105 | static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 1060 | static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
1106 | struct data_desc *txd, | 1061 | struct data_desc *txd, |
1107 | struct data_entry_desc *desc, | 1062 | struct txdata_entry_desc *desc, |
1108 | struct ieee80211_hdr *ieee80211hdr, | 1063 | struct ieee80211_hdr *ieee80211hdr, |
1109 | unsigned int length, | 1064 | unsigned int length, |
1110 | struct ieee80211_tx_control *control) | 1065 | struct ieee80211_tx_control *control) |
@@ -1200,8 +1155,8 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1200 | /* | 1155 | /* |
1201 | * RX control handlers | 1156 | * RX control handlers |
1202 | */ | 1157 | */ |
1203 | static int rt2400pci_fill_rxdone(struct data_entry *entry, | 1158 | static void rt2400pci_fill_rxdone(struct data_entry *entry, |
1204 | int *signal, int *rssi, int *ofdm, int *size) | 1159 | struct rxdata_entry_desc *desc) |
1205 | { | 1160 | { |
1206 | struct data_desc *rxd = entry->priv; | 1161 | struct data_desc *rxd = entry->priv; |
1207 | u32 word0; | 1162 | u32 word0; |
@@ -1210,20 +1165,20 @@ static int rt2400pci_fill_rxdone(struct data_entry *entry, | |||
1210 | rt2x00_desc_read(rxd, 0, &word0); | 1165 | rt2x00_desc_read(rxd, 0, &word0); |
1211 | rt2x00_desc_read(rxd, 2, &word2); | 1166 | rt2x00_desc_read(rxd, 2, &word2); |
1212 | 1167 | ||
1213 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR) || | 1168 | desc->flags = 0; |
1214 | rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) | 1169 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) |
1215 | return -EINVAL; | 1170 | desc->flags |= RX_FLAG_FAILED_FCS_CRC; |
1171 | if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) | ||
1172 | desc->flags |= RX_FLAG_FAILED_PLCP_CRC; | ||
1216 | 1173 | ||
1217 | /* | 1174 | /* |
1218 | * Obtain the status about this packet. | 1175 | * Obtain the status about this packet. |
1219 | */ | 1176 | */ |
1220 | *signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); | 1177 | desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); |
1221 | *rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - | 1178 | desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - |
1222 | entry->ring->rt2x00dev->rssi_offset; | 1179 | entry->ring->rt2x00dev->rssi_offset; |
1223 | *ofdm = 0; | 1180 | desc->ofdm = 0; |
1224 | *size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); | 1181 | desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); |
1225 | |||
1226 | return 0; | ||
1227 | } | 1182 | } |
1228 | 1183 | ||
1229 | /* | 1184 | /* |
@@ -1460,10 +1415,7 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1460 | /* | 1415 | /* |
1461 | * Initialize all hw fields. | 1416 | * Initialize all hw fields. |
1462 | */ | 1417 | */ |
1463 | rt2x00dev->hw->flags = | 1418 | rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; |
1464 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
1465 | IEEE80211_HW_MONITOR_DURING_OPER | | ||
1466 | IEEE80211_HW_NO_PROBE_FILTERING; | ||
1467 | rt2x00dev->hw->extra_tx_headroom = 0; | 1419 | rt2x00dev->hw->extra_tx_headroom = 0; |
1468 | rt2x00dev->hw->max_signal = MAX_SIGNAL; | 1420 | rt2x00dev->hw->max_signal = MAX_SIGNAL; |
1469 | rt2x00dev->hw->max_rssi = MAX_RX_SSI; | 1421 | rt2x00dev->hw->max_rssi = MAX_RX_SSI; |
@@ -1530,6 +1482,68 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1530 | /* | 1482 | /* |
1531 | * IEEE80211 stack callback functions. | 1483 | * IEEE80211 stack callback functions. |
1532 | */ | 1484 | */ |
1485 | static void rt2400pci_configure_filter(struct ieee80211_hw *hw, | ||
1486 | unsigned int changed_flags, | ||
1487 | unsigned int *total_flags, | ||
1488 | int mc_count, | ||
1489 | struct dev_addr_list *mc_list) | ||
1490 | { | ||
1491 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1492 | struct interface *intf = &rt2x00dev->interface; | ||
1493 | u32 reg; | ||
1494 | |||
1495 | /* | ||
1496 | * Mask off any flags we are going to ignore from | ||
1497 | * the total_flags field. | ||
1498 | */ | ||
1499 | *total_flags &= | ||
1500 | FIF_ALLMULTI | | ||
1501 | FIF_FCSFAIL | | ||
1502 | FIF_PLCPFAIL | | ||
1503 | FIF_CONTROL | | ||
1504 | FIF_OTHER_BSS | | ||
1505 | FIF_PROMISC_IN_BSS; | ||
1506 | |||
1507 | /* | ||
1508 | * Apply some rules to the filters: | ||
1509 | * - Some filters imply different filters to be set. | ||
1510 | * - Some things we can't filter out at all. | ||
1511 | * - Some filters are set based on interface type. | ||
1512 | */ | ||
1513 | *total_flags |= FIF_ALLMULTI; | ||
1514 | if (changed_flags & FIF_OTHER_BSS || | ||
1515 | changed_flags & FIF_PROMISC_IN_BSS) | ||
1516 | *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; | ||
1517 | if (is_interface_type(intf, IEEE80211_IF_TYPE_AP)) | ||
1518 | *total_flags |= FIF_PROMISC_IN_BSS; | ||
1519 | |||
1520 | /* | ||
1521 | * Check if there is any work left for us. | ||
1522 | */ | ||
1523 | if (intf->filter == *total_flags) | ||
1524 | return; | ||
1525 | intf->filter = *total_flags; | ||
1526 | |||
1527 | /* | ||
1528 | * Start configuration steps. | ||
1529 | * Note that the version error will always be dropped | ||
1530 | * since there is no filter for it at this time. | ||
1531 | */ | ||
1532 | rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); | ||
1533 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, | ||
1534 | !(*total_flags & FIF_FCSFAIL)); | ||
1535 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, | ||
1536 | !(*total_flags & FIF_PLCPFAIL)); | ||
1537 | rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, | ||
1538 | !(*total_flags & FIF_CONTROL)); | ||
1539 | rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, | ||
1540 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1541 | rt2x00_set_field32(®, RXCSR0_DROP_TODS, | ||
1542 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1543 | rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); | ||
1544 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | ||
1545 | } | ||
1546 | |||
1533 | static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw, | 1547 | static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw, |
1534 | u32 short_retry, u32 long_retry) | 1548 | u32 short_retry, u32 long_retry) |
1535 | { | 1549 | { |
@@ -1602,11 +1616,13 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) | |||
1602 | 1616 | ||
1603 | static const struct ieee80211_ops rt2400pci_mac80211_ops = { | 1617 | static const struct ieee80211_ops rt2400pci_mac80211_ops = { |
1604 | .tx = rt2x00mac_tx, | 1618 | .tx = rt2x00mac_tx, |
1619 | .start = rt2x00mac_start, | ||
1620 | .stop = rt2x00mac_stop, | ||
1605 | .add_interface = rt2x00mac_add_interface, | 1621 | .add_interface = rt2x00mac_add_interface, |
1606 | .remove_interface = rt2x00mac_remove_interface, | 1622 | .remove_interface = rt2x00mac_remove_interface, |
1607 | .config = rt2x00mac_config, | 1623 | .config = rt2x00mac_config, |
1608 | .config_interface = rt2x00mac_config_interface, | 1624 | .config_interface = rt2x00mac_config_interface, |
1609 | .set_multicast_list = rt2x00mac_set_multicast_list, | 1625 | .configure_filter = rt2400pci_configure_filter, |
1610 | .get_stats = rt2x00mac_get_stats, | 1626 | .get_stats = rt2x00mac_get_stats, |
1611 | .set_retry_limit = rt2400pci_set_retry_limit, | 1627 | .set_retry_limit = rt2400pci_set_retry_limit, |
1612 | .conf_tx = rt2400pci_conf_tx, | 1628 | .conf_tx = rt2400pci_conf_tx, |
@@ -1635,7 +1651,6 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | |||
1635 | .fill_rxdone = rt2400pci_fill_rxdone, | 1651 | .fill_rxdone = rt2400pci_fill_rxdone, |
1636 | .config_mac_addr = rt2400pci_config_mac_addr, | 1652 | .config_mac_addr = rt2400pci_config_mac_addr, |
1637 | .config_bssid = rt2400pci_config_bssid, | 1653 | .config_bssid = rt2400pci_config_bssid, |
1638 | .config_packet_filter = rt2400pci_config_packet_filter, | ||
1639 | .config_type = rt2400pci_config_type, | 1654 | .config_type = rt2400pci_config_type, |
1640 | .config = rt2400pci_config, | 1655 | .config = rt2400pci_config, |
1641 | }; | 1656 | }; |
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, ®, sizeof(reg)); | 277 | rt2x00pci_register_multiwrite(rt2x00dev, CSR5, ®, sizeof(reg)); |
278 | } | 278 | } |
279 | 279 | ||
280 | static 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, ®); | ||
289 | rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, !promisc); | ||
290 | rt2x00_set_field32(®, RXCSR0_DROP_MCAST, !multicast); | ||
291 | rt2x00_set_field32(®, RXCSR0_DROP_BCAST, !broadcast); | ||
292 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | ||
293 | } | ||
294 | |||
295 | static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type) | 280 | static 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, ®); | ||
305 | |||
306 | if (!is_monitor_present(&rt2x00dev->interface) && | ||
307 | (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) | ||
308 | rt2x00_set_field32(®, RXCSR0_DROP_TODS, 1); | ||
309 | else | ||
310 | rt2x00_set_field32(®, 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(®, RXCSR0_DROP_CRC, 1); | ||
320 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 1); | ||
321 | rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 1); | ||
322 | rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); | ||
323 | } else if (is_monitor_present(&rt2x00dev->interface)) { | ||
324 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, 0); | ||
325 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0); | ||
326 | rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0); | ||
327 | rt2x00_set_field32(®, 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, ®); | 290 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); |
@@ -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, ®); | 302 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
348 | if (is_interface_present(&rt2x00dev->interface)) { | 303 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
349 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 304 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
350 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
351 | } | ||
352 | |||
353 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 305 | rt2x00_set_field32(®, 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(®, CSR14_TSF_SYNC, 2); | 308 | rt2x00_set_field32(®, 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(®, CSR14_TSF_SYNC, 1); | 310 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 1); |
358 | else if (is_monitor_present(&rt2x00dev->interface) && | 311 | else |
359 | !is_interface_present(&rt2x00dev->interface)) | ||
360 | rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); | 312 | rt2x00_set_field32(®, 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 | */ |
1270 | static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 1221 | static 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 | */ |
1352 | static int rt2500pci_fill_rxdone(struct data_entry *entry, | 1303 | static 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 | */ |
1817 | static 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, ®); | ||
1867 | rt2x00_set_field32(®, RXCSR0_DROP_CRC, | ||
1868 | !(*total_flags & FIF_FCSFAIL)); | ||
1869 | rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, | ||
1870 | !(*total_flags & FIF_PLCPFAIL)); | ||
1871 | rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, | ||
1872 | !(*total_flags & FIF_CONTROL)); | ||
1873 | rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, | ||
1874 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1875 | rt2x00_set_field32(®, RXCSR0_DROP_TODS, | ||
1876 | !(*total_flags & FIF_PROMISC_IN_BSS)); | ||
1877 | rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); | ||
1878 | rt2x00_set_field32(®, RXCSR0_DROP_MCAST, | ||
1879 | !(*total_flags & FIF_ALLMULTI)); | ||
1880 | rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); | ||
1881 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | ||
1882 | } | ||
1883 | |||
1870 | static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw, | 1884 | static 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 | ||
1915 | static const struct ieee80211_ops rt2500pci_mac80211_ops = { | 1929 | static 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 | }; |
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 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 80b079d723d6..046eecfb16c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -294,9 +294,6 @@ struct interface { | |||
294 | 294 | ||
295 | /* | 295 | /* |
296 | * Current working type (IEEE80211_IF_TYPE_*). | 296 | * Current working type (IEEE80211_IF_TYPE_*). |
297 | * This excludes the type IEEE80211_IF_TYPE_MNTR | ||
298 | * since that is counted seperately in the monitor_count | ||
299 | * field. | ||
300 | * When set to INVALID_INTERFACE, no interface is configured. | 297 | * When set to INVALID_INTERFACE, no interface is configured. |
301 | */ | 298 | */ |
302 | int type; | 299 | int type; |
@@ -314,18 +311,8 @@ struct interface { | |||
314 | 311 | ||
315 | /* | 312 | /* |
316 | * Store the packet filter mode for the current interface. | 313 | * Store the packet filter mode for the current interface. |
317 | * monitor mode always disabled filtering. But in such | ||
318 | * cases we still need to store the value here in case | ||
319 | * the monitor mode interfaces are removed, while a | ||
320 | * non-monitor mode interface remains. | ||
321 | */ | 314 | */ |
322 | unsigned short filter; | 315 | unsigned int filter; |
323 | |||
324 | /* | ||
325 | * Monitor mode count, the number of interfaces | ||
326 | * in monitor mode that that have been added. | ||
327 | */ | ||
328 | unsigned short monitor_count; | ||
329 | }; | 316 | }; |
330 | 317 | ||
331 | static inline int is_interface_present(struct interface *intf) | 318 | static inline int is_interface_present(struct interface *intf) |
@@ -333,9 +320,9 @@ static inline int is_interface_present(struct interface *intf) | |||
333 | return !!intf->id; | 320 | return !!intf->id; |
334 | } | 321 | } |
335 | 322 | ||
336 | static inline int is_monitor_present(struct interface *intf) | 323 | static inline int is_interface_type(struct interface *intf, int type) |
337 | { | 324 | { |
338 | return !!intf->monitor_count; | 325 | return intf->type == type; |
339 | } | 326 | } |
340 | 327 | ||
341 | /* | 328 | /* |
@@ -402,7 +389,7 @@ struct rt2x00lib_ops { | |||
402 | */ | 389 | */ |
403 | void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, | 390 | void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, |
404 | struct data_desc *txd, | 391 | struct data_desc *txd, |
405 | struct data_entry_desc *desc, | 392 | struct txdata_entry_desc *desc, |
406 | struct ieee80211_hdr *ieee80211hdr, | 393 | struct ieee80211_hdr *ieee80211hdr, |
407 | unsigned int length, | 394 | unsigned int length, |
408 | struct ieee80211_tx_control *control); | 395 | struct ieee80211_tx_control *control); |
@@ -415,8 +402,8 @@ struct rt2x00lib_ops { | |||
415 | /* | 402 | /* |
416 | * RX control handlers | 403 | * RX control handlers |
417 | */ | 404 | */ |
418 | int (*fill_rxdone) (struct data_entry *entry, | 405 | void (*fill_rxdone) (struct data_entry *entry, |
419 | int *signal, int *rssi, int *ofdm, int *size); | 406 | struct rxdata_entry_desc *desc); |
420 | 407 | ||
421 | /* | 408 | /* |
422 | * Configuration handlers. | 409 | * Configuration handlers. |
@@ -511,11 +498,10 @@ struct rt2x00_dev { | |||
511 | #define DEVICE_INITIALIZED 3 | 498 | #define DEVICE_INITIALIZED 3 |
512 | #define DEVICE_INITIALIZED_HW 4 | 499 | #define DEVICE_INITIALIZED_HW 4 |
513 | #define REQUIRE_FIRMWARE 5 | 500 | #define REQUIRE_FIRMWARE 5 |
514 | #define PACKET_FILTER_SCHEDULED 6 | 501 | /* Hole: Add new Flag here */ |
515 | #define PACKET_FILTER_PENDING 7 | ||
516 | #define INTERFACE_RESUME 8 | 502 | #define INTERFACE_RESUME 8 |
517 | #define INTERFACE_ENABLED 9 | 503 | #define INTERFACE_ENABLED 9 |
518 | #define INTERFACE_ENABLED_MONITOR 10 | 504 | /* Hole: Add new Flag here */ |
519 | #define REQUIRE_BEACON_RING 11 | 505 | #define REQUIRE_BEACON_RING 11 |
520 | #define DEVICE_SUPPORT_HW_BUTTON 12 | 506 | #define DEVICE_SUPPORT_HW_BUTTON 12 |
521 | #define CONFIG_FRAME_TYPE 13 | 507 | #define CONFIG_FRAME_TYPE 13 |
@@ -606,9 +592,10 @@ struct rt2x00_dev { | |||
606 | struct ieee80211_rx_status rx_status; | 592 | struct ieee80211_rx_status rx_status; |
607 | 593 | ||
608 | /* | 594 | /* |
609 | * Beacon scheduled work. | 595 | * Scheduled work. |
610 | */ | 596 | */ |
611 | struct work_struct beacon_work; | 597 | struct work_struct beacon_work; |
598 | struct work_struct filter_work; | ||
612 | 599 | ||
613 | /* | 600 | /* |
614 | * Data ring arrays for RX, TX and Beacon. | 601 | * Data ring arrays for RX, TX and Beacon. |
@@ -760,7 +747,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | |||
760 | void rt2x00lib_txdone(struct data_entry *entry, | 747 | void rt2x00lib_txdone(struct data_entry *entry, |
761 | const int status, const int retry); | 748 | const int status, const int retry); |
762 | void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, | 749 | void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, |
763 | const int signal, const int rssi, const int ofdm); | 750 | struct rxdata_entry_desc *desc); |
764 | 751 | ||
765 | /* | 752 | /* |
766 | * TX descriptor initializer | 753 | * TX descriptor initializer |
@@ -785,8 +772,6 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
785 | int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); | 772 | int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); |
786 | int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id, | 773 | int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id, |
787 | struct ieee80211_if_conf *conf); | 774 | struct ieee80211_if_conf *conf); |
788 | void rt2x00mac_set_multicast_list(struct ieee80211_hw *hw, | ||
789 | unsigned short flags, int mc_count); | ||
790 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, | 775 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, |
791 | struct ieee80211_low_level_stats *stats); | 776 | struct ieee80211_low_level_stats *stats); |
792 | int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, | 777 | int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index de890a17d8fd..f962ce497086 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -46,72 +46,24 @@ void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) | |||
46 | rt2x00dev->ops->lib->config_bssid(rt2x00dev, bssid); | 46 | rt2x00dev->ops->lib->config_bssid(rt2x00dev, bssid); |
47 | } | 47 | } |
48 | 48 | ||
49 | void rt2x00lib_config_packet_filter(struct rt2x00_dev *rt2x00dev, int filter) | ||
50 | { | ||
51 | /* | ||
52 | * Only configure the device when something has changed, | ||
53 | * or if we are in RESUME state in which case all configuration | ||
54 | * will be forced upon the device. | ||
55 | */ | ||
56 | if (!test_bit(INTERFACE_RESUME, &rt2x00dev->flags) && | ||
57 | !test_bit(PACKET_FILTER_PENDING, &rt2x00dev->flags)) | ||
58 | return; | ||
59 | |||
60 | /* | ||
61 | * Write configuration to device and clear the update flag. | ||
62 | */ | ||
63 | rt2x00dev->ops->lib->config_packet_filter(rt2x00dev, filter); | ||
64 | __clear_bit(PACKET_FILTER_PENDING, &rt2x00dev->flags); | ||
65 | } | ||
66 | |||
67 | void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, int type) | 49 | void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, int type) |
68 | { | 50 | { |
69 | struct interface *intf = &rt2x00dev->interface; | 51 | struct interface *intf = &rt2x00dev->interface; |
70 | 52 | ||
71 | /* | ||
72 | * Fallback when a invalid interface is attempted to | ||
73 | * be configured. If a monitor interface is present, | ||
74 | * we are going configure that, otherwise exit. | ||
75 | */ | ||
76 | if (type == INVALID_INTERFACE) { | ||
77 | if (is_monitor_present(intf)) | ||
78 | type = IEEE80211_IF_TYPE_MNTR; | ||
79 | else | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Only configure the device when something has changed, | ||
85 | * or if we are in RESUME state in which case all configuration | ||
86 | * will be forced upon the device. | ||
87 | */ | ||
88 | if (!test_bit(INTERFACE_RESUME, &rt2x00dev->flags) && | 53 | if (!test_bit(INTERFACE_RESUME, &rt2x00dev->flags) && |
89 | (!(is_interface_present(intf) ^ | 54 | (!!test_bit(INTERFACE_ENABLED, &rt2x00dev->flags) == |
90 | test_bit(INTERFACE_ENABLED, &rt2x00dev->flags)) && | 55 | !!is_interface_present(intf))) |
91 | !(is_monitor_present(intf) ^ | ||
92 | test_bit(INTERFACE_ENABLED_MONITOR, &rt2x00dev->flags)))) | ||
93 | return; | 56 | return; |
94 | 57 | ||
95 | /* | ||
96 | * Configure device. | ||
97 | */ | ||
98 | rt2x00dev->ops->lib->config_type(rt2x00dev, type); | 58 | rt2x00dev->ops->lib->config_type(rt2x00dev, type); |
99 | 59 | ||
100 | /* | 60 | /* |
101 | * Update the configuration flags. | 61 | * Update the configuration flags. |
102 | */ | 62 | */ |
103 | if (type != IEEE80211_IF_TYPE_MNTR) { | 63 | if (is_interface_present(intf)) |
104 | if (is_interface_present(intf)) | 64 | __set_bit(INTERFACE_ENABLED, &rt2x00dev->flags); |
105 | __set_bit(INTERFACE_ENABLED, &rt2x00dev->flags); | 65 | else |
106 | else | 66 | __clear_bit(INTERFACE_ENABLED, &rt2x00dev->flags); |
107 | __clear_bit(INTERFACE_ENABLED, &rt2x00dev->flags); | ||
108 | } else { | ||
109 | if (is_monitor_present(intf)) | ||
110 | __set_bit(INTERFACE_ENABLED_MONITOR, &rt2x00dev->flags); | ||
111 | else | ||
112 | __clear_bit(INTERFACE_ENABLED_MONITOR, | ||
113 | &rt2x00dev->flags); | ||
114 | } | ||
115 | } | 67 | } |
116 | 68 | ||
117 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf) | 69 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index cd82eeface8f..bbccb8933876 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -135,10 +135,12 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
135 | return; | 135 | return; |
136 | 136 | ||
137 | /* | 137 | /* |
138 | * Stop beacon generation. | 138 | * Stop all scheduled work. |
139 | */ | 139 | */ |
140 | if (work_pending(&rt2x00dev->beacon_work)) | 140 | if (work_pending(&rt2x00dev->beacon_work)) |
141 | cancel_work_sync(&rt2x00dev->beacon_work); | 141 | cancel_work_sync(&rt2x00dev->beacon_work); |
142 | if (work_pending(&rt2x00dev->filter_work)) | ||
143 | cancel_work_sync(&rt2x00dev->filter_work); | ||
142 | 144 | ||
143 | /* | 145 | /* |
144 | * Stop the TX queues. | 146 | * Stop the TX queues. |
@@ -257,6 +259,17 @@ static void rt2x00lib_link_tuner(struct work_struct *work) | |||
257 | LINK_TUNE_INTERVAL); | 259 | LINK_TUNE_INTERVAL); |
258 | } | 260 | } |
259 | 261 | ||
262 | static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) | ||
263 | { | ||
264 | struct rt2x00_dev *rt2x00dev = | ||
265 | container_of(work, struct rt2x00_dev, filter_work); | ||
266 | |||
267 | rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw, | ||
268 | rt2x00dev->interface.filter, | ||
269 | &rt2x00dev->interface.filter, | ||
270 | 0, NULL); | ||
271 | } | ||
272 | |||
260 | /* | 273 | /* |
261 | * Interrupt context handlers. | 274 | * Interrupt context handlers. |
262 | */ | 275 | */ |
@@ -337,7 +350,7 @@ void rt2x00lib_txdone(struct data_entry *entry, | |||
337 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 350 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
338 | 351 | ||
339 | void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, | 352 | void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, |
340 | const int signal, const int rssi, const int ofdm) | 353 | struct rxdata_entry_desc *desc) |
341 | { | 354 | { |
342 | struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; | 355 | struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; |
343 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; | 356 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; |
@@ -358,22 +371,24 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, | |||
358 | * the signal is the PLCP value. If it was received with | 371 | * the signal is the PLCP value. If it was received with |
359 | * a CCK bitrate the signal is the rate in 0.5kbit/s. | 372 | * a CCK bitrate the signal is the rate in 0.5kbit/s. |
360 | */ | 373 | */ |
361 | if (!ofdm) | 374 | if (!desc->ofdm) |
362 | val = DEVICE_GET_RATE_FIELD(rate->val, RATE); | 375 | val = DEVICE_GET_RATE_FIELD(rate->val, RATE); |
363 | else | 376 | else |
364 | val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); | 377 | val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); |
365 | 378 | ||
366 | if (val == signal) { | 379 | if (val == desc->signal) { |
367 | val = rate->val; | 380 | val = rate->val; |
368 | break; | 381 | break; |
369 | } | 382 | } |
370 | } | 383 | } |
371 | 384 | ||
372 | rt2x00_update_link_rssi(&rt2x00dev->link, rssi); | 385 | rt2x00_update_link_rssi(&rt2x00dev->link, desc->rssi); |
373 | rt2x00dev->link.rx_success++; | 386 | rt2x00dev->link.rx_success++; |
374 | rx_status->rate = val; | 387 | rx_status->rate = val; |
375 | rx_status->signal = rt2x00lib_calculate_link_signal(rt2x00dev, rssi); | 388 | rx_status->signal = |
376 | rx_status->ssi = rssi; | 389 | rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi); |
390 | rx_status->ssi = desc->rssi; | ||
391 | rx_status->flag = desc->flags; | ||
377 | 392 | ||
378 | /* | 393 | /* |
379 | * Send frame to mac80211 | 394 | * Send frame to mac80211 |
@@ -391,7 +406,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
391 | unsigned int length, | 406 | unsigned int length, |
392 | struct ieee80211_tx_control *control) | 407 | struct ieee80211_tx_control *control) |
393 | { | 408 | { |
394 | struct data_entry_desc desc; | 409 | struct txdata_entry_desc desc; |
395 | struct data_ring *ring; | 410 | struct data_ring *ring; |
396 | int tx_rate; | 411 | int tx_rate; |
397 | int bitrate; | 412 | int bitrate; |
@@ -956,6 +971,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
956 | * Initialize configuration work. | 971 | * Initialize configuration work. |
957 | */ | 972 | */ |
958 | INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled); | 973 | INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled); |
974 | INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); | ||
959 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); | 975 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); |
960 | 976 | ||
961 | /* | 977 | /* |
@@ -1098,7 +1114,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) | |||
1098 | rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); | 1114 | rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); |
1099 | rt2x00lib_config_bssid(rt2x00dev, intf->bssid); | 1115 | rt2x00lib_config_bssid(rt2x00dev, intf->bssid); |
1100 | rt2x00lib_config_type(rt2x00dev, intf->type); | 1116 | rt2x00lib_config_type(rt2x00dev, intf->type); |
1101 | rt2x00lib_config_packet_filter(rt2x00dev, intf->filter); | ||
1102 | 1117 | ||
1103 | /* | 1118 | /* |
1104 | * When in Master or Ad-hoc mode, | 1119 | * When in Master or Ad-hoc mode, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 3324090a96a7..fcc2ffdd1a3c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -51,7 +51,6 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev); | |||
51 | */ | 51 | */ |
52 | void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac); | 52 | void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac); |
53 | void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid); | 53 | void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid); |
54 | void rt2x00lib_config_packet_filter(struct rt2x00_dev *rt2x00dev, int filter); | ||
55 | void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, int type); | 54 | void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, int type); |
56 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf); | 55 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf); |
57 | 56 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 778ed41e21ef..17802f6d3d6d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -176,46 +176,26 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
176 | { | 176 | { |
177 | struct rt2x00_dev *rt2x00dev = hw->priv; | 177 | struct rt2x00_dev *rt2x00dev = hw->priv; |
178 | struct interface *intf = &rt2x00dev->interface; | 178 | struct interface *intf = &rt2x00dev->interface; |
179 | int retval; | ||
180 | 179 | ||
181 | /* | 180 | /* |
182 | * We only support 1 non-monitor interface. | 181 | * We only support 1 non-monitor interface. |
183 | */ | 182 | */ |
184 | if (conf->type != IEEE80211_IF_TYPE_MNTR && is_interface_present(intf)) | 183 | if (is_interface_present(intf)) |
185 | return -ENOBUFS; | 184 | return -ENOBUFS; |
186 | 185 | ||
187 | /* | 186 | intf->id = conf->if_id; |
188 | * HACK: Placeholder until start/stop handler has been | 187 | intf->type = conf->type; |
189 | * added to the mac80211 callback functions structure. | 188 | if (conf->type == IEEE80211_IF_TYPE_AP) |
190 | */ | 189 | memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); |
191 | retval = rt2x00mac_start(hw); | 190 | memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); |
192 | if (retval) | ||
193 | return retval; | ||
194 | |||
195 | /* | ||
196 | * We support muliple monitor mode interfaces. | ||
197 | * All we need to do is increase the monitor_count. | ||
198 | */ | ||
199 | if (conf->type == IEEE80211_IF_TYPE_MNTR) { | ||
200 | intf->monitor_count++; | ||
201 | } else { | ||
202 | intf->id = conf->if_id; | ||
203 | intf->type = conf->type; | ||
204 | if (conf->type == IEEE80211_IF_TYPE_AP) | ||
205 | memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); | ||
206 | memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); | ||
207 | intf->filter = 0; | ||
208 | } | ||
209 | 191 | ||
210 | /* | 192 | /* |
211 | * Configure interface. | ||
212 | * The MAC adddress must be configured after the device | 193 | * The MAC adddress must be configured after the device |
213 | * has been initialized. Else the device can reset the | 194 | * has been initialized. Otherwise the device can reset |
214 | * MAC registers. | 195 | * the MAC registers. |
215 | */ | 196 | */ |
216 | rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); | 197 | rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); |
217 | rt2x00lib_config_type(rt2x00dev, conf->type); | 198 | rt2x00lib_config_type(rt2x00dev, conf->type); |
218 | rt2x00lib_config_packet_filter(rt2x00dev, intf->filter); | ||
219 | 199 | ||
220 | return 0; | 200 | return 0; |
221 | } | 201 | } |
@@ -230,22 +210,13 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
230 | /* | 210 | /* |
231 | * We only support 1 non-monitor interface. | 211 | * We only support 1 non-monitor interface. |
232 | */ | 212 | */ |
233 | if (conf->type != IEEE80211_IF_TYPE_MNTR && !is_interface_present(intf)) | 213 | if (!is_interface_present(intf)) |
234 | return; | 214 | return; |
235 | 215 | ||
236 | /* | 216 | intf->id = 0; |
237 | * When removing an monitor interface, decrease monitor_count. | 217 | intf->type = INVALID_INTERFACE; |
238 | * For non-monitor interfaces, all interface data needs to be reset. | 218 | memset(&intf->bssid, 0x00, ETH_ALEN); |
239 | */ | 219 | memset(&intf->mac, 0x00, ETH_ALEN); |
240 | if (conf->type == IEEE80211_IF_TYPE_MNTR) { | ||
241 | intf->monitor_count--; | ||
242 | } else if (intf->type == conf->type) { | ||
243 | intf->id = 0; | ||
244 | intf->type = INVALID_INTERFACE; | ||
245 | memset(&intf->bssid, 0x00, ETH_ALEN); | ||
246 | memset(&intf->mac, 0x00, ETH_ALEN); | ||
247 | intf->filter = 0; | ||
248 | } | ||
249 | 220 | ||
250 | /* | 221 | /* |
251 | * Make sure the bssid and mac address registers | 222 | * Make sure the bssid and mac address registers |
@@ -254,12 +225,6 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
254 | rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); | 225 | rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); |
255 | rt2x00lib_config_bssid(rt2x00dev, intf->bssid); | 226 | rt2x00lib_config_bssid(rt2x00dev, intf->bssid); |
256 | rt2x00lib_config_type(rt2x00dev, intf->type); | 227 | rt2x00lib_config_type(rt2x00dev, intf->type); |
257 | |||
258 | /* | ||
259 | * HACK: Placeholder untill start/stop handler has been | ||
260 | * added to the mac80211 callback functions structure. | ||
261 | */ | ||
262 | rt2x00mac_stop(hw); | ||
263 | } | 228 | } |
264 | EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); | 229 | EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); |
265 | 230 | ||
@@ -290,14 +255,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
290 | rt2x00lib_config(rt2x00dev, conf); | 255 | rt2x00lib_config(rt2x00dev, conf); |
291 | 256 | ||
292 | /* | 257 | /* |
293 | * If promisc mode cannot be configured in irq context, | ||
294 | * then it is now the time to configure it. | ||
295 | */ | ||
296 | if (test_bit(PACKET_FILTER_SCHEDULED, &rt2x00dev->flags)) | ||
297 | rt2x00lib_config_packet_filter(rt2x00dev, | ||
298 | rt2x00dev->interface.filter); | ||
299 | |||
300 | /* | ||
301 | * Reenable RX only if the radio should be on. | 258 | * Reenable RX only if the radio should be on. |
302 | */ | 259 | */ |
303 | if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 260 | if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) |
@@ -326,13 +283,10 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id, | |||
326 | return 0; | 283 | return 0; |
327 | 284 | ||
328 | /* | 285 | /* |
329 | * Monitor mode does not need configuring. | ||
330 | * If the given type does not match the configured type, | 286 | * If the given type does not match the configured type, |
331 | * there has been a problem. | 287 | * there has been a problem. |
332 | */ | 288 | */ |
333 | if (conf->type == IEEE80211_IF_TYPE_MNTR) | 289 | if (conf->type != intf->type) |
334 | return 0; | ||
335 | else if (conf->type != intf->type) | ||
336 | return -EINVAL; | 290 | return -EINVAL; |
337 | 291 | ||
338 | /* | 292 | /* |
@@ -360,36 +314,6 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id, | |||
360 | } | 314 | } |
361 | EXPORT_SYMBOL_GPL(rt2x00mac_config_interface); | 315 | EXPORT_SYMBOL_GPL(rt2x00mac_config_interface); |
362 | 316 | ||
363 | void rt2x00mac_set_multicast_list(struct ieee80211_hw *hw, | ||
364 | unsigned short flags, int mc_count) | ||
365 | { | ||
366 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
367 | |||
368 | /* | ||
369 | * Check if the new state is different then the old state. | ||
370 | */ | ||
371 | if (rt2x00dev->interface.filter == flags) | ||
372 | return; | ||
373 | |||
374 | rt2x00dev->interface.filter = flags; | ||
375 | |||
376 | /* | ||
377 | * Raise the pending bit to indicate the | ||
378 | * packet filter should be updated. | ||
379 | */ | ||
380 | __set_bit(PACKET_FILTER_PENDING, &rt2x00dev->flags); | ||
381 | |||
382 | /* | ||
383 | * Check if Packet filter actions are allowed in | ||
384 | * atomic context. If not, raise the pending flag and | ||
385 | * let it be. | ||
386 | */ | ||
387 | if (!test_bit(PACKET_FILTER_SCHEDULED, &rt2x00dev->flags) || | ||
388 | !in_atomic()) | ||
389 | rt2x00lib_config_packet_filter(rt2x00dev, flags); | ||
390 | } | ||
391 | EXPORT_SYMBOL_GPL(rt2x00mac_set_multicast_list); | ||
392 | |||
393 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, | 317 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, |
394 | struct ieee80211_low_level_stats *stats) | 318 | struct ieee80211_low_level_stats *stats) |
395 | { | 319 | { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 85629f1999ab..2780df00623c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -124,47 +124,40 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | |||
124 | struct data_entry *entry; | 124 | struct data_entry *entry; |
125 | struct data_desc *rxd; | 125 | struct data_desc *rxd; |
126 | struct sk_buff *skb; | 126 | struct sk_buff *skb; |
127 | u32 desc; | 127 | struct rxdata_entry_desc desc; |
128 | int retval; | 128 | u32 word; |
129 | int signal; | ||
130 | int rssi; | ||
131 | int ofdm; | ||
132 | int size; | ||
133 | 129 | ||
134 | while (1) { | 130 | while (1) { |
135 | entry = rt2x00_get_data_entry(ring); | 131 | entry = rt2x00_get_data_entry(ring); |
136 | rxd = entry->priv; | 132 | rxd = entry->priv; |
137 | rt2x00_desc_read(rxd, 0, &desc); | 133 | rt2x00_desc_read(rxd, 0, &word); |
138 | 134 | ||
139 | if (rt2x00_get_field32(desc, RXD_ENTRY_OWNER_NIC)) | 135 | if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) |
140 | break; | 136 | break; |
141 | 137 | ||
142 | retval = rt2x00dev->ops->lib->fill_rxdone(entry, &signal, | 138 | memset(&desc, 0x00, sizeof(desc)); |
143 | &rssi, &ofdm, &size); | 139 | rt2x00dev->ops->lib->fill_rxdone(entry, &desc); |
144 | if (retval) | ||
145 | goto skip_entry; | ||
146 | 140 | ||
147 | /* | 141 | /* |
148 | * Allocate the sk_buffer, initialize it and copy | 142 | * Allocate the sk_buffer, initialize it and copy |
149 | * all data into it. | 143 | * all data into it. |
150 | */ | 144 | */ |
151 | skb = dev_alloc_skb(size + NET_IP_ALIGN); | 145 | skb = dev_alloc_skb(desc.size + NET_IP_ALIGN); |
152 | if (!skb) | 146 | if (!skb) |
153 | return; | 147 | return; |
154 | 148 | ||
155 | skb_reserve(skb, NET_IP_ALIGN); | 149 | skb_reserve(skb, NET_IP_ALIGN); |
156 | skb_put(skb, size); | 150 | skb_put(skb, desc.size); |
157 | memcpy(skb->data, entry->data_addr, size); | 151 | memcpy(skb->data, entry->data_addr, desc.size); |
158 | 152 | ||
159 | /* | 153 | /* |
160 | * Send the frame to rt2x00lib for further processing. | 154 | * Send the frame to rt2x00lib for further processing. |
161 | */ | 155 | */ |
162 | rt2x00lib_rxdone(entry, skb, signal, rssi, ofdm); | 156 | rt2x00lib_rxdone(entry, skb, &desc); |
163 | 157 | ||
164 | skip_entry: | ||
165 | if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) { | 158 | if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) { |
166 | rt2x00_set_field32(&desc, RXD_ENTRY_OWNER_NIC, 1); | 159 | rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1); |
167 | rt2x00_desc_write(rxd, 0, desc); | 160 | rt2x00_desc_write(rxd, 0, word); |
168 | } | 161 | } |
169 | 162 | ||
170 | rt2x00_ring_index_inc(ring); | 163 | rt2x00_ring_index_inc(ring); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index dc5b696f4751..b54457c921c5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c | |||
@@ -45,11 +45,9 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) | |||
45 | return 0; | 45 | return 0; |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Only continue if we have an active interface, | 48 | * Only continue if we have an active interface. |
49 | * either monitor or non-monitor should be present. | ||
50 | */ | 49 | */ |
51 | if (!is_interface_present(&rt2x00dev->interface) && | 50 | if (!is_interface_present(&rt2x00dev->interface)) |
52 | !is_monitor_present(&rt2x00dev->interface)) | ||
53 | return 0; | 51 | return 0; |
54 | 52 | ||
55 | if (state == RFKILL_STATE_ON) { | 53 | if (state == RFKILL_STATE_ON) { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h index 122c75248e74..1a864d32cfbd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ring.h +++ b/drivers/net/wireless/rt2x00/rt2x00ring.h | |||
@@ -41,11 +41,24 @@ struct data_desc { | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * data_entry_desc | 44 | * rxdata_entry_desc |
45 | * Summary of information that has been read from the | ||
46 | * RX frame descriptor. | ||
47 | */ | ||
48 | struct rxdata_entry_desc { | ||
49 | int signal; | ||
50 | int rssi; | ||
51 | int ofdm; | ||
52 | int size; | ||
53 | int flags; | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * txdata_entry_desc | ||
45 | * Summary of information that should be written into the | 58 | * Summary of information that should be written into the |
46 | * descriptor for sending a TX frame. | 59 | * descriptor for sending a TX frame. |
47 | */ | 60 | */ |
48 | struct data_entry_desc { | 61 | struct txdata_entry_desc { |
49 | unsigned long flags; | 62 | unsigned long flags; |
50 | #define ENTRY_TXDONE 1 | 63 | #define ENTRY_TXDONE 1 |
51 | #define ENTRY_TXD_RTS_FRAME 2 | 64 | #define ENTRY_TXD_RTS_FRAME 2 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index a0f05ca54bb4..8d2081189025 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -220,11 +220,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
220 | struct data_ring *ring = entry->ring; | 220 | struct data_ring *ring = entry->ring; |
221 | struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; | 221 | struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; |
222 | struct sk_buff *skb; | 222 | struct sk_buff *skb; |
223 | int retval; | 223 | struct rxdata_entry_desc desc; |
224 | int signal; | ||
225 | int rssi; | ||
226 | int ofdm; | ||
227 | int size; | ||
228 | int frame_size; | 224 | int frame_size; |
229 | 225 | ||
230 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | 226 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || |
@@ -239,10 +235,8 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
239 | if (urb->actual_length < entry->ring->desc_size || urb->status) | 235 | if (urb->actual_length < entry->ring->desc_size || urb->status) |
240 | goto skip_entry; | 236 | goto skip_entry; |
241 | 237 | ||
242 | retval = rt2x00dev->ops->lib->fill_rxdone(entry, &signal, &rssi, | 238 | memset(&desc, 0x00, sizeof(desc)); |
243 | &ofdm, &size); | 239 | rt2x00dev->ops->lib->fill_rxdone(entry, &desc); |
244 | if (retval) | ||
245 | goto skip_entry; | ||
246 | 240 | ||
247 | /* | 241 | /* |
248 | * Allocate a new sk buffer to replace the current one. | 242 | * Allocate a new sk buffer to replace the current one. |
@@ -261,12 +255,12 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
261 | * Trim the skb_buffer to only contain the valid | 255 | * Trim the skb_buffer to only contain the valid |
262 | * frame data (so ignore the device's descriptor). | 256 | * frame data (so ignore the device's descriptor). |
263 | */ | 257 | */ |
264 | skb_trim(entry->skb, size); | 258 | skb_trim(entry->skb, desc.size); |
265 | 259 | ||
266 | /* | 260 | /* |
267 | * Send the frame to rt2x00lib for further processing. | 261 | * Send the frame to rt2x00lib for further processing. |
268 | */ | 262 | */ |
269 | rt2x00lib_rxdone(entry, entry->skb, signal, rssi, ofdm); | 263 | rt2x00lib_rxdone(entry, entry->skb, &desc); |
270 | 264 | ||
271 | /* | 265 | /* |
272 | * Replace current entry's skb with the newly allocated one, | 266 | * Replace current entry's skb with the newly allocated one, |
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 | }; |
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 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 5d63a1a714f3..f0951519f74b 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h | |||
@@ -290,7 +290,7 @@ struct hw_pairwise_ta_entry { | |||
290 | #define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000) | 290 | #define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000) |
291 | #define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000) | 291 | #define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000) |
292 | #define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000) | 292 | #define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000) |
293 | #define TXRX_CSR0_DROP_BORADCAST FIELD32(0x01000000) | 293 | #define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000) |
294 | #define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000) | 294 | #define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000) |
295 | #define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000) | 295 | #define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000) |
296 | 296 | ||
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index 7993b3d87203..6ad322ef0da1 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h | |||
@@ -36,8 +36,7 @@ struct rtl8187_rx_info { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | struct rtl8187_rx_hdr { | 38 | struct rtl8187_rx_hdr { |
39 | __le16 len; | 39 | __le32 flags; |
40 | __le16 rate; | ||
41 | u8 noise; | 40 | u8 noise; |
42 | u8 signal; | 41 | u8 signal; |
43 | u8 agc; | 42 | u8 agc; |
@@ -74,7 +73,7 @@ struct rtl8187_priv { | |||
74 | struct ieee80211_rate rates[12]; | 73 | struct ieee80211_rate rates[12]; |
75 | struct ieee80211_hw_mode modes[2]; | 74 | struct ieee80211_hw_mode modes[2]; |
76 | struct usb_device *udev; | 75 | struct usb_device *udev; |
77 | u8 *hwaddr; | 76 | u32 rx_conf; |
78 | u16 txpwr_base; | 77 | u16 txpwr_base; |
79 | u8 asic_rev; | 78 | u8 asic_rev; |
80 | struct sk_buff_head rx_queue; | 79 | struct sk_buff_head rx_queue; |
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index bf9f0cc5a645..b0a92f543da4 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c | |||
@@ -41,6 +41,57 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
41 | 41 | ||
42 | MODULE_DEVICE_TABLE(usb, rtl8187_table); | 42 | MODULE_DEVICE_TABLE(usb, rtl8187_table); |
43 | 43 | ||
44 | static void rtl8187_iowrite_async_cb(struct urb *urb) | ||
45 | { | ||
46 | kfree(urb->context); | ||
47 | usb_free_urb(urb); | ||
48 | } | ||
49 | |||
50 | static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr, | ||
51 | void *data, u16 len) | ||
52 | { | ||
53 | struct usb_ctrlrequest *dr; | ||
54 | struct urb *urb; | ||
55 | struct rtl8187_async_write_data { | ||
56 | u8 data[4]; | ||
57 | struct usb_ctrlrequest dr; | ||
58 | } *buf; | ||
59 | |||
60 | buf = kmalloc(sizeof(*buf), GFP_ATOMIC); | ||
61 | if (!buf) | ||
62 | return; | ||
63 | |||
64 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
65 | if (!urb) { | ||
66 | kfree(buf); | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | dr = &buf->dr; | ||
71 | |||
72 | dr->bRequestType = RTL8187_REQT_WRITE; | ||
73 | dr->bRequest = RTL8187_REQ_SET_REG; | ||
74 | dr->wValue = addr; | ||
75 | dr->wIndex = 0; | ||
76 | dr->wLength = cpu_to_le16(len); | ||
77 | |||
78 | memcpy(buf, data, len); | ||
79 | |||
80 | usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0), | ||
81 | (unsigned char *)dr, buf, len, | ||
82 | rtl8187_iowrite_async_cb, buf); | ||
83 | usb_submit_urb(urb, GFP_ATOMIC); | ||
84 | } | ||
85 | |||
86 | static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv, | ||
87 | __le32 *addr, u32 val) | ||
88 | { | ||
89 | __le32 buf = cpu_to_le32(val); | ||
90 | |||
91 | rtl8187_iowrite_async(priv, cpu_to_le16((unsigned long)addr), | ||
92 | &buf, sizeof(buf)); | ||
93 | } | ||
94 | |||
44 | void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | 95 | void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) |
45 | { | 96 | { |
46 | struct rtl8187_priv *priv = dev->priv; | 97 | struct rtl8187_priv *priv = dev->priv; |
@@ -125,6 +176,7 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
125 | struct rtl8187_rx_hdr *hdr; | 176 | struct rtl8187_rx_hdr *hdr; |
126 | struct ieee80211_rx_status rx_status = { 0 }; | 177 | struct ieee80211_rx_status rx_status = { 0 }; |
127 | int rate, signal; | 178 | int rate, signal; |
179 | u32 flags; | ||
128 | 180 | ||
129 | spin_lock(&priv->rx_queue.lock); | 181 | spin_lock(&priv->rx_queue.lock); |
130 | if (skb->next) | 182 | if (skb->next) |
@@ -143,10 +195,11 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
143 | 195 | ||
144 | skb_put(skb, urb->actual_length); | 196 | skb_put(skb, urb->actual_length); |
145 | hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); | 197 | hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); |
146 | skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF); | 198 | flags = le32_to_cpu(hdr->flags); |
199 | skb_trim(skb, flags & 0x0FFF); | ||
147 | 200 | ||
148 | signal = hdr->agc >> 1; | 201 | signal = hdr->agc >> 1; |
149 | rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF; | 202 | rate = (flags >> 20) & 0xF; |
150 | if (rate > 3) { /* OFDM rate */ | 203 | if (rate > 3) { /* OFDM rate */ |
151 | if (signal > 90) | 204 | if (signal > 90) |
152 | signal = 90; | 205 | signal = 90; |
@@ -169,6 +222,8 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
169 | rx_status.channel = dev->conf.channel; | 222 | rx_status.channel = dev->conf.channel; |
170 | rx_status.phymode = dev->conf.phymode; | 223 | rx_status.phymode = dev->conf.phymode; |
171 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | 224 | rx_status.mactime = le64_to_cpu(hdr->mac_time); |
225 | if (flags & (1 << 13)) | ||
226 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | ||
172 | ieee80211_rx_irqsafe(dev, skb, &rx_status); | 227 | ieee80211_rx_irqsafe(dev, skb, &rx_status); |
173 | 228 | ||
174 | skb = dev_alloc_skb(RTL8187_MAX_RX); | 229 | skb = dev_alloc_skb(RTL8187_MAX_RX); |
@@ -293,8 +348,6 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) | |||
293 | rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); | 348 | rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); |
294 | 349 | ||
295 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 350 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
296 | for (i = 0; i < ETH_ALEN; i++) | ||
297 | rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]); | ||
298 | 351 | ||
299 | rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF); | 352 | rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF); |
300 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); | 353 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); |
@@ -365,7 +418,7 @@ static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel) | |||
365 | rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); | 418 | rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); |
366 | } | 419 | } |
367 | 420 | ||
368 | static int rtl8187_open(struct ieee80211_hw *dev) | 421 | static int rtl8187_start(struct ieee80211_hw *dev) |
369 | { | 422 | { |
370 | struct rtl8187_priv *priv = dev->priv; | 423 | struct rtl8187_priv *priv = dev->priv; |
371 | u32 reg; | 424 | u32 reg; |
@@ -383,16 +436,13 @@ static int rtl8187_open(struct ieee80211_hw *dev) | |||
383 | RTL818X_RX_CONF_RX_AUTORESETPHY | | 436 | RTL818X_RX_CONF_RX_AUTORESETPHY | |
384 | RTL818X_RX_CONF_BSSID | | 437 | RTL818X_RX_CONF_BSSID | |
385 | RTL818X_RX_CONF_MGMT | | 438 | RTL818X_RX_CONF_MGMT | |
386 | RTL818X_RX_CONF_CTRL | | ||
387 | RTL818X_RX_CONF_DATA | | 439 | RTL818X_RX_CONF_DATA | |
388 | (7 << 13 /* RX FIFO threshold NONE */) | | 440 | (7 << 13 /* RX FIFO threshold NONE */) | |
389 | (7 << 10 /* MAX RX DMA */) | | 441 | (7 << 10 /* MAX RX DMA */) | |
390 | RTL818X_RX_CONF_BROADCAST | | 442 | RTL818X_RX_CONF_BROADCAST | |
391 | RTL818X_RX_CONF_MULTICAST | | ||
392 | RTL818X_RX_CONF_NICMAC; | 443 | RTL818X_RX_CONF_NICMAC; |
393 | if (priv->mode == IEEE80211_IF_TYPE_MNTR) | ||
394 | reg |= RTL818X_RX_CONF_MONITOR; | ||
395 | 444 | ||
445 | priv->rx_conf = reg; | ||
396 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); | 446 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); |
397 | 447 | ||
398 | reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); | 448 | reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); |
@@ -419,7 +469,7 @@ static int rtl8187_open(struct ieee80211_hw *dev) | |||
419 | return 0; | 469 | return 0; |
420 | } | 470 | } |
421 | 471 | ||
422 | static int rtl8187_stop(struct ieee80211_hw *dev) | 472 | static void rtl8187_stop(struct ieee80211_hw *dev) |
423 | { | 473 | { |
424 | struct rtl8187_priv *priv = dev->priv; | 474 | struct rtl8187_priv *priv = dev->priv; |
425 | struct rtl8187_rx_info *info; | 475 | struct rtl8187_rx_info *info; |
@@ -445,28 +495,31 @@ static int rtl8187_stop(struct ieee80211_hw *dev) | |||
445 | usb_kill_urb(info->urb); | 495 | usb_kill_urb(info->urb); |
446 | kfree_skb(skb); | 496 | kfree_skb(skb); |
447 | } | 497 | } |
448 | return 0; | 498 | return; |
449 | } | 499 | } |
450 | 500 | ||
451 | static int rtl8187_add_interface(struct ieee80211_hw *dev, | 501 | static int rtl8187_add_interface(struct ieee80211_hw *dev, |
452 | struct ieee80211_if_init_conf *conf) | 502 | struct ieee80211_if_init_conf *conf) |
453 | { | 503 | { |
454 | struct rtl8187_priv *priv = dev->priv; | 504 | struct rtl8187_priv *priv = dev->priv; |
505 | int i; | ||
455 | 506 | ||
456 | /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */ | 507 | if (priv->mode != IEEE80211_IF_TYPE_MNTR) |
457 | if (priv->mode != IEEE80211_IF_TYPE_MGMT) | 508 | return -EOPNOTSUPP; |
458 | return -1; | ||
459 | 509 | ||
460 | switch (conf->type) { | 510 | switch (conf->type) { |
461 | case IEEE80211_IF_TYPE_STA: | 511 | case IEEE80211_IF_TYPE_STA: |
462 | case IEEE80211_IF_TYPE_MNTR: | ||
463 | priv->mode = conf->type; | 512 | priv->mode = conf->type; |
464 | break; | 513 | break; |
465 | default: | 514 | default: |
466 | return -EOPNOTSUPP; | 515 | return -EOPNOTSUPP; |
467 | } | 516 | } |
468 | 517 | ||
469 | priv->hwaddr = conf->mac_addr ? conf->mac_addr : dev->wiphy->perm_addr; | 518 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
519 | for (i = 0; i < ETH_ALEN; i++) | ||
520 | rtl818x_iowrite8(priv, &priv->map->MAC[i], | ||
521 | ((u8 *)conf->mac_addr)[i]); | ||
522 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | ||
470 | 523 | ||
471 | return 0; | 524 | return 0; |
472 | } | 525 | } |
@@ -475,7 +528,7 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev, | |||
475 | struct ieee80211_if_init_conf *conf) | 528 | struct ieee80211_if_init_conf *conf) |
476 | { | 529 | { |
477 | struct rtl8187_priv *priv = dev->priv; | 530 | struct rtl8187_priv *priv = dev->priv; |
478 | priv->mode = IEEE80211_IF_TYPE_MGMT; | 531 | priv->mode = IEEE80211_IF_TYPE_MNTR; |
479 | } | 532 | } |
480 | 533 | ||
481 | static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) | 534 | static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) |
@@ -523,14 +576,52 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id, | |||
523 | return 0; | 576 | return 0; |
524 | } | 577 | } |
525 | 578 | ||
579 | static void rtl8187_configure_filter(struct ieee80211_hw *dev, | ||
580 | unsigned int changed_flags, | ||
581 | unsigned int *total_flags, | ||
582 | int mc_count, struct dev_addr_list *mc_list) | ||
583 | { | ||
584 | struct rtl8187_priv *priv = dev->priv; | ||
585 | |||
586 | *total_flags = 0; | ||
587 | |||
588 | if (changed_flags & FIF_PROMISC_IN_BSS) | ||
589 | priv->rx_conf ^= RTL818X_RX_CONF_NICMAC; | ||
590 | if (changed_flags & FIF_ALLMULTI) | ||
591 | priv->rx_conf ^= RTL818X_RX_CONF_MULTICAST; | ||
592 | if (changed_flags & FIF_FCSFAIL) | ||
593 | priv->rx_conf ^= RTL818X_RX_CONF_FCS; | ||
594 | if (changed_flags & FIF_CONTROL) | ||
595 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; | ||
596 | if (changed_flags & FIF_OTHER_BSS) | ||
597 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; | ||
598 | |||
599 | if (mc_count > 0) | ||
600 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; | ||
601 | |||
602 | if (priv->rx_conf & RTL818X_RX_CONF_NICMAC) | ||
603 | *total_flags |= FIF_PROMISC_IN_BSS; | ||
604 | if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) | ||
605 | *total_flags |= FIF_ALLMULTI; | ||
606 | if (priv->rx_conf & RTL818X_RX_CONF_FCS) | ||
607 | *total_flags |= FIF_FCSFAIL; | ||
608 | if (priv->rx_conf & RTL818X_RX_CONF_CTRL) | ||
609 | *total_flags |= FIF_CONTROL; | ||
610 | if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) | ||
611 | *total_flags |= FIF_OTHER_BSS; | ||
612 | |||
613 | rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); | ||
614 | } | ||
615 | |||
526 | static const struct ieee80211_ops rtl8187_ops = { | 616 | static const struct ieee80211_ops rtl8187_ops = { |
527 | .tx = rtl8187_tx, | 617 | .tx = rtl8187_tx, |
528 | .open = rtl8187_open, | 618 | .start = rtl8187_start, |
529 | .stop = rtl8187_stop, | 619 | .stop = rtl8187_stop, |
530 | .add_interface = rtl8187_add_interface, | 620 | .add_interface = rtl8187_add_interface, |
531 | .remove_interface = rtl8187_remove_interface, | 621 | .remove_interface = rtl8187_remove_interface, |
532 | .config = rtl8187_config, | 622 | .config = rtl8187_config, |
533 | .config_interface = rtl8187_config_interface, | 623 | .config_interface = rtl8187_config_interface, |
624 | .configure_filter = rtl8187_configure_filter, | ||
534 | }; | 625 | }; |
535 | 626 | ||
536 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 627 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -604,7 +695,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
604 | priv->modes[1].rates = priv->rates; | 695 | priv->modes[1].rates = priv->rates; |
605 | priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); | 696 | priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); |
606 | priv->modes[1].channels = priv->channels; | 697 | priv->modes[1].channels = priv->channels; |
607 | priv->mode = IEEE80211_IF_TYPE_MGMT; | 698 | priv->mode = IEEE80211_IF_TYPE_MNTR; |
608 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 699 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
609 | IEEE80211_HW_RX_INCLUDES_FCS; | 700 | IEEE80211_HW_RX_INCLUDES_FCS; |
610 | dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); | 701 | dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); |
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 283de30628e1..880d4becae31 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h | |||
@@ -71,6 +71,7 @@ struct rtl818x_csr { | |||
71 | #define RTL818X_RX_CONF_NICMAC (1 << 1) | 71 | #define RTL818X_RX_CONF_NICMAC (1 << 1) |
72 | #define RTL818X_RX_CONF_MULTICAST (1 << 2) | 72 | #define RTL818X_RX_CONF_MULTICAST (1 << 2) |
73 | #define RTL818X_RX_CONF_BROADCAST (1 << 3) | 73 | #define RTL818X_RX_CONF_BROADCAST (1 << 3) |
74 | #define RTL818X_RX_CONF_FCS (1 << 5) | ||
74 | #define RTL818X_RX_CONF_DATA (1 << 18) | 75 | #define RTL818X_RX_CONF_DATA (1 << 18) |
75 | #define RTL818X_RX_CONF_CTRL (1 << 19) | 76 | #define RTL818X_RX_CONF_CTRL (1 << 19) |
76 | #define RTL818X_RX_CONF_MGMT (1 << 20) | 77 | #define RTL818X_RX_CONF_MGMT (1 << 20) |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5ff45553a985..855754d4c50d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -467,7 +467,6 @@ enum ieee80211_if_types { | |||
467 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid | 467 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid |
468 | * until the interface is removed (i.e. it cannot be used after | 468 | * until the interface is removed (i.e. it cannot be used after |
469 | * remove_interface() callback was called for this interface). | 469 | * remove_interface() callback was called for this interface). |
470 | * This pointer will be %NULL for monitor interfaces, be careful. | ||
471 | * | 470 | * |
472 | * This structure is used in add_interface() and remove_interface() | 471 | * This structure is used in add_interface() and remove_interface() |
473 | * callbacks of &struct ieee80211_hw. | 472 | * callbacks of &struct ieee80211_hw. |
@@ -653,13 +652,9 @@ struct ieee80211_hw { | |||
653 | 652 | ||
654 | /* hole at 8 */ | 653 | /* hole at 8 */ |
655 | 654 | ||
656 | /* Device is capable of performing full monitor mode even during | 655 | /* hole at 9 */ |
657 | * normal operation. */ | ||
658 | #define IEEE80211_HW_MONITOR_DURING_OPER (1<<9) | ||
659 | 656 | ||
660 | /* Device does not need BSSID filter set to broadcast in order to | 657 | /* hole at 10 */ |
661 | * receive all probe responses while scanning */ | ||
662 | #define IEEE80211_HW_NO_PROBE_FILTERING (1<<10) | ||
663 | 658 | ||
664 | /* Channels are already configured to the default regulatory domain | 659 | /* Channels are already configured to the default regulatory domain |
665 | * specified in the device's EEPROM */ | 660 | * specified in the device's EEPROM */ |
@@ -694,6 +689,39 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr) | |||
694 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); | 689 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); |
695 | } | 690 | } |
696 | 691 | ||
692 | /* | ||
693 | * flags for change_filter_flags() | ||
694 | * | ||
695 | * Note that e.g. if PROMISC_IN_BSS is unset then | ||
696 | * you should still do MAC address filtering if | ||
697 | * possible even if OTHER_BSS is set to indicate | ||
698 | * no BSSID filtering should be done. | ||
699 | */ | ||
700 | /* | ||
701 | * promiscuous mode within your BSS, | ||
702 | * think of the BSS as your network segment and then this corresponds | ||
703 | * to the regular ethernet device promiscuous mode | ||
704 | */ | ||
705 | #define FIF_PROMISC_IN_BSS 0x01 | ||
706 | /* show all multicast frames */ | ||
707 | #define FIF_ALLMULTI 0x02 | ||
708 | /* show frames with failed FCS, but set RX_FLAG_FAILED_FCS_CRC for them */ | ||
709 | #define FIF_FCSFAIL 0x04 | ||
710 | /* show frames with failed PLCP CRC, but set RX_FLAG_FAILED_PLCP_CRC for them */ | ||
711 | #define FIF_PLCPFAIL 0x08 | ||
712 | /* | ||
713 | * This flag is set during scanning to indicate to the hardware | ||
714 | * that it should not filter beacons or probe responses by BSSID. | ||
715 | */ | ||
716 | #define FIF_BCN_PRBRESP_PROMISC 0x10 | ||
717 | /* | ||
718 | * show control frames, if PROMISC_IN_BSS is not set then | ||
719 | * only those addressed to this station | ||
720 | */ | ||
721 | #define FIF_CONTROL 0x20 | ||
722 | /* show frames from other BSSes */ | ||
723 | #define FIF_OTHER_BSS 0x40 | ||
724 | |||
697 | /* Configuration block used by the low-level driver to tell the 802.11 code | 725 | /* Configuration block used by the low-level driver to tell the 802.11 code |
698 | * about supported hardware features and to pass function pointers to callback | 726 | * about supported hardware features and to pass function pointers to callback |
699 | * functions. */ | 727 | * functions. */ |
@@ -706,32 +734,55 @@ struct ieee80211_ops { | |||
706 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb, | 734 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb, |
707 | struct ieee80211_tx_control *control); | 735 | struct ieee80211_tx_control *control); |
708 | 736 | ||
709 | /* Handler that is called when any netdevice attached to the hardware | 737 | /* |
710 | * device is set UP for the first time. This can be used, e.g., to | 738 | * Called before the first netdevice attached to the hardware |
711 | * enable interrupts and beacon sending. */ | 739 | * is enabled. This should turn on the hardware and must turn on |
712 | int (*open)(struct ieee80211_hw *hw); | 740 | * frame reception (for possibly enabled monitor interfaces.) |
713 | 741 | * Returns negative error codes, these may be seen in userspace, | |
714 | /* Handler that is called when the last netdevice attached to the | 742 | * or zero. |
715 | * hardware device is set DOWN. This can be used, e.g., to disable | 743 | * When the device is started it should not have a MAC address |
716 | * interrupts and beacon sending. */ | 744 | * to avoid acknowledging frames before a non-monitor device |
717 | int (*stop)(struct ieee80211_hw *hw); | 745 | * is added. |
718 | 746 | * | |
719 | /* Handler for asking a driver if a new interface can be added (or, | 747 | * Must be implemented. |
720 | * more exactly, set UP). If the handler returns zero, the interface | 748 | */ |
721 | * is added. Driver should perform any initialization it needs prior | 749 | int (*start)(struct ieee80211_hw *hw); |
722 | * to returning zero. By returning non-zero addition of the interface | 750 | |
723 | * is inhibited. Unless monitor_during_oper is set, it is guaranteed | 751 | /* |
724 | * that monitor interfaces and normal interfaces are mutually | 752 | * Called after last netdevice attached to the hardware |
725 | * exclusive. If assigned, the open() handler is called after | 753 | * is disabled. This should turn off the hardware (at least |
726 | * add_interface() if this is the first device added. The | 754 | * it must turn off frame reception.) |
727 | * add_interface() callback has to be assigned because it is the only | 755 | * May be called right after add_interface if that rejects |
728 | * way to obtain the requested MAC address for any interface. | 756 | * an interface. |
757 | * | ||
758 | * Must be implemented. | ||
759 | */ | ||
760 | void (*stop)(struct ieee80211_hw *hw); | ||
761 | |||
762 | /* | ||
763 | * Called when a netdevice attached to the hardware is enabled. | ||
764 | * Because it is not called for monitor mode devices, open() | ||
765 | * and stop() must be implemented. | ||
766 | * The driver should perform any initialization it needs before | ||
767 | * the device can be enabled. The initial configuration for the | ||
768 | * interface is given in the conf parameter. | ||
769 | * | ||
770 | * Must be implemented. | ||
729 | */ | 771 | */ |
730 | int (*add_interface)(struct ieee80211_hw *hw, | 772 | int (*add_interface)(struct ieee80211_hw *hw, |
731 | struct ieee80211_if_init_conf *conf); | 773 | struct ieee80211_if_init_conf *conf); |
732 | 774 | ||
733 | /* Notify a driver that an interface is going down. The stop() handler | 775 | /* |
734 | * is called prior to this if this is a last interface. */ | 776 | * Notifies a driver that an interface is going down. The stop() handler |
777 | * is called after this if it is the last interface and no monitor | ||
778 | * interfaces are present. | ||
779 | * When all interfaces are removed, the MAC address in the hardware | ||
780 | * must be cleared so the device no longer acknowledges packets, | ||
781 | * the mac_addr member of the conf structure is, however, set to the | ||
782 | * MAC address of the device going away. | ||
783 | * | ||
784 | * Hence, this callback must be implemented. | ||
785 | */ | ||
735 | void (*remove_interface)(struct ieee80211_hw *hw, | 786 | void (*remove_interface)(struct ieee80211_hw *hw, |
736 | struct ieee80211_if_init_conf *conf); | 787 | struct ieee80211_if_init_conf *conf); |
737 | 788 | ||
@@ -744,15 +795,21 @@ struct ieee80211_ops { | |||
744 | int (*config_interface)(struct ieee80211_hw *hw, | 795 | int (*config_interface)(struct ieee80211_hw *hw, |
745 | int if_id, struct ieee80211_if_conf *conf); | 796 | int if_id, struct ieee80211_if_conf *conf); |
746 | 797 | ||
747 | /* ieee80211 drivers do not have access to the &struct net_device | 798 | /* |
748 | * that is (are) connected with their device. Hence (and because | 799 | * Configure the device's RX filter. |
749 | * we need to combine the multicast lists and flags for multiple | 800 | * |
750 | * virtual interfaces), they cannot assign set_multicast_list. | 801 | * The multicast address filter must be changed if the hardware flags |
751 | * The parameters here replace dev->flags and dev->mc_count, | 802 | * indicate that one is present. |
752 | * dev->mc_list is replaced by calling ieee80211_get_mc_list_item. | 803 | * |
753 | * Must be atomic. */ | 804 | * All unsupported flags in 'total_flags' must be cleared, |
754 | void (*set_multicast_list)(struct ieee80211_hw *hw, | 805 | * clear all bits except those you honoured. |
755 | unsigned short flags, int mc_count); | 806 | * |
807 | * The callback must be implemented and must be atomic. | ||
808 | */ | ||
809 | void (*configure_filter)(struct ieee80211_hw *hw, | ||
810 | unsigned int changed_flags, | ||
811 | unsigned int *total_flags, | ||
812 | int mc_count, struct dev_addr_list *mc_list); | ||
756 | 813 | ||
757 | /* Set TIM bit handler. If the hardware/firmware takes care of beacon | 814 | /* Set TIM bit handler. If the hardware/firmware takes care of beacon |
758 | * generation, IEEE 802.11 code uses this function to tell the | 815 | * generation, IEEE 802.11 code uses this function to tell the |
@@ -1155,24 +1212,6 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw); | |||
1155 | */ | 1212 | */ |
1156 | void ieee80211_wake_queues(struct ieee80211_hw *hw); | 1213 | void ieee80211_wake_queues(struct ieee80211_hw *hw); |
1157 | 1214 | ||
1158 | /** | ||
1159 | * ieee80211_get_mc_list_item - iteration over items in multicast list | ||
1160 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | ||
1161 | * @prev: value returned by previous call to ieee80211_get_mc_list_item() or | ||
1162 | * NULL to start a new iteration. | ||
1163 | * @ptr: pointer to buffer of void * type for internal usage of | ||
1164 | * ieee80211_get_mc_list_item(). | ||
1165 | * | ||
1166 | * Iterates over items in multicast list of given device. To get the first | ||
1167 | * item, pass NULL in @prev and in *@ptr. In subsequent calls, pass the | ||
1168 | * value returned by previous call in @prev. Don't alter *@ptr during | ||
1169 | * iteration. When there are no more items, NULL is returned. | ||
1170 | */ | ||
1171 | struct dev_mc_list * | ||
1172 | ieee80211_get_mc_list_item(struct ieee80211_hw *hw, | ||
1173 | struct dev_mc_list *prev, | ||
1174 | void **ptr); | ||
1175 | |||
1176 | /* called by driver to notify scan status completed */ | 1215 | /* called by driver to notify scan status completed */ |
1177 | void ieee80211_scan_completed(struct ieee80211_hw *hw); | 1216 | void ieee80211_scan_completed(struct ieee80211_hw *hw); |
1178 | 1217 | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9efb84c47bb0..c9948fa58e08 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -165,20 +165,6 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | |||
165 | /* VLAN attributes */ | 165 | /* VLAN attributes */ |
166 | IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC); | 166 | IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC); |
167 | 167 | ||
168 | /* MONITOR attributes */ | ||
169 | static ssize_t ieee80211_if_fmt_mode( | ||
170 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
171 | { | ||
172 | struct ieee80211_local *local = sdata->local; | ||
173 | |||
174 | return scnprintf(buf, buflen, "%s\n", | ||
175 | ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) || | ||
176 | local->open_count == local->monitors) ? | ||
177 | "hard" : "soft"); | ||
178 | } | ||
179 | __IEEE80211_IF_FILE(mode); | ||
180 | |||
181 | |||
182 | #define DEBUGFS_ADD(name, type)\ | 168 | #define DEBUGFS_ADD(name, type)\ |
183 | sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\ | 169 | sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\ |
184 | sdata->debugfsdir, sdata, &name##_ops); | 170 | sdata->debugfsdir, sdata, &name##_ops); |
@@ -242,7 +228,6 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
242 | 228 | ||
243 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 229 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
244 | { | 230 | { |
245 | DEBUGFS_ADD(mode, monitor); | ||
246 | } | 231 | } |
247 | 232 | ||
248 | static void add_files(struct ieee80211_sub_if_data *sdata) | 233 | static void add_files(struct ieee80211_sub_if_data *sdata) |
@@ -337,7 +322,6 @@ static void del_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
337 | 322 | ||
338 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) | 323 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) |
339 | { | 324 | { |
340 | DEBUGFS_DEL(mode, monitor); | ||
341 | } | 325 | } |
342 | 326 | ||
343 | static void del_files(struct ieee80211_sub_if_data *sdata, int type) | 327 | static void del_files(struct ieee80211_sub_if_data *sdata, int type) |
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 57ec8880bb1a..319ec2a1d84f 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -53,6 +53,38 @@ static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | |||
53 | return ETH_ALEN; | 53 | return ETH_ALEN; |
54 | } | 54 | } |
55 | 55 | ||
56 | /* must be called under mdev tx lock */ | ||
57 | static void ieee80211_configure_filter(struct ieee80211_local *local) | ||
58 | { | ||
59 | unsigned int changed_flags; | ||
60 | unsigned int new_flags = 0; | ||
61 | |||
62 | if (local->iff_promiscs) | ||
63 | new_flags |= FIF_PROMISC_IN_BSS; | ||
64 | |||
65 | if (local->iff_allmultis) | ||
66 | new_flags |= FIF_ALLMULTI; | ||
67 | |||
68 | if (local->monitors) | ||
69 | new_flags |= FIF_CONTROL | | ||
70 | FIF_OTHER_BSS | | ||
71 | FIF_BCN_PRBRESP_PROMISC; | ||
72 | |||
73 | changed_flags = local->filter_flags ^ new_flags; | ||
74 | |||
75 | /* be a bit nasty */ | ||
76 | new_flags |= (1<<31); | ||
77 | |||
78 | local->ops->configure_filter(local_to_hw(local), | ||
79 | changed_flags, &new_flags, | ||
80 | local->mdev->mc_count, | ||
81 | local->mdev->mc_list); | ||
82 | |||
83 | WARN_ON(new_flags & (1<<31)); | ||
84 | |||
85 | local->filter_flags = new_flags & ~(1<<31); | ||
86 | } | ||
87 | |||
56 | /* master interface */ | 88 | /* master interface */ |
57 | 89 | ||
58 | static int ieee80211_master_open(struct net_device *dev) | 90 | static int ieee80211_master_open(struct net_device *dev) |
@@ -86,6 +118,13 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
86 | return 0; | 118 | return 0; |
87 | } | 119 | } |
88 | 120 | ||
121 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | ||
122 | { | ||
123 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
124 | |||
125 | ieee80211_configure_filter(local); | ||
126 | } | ||
127 | |||
89 | /* management interface */ | 128 | /* management interface */ |
90 | 129 | ||
91 | static void | 130 | static void |
@@ -267,49 +306,6 @@ static inline int identical_mac_addr_allowed(int type1, int type2) | |||
267 | type2 == IEEE80211_IF_TYPE_VLAN))); | 306 | type2 == IEEE80211_IF_TYPE_VLAN))); |
268 | } | 307 | } |
269 | 308 | ||
270 | /* Check if running monitor interfaces should go to a "soft monitor" mode | ||
271 | * and switch them if necessary. */ | ||
272 | static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local) | ||
273 | { | ||
274 | struct ieee80211_if_init_conf conf; | ||
275 | |||
276 | if (local->open_count && local->open_count == local->monitors && | ||
277 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) && | ||
278 | local->ops->remove_interface) { | ||
279 | conf.if_id = -1; | ||
280 | conf.type = IEEE80211_IF_TYPE_MNTR; | ||
281 | conf.mac_addr = NULL; | ||
282 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | /* Check if running monitor interfaces should go to a "hard monitor" mode | ||
287 | * and switch them if necessary. */ | ||
288 | static void ieee80211_start_hard_monitor(struct ieee80211_local *local) | ||
289 | { | ||
290 | struct ieee80211_if_init_conf conf; | ||
291 | |||
292 | if (local->open_count && local->open_count == local->monitors && | ||
293 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { | ||
294 | conf.if_id = -1; | ||
295 | conf.type = IEEE80211_IF_TYPE_MNTR; | ||
296 | conf.mac_addr = NULL; | ||
297 | local->ops->add_interface(local_to_hw(local), &conf); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | static void ieee80211_if_open(struct net_device *dev) | ||
302 | { | ||
303 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
304 | |||
305 | switch (sdata->type) { | ||
306 | case IEEE80211_IF_TYPE_STA: | ||
307 | case IEEE80211_IF_TYPE_IBSS: | ||
308 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
309 | break; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static int ieee80211_open(struct net_device *dev) | 309 | static int ieee80211_open(struct net_device *dev) |
314 | { | 310 | { |
315 | struct ieee80211_sub_if_data *sdata, *nsdata; | 311 | struct ieee80211_sub_if_data *sdata, *nsdata; |
@@ -335,84 +331,96 @@ static int ieee80211_open(struct net_device *dev) | |||
335 | is_zero_ether_addr(sdata->u.wds.remote_addr)) | 331 | is_zero_ether_addr(sdata->u.wds.remote_addr)) |
336 | return -ENOLINK; | 332 | return -ENOLINK; |
337 | 333 | ||
338 | if (sdata->type == IEEE80211_IF_TYPE_MNTR && local->open_count && | ||
339 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { | ||
340 | /* run the interface in a "soft monitor" mode */ | ||
341 | local->monitors++; | ||
342 | local->open_count++; | ||
343 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
344 | return 0; | ||
345 | } | ||
346 | ieee80211_if_open(dev); | ||
347 | ieee80211_start_soft_monitor(local); | ||
348 | |||
349 | conf.if_id = dev->ifindex; | ||
350 | conf.type = sdata->type; | ||
351 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) | ||
352 | conf.mac_addr = NULL; | ||
353 | else | ||
354 | conf.mac_addr = dev->dev_addr; | ||
355 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
356 | if (res) { | ||
357 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) | ||
358 | ieee80211_start_hard_monitor(local); | ||
359 | return res; | ||
360 | } | ||
361 | |||
362 | if (local->open_count == 0) { | 334 | if (local->open_count == 0) { |
363 | res = 0; | 335 | res = 0; |
364 | tasklet_enable(&local->tx_pending_tasklet); | 336 | if (local->ops->start) |
365 | tasklet_enable(&local->tasklet); | 337 | res = local->ops->start(local_to_hw(local)); |
366 | if (local->ops->open) | 338 | if (res) |
367 | res = local->ops->open(local_to_hw(local)); | ||
368 | if (res == 0) { | ||
369 | res = dev_open(local->mdev); | ||
370 | if (res) { | ||
371 | if (local->ops->stop) | ||
372 | local->ops->stop(local_to_hw(local)); | ||
373 | } else { | ||
374 | res = ieee80211_hw_config(local); | ||
375 | if (res && local->ops->stop) | ||
376 | local->ops->stop(local_to_hw(local)); | ||
377 | else if (!res && local->apdev) | ||
378 | dev_open(local->apdev); | ||
379 | } | ||
380 | } | ||
381 | if (res) { | ||
382 | if (local->ops->remove_interface) | ||
383 | local->ops->remove_interface(local_to_hw(local), | ||
384 | &conf); | ||
385 | return res; | 339 | return res; |
386 | } | ||
387 | } | 340 | } |
388 | local->open_count++; | ||
389 | 341 | ||
390 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) { | 342 | switch (sdata->type) { |
343 | case IEEE80211_IF_TYPE_MNTR: | ||
344 | /* must be before the call to ieee80211_configure_filter */ | ||
391 | local->monitors++; | 345 | local->monitors++; |
392 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | 346 | if (local->monitors == 1) { |
393 | } else { | 347 | netif_tx_lock_bh(local->mdev); |
348 | ieee80211_configure_filter(local); | ||
349 | netif_tx_unlock_bh(local->mdev); | ||
350 | |||
351 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
352 | ieee80211_hw_config(local); | ||
353 | } | ||
354 | break; | ||
355 | case IEEE80211_IF_TYPE_STA: | ||
356 | case IEEE80211_IF_TYPE_IBSS: | ||
357 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
358 | /* fall through */ | ||
359 | default: | ||
360 | conf.if_id = dev->ifindex; | ||
361 | conf.type = sdata->type; | ||
362 | conf.mac_addr = dev->dev_addr; | ||
363 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
364 | if (res && !local->open_count && local->ops->stop) | ||
365 | local->ops->stop(local_to_hw(local)); | ||
366 | if (res) | ||
367 | return res; | ||
368 | |||
394 | ieee80211_if_config(dev); | 369 | ieee80211_if_config(dev); |
395 | ieee80211_reset_erp_info(dev); | 370 | ieee80211_reset_erp_info(dev); |
396 | ieee80211_enable_keys(sdata); | 371 | ieee80211_enable_keys(sdata); |
372 | |||
373 | if (sdata->type == IEEE80211_IF_TYPE_STA && | ||
374 | !local->user_space_mlme) | ||
375 | netif_carrier_off(dev); | ||
376 | else | ||
377 | netif_carrier_on(dev); | ||
397 | } | 378 | } |
398 | 379 | ||
399 | if (sdata->type == IEEE80211_IF_TYPE_STA && | 380 | if (local->open_count == 0) { |
400 | !local->user_space_mlme) | 381 | res = dev_open(local->mdev); |
401 | netif_carrier_off(dev); | 382 | WARN_ON(res); |
402 | else | 383 | if (local->apdev) { |
403 | netif_carrier_on(dev); | 384 | res = dev_open(local->apdev); |
385 | WARN_ON(res); | ||
386 | } | ||
387 | tasklet_enable(&local->tx_pending_tasklet); | ||
388 | tasklet_enable(&local->tasklet); | ||
389 | } | ||
390 | |||
391 | local->open_count++; | ||
404 | 392 | ||
405 | netif_start_queue(dev); | 393 | netif_start_queue(dev); |
394 | |||
406 | return 0; | 395 | return 0; |
407 | } | 396 | } |
408 | 397 | ||
409 | static void ieee80211_if_shutdown(struct net_device *dev) | 398 | static int ieee80211_stop(struct net_device *dev) |
410 | { | 399 | { |
400 | struct ieee80211_sub_if_data *sdata; | ||
411 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 401 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
412 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 402 | struct ieee80211_if_init_conf conf; |
403 | |||
404 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
405 | |||
406 | netif_stop_queue(dev); | ||
407 | |||
408 | dev_mc_unsync(local->mdev, dev); | ||
409 | |||
410 | local->open_count--; | ||
413 | 411 | ||
414 | ASSERT_RTNL(); | ||
415 | switch (sdata->type) { | 412 | switch (sdata->type) { |
413 | case IEEE80211_IF_TYPE_MNTR: | ||
414 | local->monitors--; | ||
415 | if (local->monitors == 0) { | ||
416 | netif_tx_lock_bh(local->mdev); | ||
417 | ieee80211_configure_filter(local); | ||
418 | netif_tx_unlock_bh(local->mdev); | ||
419 | |||
420 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
421 | ieee80211_hw_config(local); | ||
422 | } | ||
423 | break; | ||
416 | case IEEE80211_IF_TYPE_STA: | 424 | case IEEE80211_IF_TYPE_STA: |
417 | case IEEE80211_IF_TYPE_IBSS: | 425 | case IEEE80211_IF_TYPE_IBSS: |
418 | sdata->u.sta.state = IEEE80211_DISABLED; | 426 | sdata->u.sta.state = IEEE80211_DISABLED; |
@@ -433,116 +441,61 @@ static void ieee80211_if_shutdown(struct net_device *dev) | |||
433 | cancel_delayed_work(&local->scan_work); | 441 | cancel_delayed_work(&local->scan_work); |
434 | } | 442 | } |
435 | flush_workqueue(local->hw.workqueue); | 443 | flush_workqueue(local->hw.workqueue); |
436 | break; | 444 | /* fall through */ |
437 | } | 445 | default: |
438 | } | 446 | conf.if_id = dev->ifindex; |
439 | 447 | conf.type = sdata->type; | |
440 | static int ieee80211_stop(struct net_device *dev) | 448 | conf.mac_addr = dev->dev_addr; |
441 | { | ||
442 | struct ieee80211_sub_if_data *sdata; | ||
443 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
444 | |||
445 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
446 | |||
447 | if (sdata->type == IEEE80211_IF_TYPE_MNTR && | ||
448 | local->open_count > 1 && | ||
449 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { | ||
450 | /* remove "soft monitor" interface */ | ||
451 | local->open_count--; | ||
452 | local->monitors--; | ||
453 | if (!local->monitors) | ||
454 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | netif_stop_queue(dev); | ||
459 | ieee80211_if_shutdown(dev); | ||
460 | |||
461 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) { | ||
462 | local->monitors--; | ||
463 | if (!local->monitors) | ||
464 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
465 | } else { | ||
466 | /* disable all keys for as long as this netdev is down */ | 449 | /* disable all keys for as long as this netdev is down */ |
467 | ieee80211_disable_keys(sdata); | 450 | ieee80211_disable_keys(sdata); |
451 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
468 | } | 452 | } |
469 | 453 | ||
470 | local->open_count--; | ||
471 | if (local->open_count == 0) { | 454 | if (local->open_count == 0) { |
472 | if (netif_running(local->mdev)) | 455 | if (netif_running(local->mdev)) |
473 | dev_close(local->mdev); | 456 | dev_close(local->mdev); |
457 | |||
474 | if (local->apdev) | 458 | if (local->apdev) |
475 | dev_close(local->apdev); | 459 | dev_close(local->apdev); |
460 | |||
476 | if (local->ops->stop) | 461 | if (local->ops->stop) |
477 | local->ops->stop(local_to_hw(local)); | 462 | local->ops->stop(local_to_hw(local)); |
463 | |||
478 | tasklet_disable(&local->tx_pending_tasklet); | 464 | tasklet_disable(&local->tx_pending_tasklet); |
479 | tasklet_disable(&local->tasklet); | 465 | tasklet_disable(&local->tasklet); |
480 | } | 466 | } |
481 | if (local->ops->remove_interface) { | ||
482 | struct ieee80211_if_init_conf conf; | ||
483 | |||
484 | conf.if_id = dev->ifindex; | ||
485 | conf.type = sdata->type; | ||
486 | conf.mac_addr = dev->dev_addr; | ||
487 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
488 | } | ||
489 | |||
490 | ieee80211_start_hard_monitor(local); | ||
491 | 467 | ||
492 | return 0; | 468 | return 0; |
493 | } | 469 | } |
494 | 470 | ||
495 | enum netif_tx_lock_class { | ||
496 | TX_LOCK_NORMAL, | ||
497 | TX_LOCK_MASTER, | ||
498 | }; | ||
499 | |||
500 | static inline void netif_tx_lock_nested(struct net_device *dev, int subclass) | ||
501 | { | ||
502 | spin_lock_nested(&dev->_xmit_lock, subclass); | ||
503 | dev->xmit_lock_owner = smp_processor_id(); | ||
504 | } | ||
505 | |||
506 | static void ieee80211_set_multicast_list(struct net_device *dev) | 471 | static void ieee80211_set_multicast_list(struct net_device *dev) |
507 | { | 472 | { |
508 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 473 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
509 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 474 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
510 | unsigned short flags; | 475 | int allmulti, promisc, sdata_allmulti, sdata_promisc; |
511 | 476 | ||
512 | netif_tx_lock_nested(local->mdev, TX_LOCK_MASTER); | 477 | allmulti = !!(dev->flags & IFF_ALLMULTI); |
513 | if (((dev->flags & IFF_ALLMULTI) != 0) ^ | 478 | promisc = !!(dev->flags & IFF_PROMISC); |
514 | ((sdata->flags & IEEE80211_SDATA_ALLMULTI) != 0)) { | 479 | sdata_allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; |
515 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 480 | sdata_promisc = sdata->flags & IEEE80211_SDATA_PROMISC; |
516 | local->iff_allmultis--; | 481 | |
517 | else | 482 | if (allmulti != sdata_allmulti) { |
483 | if (dev->flags & IFF_ALLMULTI) | ||
518 | local->iff_allmultis++; | 484 | local->iff_allmultis++; |
485 | else | ||
486 | local->iff_allmultis--; | ||
519 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; | 487 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; |
520 | } | 488 | } |
521 | if (((dev->flags & IFF_PROMISC) != 0) ^ | 489 | |
522 | ((sdata->flags & IEEE80211_SDATA_PROMISC) != 0)) { | 490 | if (promisc != sdata_promisc) { |
523 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 491 | if (dev->flags & IFF_PROMISC) |
524 | local->iff_promiscs--; | ||
525 | else | ||
526 | local->iff_promiscs++; | 492 | local->iff_promiscs++; |
493 | else | ||
494 | local->iff_promiscs--; | ||
527 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 495 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
528 | } | 496 | } |
529 | if (dev->mc_count != sdata->mc_count) { | 497 | |
530 | local->mc_count = local->mc_count - sdata->mc_count + | 498 | dev_mc_sync(local->mdev, dev); |
531 | dev->mc_count; | ||
532 | sdata->mc_count = dev->mc_count; | ||
533 | } | ||
534 | if (local->ops->set_multicast_list) { | ||
535 | flags = local->mdev->flags; | ||
536 | if (local->iff_allmultis) | ||
537 | flags |= IFF_ALLMULTI; | ||
538 | if (local->iff_promiscs) | ||
539 | flags |= IFF_PROMISC; | ||
540 | read_lock(&local->sub_if_lock); | ||
541 | local->ops->set_multicast_list(local_to_hw(local), flags, | ||
542 | local->mc_count); | ||
543 | read_unlock(&local->sub_if_lock); | ||
544 | } | ||
545 | netif_tx_unlock(local->mdev); | ||
546 | } | 499 | } |
547 | 500 | ||
548 | static const struct header_ops ieee80211_header_ops = { | 501 | static const struct header_ops ieee80211_header_ops = { |
@@ -612,7 +565,6 @@ static int __ieee80211_if_config(struct net_device *dev, | |||
612 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 565 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
613 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 566 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
614 | struct ieee80211_if_conf conf; | 567 | struct ieee80211_if_conf conf; |
615 | static u8 scan_bssid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
616 | 568 | ||
617 | if (!local->ops->config_interface || !netif_running(dev)) | 569 | if (!local->ops->config_interface || !netif_running(dev)) |
618 | return 0; | 570 | return 0; |
@@ -621,11 +573,7 @@ static int __ieee80211_if_config(struct net_device *dev, | |||
621 | conf.type = sdata->type; | 573 | conf.type = sdata->type; |
622 | if (sdata->type == IEEE80211_IF_TYPE_STA || | 574 | if (sdata->type == IEEE80211_IF_TYPE_STA || |
623 | sdata->type == IEEE80211_IF_TYPE_IBSS) { | 575 | sdata->type == IEEE80211_IF_TYPE_IBSS) { |
624 | if (local->sta_scanning && | 576 | conf.bssid = sdata->u.sta.bssid; |
625 | local->scan_dev == dev) | ||
626 | conf.bssid = scan_bssid; | ||
627 | else | ||
628 | conf.bssid = sdata->u.sta.bssid; | ||
629 | conf.ssid = sdata->u.sta.ssid; | 577 | conf.ssid = sdata->u.sta.ssid; |
630 | conf.ssid_len = sdata->u.sta.ssid_len; | 578 | conf.ssid_len = sdata->u.sta.ssid_len; |
631 | conf.generic_elem = sdata->u.sta.extra_ie; | 579 | conf.generic_elem = sdata->u.sta.extra_ie; |
@@ -722,37 +670,6 @@ void ieee80211_reset_erp_info(struct net_device *dev) | |||
722 | IEEE80211_ERP_CHANGE_PREAMBLE); | 670 | IEEE80211_ERP_CHANGE_PREAMBLE); |
723 | } | 671 | } |
724 | 672 | ||
725 | struct dev_mc_list *ieee80211_get_mc_list_item(struct ieee80211_hw *hw, | ||
726 | struct dev_mc_list *prev, | ||
727 | void **ptr) | ||
728 | { | ||
729 | struct ieee80211_local *local = hw_to_local(hw); | ||
730 | struct ieee80211_sub_if_data *sdata = *ptr; | ||
731 | struct dev_mc_list *mc; | ||
732 | |||
733 | if (!prev) { | ||
734 | WARN_ON(sdata); | ||
735 | sdata = NULL; | ||
736 | } | ||
737 | if (!prev || !prev->next) { | ||
738 | if (sdata) | ||
739 | sdata = list_entry(sdata->list.next, | ||
740 | struct ieee80211_sub_if_data, list); | ||
741 | else | ||
742 | sdata = list_entry(local->sub_if_list.next, | ||
743 | struct ieee80211_sub_if_data, list); | ||
744 | if (&sdata->list != &local->sub_if_list) | ||
745 | mc = sdata->dev->mc_list; | ||
746 | else | ||
747 | mc = NULL; | ||
748 | } else | ||
749 | mc = prev->next; | ||
750 | |||
751 | *ptr = sdata; | ||
752 | return mc; | ||
753 | } | ||
754 | EXPORT_SYMBOL(ieee80211_get_mc_list_item); | ||
755 | |||
756 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 673 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
757 | struct sk_buff *skb, | 674 | struct sk_buff *skb, |
758 | struct ieee80211_tx_status *status) | 675 | struct ieee80211_tx_status *status) |
@@ -1158,8 +1075,12 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1158 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 1075 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
1159 | 1076 | ||
1160 | BUG_ON(!ops->tx); | 1077 | BUG_ON(!ops->tx); |
1078 | BUG_ON(!ops->start); | ||
1079 | BUG_ON(!ops->stop); | ||
1161 | BUG_ON(!ops->config); | 1080 | BUG_ON(!ops->config); |
1162 | BUG_ON(!ops->add_interface); | 1081 | BUG_ON(!ops->add_interface); |
1082 | BUG_ON(!ops->remove_interface); | ||
1083 | BUG_ON(!ops->configure_filter); | ||
1163 | local->ops = ops; | 1084 | local->ops = ops; |
1164 | 1085 | ||
1165 | /* for now, mdev needs sub_if_data :/ */ | 1086 | /* for now, mdev needs sub_if_data :/ */ |
@@ -1206,6 +1127,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1206 | mdev->stop = ieee80211_master_stop; | 1127 | mdev->stop = ieee80211_master_stop; |
1207 | mdev->type = ARPHRD_IEEE80211; | 1128 | mdev->type = ARPHRD_IEEE80211; |
1208 | mdev->header_ops = &ieee80211_header_ops; | 1129 | mdev->header_ops = &ieee80211_header_ops; |
1130 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | ||
1209 | 1131 | ||
1210 | sdata->type = IEEE80211_IF_TYPE_AP; | 1132 | sdata->type = IEEE80211_IF_TYPE_AP; |
1211 | sdata->dev = mdev; | 1133 | sdata->dev = mdev; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c3f6f89755b1..74deecd09677 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -297,8 +297,6 @@ struct ieee80211_sub_if_data { | |||
297 | struct net_device *dev; | 297 | struct net_device *dev; |
298 | struct ieee80211_local *local; | 298 | struct ieee80211_local *local; |
299 | 299 | ||
300 | int mc_count; | ||
301 | |||
302 | unsigned int flags; | 300 | unsigned int flags; |
303 | 301 | ||
304 | int drop_unencrypted; | 302 | int drop_unencrypted; |
@@ -411,6 +409,7 @@ struct ieee80211_local { | |||
411 | struct net_device *apdev; /* wlan#ap - management frames (hostapd) */ | 409 | struct net_device *apdev; /* wlan#ap - management frames (hostapd) */ |
412 | int open_count; | 410 | int open_count; |
413 | int monitors; | 411 | int monitors; |
412 | unsigned int filter_flags; /* FIF_* */ | ||
414 | struct iw_statistics wstats; | 413 | struct iw_statistics wstats; |
415 | u8 wstats_flags; | 414 | u8 wstats_flags; |
416 | int tx_headroom; /* required headroom for hardware/radiotap */ | 415 | int tx_headroom; /* required headroom for hardware/radiotap */ |
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 3f0a2faf37d4..17455c6a5229 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -2662,10 +2662,16 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
2662 | printk(KERN_DEBUG "%s: failed to restore operational" | 2662 | printk(KERN_DEBUG "%s: failed to restore operational" |
2663 | "channel after scan\n", dev->name); | 2663 | "channel after scan\n", dev->name); |
2664 | 2664 | ||
2665 | if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) && | 2665 | |
2666 | ieee80211_if_config(dev)) | 2666 | netif_tx_lock_bh(local->mdev); |
2667 | printk(KERN_DEBUG "%s: failed to restore operational" | 2667 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; |
2668 | "BSSID after scan\n", dev->name); | 2668 | local->ops->configure_filter(local_to_hw(local), |
2669 | FIF_BCN_PRBRESP_PROMISC, | ||
2670 | &local->filter_flags, | ||
2671 | local->mdev->mc_count, | ||
2672 | local->mdev->mc_list); | ||
2673 | |||
2674 | netif_tx_unlock_bh(local->mdev); | ||
2669 | 2675 | ||
2670 | memset(&wrqu, 0, sizeof(wrqu)); | 2676 | memset(&wrqu, 0, sizeof(wrqu)); |
2671 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); | 2677 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); |
@@ -2849,10 +2855,14 @@ static int ieee80211_sta_start_scan(struct net_device *dev, | |||
2849 | local->scan_channel_idx = 0; | 2855 | local->scan_channel_idx = 0; |
2850 | local->scan_dev = dev; | 2856 | local->scan_dev = dev; |
2851 | 2857 | ||
2852 | if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) && | 2858 | netif_tx_lock_bh(local->mdev); |
2853 | ieee80211_if_config(dev)) | 2859 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; |
2854 | printk(KERN_DEBUG "%s: failed to set BSSID for scan\n", | 2860 | local->ops->configure_filter(local_to_hw(local), |
2855 | dev->name); | 2861 | FIF_BCN_PRBRESP_PROMISC, |
2862 | &local->filter_flags, | ||
2863 | local->mdev->mc_count, | ||
2864 | local->mdev->mc_list); | ||
2865 | netif_tx_unlock_bh(local->mdev); | ||
2856 | 2866 | ||
2857 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | 2867 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ |
2858 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 2868 | queue_delayed_work(local->hw.workqueue, &local->scan_work, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b5f2e4c25c7e..2535d8d4ce90 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1307,7 +1307,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1307 | } else if (!multicast && | 1307 | } else if (!multicast && |
1308 | compare_ether_addr(sdata->dev->dev_addr, | 1308 | compare_ether_addr(sdata->dev->dev_addr, |
1309 | hdr->addr1) != 0) { | 1309 | hdr->addr1) != 0) { |
1310 | if (!(sdata->flags & IEEE80211_SDATA_PROMISC)) | 1310 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1311 | return 0; | 1311 | return 0; |
1312 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; | 1312 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; |
1313 | } | 1313 | } |
@@ -1322,7 +1322,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1322 | } else if (!multicast && | 1322 | } else if (!multicast && |
1323 | compare_ether_addr(sdata->dev->dev_addr, | 1323 | compare_ether_addr(sdata->dev->dev_addr, |
1324 | hdr->addr1) != 0) { | 1324 | hdr->addr1) != 0) { |
1325 | if (!(sdata->flags & IEEE80211_SDATA_PROMISC)) | 1325 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1326 | return 0; | 1326 | return 0; |
1327 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; | 1327 | rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; |
1328 | } else if (!rx->sta) | 1328 | } else if (!rx->sta) |