diff options
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 52 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/mac80211-ops.c | 19 |
3 files changed, 53 insertions, 31 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 91411e9b4b68..e6ff62e60a79 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -442,19 +442,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
442 | return ath5k_reset(sc, chan, true); | 442 | return ath5k_reset(sc, chan, true); |
443 | } | 443 | } |
444 | 444 | ||
445 | struct ath_vif_iter_data { | 445 | void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
446 | const u8 *hw_macaddr; | ||
447 | u8 mask[ETH_ALEN]; | ||
448 | u8 active_mac[ETH_ALEN]; /* first active MAC */ | ||
449 | bool need_set_hw_addr; | ||
450 | bool found_active; | ||
451 | bool any_assoc; | ||
452 | enum nl80211_iftype opmode; | ||
453 | }; | ||
454 | |||
455 | static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
456 | { | 446 | { |
457 | struct ath_vif_iter_data *iter_data = data; | 447 | struct ath5k_vif_iter_data *iter_data = data; |
458 | int i; | 448 | int i; |
459 | struct ath5k_vif *avf = (void *)vif->drv_priv; | 449 | struct ath5k_vif *avf = (void *)vif->drv_priv; |
460 | 450 | ||
@@ -484,9 +474,12 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
484 | */ | 474 | */ |
485 | if (avf->opmode == NL80211_IFTYPE_AP) | 475 | if (avf->opmode == NL80211_IFTYPE_AP) |
486 | iter_data->opmode = NL80211_IFTYPE_AP; | 476 | iter_data->opmode = NL80211_IFTYPE_AP; |
487 | else | 477 | else { |
478 | if (avf->opmode == NL80211_IFTYPE_STATION) | ||
479 | iter_data->n_stas++; | ||
488 | if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED) | 480 | if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED) |
489 | iter_data->opmode = avf->opmode; | 481 | iter_data->opmode = avf->opmode; |
482 | } | ||
490 | } | 483 | } |
491 | 484 | ||
492 | void | 485 | void |
@@ -494,7 +487,8 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, | |||
494 | struct ieee80211_vif *vif) | 487 | struct ieee80211_vif *vif) |
495 | { | 488 | { |
496 | struct ath_common *common = ath5k_hw_common(sc->ah); | 489 | struct ath_common *common = ath5k_hw_common(sc->ah); |
497 | struct ath_vif_iter_data iter_data; | 490 | struct ath5k_vif_iter_data iter_data; |
491 | u32 rfilt; | ||
498 | 492 | ||
499 | /* | 493 | /* |
500 | * Use the hardware MAC address as reference, the hardware uses it | 494 | * Use the hardware MAC address as reference, the hardware uses it |
@@ -505,12 +499,13 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, | |||
505 | iter_data.found_active = false; | 499 | iter_data.found_active = false; |
506 | iter_data.need_set_hw_addr = true; | 500 | iter_data.need_set_hw_addr = true; |
507 | iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED; | 501 | iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED; |
502 | iter_data.n_stas = 0; | ||
508 | 503 | ||
509 | if (vif) | 504 | if (vif) |
510 | ath_vif_iter(&iter_data, vif->addr, vif); | 505 | ath5k_vif_iter(&iter_data, vif->addr, vif); |
511 | 506 | ||
512 | /* Get list of all active MAC addresses */ | 507 | /* Get list of all active MAC addresses */ |
513 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter, | 508 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, |
514 | &iter_data); | 509 | &iter_data); |
515 | memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN); | 510 | memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN); |
516 | 511 | ||
@@ -528,20 +523,19 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, | |||
528 | 523 | ||
529 | if (ath5k_hw_hasbssidmask(sc->ah)) | 524 | if (ath5k_hw_hasbssidmask(sc->ah)) |
530 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | 525 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); |
531 | } | ||
532 | 526 | ||
533 | void | 527 | /* Set up RX Filter */ |
534 | ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif) | 528 | if (iter_data.n_stas > 1) { |
535 | { | 529 | /* If you have multiple STA interfaces connected to |
536 | struct ath5k_hw *ah = sc->ah; | 530 | * different APs, ARPs are not received (most of the time?) |
537 | u32 rfilt; | 531 | * Enabling PROMISC appears to fix that probem. |
532 | */ | ||
533 | sc->filter_flags |= AR5K_RX_FILTER_PROM; | ||
534 | } | ||
538 | 535 | ||
539 | /* configure rx filter */ | ||
540 | rfilt = sc->filter_flags; | 536 | rfilt = sc->filter_flags; |
541 | ath5k_hw_set_rx_filter(ah, rfilt); | 537 | ath5k_hw_set_rx_filter(sc->ah, rfilt); |
542 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | 538 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); |
543 | |||
544 | ath5k_update_bssid_mask_and_opmode(sc, vif); | ||
545 | } | 539 | } |
546 | 540 | ||
547 | static inline int | 541 | static inline int |
@@ -1117,7 +1111,7 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1117 | spin_unlock_bh(&sc->rxbuflock); | 1111 | spin_unlock_bh(&sc->rxbuflock); |
1118 | 1112 | ||
1119 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ | 1113 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ |
1120 | ath5k_mode_setup(sc, NULL); /* set filters, etc. */ | 1114 | ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */ |
1121 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ | 1115 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ |
1122 | 1116 | ||
1123 | return 0; | 1117 | return 0; |
@@ -2923,13 +2917,13 @@ ath5k_deinit_softc(struct ath5k_softc *sc) | |||
2923 | bool | 2917 | bool |
2924 | ath_any_vif_assoc(struct ath5k_softc *sc) | 2918 | ath_any_vif_assoc(struct ath5k_softc *sc) |
2925 | { | 2919 | { |
2926 | struct ath_vif_iter_data iter_data; | 2920 | struct ath5k_vif_iter_data iter_data; |
2927 | iter_data.hw_macaddr = NULL; | 2921 | iter_data.hw_macaddr = NULL; |
2928 | iter_data.any_assoc = false; | 2922 | iter_data.any_assoc = false; |
2929 | iter_data.need_set_hw_addr = false; | 2923 | iter_data.need_set_hw_addr = false; |
2930 | iter_data.found_active = true; | 2924 | iter_data.found_active = true; |
2931 | 2925 | ||
2932 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter, | 2926 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, |
2933 | &iter_data); | 2927 | &iter_data); |
2934 | return iter_data.any_assoc; | 2928 | return iter_data.any_assoc; |
2935 | } | 2929 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 8f919dca95f1..8d1df1fa2351 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -259,6 +259,19 @@ struct ath5k_softc { | |||
259 | struct survey_info survey; /* collected survey info */ | 259 | struct survey_info survey; /* collected survey info */ |
260 | }; | 260 | }; |
261 | 261 | ||
262 | struct ath5k_vif_iter_data { | ||
263 | const u8 *hw_macaddr; | ||
264 | u8 mask[ETH_ALEN]; | ||
265 | u8 active_mac[ETH_ALEN]; /* first active MAC */ | ||
266 | bool need_set_hw_addr; | ||
267 | bool found_active; | ||
268 | bool any_assoc; | ||
269 | enum nl80211_iftype opmode; | ||
270 | int n_stas; | ||
271 | }; | ||
272 | void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif); | ||
273 | |||
274 | |||
262 | #define ath5k_hw_hasbssidmask(_ah) \ | 275 | #define ath5k_hw_hasbssidmask(_ah) \ |
263 | (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) | 276 | (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) |
264 | #define ath5k_hw_hasveol(_ah) \ | 277 | #define ath5k_hw_hasveol(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 1fbe3c0b9f08..c9b0b676adda 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -158,8 +158,7 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
158 | 158 | ||
159 | memcpy(&avf->lladdr, vif->addr, ETH_ALEN); | 159 | memcpy(&avf->lladdr, vif->addr, ETH_ALEN); |
160 | 160 | ||
161 | ath5k_mode_setup(sc, vif); | 161 | ath5k_update_bssid_mask_and_opmode(sc, vif); |
162 | |||
163 | ret = 0; | 162 | ret = 0; |
164 | end: | 163 | end: |
165 | mutex_unlock(&sc->lock); | 164 | mutex_unlock(&sc->lock); |
@@ -381,6 +380,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | |||
381 | struct ath5k_softc *sc = hw->priv; | 380 | struct ath5k_softc *sc = hw->priv; |
382 | struct ath5k_hw *ah = sc->ah; | 381 | struct ath5k_hw *ah = sc->ah; |
383 | u32 mfilt[2], rfilt; | 382 | u32 mfilt[2], rfilt; |
383 | struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */ | ||
384 | 384 | ||
385 | mutex_lock(&sc->lock); | 385 | mutex_lock(&sc->lock); |
386 | 386 | ||
@@ -454,6 +454,21 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | |||
454 | break; | 454 | break; |
455 | } | 455 | } |
456 | 456 | ||
457 | iter_data.hw_macaddr = NULL; | ||
458 | iter_data.n_stas = 0; | ||
459 | iter_data.need_set_hw_addr = false; | ||
460 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, | ||
461 | &iter_data); | ||
462 | |||
463 | /* Set up RX Filter */ | ||
464 | if (iter_data.n_stas > 1) { | ||
465 | /* If you have multiple STA interfaces connected to | ||
466 | * different APs, ARPs are not received (most of the time?) | ||
467 | * Enabling PROMISC appears to fix that probem. | ||
468 | */ | ||
469 | rfilt |= AR5K_RX_FILTER_PROM; | ||
470 | } | ||
471 | |||
457 | /* Set filters */ | 472 | /* Set filters */ |
458 | ath5k_hw_set_rx_filter(ah, rfilt); | 473 | ath5k_hw_set_rx_filter(ah, rfilt); |
459 | 474 | ||