net: wireless: bcmdhd: Fix WD wakelock behavior
authorDmitry Shmidt <dimitrysh@google.com>
Tue, 23 Oct 2012 18:39:40 +0000 (11:39 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Wed, 24 Oct 2012 20:18:00 +0000 (13:18 -0700)
Change-Id: I7ebae2be248cbb4bc98e2b448641f65b77a320f4
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Conflicts:

drivers/net/wireless/bcmdhd/dhd_linux.c

drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_linux.c

index 34616d38b861fb52e6b5fd90037176eadffabe25..5160ee12796aa6cca9f8a0ba6ce6921f1d7f0e74 100644 (file)
@@ -301,6 +301,8 @@ 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_rx_timeout_enable(dhd_pub_t *pub, int val);
 extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val);
+extern int dhd_os_wd_wake_lock(dhd_pub_t *pub);
+extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub);
 
 inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp)
 {
@@ -323,8 +325,10 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
 }
 
-#define DHD_OS_WAKE_LOCK(pub)                  dhd_os_wake_lock(pub)
-#define DHD_OS_WAKE_UNLOCK(pub)                dhd_os_wake_unlock(pub)
+#define DHD_OS_WAKE_LOCK(pub)                  dhd_os_wake_lock(pub)
+#define DHD_OS_WAKE_UNLOCK(pub)                        dhd_os_wake_unlock(pub)
+#define DHD_OS_WD_WAKE_LOCK(pub)               dhd_os_wd_wake_lock(pub)
+#define DHD_OS_WD_WAKE_UNLOCK(pub)             dhd_os_wd_wake_unlock(pub)
 #define DHD_OS_WAKE_LOCK_TIMEOUT(pub)          dhd_os_wake_lock_timeout(pub)
 #define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val)   dhd_os_wake_lock_rx_timeout_enable(pub, val)
 #define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_ctrl_timeout_enable(pub, val)
index 0f419a5e1cbc3c8737d2d08379507796f28ccc65..d0b4c1c325c6a5be9793827b9f6b1c9e61ff4da8 100644 (file)
@@ -259,6 +259,7 @@ typedef struct dhd_info {
        struct wake_lock wl_wifi;   /* Wifi wakelock */
        struct wake_lock wl_rxwake; /* Wifi rx wakelock */
        struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */
+       struct wake_lock wl_wdwake; /* Wifi wd wakelock */
 #endif
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
@@ -270,6 +271,7 @@ typedef struct dhd_info {
 #endif
        spinlock_t wakelock_spinlock;
        int wakelock_counter;
+       int wakelock_wd_counter;
        int wakelock_rx_timeout_enable;
        int wakelock_ctrl_timeout_enable;
 
@@ -1697,7 +1699,6 @@ dhd_watchdog_thread(void *data)
                                dhd_os_spin_unlock(&dhd->pub, flags);
                        }
                        dhd_os_sdunlock(&dhd->pub);
-                       DHD_OS_WAKE_UNLOCK(&dhd->pub);
                } else {
                        break;
                }
@@ -1711,9 +1712,7 @@ static void dhd_watchdog(ulong data)
        dhd_info_t *dhd = (dhd_info_t *)data;
        unsigned long flags;
 
-       DHD_OS_WAKE_LOCK(&dhd->pub);
        if (dhd->pub.dongle_reset) {
-               DHD_OS_WAKE_UNLOCK(&dhd->pub);
                return;
        }
 
@@ -1737,7 +1736,6 @@ static void dhd_watchdog(ulong data)
                mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms));
        dhd_os_spin_unlock(&dhd->pub, flags);
        dhd_os_sdunlock(&dhd->pub);
-       DHD_OS_WAKE_UNLOCK(&dhd->pub);
 }
 
 #ifdef DHDTHREAD
@@ -2681,12 +2679,14 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
        /* Initialize Wakelock stuff */
        spin_lock_init(&dhd->wakelock_spinlock);
        dhd->wakelock_counter = 0;
