Commit e7a2a4f5 authored by Sujith Manoharan's avatar Sujith Manoharan Committed by John W. Linville

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: default avatarSujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 67289941
...@@ -243,6 +243,7 @@ struct ath9k_htc_target_stats { ...@@ -243,6 +243,7 @@ struct ath9k_htc_target_stats {
struct ath9k_htc_vif { struct ath9k_htc_vif {
u8 index; u8 index;
u16 seq_no; u16 seq_no;
bool beacon_configured;
}; };
struct ath9k_vif_iter_data { struct ath9k_vif_iter_data {
......
...@@ -123,8 +123,9 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, ...@@ -123,8 +123,9 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
/* TSF out of range threshold fixed at 1 second */ /* TSF out of range threshold fixed at 1 second */
bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
ath_dbg(common, ATH_DBG_BEACON, intval, tsf, tsftu);
ath_dbg(common, ATH_DBG_CONFIG,
"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
bs.bs_bmissthreshold, bs.bs_sleepduration, bs.bs_bmissthreshold, bs.bs_sleepduration,
bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
...@@ -309,12 +310,23 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) ...@@ -309,12 +310,23 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
} }
} }
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
bool *beacon_configured = (bool *)data;
struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
if (vif->type == NL80211_IFTYPE_STATION &&
avp->beacon_configured)
*beacon_configured = true;
}
static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
bool beacon_configured;
/* /*
* Changing the beacon interval when multiple AP interfaces * Changing the beacon interval when multiple AP interfaces
...@@ -327,7 +339,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, ...@@ -327,7 +339,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
(cur_conf->beacon_interval != bss_conf->beacon_int)) { (cur_conf->beacon_interval != bss_conf->beacon_int)) {
ath_dbg(common, ATH_DBG_CONFIG, ath_dbg(common, ATH_DBG_CONFIG,
"Changing beacon interval of multiple AP interfaces !\n"); "Changing beacon interval of multiple AP interfaces !\n");
return; return false;
} }
/* /*
...@@ -338,8 +350,41 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, ...@@ -338,8 +350,41 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
(vif->type != NL80211_IFTYPE_AP)) { (vif->type != NL80211_IFTYPE_AP)) {
ath_dbg(common, ATH_DBG_CONFIG, ath_dbg(common, ATH_DBG_CONFIG,
"HW in AP mode, cannot set STA beacon parameters\n"); "HW in AP mode, cannot set STA beacon parameters\n");
return; return false;
}
/*
* The beacon parameters are configured only for the first
* station interface.
*/
if ((priv->ah->opmode == NL80211_IFTYPE_STATION) &&
(priv->num_sta_vif > 1) &&
(vif->type == NL80211_IFTYPE_STATION)) {
beacon_configured = false;
ieee80211_iterate_active_interfaces_atomic(priv->hw,
ath9k_htc_beacon_iter,
&beacon_configured);
if (beacon_configured) {
ath_dbg(common, ATH_DBG_CONFIG,
"Beacon already configured for a station interface\n");
return false;
} }
}
return true;
}
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
if (!ath9k_htc_check_beacon_config(priv, vif))
return;
cur_conf->beacon_interval = bss_conf->beacon_int; cur_conf->beacon_interval = bss_conf->beacon_int;
if (cur_conf->beacon_interval == 0) if (cur_conf->beacon_interval == 0)
...@@ -352,6 +397,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, ...@@ -352,6 +397,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
ath9k_htc_beacon_config_sta(priv, cur_conf); ath9k_htc_beacon_config_sta(priv, cur_conf);
avp->beacon_configured = true;
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
ath9k_htc_beacon_config_adhoc(priv, cur_conf); ath9k_htc_beacon_config_adhoc(priv, cur_conf);
......
...@@ -1601,24 +1601,37 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1601,24 +1601,37 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah; struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
bool set_assoc;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
ath9k_htc_ps_wakeup(priv); ath9k_htc_ps_wakeup(priv);
/*
* Set the HW AID/BSSID only for the first station interface
* or in IBSS mode.
*/
set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) ||
((priv->ah->opmode == NL80211_IFTYPE_STATION) &&
(priv->num_sta_vif == 1)));
if (changed & BSS_CHANGED_ASSOC) { if (changed & BSS_CHANGED_ASSOC) {
common->curaid = bss_conf->assoc ? if (set_assoc) {
bss_conf->aid : 0;
ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
bss_conf->assoc); bss_conf->assoc);
common->curaid = bss_conf->assoc ?
bss_conf->aid : 0;
if (bss_conf->assoc) if (bss_conf->assoc)
ath9k_htc_start_ani(priv); ath9k_htc_start_ani(priv);
else else
ath9k_htc_stop_ani(priv); ath9k_htc_stop_ani(priv);
} }
}
if (changed & BSS_CHANGED_BSSID) { if (changed & BSS_CHANGED_BSSID) {
/* Set BSSID */ if (set_assoc) {
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
ath9k_hw_write_associd(ah); ath9k_hw_write_associd(ah);
...@@ -1626,6 +1639,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1626,6 +1639,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
"BSSID: %pM aid: 0x%x\n", "BSSID: %pM aid: 0x%x\n",
common->curbssid, common->curaid); common->curbssid, common->curaid);
} }
}
if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
ath_dbg(common, ATH_DBG_CONFIG, ath_dbg(common, ATH_DBG_CONFIG,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment