diff options
author | Sujith Manoharan <Sujith.Manoharan@atheros.com> | 2011-04-13 01:53:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-13 15:22:30 -0400 |
commit | b0a6ba983e3663bf256ca2e79d17bb846878cd9e (patch) | |
tree | cbe44eca979372ee0e723552c406da55f1d8fb83 | |
parent | 7d547eb4bb664c5a6b7c8790c2ecb0aec5d15385 (diff) |
ath9k_htc: Fix beacon miss under heavy load
Transmission of beacons becomes erratic when TX load
is high, since the latency involved in the generation
of a SWBA interrupt on the target to the actual sending
of a beacon is quite high for USB devices.
Fix this by adjusting the beacon response time.
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 | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 39 |
2 files changed, 41 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index a072a9eb3f3e..133fc6dc3929 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -358,6 +358,13 @@ struct ath_led { | |||
358 | 358 | ||
359 | #define BSTUCK_THRESHOLD 10 | 359 | #define BSTUCK_THRESHOLD 10 |
360 | 360 | ||
361 | /* | ||
362 | * Adjust these when the max. no of beaconing interfaces is | ||
363 | * increased. | ||
364 | */ | ||
365 | #define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ | ||
366 | #define MIN_SWBA_RESPONSE 10 /* in TUs */ | ||
367 | |||
361 | struct htc_beacon_config { | 368 | struct htc_beacon_config { |
362 | struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; | 369 | struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; |
363 | u16 beacon_interval; | 370 | u16 beacon_interval; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index c96779c24296..48bc28823f6f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -198,6 +198,15 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | |||
198 | intval /= ATH9K_HTC_MAX_BCN_VIF; | 198 | intval /= ATH9K_HTC_MAX_BCN_VIF; |
199 | nexttbtt = intval; | 199 | nexttbtt = intval; |
200 | 200 | ||
201 | /* | ||
202 | * To reduce beacon misses under heavy TX load, | ||
203 | * set the beacon response time to a larger value. | ||
204 | */ | ||
205 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
206 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
207 | else | ||
208 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
209 | |||
201 | if (priv->op_flags & OP_TSF_RESET) { | 210 | if (priv->op_flags & OP_TSF_RESET) { |
202 | ath9k_hw_reset_tsf(priv->ah); | 211 | ath9k_hw_reset_tsf(priv->ah); |
203 | priv->op_flags &= ~OP_TSF_RESET; | 212 | priv->op_flags &= ~OP_TSF_RESET; |
@@ -216,9 +225,10 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | |||
216 | imask |= ATH9K_INT_SWBA; | 225 | imask |= ATH9K_INT_SWBA; |
217 | 226 | ||
218 | ath_dbg(common, ATH_DBG_CONFIG, | 227 | ath_dbg(common, ATH_DBG_CONFIG, |
219 | "AP Beacon config, intval: %d, nexttbtt: %u " | 228 | "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d " |
220 | "imask: 0x%x\n", | 229 | "imask: 0x%x\n", |
221 | bss_conf->beacon_interval, nexttbtt, imask); | 230 | bss_conf->beacon_interval, nexttbtt, |
231 | priv->ah->config.sw_beacon_response_time, imask); | ||
222 | 232 | ||
223 | ath9k_htc_beaconq_config(priv); | 233 | ath9k_htc_beaconq_config(priv); |
224 | 234 | ||
@@ -252,12 +262,22 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | |||
252 | nexttbtt += intval; | 262 | nexttbtt += intval; |
253 | } while (nexttbtt < tsftu); | 263 | } while (nexttbtt < tsftu); |
254 | 264 | ||
265 | /* | ||
266 | * Only one IBSS interfce is allowed. | ||
267 | */ | ||
268 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
269 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
270 | else | ||
271 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
272 | |||
255 | if (priv->op_flags & OP_ENABLE_BEACON) | 273 | if (priv->op_flags & OP_ENABLE_BEACON) |
256 | imask |= ATH9K_INT_SWBA; | 274 | imask |= ATH9K_INT_SWBA; |
257 | 275 | ||
258 | ath_dbg(common, ATH_DBG_CONFIG, | 276 | ath_dbg(common, ATH_DBG_CONFIG, |
259 | "IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n", | 277 | "IBSS Beacon config, intval: %d, nexttbtt: %u, " |
260 | bss_conf->beacon_interval, nexttbtt, imask); | 278 | "resp_time: %d, imask: 0x%x\n", |
279 | bss_conf->beacon_interval, nexttbtt, | ||
280 | priv->ah->config.sw_beacon_response_time, imask); | ||
261 | 281 | ||
262 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 282 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
263 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); | 283 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); |
@@ -317,6 +337,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, | |||
317 | static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | 337 | static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, |
318 | int slot) | 338 | int slot) |
319 | { | 339 | { |
340 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
320 | struct ieee80211_vif *vif; | 341 | struct ieee80211_vif *vif; |
321 | struct ath9k_htc_vif *avp; | 342 | struct ath9k_htc_vif *avp; |
322 | struct tx_beacon_header beacon_hdr; | 343 | struct tx_beacon_header beacon_hdr; |
@@ -325,6 +346,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | |||
325 | struct ieee80211_mgmt *mgmt; | 346 | struct ieee80211_mgmt *mgmt; |
326 | struct sk_buff *beacon; | 347 | struct sk_buff *beacon; |
327 | u8 *tx_fhdr; | 348 | u8 *tx_fhdr; |
349 | int ret; | ||
328 | 350 | ||
329 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); | 351 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); |
330 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | 352 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); |
@@ -367,7 +389,14 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | |||
367 | tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); | 389 | tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); |
368 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); | 390 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); |
369 | 391 | ||
370 | htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); | 392 | ret = htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); |
393 | if (ret != 0) { | ||
394 | if (ret == -ENOMEM) { | ||
395 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
396 | "Failed to send beacon, no free TX buffer\n"); | ||
397 | } | ||
398 | dev_kfree_skb_any(beacon); | ||
399 | } | ||
371 | 400 | ||
372 | spin_unlock_bh(&priv->beacon_lock); | 401 | spin_unlock_bh(&priv->beacon_lock); |
373 | } | 402 | } |