diff options
Diffstat (limited to 'package')
| -rw-r--r-- | package/mac80211/patches/561-ath9k_fix_staggered_beacons.patch | 317 | 
1 files changed, 317 insertions, 0 deletions
| diff --git a/package/mac80211/patches/561-ath9k_fix_staggered_beacons.patch b/package/mac80211/patches/561-ath9k_fix_staggered_beacons.patch new file mode 100644 index 000000000..08f91258f --- /dev/null +++ b/package/mac80211/patches/561-ath9k_fix_staggered_beacons.patch @@ -0,0 +1,317 @@ +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -57,8 +57,8 @@ int ath_beaconq_config(struct ath_softc  +  + /* +  *  Associates the beacon frame buffer with a transmit descriptor.  Will set +- *  up all required antenna switch parameters, rate codes, and channel flags. +- *  Beacons are always sent out at the lowest rate, and are not retried. ++ *  up rate codes, and channel flags. Beacons are always sent out at the ++ *  lowest rate, and are not retried. + */ + static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, + 			     struct ath_buf *bf, int rateidx) +@@ -68,7 +68,7 @@ static void ath_beacon_setup(struct ath_ + 	struct ath_common *common = ath9k_hw_common(ah); + 	struct ath_desc *ds; + 	struct ath9k_11n_rate_series series[4]; +-	int flags, antenna, ctsrate = 0, ctsduration = 0; ++	int flags, ctsrate = 0, ctsduration = 0; + 	struct ieee80211_supported_band *sband; + 	u8 rate = 0; +  +@@ -76,12 +76,6 @@ static void ath_beacon_setup(struct ath_ + 	flags = ATH9K_TXDESC_NOACK; +  + 	ds->ds_link = 0; +-	/* +-	 * Switch antenna every beacon. +-	 * Should only switch every beacon period, not for every SWBA +-	 * XXX assumes two antennae +-	 */ +-	antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); +  + 	sband = &sc->sbands[common->hw->conf.channel->band]; + 	rate = sband->bitrates[rateidx].hw_value; +@@ -278,7 +272,7 @@ int ath_beacon_alloc(struct ath_softc *s + 		return -ENOMEM; +  + 	tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; +-	sc->beacon.bc_tstamp = le64_to_cpu(tstamp); ++	sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp); + 	/* Calculate a TSF adjustment factor required for staggered beacons. */ + 	if (avp->av_bslot > 0) { + 		u64 tsfadjust; +@@ -294,8 +288,8 @@ int ath_beacon_alloc(struct ath_softc *s + 		 * adjustment. Other slots are adjusted to get the timestamp + 		 * close to the TBTT for the BSS. + 		 */ +-		tsfadjust = intval * avp->av_bslot / ATH_BCBUF; +-		avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); ++		tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF; ++		avp->tsf_adjust = cpu_to_le64(tsfadjust); +  + 		ath_dbg(common, ATH_DBG_BEACON, + 			"stagger beacons, bslot %d intval %u tsfadjust %llu\n", +@@ -401,8 +395,9 @@ void ath_beacon_tasklet(unsigned long da + 	intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; +  + 	tsf = ath9k_hw_gettsf64(ah); +-	tsftu = TSF_TO_TU(tsf>>32, tsf); +-	slot = ((tsftu % intval) * ATH_BCBUF) / intval; ++	tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); ++	tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); ++	slot = (tsftu % (intval * ATH_BCBUF)) / intval; + 	/* + 	 * Reverse the slot order to get slot 0 on the TBTT offset that does + 	 * not require TSF adjustment and other slots adding +@@ -415,7 +410,7 @@ void ath_beacon_tasklet(unsigned long da +  + 	ath_dbg(common, ATH_DBG_BEACON, + 		"slot %d [tsf %llu tsftu %u intval %u] vif %p\n", +-		slot, tsf, tsftu, intval, vif); ++		slot, tsf, tsftu / ATH_BCBUF, intval, vif); +  + 	bfaddr = 0; + 	if (vif) { +@@ -463,13 +458,17 @@ static void ath9k_beacon_init(struct ath + 			      u32 next_beacon, + 			      u32 beacon_period) + { +-	if (beacon_period & ATH9K_BEACON_RESET_TSF) ++	if (sc->sc_flags & SC_OP_TSF_RESET) { + 		ath9k_ps_wakeup(sc); ++		ath9k_hw_reset_tsf(sc->sc_ah); ++	} +  + 	ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); +  +-	if (beacon_period & ATH9K_BEACON_RESET_TSF) ++	if (sc->sc_flags & SC_OP_TSF_RESET) { + 		ath9k_ps_restore(sc); ++		sc->sc_flags &= ~SC_OP_TSF_RESET; ++	} + } +  + /* +@@ -484,18 +483,14 @@ static void ath_beacon_config_ap(struct  + 	u32 nexttbtt, intval; +  + 	/* NB: the beacon interval is kept internally in TU's */ +-	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; ++	intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); + 	intval /= ATH_BCBUF;    /* for staggered beacons */ + 	nexttbtt = intval; +  +-	if (sc->sc_flags & SC_OP_TSF_RESET) +-		intval |= ATH9K_BEACON_RESET_TSF; +- + 	/* + 	 * In AP mode we enable the beacon timers and SWBA interrupts to + 	 * prepare beacon frames. + 	 */ +-	intval |= ATH9K_BEACON_ENA; + 	ah->imask |= ATH9K_INT_SWBA; + 	ath_beaconq_config(sc); +  +@@ -505,11 +500,6 @@ static void ath_beacon_config_ap(struct  + 	ath9k_beacon_init(sc, nexttbtt, intval); + 	sc->beacon.bmisscnt = 0; + 	ath9k_hw_set_interrupts(ah, ah->imask); +- +-	/* Clear the reset TSF flag, so that subsequent beacon updation +-	   will not reset the HW TSF. */ +- +-	sc->sc_flags &= ~SC_OP_TSF_RESET; + } +  + /* +@@ -643,25 +633,20 @@ static void ath_beacon_config_adhoc(stru + { + 	struct ath_hw *ah = sc->sc_ah; + 	struct ath_common *common = ath9k_hw_common(ah); +-	u64 tsf; +-	u32 tsftu, intval, nexttbtt; +- +-	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; +- ++	u32 tsf, delta, intval, nexttbtt; +  +-	/* Pull nexttbtt forward to reflect the current TSF */ ++	tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); ++	intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); +  +-	nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); +-	if (nexttbtt == 0) +-                nexttbtt = intval; +-        else if (intval) +-                nexttbtt = roundup(nexttbtt, intval); +- +-	tsf = ath9k_hw_gettsf64(ah); +-	tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; +-	do { +-		nexttbtt += intval; +-	} while (nexttbtt < tsftu); ++	if (!sc->beacon.bc_tstamp) ++		nexttbtt = tsf + intval; ++	else { ++		if (tsf > sc->beacon.bc_tstamp) ++			delta = (tsf - sc->beacon.bc_tstamp); ++		else ++			delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); ++		nexttbtt = tsf + roundup(delta, intval); ++	} +  + 	ath_dbg(common, ATH_DBG_BEACON, + 		"IBSS nexttbtt %u intval %u (%u)\n", +@@ -672,7 +657,6 @@ static void ath_beacon_config_adhoc(stru + 	 * if we need to manually prepare beacon frames.  Otherwise we use a + 	 * self-linked tx descriptor and let the hardware deal with things. + 	 */ +-	intval |= ATH9K_BEACON_ENA; + 	ah->imask |= ATH9K_INT_SWBA; +  + 	ath_beaconq_config(sc); +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1706,21 +1706,15 @@ void ath9k_hw_beaconinit(struct ath_hw * + 	case NL80211_IFTYPE_MESH_POINT: + 		REG_SET_BIT(ah, AR_TXCFG, + 			    AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); +-		REG_WRITE(ah, AR_NEXT_NDP_TIMER, +-			  TU_TO_USEC(next_beacon + +-				     (ah->atim_window ? ah-> +-				      atim_window : 1))); ++		REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon + ++			  TU_TO_USEC(ah->atim_window ? ah->atim_window : 1)); + 		flags |= AR_NDP_TIMER_EN; + 	case NL80211_IFTYPE_AP: +-		REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); +-		REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, +-			  TU_TO_USEC(next_beacon - +-				     ah->config. +-				     dma_beacon_response_time)); +-		REG_WRITE(ah, AR_NEXT_SWBA, +-			  TU_TO_USEC(next_beacon - +-				     ah->config. +-				     sw_beacon_response_time)); ++		REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); ++		REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - ++			  TU_TO_USEC(ah->config.dma_beacon_response_time)); ++		REG_WRITE(ah, AR_NEXT_SWBA, next_beacon - ++			  TU_TO_USEC(ah->config.sw_beacon_response_time)); + 		flags |= + 			AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; + 		break; +@@ -1732,18 +1726,13 @@ void ath9k_hw_beaconinit(struct ath_hw * + 		break; + 	} +  +-	REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); +-	REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); +-	REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); +-	REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); ++	REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); ++	REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); ++	REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); ++	REG_WRITE(ah, AR_NDP_PERIOD, beacon_period); +  + 	REGWRITE_BUFFER_FLUSH(ah); +  +-	beacon_period &= ~ATH9K_BEACON_ENA; +-	if (beacon_period & ATH9K_BEACON_RESET_TSF) { +-		ath9k_hw_reset_tsf(ah); +-	} +- + 	REG_SET_BIT(ah, AR_TIMER_MODE, flags); + } + EXPORT_SYMBOL(ath9k_hw_beaconinit); +@@ -2404,10 +2393,11 @@ static u32 rightmost_index(struct ath_ge + 	return timer_table->gen_timer_index[b]; + } +  +-static u32 ath9k_hw_gettsf32(struct ath_hw *ah) ++u32 ath9k_hw_gettsf32(struct ath_hw *ah) + { + 	return REG_READ(ah, AR_TSF_L32); + } ++EXPORT_SYMBOL(ath9k_hw_gettsf32); +  + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, + 					  void (*trigger)(void *), +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -392,7 +392,7 @@ struct ath_beacon { + 	u32 beaconq; + 	u32 bmisscnt; + 	u32 ast_be_xmit; +-	u64 bc_tstamp; ++	u32 bc_tstamp; + 	struct ieee80211_vif *bslot[ATH_BCBUF]; + 	int slottime; + 	int slotupdate; +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -412,8 +412,6 @@ struct ath9k_beacon_state { + 	u32 bs_nextdtim; + 	u32 bs_intval; + #define ATH9K_BEACON_PERIOD       0x0000ffff +-#define ATH9K_BEACON_ENA          0x00800000 +-#define ATH9K_BEACON_RESET_TSF    0x01000000 + #define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */ + 	u32 bs_dtimperiod; + 	u16 bs_cfpperiod; +@@ -927,6 +925,7 @@ void ath9k_hw_setopmode(struct ath_hw *a + void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); + void ath9k_hw_setbssidmask(struct ath_hw *ah); + void ath9k_hw_write_associd(struct ath_hw *ah); ++u32 ath9k_hw_gettsf32(struct ath_hw *ah); + u64 ath9k_hw_gettsf64(struct ath_hw *ah); + void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); + void ath9k_hw_reset_tsf(struct ath_hw *ah); +--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +@@ -155,7 +155,7 @@ static void ath9k_htc_beacon_config_ap(s + 	nexttbtt = intval; +  + 	if (priv->op_flags & OP_TSF_RESET) { +-		intval |= ATH9K_BEACON_RESET_TSF; ++		ath9k_hw_reset_tsf(priv->ah); + 		priv->op_flags &= ~OP_TSF_RESET; + 	} else { + 		/* +@@ -168,8 +168,6 @@ static void ath9k_htc_beacon_config_ap(s + 		} while (nexttbtt < tsftu); + 	} +  +-	intval |= ATH9K_BEACON_ENA; +- + 	if (priv->op_flags & OP_ENABLE_BEACON) + 		imask |= ATH9K_INT_SWBA; +  +@@ -178,7 +176,7 @@ static void ath9k_htc_beacon_config_ap(s + 		bss_conf->beacon_interval, nexttbtt, imask); +  + 	WMI_CMD(WMI_DISABLE_INTR_CMDID); +-	ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); ++	ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); + 	priv->bmiss_cnt = 0; + 	htc_imask = cpu_to_be32(imask); + 	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); +@@ -207,7 +205,6 @@ static void ath9k_htc_beacon_config_adho + 		nexttbtt += intval; + 	} while (nexttbtt < tsftu); +  +-	intval |= ATH9K_BEACON_ENA; + 	if (priv->op_flags & OP_ENABLE_BEACON) + 		imask |= ATH9K_INT_SWBA; +  +@@ -216,7 +213,7 @@ static void ath9k_htc_beacon_config_adho + 		bss_conf->beacon_interval, nexttbtt, imask); +  + 	WMI_CMD(WMI_DISABLE_INTR_CMDID); +-	ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); ++	ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); + 	priv->bmiss_cnt = 0; + 	htc_imask = cpu_to_be32(imask); + 	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 
