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

ath9k_htc: Add TSF adjust capability

In multi-interface mode, beacons/probe responses that are
sent out must have their timestamp field updated. Calculate
the TSF adjustment value for each beaconing interface and set it
in the frame properly.
Signed-off-by: default avatarSujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 832f6a18
...@@ -245,6 +245,7 @@ struct ath9k_htc_vif { ...@@ -245,6 +245,7 @@ struct ath9k_htc_vif {
u16 seq_no; u16 seq_no;
bool beacon_configured; bool beacon_configured;
int bslot; int bslot;
__le64 tsfadjust;
}; };
struct ath9k_vif_iter_data { struct ath9k_vif_iter_data {
...@@ -480,6 +481,8 @@ void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, ...@@ -480,6 +481,8 @@ void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif);
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
......
...@@ -234,6 +234,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, ...@@ -234,6 +234,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
struct tx_beacon_header beacon_hdr; struct tx_beacon_header beacon_hdr;
struct ath9k_htc_tx_ctl tx_ctl; struct ath9k_htc_tx_ctl tx_ctl;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
struct ieee80211_mgmt *mgmt;
struct sk_buff *beacon; struct sk_buff *beacon;
u8 *tx_fhdr; u8 *tx_fhdr;
...@@ -257,6 +258,13 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, ...@@ -257,6 +258,13 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
return; return;
} }
/*
* Update the TSF adjust value here, the HW will
* add this value for every beacon.
*/
mgmt = (struct ieee80211_mgmt *)beacon->data;
mgmt->u.beacon.timestamp = avp->tsfadjust;
info = IEEE80211_SKB_CB(beacon); info = IEEE80211_SKB_CB(beacon);
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
struct ieee80211_hdr *hdr = struct ieee80211_hdr *hdr =
...@@ -406,6 +414,34 @@ void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, ...@@ -406,6 +414,34 @@ void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
"Removed interface at beacon slot: %d\n", avp->bslot); "Removed interface at beacon slot: %d\n", avp->bslot);
} }
/*
* Calculate the TSF adjustment value for all slots
* other than zero.
*/
void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv;
struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
u64 tsfadjust;
if (avp->bslot == 0)
return;
/*
* The beacon interval cannot be different for multi-AP mode,
* and we reach here only for VIF slots greater than zero,
* so beacon_interval is guaranteed to be set in cur_conf.
*/
tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF;
avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
ath_dbg(common, ATH_DBG_CONFIG,
"tsfadjust is: %llu for bslot: %d\n",
(unsigned long long)tsfadjust, avp->bslot);
}
static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{ {
bool *beacon_configured = (bool *)data; bool *beacon_configured = (bool *)data;
......
...@@ -1291,8 +1291,10 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, ...@@ -1291,8 +1291,10 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
ath9k_htc_set_opmode(priv); ath9k_htc_set_opmode(priv);
if ((priv->ah->opmode == NL80211_IFTYPE_AP) && if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
!(priv->op_flags & OP_ANI_RUNNING)) !(priv->op_flags & OP_ANI_RUNNING)) {
ath9k_hw_set_tsfadjust(priv->ah, 1);
ath9k_htc_start_ani(priv); ath9k_htc_start_ani(priv);
}
ath_dbg(common, ATH_DBG_CONFIG, ath_dbg(common, ATH_DBG_CONFIG,
"Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index);
...@@ -1652,6 +1654,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1652,6 +1654,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
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,
"Beacon enabled for BSS: %pM\n", bss_conf->bssid); "Beacon enabled for BSS: %pM\n", bss_conf->bssid);
ath9k_htc_set_tsfadjust(priv, vif);
priv->op_flags |= OP_ENABLE_BEACON; priv->op_flags |= OP_ENABLE_BEACON;
ath9k_htc_beacon_config(priv, vif); ath9k_htc_beacon_config(priv, vif);
} }
......
...@@ -82,11 +82,12 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, ...@@ -82,11 +82,12 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ieee80211_mgmt *mgmt;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_sta *sta = tx_info->control.sta;
struct ieee80211_vif *vif = tx_info->control.vif; struct ieee80211_vif *vif = tx_info->control.vif;
struct ath9k_htc_sta *ista; struct ath9k_htc_sta *ista;
struct ath9k_htc_vif *avp; struct ath9k_htc_vif *avp = NULL;
struct ath9k_htc_tx_ctl tx_ctl; struct ath9k_htc_tx_ctl tx_ctl;
enum htc_endpoint_id epid; enum htc_endpoint_id epid;
u16 qnum; u16 qnum;
...@@ -195,6 +196,15 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) ...@@ -195,6 +196,15 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr));
/*
* Set the TSF adjust value for probe response
* frame also.
*/
if (avp && unlikely(ieee80211_is_probe_resp(fc))) {
mgmt = (struct ieee80211_mgmt *)skb->data;
mgmt->u.probe_resp.timestamp = avp->tsfadjust;
}
tx_ctl.type = ATH9K_HTC_NORMAL; tx_ctl.type = ATH9K_HTC_NORMAL;
mgmt_hdr.node_idx = sta_idx; mgmt_hdr.node_idx = sta_idx;
......
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