summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_proto.c
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2012-03-25 03:11:57 +0000
committeradrian <adrian@FreeBSD.org>2012-03-25 03:11:57 +0000
commit2acdb6a872bf31d86f5d08f522dcdf2a0e290626 (patch)
treea5520cea75b7e712fd6a1762e30122d3ff900f60 /sys/net80211/ieee80211_proto.c
parent4dabba6aea432d6bf5e1baf9e344fc143410af0d (diff)
downloadFreeBSD-src-2acdb6a872bf31d86f5d08f522dcdf2a0e290626.zip
FreeBSD-src-2acdb6a872bf31d86f5d08f522dcdf2a0e290626.tar.gz
Create a new task to handle 802.11n channel width changes.
Currently, a channel width change updates the 802.11n HT info data in net80211 but it doesn't trigger any device changes. So the device driver may decide that HT40 frames can be transmitted but the last device channel set only had HT20 set. Now, a task is scheduled so a hardware reset or change isn't done during any active ongoing RX. It also means that it's serialised with the other task operations (eg channel change.) This isn't the final incantation of this work, see below. For now, any unmodified drivers will simply receive a channel change log entry. A subsequent patch to ath(4) will introduce some basic channel change handling (by resetting the NIC.) Other NICs may need to update their rate control information. TODO: * There's still a small window at the present moment where the channel width has been updated but the task hasn't been fired. The final version of this should likely pass in a channel width field to the driver and let the driver atomically do whatever it needs to before changing the channel. PR: kern/166286
Diffstat (limited to 'sys/net80211/ieee80211_proto.c')
-rw-r--r--sys/net80211/ieee80211_proto.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index caa813a..232dbba 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -105,6 +105,7 @@ static void parent_updown(void *, int);
static void update_mcast(void *, int);
static void update_promisc(void *, int);
static void update_channel(void *, int);
+static void update_chw(void *, int);
static void ieee80211_newstate_cb(void *, int);
static int ieee80211_new_state_locked(struct ieee80211vap *,
enum ieee80211_state, int);
@@ -144,6 +145,7 @@ ieee80211_proto_attach(struct ieee80211com *ic)
TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic);
TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic);
TASK_INIT(&ic->ic_bmiss_task, 0, beacon_miss, ic);
+ TASK_INIT(&ic->ic_chw_task, 0, update_chw, ic);
ic->ic_wme.wme_hipri_switch_hysteresis =
AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
@@ -1147,6 +1149,17 @@ update_channel(void *arg, int npending)
ieee80211_radiotap_chan_change(ic);
}
+static void
+update_chw(void *arg, int npending)
+{
+ struct ieee80211com *ic = arg;
+
+ /*
+ * XXX should we defer the channel width _config_ update until now?
+ */
+ ic->ic_update_chw(ic);
+}
+
/*
* Block until the parent is in a known state. This is
* used after any operations that dispatch a task (e.g.
@@ -1161,6 +1174,7 @@ ieee80211_waitfor_parent(struct ieee80211com *ic)
ieee80211_draintask(ic, &ic->ic_promisc_task);
ieee80211_draintask(ic, &ic->ic_chan_task);
ieee80211_draintask(ic, &ic->ic_bmiss_task);
+ ieee80211_draintask(ic, &ic->ic_chw_task);
taskqueue_unblock(ic->ic_tq);
}
OpenPOWER on IntegriCloud