summaryrefslogtreecommitdiffstats
path: root/sys/dev/ral
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2008-02-03 11:47:38 +0000
committersephe <sephe@FreeBSD.org>2008-02-03 11:47:38 +0000
commit24b66433f671444aa93c1423127ccf6e1dc020d6 (patch)
tree804c5a2eaa86b625995d85d145e8dddd488de3cc /sys/dev/ral
parent0e657b23ab26ffd1c8ec08fa31672c4397437a0b (diff)
downloadFreeBSD-src-24b66433f671444aa93c1423127ccf6e1dc020d6.zip
FreeBSD-src-24b66433f671444aa93c1423127ccf6e1dc020d6.tar.gz
Various bug fixes for 2560 parts of ral(4):
- Rename rt2560_read_eeprom to rt2560_read_config, we already have rt2560_eeprom_read - If hardware gives us wrong encryption done index, shout out loudly and terminate the processing loop - Process encryption done if RX done bit is set in interrupt status register (according to Ralink Linux driver) - Turn VALID/BUSY bits in TX descriptor only after TX descriptor is fully setup - Fix BBP read: RT2560_BBPCSR can't be written until its RT2560_BBP_BUSY bit is off (according to Ralink Linux driver) - Skip invalid (0 of 0xffff) BBP register/value entries stored in EEPROM - Fix channel TX power location in EEPROM, if channel TX power is above 31 set it to 24 (TX power only has 5bits in RF register, "24" is according to Ralink Linux driver) - Configure BBP according to the BBP register/value stored in EEPROM, restore BBP17 (RX sensitivity tuning) to default value after this. - Set TX/RX antenna after BBP is initialized; these two operation will try to set BBP registers - Reconfigure ACK TX time registers according to 802.11g standard (TX @36Mb, other side's ACK should be sent @24Mb). - 2560 parts have two TX ring: one for management/control packets, one for data packets. Add private OACTIVE flag for each of them. Turn on IFF_DRV_OACTIVE if one of private OACTIVE is on; turn off IFF_DRV_OACTIVE iff all of them are off. - Rework watchdog to mimic old if_watchdog action. Process TX done/encryption done in watchdog function (according to Ralink Linux driver) Obtained from: DragonFly Approved by: sam (mentor) Tested by: sam Related to PR: kern/117655 # Forcing long slot time setting is not included in this commit, comment and # related code is in place, so if problem pops up, quick tests could be done.
Diffstat (limited to 'sys/dev/ral')
-rw-r--r--sys/dev/ral/rt2560.c142
-rw-r--r--sys/dev/ral/rt2560reg.h4
-rw-r--r--sys/dev/ral/rt2560var.h6
3 files changed, 115 insertions, 37 deletions
diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c
index 58f4590..63f7de0 100644
--- a/sys/dev/ral/rt2560.c
+++ b/sys/dev/ral/rt2560.c
@@ -150,7 +150,7 @@ static void rt2560_set_macaddr(struct rt2560_softc *, uint8_t *);
static void rt2560_get_macaddr(struct rt2560_softc *, uint8_t *);
static void rt2560_update_promisc(struct rt2560_softc *);
static const char *rt2560_get_rf(int);
-static void rt2560_read_eeprom(struct rt2560_softc *);
+static void rt2560_read_config(struct rt2560_softc *);
static int rt2560_bbp_init(struct rt2560_softc *);
static void rt2560_set_txantenna(struct rt2560_softc *, int);
static void rt2560_set_rxantenna(struct rt2560_softc *, int);
@@ -211,7 +211,7 @@ rt2560_attach(device_t dev, int id)
rt2560_get_macaddr(sc, ic->ic_myaddr);
/* retrieve RF rev. no and various other things from EEPROM */
- rt2560_read_eeprom(sc);
+ rt2560_read_config(sc);
device_printf(dev, "MAC/BBP RT2560 (rev 0x%02x), RF %s\n",
sc->asic_rev, rt2560_get_rf(sc->rf_rev));
@@ -358,7 +358,6 @@ rt2560_detach(void *xsc)
struct ifnet *ifp = ic->ic_ifp;
rt2560_stop(sc);
- callout_stop(&sc->watchdog_ch);
callout_stop(&sc->rssadapt_ch);
bpfdetach(ifp);
@@ -891,7 +890,13 @@ rt2560_encryption_intr(struct rt2560_softc *sc)
bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
BUS_DMASYNC_POSTREAD);
- for (; sc->txq.next_encrypt != hw;) {
+ while (sc->txq.next_encrypt != hw) {
+ if (sc->txq.next_encrypt == sc->txq.cur_encrypt) {
+ printf("hw encrypt %d, cur_encrypt %d\n", hw,
+ sc->txq.cur_encrypt);
+ break;
+ }
+
desc = &sc->txq.desc[sc->txq.next_encrypt];
if ((le32toh(desc->flags) & RT2560_TX_BUSY) ||
@@ -904,7 +909,8 @@ rt2560_encryption_intr(struct rt2560_softc *sc)
desc->eiv = bswap32(desc->eiv);
/* mark the frame ready for transmission */
- desc->flags |= htole32(RT2560_TX_BUSY | RT2560_TX_VALID);
+ desc->flags |= htole32(RT2560_TX_VALID);
+ desc->flags |= htole32(RT2560_TX_BUSY);
DPRINTFN(15, ("encryption done idx=%u\n",
sc->txq.next_encrypt));
@@ -997,9 +1003,16 @@ rt2560_tx_intr(struct rt2560_softc *sc)
bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
BUS_DMASYNC_PREWRITE);
- sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rt2560_start(ifp);
+ if (sc->prioq.queued == 0 && sc->txq.queued == 0)
+ sc->sc_tx_timer = 0;
+
+ if (sc->txq.queued < RT2560_TX_RING_COUNT - 1) {
+ sc->sc_flags &= ~RT2560_F_DATA_OACTIVE;
+ if ((sc->sc_flags &
+ (RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ rt2560_start(ifp);
+ }
}
static void
@@ -1075,9 +1088,16 @@ rt2560_prio_intr(struct rt2560_softc *sc)
bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
BUS_DMASYNC_PREWRITE);
- sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rt2560_start(ifp);
+ if (sc->prioq.queued == 0 && sc->txq.queued == 0)
+ sc->sc_tx_timer = 0;
+
+ if (sc->prioq.queued < RT2560_PRIO_RING_COUNT) {
+ sc->sc_flags &= ~RT2560_F_PRIO_OACTIVE;
+ if ((sc->sc_flags &
+ (RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ rt2560_start(ifp);
+ }
}
/*
@@ -1193,7 +1213,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
}
- sc->sc_flags |= RAL_INPUT_RUNNING;
+ sc->sc_flags |= RT2560_F_INPUT_RUNNING;
RAL_UNLOCK(sc);
wh = mtod(m, struct ieee80211_frame *);
ni = ieee80211_find_rxnode(ic,
@@ -1212,7 +1232,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
ieee80211_free_node(ni);
RAL_LOCK(sc);
- sc->sc_flags &= ~RAL_INPUT_RUNNING;
+ sc->sc_flags &= ~RT2560_F_INPUT_RUNNING;
skip: desc->flags = htole32(RT2560_RX_BUSY);
DPRINTFN(15, ("decryption done idx=%u\n", sc->rxq.cur_decrypt));
@@ -1370,8 +1390,10 @@ rt2560_intr(void *arg)
if (r & RT2560_DECRYPTION_DONE)
rt2560_decryption_intr(sc);
- if (r & RT2560_RX_DONE)
+ if (r & RT2560_RX_DONE) {
rt2560_rx_intr(sc);
+ rt2560_encryption_intr(sc);
+ }
/* re-enable interrupts */
RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
@@ -1515,8 +1537,6 @@ rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
desc->flags = htole32(flags);
desc->flags |= htole32(len << 16);
- desc->flags |= encrypt ? htole32(RT2560_TX_CIPHER_BUSY) :
- htole32(RT2560_TX_BUSY | RT2560_TX_VALID);
desc->physaddr = htole32(physaddr);
desc->wme = htole16(
@@ -1548,6 +1568,11 @@ rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
desc->plcp_signal |= 0x08;
}
+
+ if (!encrypt)
+ desc->flags |= htole32(RT2560_TX_VALID);
+ desc->flags |= encrypt ? htole32(RT2560_TX_CIPHER_BUSY)
+ : htole32(RT2560_TX_BUSY);
}
static int
@@ -2002,6 +2027,7 @@ rt2560_start(struct ifnet *ifp)
if (m0 != NULL) {
if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ sc->sc_flags |= RT2560_F_PRIO_OACTIVE;
break;
}
IF_DEQUEUE(&ic->ic_mgtq, m0);
@@ -2025,6 +2051,7 @@ rt2560_start(struct ifnet *ifp)
if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) {
IFQ_DRV_PREPEND(&ifp->if_snd, m0);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ sc->sc_flags |= RT2560_F_DATA_OACTIVE;
break;
}
/*
@@ -2062,7 +2089,6 @@ rt2560_start(struct ifnet *ifp)
ieee80211_cancel_scan(ic);
ieee80211_free_node(ni);
continue;
-
}
BPF_MTAP(ifp, m0);
@@ -2085,7 +2111,6 @@ rt2560_start(struct ifnet *ifp)
sc->sc_tx_timer = 5;
ic->ic_lastdata = ticks;
- callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
}
RAL_UNLOCK(sc);
@@ -2095,16 +2120,24 @@ static void
rt2560_watchdog(void *arg)
{
struct rt2560_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
+ rt2560_encryption_intr(sc);
+ rt2560_tx_intr(sc);
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
rt2560_init(sc);
- sc->sc_ifp->if_oerrors++;
+ ifp->if_oerrors++;
+ /* watchdog timeout is set in rt2560_init() */
return;
}
- callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
}
+ callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
}
/*
@@ -2195,6 +2228,16 @@ rt2560_bbp_read(struct rt2560_softc *sc, uint8_t reg)
uint32_t val;
int ntries;
+ for (ntries = 0; ntries < 100; ntries++) {
+ if (!(RAL_READ(sc, RT2560_BBPCSR) & RT2560_BBP_BUSY))
+ break;
+ DELAY(1);
+ }
+ if (ntries == 100) {
+ device_printf(sc->sc_dev, "could not read from BBP\n");
+ return 0;
+ }
+
val = RT2560_BBP_BUSY | reg << 8;
RAL_WRITE(sc, RT2560_BBPCSR, val);
@@ -2440,7 +2483,27 @@ rt2560_update_slot(struct ifnet *ifp)
uint16_t tx_sifs, tx_pifs, tx_difs, eifs;
uint32_t tmp;
+#ifndef FORCE_SLOTTIME
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
+#else
+ /*
+ * Setting slot time according to "short slot time" capability
+ * in beacon/probe_resp seems to cause problem to acknowledge
+ * certain AP's data frames transimitted at CCK/DS rates: the
+ * problematic AP keeps retransmitting data frames, probably
+ * because MAC level acks are not received by hardware.
+ * So we cheat a little bit here by claiming we are capable of
+ * "short slot time" but setting hardware slot time to the normal
+ * slot time. ral(4) does not seem to have trouble to receive
+ * frames transmitted using short slot time even if hardware
+ * slot time is set to normal slot time. If we didn't use this
+ * trick, we would have to claim that short slot time is not
+ * supported; this would give relative poor RX performance
+ * (-1Mb~-2Mb lower) and the _whole_ BSS would stop using short
+ * slot time.
+ */
+ slottime = 20;
+#endif
/* update the MAC slot boundaries */
tx_sifs = RAL_SIFS - RT2560_TXRX_TURNAROUND;
@@ -2567,7 +2630,7 @@ rt2560_get_rf(int rev)
}
static void
-rt2560_read_eeprom(struct rt2560_softc *sc)
+rt2560_read_config(struct rt2560_softc *sc)
{
uint16_t val;
int i;
@@ -2583,6 +2646,9 @@ rt2560_read_eeprom(struct rt2560_softc *sc)
/* read default values for BBP registers */
for (i = 0; i < 16; i++) {
val = rt2560_eeprom_read(sc, RT2560_EEPROM_BBP_BASE + i);
+ if (val == 0 || val == 0xffff)
+ continue;
+
sc->bbp_prom[i].reg = val >> 8;
sc->bbp_prom[i].val = val & 0xff;
}
@@ -2590,8 +2656,12 @@ rt2560_read_eeprom(struct rt2560_softc *sc)
/* read Tx power for all b/g channels */
for (i = 0; i < 14 / 2; i++) {
val = rt2560_eeprom_read(sc, RT2560_EEPROM_TXPOWER + i);
- sc->txpow[i * 2] = val >> 8;
- sc->txpow[i * 2 + 1] = val & 0xff;
+ sc->txpow[i * 2] = val & 0xff;
+ sc->txpow[i * 2 + 1] = val >> 8;
+ }
+ for (i = 0; i < 14; ++i) {
+ if (sc->txpow[i] > 31)
+ sc->txpow[i] = 24;
}
val = rt2560_eeprom_read(sc, RT2560_EEPROM_CALIBRATE);
@@ -2648,14 +2718,14 @@ rt2560_bbp_init(struct rt2560_softc *sc)
rt2560_bbp_write(sc, rt2560_def_bbp[i].reg,
rt2560_def_bbp[i].val);
}
-#if 0
+
/* initialize BBP registers to values stored in EEPROM */
for (i = 0; i < 16; i++) {
- if (sc->bbp_prom[i].reg == 0xff)
- continue;
+ if (sc->bbp_prom[i].reg == 0 && sc->bbp_prom[i].val == 0)
+ break;
rt2560_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
}
-#endif
+ rt2560_bbp_write(sc, 17, 0x48); /* XXX restore bbp17 */
return 0;
#undef N
@@ -2752,8 +2822,6 @@ rt2560_init(void *priv)
/* set basic rate set (will be updated later) */
RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
- rt2560_set_txantenna(sc, sc->tx_ant);
- rt2560_set_rxantenna(sc, sc->rx_ant);
rt2560_update_slot(ifp);
rt2560_update_plcp(sc);
rt2560_update_led(sc, 0, 0);
@@ -2767,6 +2835,9 @@ rt2560_init(void *priv)
return;
}
+ rt2560_set_txantenna(sc, sc->tx_ant);
+ rt2560_set_rxantenna(sc, sc->rx_ant);
+
/* set default BSS channel */
rt2560_set_chan(sc, ic->ic_curchan);
@@ -2794,6 +2865,8 @@ rt2560_init(void *priv)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
+
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
@@ -2812,14 +2885,16 @@ rt2560_stop(void *arg)
struct ifnet *ifp = ic->ic_ifp;
volatile int *flags = &sc->sc_flags;
- while (*flags & RAL_INPUT_RUNNING) {
+ while (*flags & RT2560_F_INPUT_RUNNING) {
tsleep(sc, 0, "ralrunning", hz/10);
}
RAL_LOCK(sc);
+
+ callout_stop(&sc->watchdog_ch);
+
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
- sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
/* abort Tx */
@@ -2842,6 +2917,9 @@ rt2560_stop(void *arg)
rt2560_reset_tx_ring(sc, &sc->bcnq);
rt2560_reset_rx_ring(sc, &sc->rxq);
}
+ sc->sc_tx_timer = 0;
+ sc->sc_flags &= ~(RT2560_F_PRIO_OACTIVE | RT2560_F_DATA_OACTIVE);
+
RAL_UNLOCK(sc);
}
@@ -2891,7 +2969,6 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
goto bad;
}
sc->sc_tx_timer = 5;
- callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
RAL_UNLOCK(sc);
@@ -2902,4 +2979,3 @@ bad:
RAL_UNLOCK(sc);
return EIO; /* XXX */
}
-
diff --git a/sys/dev/ral/rt2560reg.h b/sys/dev/ral/rt2560reg.h
index 3871ed3..bab455d 100644
--- a/sys/dev/ral/rt2560reg.h
+++ b/sys/dev/ral/rt2560reg.h
@@ -333,8 +333,8 @@ struct rt2560_rx_desc {
{ RT2560_TXCSR1, 0x07614562 }, \
{ RT2560_ARSP_PLCP_0, 0x8c8d8b8a }, \
{ RT2560_ACKPCTCSR, 0x7038140a }, \
- { RT2560_ARTCSR1, 0x1d21252d }, \
- { RT2560_ARTCSR2, 0x1919191d }, \
+ { RT2560_ARTCSR1, 0x21212929 }, \
+ { RT2560_ARTCSR2, 0x1d1d1d1d }, \
{ RT2560_RXCSR0, 0xffffffff }, \
{ RT2560_RXCSR3, 0xb3aab3af }, \
{ RT2560_PCICSR, 0x000003b8 }, \
diff --git a/sys/dev/ral/rt2560var.h b/sys/dev/ral/rt2560var.h
index c01abb1..1f68311 100644
--- a/sys/dev/ral/rt2560var.h
+++ b/sys/dev/ral/rt2560var.h
@@ -161,8 +161,10 @@ struct rt2560_softc {
} sc_txtapu;
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
-#define RAL_INPUT_RUNNING 1
- int sc_flags;
+#define RT2560_F_INPUT_RUNNING 0x1
+#define RT2560_F_PRIO_OACTIVE 0x2
+#define RT2560_F_DATA_OACTIVE 0x4
+ int sc_flags;
};
int rt2560_attach(device_t, int);
OpenPOWER on IntegriCloud