Convert the TX path to use the new HAL methods for accessing the
TX descriptor link pointers. This is required for the AR93xx and later chipsets. The RX path is slightly different - the legacy RX path directly accesses ath_desc->ds_link for now, however this isn't at all done for EDMA (FIFO) RX. Now, for those performing a little software archeology here: This is all a bit sub-optimal. "struct ath_desc" is only really relevant for the pre-AR93xx NICs - where ds_link and ds_data is always in the same location. The AR93xx and later NICs have different descriptor layouts altogether. Now, for AR93xx and later NICs, you should never directly reference ds_link and ds_data, as: * the RX descriptors don't have either - the data is _after_ the RX descriptor. They're just one large buffer. There's also no need for a per-descriptor RX buffer size as they're all fixed sizes. * the TX descriptors have 4 buffer and 4 length fields _and_ a link pointer. Each frame takes up one TX FIFO pointer, but it can contain multiple subframes (either multiple frames in a buffer, and/or multiple frames in an aggregate/RIFS burst.) * .. so, when TX frames are queued to a hardware queue, the link pointer is ONLY for buffers in that frame/aggregate. The next frame starts in a new FIFO pointer. * Finally, descriptor completion status is in a different ring. I'll write something up about that when its time to do so. This was inspired by Linux ath9k and the reference driver but is a reimplementation. Obtained from: Linux ath9k, Qualcomm Atheros
This commit is contained in:
parent
158ed614ca
commit
0dca43b8b6
@ -277,14 +277,15 @@ ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf)
|
||||
|
||||
flags = HAL_TXDESC_NOACK;
|
||||
if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) {
|
||||
ds->ds_link = bf->bf_daddr; /* self-linked */
|
||||
/* self-linked descriptor */
|
||||
ath_hal_settxdesclink(sc->sc_ah, ds, bf->bf_daddr);
|
||||
flags |= HAL_TXDESC_VEOL;
|
||||
/*
|
||||
* Let hardware handle antenna switching.
|
||||
*/
|
||||
antenna = sc->sc_txantenna;
|
||||
} else {
|
||||
ds->ds_link = 0;
|
||||
ath_hal_settxdesclink(sc->sc_ah, ds, 0);
|
||||
/*
|
||||
* Switch antenna every 4 beacons.
|
||||
* XXX assumes two antenna
|
||||
@ -405,8 +406,10 @@ ath_beacon_proc(void *arg, int pending)
|
||||
if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) {
|
||||
bf = ath_beacon_generate(sc, vap);
|
||||
if (bf != NULL) {
|
||||
/* XXX should do this using the ds */
|
||||
*bflink = bf->bf_daddr;
|
||||
bflink = &bf->bf_desc->ds_link;
|
||||
ath_hal_gettxdesclinkptr(sc->sc_ah,
|
||||
bf->bf_desc, &bflink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -310,9 +310,10 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
|
||||
for (i = 0; i < bf->bf_nseg; i++, ds++) {
|
||||
ds->ds_data = bf->bf_segs[i].ds_addr;
|
||||
if (i == bf->bf_nseg - 1)
|
||||
ds->ds_link = 0;
|
||||
ath_hal_settxdesclink(ah, ds, 0);
|
||||
else
|
||||
ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1);
|
||||
ath_hal_settxdesclink(ah, ds,
|
||||
bf->bf_daddr + sizeof(*ds) * (i + 1));
|
||||
ath_hal_filltxdesc(ah, ds
|
||||
, bf->bf_segs[i].ds_len /* segment length */
|
||||
, i == 0 /* first segment */
|
||||
@ -350,9 +351,10 @@ ath_tx_chaindesclist_subframe(struct ath_softc *sc, struct ath_buf *bf)
|
||||
for (i = 0; i < bf->bf_nseg; i++, ds++) {
|
||||
ds->ds_data = bf->bf_segs[i].ds_addr;
|
||||
if (i == bf->bf_nseg - 1)
|
||||
ds->ds_link = 0;
|
||||
ath_hal_settxdesclink(ah, ds, 0);
|
||||
else
|
||||
ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1);
|
||||
ath_hal_settxdesclink(ah, ds,
|
||||
bf->bf_daddr + sizeof(*ds) * (i + 1));
|
||||
|
||||
/*
|
||||
* This performs the setup for an aggregate frame.
|
||||
@ -414,7 +416,8 @@ ath_tx_setds_11n(struct ath_softc *sc, struct ath_buf *bf_first)
|
||||
* to the beginning descriptor of this frame.
|
||||
*/
|
||||
if (bf_prev != NULL)
|
||||
bf_prev->bf_lastds->ds_link = bf->bf_daddr;
|
||||
ath_hal_settxdesclink(sc->sc_ah, bf_prev->bf_lastds,
|
||||
bf->bf_daddr);
|
||||
|
||||
/* Save a copy so we can link the next descriptor in */
|
||||
bf_prev = bf;
|
||||
@ -482,7 +485,7 @@ ath_tx_handoff_mcast(struct ath_softc *sc, struct ath_txq *txq,
|
||||
*txq->axq_link = bf->bf_daddr;
|
||||
}
|
||||
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
|
||||
txq->axq_link = &bf->bf_lastds->ds_link;
|
||||
ath_hal_gettxdesclinkptr(sc->sc_ah, bf->bf_lastds, &txq->axq_link);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -616,7 +619,7 @@ ath_tx_handoff_hw(struct ath_softc *sc, struct ath_txq *txq,
|
||||
#endif /* IEEE80211_SUPPORT_TDMA */
|
||||
if (bf->bf_state.bfs_aggr)
|
||||
txq->axq_aggr_depth++;
|
||||
txq->axq_link = &bf->bf_lastds->ds_link;
|
||||
ath_hal_gettxdesclinkptr(ah, bf->bf_lastds, &txq->axq_link);
|
||||
ath_hal_txstart(ah, txq->axq_qnum);
|
||||
}
|
||||
}
|
||||
@ -645,7 +648,7 @@ ath_txq_restart_dma(struct ath_softc *sc, struct ath_txq *txq)
|
||||
return;
|
||||
|
||||
ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
|
||||
txq->axq_link = &bf_last->bf_lastds->ds_link;
|
||||
ath_hal_gettxdesclinkptr(ah, bf->bf_lastds, &txq->axq_link);
|
||||
ath_hal_txstart(ah, txq->axq_qnum);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user