summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_power.c
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2013-01-15 17:50:07 +0000
committeradrian <adrian@FreeBSD.org>2013-01-15 17:50:07 +0000
commit7c5e15d91f93e7203abfcf4a00a6a26aef33e7b1 (patch)
tree8617aa9b7c14753dbad63c3d5d145f9d156490e5 /sys/net80211/ieee80211_power.c
parentad78d0986c5ee7ae0a29014180985eeddd916acd (diff)
downloadFreeBSD-src-7c5e15d91f93e7203abfcf4a00a6a26aef33e7b1.zip
FreeBSD-src-7c5e15d91f93e7203abfcf4a00a6a26aef33e7b1.tar.gz
Remove the use of the ifnet send queue and if_start() in the power
save queue code. Instead, use if_transmit() directly - and handle the cases where frame transmission fails. I don't necessarily like this and I think at this point the M_ENCAP check, node freeing upon fail and the actual if_transmit() call should be done in methods in ieee80211_freebsd.c, but I digress slightly.. This removes one of the last few uses of if_start() and the ifnet if_snd queue. The last major offender is ieee80211_output.c, where ieee80211_start() implements if_start() and uses the ifnet queue directly. (There's a couple of gotchas here, where the if_start pointer is compared to ieee80211_start(), but that's a later problem.)
Diffstat (limited to 'sys/net80211/ieee80211_power.c')
-rw-r--r--sys/net80211/ieee80211_power.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 558e1f3..31bc578 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -416,6 +416,8 @@ pwrsave_flushq(struct ieee80211_node *ni)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_psq_head *qhead;
struct ifnet *parent, *ifp;
+ struct mbuf *parent_q = NULL, *ifp_q = NULL;
+ struct mbuf *m;
IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
"flush ps queue, %u packets queued", psq->psq_len);
@@ -427,8 +429,7 @@ pwrsave_flushq(struct ieee80211_node *ni)
parent = vap->iv_ic->ic_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
- IF_PREPEND_LIST(&parent->if_snd, qhead->head, qhead->tail,
- qhead->len);
+ parent_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
@@ -439,8 +440,7 @@ pwrsave_flushq(struct ieee80211_node *ni)
ifp = vap->iv_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
- IF_PREPEND_LIST(&ifp->if_snd, qhead->head, qhead->tail,
- qhead->len);
+ ifp_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
@@ -450,10 +450,34 @@ pwrsave_flushq(struct ieee80211_node *ni)
/* NB: do this outside the psq lock */
/* XXX packets might get reordered if parent is OACTIVE */
- if (parent != NULL)
- if_start(parent);
- if (ifp != NULL)
- if_start(ifp);
+ /* parent frames, should be encapsulated */
+ if (parent != NULL) {
+ while (parent_q != NULL) {
+ m = parent_q;
+ parent_q = m->m_nextpkt;
+ /* must be encapsulated */
+ KASSERT((m->m_flags & M_ENCAP),
+ ("%s: parentq with non-M_ENCAP frame!\n",
+ __func__));
+ /*
+ * For encaped frames, we need to free the node
+ * reference upon failure.
+ */
+ if (parent->if_transmit(parent, m) != 0)
+ ieee80211_free_node(ni);
+ }
+ }
+
+ /* VAP frames, aren't encapsulated */
+ if (ifp != NULL) {
+ while (ifp_q != NULL) {
+ m = ifp_q;
+ ifp_q = m->m_nextpkt;
+ KASSERT((!(m->m_flags & M_ENCAP)),
+ ("%s: vapq with M_ENCAP frame!\n", __func__));
+ (void) ifp->if_transmit(ifp, m);
+ }
+ }
}
/*
OpenPOWER on IntegriCloud