Commit 8a61af65 authored by Johannes Berg's avatar Johannes Berg

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: default avatarJohannes Berg <johannes.berg@intel.com>
parent 529ba6e9
...@@ -3754,6 +3754,11 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, ...@@ -3754,6 +3754,11 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
* The iterator will not find a context that's being added (during * The iterator will not find a context that's being added (during
* the driver callback to add it) but will find it while it's being * the driver callback to add it) but will find it while it's being
* removed. * removed.
*
* Note that during hardware restart, all contexts that existed
* before the restart are considered already present so will be
* found while iterating, whether they've been re-added already
* or not.
*/ */
void ieee80211_iter_chan_contexts_atomic( void ieee80211_iter_chan_contexts_atomic(
struct ieee80211_hw *hw, struct ieee80211_hw *hw,
......
...@@ -381,6 +381,7 @@ void ieee80211_iter_chan_contexts_atomic( ...@@ -381,6 +381,7 @@ void ieee80211_iter_chan_contexts_atomic(
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(ctx, &local->chanctx_list, list) list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
if (ctx->driver_present)
iter(hw, &ctx->conf, iter_data); iter(hw, &ctx->conf, iter_data);
rcu_read_unlock(); rcu_read_unlock();
} }
......
...@@ -913,6 +913,8 @@ static inline int drv_add_chanctx(struct ieee80211_local *local, ...@@ -913,6 +913,8 @@ static inline int drv_add_chanctx(struct ieee80211_local *local,
if (local->ops->add_chanctx) if (local->ops->add_chanctx)
ret = local->ops->add_chanctx(&local->hw, &ctx->conf); ret = local->ops->add_chanctx(&local->hw, &ctx->conf);
trace_drv_return_int(local, ret); trace_drv_return_int(local, ret);
if (!ret)
ctx->driver_present = true;
return ret; return ret;
} }
...@@ -924,6 +926,7 @@ static inline void drv_remove_chanctx(struct ieee80211_local *local, ...@@ -924,6 +926,7 @@ static inline void drv_remove_chanctx(struct ieee80211_local *local,
if (local->ops->remove_chanctx) if (local->ops->remove_chanctx)
local->ops->remove_chanctx(&local->hw, &ctx->conf); local->ops->remove_chanctx(&local->hw, &ctx->conf);
trace_drv_return_void(local); trace_drv_return_void(local);
ctx->driver_present = false;
} }
static inline void drv_change_chanctx(struct ieee80211_local *local, static inline void drv_change_chanctx(struct ieee80211_local *local,
...@@ -931,8 +934,10 @@ 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) u32 changed)
{ {
trace_drv_change_chanctx(local, ctx, 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); local->ops->change_chanctx(&local->hw, &ctx->conf, changed);
}
trace_drv_return_void(local); trace_drv_return_void(local);
} }
...@@ -945,10 +950,12 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local, ...@@ -945,10 +950,12 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
check_sdata_in_driver(sdata); check_sdata_in_driver(sdata);
trace_drv_assign_vif_chanctx(local, sdata, ctx); 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, ret = local->ops->assign_vif_chanctx(&local->hw,
&sdata->vif, &sdata->vif,
&ctx->conf); &ctx->conf);
}
trace_drv_return_int(local, ret); trace_drv_return_int(local, ret);
return ret; return ret;
...@@ -961,10 +968,12 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, ...@@ -961,10 +968,12 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
check_sdata_in_driver(sdata); check_sdata_in_driver(sdata);
trace_drv_unassign_vif_chanctx(local, sdata, ctx); 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, local->ops->unassign_vif_chanctx(&local->hw,
&sdata->vif, &sdata->vif,
&ctx->conf); &ctx->conf);
}
trace_drv_return_void(local); trace_drv_return_void(local);
} }
......
...@@ -685,6 +685,7 @@ struct ieee80211_chanctx { ...@@ -685,6 +685,7 @@ struct ieee80211_chanctx {
enum ieee80211_chanctx_mode mode; enum ieee80211_chanctx_mode mode;
int refcount; int refcount;
bool driver_present;
struct ieee80211_chanctx_conf conf; struct ieee80211_chanctx_conf conf;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment