From 4d58abd0bb3505380c436eeb9d1693bfb9fba449 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 13 Jun 2011 17:33:26 -0700 Subject: [PATCH] net: wireless: bcmdhd: Fix race conditions for sysioc_thread Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 14 +++++++++++--- drivers/net/wireless/bcmdhd/wl_iw.c | 29 +++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 854da51..7d78bae 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -407,7 +407,7 @@ typedef struct dhd_info { struct wake_lock wl_rxwake; /* Wifi rx wakelock */ #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) struct mutex wl_start_lock; /* mutex when START called to prevent any other Linux calls */ #endif spinlock_t wakelock_spinlock; @@ -1205,6 +1205,7 @@ _dhd_sysioc_thread(void *data) break; } + dhd_os_start_lock(&dhd->pub); for (i = 0; i < DHD_MAX_IFS; i++) { if (dhd->iflist[i]) { @@ -1249,6 +1250,8 @@ _dhd_sysioc_thread(void *data) } DHD_OS_WAKE_UNLOCK(&dhd->pub); + dhd_os_start_unlock(&dhd->pub); + } DHD_TRACE(("%s: stopped\n", __FUNCTION__)); complete_and_exit(&tsk->completed, 0); @@ -2563,6 +2566,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + mutex_init(&dhd->wl_start_lock); +#endif dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; /* Attach and link in the protocol */ @@ -3961,24 +3967,26 @@ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 void dhd_os_start_lock(dhd_pub_t *pub) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) dhd_info_t *dhd = (dhd_info_t *)(pub->info); if (dhd) mutex_lock(&dhd->wl_start_lock); +#endif } void dhd_os_start_unlock(dhd_pub_t *pub) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) dhd_info_t *dhd = (dhd_info_t *)(pub->info); if (dhd) mutex_unlock(&dhd->wl_start_lock); +#endif } -#endif #ifdef SOFTAP unsigned long dhd_os_spin_lock(dhd_pub_t *pub) diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index ef713ee..0af6073 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -130,7 +130,6 @@ wl_iw_extra_params_t g_wl_iw_params; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 -static struct mutex wl_start_lock; static struct mutex wl_cache_lock; static struct mutex wl_softap_lock; @@ -1633,6 +1632,7 @@ int wl_control_wl_start(struct net_device *dev) { int ret = 0; + wl_iw_t *iw; WL_TRACE(("Enter %s \n", __FUNCTION__)); @@ -1640,8 +1640,15 @@ wl_control_wl_start(struct net_device *dev) WL_ERROR(("%s: dev is null\n", __FUNCTION__)); return -1; } - - DHD_OS_MUTEX_LOCK(&wl_start_lock); + + iw = *(wl_iw_t **)netdev_priv(dev); + + if (!iw) { + WL_ERROR(("%s: wl is null\n", __FUNCTION__)); + return -1; + } + + dhd_os_start_lock(iw->pub); if (g_onoff == G_WLAN_SET_OFF) { dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); @@ -1662,7 +1669,7 @@ wl_control_wl_start(struct net_device *dev) } WL_TRACE(("Exited %s\n", __FUNCTION__)); - DHD_OS_MUTEX_UNLOCK(&wl_start_lock); + dhd_os_start_unlock(iw->pub); return ret; } @@ -1674,6 +1681,7 @@ wl_iw_control_wl_off( ) { int ret = 0; + wl_iw_t *iw; WL_TRACE(("Enter %s\n", __FUNCTION__)); @@ -1682,7 +1690,14 @@ wl_iw_control_wl_off( return -1; } - DHD_OS_MUTEX_LOCK(&wl_start_lock); + iw = *(wl_iw_t **)netdev_priv(dev); + + if (!iw) { + WL_ERROR(("%s: wl is null\n", __FUNCTION__)); + return -1; + } + + dhd_os_start_lock(iw->pub); #ifdef SOFTAP ap_cfg_running = FALSE; @@ -1718,7 +1733,6 @@ wl_iw_control_wl_off( sdioh_stop(NULL); #endif - net_os_set_dtim_skip(dev, 0); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); @@ -1726,7 +1740,7 @@ wl_iw_control_wl_off( wl_iw_send_priv_event(dev, "STOP"); } - DHD_OS_MUTEX_UNLOCK(&wl_start_lock); + dhd_os_start_unlock(iw->pub); WL_TRACE(("Exited %s\n", __FUNCTION__)); @@ -8475,7 +8489,6 @@ wl_iw_attach(struct net_device *dev, void * dhdp) #endif DHD_OS_MUTEX_INIT(&wl_cache_lock); - DHD_OS_MUTEX_INIT(&wl_start_lock); DHD_OS_MUTEX_INIT(&wl_softap_lock); #if defined(WL_IW_USE_ISCAN) -- 2.7.4