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