Here is the combined diff from these sources:
http://www.mail-archive.com/[email protected]/msg01261.html
http://www.mail-archive.com/[email protected]/msg83528.html
Applied against most recent -current checkout:
--- rt2661.c.orig Mon Jan 18 11:51:03 2010
+++ rt2661.c Mon Jan 18 12:11:55 2010
@@ -97,9 +97,8 @@ void rt2661_newassoc(struct ieee80211com *, struct ie
int rt2661_newstate(struct ieee80211com *, enum ieee80211_state,
int);
uint16_t rt2661_eeprom_read(struct rt2661_softc *, uint8_t);
+void rt2661_free_tx_desc(struct rt2661_softc *, struct
rt2661_tx_ring *);
void rt2661_tx_intr(struct rt2661_softc *);
-void rt2661_tx_dma_intr(struct rt2661_softc *,
- struct rt2661_tx_ring *);
void rt2661_rx_intr(struct rt2661_softc *);
#ifndef IEEE80211_STA_ONLY
void rt2661_mcu_beacon_expire(struct rt2661_softc *);
@@ -115,7 +114,7 @@ uint16_t rt2661_txtime(int, int, uint32_t);
uint8_t rt2661_plcp_signal(int);
void rt2661_setup_tx_desc(struct rt2661_softc *,
struct rt2661_tx_desc *, uint32_t, uint16_t, int, int,
- const bus_dma_segment_t *, int, int);
+ const bus_dma_segment_t *, int, int, int);
int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *,
struct ieee80211_node *);
int rt2661_tx_data(struct rt2661_softc *, struct mbuf *,
@@ -376,7 +375,7 @@ rt2661_alloc_tx_ring(struct rt2661_softc *sc, struct r
ring->count = count;
ring->queued = 0;
- ring->cur = ring->next = ring->stat = 0;
+ ring->cur = ring->stat = 0;
error = bus_dmamap_create(sc->sc_dmat, count * RT2661_TX_DESC_SIZE, 1,
count * RT2661_TX_DESC_SIZE, 0, BUS_DMA_NOWAIT, &ring->map);
@@ -470,7 +469,7 @@ rt2661_reset_tx_ring(struct rt2661_softc *sc, struct r
BUS_DMASYNC_PREWRITE);
ring->queued = 0;
- ring->cur = ring->next = ring->stat = 0;
+ ring->cur = ring->stat = 0;
}
void
@@ -881,6 +880,36 @@ rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t ad
}
void
+rt2661_free_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
+{
+ struct rt2661_tx_desc *desc = &txq->desc[txq->stat];
+ struct rt2661_tx_data *data = &txq->data[txq->stat];
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ bus_dmamap_sync(sc->sc_dmat, data->map, 0,
+ data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, data->map);
+ m_freem(data->m);
+ data->m = NULL;
+
+ /* descriptor is no longer valid */
+ desc->flags &= ~htole32(RT2661_TX_VALID);
+
+ bus_dmamap_sync(sc->sc_dmat, txq->map,
+ txq->stat * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
+ BUS_DMASYNC_PREWRITE);
+
+ if (data->ni) {
+ ieee80211_release_node(ic, data->ni);
+ data->ni = NULL;
+ }
+
+ txq->queued--;
+ if (++txq->stat >= txq->count) /* faster than % count */
+ txq->stat = 0;
+}
+
+void
rt2661_tx_intr(struct rt2661_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -888,7 +917,7 @@ rt2661_tx_intr(struct rt2661_softc *sc)
struct rt2661_tx_ring *txq;
struct rt2661_tx_data *data;
struct rt2661_node *rn;
- int qid, retrycnt;
+ int qid, ind, retrycnt;
for (;;) {
const uint32_t val = RAL_READ(sc, RT2661_STA_CSR4);
@@ -898,7 +927,14 @@ rt2661_tx_intr(struct rt2661_softc *sc)
/* retrieve the queue in which this frame was sent */
qid = RT2661_TX_QID(val);
txq = (qid <= 3) ? &sc->txq[qid] : &sc->mgtq;
+ ind = RT2661_TX_INDEX(val);
+ if (txq->stat != ind)
+ DPRINTFN(10, ("missed TX interrupt, catching up "
+ "stat %d to index %d\n", txq->stat, ind, qid));
+ while (txq->stat != ind)
+ rt2661_free_tx_desc(sc, txq);
+
/* retrieve rate control algorithm context */
data = &txq->data[txq->stat];
rn = (struct rt2661_node *)data->ni;
@@ -934,14 +970,7 @@ rt2661_tx_intr(struct rt2661_softc *sc)
ifp->if_oerrors++;
}
- ieee80211_release_node(ic, data->ni);
- data->ni = NULL;
-
- DPRINTFN(15, ("tx done q=%d idx=%u\n", qid, txq->stat));
-
- txq->queued--;
- if (++txq->stat >= txq->count) /* faster than % count */
- txq->stat = 0;
+ rt2661_free_tx_desc(sc, txq);
}
sc->sc_tx_timer = 0;
@@ -950,42 +979,6 @@ rt2661_tx_intr(struct rt2661_softc *sc)
}
void
-rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
-{
- for (;;) {
- struct rt2661_tx_desc *desc = &txq->desc[txq->next];
- struct rt2661_tx_data *data = &txq->data[txq->next];
-
- bus_dmamap_sync(sc->sc_dmat, txq->map,
- txq->next * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
- BUS_DMASYNC_POSTREAD);
-
- if ((letoh32(desc->flags) & RT2661_TX_BUSY) ||
- !(letoh32(desc->flags) & RT2661_TX_VALID))
- break;
-
- bus_dmamap_sync(sc->sc_dmat, data->map, 0,
- data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->sc_dmat, data->map);
- m_freem(data->m);
- data->m = NULL;
- /* node reference is released in rt2661_tx_intr() */
-
- /* descriptor is no longer valid */
- desc->flags &= ~htole32(RT2661_TX_VALID);
-
- bus_dmamap_sync(sc->sc_dmat, txq->map,
- txq->next * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
- BUS_DMASYNC_PREWRITE);
-
- DPRINTFN(15, ("tx dma done q=%p idx=%u\n", txq, txq->next));
-
- if (++txq->next >= txq->count) /* faster than % count */
- txq->next = 0;
- }
-}
-
-void
rt2661_rx_intr(struct rt2661_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -1212,24 +1205,9 @@ rt2661_intr(void *arg)
if (!(ifp->if_flags & IFF_RUNNING))
return 0;
- if (r1 & RT2661_MGT_DONE)
- rt2661_tx_dma_intr(sc, &sc->mgtq);
-
if (r1 & RT2661_RX_DONE)
rt2661_rx_intr(sc);
- if (r1 & RT2661_TX0_DMA_DONE)
- rt2661_tx_dma_intr(sc, &sc->txq[0]);
-
- if (r1 & RT2661_TX1_DMA_DONE)
- rt2661_tx_dma_intr(sc, &sc->txq[1]);
-
- if (r1 & RT2661_TX2_DMA_DONE)
- rt2661_tx_dma_intr(sc, &sc->txq[2]);
-
- if (r1 & RT2661_TX3_DMA_DONE)
- rt2661_tx_dma_intr(sc, &sc->txq[3]);
-
if (r1 & RT2661_TX_DONE)
rt2661_tx_intr(sc);
@@ -1377,7 +1355,7 @@ rt2661_plcp_signal(int rate)
void
rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
uint32_t flags, uint16_t xflags, int len, int rate,
- const bus_dma_segment_t *segs, int nsegs, int ac)
+ const bus_dma_segment_t *segs, int nsegs, int ac, int ind)
{
struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
@@ -1385,7 +1363,6 @@ rt2661_setup_tx_desc(struct rt2661_softc *sc, struct r
desc->flags = htole32(flags);
desc->flags |= htole32(len << 16);
- desc->flags |= htole32(RT2661_TX_BUSY | RT2661_TX_VALID);
desc->xflags = htole16(xflags);
desc->xflags |= htole16(nsegs << 13);
@@ -1401,7 +1378,7 @@ rt2661_setup_tx_desc(struct rt2661_softc *sc, struct r
* private data only. It will be made available by the NIC in STA_CSR4
* on Tx interrupts.
*/
- desc->qid = ac;
+ desc->qid = (ac <= 3 ? ac : 7) | (ind << 3);
/* setup PLCP fields */
desc->plcp_signal = rt2661_plcp_signal(rate);
@@ -1433,6 +1410,8 @@ rt2661_setup_tx_desc(struct rt2661_softc *sc, struct r
desc->addr[i] = htole32(segs[i].ds_addr);
desc->len [i] = htole16(segs[i].ds_len);
}
+
+ desc->flags |= htole32(RT2661_TX_BUSY | RT2661_TX_VALID);
}
int
@@ -1505,7 +1484,7 @@ rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0
rt2661_setup_tx_desc(sc, desc, flags, 0 /* XXX HWSEQ */,
m0->m_pkthdr.len, rate, data->map->dm_segs, data->map->dm_nsegs,
- RT2661_QID_MGT);
+ RT2661_QID_MGT, sc->mgtq.cur);
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -1633,7 +1612,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m
rt2661_setup_tx_desc(sc, desc,
(needrts ? RT2661_TX_NEED_ACK : 0) | RT2661_TX_MORE_FRAG,
0, mprot->m_pkthdr.len, protrate, data->map->dm_segs,
- data->map->dm_nsegs, ac);
+ data->map->dm_nsegs, ac, txq->cur);
bus_dmamap_sync(sc->sc_dmat, data->map, 0,
data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
@@ -1723,7 +1702,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m
}
rt2661_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate,
- data->map->dm_segs, data->map->dm_nsegs, ac);
+ data->map->dm_segs, data->map->dm_nsegs, ac, txq->cur);
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -2797,7 +2776,7 @@ rt2661_prepare_beacon(struct rt2661_softc *sc)
rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
rt2661_setup_tx_desc(sc, &desc, RT2661_TX_TIMESTAMP, RT2661_TX_HWSEQ,
- m0->m_pkthdr.len, rate, NULL, 0, RT2661_QID_MGT);
+ m0->m_pkthdr.len, rate, NULL, 0, RT2661_QID_MGT, 0);
/* copy the first 24 bytes of Tx descriptor into NIC memory */
RAL_WRITE_REGION_1(sc, RT2661_HW_BEACON_BASE0, (uint8_t *)&desc, 24);
--- rt2661reg.h.orig Mon Jan 18 12:08:57 2010
+++ rt2661reg.h Mon Jan 18 12:09:46 2010
@@ -189,7 +189,8 @@
#define RT2661_TX_STAT_VALID (1 << 0)
#define RT2661_TX_RESULT(v) (((v) >> 1) & 0x7)
#define RT2661_TX_RETRYCNT(v) (((v) >> 4) & 0xf)
-#define RT2661_TX_QID(v) (((v) >> 8) & 0xf)
+#define RT2661_TX_QID(v) (((v) >> 8) & 0x7)
+#define RT2661_TX_INDEX(v) (((v) >>11) & 0x1f)
#define RT2661_TX_SUCCESS 0
#define RT2661_TX_RETRY_FAIL 6
--- rt2661var.h.orig Mon Jan 18 12:09:54 2010
+++ rt2661var.h Mon Jan 18 12:10:12 2010
@@ -62,7 +62,6 @@ struct rt2661_tx_ring {
int count;
int queued;
int cur;
- int next;
int stat;
};