summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c23
-rw-r--r--drivers/net/wireless/bcm4329/dhd_linux.c80
-rw-r--r--drivers/net/wireless/bcm4329/dhd_sdio.c80
-rw-r--r--drivers/net/wireless/bcm4329/wl_iw.c16
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;