Page MenuHomeFreeBSD

D4054.diff
No OneTemporary

D4054.diff

Index: sys/net80211/ieee80211.c
===================================================================
--- sys/net80211/ieee80211.c
+++ sys/net80211/ieee80211.c
@@ -325,6 +325,7 @@
ieee80211_crypto_attach(ic);
ieee80211_node_attach(ic);
ieee80211_power_attach(ic);
+ ieee80211_tx_watchdog_attach(ic);
ieee80211_proto_attach(ic);
#ifdef IEEE80211_SUPPORT_SUPERG
ieee80211_superg_attach(ic);
@@ -376,6 +377,7 @@
ieee80211_ht_detach(ic);
/* NB: must be called before ieee80211_node_detach */
ieee80211_proto_detach(ic);
+ ieee80211_tx_watchdog_detach(ic);
ieee80211_crypto_detach(ic);
ieee80211_power_detach(ic);
ieee80211_node_detach(ic);
Index: sys/net80211/ieee80211_freebsd.h
===================================================================
--- sys/net80211/ieee80211_freebsd.h
+++ sys/net80211/ieee80211_freebsd.h
@@ -83,6 +83,23 @@
mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED)
/*
+ * Watchdog lock.
+ */
+typedef struct {
+ char name[16]; /* e.g. "ath0_wt_lock" */
+ struct mtx mtx;
+} ieee80211_wt_lock_t;
+#define IEEE80211_WT_LOCK_INIT(_ic, _name) do { \
+ ieee80211_wt_lock_t *wl = &(_ic)->ic_wtlock; \
+ snprintf(wl->name, sizeof(wl->name), "%s_wt_lock", _name); \
+ mtx_init(&wl->mtx, wl->name, NULL, MTX_DEF); \
+} while (0)
+#define IEEE80211_WT_LOCK_OBJ(_ic) (&(_ic)->ic_wtlock.mtx)
+#define IEEE80211_WT_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_WT_LOCK_OBJ(_ic))
+#define IEEE80211_WT_LOCK(_ic) mtx_lock(IEEE80211_WT_LOCK_OBJ(_ic))
+#define IEEE80211_WT_UNLOCK(_ic) mtx_unlock(IEEE80211_WT_LOCK_OBJ(_ic))
+
+/*
* Node locking definitions.
*/
typedef struct {
@@ -334,6 +351,11 @@
#define NET80211_TAG_RECV_PARAMS 2
struct ieee80211com;
+void ieee80211_tx_watchdog_attach(struct ieee80211com *);
+void ieee80211_tx_watchdog_refresh(struct ieee80211com *, int, int);
+void ieee80211_tx_watchdog_stop(struct ieee80211com *);
+void ieee80211_tx_watchdog_detach(struct ieee80211com *);
+
int ieee80211_parent_xmitpkt(struct ieee80211com *, struct mbuf *);
int ieee80211_vap_xmitpkt(struct ieee80211vap *, struct mbuf *);
Index: sys/net80211/ieee80211_freebsd.c
===================================================================
--- sys/net80211/ieee80211_freebsd.c
+++ sys/net80211/ieee80211_freebsd.c
@@ -562,6 +562,82 @@
return (0);
}
+void
+ieee80211_tx_watchdog_attach(struct ieee80211com *ic)
+{
+ if (ic->ic_flags_ext & IEEE80211_FEXT_WATCHDOG) {
+ IEEE80211_WT_LOCK_INIT(ic, ic->ic_name);
+ callout_init_mtx(&ic->ic_tx_watchdog,
+ IEEE80211_WT_LOCK_OBJ(ic), 0);
+ }
+}
+
+static void
+ieee80211_tx_watchdog(void *arg)
+{
+ struct ieee80211com *ic = arg;
+
+ if (ic->ic_tx_timer > 0) {
+ if (--ic->ic_tx_timer == 0) {
+ ic_printf(ic, "device timeout\n");
+
+ counter_u64_add(ic->ic_oerrors, ic->ic_tx_queued);
+ ic->ic_tx_queued = 0;
+
+ ieee80211_restart_all(ic);
+ return;
+ }
+
+ callout_reset(&ic->ic_tx_watchdog, hz, ieee80211_tx_watchdog,
+ ic);
+ }
+}
+
+void
+ieee80211_tx_watchdog_refresh(struct ieee80211com *ic, int nframes, int update)
+{
+ if (ic->ic_flags_ext & IEEE80211_FEXT_WATCHDOG) {
+ IEEE80211_WT_LOCK(ic);
+ if (ic->ic_tx_queued + nframes < 0)
+ ic->ic_tx_queued = -nframes;
+
+ if (ic->ic_tx_queued == 0) {
+ ic->ic_tx_timer = IEEE80211_WATCHDOG_TIMEOUT;
+ callout_reset(&ic->ic_tx_watchdog, hz,
+ ieee80211_tx_watchdog, ic);
+ }
+
+ ic->ic_tx_queued += nframes;
+
+ if (ic->ic_tx_queued == 0)
+ ic->ic_tx_timer = 0;
+ else if (update != 0)
+ ic->ic_tx_timer = IEEE80211_WATCHDOG_TIMEOUT;
+ IEEE80211_WT_UNLOCK(ic);
+ }
+}
+
+void
+ieee80211_tx_watchdog_stop(struct ieee80211com *ic)
+{
+ if (ic->ic_flags_ext & IEEE80211_FEXT_WATCHDOG) {
+ IEEE80211_WT_LOCK(ic);
+ callout_stop(&ic->ic_tx_watchdog);
+ ic->ic_tx_timer = 0;
+ ic->ic_tx_queued = 0;
+ IEEE80211_WT_UNLOCK(ic);
+ }
+}
+
+void
+ieee80211_tx_watchdog_detach(struct ieee80211com *ic)
+{
+ if (ic->ic_flags_ext & IEEE80211_FEXT_WATCHDOG) {
+ callout_drain(&ic->ic_tx_watchdog);
+ IEEE80211_WT_LOCK_DESTROY(ic);
+ }
+}
+
/*
* Transmit a frame to the parent interface.
@@ -569,21 +645,27 @@
int
ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
{
- int error;
+ int error, nframes;
+ struct mbuf *mnext;
+
+ nframes = 1;
+ for (mnext = m->m_nextpkt; mnext != NULL; mnext = mnext->m_nextpkt)
+ nframes++;
/*
* Assert the IC TX lock is held - this enforces the
* processing -> queuing order is maintained
*/
IEEE80211_TX_LOCK_ASSERT(ic);
+ ieee80211_tx_watchdog_refresh(ic, nframes, 0);
error = ic->ic_transmit(ic, m);
if (error) {
struct ieee80211_node *ni;
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
- /* XXX number of fragments */
- if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, nframes);
+ ieee80211_tx_watchdog_refresh(ic, -nframes, 0);
ieee80211_free_node(ni);
ieee80211_free_mbuf(m);
}
Index: sys/net80211/ieee80211_output.c
===================================================================
--- sys/net80211/ieee80211_output.c
+++ sys/net80211/ieee80211_output.c
@@ -530,9 +530,11 @@
if (params)
(void) ieee80211_add_xmit_params(m, params);
+ ieee80211_tx_watchdog_refresh(ic, 1, 0);
error = ic->ic_raw_xmit(ni, m, params);
if (error) {
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+ ieee80211_tx_watchdog_refresh(ic, -1, 0);
ieee80211_free_node(ni);
}
return (error);
@@ -3489,7 +3491,9 @@
if (ni != NULL) {
struct ifnet *ifp = ni->ni_vap->iv_ifp;
+ struct ieee80211com *ic = ni->ni_ic;
+ ieee80211_tx_watchdog_refresh(ic, -1, 1);
if (status == 0) {
if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
Index: sys/net80211/ieee80211_proto.c
===================================================================
--- sys/net80211/ieee80211_proto.c
+++ sys/net80211/ieee80211_proto.c
@@ -1422,6 +1422,7 @@
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
"down parent %s\n", ic->ic_name);
ieee80211_runtask(ic, &ic->ic_parent_task);
+ ieee80211_tx_watchdog_stop(ic);
}
}
}
Index: sys/net80211/ieee80211_var.h
===================================================================
--- sys/net80211/ieee80211_var.h
+++ sys/net80211/ieee80211_var.h
@@ -86,6 +86,8 @@
#define IEEE80211_TU_TO_MS(x) (((x) * 1024) / 1000)
#define IEEE80211_TU_TO_TICKS(x)(((x) * 1024 * hz) / (1000 * 1000))
+#define IEEE80211_WATCHDOG_TIMEOUT 5
+
/*
* 802.11 control state is split into a common portion that maps
* 1-1 to a physical device and one or more "Virtual AP's" (VAP)
@@ -120,12 +122,14 @@
const char *ic_name; /* usually device name */
ieee80211_com_lock_t ic_comlock; /* state update lock */
ieee80211_tx_lock_t ic_txlock; /* ic/vap TX lock */
+ ieee80211_wt_lock_t ic_wtlock; /* watchdog lock */
LIST_ENTRY(ieee80211com) ic_next; /* on global list */
TAILQ_HEAD(, ieee80211vap) ic_vaps; /* list of vap instances */
int ic_headroom; /* driver tx headroom needs */
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
enum ieee80211_opmode ic_opmode; /* operation mode */
struct callout ic_inact; /* inactivity processing */
+ struct callout ic_tx_watchdog; /* TX watchdog */
struct taskqueue *ic_tq; /* deferred state thread */
struct task ic_parent_task; /* deferred parent processing */
struct task ic_promisc_task;/* deferred promisc update */
@@ -139,6 +143,9 @@
counter_u64_t ic_ierrors; /* input errors */
counter_u64_t ic_oerrors; /* output errors */
+ int16_t ic_tx_queued; /* number of queued frames */
+ uint8_t ic_tx_timer; /* watchdog timer */
+
uint32_t ic_flags; /* state flags */
uint32_t ic_flags_ext; /* extended state flags */
uint32_t ic_flags_ht; /* HT state flags */
@@ -597,6 +604,7 @@
#define IEEE80211_FEXT_WDSLEGACY 0x00010000 /* CONF: legacy WDS operation */
#define IEEE80211_FEXT_PROBECHAN 0x00020000 /* CONF: probe passive channel*/
#define IEEE80211_FEXT_UNIQMAC 0x00040000 /* CONF: user or computed mac */
+#define IEEE80211_FEXT_WATCHDOG 0x00080000 /* CONF: track tx activity */
#define IEEE80211_FEXT_BITS \
"\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 20, 1:22 AM (22 h, 32 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14727047
Default Alt Text
D4054.diff (8 KB)

Event Timeline