From owner-p4-projects@FreeBSD.ORG Sun Jan 13 07:49:36 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6596E16A498; Sun, 13 Jan 2008 07:49:36 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 28E5E16A480 for ; Sun, 13 Jan 2008 07:49:36 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 4066513C44B for ; Sun, 13 Jan 2008 07:49:36 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m0D7naql010711 for ; Sun, 13 Jan 2008 07:49:36 GMT (envelope-from sephe@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m0D7nZF4010707 for perforce@freebsd.org; Sun, 13 Jan 2008 07:49:35 GMT (envelope-from sephe@FreeBSD.org) Date: Sun, 13 Jan 2008 07:49:35 GMT Message-Id: <200801130749.m0D7nZF4010707@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau To: Perforce Change Reviews Cc: Subject: PERFORCE change 133171 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 13 Jan 2008 07:49:36 -0000 http://perforce.freebsd.org/chv.cgi?CH=133171 Change 133171 by sephe@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 #include #include +#include #include #include @@ -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) <<<