[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    athn(4): explicit timing of control frames
From:       Stefan Sperling <stsp () stsp ! name>
Date:       2019-02-19 10:39:30
Message-ID: 20190219103930.GQ61773 () ted ! stsp ! name
[Download RAW message or body]

Our athn(4) driver currently doesn't configure timing of control
frames generated in hardware. It keeps using whatever magic numbers our
init vals arrays are setting up. With this diff we update the chip with
the same values as used by Linux when configuration changes occur.

I don't notice any difference in my testing. Please run this diff with
PCI and USB devices, watch for regressions, and let me know your results.

diff bb1f4f10a1f3306630a2ce77de0832219fb53582 /usr/src
blob - af5296bfd5ef783a552ca16f283c8b43ea1ff15d
file + sys/dev/ic/athn.c
--- sys/dev/ic/athn.c
+++ sys/dev/ic/athn.c
@@ -136,6 +136,14 @@ int		athn_newstate(struct ieee80211com *, enum ieee802
 		    int);
 void		athn_updateedca(struct ieee80211com *);
 int		athn_clock_rate(struct athn_softc *);
+int		athn_chan_sifs(struct ieee80211_channel *);
+void		athn_setsifs(struct athn_softc *);
+int		athn_acktimeout(struct ieee80211_channel *, int);
+void		athn_setacktimeout(struct athn_softc *,
+		    struct ieee80211_channel *, int);
+void		athn_setctstimeout(struct athn_softc *,
+		    struct ieee80211_channel *, int);
+void		athn_setclockrate(struct athn_softc *);
 void		athn_updateslot(struct ieee80211com *);
 void		athn_start(struct ifnet *);
 void		athn_watchdog(struct ifnet *);
@@ -2403,6 +2411,9 @@ athn_hw_reset(struct athn_softc *sc, struct ieee80211_
 
 	AR_SETBITS(sc, AR_PCU_MISC, AR_PCU_MIC_NEW_LOC_ENA);
 
+	athn_setsifs(sc);
+	athn_updateslot(ic);
+	athn_setclockrate(sc);
 	if (AR_SREV_9287_13_OR_LATER(sc) && !AR_SREV_9380_10_OR_LATER(sc))
 		ar9287_1_3_setup_async_fifo(sc);
 
@@ -2713,7 +2724,13 @@ athn_clock_rate(struct athn_softc *sc)
 	struct ieee80211com *ic = &sc->sc_ic;
 	int clockrate;	/* MHz. */
 
-	if (ic->ic_bss->ni_chan != IEEE80211_CHAN_ANYC &&
+	/*
+	 * AR9287 v1.3+ MAC runs at 117MHz (instead of 88/44MHz) when
+	 * ASYNC FIFO is enabled.
+	 */
+	if (AR_SREV_9287_13_OR_LATER(sc) && !AR_SREV_9380_10_OR_LATER(sc))
+		clockrate = 117;
+	else if (ic->ic_bss->ni_chan != IEEE80211_CHAN_ANYC &&
 	    IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan)) {
 		if (sc->flags & ATHN_FLAG_FAST_PLL_CLOCK)
 			clockrate = AR_CLOCK_RATE_FAST_5GHZ_OFDM;
@@ -2729,7 +2746,70 @@ athn_clock_rate(struct athn_softc *sc)
 	return (clockrate);
 }
 
+int
+athn_chan_sifs(struct ieee80211_channel *c)
+{
+	return IEEE80211_IS_CHAN_2GHZ(c) ? IEEE80211_DUR_DS_SIFS : 16;
+}
+
 void
+athn_setsifs(struct athn_softc *sc)
+{
+	int sifs = athn_chan_sifs(sc->sc_ic.ic_bss->ni_chan);
+	AR_WRITE(sc, AR_D_GBL_IFS_SIFS, (sifs - 2) * athn_clock_rate(sc));
+	AR_WRITE_BARRIER(sc);
+}
+
+int
+athn_acktimeout(struct ieee80211_channel *c, int slot)
+{
+	int sifs = athn_chan_sifs(c);
+	int ackto = sifs + slot;
+
+	/* Workaround for early ACK timeouts. */
+	if (IEEE80211_IS_CHAN_2GHZ(c))
+		ackto += 64 - sifs - slot;
+
+	return ackto;
+}
+
+void
+athn_setacktimeout(struct athn_softc *sc, struct ieee80211_channel *c, int slot)
+{
+	int ackto = athn_acktimeout(c, slot);
+	uint32_t reg = AR_READ(sc, AR_TIME_OUT);
+	reg = RW(reg, AR_TIME_OUT_ACK, ackto * athn_clock_rate(sc));
+	AR_WRITE(sc, AR_TIME_OUT, reg);
+	AR_WRITE_BARRIER(sc);
+}
+
+void
+athn_setctstimeout(struct athn_softc *sc, struct ieee80211_channel *c, int slot)
+{
+	int ctsto = athn_acktimeout(c, slot);
+	int sifs = athn_chan_sifs(c);
+	uint32_t reg = AR_READ(sc, AR_TIME_OUT);
+
+	/* Workaround for early CTS timeouts. */
+	if (IEEE80211_IS_CHAN_2GHZ(c))
+		ctsto += 48 - sifs - slot;
+
+	reg = RW(reg, AR_TIME_OUT_CTS, ctsto * athn_clock_rate(sc));
+	AR_WRITE(sc, AR_TIME_OUT, reg);
+	AR_WRITE_BARRIER(sc);
+}
+
+void
+athn_setclockrate(struct athn_softc *sc)
+{
+	int clockrate = athn_clock_rate(sc);
+	uint32_t reg = AR_READ(sc, AR_USEC);
+	reg = RW(reg, AR_USEC_USEC, clockrate - 1);
+	AR_WRITE(sc, AR_USEC, reg);
+	AR_WRITE_BARRIER(sc);
+}
+
+void
 athn_updateslot(struct ieee80211com *ic)
 {
 	struct athn_softc *sc = ic->ic_softc;
@@ -2739,6 +2819,9 @@ athn_updateslot(struct ieee80211com *ic)
 	    IEEE80211_DUR_DS_SHSLOT : IEEE80211_DUR_DS_SLOT;
 	AR_WRITE(sc, AR_D_GBL_IFS_SLOT, slot * athn_clock_rate(sc));
 	AR_WRITE_BARRIER(sc);
+
+	athn_setacktimeout(sc, ic->ic_bss->ni_chan, slot);
+	athn_setctstimeout(sc, ic->ic_bss->ni_chan, slot);
 }
 
 void

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic