aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c52
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h13
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c19
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 91411e9b4b6..e6ff62e60a7 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
445struct ath_vif_iter_data { 445void 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
455static 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
492void 485void
@@ -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
533void 527 /* Set up RX Filter */
534ath5k_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
547static inline int 541static 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)
2923bool 2917bool
2924ath_any_vif_assoc(struct ath5k_softc *sc) 2918ath_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 8f919dca95f..8d1df1fa235 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
262struct 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};
272void 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 1fbe3c0b9f0..c9b0b676add 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;
164end: 163end:
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