diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2010-11-02 16:35:22 -0700 |
---|---|---|
committer | Jonas ABERG <jonas.aberg@stericsson.com> | 2011-04-01 13:23:44 +0200 |
commit | 5e5a2fd34de09353f5337a9de5e42743490b1b9a (patch) | |
tree | aa1ff696bee2e371470287dc3ea4c0a6effa08ce /drivers/net | |
parent | 51df0e4d1eed30a131116d2812b8ec0ca947c444 (diff) |
net: wireless: bcm4329: Fix race conditions for sysioc_thread
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Change-Id: I6a651b0267946e54762f2df33909c9dc5a41a7c0
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/19491
Tested-by: Piotr TOMASZEWSKI <piotr.tomaszewski@stericsson.com>
Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/bcm4329/dhd.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/bcm4329/dhd_linux.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/bcm4329/wl_iw.c | 19 |
3 files changed, 38 insertions, 8 deletions
diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h index cc7e8cb286b..5d8dc32fd30 100644 --- a/drivers/net/wireless/bcm4329/dhd.h +++ b/drivers/net/wireless/bcm4329/dhd.h @@ -218,6 +218,9 @@ extern int dhd_os_wake_unlock(dhd_pub_t *pub); extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); extern int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub); +extern void dhd_os_start_lock(dhd_pub_t *pub); +extern void dhd_os_start_unlock(dhd_pub_t *pub); + typedef struct dhd_if_event { uint8 ifidx; uint8 action; diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index f687b31e333..ba185752e78 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -281,6 +281,8 @@ typedef struct dhd_info { int hang_was_sent; + struct mutex wl_start_lock; + /* Thread to issue ioctl for multicast */ long sysioc_pid; struct semaphore sysioc_sem; @@ -992,9 +994,11 @@ _dhd_sysioc_thread(void *data) DAEMONIZE("dhd_sysioc"); while (down_interruptible(&dhd->sysioc_sem) == 0) { + dhd_os_start_lock(&dhd->pub); dhd_os_wake_lock(&dhd->pub); for (i = 0; i < DHD_MAX_IFS; i++) { if (dhd->iflist[i]) { + DHD_TRACE(("%s: interface %d\n",__FUNCTION__, i)); #ifdef SOFTAP in_ap = (ap_net_dev != NULL); #endif /* SOFTAP */ @@ -1029,6 +1033,7 @@ _dhd_sysioc_thread(void *data) } } dhd_os_wake_unlock(&dhd->pub); + dhd_os_start_unlock(&dhd->pub); } complete_and_exit(&dhd->sysioc_exited, 0); } @@ -1042,6 +1047,7 @@ dhd_set_mac_address(struct net_device *dev, void *addr) struct sockaddr *sa = (struct sockaddr *)addr; int ifidx; + DHD_TRACE(("%s: Enter\n",__FUNCTION__)); ifidx = dhd_net2idx(dhd, dev); if (ifidx == DHD_BAD_IF) return -1; @@ -1060,6 +1066,7 @@ dhd_set_multicast_list(struct net_device *dev) dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ifidx; + DHD_TRACE(("%s: Enter\n",__FUNCTION__)); ifidx = dhd_net2idx(dhd, dev); if (ifidx == DHD_BAD_IF) return; @@ -2046,6 +2053,7 @@ 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 + mutex_init(&dhd->wl_start_lock); /* Link to info module */ dhd->pub.info = dhd; @@ -3216,3 +3224,19 @@ int net_os_send_hang_message(struct net_device *dev) } return ret; } + +void dhd_os_start_lock(dhd_pub_t *pub) +{ + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + + if (dhd) + mutex_lock(&dhd->wl_start_lock); +} + +void dhd_os_start_unlock(dhd_pub_t *pub) +{ + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + + if (dhd) + mutex_unlock(&dhd->wl_start_lock); +} diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 070c3e32531..14477ee6edc 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -109,8 +109,7 @@ static int wl_iw_softap_deassoc_stations(struct net_device *dev); } while (0) static int g_onoff = G_WLAN_SET_ON; -wl_iw_extra_params_t g_wl_iw_params; -static struct mutex wl_start_lock; +wl_iw_extra_params_t g_wl_iw_params; static struct mutex wl_cache_lock; extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, @@ -1347,6 +1346,7 @@ wl_iw_send_priv_event( int wl_control_wl_start(struct net_device *dev) { + wl_iw_t *iw; int ret = 0; WL_TRACE(("Enter %s \n", __FUNCTION__)); @@ -1356,7 +1356,8 @@ wl_control_wl_start(struct net_device *dev) return -1; } - mutex_lock(&wl_start_lock); + iw = *(wl_iw_t **)netdev_priv(dev); + dhd_os_start_lock(iw->pub); if (g_onoff == G_WLAN_SET_OFF) { dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); @@ -1377,7 +1378,7 @@ wl_control_wl_start(struct net_device *dev) } WL_TRACE(("Exited %s \n", __FUNCTION__)); - mutex_unlock(&wl_start_lock); + dhd_os_start_unlock(iw->pub); return ret; } @@ -1388,7 +1389,9 @@ wl_iw_control_wl_off( struct iw_request_info *info ) { + wl_iw_t *iw; int ret = 0; + WL_TRACE(("Enter %s\n", __FUNCTION__)); if (!dev) { @@ -1396,7 +1399,8 @@ wl_iw_control_wl_off( return -1; } - mutex_lock(&wl_start_lock); + iw = *(wl_iw_t **)netdev_priv(dev); + dhd_os_start_lock(iw->pub); #ifdef SOFTAP ap_cfg_running = FALSE; @@ -1435,7 +1439,7 @@ wl_iw_control_wl_off( wl_iw_send_priv_event(dev, "STOP"); } - mutex_unlock(&wl_start_lock); + dhd_os_start_unlock(iw->pub); WL_TRACE(("Exited %s\n", __FUNCTION__)); @@ -7753,7 +7757,7 @@ wl_iw_bt_init(struct net_device *dev) return 0; } -int wl_iw_attach(struct net_device *dev, void * dhdp) +int wl_iw_attach(struct net_device *dev, void *dhdp) { int params_size; wl_iw_t *iw; @@ -7762,7 +7766,6 @@ int wl_iw_attach(struct net_device *dev, void * dhdp) #endif mutex_init(&wl_cache_lock); - mutex_init(&wl_start_lock); #if defined(WL_IW_USE_ISCAN) if (!dev) |