summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2009-11-11 10:34:26 -0800
committerDmitry Shmidt <dimitrysh@google.com>2009-11-11 10:34:26 -0800
commitb4ace791eb574f589c53be582ea0d14e1a85ff09 (patch)
tree5293f8ec8ea0c05d6a6cfbee1fe42a345efd0c27
parent492884be0b302c6c6ea51b360c1f7b0996d96a8b (diff)
downloadwlan-b4ace791eb574f589c53be582ea0d14e1a85ff09.tar.gz
bcm4329: Sync with kernel tree (b/2249878)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_linux.c2
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c2
-rw-r--r--bcm4329/src/dhd/sys/dhd.h53
-rw-r--r--bcm4329/src/dhd/sys/dhd_cdc.c7
-rw-r--r--bcm4329/src/dhd/sys/dhd_common.c8
-rw-r--r--bcm4329/src/dhd/sys/dhd_custom_gpio.c18
-rw-r--r--bcm4329/src/dhd/sys/dhd_linux.c323
-rw-r--r--bcm4329/src/dhd/sys/dhd_sdio.c31
-rw-r--r--bcm4329/src/shared/linux_osl.c20
-rw-r--r--bcm4329/src/wl/sys/wl_iw.c193
-rw-r--r--bcm4329/src/wl/sys/wl_iw.h6
11 files changed, 482 insertions, 181 deletions
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
index 8ddffc6..5742ea5 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
@@ -544,8 +544,6 @@ static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
- WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
-
dhdsdio_isr((void *)dhdp->bus);
return IRQ_HANDLED;
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
index a13a35c..d5da588 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
@@ -1066,6 +1066,8 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
extern int
sdioh_abort(sdioh_info_t *sd, uint func)
{
+ char t_func = (char) func;
+
sd_trace(("%s: Enter\n", __FUNCTION__));
#if defined(MMC_SDIO_ABORT)
diff --git a/bcm4329/src/dhd/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h
index 004f7a3..bd05923 100644
--- a/bcm4329/src/dhd/sys/dhd.h
+++ b/bcm4329/src/dhd/sys/dhd.h
@@ -46,17 +46,15 @@
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
-#include <linux/wakelock.h>
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
+
/* The kernel threading is sdio-specific */
#else /* LINUX */
#define ENOMEM 1
-#define EFAULT 2
+#define EFAULT 2
#define EINVAL 3
-#define EIO 4
+#define EIO 4
#define ETIMEDOUT 5
-#define ERESTARTSYS 6
+#define ERESTARTSYS 6
#endif /* LINUX */
#include <wlioctl.h>
@@ -149,9 +147,6 @@ typedef struct dhd_pub {
int dongle_error;
uint8 country_code[WLC_CNTRY_BUF_SZ];
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
- struct wake_lock wakelock[WAKE_LOCK_MAX];
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
} dhd_pub_t;
#ifdef NDIS60
@@ -208,41 +203,11 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
-inline static void WAKE_LOCK_INIT(dhd_pub_t * dhdp, int index, char * y)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
- wake_lock_init(&dhdp->wakelock[index], WAKE_LOCK_SUSPEND, y);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
-}
-
-inline static void WAKE_LOCK(dhd_pub_t * dhdp, int index)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
- wake_lock(&dhdp->wakelock[index]);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
-}
-
-inline static void WAKE_UNLOCK(dhd_pub_t * dhdp, int index)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
- wake_unlock(&dhdp->wakelock[index]);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
-}
-
-inline static void WAKE_LOCK_TIMEOUT(dhd_pub_t * dhdp, int index, long time)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
- wake_lock_timeout(&dhdp->wakelock[index], time);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
-}
-
-inline static void WAKE_LOCK_DESTROY(dhd_pub_t * dhdp, int index)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
- wake_lock_destroy(&dhdp->wakelock[index]);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
-}
-
+/* Wakelock Functions */
+extern int dhd_os_wake_lock(dhd_pub_t *pub);
+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);
typedef struct dhd_if_event {
uint8 ifidx;
diff --git a/bcm4329/src/dhd/sys/dhd_cdc.c b/bcm4329/src/dhd/sys/dhd_cdc.c
index e503b50..e433667 100644
--- a/bcm4329/src/dhd/sys/dhd_cdc.c
+++ b/bcm4329/src/dhd/sys/dhd_cdc.c
@@ -73,9 +73,12 @@ dhdcdc_msg(dhd_pub_t *dhd)
{
dhd_prot_t *prot = dhd->prot;
int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
+ int ret;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ dhd_os_wake_lock(dhd);
+
/* NOTE : cdc->msg.len holds the desired length of the buffer to be
* returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
* is actually sent to the dongle
@@ -84,7 +87,9 @@ dhdcdc_msg(dhd_pub_t *dhd)
len = CDC_MAX_MSG_SIZE;
/* Send request */
- return dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
+ ret = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
+ dhd_os_wake_unlock(dhd);
+ return ret;
}
static int
diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c
index eff07f2..f840aba 100644
--- a/bcm4329/src/dhd/sys/dhd_common.c
+++ b/bcm4329/src/dhd/sys/dhd_common.c
@@ -101,8 +101,16 @@ dhd_common_init(void)
* first time that the driver is initialized vs subsequent initializations.
*/
dhd_msg_level = DHD_ERROR_VAL;
+#ifdef CONFIG_BCM4329_FW_PATH
+ strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN-1);
+#else
fw_path[0] = '\0';
+#endif
+#ifdef CONFIG_BCM4329_NVRAM_PATH
+ strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN-1);
+#else
nv_path[0] = '\0';
+#endif
}
static int
diff --git a/bcm4329/src/dhd/sys/dhd_custom_gpio.c b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
index 4da20ab..f39acda 100644
--- a/bcm4329/src/dhd/sys/dhd_custom_gpio.c
+++ b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
@@ -43,6 +43,12 @@ extern void bcm_wlan_power_off(int);
extern void bcm_wlan_power_on(int);
#endif /* CUSTOMER_HW */
+#ifdef CUSTOMER_HW2
+int wifi_set_carddetect(int on);
+int wifi_set_power(int on, unsigned long msec);
+int wifi_get_irq_number(void);
+#endif
+
#if defined(OOB_INTR_ONLY)
#if defined(BCMLXSDMMC)
@@ -57,7 +63,10 @@ MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
int dhd_customer_oob_irq_map(void)
{
-int host_oob_irq;
+ int host_oob_irq;
+#ifdef CUSTOMER_HW2
+ host_oob_irq = wifi_get_irq_number();
+#else
#if defined(CUSTOM_OOB_GPIO_NUM)
if (dhd_oob_gpio_num < 0) {
dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
@@ -75,6 +84,7 @@ int host_oob_irq;
/* TODO : move it mmc specific code */
host_oob_irq = sdioh_mmc_irq(dhd_oob_gpio_num);
+#endif
return (host_oob_irq);
}
#endif /* defined(OOB_INTR_ONLY) */
@@ -90,6 +100,9 @@ dhd_customer_gpio_wlan_ctrl(int onoff)
#ifdef CUSTOMER_HW
bcm_wlan_power_off(2);
#endif /* CUSTOMER_HW */
+#ifdef CUSTOMER_HW2
+ wifi_set_power(0, 0);
+#endif
WL_ERROR(("=========== WLAN placed in RESET ========\n"));
break;
@@ -99,6 +112,9 @@ dhd_customer_gpio_wlan_ctrl(int onoff)
#ifdef CUSTOMER_HW
bcm_wlan_power_on(2);
#endif /* CUSTOMER_HW */
+#ifdef CUSTOMER_HW2
+ wifi_set_power(1, 0);
+#endif
WL_ERROR(("=========== WLAN going back to live ========\n"));
break;
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index e5f84c0..81e3cf6 100644
--- a/bcm4329/src/dhd/sys/dhd_linux.c
+++ b/bcm4329/src/dhd/sys/dhd_linux.c
@@ -57,21 +57,62 @@
#include <dhd_bus.h>
#include <dhd_proto.h>
#include <dhd_dbg.h>
+#include <wl_iw.h>
+#ifdef CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#endif
+#include <linux/freezer.h>
#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-/* To make sdio host driver ignore card insert/remove information */
-struct wifi_platform_data {
- char *name;
- int (*set_power)(int val);
- int (*set_reset)(int val);
- int (*set_carddetect)(int val);
- void *(*mem_prealloc)(int section, unsigned long size);
-};
+#include <linux/wifi_tiwlan.h>
struct semaphore wifi_control_sem;
struct dhd_bus *g_bus;
static struct wifi_platform_data *wifi_control_data = NULL;
+static struct resource *wifi_irqres = NULL;
+
+int wifi_get_irq_number(void)
+{
+ if (wifi_irqres)
+ return (int)wifi_irqres->start;
+#ifdef CUSTOM_OOB_GPIO_NUM
+ return CUSTOM_OOB_GPIO_NUM;
+#else
+ return -1;
+#endif
+}
+
+int wifi_set_carddetect(int on)
+{
+ printk("%s = %d\n", __FUNCTION__, on);
+ if (wifi_control_data && wifi_control_data->set_carddetect) {
+ wifi_control_data->set_carddetect(on);
+ }
+ return 0;
+}
+
+int wifi_set_power(int on, unsigned long msec)
+{
+ printk("%s = %d\n", __FUNCTION__, on);
+ if (wifi_control_data && wifi_control_data->set_power) {
+ wifi_control_data->set_power(on);
+ }
+ if (msec)
+ mdelay(msec);
+ return 0;
+}
+
+int wifi_set_reset(int on, unsigned long msec)
+{
+ printk("%s = %d\n", __FUNCTION__, on);
+ if (wifi_control_data && wifi_control_data->set_reset) {
+ wifi_control_data->set_reset(on);
+ }
+ if (msec)
+ mdelay(msec);
+ return 0;
+}
static int wifi_probe(struct platform_device *pdev)
{
@@ -79,13 +120,11 @@ static int wifi_probe(struct platform_device *pdev)
(struct wifi_platform_data *)(pdev->dev.platform_data);
DHD_TRACE(("## %s\n", __FUNCTION__));
- if (wifi_ctrl) {
- wifi_control_data = wifi_ctrl;
- if (wifi_ctrl->set_power)
- wifi_ctrl->set_power(1); /* Power On */
- if (wifi_ctrl->set_carddetect)
- wifi_ctrl->set_carddetect(1); /* CardDetect (0->1) */
- }
+ wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
+ wifi_control_data = wifi_ctrl;
+
+ wifi_set_power(1, 0); /* Power On */
+ wifi_set_carddetect(1); /* CardDetect (0->1) */
up(&wifi_control_sem);
return 0;
@@ -97,12 +136,11 @@ static int wifi_remove(struct platform_device *pdev)
(struct wifi_platform_data *)(pdev->dev.platform_data);
DHD_TRACE(("## %s\n", __FUNCTION__));
- if (wifi_ctrl) {
- if (wifi_ctrl->set_carddetect)
- wifi_ctrl->set_carddetect(0); /* CardDetect (1->0) */
- if (wifi_ctrl->set_power)
- wifi_ctrl->set_power(0); /* Power Off */
- }
+ wifi_control_data = wifi_ctrl;
+
+ wifi_set_carddetect(0); /* CardDetect (1->0) */
+ wifi_set_power(0, 0); /* Power Off */
+
up(&wifi_control_sem);
return 0;
}
@@ -114,7 +152,7 @@ static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
static int wifi_resume(struct platform_device *pdev)
{
DHD_TRACE(("##> %s\n", __FUNCTION__));
- return 0;
+ return 0;
}
static struct platform_driver wifi_device = {
@@ -123,7 +161,7 @@ static struct platform_driver wifi_device = {
.suspend = wifi_suspend,
.resume = wifi_resume,
.driver = {
- .name = "msm_wifi",
+ .name = "bcm4329_wlan",
}
};
@@ -214,6 +252,15 @@ typedef struct dhd_info {
struct semaphore dpc_sem;
struct completion dpc_exited;
+ /* Wakelocks */
+#ifdef CONFIG_HAS_WAKELOCK
+ struct wake_lock wl_wifi; /* Wifi wakelock */
+ struct wake_lock wl_rxwake; /* Wifi rx wakelock */
+#endif
+ spinlock_t wl_lock;
+ int wl_count;
+ int wl_packet;
+
/* Thread to issue ioctl for multicast */
long sysioc_pid;
struct semaphore sysioc_sem;
@@ -728,9 +775,12 @@ _dhd_sysioc_thread(void *data)
dhd_info_t *dhd = (dhd_info_t *)data;
int i;
+ set_freezable();
+
DAEMONIZE("dhd_sysioc");
while (down_interruptible(&dhd->sysioc_sem) == 0) {
+ dhd_os_wake_lock(&dhd->pub);
for (i = 0; i < DHD_MAX_IFS; i++) {
if (dhd->iflist[i]) {
if (dhd->iflist[i]->state)
@@ -745,6 +795,7 @@ _dhd_sysioc_thread(void *data)
}
}
}
+ dhd_os_wake_unlock(&dhd->pub);
}
complete_and_exit(&dhd->sysioc_exited, 0);
}
@@ -818,7 +869,6 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
#ifdef BCMDBUS
ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */);
#else
- WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
ret = dhd_bus_txdata(dhdp->bus, pktbuf);
#endif /* BCMDBUS */
@@ -998,6 +1048,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
}
}
+ dhd_os_wake_lock_timeout_enable(dhdp);
}
void
@@ -1064,7 +1115,6 @@ static int
dhd_watchdog_thread(void *data)
{
dhd_info_t *dhd = (dhd_info_t *)data;
- WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_WATCHDOG, "dhd_watchdog_thread");
/* This thread doesn't need any user-level access,
* so get rid of all our resources
@@ -1078,15 +1128,16 @@ dhd_watchdog_thread(void *data)
}
#endif /* DHD_SCHED */
+ set_freezable();
+
DAEMONIZE("dhd_watchdog");
/* Run until signal received */
while (1) {
if (down_interruptible (&dhd->watchdog_sem) == 0) {
- WAKE_LOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
+ dhd_os_wake_lock(&dhd->pub);
/* Call the bus module watchdog */
dhd_bus_watchdog(&dhd->pub);
- WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
/* Count the tick for reference */
dhd->pub.tickcnt++;
@@ -1095,12 +1146,12 @@ dhd_watchdog_thread(void *data)
if (dhd->wd_timer_valid) {
mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
}
+ dhd_os_wake_unlock(&dhd->pub);
}
else
break;
}
- WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_WATCHDOG);
complete_and_exit(&dhd->watchdog_exited, 0);
}
@@ -1121,8 +1172,13 @@ dhd_watchdog(ulong data)
dhd->pub.tickcnt++;
/* Reschedule the watchdog */
+#if defined(CONTINUOUS_WATCHDOG)
dhd->timer.expires = jiffies + dhd_watchdog_ms * HZ / 1000;
add_timer(&dhd->timer);
+#else
+ if (dhd->wd_timer_valid)
+ mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+#endif /* defined(CONTINUOUS_WATCHDOG) */
}
static int
@@ -1130,7 +1186,6 @@ dhd_dpc_thread(void *data)
{
dhd_info_t *dhd = (dhd_info_t *)data;
- WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_DPC, "dhd_dpc_thread");
/* This thread doesn't need any user-level access,
* so get rid of all our resources
*/
@@ -1143,6 +1198,8 @@ dhd_dpc_thread(void *data)
}
#endif /* DHD_SCHED */
+ set_freezable();
+
DAEMONIZE("dhd_dpc");
/* Run until signal received */
@@ -1150,22 +1207,21 @@ dhd_dpc_thread(void *data)
if (down_interruptible(&dhd->dpc_sem) == 0) {
/* Call bus dpc unless it indicated down (then clean stop) */
if (dhd->pub.busstate != DHD_BUS_DOWN) {
- WAKE_LOCK(&dhd->pub, WAKE_LOCK_DPC);
if (dhd_bus_dpc(dhd->pub.bus)) {
up(&dhd->dpc_sem);
- WAKE_LOCK_TIMEOUT(&dhd->pub, WAKE_LOCK_TMOUT, 25);
}
- WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_DPC);
+ else {
+ dhd_os_wake_unlock(&dhd->pub);
+ }
} else {
dhd_bus_stop(dhd->pub.bus, TRUE);
+ dhd_os_wake_unlock(&dhd->pub);
}
}
else
break;
}
- WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_DPC);
-
complete_and_exit(&dhd->dpc_exited, 0);
}
@@ -1190,6 +1246,7 @@ dhd_sched_dpc(dhd_pub_t *dhdp)
{
dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+ dhd_os_wake_lock(dhdp);
if (dhd->dpc_pid >= 0) {
up(&dhd->dpc_sem);
return;
@@ -1505,13 +1562,9 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
if (is_set_key_cmd) {
dhd_wait_pend8021x(net);
}
- WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_IOCTL, "dhd_ioctl_entry");
- WAKE_LOCK(&dhd->pub, WAKE_LOCK_IOCTL);
bcmerror = dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
- WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_IOCTL);
- WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_IOCTL);
done:
if (!bcmerror && buf && ioc.buf) {
if (copy_to_user(ioc.buf, buf, buflen))
@@ -1556,6 +1609,8 @@ dhd_open(struct net_device *net)
#endif
int ifidx;
+ wl_control_wl_start(net); /* start if needed */
+
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
@@ -1701,6 +1756,15 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
spin_lock_init(&dhd->sdlock);
spin_lock_init(&dhd->txqlock);
+ /* Initialize Wakelock stuff */
+ spin_lock_init(&dhd->wl_lock);
+ dhd->wl_count = 0;
+ dhd->wl_packet = 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");
+#endif
+
/* Link to info module */
dhd->pub.info = dhd;
@@ -1774,9 +1838,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
register_pm_notifier(&dhd_sleep_pm_notifier);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
- /* Init lock suspend to prevent kernel going to suspend */
- WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_TMOUT, "dhd_wake_lock");
- WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_LINK_DOWN_TMOUT, "dhd_wake_lock_link_dw_event");
#ifdef CONFIG_HAS_EARLYSUSPEND
dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
@@ -1809,19 +1870,12 @@ dhd_bus_start(dhd_pub_t *dhdp)
/* try to download image and nvram to the dongle */
if (dhd->pub.busstate == DHD_BUS_DOWN) {
- WAKE_LOCK_INIT(dhdp, WAKE_LOCK_DOWNLOAD, "dhd_bus_start");
- WAKE_LOCK(dhdp, WAKE_LOCK_DOWNLOAD);
if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
fw_path, nv_path))) {
DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
__FUNCTION__, fw_path, nv_path));
- WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
- WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
return -1;
}
-
- WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
- WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
}
/* Start the watchdog timer */
@@ -2042,14 +2096,16 @@ dhd_detach(dhd_pub_t *dhdp)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
unregister_pm_notifier(&dhd_sleep_pm_notifier);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
- WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_TMOUT);
- WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_LINK_DOWN_TMOUT);
free_netdev(ifp->net);
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_lock_destroy(&dhd->wl_wifi);
+ wake_lock_destroy(&dhd->wl_rxwake);
+#endif
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
MFREE(dhd->pub.osh, dhd, sizeof(*dhd));
+ }
}
}
-}
static int __init
dhd_module_init(void)
@@ -2077,8 +2133,8 @@ dhd_module_init(void)
wifi_add_dev();
/* Waiting callback after platform_driver_register is done or exit with error */
- if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
- error = 1;
+ if (down_timeout(&wifi_control_sem, msecs_to_jiffies(5000)) != 0) {
+ error = -EINVAL;
DHD_ERROR(("%s: platform_driver_register callback timeout\n", __FUNCTION__));
goto fail;
}
@@ -2102,8 +2158,8 @@ dhd_module_init(void)
* It's needed to make sync up exit from dhd insmod and
* Kernel MMC sdio device callback registration
*/
- if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(3000)) != 0) {
- error = 1;
+ if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(5000)) != 0) {
+ error = -EINVAL;
DHD_ERROR(("%s: sdio_register_driver failed \n", __FUNCTION__));
}
#endif
@@ -2217,6 +2273,11 @@ dhd_os_wd_timer(void *bus, uint wdtick)
dhd_pub_t *pub = bus;
dhd_info_t *dhd = (dhd_info_t *)pub->info;
+#if !defined(CONTINUOUS_WATCHDOG)
+ static uint save_dhd_watchdog_ms = 0;
+#endif /* !defined(CONTINUOUS_WATCHDOG) */
+
+#if defined(CONTINUOUS_WATCHDOG)
/* Stop timer and restart at new value */
if (dhd->wd_timer_valid == TRUE) {
del_timer(&dhd->timer);
@@ -2228,6 +2289,37 @@ dhd_os_wd_timer(void *bus, uint wdtick)
add_timer(&dhd->timer);
dhd->wd_timer_valid = TRUE;
+#else
+ /* Totally stop the timer */
+ if (!wdtick && dhd->wd_timer_valid == TRUE) {
+ del_timer(&dhd->timer);
+ dhd->wd_timer_valid = FALSE;
+ save_dhd_watchdog_ms = wdtick;
+ return;
+ }
+
+ if (wdtick) {
+ dhd_watchdog_ms = (uint)wdtick;
+ if (save_dhd_watchdog_ms != dhd_watchdog_ms){
+
+ if (dhd->wd_timer_valid == TRUE)
+ /* Stop timer and restart at new value */
+ del_timer(&dhd->timer);
+
+ /* Create timer again when watchdog period is
+ dynamically changed or in the first instance
+ */
+ dhd->timer.expires = jiffies + dhd_watchdog_ms * HZ / 1000;
+ add_timer(&dhd->timer);
+ }else {
+ /* 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;
+ }
+#endif /* defined(CONTINUTOUS_WATCHDOG) */
}
void *
@@ -2282,7 +2374,7 @@ dhd_os_sdlock(dhd_pub_t *pub)
if (dhd->threads_only)
down(&dhd->sdsem);
else
- spin_lock_bh(&dhd->sdlock);
+ spin_lock_bh(&dhd->sdlock);
}
void
@@ -2295,7 +2387,7 @@ dhd_os_sdunlock(dhd_pub_t *pub)
if (dhd->threads_only)
up(&dhd->sdsem);
else
- spin_unlock_bh(&dhd->sdlock);
+ spin_unlock_bh(&dhd->sdlock);
}
void
@@ -2473,3 +2565,120 @@ dhd_wait_pend8021x(struct net_device *dev)
}
return pend;
}
+
+int dhd_os_wake_lock_timeout(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->wl_lock, flags);
+ ret = dhd->wl_packet;
+#ifdef CONFIG_HAS_WAKELOCK
+ if (dhd->wl_packet)
+ wake_lock_timeout(&dhd->wl_rxwake, (HZ >> 1));
+#endif
+ dhd->wl_packet = 0;
+ spin_unlock_irqrestore(&dhd->wl_lock, flags);
+ }
+ /* printk("%s: %d\n", __FUNCTION__, ret); */
+ return ret;
+}
+
+int net_os_wake_lock_timeout(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_lock_timeout(&dhd->pub);
+ return ret;
+}
+
+int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wl_lock, flags);
+ dhd->wl_packet = 1;
+ spin_unlock_irqrestore(&dhd->wl_lock, flags);
+ }
+ /* printk("%s\n",__func__); */
+ return 0;
+}
+
+int net_os_wake_lock_timeout_enable(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_lock_timeout_enable(&dhd->pub);
+ return ret;
+}
+
+int dhd_os_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->wl_lock, flags);
+#ifdef CONFIG_HAS_WAKELOCK
+ if (!dhd->wl_count)
+ wake_lock(&dhd->wl_wifi);
+#endif
+ dhd->wl_count++;
+ ret = dhd->wl_count;
+ spin_unlock_irqrestore(&dhd->wl_lock, flags);
+ }
+ /* printk("%s: %d\n", __FUNCTION__, ret); */
+ return ret;
+}
+
+int net_os_wake_lock(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_lock(&dhd->pub);
+ return ret;
+}
+
+int dhd_os_wake_unlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
+
+ dhd_os_wake_lock_timeout(pub);
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wl_lock, flags);
+ if (dhd->wl_count) {
+ dhd->wl_count--;
+#ifdef CONFIG_HAS_WAKELOCK
+ if (!dhd->wl_count)
+ wake_unlock(&dhd->wl_wifi);
+#endif
+ ret = dhd->wl_count;
+ }
+ spin_unlock_irqrestore(&dhd->wl_lock, flags);
+ }
+ /* printk("%s: %d\n", __FUNCTION__, ret); */
+ return ret;
+}
+
+int net_os_wake_unlock(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_wake_unlock(&dhd->pub);
+ return ret;
+}
diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c
index 6e43e43..fe8c8d7 100644
--- a/bcm4329/src/dhd/sys/dhd_sdio.c
+++ b/bcm4329/src/dhd/sys/dhd_sdio.c
@@ -293,6 +293,11 @@ static int tx_packets[NUMPRIO];
/* Deferred transmit */
const uint dhd_deferred_tx = 1;
+#if !defined(CONTINUOUS_WATCHDOG)
+extern uint dhd_watchdog_ms;
+extern void dhd_os_wd_timer(void *bus, uint wdtick);
+#endif /* !defined(CONTINUOUS_WATCHDOG) */
+
/* Tx/Rx bounds */
uint dhd_txbound;
uint dhd_rxbound;
@@ -687,8 +692,12 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
/* Early exit if we're already there */
if (bus->clkstate == target) {
- if (target == CLK_AVAIL)
+ if (target == CLK_AVAIL) {
+#if !defined(CONTINUOUS_WATCHDOG)
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+#endif /* !defined(CONTINUOUS_WATCHDOG) */
bus->activity = TRUE;
+ }
return BCME_OK;
}
@@ -699,6 +708,9 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
dhdsdio_sdclk(bus, TRUE);
/* Now request HT Avail on the backplane */
dhdsdio_htclk(bus, TRUE, pendok);
+#if !defined(CONTINUOUS_WATCHDOG)
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+#endif /* !defined(CONTINUOUS_WATCHDOG) */
bus->activity = TRUE;
break;
@@ -711,6 +723,9 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
else
DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
bus->clkstate, target));
+#if !defined(CONTINUOUS_WATCHDOG)
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+#endif /* !defined(CONTINUOUS_WATCHDOG) */
break;
case CLK_NONE:
@@ -719,6 +734,9 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
dhdsdio_htclk(bus, FALSE, FALSE);
/* Now remove the SD clock */
dhdsdio_sdclk(bus, FALSE);
+#if !defined(CONTINUOUS_WATCHDOG)
+ dhd_os_wd_timer(bus->dhd, 0);
+#endif /* !defined(CONTINUOUS_WATCHDOG) */
break;
}
#ifdef DHD_DEBUG
@@ -4002,7 +4020,9 @@ dhdsdio_isr(void *arg)
#if defined(SDIO_ISR_THREAD)
DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
+ dhd_os_wake_lock(bus->dhd);
while (dhdsdio_dpc(bus));
+ dhd_os_wake_unlock(bus->dhd);
#else
bus->dpc_sched = TRUE;
dhd_sched_dpc(bus->dhd);
@@ -4823,7 +4843,6 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
-
return ret;
}
@@ -4833,12 +4852,13 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
bool ret;
/* Download the firmware */
+ dhd_os_wake_lock(bus->dhd);
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
ret = _dhdsdio_download_firmware(bus) == 0;
dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-
+ dhd_os_wake_unlock(bus->dhd);
return ret;
}
@@ -4853,14 +4873,15 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
if (bus->dhd) {
+
+ dhdsdio_release_dongle(bus, osh);
+
dhd_detach(bus->dhd);
bus->dhd = NULL;
}
dhdsdio_release_malloc(bus, osh);
- dhdsdio_release_dongle(bus, osh);
-
/* De-register interrupt handler */
bcmsdh_intr_dereg(bus->sdh);
diff --git a/bcm4329/src/shared/linux_osl.c b/bcm4329/src/shared/linux_osl.c
index 4cf658b..9c100a4 100644
--- a/bcm4329/src/shared/linux_osl.c
+++ b/bcm4329/src/shared/linux_osl.c
@@ -148,8 +148,10 @@ osl_t *
osl_attach(void *pdev, uint bustype, bool pkttag)
{
osl_t *osh;
+ gfp_t flags;
- osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
+ flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
+ osh = kmalloc(sizeof(osl_t), flags);
ASSERT(osh);
bzero(osh, sizeof(osl_t));
@@ -190,9 +192,9 @@ osl_attach(void *pdev, uint bustype, bool pkttag)
STATIC_BUF_TOTAL_LEN))) {
printk("can not alloc static buf!\n");
}
- else
- printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf);
-
+ else {
+ /* printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); */
+ }
init_MUTEX(&bcm_static_buf->static_sem);
@@ -450,8 +452,8 @@ void*
osl_malloc(osl_t *osh, uint size)
{
void *addr;
+ gfp_t flags;
-
if (osh)
ASSERT(osh->magic == OS_HANDLE_MAGIC);
@@ -488,8 +490,8 @@ osl_malloc(osl_t *osh, uint size)
}
original:
#endif
-
- if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
+ flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
+ if ((addr = kmalloc(size, flags)) == NULL) {
if (osh)
osh->failed++;
return (NULL);
@@ -601,8 +603,10 @@ void *
osl_pktdup(osl_t *osh, void *skb)
{
void * p;
+ gfp_t flags;
- if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL)
+ flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
+ if ((p = skb_clone((struct sk_buff*)skb, flags)) == NULL)
return NULL;
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index 768373b..f92e186 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.c
@@ -56,8 +56,8 @@ typedef const struct si_pub si_t;
#include <wl_iw.h>
-
#include <linux/rtnetlink.h>
+#include <linux/mutex.h>
#define WL_IW_USE_ISCAN 1
#define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1
@@ -69,6 +69,7 @@ typedef const struct si_pub si_t;
} while (0)
static int g_onoff = G_WLAN_SET_ON;
+static struct mutex wl_start_lock;
extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
uint32 reason, char* stringBuf, uint buflen);
@@ -133,10 +134,10 @@ wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
#if defined(WL_IW_USE_ISCAN)
+static wlc_ssid_t g_specific_ssid; /* chache specific ssid request */
#define ISCAN_STATE_IDLE 0
#define ISCAN_STATE_SCANING 1
-
#define WLC_IW_ISCAN_MAXLEN 2048
typedef struct iscan_buf {
struct iscan_buf * next;
@@ -756,18 +757,18 @@ wl_iw_send_priv_event(
return 0;
}
+#ifdef WL_IW_USE_THREAD_WL_OFF
static int
_wl_control_sysioc_thread_wl_off(void *data)
{
struct wl_ctrl *wl_ctl = (struct wl_ctrl *)data;
- wl_iw_t *iw = *(wl_iw_t **)netdev_priv(wl_ctl->dev);
DAEMONIZE("wlcontrol_sysioc");
WL_TRACE(("%s Entered\n", __FUNCTION__));
+ net_os_wake_lock(wl_ctl->dev);
- WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_OFF, "sysioc_thread_wl_off");
- WAKE_LOCK(iw->pub, WAKE_LOCK_OFF);
+ mutex_lock(&wl_start_lock);
while (down_interruptible(&wl_ctl->timer_sem) == 0) {
WL_TRACE(("%s Turning off wifi dev\n", __FUNCTION__));
@@ -788,17 +789,50 @@ _wl_control_sysioc_thread_wl_off(void *data)
wl_iw_send_priv_event(wl_ctl->dev, "STOP");
+ net_os_wake_lock_timeout_enable(wl_ctl->dev);
break;
}
-
+ mutex_unlock(&wl_start_lock);
WL_TRACE(("%s Exited\n", __FUNCTION__));
- WAKE_UNLOCK(iw->pub, WAKE_LOCK_OFF);
- WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_OFF);
+ net_os_wake_unlock(wl_ctl->dev);
complete_and_exit(&wl_ctl->sysioc_exited, 0);
KILL_PROC(wl_ctl->sysioc_pid, SIGTERM);
}
+#endif
+
+int
+wl_control_wl_start(struct net_device *dev)
+{
+ int ret = 0;
+
+ WL_TRACE(("Enter %s \n", __FUNCTION__));
+
+ mutex_lock(&wl_start_lock);
+ if (g_onoff == G_WLAN_SET_OFF) {
+ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
+
+#if defined(BCMLXSDMMC)
+ sdioh_start(NULL, 0);
+#endif
+
+ dhd_dev_reset(dev, 0);
+
+#if defined(BCMLXSDMMC)
+ sdioh_start(NULL, 1);
+#endif
+
+ dhd_dev_init_ioctl(dev);
+
+ g_onoff = G_WLAN_SET_ON;
+ }
+ WL_TRACE(("Exited %s \n", __FUNCTION__));
+
+ mutex_unlock(&wl_start_lock);
+ return ret;
+}
+#ifdef WL_IW_USE_THREAD_WL_OFF
static void
wl_iw_stop_timerfunc(ulong data)
{
@@ -810,6 +844,7 @@ wl_iw_stop_timerfunc(ulong data)
up(&wl_ctl->timer_sem);
}
+#endif
static int
wl_iw_control_wl_off(
@@ -818,19 +853,18 @@ wl_iw_control_wl_off(
)
{
int ret = 0;
+#ifdef WL_IW_USE_THREAD_WL_OFF
static struct wl_ctrl ctl;
static struct timer_list timer;
-
+#endif
WL_TRACE(("Enter %s\n", __FUNCTION__));
-
-
+#ifdef WL_IW_USE_THREAD_WL_OFF
ctl.timer = &timer;
ctl.dev = dev;
sema_init(&ctl.timer_sem, 0);
init_completion(&ctl.sysioc_exited);
-
ctl.sysioc_pid = kernel_thread(_wl_control_sysioc_thread_wl_off, &ctl, 0);
timer.data = (ulong)&ctl;
@@ -838,7 +872,28 @@ wl_iw_control_wl_off(
init_timer(&timer);
timer.expires = jiffies + 2000 * HZ / 1000;
add_timer(&timer);
+#else
+ mutex_lock(&wl_start_lock);
+ if (g_onoff == G_WLAN_SET_ON) {
+ g_onoff = G_WLAN_SET_OFF;
+#if defined(WL_IW_USE_ISCAN)
+ g_iscan->iscan_state = ISCAN_STATE_IDLE;
+#endif
+
+ dhd_dev_reset(dev, 1);
+
+#if defined(BCMLXSDMMC)
+ sdioh_stop(NULL);
+#endif
+ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
+
+ wl_iw_send_priv_event(dev, "STOP");
+
+ net_os_wake_lock_timeout_enable(dev);
+ }
+ mutex_unlock(&wl_start_lock);
+#endif
WL_TRACE(("Exited %s\n", __FUNCTION__));
return ret;
@@ -854,26 +909,12 @@ wl_iw_control_wl_on(
WL_TRACE(("Enter %s \n", __FUNCTION__));
- if (g_onoff == G_WLAN_SET_OFF) {
- dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
-
-#if defined(BCMLXSDMMC)
- sdioh_start(NULL, 0);
-#endif
-
- dhd_dev_reset(dev, 0);
-
-#if defined(BCMLXSDMMC)
- sdioh_start(NULL, 1);
-#endif
-
- dhd_dev_init_ioctl(dev);
-
- g_onoff = G_WLAN_SET_ON;
- }
+ ret = wl_control_wl_start(dev);
wl_iw_send_priv_event(dev, "START");
+ net_os_wake_lock_timeout_enable(dev);
+
WL_TRACE(("Exited %s \n", __FUNCTION__));
return ret;
@@ -1709,6 +1750,18 @@ wl_iw_iscan_get(iscan_info_t *iscan)
return status;
}
+static void wl_iw_force_specific_scan(iscan_info_t *iscan)
+{
+ WL_TRACE(("### Force Specific SCAN for %s\n", g_specific_ssid.SSID));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+ (void) dev_wlc_ioctl(iscan->dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+}
+
static void wl_iw_send_scan_complete(iscan_info_t *iscan)
{
#ifndef SANDGATE2G
@@ -1726,7 +1779,7 @@ _iscan_sysioc_thread(void *data)
{
uint32 status;
iscan_info_t *iscan = (iscan_info_t *)data;
-
+ static bool iscan_pass_abort = FALSE;
DAEMONIZE("iscan_sysioc");
status = WL_SCAN_RESULTS_PARTIAL;
@@ -1744,18 +1797,25 @@ _iscan_sysioc_thread(void *data)
rtnl_unlock();
#endif
+ if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
+ WL_TRACE(("%s Get results from specific scan sttaus=%d\n", __FUNCTION__, status));
+ wl_iw_send_scan_complete(iscan);
+ iscan_pass_abort = FALSE;
+ status = -1;
+ }
+
switch (status) {
case WL_SCAN_RESULTS_PARTIAL:
WL_TRACE(("iscanresults incomplete\n"));
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_lock();
#endif
-
+
wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_unlock();
#endif
-
+
mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
iscan->timer_on = 1;
break;
@@ -1766,19 +1826,24 @@ _iscan_sysioc_thread(void *data)
break;
case WL_SCAN_RESULTS_PENDING:
WL_TRACE(("iscanresults pending\n"));
-
+
mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
iscan->timer_on = 1;
break;
case WL_SCAN_RESULTS_ABORTED:
WL_TRACE(("iscanresults aborted\n"));
iscan->iscan_state = ISCAN_STATE_IDLE;
- wl_iw_send_scan_complete(iscan);
+ if (g_scan_specified_ssid == 0)
+ wl_iw_send_scan_complete(iscan);
+ else {
+ iscan_pass_abort = TRUE;
+ wl_iw_force_specific_scan(iscan);
+ }
break;
default:
WL_TRACE(("iscanresults returned unknown status %d\n", status));
break;
- }
+ }
}
if (iscan->timer_on) {
@@ -2043,8 +2108,6 @@ wl_iw_set_scan(
char *extra
)
{
- wlc_ssid_t ssid;
-
WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
@@ -2052,7 +2115,7 @@ wl_iw_set_scan(
return 0;
- memset(&ssid, 0, sizeof(ssid));
+ memset(&g_specific_ssid, 0, sizeof(g_specific_ssid));
g_scan_specified_ssid = 0;
#if WIRELESS_EXT > 17
@@ -2060,16 +2123,16 @@ wl_iw_set_scan(
if (wrqu->data.length == sizeof(struct iw_scan_req)) {
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
struct iw_scan_req *req = (struct iw_scan_req *)extra;
- ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
- memcpy(ssid.SSID, req->essid, ssid.SSID_len);
- ssid.SSID_len = htod32(ssid.SSID_len);
+ g_specific_ssid.SSID_len = MIN(sizeof(g_specific_ssid.SSID), req->essid_len);
+ memcpy(g_specific_ssid.SSID, req->essid, g_specific_ssid.SSID_len);
+ g_specific_ssid.SSID_len = htod32(g_specific_ssid.SSID_len);
g_scan_specified_ssid = 1;
- WL_TRACE(("Specific scan ssid=%s len=%d\n", ssid.SSID, ssid.SSID_len));
+ WL_TRACE(("Specific scan ssid=%s len=%d\n", g_specific_ssid.SSID, g_specific_ssid.SSID_len));
}
}
#endif
- (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
+ (void) dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid));
return 0;
}
@@ -3768,7 +3831,6 @@ wl_iw_set_priv(
int ret = 0;
char * extra;
- wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
if (!(extra = kmalloc(dwrq->length, GFP_KERNEL)))
return -ENOMEM;
@@ -3780,17 +3842,20 @@ wl_iw_set_priv(
WL_TRACE(("%s: SIOCSIWPRIV requst = %s\n",
dev->name, extra));
+ net_os_wake_lock(dev);
if (dwrq->length && extra) {
- WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_PRIV, "wl_iw_set_priv");
- WAKE_LOCK(iw->pub, WAKE_LOCK_PRIV);
-
if (g_onoff == G_WLAN_SET_OFF) {
- wl_iw_control_wl_on(dev, info);
- if (strnicmp(extra, "START", strlen("START")) != 0)
- WL_TRACE(("%s, missing START, simulate START\n", __FUNCTION__));
- else
+ if (strnicmp(extra, "START", strlen("START")) != 0) {
+ WL_TRACE(("%s, missing START, Fail\n", __FUNCTION__));
+ kfree(extra);
+ net_os_wake_unlock(dev);
+ return -EFAULT;
+ }
+ else {
+ wl_iw_control_wl_on(dev, info);
WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
+ }
}
if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
@@ -3823,10 +3888,10 @@ wl_iw_set_priv(
dwrq->length = strlen("OK") + 1;
WL_TRACE(("Unkown PRIVATE command , ignored\n"));
}
- WAKE_UNLOCK(iw->pub, WAKE_LOCK_PRIV);
- WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_PRIV);
}
+ net_os_wake_unlock(dev);
+
if (extra) {
if (copy_to_user(dwrq->pointer, extra, dwrq->length)) {
kfree(extra);
@@ -4218,7 +4283,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
memset(&wrqu, 0, sizeof(wrqu));
memset(extra, 0, sizeof(extra));
-
switch (event_type) {
case WLC_E_TXFAIL:
cmd = IWEVTXDROP;
@@ -4336,14 +4400,19 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
#if defined(WL_IW_USE_ISCAN)
if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
(g_iscan->iscan_state != ISCAN_STATE_IDLE))
+ {
up(&g_iscan->sysioc_sem);
-#else
- cmd = SIOCGIWSCAN;
+ } else {
cmd = SIOCGIWSCAN;
wrqu.data.length = strlen(extra);
- WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
+ WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan\n"));
+ }
+#else
+ cmd = SIOCGIWSCAN;
+ wrqu.data.length = strlen(extra);
+ WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
#endif
- break;
+ break;
default:
@@ -4351,8 +4420,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
break;
}
#ifndef SANDGATE2G
- if (cmd)
- wireless_send_event(dev, cmd, &wrqu, extra);
+ if (cmd)
+ wireless_send_event(dev, cmd, &wrqu, extra);
#endif
#if WIRELESS_EXT > 14
@@ -4626,6 +4695,7 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
if (iscan->sysioc_pid < 0)
return -ENOMEM;
#endif
+ mutex_init(&wl_start_lock);
iw = *(wl_iw_t **)netdev_priv(dev);
iw->pub = (dhd_pub_t *)dhdp;
@@ -4639,13 +4709,10 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
memset(g_scan, 0, G_SCAN_RESULTS);
g_scan_specified_ssid = 0;
-
wl_iw_init_ss_cache_ctrl();
wl_iw_bt_init(dev);
-
-
return 0;
}
diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h
index 64d8fc2..0321964 100644
--- a/bcm4329/src/wl/sys/wl_iw.h
+++ b/bcm4329/src/wl/sys/wl_iw.h
@@ -118,6 +118,12 @@ extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
int wl_iw_attach(struct net_device *dev, void * dhdp);
void wl_iw_detach(void);
+int wl_control_wl_start(struct net_device *dev);
+
+extern int net_os_wake_lock(struct net_device *dev);
+extern int net_os_wake_unlock(struct net_device *dev);
+extern int net_os_wake_lock_timeout(struct net_device *dev);
+extern int net_os_wake_lock_timeout_enable(struct net_device *dev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \