summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2008-02-25 20:36:55 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2008-02-25 20:36:55 +0000
commit66f62320071ce8c6ab856dbb4c5b380f64abe78d (patch)
tree5deebc6bf0a1d0ed32ff0d649bf60ab42cb46fa1
parent45cc4d6ae703c8dd364850af3e67ef4bbbb635fc (diff)
Sync up with DragonFlyBSD driver. Please read their commit message
for details: http://leaf.dragonflybsd.org/mailarchive/commits/2008-02/msg00165.html Tested and OK brad@, kettenis@
-rw-r--r--sys/dev/ic/bwi.c146
-rw-r--r--sys/dev/ic/bwivar.h10
2 files changed, 116 insertions, 40 deletions
diff --git a/sys/dev/ic/bwi.c b/sys/dev/ic/bwi.c
index 169e2b10a01..5ffd46827bf 100644
--- a/sys/dev/ic/bwi.c
+++ b/sys/dev/ic/bwi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwi.c,v 1.72 2008/02/16 23:17:15 mglocker Exp $ */
+/* $OpenBSD: bwi.c,v 1.73 2008/02/25 20:36:54 mglocker Exp $ */
/*
* Copyright (c) 2007 The DragonFly Project. All rights reserved.
@@ -170,7 +170,8 @@ void bwi_mac_updateslot(struct bwi_mac *, int);
int bwi_mac_attach(struct bwi_softc *, int, uint8_t);
void bwi_mac_balance_atten(int *, int *);
void bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
-void bwi_mac_calibrate_txpower(struct bwi_mac *);
+void bwi_mac_calibrate_txpower(struct bwi_mac *,
+ enum bwi_txpwrcb_type);
void bwi_mac_lock(struct bwi_mac *);
void bwi_mac_unlock(struct bwi_mac *);
void bwi_mac_set_promisc(struct bwi_mac *, int);
@@ -282,7 +283,9 @@ int bwi_init(struct ifnet *);
int bwi_ioctl(struct ifnet *, u_long, caddr_t);
void bwi_start(struct ifnet *);
void bwi_watchdog(struct ifnet *);
-int bwi_stop(struct bwi_softc *);
+void bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state);
+void bwi_init_statechg(struct bwi_softc *, int);
+int bwi_stop(struct bwi_softc *, int);
int bwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
int bwi_media_change(struct ifnet *);
void bwi_iter_func(void *, struct ieee80211_node *);
@@ -580,6 +583,7 @@ int
bwi_intr(void *xsc)
{
struct bwi_softc *sc = xsc;
+ struct bwi_mac *mac;
struct ifnet *ifp = &sc->sc_ic.ic_if;
uint32_t intr_status;
uint32_t txrx_intr_status[BWI_TXRX_NRING];
@@ -602,6 +606,9 @@ bwi_intr(void *xsc)
DPRINTF(2, "%s: intr status 0x%08x\n",
sc->sc_dev.dv_xname, intr_status);
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
+ mac = (struct bwi_mac *)sc->sc_cur_regwin;
+
txrx_error = 0;
for (i = 0; i < BWI_TXRX_NRING; ++i) {
@@ -633,17 +640,21 @@ bwi_intr(void *xsc)
/* Disable all interrupts */
bwi_disable_intrs(sc, BWI_ALL_INTRS);
- if (intr_status & BWI_INTR_PHY_TXERR)
- printf("%s: intr PHY TX error\n", sc->sc_dev.dv_xname);
+ if (intr_status & BWI_INTR_PHY_TXERR) {
+ if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
+ printf("intr PHY TX error\n");
+ /* XXX to netisr0? */
+ bwi_init_statechg(sc, 0);
+ return (0);
+ }
+ }
if (txrx_error) {
/* TODO: reset device */
}
- if (intr_status & BWI_INTR_TBTT) {
- KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
- bwi_mac_config_ps((struct bwi_mac *)sc->sc_cur_regwin);
- }
+ if (intr_status & BWI_INTR_TBTT)
+ bwi_mac_config_ps(mac);
if (intr_status & BWI_INTR_EO_ATIM)
printf("%s: EO_ATIM\n", sc->sc_dev.dv_xname);
@@ -898,7 +909,7 @@ bwi_detach(void *arg)
struct ifnet *ifp = &sc->sc_ic.ic_if;
int i;
- bwi_stop(sc);
+ bwi_stop(sc, 1);
ieee80211_ifdetach(ifp);
if_detach(ifp);
@@ -2506,6 +2517,8 @@ bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
if (mac->mac_rev < 5) {
mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
DPRINTF(1, "%s: has TX stats\n", sc->sc_dev.dv_xname);
+ } else {
+ mac->mac_flags |= BWI_MAC_F_PHYE_RESET;
}
return (0);
@@ -2626,7 +2639,7 @@ bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj)
* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower
*/
void
-bwi_mac_calibrate_txpower(struct bwi_mac *mac)
+bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type)
{
struct bwi_softc *sc = mac->mac_sc;
struct bwi_rf *rf = &mac->mac_rf;
@@ -2654,14 +2667,27 @@ bwi_mac_calibrate_txpower(struct bwi_mac *mac)
if (error) {
DPRINTF(1, "%s: no DS tssi\n", sc->sc_dev.dv_xname);
- if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
- return;
+ if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) {
+ if (type == BWI_TXPWR_FORCE) {
+ rf_atten_adj = 0;
+ bbp_atten_adj = 1;
+ goto calib;
+ } else {
+ return;
+ }
+ }
error = bwi_rf_get_latest_tssi(mac, tssi,
BWI_COMM_MOBJ_TSSI_OFDM);
if (error) {
DPRINTF(1, "%s: no OFDM tssi\n", sc->sc_dev.dv_xname);
- return;
+ if (type == BWI_TXPWR_FORCE) {
+ rf_atten_adj = 0;
+ bbp_atten_adj = 1;
+ goto calib;
+ } else {
+ return;
+ }
}
for (i = 0; i < 4; ++i) {
@@ -2695,8 +2721,16 @@ bwi_mac_calibrate_txpower(struct bwi_mac *mac)
txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */
rf_atten_adj = -howmany(txpwr_diff, 8);
- bbp_atten_adj = -(txpwr_diff / 2) -
- (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
+
+ if (type == BWI_TXPWR_INIT) {
+ /*
+ * Move toward EEPROM max TX power as fast as we can
+ */
+ bbp_atten_adj = -txpwr_diff;
+ } else {
+ bbp_atten_adj = -(txpwr_diff / 2);
+ }
+ bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
if (rf_atten_adj == 0 && bbp_atten_adj == 0) {
DPRINTF(1, "%s: no need to adjust RF/BBP attenuation\n",
@@ -2705,6 +2739,7 @@ bwi_mac_calibrate_txpower(struct bwi_mac *mac)
return;
}
+calib:
DPRINTF(1, "%s: rf atten adjust %d, bbp atten adjust %d\n",
sc->sc_dev.dv_xname, rf_atten_adj, bbp_atten_adj);
bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj);
@@ -6975,16 +7010,26 @@ int
bwi_init(struct ifnet *ifp)
{
struct bwi_softc *sc = ifp->if_softc;
+
+ bwi_init_statechg(sc, 1);
+
+ return (0);
+}
+
+void
+bwi_init_statechg(struct bwi_softc *sc, int statechg)
+{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &ic->ic_if;
struct bwi_mac *mac;
int error;
DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
- error = bwi_stop(sc);
+ error = bwi_stop(sc, statechg);
if (error) {
DPRINTF(1, "%s: can't stop\n", sc->sc_dev.dv_xname);
- return (1);
+ return;
}
/* power on cardbus socket */
@@ -7046,17 +7091,21 @@ bwi_init(struct ifnet *ifp)
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- if (ic->ic_opmode != IEEE80211_M_MONITOR)
- /* start background scanning */
- ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
- else
- /* in monitor mode change directly into run state */
- ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+ if (statechg) {
+ if (ic->ic_opmode != IEEE80211_M_MONITOR) {
+ ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+ } else {
+ ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+ }
+ } else {
+ ieee80211_new_state(ic, ic->ic_state, -1);
+ }
+
back:
if (error)
- bwi_stop(sc);
-
- return (0);
+ bwi_stop(sc, 1);
+ else
+ bwi_start(ifp);
}
int
@@ -7086,7 +7135,7 @@ bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
bwi_init(ifp);
} else {
if (ifp->if_flags & IFF_RUNNING)
- bwi_stop(sc);
+ bwi_stop(sc, 1);
}
break;
case SIOCADDMULTI:
@@ -7260,8 +7309,20 @@ bwi_watchdog(struct ifnet *ifp)
ieee80211_watchdog(ifp);
}
+void
+bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate)
+{
+ timeout_del(&sc->sc_scan_ch);
+ timeout_del(&sc->sc_calib_ch);
+
+ bwi_led_newstate(sc, nstate);
+
+ if (nstate == IEEE80211_S_INIT)
+ sc->sc_txpwrcb_type = BWI_TXPWR_INIT;
+}
+
int
-bwi_stop(struct bwi_softc *sc)
+bwi_stop(struct bwi_softc *sc, int state_chg)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &ic->ic_if;
@@ -7270,7 +7331,10 @@ bwi_stop(struct bwi_softc *sc)
DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
- ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+ if (state_chg)
+ ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+ else
+ bwi_newstate_begin(sc, IEEE80211_S_INIT);
if (ifp->if_flags & IFF_RUNNING) {
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
@@ -7321,10 +7385,8 @@ bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
uint8_t chan;
timeout_del(&sc->sc_amrr_ch);
- timeout_del(&sc->sc_scan_ch);
- timeout_del(&sc->sc_calib_ch);
- bwi_led_newstate(sc, nstate);
+ bwi_newstate_begin(sc, nstate);
if (nstate == IEEE80211_S_INIT)
goto back;
@@ -7351,8 +7413,12 @@ bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
mac = (struct bwi_mac *)sc->sc_cur_regwin;
/* Initial TX power calibration */
- bwi_mac_calibrate_txpower(mac);
-
+ bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT);
+#ifdef notyet
+ sc->sc_txpwrcb_type = BWI_TXPWR_FORCE;
+#else
+ sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
+#endif
if (ic->ic_opmode == IEEE80211_M_STA) {
/* fake a join to init the tx rate */
bwi_newassoc(ic, ni, 1);
@@ -7373,7 +7439,7 @@ back:
timeout_add(&sc->sc_scan_ch, (sc->sc_dwell_time * hz) / 1000);
} else if (nstate == IEEE80211_S_RUN) {
/* XXX 15 seconds */
- timeout_add(&sc->sc_calib_ch, hz * 15);
+ timeout_add(&sc->sc_calib_ch, hz);
}
return (error);
@@ -8734,7 +8800,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
ack_rate = bwi_ack_rate(ni, rate);
dur = bwi_txtime(ic, ni,
sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN,
- ack_rate, ic->ic_flags & ~IEEE80211_F_SHPREAMBLE);
+ ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
hdr->txh_fb_duration = htole16(dur);
}
@@ -9292,8 +9358,10 @@ bwi_calibrate(void *xsc)
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
mac = (struct bwi_mac *)sc->sc_cur_regwin;
- if (ic->ic_opmode != IEEE80211_M_MONITOR)
- bwi_mac_calibrate_txpower(mac);
+ if (ic->ic_opmode != IEEE80211_M_MONITOR) {
+ bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type);
+ sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
+ }
/* XXX 15 seconds */
timeout_add(&sc->sc_calib_ch, hz * 15);
diff --git a/sys/dev/ic/bwivar.h b/sys/dev/ic/bwivar.h
index 60b3c3100bf..51cf5a92b96 100644
--- a/sys/dev/ic/bwivar.h
+++ b/sys/dev/ic/bwivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwivar.h,v 1.22 2008/02/16 16:45:28 mglocker Exp $ */
+/* $OpenBSD: bwivar.h,v 1.23 2008/02/25 20:36:54 mglocker Exp $ */
/*
* Copyright (c) 2007 The DragonFly Project. All rights reserved.
@@ -63,6 +63,12 @@
#define BWI_LED_EVENT_RX 2
#define BWI_LED_SLOWDOWN(dur) (dur) = (((dur) * 3) / 2)
+enum bwi_txpwrcb_type {
+ BWI_TXPWR_INIT = 0,
+ BWI_TXPWR_FORCE = 1,
+ BWI_TXPWR_CALIB = 2
+};
+
#define BWI_NOISE_FLOOR -95 /* TODO: noise floor calc */
#define CSR_READ_4(sc, reg) \
@@ -444,6 +450,7 @@ struct bwi_mac {
#define BWI_MAC_F_ENABLED 0x10
#define BWI_MAC_F_LOCKED 0x20 /* for debug */
#define BWI_MAC_F_TPCTL_ERROR 0x40
+#define BWI_MAC_F_PHYE_RESET 0x80
#define BWI_CREATE_MAC(mac, sc, id, rev) \
do { \
@@ -543,6 +550,7 @@ struct bwi_softc {
int sc_rx_rate;
int sc_tx_rate;
+ enum bwi_txpwrcb_type sc_txpwrcb_type;
int sc_led_blinking;
int sc_led_ticks;