summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-12-13 17:42:30 +0100
committerJohannes Berg <johannes.berg@intel.com>2013-01-03 13:01:35 +0100
commit8a61af65c6d03781015315dbc43d0942a5b31db9 (patch)
tree624695ba646281508490cb1737fb69d8174fa87a /net
parent529ba6e9313dbe60dab7e72c6fdf647a012e9f5b (diff)
downloadlinux-3.10-8a61af65c6d03781015315dbc43d0942a5b31db9.tar.gz
linux-3.10-8a61af65c6d03781015315dbc43d0942a5b31db9.tar.bz2
linux-3.10-8a61af65c6d03781015315dbc43d0942a5b31db9.zip
mac80211: fix channel context iteration
During suspend/resume channel contexts might be iterated even if they haven't been re-added to the driver, keep track of this and skip them in iteration. Also use the new status for sanity checks. Also clarify the fact that during HW restart all contexts are iterated over (thanks Eliad.) Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/chan.c3
-rw-r--r--net/mac80211/driver-ops.h15
-rw-r--r--net/mac80211/ieee80211_i.h1
3 files changed, 15 insertions, 4 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 80e55527504..1bfe0a8b19d 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -381,7 +381,8 @@ void ieee80211_iter_chan_contexts_atomic(
rcu_read_lock();
list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
- iter(hw, &ctx->conf, iter_data);
+ if (ctx->driver_present)
+ iter(hw, &ctx->conf, iter_data);
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 698dc7e6f30..608ced41548 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -913,6 +913,8 @@ static inline int drv_add_chanctx(struct ieee80211_local *local,
if (local->ops->add_chanctx)
ret = local->ops->add_chanctx(&local->hw, &ctx->conf);
trace_drv_return_int(local, ret);
+ if (!ret)
+ ctx->driver_present = true;
return ret;
}
@@ -924,6 +926,7 @@ static inline void drv_remove_chanctx(struct ieee80211_local *local,
if (local->ops->remove_chanctx)
local->ops->remove_chanctx(&local->hw, &ctx->conf);
trace_drv_return_void(local);
+ ctx->driver_present = false;
}
static inline void drv_change_chanctx(struct ieee80211_local *local,
@@ -931,8 +934,10 @@ static inline void drv_change_chanctx(struct ieee80211_local *local,
u32 changed)
{
trace_drv_change_chanctx(local, ctx, changed);
- if (local->ops->change_chanctx)
+ if (local->ops->change_chanctx) {
+ WARN_ON_ONCE(!ctx->driver_present);
local->ops->change_chanctx(&local->hw, &ctx->conf, changed);
+ }
trace_drv_return_void(local);
}
@@ -945,10 +950,12 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
check_sdata_in_driver(sdata);
trace_drv_assign_vif_chanctx(local, sdata, ctx);
- if (local->ops->assign_vif_chanctx)
+ if (local->ops->assign_vif_chanctx) {
+ WARN_ON_ONCE(!ctx->driver_present);
ret = local->ops->assign_vif_chanctx(&local->hw,
&sdata->vif,
&ctx->conf);
+ }
trace_drv_return_int(local, ret);
return ret;
@@ -961,10 +968,12 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
check_sdata_in_driver(sdata);
trace_drv_unassign_vif_chanctx(local, sdata, ctx);
- if (local->ops->unassign_vif_chanctx)
+ if (local->ops->unassign_vif_chanctx) {
+ WARN_ON_ONCE(!ctx->driver_present);
local->ops->unassign_vif_chanctx(&local->hw,
&sdata->vif,
&ctx->conf);
+ }
trace_drv_return_void(local);
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 38e7883cff2..23161189b17 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -685,6 +685,7 @@ struct ieee80211_chanctx {
enum ieee80211_chanctx_mode mode;
int refcount;
+ bool driver_present;
struct ieee80211_chanctx_conf conf;
};