diff options
author | Eliad Peller <eliad@wizery.com> | 2015-10-25 10:59:36 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-11-03 10:41:12 +0100 |
commit | 968a76cef3d1bb9a3b4d135cd788056e742859f3 (patch) | |
tree | dfe73df7dae4879fe96b045cdffc0d2d64e829be /net/mac80211/driver-ops.h | |
parent | c189a685b83955a39884dc2bdae531bc0adf3b98 (diff) | |
download | lwn-968a76cef3d1bb9a3b4d135cd788056e742859f3.tar.gz lwn-968a76cef3d1bb9a3b4d135cd788056e742859f3.zip |
mac80211: call drv_stop only if driver is started
If drv_start() fails during hw_restart, all the running
interfaces are being closed/stopped, which results in
drv_stop() being called, although the driver was never
started successfully.
This might cause drivers to perform operations on uninitialized
memory (as they assume it was initialized on drv_start)
Consider the local->started flag, and call the driver's stop()
op only if drv_start() succeeded before.
Move drv_start() and drv_stop() to driver-ops.c, as they are no
longer simple wrappers.
Signed-off-by: Eliad Peller <eliadx.peller@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/driver-ops.h')
-rw-r--r-- | net/mac80211/driver-ops.h | 32 |
1 files changed, 2 insertions, 30 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 30987099eb8f..f82cfab615f2 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -66,36 +66,8 @@ static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata, return rv; } -static inline int drv_start(struct ieee80211_local *local) -{ - int ret; - - might_sleep(); - - trace_drv_start(local); - local->started = true; - smp_mb(); - ret = local->ops->start(&local->hw); - trace_drv_return_int(local, ret); - return ret; -} - -static inline void drv_stop(struct ieee80211_local *local) -{ - might_sleep(); - - trace_drv_stop(local); - local->ops->stop(&local->hw); - trace_drv_return_void(local); - - /* sync away all work on the tasklet before clearing started */ - tasklet_disable(&local->tasklet); - tasklet_enable(&local->tasklet); - - barrier(); - - local->started = false; -} +int drv_start(struct ieee80211_local *local); +void drv_stop(struct ieee80211_local *local); #ifdef CONFIG_PM static inline int drv_suspend(struct ieee80211_local *local, |