PERFORCE change 133171 for review
Sepherosa Ziehau
sephe at FreeBSD.org
Sat Jan 12 23:49:36 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=133171
Change 133171 by sephe at sephe_zealot:sam_wifi on 2008/01/13 07:48:46
Brief:
- Make LED work
- Correct channel TX power
- Set TX_BUSY after TX desc is fully setup
- Rework TX/TX_DMA interrupt processing (*)
- Correct value of TX desc flags (*)
- TXRX_CSR5 stores ack rates instead of basic rates
(*) should make 2661D parts work as expected
Obtained-from: DragonFly
Affected files ...
.. //depot/projects/wifi/sys/dev/ral/rt2661.c#19 edit
.. //depot/projects/wifi/sys/dev/ral/rt2661reg.h#4 edit
.. //depot/projects/wifi/sys/dev/ral/rt2661var.h#7 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_proto.c#64 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_proto.h#42 edit
Differences ...
==== //depot/projects/wifi/sys/dev/ral/rt2661.c#19 (text) ====
@@ -38,6 +38,7 @@
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/endian.h>
+#include <sys/queue.h>
#include <machine/bus.h>
#include <machine/resource.h>
@@ -69,13 +70,15 @@
#ifdef RAL_DEBUG
#define DPRINTF(x) do { if (ral_debug > 0) printf x; } while (0)
#define DPRINTFN(n, x) do { if (ral_debug >= (n)) printf x; } while (0)
-int ral_debug = 0;
+int ral_debug = 1;
SYSCTL_INT(_debug, OID_AUTO, ral, CTLFLAG_RW, &ral_debug, 0, "ral debug level");
#else
#define DPRINTF(x)
#define DPRINTFN(n, x)
#endif
+MALLOC_DEFINE(M_RT2661, "rt2661_ratectl", "rt2661 rate control data");
+
static void rt2661_dma_map_addr(void *, bus_dma_segment_t *, int,
int);
static int rt2661_alloc_tx_ring(struct rt2661_softc *,
@@ -112,7 +115,7 @@
static uint8_t rt2661_plcp_signal(int);
static 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);
+ int, const bus_dma_segment_t *, int, int, int);
static struct mbuf * rt2661_get_rts(struct rt2661_softc *,
struct ieee80211_frame *, uint16_t);
static int rt2661_tx_data(struct rt2661_softc *, struct mbuf *,
@@ -133,7 +136,7 @@
static void rt2661_select_antenna(struct rt2661_softc *);
static void rt2661_enable_mrr(struct rt2661_softc *);
static void rt2661_set_txpreamble(struct rt2661_softc *);
-static void rt2661_set_basicrates(struct rt2661_softc *,
+static void rt2661_set_ackrates(struct rt2661_softc *,
const struct ieee80211_rateset *);
static void rt2661_select_band(struct rt2661_softc *,
struct ieee80211_channel *);
@@ -147,7 +150,7 @@
static int rt2661_wme_update(struct ieee80211com *) __unused;
static void rt2661_update_slot(struct ifnet *);
static const char *rt2661_get_rf(int);
-static void rt2661_read_eeprom(struct rt2661_softc *);
+static void rt2661_read_config(struct rt2661_softc *);
static int rt2661_bbp_init(struct rt2661_softc *);
static void rt2661_init(void *);
static void rt2661_stop(void *);
@@ -162,6 +165,10 @@
static int rt2661_prepare_beacon(struct rt2661_softc *);
static void rt2661_enable_tsf_sync(struct rt2661_softc *);
static int rt2661_get_rssi(struct rt2661_softc *, uint8_t);
+static void rt2661_led_newstate(struct rt2661_softc *,
+ enum ieee80211_state);
+static void rt2661_read_txpower_config(struct rt2661_softc *,
+ uint8_t, int, int *);
static const struct {
uint32_t reg;
@@ -186,6 +193,25 @@
RT2661_RF5225_2
};
+#define LED_EE2MCU(bit) { \
+ .ee_bit = RT2661_EE_LED_##bit, \
+ .mcu_bit = RT2661_MCU_LED_##bit \
+}
+static const struct {
+ uint16_t ee_bit;
+ uint16_t mcu_bit;
+} led_ee2mcu[] = {
+ LED_EE2MCU(RDYG),
+ LED_EE2MCU(RDYA),
+ LED_EE2MCU(ACT),
+ LED_EE2MCU(GPIO0),
+ LED_EE2MCU(GPIO1),
+ LED_EE2MCU(GPIO2),
+ LED_EE2MCU(GPIO3),
+ LED_EE2MCU(GPIO4)
+};
+#undef LED_EE2MCU
+
int
rt2661_attach(device_t dev, int id)
{
@@ -200,6 +226,7 @@
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
+ STAILQ_INIT(&sc->tx_ratectl);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
callout_init(&sc->rssadapt_ch, CALLOUT_MPSAFE);
@@ -218,7 +245,7 @@
}
/* retrieve RF rev. no and various other things from EEPROM */
- rt2661_read_eeprom(sc);
+ rt2661_read_config(sc);
device_printf(dev, "MAC/BBP RT%X, RF %s\n", val,
rt2661_get_rf(sc->rf_rev));
@@ -293,6 +320,7 @@
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
ic->ic_state = IEEE80211_S_INIT;
+ rt2661_led_newstate(sc, IEEE80211_S_INIT);
/* set device capabilities */
ic->ic_caps =
@@ -443,7 +471,7 @@
ring->count = count;
ring->queued = 0;
- ring->cur = ring->next = ring->stat = 0;
+ ring->cur = ring->next = 0;
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
@@ -469,7 +497,7 @@
goto fail;
}
- ring->data = malloc(count * sizeof (struct rt2661_tx_data), M_DEVBUF,
+ ring->data = malloc(count * sizeof(struct rt2661_data), M_DEVBUF,
M_NOWAIT | M_ZERO);
if (ring->data == NULL) {
device_printf(sc->sc_dev, "could not allocate soft data\n");
@@ -504,7 +532,7 @@
rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
{
struct rt2661_tx_desc *desc;
- struct rt2661_tx_data *data;
+ struct rt2661_data *data;
int i;
for (i = 0; i < ring->count; i++) {
@@ -519,24 +547,19 @@
data->m = NULL;
}
- if (data->ni != NULL) {
- ieee80211_free_node(data->ni);
- data->ni = NULL;
- }
-
desc->flags = 0;
}
bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
ring->queued = 0;
- ring->cur = ring->next = ring->stat = 0;
+ ring->cur = ring->next = 0;
}
static void
rt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
{
- struct rt2661_tx_data *data;
+ struct rt2661_data *data;
int i;
if (ring->desc != NULL) {
@@ -560,9 +583,6 @@
m_freem(data->m);
}
- if (data->ni != NULL)
- ieee80211_free_node(data->ni);
-
if (data->map != NULL)
bus_dmamap_destroy(ring->data_dmat, data->map);
}
@@ -579,7 +599,7 @@
int count)
{
struct rt2661_rx_desc *desc;
- struct rt2661_rx_data *data;
+ struct rt2661_data *data;
bus_addr_t physaddr;
int i, error;
@@ -610,7 +630,7 @@
goto fail;
}
- ring->data = malloc(count * sizeof (struct rt2661_rx_data), M_DEVBUF,
+ ring->data = malloc(count * sizeof(struct rt2661_data), M_DEVBUF,
M_NOWAIT | M_ZERO);
if (ring->data == NULL) {
device_printf(sc->sc_dev, "could not allocate soft data\n");
@@ -684,7 +704,7 @@
static void
rt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
{
- struct rt2661_rx_data *data;
+ struct rt2661_data *data;
int i;
if (ring->desc != NULL) {
@@ -786,6 +806,9 @@
ostate = ic->ic_state;
+ if (ostate != nstate)
+ rt2661_led_newstate(sc, nstate);
+
switch (nstate) {
case IEEE80211_S_INIT:
callout_stop(&sc->rssadapt_ch);
@@ -802,7 +825,7 @@
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
rt2661_enable_mrr(sc);
rt2661_set_txpreamble(sc);
- rt2661_set_basicrates(sc, &ni->ni_rates);
+ rt2661_set_ackrates(sc, &ni->ni_rates);
rt2661_set_bssid(sc, ni->ni_bssid);
}
@@ -891,90 +914,86 @@
{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
- struct rt2661_tx_ring *txq;
- struct rt2661_tx_data *data;
+ struct rt2661_tx_ratectl *rctl;
struct rt2661_node *rn;
- uint32_t val;
- int qid, retrycnt;
+ uint32_t val, result;
+ int retrycnt;
for (;;) {
- struct ieee80211_node *ni;
- struct mbuf *m;
-
val = RAL_READ(sc, RT2661_STA_CSR4);
if (!(val & RT2661_TX_STAT_VALID))
break;
- /* retrieve the queue in which this frame was sent */
- qid = RT2661_TX_QID(val);
- txq = (qid <= 3) ? &sc->txq[qid] : &sc->mgtq;
+ /* Gather statistics */
+ result = RT2661_TX_RESULT(val);
+ if (result == RT2661_TX_SUCCESS)
+ ifp->if_opackets++;
+ else
+ ifp->if_oerrors++;
+
+ /* No rate control */
+ if (RT2661_TX_QID(val) == 0)
+ continue;
/* retrieve rate control algorithm context */
- data = &txq->data[txq->stat];
- m = data->m;
- data->m = NULL;
- ni = data->ni;
- data->ni = NULL;
-
- /* if no frame has been sent, ignore */
- if (ni == NULL)
+ rctl = STAILQ_FIRST(&sc->tx_ratectl);
+ if (rctl == NULL) {
+ /*
+ * XXX
+ * This really should not happen. Maybe we should
+ * use assertion here? But why should we rely on
+ * hardware to do the correct things? Even the
+ * reference driver (RT61?) provided by Ralink does
+ * not provide enough clue that this kind of interrupt
+ * is promised to be generated for each packet. So
+ * just print a message and keep going ...
+ */
+ if_printf(ifp, "WARNING: no rate control information\n");
continue;
+ }
+ STAILQ_REMOVE_HEAD(&sc->tx_ratectl, link);
- rn = (struct rt2661_node *)ni;
+ rn = (struct rt2661_node *)rctl->ni;
- switch (RT2661_TX_RESULT(val)) {
+ switch (result) {
case RT2661_TX_SUCCESS:
retrycnt = RT2661_TX_RETRYCNT(val);
DPRINTFN(10, ("data frame sent successfully after "
"%d retries\n", retrycnt));
- if (retrycnt == 0 && data->id.id_node != NULL) {
+ if (retrycnt == 0 && rctl->id.id_node != NULL) {
ral_rssadapt_raise_rate(ic, &rn->rssadapt,
- &data->id);
+ &rctl->id);
}
- ifp->if_opackets++;
break;
case RT2661_TX_RETRY_FAIL:
DPRINTFN(9, ("sending data frame failed (too much "
"retries)\n"));
- if (data->id.id_node != NULL) {
- ral_rssadapt_lower_rate(ic, ni,
- &rn->rssadapt, &data->id);
- }
- ifp->if_oerrors++;
+ if (rctl->id.id_node != NULL) {
+ ral_rssadapt_lower_rate(ic, rctl->ni,
+ &rn->rssadapt, &rctl->id);
+ }
break;
default:
/* other failure */
device_printf(sc->sc_dev,
"sending data frame failed 0x%08x\n", val);
- ifp->if_oerrors++;
+ break;
}
- 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;
-
- if (m->m_flags & M_TXCB)
- ieee80211_process_callback(ni, m,
- RT2661_TX_RESULT(val) != RT2661_TX_SUCCESS);
- m_freem(m);
- ieee80211_free_node(ni);
+ ieee80211_free_node(rctl->ni);
+ rctl->ni = NULL;
+ free(rctl, M_RT2661);
}
-
- sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rt2661_start(ifp);
}
static void
rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
{
struct rt2661_tx_desc *desc;
- struct rt2661_tx_data *data;
+ struct rt2661_data *data;
bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_POSTREAD);
@@ -989,17 +1008,28 @@
bus_dmamap_sync(txq->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(txq->data_dmat, data->map);
+ m_freem(data->m);
+ data->m = NULL;
/* descriptor is no longer valid */
desc->flags &= ~htole32(RT2661_TX_VALID);
DPRINTFN(15, ("tx dma done q=%p idx=%u\n", txq, txq->next));
+ txq->queued--;
if (++txq->next >= txq->count) /* faster than % count */
txq->next = 0;
}
bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_PREWRITE);
+
+ if (txq->queued < txq->count) {
+ struct ifnet *ifp = sc->sc_ic.ic_ifp;
+
+ sc->sc_tx_timer = 0;
+ ifp->if_flags &= ~IFF_DRV_OACTIVE;
+ rt2661_start(ifp);
+ }
}
static void
@@ -1008,7 +1038,7 @@
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
struct rt2661_rx_desc *desc;
- struct rt2661_rx_data *data;
+ struct rt2661_data *data;
bus_addr_t physaddr;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
@@ -1020,27 +1050,27 @@
BUS_DMASYNC_POSTREAD);
for (;;) {
+ uint32_t flags;
int rssi;
desc = &sc->rxq.desc[sc->rxq.cur];
data = &sc->rxq.data[sc->rxq.cur];
+ flags = le32toh(desc->flags);
- if (le32toh(desc->flags) & RT2661_RX_BUSY)
+ if (flags & RT2661_RX_BUSY)
break;
- if ((le32toh(desc->flags) & RT2661_RX_PHY_ERROR) ||
- (le32toh(desc->flags) & RT2661_RX_CRC_ERROR)) {
+ if (flags & RT2661_RX_CRC_ERROR) {
/*
* This should not happen since we did not request
* to receive those frames when we filled TXRX_CSR0.
*/
- DPRINTFN(5, ("PHY or CRC error flags 0x%08x\n",
- le32toh(desc->flags)));
+ DPRINTFN(5, ("CRC error flags 0x%08x\n", flags));
ifp->if_ierrors++;
goto skip;
}
- if ((le32toh(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
+ if (flags & RT2661_RX_CIPHER_MASK) {
ifp->if_ierrors++;
goto skip;
}
@@ -1091,8 +1121,7 @@
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = m->m_len =
- (le32toh(desc->flags) >> 16) & 0xfff;
+ m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
rssi = rt2661_get_rssi(sc, desc->rssi);
@@ -1364,7 +1393,7 @@
static 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 ratectl)
{
struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
@@ -1372,7 +1401,7 @@
desc->flags = htole32(flags);
desc->flags |= htole32(len << 16);
- desc->flags |= htole32(RT2661_TX_BUSY | RT2661_TX_VALID);
+ desc->flags |= htole32(RT2661_TX_VALID);
desc->xflags = htole16(xflags);
desc->xflags |= htole16(nsegs << 13);
@@ -1384,11 +1413,11 @@
RT2661_LOGCWMAX(10));
/*
- * Remember in which queue this frame was sent. This field is driver
- * private data only. It will be made available by the NIC in STA_CSR4
- * on Tx interrupts.
+ * Remember whether TX rate control information should be gathered.
+ * This field is driver private data only. It will be made available
+ * by the NIC in STA_CSR4 on Tx done interrupts.
*/
- desc->qid = ac;
+ desc->qid = ratectl;
/* setup PLCP fields */
desc->plcp_signal = rt2661_plcp_signal(rate);
@@ -1420,6 +1449,8 @@
desc->addr[i] = htole32(segs[i].ds_addr);
desc->len [i] = htole16(segs[i].ds_len);
}
+
+ desc->flags |= htole32(RT2661_TX_BUSY);
}
static int
@@ -1428,7 +1459,7 @@
{
struct ieee80211com *ic = &sc->sc_ic;
struct rt2661_tx_desc *desc;
- struct rt2661_tx_data *data;
+ struct rt2661_data *data;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
bus_dma_segment_t segs[RT2661_MAX_SCATTER];
@@ -1473,7 +1504,6 @@
}
data->m = m0;
- data->ni = ni;
wh = mtod(m0, struct ieee80211_frame *);
@@ -1492,7 +1522,7 @@
}
rt2661_setup_tx_desc(sc, desc, flags, 0 /* XXX HWSEQ */,
- m0->m_pkthdr.len, rate, segs, nsegs, RT2661_QID_MGT);
+ m0->m_pkthdr.len, rate, segs, nsegs, RT2661_QID_MGT, 0);
bus_dmamap_sync(sc->mgtq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->mgtq.desc_dmat, sc->mgtq.desc_map,
@@ -1506,6 +1536,8 @@
sc->mgtq.cur = (sc->mgtq.cur + 1) % RT2661_MGT_RING_COUNT;
RAL_WRITE(sc, RT2661_TX_CNTL_CSR, RT2661_KICK_MGT);
+ ieee80211_free_node(ni);
+
return 0;
}
@@ -1547,7 +1579,8 @@
struct ieee80211com *ic = &sc->sc_ic;
struct rt2661_tx_ring *txq = &sc->txq[ac];
struct rt2661_tx_desc *desc;
- struct rt2661_tx_data *data;
+ struct rt2661_data *data;
+ struct rt2661_tx_ratectl *rctl;
struct rt2661_node *rn;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
@@ -1624,18 +1657,11 @@
return error;
}
- /* avoid multiple free() of the same node for each fragment */
- ieee80211_ref_node(ni);
-
data->m = m;
- data->ni = ni;
-
- /* RTS frames are not taken into account for rssadapt */
- data->id.id_node = NULL;
rt2661_setup_tx_desc(sc, desc, RT2661_TX_NEED_ACK |
RT2661_TX_MORE_FRAG, 0, m->m_pkthdr.len, rtsrate, segs,
- nsegs, ac);
+ nsegs, ac, 0);
bus_dmamap_sync(txq->data_dmat, data->map,
BUS_DMASYNC_PREWRITE);
@@ -1697,16 +1723,22 @@
}
data->m = m0;
- data->ni = ni;
+
+ rctl = malloc(sizeof(*rctl), M_RT2661, M_NOWAIT);
+ if (rctl != NULL) {
+ rctl->ni = ni;
- /* remember link conditions for rate adaptation algorithm */
- if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
- data->id.id_len = m0->m_pkthdr.len;
- data->id.id_rateidx = ni->ni_txrate;
- data->id.id_node = ni;
- data->id.id_rssi = ni->ni_rssi;
- } else
- data->id.id_node = NULL;
+ /* remember link conditions for rate adaptation algorithm */
+ if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
+ rctl->id.id_len = m0->m_pkthdr.len;
+ rctl->id.id_rateidx = ni->ni_txrate;
+ rctl->id.id_node = ni;
+ rctl->id.id_rssi = ni->ni_rssi;
+ } else {
+ rctl->id.id_node = NULL;
+ }
+ STAILQ_INSERT_TAIL(&sc->tx_ratectl, rctl, link);
+ }
if (!noack && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2661_TX_NEED_ACK;
@@ -1717,7 +1749,7 @@
}
rt2661_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate, segs,
- nsegs, ac);
+ nsegs, ac, rctl != NULL);
bus_dmamap_sync(txq->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_PREWRITE);
@@ -1730,6 +1762,9 @@
txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT;
RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 1 << ac);
+ if (rctl == NULL)
+ ieee80211_free_node(ni);
+
return 0;
}
@@ -2067,7 +2102,7 @@
{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
static void
-rt2661_set_basicrates(struct rt2661_softc *sc,
+rt2661_set_ackrates(struct rt2661_softc *sc,
const struct ieee80211_rateset *rs)
{
#define RV(r) ((r) & IEEE80211_RATE_VAL)
@@ -2091,9 +2126,22 @@
mask |= 1 << j;
}
+ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) &&
+ ieee80211_iserp_rateset(ic, rs)) {
+ /*
+ * Always set following rates as ACK rates to conform
+ * IEEE Std 802.11g-2003 clause 9.6
+ *
+ * 24Mbits/s 0x100
+ * 12Mbits/s 0x040
+ * 6Mbits/s 0x010
+ */
+ mask |= 0x150;
+ }
+
RAL_WRITE(sc, RT2661_TXRX_CSR5, mask);
- DPRINTF(("Setting basic rate mask to 0x%x\n", mask));
+ DPRINTF(("Setting ack rate mask to 0x%x\n", mask));
#undef RV
}
@@ -2333,11 +2381,11 @@
}
static void
-rt2661_read_eeprom(struct rt2661_softc *sc)
+rt2661_read_config(struct rt2661_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
- int i;
+ int i, start_chan;
/* read MAC address */
val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC01);
@@ -2402,16 +2450,18 @@
DPRINTF(("RF prog=%d\nRF freq=%d\n", sc->rfprog, sc->rffreq));
- /* read Tx power for all a/b/g channels */
- for (i = 0; i < 19; i++) {
- val = rt2661_eeprom_read(sc, RT2661_EEPROM_TXPOWER + i);
- sc->txpow[i * 2] = (int8_t)(val >> 8); /* signed */
- DPRINTF(("Channel=%d Tx power=%d\n",
- rt2661_rf5225_1[i * 2].chan, sc->txpow[i * 2]));
- sc->txpow[i * 2 + 1] = (int8_t)(val & 0xff); /* signed */
- DPRINTF(("Channel=%d Tx power=%d\n",
- rt2661_rf5225_1[i * 2 + 1].chan, sc->txpow[i * 2 + 1]));
- }
+#define NCHAN_2GHZ 14
+#define NCHAN_5GHZ 24
+ /*
+ * Read channel TX power
+ */
+ start_chan = 0;
+ rt2661_read_txpower_config(sc, RT2661_EEPROM_TXPOWER_2GHZ,
+ NCHAN_2GHZ, &start_chan);
+ rt2661_read_txpower_config(sc, RT2661_EEPROM_TXPOWER_5GHZ,
+ NCHAN_5GHZ, &start_chan);
+#undef NCHAN_2GHZ
+#undef NCHAN_5GHZ
/* read vendor-specific BBP values */
for (i = 0; i < 16; i++) {
@@ -2423,6 +2473,24 @@
DPRINTF(("BBP R%d=%02x\n", sc->bbp_prom[i].reg,
sc->bbp_prom[i].val));
}
+
+ val = rt2661_eeprom_read(sc, RT2661_EEPROM_LED_OFFSET);
+ DPRINTF(("LED %02x\n", val));
+ if (val == 0xffff) {
+ sc->mcu_led = RT2661_MCU_LED_DEFAULT;
+ } else {
+#define N(arr) (int)(sizeof(arr) / sizeof(arr[0]))
+
+ for (i = 0; i < N(led_ee2mcu); ++i) {
+ if (val & led_ee2mcu[i].ee_bit)
+ sc->mcu_led |= led_ee2mcu[i].mcu_bit;
+ }
+
+#undef N
+
+ sc->mcu_led |= ((val >> RT2661_EE_LED_MODE_SHIFT) &
+ RT2661_EE_LED_MODE_MASK);
+ }
}
static int
@@ -2610,6 +2678,7 @@
{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
+ struct rt2661_tx_ratectl *rctl;
uint32_t tmp;
volatile int *flags = &sc->sc_flags;
@@ -2641,7 +2710,14 @@
/* clear any pending interrupt */
RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, 0xffffffff);
-
+
+ while ((rctl = STAILQ_FIRST(&sc->tx_ratectl)) != NULL) {
+ STAILQ_REMOVE_HEAD(&sc->tx_ratectl, link);
+ ieee80211_free_node(rctl->ni);
+ rctl->ni = NULL;
+ free(rctl, M_RT2661);
+ }
+
/* reset Tx and Rx rings */
rt2661_reset_tx_ring(sc, &sc->txq[0]);
rt2661_reset_tx_ring(sc, &sc->txq[1]);
@@ -2824,7 +2900,7 @@
rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->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);
@@ -2952,3 +3028,77 @@
RAL_UNLOCK(sc);
}
+
+static void
+rt2661_led_newstate(struct rt2661_softc *sc, enum ieee80211_state nstate)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint32_t off, on;
+ uint32_t mail = sc->mcu_led;
+
+ if (RAL_READ(sc, RT2661_H2M_MAILBOX_CSR) & RT2661_H2M_BUSY) {
+ DPRINTF(("%s failed\n", __func__));
+ return;
+ }
+
+ switch (nstate) {
+ case IEEE80211_S_INIT:
+ mail &= ~(RT2661_MCU_LED_LINKA | RT2661_MCU_LED_LINKG |
+ RT2661_MCU_LED_RF);
+ break;
+ default:
+ if (ic->ic_curchan == NULL)
+ return;
+
+ on = RT2661_MCU_LED_LINKG;
+ off = RT2661_MCU_LED_LINKA;
+ if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) {
+ on = RT2661_MCU_LED_LINKA;
+ off = RT2661_MCU_LED_LINKG;
+ }
+
+ mail |= RT2661_MCU_LED_RF | on;
+ mail &= ~off;
+ break;
+ }
+
+ RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR,
+ RT2661_H2M_BUSY | RT2661_TOKEN_NO_INTR << 16 | mail);
+ RAL_WRITE(sc, RT2661_HOST_CMD_CSR, RT2661_KICK_CMD | RT2661_MCU_SET_LED);
+}
+
+static void
+rt2661_read_txpower_config(struct rt2661_softc *sc, uint8_t txpwr_ofs,
+ int nchan, int *start_chan0)
+{
+ int i, loop_max;
+ int start_chan = *start_chan0;
+
+ KASSERT(nchan % 2 == 0, ("number of channels %d is not even\n", nchan));
+ KASSERT(start_chan + nchan <= RT2661_NCHAN_MAX, ("too many channels"));
+
+ loop_max = nchan / 2;
+
+ for (i = 0; i < loop_max; i++) {
+ int chan_idx, j;
+ uint16_t val;
+
+ val = rt2661_eeprom_read(sc, txpwr_ofs + i);
+ chan_idx = i * 2 + start_chan;
+
+ for (j = 0; j < 2; ++j) {
+ int8_t tx_power; /* signed */
+
+ tx_power = (int8_t)((val >> (8 * j)) & 0xff);
+ if (tx_power > RT2661_TXPOWER_MAX)
+ tx_power = RT2661_TXPOWER_DEFAULT;
+
+ sc->txpow[chan_idx] = tx_power;
+ DPRINTF(("Channel=%d Tx power=%d\n",
+ rt2661_rf5225_1[chan_idx].chan, sc->txpow[chan_idx]));
+
+ ++chan_idx;
+ }
+ }
+ *start_chan0 += nchan;
+}
==== //depot/projects/wifi/sys/dev/ral/rt2661reg.h#4 (text) ====
@@ -161,9 +161,9 @@
#define RT2661_DROP_ACKCTS (1 << 25)
/* possible flags for register TXRX_CSR4 */
-#define RT2661_SHORT_PREAMBLE (1 << 19)
-#define RT2661_MRR_ENABLED (1 << 20)
-#define RT2661_MRR_CCK_FALLBACK (1 << 23)
+#define RT2661_SHORT_PREAMBLE (1 << 18)
+#define RT2661_MRR_ENABLED (1 << 19)
+#define RT2661_MRR_CCK_FALLBACK (1 << 22)
/* possible flags for register TXRX_CSR9 */
#define RT2661_TSF_TICKING (1 << 16)
@@ -265,8 +265,7 @@
#define RT2661_RX_DROP (1 << 1)
#define RT2661_RX_CRC_ERROR (1 << 6)
#define RT2661_RX_OFDM (1 << 7)
-#define RT2661_RX_PHY_ERROR (1 << 8)
-#define RT2661_RX_CIPHER_MASK 0x00000600
+#define RT2661_RX_CIPHER_MASK 0x00000300
uint8_t rate;
uint8_t rssi;
@@ -306,13 +305,46 @@
#define RT2661_EEPROM_ANTENNA 0x10
#define RT2661_EEPROM_CONFIG2 0x11
#define RT2661_EEPROM_BBP_BASE 0x13
-#define RT2661_EEPROM_TXPOWER 0x23
+#define RT2661_EEPROM_TXPOWER_2GHZ 0x23
#define RT2661_EEPROM_FREQ_OFFSET 0x2f
+#define RT2661_EEPROM_LED_OFFSET 0x30
+#define RT2661_EEPROM_TXPOWER_5GHZ 0x31
#define RT2661_EEPROM_RSSI_2GHZ_OFFSET 0x4d
#define RT2661_EEPROM_RSSI_5GHZ_OFFSET 0x4e
+#define RT2661_EE_LED_RDYG 0x01
+#define RT2661_EE_LED_RDYA 0x02
+#define RT2661_EE_LED_ACT 0x04
+#define RT2661_EE_LED_GPIO0 0x08
+#define RT2661_EE_LED_GPIO1 0x10
+#define RT2661_EE_LED_GPIO2 0x20
+#define RT2661_EE_LED_GPIO3 0x40
+#define RT2661_EE_LED_GPIO4 0x80
+#define RT2661_EE_LED_MODE_SHIFT 8
+#define RT2661_EE_LED_MODE_MASK 0x1f
+
#define RT2661_EEPROM_DELAY 1 /* minimum hold time (microsecond) */
+#define RT2661_MCU_LED_RF (1 << 5)
+#define RT2661_MCU_LED_LINKG (1 << 6)
+#define RT2661_MCU_LED_LINKA (1 << 7)
+#define RT2661_MCU_LED_GPIO0 (1 << 8)
+#define RT2661_MCU_LED_GPIO1 (1 << 9)
+#define RT2661_MCU_LED_GPIO2 (1 << 10)
+#define RT2661_MCU_LED_GPIO3 (1 << 11)
+#define RT2661_MCU_LED_GPIO4 (1 << 12)
+#define RT2661_MCU_LED_ACT (1 << 13)
+#define RT2661_MCU_LED_RDYG (1 << 14)
+#define RT2661_MCU_LED_RDYA (1 << 15)
+
+#define RT2661_MCU_LED_DEFAULT \
+ (RT2661_MCU_LED_GPIO0 | RT2661_MCU_LED_GPIO1 | RT2661_MCU_LED_GPIO2 | \
+ RT2661_MCU_LED_GPIO3 | RT2661_MCU_LED_GPIO4 | RT2661_MCU_LED_ACT | \
+ RT2661_MCU_LED_RDYG | RT2661_MCU_LED_RDYA)
+
+#define RT2661_TXPOWER_DEFAULT 5
+#define RT2661_TXPOWER_MAX 36
+
/*
* control and status registers access macros
*/
==== //depot/projects/wifi/sys/dev/ral/rt2661var.h#7 (text) ====
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#define RT2661_NCHAN_MAX 38
+
struct rt2661_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsf;
@@ -47,39 +49,37 @@
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL))
-struct rt2661_tx_data {
- bus_dmamap_t map;
- struct mbuf *m;
+struct rt2661_tx_ratectl {
struct ieee80211_node *ni;
struct ral_rssdesc id;
+ STAILQ_ENTRY(rt2661_tx_ratectl) link;
};
+struct rt2661_data {
+ bus_dmamap_t map;
+ struct mbuf *m;
+};
+
struct rt2661_tx_ring {
bus_dma_tag_t desc_dmat;
bus_dma_tag_t data_dmat;
bus_dmamap_t desc_map;
bus_addr_t physaddr;
struct rt2661_tx_desc *desc;
- struct rt2661_tx_data *data;
+ struct rt2661_data *data;
int count;
int queued;
int cur;
int next;
- int stat;
};
-struct rt2661_rx_data {
- bus_dmamap_t map;
- struct mbuf *m;
-};
-
struct rt2661_rx_ring {
bus_dma_tag_t desc_dmat;
bus_dma_tag_t data_dmat;
bus_dmamap_t desc_map;
bus_addr_t physaddr;
struct rt2661_rx_desc *desc;
- struct rt2661_rx_data *data;
+ struct rt2661_data *data;
int count;
int cur;
int next;
@@ -123,7 +123,7 @@
struct rt2661_rx_ring rxq;
uint32_t rf_regs[4];
- int8_t txpow[38];
+ int8_t txpow[RT2661_NCHAN_MAX];
struct {
uint8_t reg;
@@ -145,6 +145,9 @@
uint8_t bbp16;
uint8_t bbp17;
uint8_t bbp64;
+ uint16_t mcu_led;
+
+ STAILQ_HEAD(, rt2661_tx_ratectl) tx_ratectl;
int dwelltime;
==== //depot/projects/wifi/sys/net80211/ieee80211_proto.c#64 (text+ko) ====
@@ -491,7 +491,8 @@
* NB: the rate set is assumed to be sorted.
*/
int
-ieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs)
+ieee80211_iserp_rateset(struct ieee80211com *ic,
+ const struct ieee80211_rateset *rs)
{
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list