This patch doesn't apply to the .37 stable tree.
If someone wants it applied there, please email the backport
to [email protected]

thanks,

greg k-h

> commit: 6a3be6e6e7feb4cb35275475d6a863b748d59cc3
> From: Roland Vossen <[email protected]>
> Date: Tue, 25 Jan 2011 11:51:56 +0100
> Subject: [PATCH] staging: brcm80211: bugfix for softmac crash on multi cpu 
> configurations
> 
> Solved a locking issue that resulted in driver crashes with the 43224 and 
> 43225
> chips. The problem has been reported on several fora. Root cause was two fold:
> hardware was being manipulated by two unsynchronized threads, and a scan
> operation could interfere with an ongoing dynamic calibration process. Fix was
> to invoke a lock on wl_ops_config() operation and to set internal flags when a
> scan operation is started and stopped.
> 
> Please add this to the staging-linus branch.
> 
> Reviewed-by: Arend van Spriel <[email protected]>
> Signed-off-by: Roland Vossen <[email protected]>
> Cc: stable <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
> ---
>  drivers/staging/brcm80211/sys/wl_mac80211.c  |   12 ++++++++++--
>  drivers/staging/brcm80211/sys/wlc_mac80211.c |   13 +++++++++++++
>  drivers/staging/brcm80211/sys/wlc_pub.h      |    2 ++
>  3 files changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/staging/brcm80211/sys/wl_mac80211.c 
> b/drivers/staging/brcm80211/sys/wl_mac80211.c
> index f123588..cd8392b 100644
> --- a/drivers/staging/brcm80211/sys/wl_mac80211.c
> +++ b/drivers/staging/brcm80211/sys/wl_mac80211.c
> @@ -263,9 +263,7 @@ ieee_set_channel(struct ieee80211_hw *hw, struct 
> ieee80211_channel *chan,
>       switch (type) {
>       case NL80211_CHAN_HT20:
>       case NL80211_CHAN_NO_HT:
> -             WL_LOCK(wl);
>               err = wlc_set(wl->wlc, WLC_SET_CHANNEL, chan->hw_value);
> -             WL_UNLOCK(wl);
>               break;
>       case NL80211_CHAN_HT40MINUS:
>       case NL80211_CHAN_HT40PLUS:
> @@ -285,6 +283,7 @@ static int wl_ops_config(struct ieee80211_hw *hw, u32 
> changed)
>       int err = 0;
>       int new_int;
>  
> +     WL_LOCK(wl);
>       if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
>               WL_NONE("%s: Setting listen interval to %d\n",
>                       __func__, conf->listen_interval);
> @@ -341,6 +340,7 @@ static int wl_ops_config(struct ieee80211_hw *hw, u32 
> changed)
>       }
>  
>   config_out:
> +     WL_UNLOCK(wl);
>       return err;
>  }
>  
> @@ -459,13 +459,21 @@ wl_ops_set_tim(struct ieee80211_hw *hw, struct 
> ieee80211_sta *sta, bool set)
>  
>  static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
>  {
> +     struct wl_info *wl = hw->priv;
>       WL_NONE("Scan Start\n");
> +     WL_LOCK(wl);
> +     wlc_scan_start(wl->wlc);
> +     WL_UNLOCK(wl);
>       return;
>  }
>  
>  static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
>  {
> +     struct wl_info *wl = hw->priv;
>       WL_NONE("Scan Complete\n");
> +     WL_LOCK(wl);
> +     wlc_scan_stop(wl->wlc);
> +     WL_UNLOCK(wl);
>       return;
>  }
>  
> diff --git a/drivers/staging/brcm80211/sys/wlc_mac80211.c 
> b/drivers/staging/brcm80211/sys/wlc_mac80211.c
> index a130386..e37e805 100644
> --- a/drivers/staging/brcm80211/sys/wlc_mac80211.c
> +++ b/drivers/staging/brcm80211/sys/wlc_mac80211.c
> @@ -8461,3 +8461,16 @@ static void wlc_txq_free(struct wlc_info *wlc, struct 
> osl_info *osh,
>  
>       kfree(qi);
>  }
> +
> +/*
> + * Flag 'scan in progress' to withold dynamic phy calibration
> + */
> +void wlc_scan_start(struct wlc_info *wlc)
> +{
> +     wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
> +}
> +
> +void wlc_scan_stop(struct wlc_info *wlc)
> +{
> +     wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
> +}
> diff --git a/drivers/staging/brcm80211/sys/wlc_pub.h 
> b/drivers/staging/brcm80211/sys/wlc_pub.h
> index 146a690..aff4130 100644
> --- a/drivers/staging/brcm80211/sys/wlc_pub.h
> +++ b/drivers/staging/brcm80211/sys/wlc_pub.h
> @@ -570,6 +570,8 @@ extern void wlc_enable_mac(struct wlc_info *wlc);
>  extern u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate);
>  extern u32 wlc_get_rspec_history(struct wlc_bsscfg *cfg);
>  extern u32 wlc_get_current_highest_rate(struct wlc_bsscfg *cfg);
> +extern void wlc_scan_start(struct wlc_info *wlc);
> +extern void wlc_scan_stop(struct wlc_info *wlc);
>  
>  static inline int wlc_iovar_getuint(struct wlc_info *wlc, const char *name,
>                                   uint *arg)
> 
> _______________________________________________
> stable mailing list
> [email protected]
> http://linux.kernel.org/mailman/listinfo/stable

_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to