PERFORCE change 84401 for review
Sam Leffler
sam at FreeBSD.org
Tue Sep 27 15:40:37 PDT 2005
http://perforce.freebsd.org/chv.cgi?CH=84401
Change 84401 by sam at sam_ebb on 2005/09/27 22:39:33
stuff
Affected files ...
.. //depot/projects/wifi/sys/dev/ath/if_ath.c#105 edit
.. //depot/projects/wifi/sys/dev/ath/if_athioctl.h#9 edit
.. //depot/projects/wifi/sys/dev/ath/if_athvar.h#44 edit
Differences ...
==== //depot/projects/wifi/sys/dev/ath/if_ath.c#105 (text+ko) ====
@@ -816,10 +816,25 @@
ath_bmiss_proc(void *arg, int pending)
{
struct ath_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+ u_int64_t lastrx = sc->sc_lastrx;
+ u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah);
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: tsf %llu lastrx %lld (%llu) bmiss %u\n",
+ __func__, tsf, tsf - lastrx, lastrx, ic->ic_bmisstimeout*1024);
- ieee80211_beacon_miss(&sc->sc_ic);
+ /*
+ * Workaround phantom bmiss interrupts by sanity-checking
+ * the time of our last rx'd frame. If it is within the
+ * beacon miss interval then ignore the interrupt. If it's
+ * truly a bmiss we'll get another interrupt soon and that'll
+ * be dispatched up for processing.
+ */
+ if (tsf - lastrx > ic->ic_bmisstimeout*1024)
+ ieee80211_beacon_miss(&sc->sc_ic);
+ else
+ sc->sc_stats.ast_bmiss_phantom++;
}
static u_int
@@ -893,6 +908,8 @@
* state cached in the driver.
*/
sc->sc_diversity = ath_hal_getdiversity(ah);
+ sc->sc_calinterval = 1;
+ sc->sc_caltries = 0;
/*
* Setup the hardware after reset: the key cache
@@ -1043,6 +1060,8 @@
__func__, status);
ath_update_txpow(sc); /* update tx power state */
sc->sc_diversity = ath_hal_getdiversity(ah);
+ sc->sc_calinterval = 1;
+ sc->sc_caltries = 0;
if (ath_startrecv(sc) != 0) /* restart recv */
if_printf(ifp, "%s: unable to start recv logic\n", __func__);
/*
@@ -1449,7 +1468,7 @@
STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
ATH_TXBUF_UNLOCK(sc);
if (bf == NULL) {
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: out of xmit buffers\n",
+ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: out of xmit buffers\n",
__func__);
sc->sc_stats.ast_tx_qstop++;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -1465,7 +1484,7 @@
* No data frames go out unless we're associated.
*/
if (ic->ic_state != IEEE80211_S_RUN) {
- DPRINTF(sc, ATH_DEBUG_ANY,
+ DPRINTF(sc, ATH_DEBUG_XMIT,
"%s: discard data packet, state %s\n",
__func__,
ieee80211_state_name[ic->ic_state]);
@@ -1556,7 +1575,7 @@
*/
m = ieee80211_encap(ic, m, ni);
if (m == NULL) {
- DPRINTF(sc, ATH_DEBUG_ANY,
+ DPRINTF(sc, ATH_DEBUG_XMIT,
"%s: encapsulation failure\n",
__func__);
sc->sc_stats.ast_tx_encap++;
@@ -1570,7 +1589,7 @@
*/
if ((m->m_flags & M_FRAG) &&
!ath_txfrag_setup(sc, &frags, m, ni)) {
- DPRINTF(sc, ATH_DEBUG_ANY,
+ DPRINTF(sc, ATH_DEBUG_XMIT,
"%s: out of txfrag buffers\n", __func__);
ic->ic_stats.is_tx_nobuf++; /* XXX */
goto bad;
@@ -1639,7 +1658,7 @@
* XXX check sta power-save state?
*/
if (ic->ic_state != IEEE80211_S_RUN) {
- DPRINTF(sc, ATH_DEBUG_ANY,
+ DPRINTF(sc, ATH_DEBUG_XMIT,
"%s: flush fragmented packet, state %s\n",
__func__,
ieee80211_state_name[ic->ic_state]);
@@ -3105,13 +3124,14 @@
struct mbuf *m;
struct ieee80211_node *ni;
struct ath_node *an;
- int len, type;
+ int len, type, ngood;
u_int phyerr;
HAL_STATUS status;
NET_LOCK_GIANT(); /* XXX */
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
+ ngood = 0;
do {
bf = STAILQ_FIRST(&sc->sc_rxbuf);
if (bf == NULL) { /* NB: shouldn't happen */
@@ -3126,7 +3146,7 @@
m = bf->bf_m;
if (m == NULL) { /* NB: shouldn't happen */
if_printf(ifp, "%s: no mbuf!\n", __func__);
- continue;
+ break;
}
/* XXX sync descriptor memory */
/*
@@ -3358,12 +3378,24 @@
} else if (ticks - sc->sc_ledevent >= sc->sc_ledidle)
ath_led_event(sc, ATH_LED_POLL);
}
+ /*
+ * Arrange to update the last rx timestamp only for
+ * data frames; this avoids false positives caused by
+ * hearing beacon frames from ap's on the same channel.
+ * If the only frames we receive are management frames
+ * when we take a bmiss then we can probably cope with
+ * falling back to the state machine as we're not busy.
+ */
+ if (type == IEEE80211_FC0_TYPE_DATA)
+ ngood++;
rx_next:
STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
} while (ath_rxbuf_init(sc, bf) == 0);
/* rx signal state monitoring */
ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
+ if (ngood)
+ sc->sc_lastrx = ath_hal_gettsf64(ah);
NET_UNLOCK_GIANT(); /* XXX */
#undef PA2DESC
@@ -4198,7 +4230,7 @@
/*
* Process completed xmit descriptors from the specified queue.
*/
-static void
+static int
ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_hal *ah = sc->sc_ah;
@@ -4207,13 +4239,14 @@
struct ath_desc *ds, *ds0;
struct ieee80211_node *ni;
struct ath_node *an;
- int sr, lr, pri;
+ int sr, lr, pri, nacked;
HAL_STATUS status;
DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: tx queue %u head %p link %p\n",
__func__, txq->axq_qnum,
(caddr_t)(uintptr_t) ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
txq->axq_link);
+ nacked = 0;
for (;;) {
ATH_TXQ_LOCK(txq);
txq->axq_intrcnt = 0; /* reset periodic desc intr count */
@@ -4276,8 +4309,15 @@
* Hand the descriptor to the rate control algorithm.
*/
if ((ds->ds_txstat.ts_status & HAL_TXERR_FILT) == 0 &&
- (bf->bf_flags & HAL_TXDESC_NOACK) == 0)
+ (bf->bf_flags & HAL_TXDESC_NOACK) == 0) {
+ /*
+ * If frame was ack'd update the last rx time
+ * used to workaround phantom bmiss interrupts.
+ */
+ if (ds->ds_txstat.ts_status == 0)
+ nacked++;
ath_rate_tx_complete(sc, an, ds, ds0);
+ }
/*
* Reclaim reference to node.
*
@@ -4303,6 +4343,7 @@
*/
if (txq->axq_depth <= 1)
ath_ff_stageq_flush(sc, txq, ath_ff_always);
+ return nacked;
}
static __inline int
@@ -4323,8 +4364,8 @@
struct ath_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
- if (txqactive(sc->sc_ah, 0))
- ath_tx_processq(sc, &sc->sc_txq[0]);
+ if (txqactive(sc->sc_ah, 0) && ath_tx_processq(sc, &sc->sc_txq[0]))
+ sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
ath_tx_processq(sc, sc->sc_cabq);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -4345,20 +4386,24 @@
{
struct ath_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
+ int nacked;
/*
* Process each active queue.
*/
+ nacked = 0;
if (txqactive(sc->sc_ah, 0))
- ath_tx_processq(sc, &sc->sc_txq[0]);
+ nacked += ath_tx_processq(sc, &sc->sc_txq[0]);
if (txqactive(sc->sc_ah, 1))
- ath_tx_processq(sc, &sc->sc_txq[1]);
+ nacked += ath_tx_processq(sc, &sc->sc_txq[1]);
if (txqactive(sc->sc_ah, 2))
- ath_tx_processq(sc, &sc->sc_txq[2]);
+ nacked += ath_tx_processq(sc, &sc->sc_txq[2]);
if (txqactive(sc->sc_ah, 3))
- ath_tx_processq(sc, &sc->sc_txq[3]);
+ nacked += ath_tx_processq(sc, &sc->sc_txq[3]);
if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
ath_tx_processq(sc, sc->sc_cabq);
+ if (nacked)
+ sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_timer = 0;
@@ -4377,14 +4422,17 @@
{
struct ath_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
- int i;
+ int i, nacked;
/*
* Process each active queue.
*/
+ nacked = 0;
for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
if (ATH_TXQ_SETUP(sc, i) && txqactive(sc->sc_ah, i))
- ath_tx_processq(sc, &sc->sc_txq[i]);
+ nacked += ath_tx_processq(sc, &sc->sc_txq[i]);
+ if (nacked)
+ sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_timer = 0;
@@ -4630,6 +4678,8 @@
sc->sc_curchan = hchan;
ath_update_txpow(sc); /* update tx power state */
sc->sc_diversity = ath_hal_getdiversity(ah);
+ sc->sc_calinterval = 1;
+ sc->sc_caltries = 0;
/*
* Re-enable rx framework.
@@ -4663,27 +4713,50 @@
{
struct ath_softc *sc = arg;
struct ath_hal *ah = sc->sc_ah;
+ HAL_BOOL iqCalDone;
sc->sc_stats.ast_per_cal++;
- DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: channel %u/%x\n",
- __func__, sc->sc_curchan.channel, sc->sc_curchan.channelFlags);
-
if (ath_hal_getrfgain(ah) == HAL_RFGAIN_NEED_CHANGE) {
/*
* Rfgain is out of bounds, reset the chip
* to load new gain values.
*/
sc->sc_stats.ast_per_rfgain++;
+ DPRINTF(sc, ATH_DEBUG_CALIBRATE,
+ "%s: rfgain change\n", __func__);
ath_reset(sc->sc_ifp);
}
- if (!ath_hal_calibrate(ah, &sc->sc_curchan)) {
+ if (!ath_hal_calibrate(ah, &sc->sc_curchan, &iqCalDone)) {
DPRINTF(sc, ATH_DEBUG_ANY,
"%s: calibration of channel %u failed\n",
__func__, sc->sc_curchan.channel);
sc->sc_stats.ast_per_calfail++;
}
- callout_reset(&sc->sc_cal_ch, ath_calinterval * hz, ath_calibrate, sc);
+ /*
+ * Poll more frequently when the IQ calibration is in
+ * progress to speedup loading the final settings.
+ * We temper this aggressive polling with an exponential
+ * back off after 4 tries up to ath_calinterval.
+ */
+ if (iqCalDone || sc->sc_calinterval >= ath_calinterval) {
+ sc->sc_caltries = 0;
+ sc->sc_calinterval = ath_calinterval;
+ } else if (sc->sc_caltries > 4) {
+ sc->sc_caltries = 0;
+ sc->sc_calinterval <<= 1;
+ if (sc->sc_calinterval > ath_calinterval)
+ sc->sc_calinterval = ath_calinterval;
+ }
+ KASSERT(0 < sc->sc_calinterval && sc->sc_calinterval <= ath_calinterval,
+ ("bad calibration interval %u", sc->sc_calinterval));
+
+ DPRINTF(sc, ATH_DEBUG_CALIBRATE,
+ "%s: next +%u (%siqCalDone tries %u)\n", __func__,
+ sc->sc_calinterval, iqCalDone ? "" : "!", sc->sc_caltries);
+ sc->sc_caltries++;
+ callout_reset(&sc->sc_cal_ch, sc->sc_calinterval * hz,
+ ath_calibrate, sc);
}
static void
@@ -4880,7 +4953,7 @@
*/
if (nstate == IEEE80211_S_RUN) {
/* start periodic recalibration timer */
- callout_reset(&sc->sc_cal_ch, ath_calinterval * hz,
+ callout_reset(&sc->sc_cal_ch, sc->sc_calinterval * hz,
ath_calibrate, sc);
}
bad:
@@ -5535,6 +5608,33 @@
return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0;
}
+static int
+ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
+{
+ struct ath_softc *sc = arg1;
+ u_int rfkill = ath_hal_getrfkill(sc->sc_ah);
+ int error;
+
+ error = sysctl_handle_int(oidp, &rfkill, 0, req);
+ if (error || !req->newptr)
+ return error;
+ return !ath_hal_setrfkill(sc->sc_ah, rfkill) ? EINVAL : 0;
+}
+
+static int
+ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS)
+{
+ struct ath_softc *sc = arg1;
+ u_int rfsilent;
+ int error;
+
+ ath_hal_getrfsilent(sc->sc_ah, &rfsilent);
+ error = sysctl_handle_int(oidp, &rfsilent, 0, req);
+ if (error || !req->newptr)
+ return error;
+ return !ath_hal_setrfsilent(sc->sc_ah, rfsilent) ? EINVAL : 0;
+}
+
static void
ath_sysctlattach(struct ath_softc *sc)
{
@@ -5610,6 +5710,14 @@
"fftxqmax", CTLFLAG_RW, &sc->sc_fftxqmax, 0,
"max queued frames before tail drop");
}
+ if (ath_hal_hasrfsilent(ah)) {
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "rfsilent", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ ath_sysctl_rfsilent, "I", "h/w RF silent config");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "rfkill", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ ath_sysctl_rfkill, "I", "enable/disable RF kill switch");
+ }
}
static void
==== //depot/projects/wifi/sys/dev/ath/if_athioctl.h#9 (text+ko) ====
@@ -46,6 +46,7 @@
u_int32_t ast_watchdog; /* device reset by watchdog */
u_int32_t ast_hardware; /* fatal hardware error interrupts */
u_int32_t ast_bmiss; /* beacon miss interrupts */
+ u_int32_t ast_bmiss_phantom;/* beacon miss interrupts */
u_int32_t ast_bstuck; /* beacon stuck interrupts */
u_int32_t ast_rxorn; /* rx overrun interrupts */
u_int32_t ast_rxeol; /* rx eol interrupts */
@@ -110,6 +111,7 @@
u_int32_t ast_ff_rx; /* fast frames rx'd */
u_int32_t ast_ff_flush; /* fast frames flushed from staging q */
u_int32_t ast_tx_qfull; /* tx dropped 'cuz of queue limit */
+ u_int32_t ast_pad[32];
};
#define SIOCGATHSTATS _IOWR('i', 137, struct ifreq)
==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#44 (text+ko) ====
@@ -289,6 +289,7 @@
struct task sc_rxorntask; /* rxorn int processing */
u_int8_t sc_defant; /* current default antenna */
u_int8_t sc_rxotherant; /* rx's on non-default antenna*/
+ u_int64_t sc_lastrx; /* tsf at last rx'd frame */
struct ath_descdma sc_txdma; /* TX descriptors */
ath_bufhead sc_txbuf; /* transmit buffer */
@@ -315,6 +316,8 @@
} sc_updateslot; /* slot time update fsm */
struct callout sc_cal_ch; /* callout handle for cals */
+ int sc_calinterval; /* current polling interval */
+ int sc_caltries; /* cals at current interval */
HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */
};
#define sc_tx_th u_tx_rt.th
@@ -411,8 +414,8 @@
((*(_ah)->ah_startTxDma)((_ah), (_q)))
#define ath_hal_setchannel(_ah, _chan) \
((*(_ah)->ah_setChannel)((_ah), (_chan)))
-#define ath_hal_calibrate(_ah, _chan) \
- ((*(_ah)->ah_perCalibration)((_ah), (_chan)))
+#define ath_hal_calibrate(_ah, _chan, _iqcal) \
+ ((*(_ah)->ah_perCalibration)((_ah), (_chan), (_iqcal)))
#define ath_hal_setledstate(_ah, _state) \
((*(_ah)->ah_setLedState)((_ah), (_state)))
#define ath_hal_beaconinit(_ah, _nextb, _bperiod) \
@@ -528,6 +531,16 @@
#endif
#define ath_hal_hasfastframes(_ah) \
(ath_hal_getcapability(_ah, HAL_CAP_FASTFRAME, 0, NULL) == HAL_OK)
+#define ath_hal_hasrfsilent(_ah) \
+ (ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 0, NULL) == HAL_OK)
+#define ath_hal_getrfkill(_ah) \
+ (ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 1, NULL) == HAL_OK)
+#define ath_hal_setrfkill(_ah, _onoff) \
+ ath_hal_setcapability(_ah, HAL_CAP_RFSILENT, 1, _onoff, NULL)
+#define ath_hal_getrfsilent(_ah, _prfsilent) \
+ (ath_hal_getcapability(_ah, HAL_CAP_RFSILENT, 2, _prfsilent) == HAL_OK)
+#define ath_hal_setrfsilent(_ah, _rfsilent) \
+ ath_hal_setcapability(_ah, HAL_CAP_RFSILENT, 2, _rfsilent, NULL)
#define ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))
More information about the p4-projects
mailing list