+       dhd->wakelock_wd_counter = 0;
        dhd->wakelock_rx_timeout_enable = 0;
        dhd->wakelock_ctrl_timeout_enable = 0;
 #ifdef CONFIG_HAS_WAKELOCK
        wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
        wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
        wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake");
+       wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake");
 #endif
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
        mutex_init(&dhd->dhd_net_if_mutex);
@@ -2871,12 +2871,12 @@ dhd_bus_start(dhd_pub_t *dhdp)
                dhd->wd_timer_valid = FALSE;
                dhd_os_spin_unlock(&dhd->pub, flags);
                del_timer_sync(&dhd->timer);
-
                DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__));
 #ifdef DHDTHREAD
                if (dhd->threads_only)
                        dhd_os_sdunlock(dhdp);
 #endif /* DHDTHREAD */
+               DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
                return -ENODEV;
        }
 
@@ -2895,6 +2895,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
                if (dhd->threads_only)
                        dhd_os_sdunlock(dhdp);
 #endif /* DHDTHREAD */
+               DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
                return -ENODEV;
        }
 
@@ -3787,10 +3788,15 @@ void dhd_detach(dhd_pub_t *dhdp)
 
        if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) {
 #ifdef CONFIG_HAS_WAKELOCK
+               dhd->wakelock_counter = 0;
+               dhd->wakelock_wd_counter = 0;
+               dhd->wakelock_rx_timeout_enable = 0;
+               dhd->wakelock_ctrl_timeout_enable = 0;
                wake_lock_destroy(&dhd->wl_wifi);
                wake_lock_destroy(&dhd->wl_rxwake);
                wake_lock_destroy(&dhd->wl_ctrlwake);
-#endif
+               wake_lock_destroy(&dhd->wl_wdwake);
+#endif /* CONFIG_HAS_WAKELOCK */
        }
 }
 
@@ -3983,11 +3989,18 @@ dhd_os_wd_timer(void *bus, uint wdtick)
 
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
+       if (!dhd)
+               return;
+
+       if (wdtick)
+               DHD_OS_WD_WAKE_LOCK(pub);
+
        flags = dhd_os_spin_lock(pub);
 
        /* don't start the wd until fw is loaded */
        if (pub->busstate == DHD_BUS_DOWN) {
                dhd_os_spin_unlock(pub, flags);
+               DHD_OS_WD_WAKE_UNLOCK(pub);
                return;
        }
 
@@ -4000,6 +4013,7 @@ dhd_os_wd_timer(void *bus, uint wdtick)
 #else
                del_timer(&dhd->timer);
 #endif /* DHDTHREAD */
+               DHD_OS_WD_WAKE_UNLOCK(pub);
                return;
        }
 
@@ -4877,6 +4891,44 @@ int net_os_wake_unlock(struct net_device *dev)
        return ret;
 }
 
+int dhd_os_wd_wake_lock(dhd_pub_t *pub)
+{
+       dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+       unsigned long flags;
+       int ret = 0;
+
+       if (dhd) {
+               spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+#ifdef CONFIG_HAS_WAKELOCK
+               if (!dhd->wakelock_wd_counter)
+                       wake_lock(&dhd->wl_wdwake);
+#endif
+               dhd->wakelock_wd_counter++;
+               ret = dhd->wakelock_wd_counter;
+               spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+       }
+       return ret;
+}
+
+int dhd_os_wd_wake_unlock(dhd_pub_t *pub)
+{
+       dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+       unsigned long flags;
+       int ret = 0;
+
+       if (dhd) {
+               spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+               if (dhd->wakelock_wd_counter) {
+                       dhd->wakelock_wd_counter = 0;
+#ifdef CONFIG_HAS_WAKELOCK
+                       wake_unlock(&dhd->wl_wdwake);
+#endif
+               }
+               spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+       }
+       return ret;
+}
+
 int dhd_os_check_if_up(void *dhdp)
 {
        dhd_pub_t *pub = (dhd_pub_t *)dhdp;