aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2011-04-13 01:53:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-13 15:22:18 -0400
commit9b674a0207c9b75ddcdcdb07e46843fac8267507 (patch)
tree3a52d2c77ce5af8159dc165d7f0a8b99ed499f11
parent832f6a18fc2aead14954c081ece03b7a5b425f81 (diff)
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: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c36
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c12
4 files changed, 54 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 31c649605d79..87e4ca911a58 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -245,6 +245,7 @@ struct ath9k_htc_vif {
245 u16 seq_no; 245 u16 seq_no;
246 bool beacon_configured; 246 bool beacon_configured;
247 int bslot; 247 int bslot;
248 __le64 tsfadjust;
248}; 249};
249 250
250struct ath9k_vif_iter_data { 251struct ath9k_vif_iter_data {
@@ -480,6 +481,8 @@ void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv,
480 struct ieee80211_vif *vif); 481 struct ieee80211_vif *vif);
481void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, 482void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
482 struct ieee80211_vif *vif); 483 struct ieee80211_vif *vif);
484void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv,
485 struct ieee80211_vif *vif);
483void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); 486void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
484void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, 487void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
485 struct ieee80211_vif *vif); 488 struct ieee80211_vif *vif);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index b561f703e467..2fad613add51 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -234,6 +234,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
234 struct tx_beacon_header beacon_hdr; 234 struct tx_beacon_header beacon_hdr;
235 struct ath9k_htc_tx_ctl tx_ctl; 235 struct ath9k_htc_tx_ctl tx_ctl;
236 struct ieee80211_tx_info *info; 236 struct ieee80211_tx_info *info;
237 struct ieee80211_mgmt *mgmt;
237 struct sk_buff *beacon; 238 struct sk_buff *beacon;
238 u8 *tx_fhdr; 239 u8 *tx_fhdr;
239 240
@@ -257,6 +258,13 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
257 return; 258 return;
258 } 259 }
259 260
261 /*
262 * Update the TSF adjust value here, the HW will
263 * add this value for every beacon.
264 */
265 mgmt = (struct ieee80211_mgmt *)beacon->data;
266 mgmt->u.beacon.timestamp = avp->tsfadjust;
267
260 info = IEEE80211_SKB_CB(beacon); 268 info = IEEE80211_SKB_CB(beacon);
261 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 269 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
262 struct ieee80211_hdr *hdr = 270 struct ieee80211_hdr *hdr =
@@ -406,6 +414,34 @@ void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
406 "Removed interface at beacon slot: %d\n", avp->bslot); 414 "Removed interface at beacon slot: %d\n", avp->bslot);
407} 415}
408 416
417/*
418 * Calculate the TSF adjustment value for all slots
419 * other than zero.
420 */
421void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv,
422 struct ieee80211_vif *vif)
423{
424 struct ath_common *common = ath9k_hw_common(priv->ah);
425 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv;
426 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
427 u64 tsfadjust;
428
429 if (avp->bslot == 0)
430 return;
431
432 /*
433 * The beacon interval cannot be different for multi-AP mode,
434 * and we reach here only for VIF slots greater than zero,
435 * so beacon_interval is guaranteed to be set in cur_conf.
436 */
437 tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF;
438 avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
439
440 ath_dbg(common, ATH_DBG_CONFIG,
441 "tsfadjust is: %llu for bslot: %d\n",
442 (unsigned long long)tsfadjust, avp->bslot);
443}
444
409static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 445static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
410{ 446{
411 bool *beacon_configured = (bool *)data; 447 bool *beacon_configured = (bool *)data;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 293a9b38e22e..6926ac0d5e5c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1291,8 +1291,10 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
1291 ath9k_htc_set_opmode(priv); 1291 ath9k_htc_set_opmode(priv);
1292 1292
1293 if ((priv->ah->opmode == NL80211_IFTYPE_AP) && 1293 if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
1294 !(priv->op_flags & OP_ANI_RUNNING)) 1294 !(priv->op_flags & OP_ANI_RUNNING)) {
1295 ath9k_hw_set_tsfadjust(priv->ah, 1);
1295 ath9k_htc_start_ani(priv); 1296 ath9k_htc_start_ani(priv);
1297 }
1296 1298
1297 ath_dbg(common, ATH_DBG_CONFIG, 1299 ath_dbg(common, ATH_DBG_CONFIG,
1298 "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); 1300 "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 if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { 1654 if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
1653 ath_dbg(common, ATH_DBG_CONFIG, 1655 ath_dbg(common, ATH_DBG_CONFIG,
1654 "Beacon enabled for BSS: %pM\n", bss_conf->bssid); 1656 "Beacon enabled for BSS: %pM\n", bss_conf->bssid);
1657 ath9k_htc_set_tsfadjust(priv, vif);
1655 priv->op_flags |= OP_ENABLE_BEACON; 1658 priv->op_flags |= OP_ENABLE_BEACON;
1656 ath9k_htc_beacon_config(priv, vif); 1659 ath9k_htc_beacon_config(priv, vif);
1657 } 1660 }
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 4a4f27ba96af..b3f94850821e 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -82,11 +82,12 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
82int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) 82int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
83{ 83{
84 struct ieee80211_hdr *hdr; 84 struct ieee80211_hdr *hdr;
85 struct ieee80211_mgmt *mgmt;
85 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 86 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
86 struct ieee80211_sta *sta = tx_info->control.sta; 87 struct ieee80211_sta *sta = tx_info->control.sta;
87 struct ieee80211_vif *vif = tx_info->control.vif; 88 struct ieee80211_vif *vif = tx_info->control.vif;
88 struct ath9k_htc_sta *ista; 89 struct ath9k_htc_sta *ista;
89 struct ath9k_htc_vif *avp; 90 struct ath9k_htc_vif *avp = NULL;
90 struct ath9k_htc_tx_ctl tx_ctl; 91 struct ath9k_htc_tx_ctl tx_ctl;
91 enum htc_endpoint_id epid; 92 enum htc_endpoint_id epid;
92 u16 qnum; 93 u16 qnum;
@@ -195,6 +196,15 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
195 196
196 memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); 197 memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr));
197 198
199 /*
200 * Set the TSF adjust value for probe response
201 * frame also.
202 */
203 if (avp && unlikely(ieee80211_is_probe_resp(fc))) {
204 mgmt = (struct ieee80211_mgmt *)skb->data;
205 mgmt->u.probe_resp.timestamp = avp->tsfadjust;
206 }
207
198 tx_ctl.type = ATH9K_HTC_NORMAL; 208 tx_ctl.type = ATH9K_HTC_NORMAL;
199 209
200 mgmt_hdr.node_idx = sta_idx; 210 mgmt_hdr.node_idx = sta_idx;