diff options
-rw-r--r-- | drivers/cpufreq/cpufreq_interactive.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/bcm4329/dhd_linux.c | 80 | ||||
-rw-r--r-- | drivers/net/wireless/bcm4329/dhd_sdio.c | 80 | ||||
-rw-r--r-- | drivers/net/wireless/bcm4329/wl_iw.c | 16 |
4 files changed, 105 insertions, 94 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 6069ca20a014..4909c7bb741b 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -180,6 +180,7 @@ static void cpufreq_interactive_timer(unsigned long data) u64 now_idle; unsigned int new_freq; unsigned int index; + unsigned long flags; /* * Once pcpu->timer_run_time is updated to >= pcpu->idle_exit_time, @@ -280,18 +281,18 @@ static void cpufreq_interactive_timer(unsigned long data) if (new_freq < pcpu->target_freq) { pcpu->target_freq = new_freq; - spin_lock(&down_cpumask_lock); + spin_lock_irqsave(&down_cpumask_lock, flags); cpumask_set_cpu(data, &down_cpumask); - spin_unlock(&down_cpumask_lock); + spin_unlock_irqrestore(&down_cpumask_lock, flags); queue_work(down_wq, &freq_scale_down_work); } else { pcpu->target_freq = new_freq; #if DEBUG up_request_time = ktime_to_us(ktime_get()); #endif - spin_lock(&up_cpumask_lock); + spin_lock_irqsave(&up_cpumask_lock, flags); cpumask_set_cpu(data, &up_cpumask); - spin_unlock(&up_cpumask_lock); + spin_unlock_irqrestore(&up_cpumask_lock, flags); wake_up_process(up_task); } @@ -423,6 +424,7 @@ static int cpufreq_interactive_up_task(void *data) { unsigned int cpu; cpumask_t tmp_mask; + unsigned long flags; struct cpufreq_interactive_cpuinfo *pcpu; #if DEBUG @@ -433,16 +435,16 @@ static int cpufreq_interactive_up_task(void *data) while (1) { set_current_state(TASK_INTERRUPTIBLE); - spin_lock(&up_cpumask_lock); + spin_lock_irqsave(&up_cpumask_lock, flags); if (cpumask_empty(&up_cpumask)) { - spin_unlock(&up_cpumask_lock); + spin_unlock_irqrestore(&up_cpumask_lock, flags); schedule(); if (kthread_should_stop()) break; - spin_lock(&up_cpumask_lock); + spin_lock_irqsave(&up_cpumask_lock, flags); } set_current_state(TASK_RUNNING); @@ -461,7 +463,7 @@ static int cpufreq_interactive_up_task(void *data) tmp_mask = up_cpumask; cpumask_clear(&up_cpumask); - spin_unlock(&up_cpumask_lock); + spin_unlock_irqrestore(&up_cpumask_lock, flags); for_each_cpu(cpu, &tmp_mask) { pcpu = &per_cpu(cpuinfo, cpu); @@ -488,12 +490,13 @@ static void cpufreq_interactive_freq_down(struct work_struct *work) { unsigned int cpu; cpumask_t tmp_mask; + unsigned long flags; struct cpufreq_interactive_cpuinfo *pcpu; - spin_lock(&down_cpumask_lock); + spin_lock_irqsave(&down_cpumask_lock, flags); tmp_mask = down_cpumask; cpumask_clear(&down_cpumask); - spin_unlock(&down_cpumask_lock); + spin_unlock_irqrestore(&down_cpumask_lock, flags); for_each_cpu(cpu, &tmp_mask) { pcpu = &per_cpu(cpuinfo, cpu); diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index 472b992751e7..b6bb7d11b79f 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -1399,22 +1399,24 @@ dhd_watchdog_thread(void *data) /* Run until signal received */ while (1) { if (down_interruptible (&dhd->watchdog_sem) == 0) { - + dhd_os_sdlock(&dhd->pub); if (dhd->pub.dongle_reset == FALSE) { + DHD_TIMER(("%s:\n", __FUNCTION__)); /* Call the bus module watchdog */ dhd_bus_watchdog(&dhd->pub); - } - /* Count the tick for reference */ - dhd->pub.tickcnt++; - /* Reschedule the watchdog */ - if (dhd->wd_timer_valid) - mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); + /* Count the tick for reference */ + dhd->pub.tickcnt++; + /* Reschedule the watchdog */ + if (dhd->wd_timer_valid) + mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); + } + dhd_os_sdunlock(&dhd->pub); dhd_os_wake_unlock(&dhd->pub); - } - else + } else { break; + } } complete_and_exit(&dhd->watchdog_exited, 0); @@ -1426,11 +1428,17 @@ dhd_watchdog(ulong data) dhd_info_t *dhd = (dhd_info_t *)data; dhd_os_wake_lock(&dhd->pub); + if (dhd->pub.dongle_reset) { + dhd_os_wake_unlock(&dhd->pub); + return; + } + if (dhd->watchdog_pid >= 0) { up(&dhd->watchdog_sem); return; } + dhd_os_sdlock(&dhd->pub); /* Call the bus module watchdog */ dhd_bus_watchdog(&dhd->pub); @@ -1440,6 +1448,7 @@ dhd_watchdog(ulong data) /* Reschedule the watchdog */ if (dhd->wd_timer_valid) mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); + dhd_os_sdunlock(&dhd->pub); dhd_os_wake_unlock(&dhd->pub); } @@ -2198,8 +2207,8 @@ dhd_bus_start(dhd_pub_t *dhdp) #if defined(OOB_INTR_ONLY) /* Host registration for OOB interrupt */ if (bcmsdh_register_oob_intr(dhdp)) { - del_timer_sync(&dhd->timer); dhd->wd_timer_valid = FALSE; + del_timer_sync(&dhd->timer); DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__)); return -ENODEV; } @@ -2210,8 +2219,8 @@ dhd_bus_start(dhd_pub_t *dhdp) /* If bus is not ready, can't come up */ if (dhd->pub.busstate != DHD_BUS_DATA) { - del_timer_sync(&dhd->timer); dhd->wd_timer_valid = FALSE; + del_timer_sync(&dhd->timer); DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__)); return -ENODEV; } @@ -2420,8 +2429,8 @@ dhd_bus_detach(dhd_pub_t *dhdp) #endif /* defined(OOB_INTR_ONLY) */ /* Clear the watchdog timer */ - del_timer_sync(&dhd->timer); dhd->wd_timer_valid = FALSE; + del_timer_sync(&dhd->timer); } } } @@ -2687,29 +2696,28 @@ void dhd_os_wd_timer(void *bus, uint wdtick) { dhd_pub_t *pub = bus; - static uint save_dhd_watchdog_ms = 0; dhd_info_t *dhd = (dhd_info_t *)pub->info; + unsigned long flags; + int del_timer_flag = FALSE; - /* don't start the wd until fw is loaded */ - if (pub->busstate == DHD_BUS_DOWN) - return; + flags = dhd_os_spin_lock(pub); - /* Totally stop the timer */ - if (!wdtick && dhd->wd_timer_valid == TRUE) { - del_timer_sync(&dhd->timer); - dhd->wd_timer_valid = FALSE; - save_dhd_watchdog_ms = wdtick; - return; + /* don't start the wd until fw is loaded */ + if (pub->busstate != DHD_BUS_DOWN) { + if (wdtick) { + dhd_watchdog_ms = (uint)wdtick; + dhd->wd_timer_valid = TRUE; + /* Re arm the timer, at last watchdog period */ + mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); + } else if (dhd->wd_timer_valid == TRUE) { + /* Totally stop the timer */ + dhd->wd_timer_valid = FALSE; + del_timer_flag = TRUE; + } } - - if (wdtick) { - dhd_watchdog_ms = (uint)wdtick; - - /* Re arm the timer, at last watchdog period */ - mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); - - dhd->wd_timer_valid = TRUE; - save_dhd_watchdog_ms = wdtick; + dhd_os_spin_unlock(pub, flags); + if (del_timer_flag) { + del_timer_sync(&dhd->timer); } } @@ -2927,20 +2935,12 @@ dhd_dev_reset(struct net_device *dev, uint8 flag) dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - /* Turning off watchdog */ - if (flag) - dhd_os_wd_timer(&dhd->pub, 0); - ret = dhd_bus_devreset(&dhd->pub, flag); if (ret) { DHD_ERROR(("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret)); return ret; } - - /* Turning on watchdog back */ - if (!flag) - dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms); - DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__)); + DHD_ERROR(("%s: WLAN %s DONE\n", __FUNCTION__, flag ? "OFF" : "ON")); return ret; } diff --git a/drivers/net/wireless/bcm4329/dhd_sdio.c b/drivers/net/wireless/bcm4329/dhd_sdio.c index 7494e3836732..ac46ca91eaeb 100644 --- a/drivers/net/wireless/bcm4329/dhd_sdio.c +++ b/drivers/net/wireless/bcm4329/dhd_sdio.c @@ -438,7 +438,7 @@ static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh, void * regsva, uint16 devid); static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh); static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh); -static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh); +static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, int reset_flag); static uint process_nvram_vars(char *varbuf, uint len); @@ -705,6 +705,7 @@ dhdsdio_sdclk(dhd_bus_t *bus, bool on) static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) { + int ret = BCME_OK; #ifdef DHD_DEBUG uint oldstate = bus->clkstate; #endif /* DHD_DEBUG */ @@ -717,7 +718,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); bus->activity = TRUE; } - return BCME_OK; + return ret; } switch (target) { @@ -726,29 +727,32 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) if (bus->clkstate == CLK_NONE) dhdsdio_sdclk(bus, TRUE); /* Now request HT Avail on the backplane */ - dhdsdio_htclk(bus, TRUE, pendok); - dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); - bus->activity = TRUE; + ret = dhdsdio_htclk(bus, TRUE, pendok); + if (ret == BCME_OK) { + dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); + bus->activity = TRUE; + } break; case CLK_SDONLY: /* Remove HT request, or bring up SD clock */ if (bus->clkstate == CLK_NONE) - dhdsdio_sdclk(bus, TRUE); + ret = dhdsdio_sdclk(bus, TRUE); else if (bus->clkstate == CLK_AVAIL) - dhdsdio_htclk(bus, FALSE, FALSE); + ret = dhdsdio_htclk(bus, FALSE, FALSE); else DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n", bus->clkstate, target)); - dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); + if (ret == BCME_OK) + dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); break; case CLK_NONE: /* Make sure to remove HT request */ if (bus->clkstate == CLK_AVAIL) - dhdsdio_htclk(bus, FALSE, FALSE); + ret = dhdsdio_htclk(bus, FALSE, FALSE); /* Now remove the SD clock */ - dhdsdio_sdclk(bus, FALSE); + ret = dhdsdio_sdclk(bus, FALSE); dhd_os_wd_timer(bus->dhd, 0); break; } @@ -756,7 +760,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate)); #endif /* DHD_DEBUG */ - return BCME_OK; + return ret; } int @@ -2782,23 +2786,24 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) dhd_timeout_t tmo; uint retries = 0; uint8 ready, enable; - int err, ret = 0; + int err, ret = BCME_ERROR; uint8 saveclk; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); ASSERT(bus->dhd); if (!bus->dhd) - return 0; + return BCME_OK; if (enforce_mutex) dhd_os_sdlock(bus->dhd); /* Make sure backplane clock is on, needed to generate F2 interrupt */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - if (bus->clkstate != CLK_AVAIL) + err = dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + if ((err != BCME_OK) || (bus->clkstate != CLK_AVAIL)) { + DHD_ERROR(("%s: Failed to set backplane clock: err %d\n", __FUNCTION__, err)); goto exit; - + } /* Force clocks on backplane to be sure F2 interrupt propagates */ saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); @@ -2873,6 +2878,7 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) if (dhdp->busstate != DHD_BUS_DATA) dhdsdio_clkctl(bus, CLK_NONE, FALSE); + ret = BCME_OK; exit: if (enforce_mutex) dhd_os_sdunlock(bus->dhd); @@ -4631,8 +4637,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) if (bus->sleeping) return FALSE; - dhd_os_sdlock(bus->dhd); - /* Poll period: check device if appropriate. */ if (bus->poll && (++bus->polltick >= bus->pollrate)) { uint32 intstatus = 0; @@ -4702,8 +4706,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) } } - dhd_os_sdunlock(bus->dhd); - return bus->ipend; } @@ -5299,7 +5301,7 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh) if (bus->dhd) { - dhdsdio_release_dongle(bus, osh); + dhdsdio_release_dongle(bus, osh, TRUE); dhd_detach(bus->dhd); bus->dhd = NULL; @@ -5343,11 +5345,11 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) static void -dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh) +dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, int reset_flag) { DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - if (bus->dhd && bus->dhd->dongle_reset) + if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag) return; if (bus->sih) { @@ -5797,17 +5799,19 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) if (flag == TRUE) { if (!bus->dhd->dongle_reset) { + dhd_os_sdlock(dhdp); + /* Turning off watchdog */ + dhd_os_wd_timer(dhdp, 0); #if !defined(IGNORE_ETH0_DOWN) /* Force flow control as protection when stop come before ifconfig_down */ dhd_txflowcontrol(bus->dhd, 0, ON); #endif /* !defined(IGNORE_ETH0_DOWN) */ /* Expect app to have torn down any connection before calling */ /* Stop the bus, disable F2 */ - dhd_os_sdlock(dhdp); dhd_bus_stop(bus, FALSE); /* Clean tx/rx buffer pointers, detach from the dongle */ - dhdsdio_release_dongle(bus, bus->dhd->osh); + dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE); bus->dhd->dongle_reset = TRUE; bus->dhd->up = FALSE; @@ -5838,21 +5842,25 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh)) { /* Re-init bus, enable F2 transfer */ - dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); - + bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); + if (bcmerror == BCME_OK) { #if defined(OOB_INTR_ONLY) - dhd_enable_oob_intr(bus, TRUE); + dhd_enable_oob_intr(bus, TRUE); #endif /* defined(OOB_INTR_ONLY) */ - - bus->dhd->dongle_reset = FALSE; - bus->dhd->up = TRUE; - + bus->dhd->dongle_reset = FALSE; + bus->dhd->up = TRUE; #if !defined(IGNORE_ETH0_DOWN) - /* Restore flow control */ - dhd_txflowcontrol(bus->dhd, 0, OFF); -#endif + /* Restore flow control */ + dhd_txflowcontrol(bus->dhd, 0, OFF); +#endif + /* Turning on watchdog back */ + dhd_os_wd_timer(dhdp, dhd_watchdog_ms); - DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); + DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); + } else { + dhd_bus_stop(bus, FALSE); + dhdsdio_release_dongle(bus, bus->dhd->osh, FALSE); + } } else bcmerror = BCME_SDIO_ERROR; } else diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index e6a8c61aff9d..8187bd1cb0ca 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -1532,13 +1532,13 @@ wl_control_wl_start(struct net_device *dev) ret = dhd_dev_reset(dev, 0); + if (ret == BCME_OK) { #if defined(BCMLXSDMMC) - sdioh_start(NULL, 1); + sdioh_start(NULL, 1); #endif - - dhd_dev_init_ioctl(dev); - - g_onoff = G_WLAN_SET_ON; + dhd_dev_init_ioctl(dev); + g_onoff = G_WLAN_SET_ON; + } } WL_TRACE(("Exited %s \n", __FUNCTION__)); @@ -1624,10 +1624,10 @@ wl_iw_control_wl_on( WL_TRACE(("Enter %s \n", __FUNCTION__)); - if ((ret = wl_control_wl_start(dev)) == BCME_SDIO_ERROR) { + if ((ret = wl_control_wl_start(dev)) != BCME_OK) { WL_ERROR(("%s failed first attemp\n", __FUNCTION__)); - bcm_mdelay(100); - if ((ret = wl_control_wl_start(dev)) == BCME_SDIO_ERROR) { + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); + if ((ret = wl_control_wl_start(dev)) != BCME_OK) { WL_ERROR(("%s failed second attemp\n", __FUNCTION__)); net_os_send_hang_message(dev); return ret; |