diff options
author | Sujith Manoharan <Sujith.Manoharan@atheros.com> | 2011-02-26 22:50:40 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-03-01 13:48:21 -0500 |
commit | e7a2a4f5e61ccfae03185384e06b852dbb1e3630 (patch) | |
tree | f798c3576f9eaf7ecaf3e7ee7c2cb85435b6d84c | |
parent | 67289941d80f18fd8239e350e015a4b84878412b (diff) |
ath9k_htc: Handle BSSID/AID for multiple interfaces
The AID and BSSID should be set in the HW only for the
first station interface or adhoc interface. Also, cancel
the ANI timer in stop() for multi-STA scenario. And finally
configure the HW beacon timers only for the first station
interface.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 58 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 42 |
3 files changed, 81 insertions, 20 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index e9c51cae88ab..753a245c5ad1 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -243,6 +243,7 @@ struct ath9k_htc_target_stats { | |||
243 | struct ath9k_htc_vif { | 243 | struct ath9k_htc_vif { |
244 | u8 index; | 244 | u8 index; |
245 | u16 seq_no; | 245 | u16 seq_no; |
246 | bool beacon_configured; | ||
246 | }; | 247 | }; |
247 | 248 | ||
248 | struct ath9k_vif_iter_data { | 249 | struct ath9k_vif_iter_data { |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 007b99fc50c8..8d1d8792436d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -123,8 +123,9 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
123 | /* TSF out of range threshold fixed at 1 second */ | 123 | /* TSF out of range threshold fixed at 1 second */ |
124 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | 124 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
125 | 125 | ||
126 | ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | 126 | ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n", |
127 | ath_dbg(common, ATH_DBG_BEACON, | 127 | intval, tsf, tsftu); |
128 | ath_dbg(common, ATH_DBG_CONFIG, | ||
128 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | 129 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", |
129 | bs.bs_bmissthreshold, bs.bs_sleepduration, | 130 | bs.bs_bmissthreshold, bs.bs_sleepduration, |
130 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | 131 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); |
@@ -309,12 +310,23 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | |||
309 | } | 310 | } |
310 | } | 311 | } |
311 | 312 | ||
312 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 313 | static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
313 | struct ieee80211_vif *vif) | 314 | { |
315 | bool *beacon_configured = (bool *)data; | ||
316 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
317 | |||
318 | if (vif->type == NL80211_IFTYPE_STATION && | ||
319 | avp->beacon_configured) | ||
320 | *beacon_configured = true; | ||
321 | } | ||
322 | |||
323 | static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, | ||
324 | struct ieee80211_vif *vif) | ||
314 | { | 325 | { |
315 | struct ath_common *common = ath9k_hw_common(priv->ah); | 326 | struct ath_common *common = ath9k_hw_common(priv->ah); |
316 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | 327 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
317 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 328 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
329 | bool beacon_configured; | ||
318 | 330 | ||
319 | /* | 331 | /* |
320 | * Changing the beacon interval when multiple AP interfaces | 332 | * Changing the beacon interval when multiple AP interfaces |
@@ -327,7 +339,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | |||
327 | (cur_conf->beacon_interval != bss_conf->beacon_int)) { | 339 | (cur_conf->beacon_interval != bss_conf->beacon_int)) { |
328 | ath_dbg(common, ATH_DBG_CONFIG, | 340 | ath_dbg(common, ATH_DBG_CONFIG, |
329 | "Changing beacon interval of multiple AP interfaces !\n"); | 341 | "Changing beacon interval of multiple AP interfaces !\n"); |
330 | return; | 342 | return false; |
331 | } | 343 | } |
332 | 344 | ||
333 | /* | 345 | /* |
@@ -338,9 +350,42 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | |||
338 | (vif->type != NL80211_IFTYPE_AP)) { | 350 | (vif->type != NL80211_IFTYPE_AP)) { |
339 | ath_dbg(common, ATH_DBG_CONFIG, | 351 | ath_dbg(common, ATH_DBG_CONFIG, |
340 | "HW in AP mode, cannot set STA beacon parameters\n"); | 352 | "HW in AP mode, cannot set STA beacon parameters\n"); |
341 | return; | 353 | return false; |
354 | } | ||
355 | |||
356 | /* | ||
357 | * The beacon parameters are configured only for the first | ||
358 | * station interface. | ||
359 | */ | ||
360 | if ((priv->ah->opmode == NL80211_IFTYPE_STATION) && | ||
361 | (priv->num_sta_vif > 1) && | ||
362 | (vif->type == NL80211_IFTYPE_STATION)) { | ||
363 | beacon_configured = false; | ||
364 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
365 | ath9k_htc_beacon_iter, | ||
366 | &beacon_configured); | ||
367 | |||
368 | if (beacon_configured) { | ||
369 | ath_dbg(common, ATH_DBG_CONFIG, | ||
370 | "Beacon already configured for a station interface\n"); | ||
371 | return false; | ||
372 | } | ||
342 | } | 373 | } |
343 | 374 | ||
375 | return true; | ||
376 | } | ||
377 | |||
378 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | ||
379 | struct ieee80211_vif *vif) | ||
380 | { | ||
381 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
382 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
383 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
384 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
385 | |||
386 | if (!ath9k_htc_check_beacon_config(priv, vif)) | ||
387 | return; | ||
388 | |||
344 | cur_conf->beacon_interval = bss_conf->beacon_int; | 389 | cur_conf->beacon_interval = bss_conf->beacon_int; |
345 | if (cur_conf->beacon_interval == 0) | 390 | if (cur_conf->beacon_interval == 0) |
346 | cur_conf->beacon_interval = 100; | 391 | cur_conf->beacon_interval = 100; |
@@ -352,6 +397,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | |||
352 | switch (vif->type) { | 397 | switch (vif->type) { |
353 | case NL80211_IFTYPE_STATION: | 398 | case NL80211_IFTYPE_STATION: |
354 | ath9k_htc_beacon_config_sta(priv, cur_conf); | 399 | ath9k_htc_beacon_config_sta(priv, cur_conf); |
400 | avp->beacon_configured = true; | ||
355 | break; | 401 | break; |
356 | case NL80211_IFTYPE_ADHOC: | 402 | case NL80211_IFTYPE_ADHOC: |
357 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); | 403 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 71adab34006c..db8c0c044e9e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1601,30 +1601,44 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1601 | struct ath9k_htc_priv *priv = hw->priv; | 1601 | struct ath9k_htc_priv *priv = hw->priv; |
1602 | struct ath_hw *ah = priv->ah; | 1602 | struct ath_hw *ah = priv->ah; |
1603 | struct ath_common *common = ath9k_hw_common(ah); | 1603 | struct ath_common *common = ath9k_hw_common(ah); |
1604 | bool set_assoc; | ||
1604 | 1605 | ||
1605 | mutex_lock(&priv->mutex); | 1606 | mutex_lock(&priv->mutex); |
1606 | ath9k_htc_ps_wakeup(priv); | 1607 | ath9k_htc_ps_wakeup(priv); |
1607 | 1608 | ||
1609 | /* | ||
1610 | * Set the HW AID/BSSID only for the first station interface | ||
1611 | * or in IBSS mode. | ||
1612 | */ | ||
1613 | set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) || | ||
1614 | ((priv->ah->opmode == NL80211_IFTYPE_STATION) && | ||
1615 | (priv->num_sta_vif == 1))); | ||
1616 | |||
1617 | |||
1608 | if (changed & BSS_CHANGED_ASSOC) { | 1618 | if (changed & BSS_CHANGED_ASSOC) { |
1609 | common->curaid = bss_conf->assoc ? | 1619 | if (set_assoc) { |
1610 | bss_conf->aid : 0; | 1620 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", |
1611 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | 1621 | bss_conf->assoc); |
1612 | bss_conf->assoc); | ||
1613 | 1622 | ||
1614 | if (bss_conf->assoc) | 1623 | common->curaid = bss_conf->assoc ? |
1615 | ath9k_htc_start_ani(priv); | 1624 | bss_conf->aid : 0; |
1616 | else | 1625 | |
1617 | ath9k_htc_stop_ani(priv); | 1626 | if (bss_conf->assoc) |
1627 | ath9k_htc_start_ani(priv); | ||
1628 | else | ||
1629 | ath9k_htc_stop_ani(priv); | ||
1630 | } | ||
1618 | } | 1631 | } |
1619 | 1632 | ||
1620 | if (changed & BSS_CHANGED_BSSID) { | 1633 | if (changed & BSS_CHANGED_BSSID) { |
1621 | /* Set BSSID */ | 1634 | if (set_assoc) { |
1622 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | 1635 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
1623 | ath9k_hw_write_associd(ah); | 1636 | ath9k_hw_write_associd(ah); |
1624 | 1637 | ||
1625 | ath_dbg(common, ATH_DBG_CONFIG, | 1638 | ath_dbg(common, ATH_DBG_CONFIG, |
1626 | "BSSID: %pM aid: 0x%x\n", | 1639 | "BSSID: %pM aid: 0x%x\n", |
1627 | common->curbssid, common->curaid); | 1640 | common->curbssid, common->curaid); |
1641 | } | ||
1628 | } | 1642 | } |
1629 | 1643 | ||
1630 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { | 1644 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { |