Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0a6ba98 authored by Sujith Manoharan's avatar Sujith Manoharan Committed by John W. Linville
Browse files

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: default avatarSujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 7d547eb4
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -358,6 +358,13 @@ struct ath_led {

#define BSTUCK_THRESHOLD 10

/*
 * Adjust these when the max. no of beaconing interfaces is
 * increased.
 */
#define DEFAULT_SWBA_RESPONSE 40 /* in TUs */
#define MIN_SWBA_RESPONSE     10 /* in TUs */

struct htc_beacon_config {
	struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF];
	u16 beacon_interval;
+34 −5
Original line number Diff line number Diff line
@@ -198,6 +198,15 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
	intval /= ATH9K_HTC_MAX_BCN_VIF;
	nexttbtt = intval;

	/*
	 * To reduce beacon misses under heavy TX load,
	 * set the beacon response time to a larger value.
	 */
	if (intval > DEFAULT_SWBA_RESPONSE)
		priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE;
	else
		priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;

	if (priv->op_flags & OP_TSF_RESET) {
		ath9k_hw_reset_tsf(priv->ah);
		priv->op_flags &= ~OP_TSF_RESET;
@@ -216,9 +225,10 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
		imask |= ATH9K_INT_SWBA;

	ath_dbg(common, ATH_DBG_CONFIG,
		"AP Beacon config, intval: %d, nexttbtt: %u "
		"AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d "
		"imask: 0x%x\n",
		bss_conf->beacon_interval, nexttbtt, imask);
		bss_conf->beacon_interval, nexttbtt,
		priv->ah->config.sw_beacon_response_time, imask);

	ath9k_htc_beaconq_config(priv);

@@ -252,12 +262,22 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
		nexttbtt += intval;
	} while (nexttbtt < tsftu);

	/*
	 * Only one IBSS interfce is allowed.
	 */
	if (intval > DEFAULT_SWBA_RESPONSE)
		priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE;
	else
		priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;

	if (priv->op_flags & OP_ENABLE_BEACON)
		imask |= ATH9K_INT_SWBA;

	ath_dbg(common, ATH_DBG_CONFIG,
		"IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n",
		bss_conf->beacon_interval, nexttbtt, imask);
		"IBSS Beacon config, intval: %d, nexttbtt: %u, "
		"resp_time: %d, imask: 0x%x\n",
		bss_conf->beacon_interval, nexttbtt,
		priv->ah->config.sw_beacon_response_time, imask);

	WMI_CMD(WMI_DISABLE_INTR_CMDID);
	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,
static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
				  int slot)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ieee80211_vif *vif;
	struct ath9k_htc_vif *avp;
	struct tx_beacon_header beacon_hdr;
@@ -325,6 +346,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
	struct ieee80211_mgmt *mgmt;
	struct sk_buff *beacon;
	u8 *tx_fhdr;
	int ret;

	memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header));
	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,
	tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));
	memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr));

	htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl);
	ret = htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl);
	if (ret != 0) {
		if (ret == -ENOMEM) {
			ath_dbg(common, ATH_DBG_BSTUCK,
				"Failed to send beacon, no free TX buffer\n");
		}
		dev_kfree_skb_any(beacon);
	}

	spin_unlock_bh(&priv->beacon_lock);
}