net: wireless: bcm4329: Fix race conditions for sysioc_thread
authorDmitry Shmidt <dimitrysh@google.com>
Tue, 2 Nov 2010 23:35:22 +0000 (16:35 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Tue, 2 Nov 2010 23:37:17 +0000 (16:37 -0700)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/wl_iw.c

index 4e5ffcbd5237114ae4ba214fb871a389cc055418..d136517c51a47b3248975d0afc87710d67147f63 100644 (file)
@@ -219,6 +219,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;
index d7e72c8d12d201b0907792725f86ff9396101b42..0b52e0373e3eebe5a0a6d58fc51a54bf2771eb14 100644 (file)
@@ -282,6 +282,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;
@@ -1065,9 +1067,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 */
@@ -1102,6 +1106,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);
 }
@@ -1115,6 +1120,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;
@@ -1133,6 +1139,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;
@@ -2119,6 +2126,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;
@@ -3289,3 +3297,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);
+}
index 82164edc6534679568a8916b6e167eb66da1175e..525d3909e7ae6bfcf5ceb7978db2d203759782dc 100644 (file)
@@ -110,8 +110,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,
@@ -1449,6 +1448,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__));
@@ -1458,7 +1458,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);
@@ -1479,7 +1480,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;
 }
 
@@ -1490,7 +1491,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) {
@@ -1498,7 +1501,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;
@@ -1537,7 +1541,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__));
 
@@ -7884,7 +7888,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;
@@ -7893,7 +7897,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)