Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102943212
D4054.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D4054.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D4054: net80211: add watchdog routines
Attached
Detach File
Event Timeline
Log In to Comment