summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-11-29 01:23:59 +0000
committersam <sam@FreeBSD.org>2003-11-29 01:23:59 +0000
commit0be6a7a9dd44f673c83eae25d2fc3dfff88d8739 (patch)
tree6df5abc920cf0a83ae8b69eb95fc1a0551a9d9f7 /sys/dev/ath
parent55858fe02ce858b955630e876d857ea841aba875 (diff)
downloadFreeBSD-src-0be6a7a9dd44f673c83eae25d2fc3dfff88d8739.zip
FreeBSD-src-0be6a7a9dd44f673c83eae25d2fc3dfff88d8739.tar.gz
o track API change for HAL v0.9.6.1
o fix race condition when processing rx descriptors: because we use a self-linked descriptor at the end of the rx descriptor list to avoid rx overruns (which can easily happen for 5212 parts that enable PHY errors) we must carefully check that a descriptor is "done" by looking ahead to the next descriptor before believing the done bit in the current descriptor (this is all handled in the HAL since the rx descriptor format is chip-specific so we need to pass in two additional parameters--the physical address of the current descriptor and the virtual address of the next descriptor in the list) o check copyout return status for SIOCGATHSTATS ioctl Approved by: re (scottl)
Diffstat (limited to 'sys/dev/ath')
-rw-r--r--sys/dev/ath/if_ath.c53
-rw-r--r--sys/dev/ath/if_athioctl.h9
-rw-r--r--sys/dev/ath/if_athvar.h12
3 files changed, 56 insertions, 18 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 347e101..55467db 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -905,8 +905,24 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ath_mode_init(sc);
break;
case SIOCGATHSTATS:
- copyout(&sc->sc_stats, ifr->ifr_data, sizeof (sc->sc_stats));
+ error = copyout(&sc->sc_stats,
+ ifr->ifr_data, sizeof (sc->sc_stats));
break;
+ case SIOCGATHDIAG: {
+ struct ath_diag *ad = (struct ath_diag *)data;
+ struct ath_hal *ah = sc->sc_ah;
+ void *data;
+ u_int size;
+
+ if (ath_hal_getdiagstate(ah, ad->ad_id, &data, &size)) {
+ if (size < ad->ad_size)
+ ad->ad_size = size;
+ if (data)
+ error = copyout(data, ad->ad_data, ad->ad_size);
+ } else
+ error = EINVAL;
+ break;
+ }
default:
error = ieee80211_ioctl(ifp, cmd, data);
if (error == ENETRESET) {
@@ -1599,6 +1615,9 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
static void
ath_rx_proc(void *arg, int npending)
{
+#define PA2DESC(_sc, _pa) \
+ ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
+ ((_pa) - (_sc)->sc_desc_paddr)))
struct ath_softc *sc = arg;
struct ath_buf *bf;
struct ieee80211com *ic = &sc->sc_ic;
@@ -1631,7 +1650,20 @@ ath_rx_proc(void *arg, int npending)
if_printf(ifp, "ath_rx_proc: no mbuf!\n");
continue;
}
- status = ath_hal_rxprocdesc(ah, ds);
+ /* XXX sync descriptor memory */
+ /*
+ * Must provide the virtual address of the current
+ * descriptor, the physical address, and the virtual
+ * address of the next descriptor in the h/w chain.
+ * This allows the HAL to look ahead to see if the
+ * hardware is done with a descriptor by checking the
+ * done bit in the following descriptor and the address
+ * of the current descriptor the DMA engine is working
+ * on. All this is necessary because of our use of
+ * a self-linked list to avoid rx overruns.
+ */
+ status = ath_hal_rxprocdesc(ah, ds,
+ bf->bf_daddr, PA2DESC(sc, ds->ds_link));
#ifdef AR_DEBUG
if (ath_debug > 1)
ath_printrxbuf(bf, status == HAL_OK);
@@ -1766,6 +1798,7 @@ ath_rx_proc(void *arg, int npending)
ath_hal_rxmonitor(ah); /* rx signal state monitoring */
ath_hal_rxena(ah); /* in case of RXEOL */
+#undef PA2DESC
}
/*
@@ -2237,6 +2270,9 @@ ath_draintxq(struct ath_softc *sc)
static void
ath_stoprecv(struct ath_softc *sc)
{
+#define PA2DESC(_sc, _pa) \
+ ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
+ ((_pa) - (_sc)->sc_desc_paddr)))
struct ath_hal *ah = sc->sc_ah;
ath_hal_stoppcurecv(ah); /* disable PCU */
@@ -2250,12 +2286,15 @@ ath_stoprecv(struct ath_softc *sc)
DPRINTF(("ath_stoprecv: rx queue %p, link %p\n",
(caddr_t) ath_hal_getrxbuf(ah), sc->sc_rxlink));
TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
- if (ath_hal_rxprocdesc(ah, bf->bf_desc) == HAL_OK)
+ struct ath_desc *ds = bf->bf_desc;
+ if (ath_hal_rxprocdesc(ah, ds, bf->bf_daddr,
+ PA2DESC(sc, ds->ds_link)) == HAL_OK)
ath_printrxbuf(bf, 1);
}
}
#endif
sc->sc_rxlink = NULL; /* just in case */
+#undef PA2DESC
}
/*
@@ -2422,7 +2461,7 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_node *ni;
int i, error;
- u_int8_t *bssid;
+ const u_int8_t *bssid;
u_int32_t rfilt;
static const HAL_LED_STATE leds[] = {
HAL_LED_INIT, /* IEEE80211_S_INIT */
@@ -2780,12 +2819,6 @@ sysctl_hw_ath_dump(SYSCTL_HANDLER_ARGS)
sc = ifp->if_softc;
if (strcmp(dmode, "hal") == 0)
ath_hal_dumpstate(sc->sc_ah);
- else if (strcmp(dmode, "eeprom") == 0)
- ath_hal_dumpeeprom(sc->sc_ah);
- else if (strcmp(dmode, "rfgain") == 0)
- ath_hal_dumprfgain(sc->sc_ah);
- else if (strcmp(dmode, "ani") == 0)
- ath_hal_dumpani(sc->sc_ah);
else
return EINVAL;
}
diff --git a/sys/dev/ath/if_athioctl.h b/sys/dev/ath/if_athioctl.h
index 308f9cb..0476f7f 100644
--- a/sys/dev/ath/if_athioctl.h
+++ b/sys/dev/ath/if_athioctl.h
@@ -91,6 +91,15 @@ struct ath_stats {
#define SIOCGATHSTATS _IOWR('i', 137, struct ifreq)
+struct ath_diag {
+ char ad_name[IFNAMSIZ]; /* if name, e.g. "ath0" */
+ u_int ad_id;
+ caddr_t ad_data;
+ u_int ad_size;
+
+};
+#define SIOCGATHDIAG _IOWR('i', 138, struct ath_diag)
+
/*
* Radio capture format.
*/
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 6e9ae65..13e7a60 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -274,12 +274,8 @@ void ath_intr(void *);
((*(_ah)->ah_stopDmaReceive)((_ah)))
#define ath_hal_dumpstate(_ah) \
((*(_ah)->ah_dumpState)((_ah)))
-#define ath_hal_dumpeeprom(_ah) \
- ((*(_ah)->ah_dumpEeprom)((_ah)))
-#define ath_hal_dumprfgain(_ah) \
- ((*(_ah)->ah_dumpRfGain)((_ah)))
-#define ath_hal_dumpani(_ah) \
- ((*(_ah)->ah_dumpAni)((_ah)))
+#define ath_hal_getdiagstate(_ah, _id, _data, _size) \
+ ((*(_ah)->ah_getDiagState)((_ah), (_id), (_data), (_size)))
#define ath_hal_setuptxqueue(_ah, _type, _irq) \
((*(_ah)->ah_setupTxQueue)((_ah), (_type), (_irq)))
#define ath_hal_resettxqueue(_ah, _q) \
@@ -299,8 +295,8 @@ void ath_intr(void *);
(_flen), (_hlen), (_rate), (_antmode)))
#define ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))
-#define ath_hal_rxprocdesc(_ah, _ds) \
- ((*(_ah)->ah_procRxDesc)((_ah), (_ds)))
+#define ath_hal_rxprocdesc(_ah, _ds, _dspa, _dsnext) \
+ ((*(_ah)->ah_procRxDesc)((_ah), (_ds), (_dspa), (_dsnext)))
#define ath_hal_setuptxdesc(_ah, _ds, _plen, _hlen, _atype, _txpow, \
_txr0, _txtr0, _keyix, _ant, _flags, \
_rtsrate, _rtsdura) \
OpenPOWER on IntegriCloud