Merge RX timestamps changes from madwifi-dfs branch

git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@2859 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
benoit 2007-11-18 22:04:47 +00:00
parent bd6e91ee85
commit b2be90d89d
2 changed files with 105 additions and 41 deletions

View File

@ -966,6 +966,8 @@ ath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_TAG tag)
DEV_NAME(dev));
}
sc->sc_last_tsf = 0;
return 0;
bad3:
ieee80211_ifdetach(ic);
@ -1378,15 +1380,31 @@ ath_resume(struct net_device *dev)
ath_init(dev);
}
/* Extend 15-bit time stamp from rx descriptor to a full 64-bit TSF
* using the current h/w TSF. We no longer make an adjustement since
* tsf should always be bf_tsf and bf_tsf is adjusted. */
/* Extend 15-bit timestamp from RX descriptor to a full 64-bit TSF using the
* provided hardware TSF. The result is the closest value relative to hardware
* TSF.
*/
/* NB: Not all chipsets return the same precision rstamp */
static __inline u_int64_t
ath_extend_tsf(u_int64_t tsf, u_int32_t rstamp)
{
return ((tsf &~ 0x7fff) | rstamp);
#define TSTAMP_MASK 0x7fff
u_int64_t result;
result = (tsf & ~TSTAMP_MASK) | rstamp;
if (result > tsf) {
if (result - tsf > (TSTAMP_MASK/2)) {
result -= (TSTAMP_MASK+1);
}
} else {
if (tsf - result > (TSTAMP_MASK/2)) {
result += (TSTAMP_MASK+1);
}
}
return result;
}
static void
@ -1403,12 +1421,15 @@ ath_uapsd_processtriggers(struct ath_softc *sc)
struct ath_txq *uapsd_xmit_q = sc->sc_uapsdq;
struct ieee80211com *ic = &sc->sc_ic;
int ac, retval;
unsigned long last_rs_tstamp = 0;
u_int32_t last_rs_tstamp = 0;
int check_for_radar = 0;
struct ath_buf *prev_rxbufcur;
u_int8_t tid;
u_int16_t frame_seq;
u_int64_t hw_tsf;
int count = 0;
int rollover = 0;
#define PA2DESC(_sc, _pa) \
((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
@ -1482,28 +1503,23 @@ ath_uapsd_processtriggers(struct ath_softc *sc)
if (HAL_EINPROGRESS == retval)
break;
/* update the per packet TSF with hw_tsf, hw_tsf is
* updated on each RX interrupt, at the start of this
* routine. */
bf->bf_tsf = hw_tsf;
/* If we detect a rollover on rs_tstamp values, then we
* know that all packets we have seen already MUST be
* decremented by 0x8000 (1<<15) because the last packet
* in the queue is for hw_tsf and any rollover we
* encounter means prior packets were not tagged with
* correct bf_tsf because of this rollover. This
* assumes that when rollover happens, we get packets
* afterwards. But, if not, we still have TSF values
* that do not go backward in time!
*/
if (rs->rs_tstamp < last_rs_tstamp ||
(STAILQ_NEXT(bf, bf_list) == NULL &&
ath_extend_tsf(bf->bf_tsf, rs->rs_tstamp) >
hw_tsf)) {
/* Adjust TSF of this and all prior packets */
struct ath_buf *p = sc->sc_rxbufcur;
for (;p && p != bf; p = STAILQ_NEXT(p, bf_list))
p->bf_tsf -= 0x8000;
/* update the per packet TSF with rs_tstamp */
bf->bf_tsf = rs->rs_tstamp;
bf->bf_status |= ATH_BUFSTATUS_RXTSTAMP;
count ++;
DPRINTF(sc, ATH_DEBUG_BEACON,
"%s: rs_tstamp=%10llx count=%d\n",
DEV_NAME(sc->sc_dev),
bf->bf_tsf, count);
/* compute rollover */
if (last_rs_tstamp > rs->rs_tstamp) {
rollover ++;
DPRINTF(sc, ATH_DEBUG_BEACON,
"%s: %d rollover detected\n",
DEV_NAME(sc->sc_dev),
rollover);
}
last_rs_tstamp = rs->rs_tstamp;
@ -1758,6 +1774,57 @@ ath_uapsd_processtriggers(struct ath_softc *sc)
}
sc->sc_rxbufcur = bf;
/* SECOND PASS - FIX RX TIMESTAMPS */
if (count > 0) {
hw_tsf = ath_hal_gettsf64(ah);
if (last_rs_tstamp > (hw_tsf & TSTAMP_MASK)) {
rollover ++;
DPRINTF(sc, ATH_DEBUG_BEACON,
"%s: %d rollover detected for hw_tsf=%10llx\n",
DEV_NAME(sc->sc_dev),
rollover, hw_tsf);
}
last_rs_tstamp = 0;
for (bf=prev_rxbufcur; bf; bf = STAILQ_NEXT(bf, bf_list)) {
ds = bf->bf_desc;
if (ds->ds_link == bf->bf_daddr) {
/* NB: never process the self-linked entry at
* the end */
break;
}
/* we only process buffers who needs RX timestamps
* adjustements */
if (bf->bf_status & ATH_BUFSTATUS_RXTSTAMP) {
bf->bf_status &= ~ATH_BUFSTATUS_RXTSTAMP;
/* update rollover */
if (last_rs_tstamp > bf->bf_tsf) {
rollover --;
}
/* update last_rs_tstamp */
last_rs_tstamp = bf->bf_tsf;
bf->bf_tsf =(hw_tsf & ~TSTAMP_MASK)|bf->bf_tsf;
bf->bf_tsf -= rollover * (TSTAMP_MASK+1);
DPRINTF(sc, ATH_DEBUG_BEACON,
"%s: bf_tsf=%10llx hw_tsf=%10llx\n",
DEV_NAME(sc->sc_dev),
bf->bf_tsf, hw_tsf);
if (bf->bf_tsf < sc->sc_last_tsf) {
printk("TSF error: bf_tsf=%10llx sc_last_tsf=%10llx\n",
bf->bf_tsf,
sc->sc_last_tsf);
}
sc->sc_last_tsf = bf->bf_tsf;
}
}
}
ATH_RXBUF_UNLOCK_IRQ(sc);
#undef PA2DESC
}
@ -5592,8 +5659,9 @@ ath_tx_capture(struct net_device *dev, const struct ath_buf *bf, struct sk_buff
}
/*
* Intercept management frames to collect beacon rssi data
* and to do ibss merges.
* Intercept management frames to collect beacon rssi data and to do
* ibss merges. This function is called for all management frames,
* including those belonging to other BSS.
*/
static void
ath_recv_mgmt(struct ieee80211_node *ni, struct sk_buff *skb,
@ -5680,8 +5748,6 @@ ath_rx_tasklet(TQUEUE_ARG data)
unsigned int len;
int type;
u_int phyerr;
u_int64_t rs_tsf;
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s\n", __func__);
do {
@ -5816,12 +5882,7 @@ rx_accept:
skb_put(skb, len);
skb->protocol = __constant_htons(ETH_P_CONTROL);
/* Pass up TSF clock in MAC time
* Rx descriptor has the low 15 bits of the TSf at
* the time the frame was received. Use the current
* TSF to extend this to 64 bits. */
rs_tsf = ath_extend_tsf(bf->bf_tsf, rs->rs_tstamp);
/* Pass up TSF clock in MAC time */
if (sc->sc_nmonvaps > 0) {
/*
* Some vap is in monitor mode, so send to
@ -5837,7 +5898,7 @@ rx_accept:
goto rx_next;
}
#endif
ath_rx_capture(dev, bf, skb, rs_tsf);
ath_rx_capture(dev, bf, skb, bf->bf_tsf);
if (sc->sc_ic.ic_opmode == IEEE80211_M_MONITOR) {
/* no other VAPs need the packet */
dev_kfree_skb(skb);
@ -5893,7 +5954,7 @@ rx_accept:
* grab a reference for processing the frame. */
ni = ieee80211_ref_node(ni);
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
type = ieee80211_input(ni, skb, rs->rs_rssi, rs_tsf);
type = ieee80211_input(ni, skb, rs->rs_rssi, bf->bf_tsf);
ieee80211_unref_node(&ni);
} else {
/*
@ -5907,7 +5968,7 @@ rx_accept:
ieee80211_keyix_t keyix;
ATH_RSSI_LPF(an->an_avgrssi, rs->rs_rssi);
type = ieee80211_input(ni, skb, rs->rs_rssi, rs_tsf);
type = ieee80211_input(ni, skb, rs->rs_rssi, bf->bf_tsf);
/*
* If the station has a key cache slot assigned
* update the key->node mapping table.
@ -5919,7 +5980,7 @@ rx_accept:
an = NULL;
ieee80211_unref_node(&ni);
} else
type = ieee80211_input_all(ic, skb, rs->rs_rssi, rs_tsf);
type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
}
if (sc->sc_diversity) {

View File

@ -430,6 +430,8 @@ struct ath_buf {
has already been handled. We may receive
multiple interrupts before the rx_tasklet
clears the queue */
#define ATH_BUFSTATUS_RXTSTAMP 0x00000004 /* RX timestamps needs to be adjusted */
/* DMA state for tx/rx descriptors. */
struct ath_descdma {
const char *dd_name;
@ -703,6 +705,7 @@ struct ath_softc {
#endif
u_int sc_slottimeconf; /* manual override for slottime */
u_int64_t sc_tsf; /* TSF at last rx interrupt */
u_int64_t sc_last_tsf;
};
typedef void (*ath_callback) (struct ath_softc *);