diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2009-11-11 10:34:26 -0800 |
---|---|---|
committer | Dmitry Shmidt <dimitrysh@google.com> | 2009-11-11 10:34:26 -0800 |
commit | b4ace791eb574f589c53be582ea0d14e1a85ff09 (patch) | |
tree | 5293f8ec8ea0c05d6a6cfbee1fe42a345efd0c27 | |
parent | 492884be0b302c6c6ea51b360c1f7b0996d96a8b (diff) | |
download | wlan-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.c | 2 | ||||
-rw-r--r-- | bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c | 2 | ||||
-rw-r--r-- | bcm4329/src/dhd/sys/dhd.h | 53 | ||||
-rw-r--r-- | bcm4329/src/dhd/sys/dhd_cdc.c | 7 | ||||
-rw-r--r-- | bcm4329/src/dhd/sys/dhd_common.c | 8 | ||||
-rw-r--r-- | bcm4329/src/dhd/sys/dhd_custom_gpio.c | 18 | ||||
-rw-r--r-- | bcm4329/src/dhd/sys/dhd_linux.c | 323 | ||||
-rw-r--r-- | bcm4329/src/dhd/sys/dhd_sdio.c | 31 | ||||
-rw-r--r-- | bcm4329/src/shared/linux_osl.c | 20 | ||||
-rw-r--r-- | bcm4329/src/wl/sys/wl_iw.c | 193 | ||||
-rw-r--r-- | bcm4329/src/wl/sys/wl_iw.h | 6 |
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) \ |