net: wireless: bcmdhd: Combined patch from 4.218.248-31
Howard M. Harte [Thu, 16 Jun 2011 01:52:15 +0000 (18:52 -0700)]
bcmdhd: Allocate skb with GFP_KERNEL flag if possible: fix for older kernels.
bcmdhd: Fix race conditions for sysioc_thread
    * Fix up formatting and #ifdefs.
net: wireless: bcmdhd: Fix get_customized_country_code() for older kernels.
net: wireless: bcmdhd: Move PNO function prototypes to dhd.h.
Add private command support.
net: wireless: bcmdhd: Set proper read barrier
net: wireless: bcmdhd: Fix memory leak in case of dhd_bus_init() failure
net: wireless: bcmdhd: Fix wake_lock symmetry
net: wireless: bcmdhd: Ignore error if scan results are empty
net: wireless: bcmdhd: Add sdlock to firmware loading
net: wireless: bcmdhd: Fix watchdog syncronization during start/stop
net: wireless: bcmdhd: Fix Makefile to allow WEXT compilation

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>

12 files changed:
drivers/net/wireless/bcmdhd/Makefile
drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
drivers/net/wireless/bcmdhd/dhd_linux.c
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd/include/linuxver.h
drivers/net/wireless/bcmdhd/linux_osl.c
drivers/net/wireless/bcmdhd/wl_android.c [new file with mode: 0644]
drivers/net/wireless/bcmdhd/wl_iw.c
drivers/net/wireless/bcmdhd/wl_iw.h
drivers/net/wireless/bcmdhd/wldev_common.c
drivers/net/wireless/bcmdhd/wldev_common.h

index b476372..fc5a02f 100644 (file)
@@ -6,13 +6,14 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Werror -Dlinux -DBCMDRIVER             \
        -DCUSTOMER_HW2 -DCUSTOM_OOB_GPIO_NUM=2 -DOOB_INTR_ONLY -DHW_OOB       \
        -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DBCMPLATFORM_BUS -DWLP2P     \
        -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT          \
-       -DKEEP_ALIVE -DCSCAN -DGET_CUSTOM_MAC_ENABLE                          \
+       -DKEEP_ALIVE -DCSCAN -DGET_CUSTOM_MAC_ENABLE -DPKT_FILTER_SUPPORT     \
+       -DEMBEDDED_PLATFORM                                                   \
        -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
 
 DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o   \
        dhd_linux_sched.o bcmwifi.o dhd_sdio.o bcmevent.o dhd_bta.o hndpmu.o  \
        bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o linux_osl.o            \
-       bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o
+       bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o
 
 obj-$(CONFIG_BCMDHD) += bcmdhd.o
 bcmdhd-objs += $(DHDOFILES)
@@ -21,7 +22,7 @@ bcmdhd-objs += wl_iw.o
 DHDCFLAGS += -DSOFTAP
 endif
 ifneq ($(CONFIG_CFG80211),)
-bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wldev_common.o
+bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o
 DHDCFLAGS += -DWL_CFG80211
 endif
 EXTRA_CFLAGS = $(DHDCFLAGS)
index 9033da9..f7a103a 100644 (file)
@@ -268,13 +268,13 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
 #define DHD_OS_WAKE_LOCK_TIMEOUT(pub)          dhd_os_wake_lock_timeout(pub)
 #define DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(pub)   dhd_os_wake_lock_timeout_enable(pub)
 
-extern void dhd_os_start_lock(dhd_pub_t *pub);
-extern void dhd_os_start_unlock(dhd_pub_t *pub);
-
 extern unsigned long dhd_os_spin_lock(dhd_pub_t *pub);
 extern void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags);
 
 
+extern void dhd_os_start_lock(dhd_pub_t *pub);
+extern void dhd_os_start_unlock(dhd_pub_t *pub);
+
 typedef struct dhd_if_event {
        uint8 ifidx;
        uint8 action;
@@ -363,6 +363,18 @@ extern int    dhd_custom_get_mac_address(unsigned char *buf);
 extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
 extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
 extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
+extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
+extern int dhd_pno_clean(dhd_pub_t *dhd);
+extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid,
+                       ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
+extern int dhd_pno_get_status(dhd_pub_t *dhd);
+extern int dhd_dev_pno_reset(struct net_device *dev);
+extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local,
+                           int nssid, ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
+extern int dhd_dev_pno_enable(struct net_device *dev,  int pfn_enabled);
+extern int dhd_dev_get_pno_status(struct net_device *dev);
+extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
+
 #ifdef DHD_DEBUG
 extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size);
 #endif /* DHD_DEBUG */
index 76587a1..9958513 100644 (file)
@@ -41,7 +41,7 @@
 extern  void bcm_wlan_power_off(int);
 extern  void bcm_wlan_power_on(int);
 #endif /* CUSTOMER_HW */
-#if  defined(CUSTOMER_HW2)
+#if defined(CUSTOMER_HW2)
 #ifdef CONFIG_WIFI_CONTROL_FUNC
 int wifi_set_carddetect(int on);
 int wifi_set_power(int on, unsigned long msec);
@@ -54,8 +54,8 @@ int wifi_set_power(int on, unsigned long msec) { return -1; }
 int wifi_get_irq_number(unsigned long *irq_flags_ptr) { return -1; }
 int wifi_get_mac_addr(unsigned char *buf) { return -1; }
 void *wifi_get_country_code(char *ccode) { return NULL; }
-#endif
-#endif
+#endif /* CONFIG_WIFI_CONTROL_FUNC */
+#endif /* CUSTOMER_HW2 */
 
 #if defined(OOB_INTR_ONLY)
 
@@ -253,7 +253,7 @@ const struct cntry_locales_custom translate_custom_table[] = {
 */
 void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
 {
-#ifdef CUSTOMER_HW2
+#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
        struct cntry_locales_custom *cloc_ptr;
 
        if (!cspec)
@@ -290,5 +290,5 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
        cspec->rev = translate_custom_table[0].custom_locale_rev;
 #endif /* EXMAPLE_TABLE */
        return;
-#endif
+#endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
 }
index 7d78bae..57f38ee 100644 (file)
@@ -90,7 +90,7 @@ static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
 #endif /* WLMEDIA_HTSF */
 
 #if defined(SOFTAP)
-extern bool    ap_cfg_running;
+extern bool ap_cfg_running;
 #endif
 
 /* enable HOSTIP cache update from the host side when an eth0:N is up */
@@ -171,6 +171,7 @@ int wifi_get_mac_addr(unsigned char *buf)
 }
 #endif
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
 void *wifi_get_country_code(char *ccode)
 {
        DHD_TRACE(("%s\n", __FUNCTION__));
@@ -181,6 +182,7 @@ void *wifi_get_country_code(char *ccode)
        }
        return NULL;
 }
+#endif
 
 static int wifi_probe(struct platform_device *pdev)
 {
@@ -437,6 +439,7 @@ char nvram_path[MOD_PARAM_PATHLEN];
 
 extern int wl_control_wl_start(struct net_device *dev);
 extern int net_os_send_hang_message(struct net_device *dev);
+extern int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 struct semaphore dhd_registration_sem;
 #define DHD_REGISTRATION_TIMEOUT  12000  /* msec : allowed time to finished dhd registration */
@@ -459,7 +462,7 @@ module_param(dhd_watchdog_ms, uint, 0);
 
 #if defined(DHD_DEBUG)
 /* Console poll interval */
-uint dhd_console_ms = 250;
+uint dhd_console_ms = 0;
 module_param(dhd_console_ms, uint, 0);
 #endif /* defined(DHD_DEBUG) */
 
@@ -1206,6 +1209,7 @@ _dhd_sysioc_thread(void *data)
                }
 
                dhd_os_start_lock(&dhd->pub);
+               DHD_OS_WAKE_LOCK(&dhd->pub);
 
                for (i = 0; i < DHD_MAX_IFS; i++) {
                        if (dhd->iflist[i]) {
@@ -1251,7 +1255,6 @@ _dhd_sysioc_thread(void *data)
 
                DHD_OS_WAKE_UNLOCK(&dhd->pub);
                dhd_os_start_unlock(&dhd->pub);
-
        }
        DHD_TRACE(("%s: stopped\n", __FUNCTION__));
        complete_and_exit(&tsk->completed, 0);
@@ -1762,11 +1765,10 @@ dhd_watchdog_thread(void *data)
                                break;
                        }
 
+                       dhd_os_sdlock(&dhd->pub);
                        if (dhd->pub.dongle_reset == FALSE) {
                                DHD_TIMER(("%s:\n", __FUNCTION__));
 
-                               DHD_OS_WAKE_LOCK(&dhd->pub);
-
                                /* Call the bus module watchdog */
                                dhd_bus_watchdog(&dhd->pub);
 
@@ -1776,11 +1778,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);
                        }
+                       dhd_os_sdunlock(&dhd->pub);
+                       DHD_OS_WAKE_UNLOCK(&dhd->pub);
                } else {
                        break;
-       }
+               }
 
        complete_and_exit(&tsk->completed, 0);
 }
@@ -1790,11 +1793,12 @@ static void 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;
        }
 
-       DHD_OS_WAKE_LOCK(&dhd->pub);
 #ifdef DHDTHREAD
        if (dhd->thr_wdt_ctl.thr_pid >= 0) {
                up(&dhd->thr_wdt_ctl.sema);
@@ -1802,6 +1806,7 @@ static void dhd_watchdog(ulong data)
        }
 #endif /* DHDTHREAD */
 
+       dhd_os_sdlock(&dhd->pub);
        /* Call the bus module watchdog */
        dhd_bus_watchdog(&dhd->pub);
 
@@ -1811,6 +1816,7 @@ static void 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);
 }
 
@@ -1852,7 +1858,6 @@ dhd_dpc_thread(void *data)
                        if (dhd->pub.busstate != DHD_BUS_DOWN) {
                                if (dhd_bus_dpc(dhd->pub.bus)) {
                                        up(&tsk->sema);
-                                       DHD_OS_WAKE_LOCK_TIMEOUT(&dhd->pub);
                                }
                                else {
                                        DHD_OS_WAKE_UNLOCK(&dhd->pub);
@@ -2151,6 +2156,12 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
        }
 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
 
+       if (cmd == SIOCDEVPRIVATE+1) {
+               ret = wl_android_priv_cmd(net, ifr, cmd);
+               DHD_OS_WAKE_UNLOCK(&dhd->pub);
+               return ret;
+       }
+
        if (cmd != SIOCDEVPRIVATE) {
                DHD_OS_WAKE_UNLOCK(&dhd->pub);
                return -EOPNOTSUPP;
@@ -2695,6 +2706,8 @@ dhd_bus_start(dhd_pub_t *dhdp)
 
        DHD_TRACE(("%s: \n", __FUNCTION__));
 
+       dhd_os_sdlock(dhdp);
+
        /* try to download image and nvram to the dongle */
        if  ((dhd->pub.busstate == DHD_BUS_DOWN) &&
                (fw_path != NULL) && (fw_path[0] != '\0') &&
@@ -2704,24 +2717,23 @@ dhd_bus_start(dhd_pub_t *dhdp)
                                                fw_path, nv_path))) {
                        DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
                                   __FUNCTION__, fw_path, nv_path));
+                       dhd_os_sdunlock(dhdp);
                        return -1;
                }
        }
-       if (dhd->pub.busstate != DHD_BUS_LOAD)
+       if (dhd->pub.busstate != DHD_BUS_LOAD) {
+               dhd_os_sdunlock(dhdp);
                return -ENETDOWN;
+       }
 
        /* Start the watchdog timer */
        dhd->pub.tickcnt = 0;
        dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
 
        /* Bring up the bus */
-#ifdef DHDTHREAD
-       if ((ret = dhd_bus_init(&dhd->pub, TRUE)) != 0) {
-#else
        if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) {
-#endif
-
                DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret));
+               dhd_os_sdunlock(dhdp);
                return ret;
        }
 #if defined(OOB_INTR_ONLY)
@@ -2732,6 +2744,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
                del_timer_sync(&dhd->timer);
 
                DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__));
+               dhd_os_sdunlock(dhdp);
                return -ENODEV;
        }
 
@@ -2744,9 +2757,12 @@ dhd_bus_start(dhd_pub_t *dhdp)
                del_timer_sync(&dhd->timer);
                dhd->wd_timer_valid = FALSE;
                DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
+               dhd_os_sdunlock(dhdp);
                return -ENODEV;
        }
 
+       dhd_os_sdunlock(dhdp);
+
 #ifdef EMBEDDED_PLATFORM
        bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
        dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
@@ -3432,53 +3448,38 @@ 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;
 
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
+       flags = dhd_os_spin_lock(pub);
+
        /* don't start the wd until fw is loaded */
-       if (pub->busstate == DHD_BUS_DOWN)
+       if (pub->busstate == DHD_BUS_DOWN) {
+               dhd_os_spin_unlock(pub, flags);
                return;
+       }
 
        /* Totally stop the timer */
        if (!wdtick && dhd->wd_timer_valid == TRUE) {
+               dhd->wd_timer_valid = FALSE;
+               dhd_os_spin_unlock(pub, flags);
 #ifdef DHDTHREAD
                del_timer_sync(&dhd->timer);
 #else
                del_timer(&dhd->timer);
 #endif /* DHDTHREAD */
-               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 */
-#ifdef DHDTHREAD
-                               del_timer_sync(&dhd->timer);
-#else
-                               del_timer(&dhd->timer);
-#endif /* DHDTHREAD */
-
-                       /* 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;
+               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;
        }
+       dhd_os_spin_unlock(pub, flags);
 }
 
 void *
@@ -3820,19 +3821,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;
 }
@@ -3987,8 +3981,6 @@ void dhd_os_start_unlock(dhd_pub_t *pub)
 #endif
 }
 
-
-#ifdef SOFTAP
 unsigned long dhd_os_spin_lock(dhd_pub_t *pub)
 {
        dhd_info_t *dhd = (dhd_info_t *)(pub->info);
@@ -4007,7 +3999,6 @@ void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags)
        if (dhd)
                spin_unlock_irqrestore(&dhd->dhd_lock, flags);
 }
-#endif /* SOFTAP */
 
 static int
 dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
index f3e53bf..30a1cc2 100644 (file)
@@ -479,7 +479,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, bool dongle_isolation);
+static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag);
 
 static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size);
 static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
@@ -4961,8 +4961,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
        if (dhdp->busstate == DHD_BUS_DOWN)
                return FALSE;
 
-       dhd_os_sdlock(bus->dhd);
-
        /* Poll period: check device if appropriate. */
        if (bus->poll && (++bus->polltick >= bus->pollrate)) {
                uint32 intstatus = 0;
@@ -5032,8 +5030,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
                }
        }
 
-       dhd_os_sdunlock(bus->dhd);
-
        return bus->ipend;
 }
 
@@ -5656,7 +5652,7 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
                        dhd_common_deinit(bus->dhd, NULL);
                        dongle_isolation = bus->dhd->dongle_isolation;
                        dhd_detach(bus->dhd);
-                       dhdsdio_release_dongle(bus, osh, dongle_isolation);
+                       dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
                        dhd_free(bus->dhd);
                        bus->dhd = NULL;
                }
@@ -5709,12 +5705,12 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
 
 
 static void
-dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation)
+dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
 {
        DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
                bus->dhd, bus->dhd->dongle_reset));
 
-       if (bus->dhd && bus->dhd->dongle_reset)
+       if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
                return;
 
        if (bus->sih) {
@@ -6137,7 +6133,7 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
 #endif /* defined(OOB_INTR_ONLY) */
 
                        /* Clean tx/rx buffer pointers, detach from the dongle */
-                       dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE);
+                       dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
 
                        bus->dhd->dongle_reset = TRUE;
                        bus->dhd->up = FALSE;
@@ -6182,12 +6178,12 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
                                        /* Restore flow control  */
                                        dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
 #endif 
-                                               dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
+                                       dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
 
                                        DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
                                        } else {
                                                dhd_bus_stop(bus, FALSE);
-                                               dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE);
+                                               dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, FALSE);
                                        }
                                } else
                                        bcmerror = BCME_SDIO_ERROR;
index fd399cb..b64d0bb 100644 (file)
@@ -481,11 +481,7 @@ typedef struct {
 #define DBG_THR(x)
 #endif
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x)
-#else
 #define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x)
-#endif
 
 
 #define PROC_START(thread_func, owner, tsk_ctl, flags) \
index bfbfc88..eda5ddf 100644 (file)
@@ -248,9 +248,13 @@ osl_detach(osl_t *osh)
 
 struct sk_buff *osl_alloc_skb(unsigned int len)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
        gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
 
        return __dev_alloc_skb(len, flags);
+#else
+       return dev_alloc_skb(len);
+#endif
 }
 
 #ifdef CTFPOOL
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
new file mode 100644 (file)
index 0000000..fbae30c
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Linux cfg80211 driver - Android private commands
+ *
+ * Copyright (C) 1999-2011, Broadcom Corporation
+ *
+ *         Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ *      As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module.  An independent module is a module which is not
+ * derived from this software.  The special exception does not apply to any
+ * modifications of the software.
+ *
+ *      Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wl_android.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <wldev_common.h>
+
+/*
+ * Android private command strings, PLEASE define new private commands here
+ * so they can be updated easily in the future (if needed)
+ */
+
+#define CMD_START              "START"
+#define CMD_STOP               "STOP"
+#define        CMD_SCAN_ACTIVE         "SCAN-ACTIVE"
+#define        CMD_SCAN_PASSIVE        "SCAN-PASSIVE"
+#define CMD_RSSI               "RSSI"
+#define CMD_LINKSPEED          "LINKSPEED"
+#define CMD_RXFILTER_START     "RXFILTER-START"
+#define CMD_RXFILTER_STOP      "RXFILTER-STOP"
+#define CMD_BTCOEXSCAN_START   "BTCOEXSCAN-START"
+#define CMD_BTCOEXSCAN_STOP    "BTCOEXSCAN-STOP"
+#define CMD_BTCOEXMODE         "BTCOEXMODE"
+
+typedef struct android_wifi_priv_cmd {
+       char *buf;
+       int used_len;
+       int total_len;
+} android_wifi_priv_cmd;
+
+static int g_wifi_on = 0;
+static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len);
+
+int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+       int ret = 0;
+       char *command = NULL;
+       int bytes_written = 0;
+       android_wifi_priv_cmd *priv_cmd;
+
+       /* net_os_wake_lock(dev); */
+
+       priv_cmd = (android_wifi_priv_cmd*)ifr->ifr_data;
+       if (!priv_cmd)
+       {
+               ret = -EINVAL;
+               goto exit;
+       }
+       command = kmalloc(priv_cmd->total_len, GFP_KERNEL);
+       if (!command)
+       {
+               printk("%s: failed to allocate memory\n", __FUNCTION__);
+               ret = -ENOMEM;
+               goto exit;
+       }
+       if (copy_from_user(command, priv_cmd->buf, priv_cmd->total_len)) {
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       printk("%s: Android private command \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name);
+
+       if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
+               /* TBD: START */
+               printk("%s, Received regular START command\n", __FUNCTION__);
+               g_wifi_on = 1;
+       }
+       if (!g_wifi_on) {
+               /*
+               printk("%s START command has to be called first\n", __FUNCTION__);
+               ret = -EFAULT;
+               goto exit;
+               */
+       }
+       if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
+               /* TBD: STOP */
+       }
+       else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) {
+               /* TBD: SCAN-ACTIVE */
+       }
+       else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) {
+               /* TBD: SCAN-PASSIVE */
+       }
+       else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
+               /* TBD: RSSI */
+       }
+       else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) {
+               bytes_written = wl_android_get_link_speed(net, command, priv_cmd->total_len);
+       }
+       else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) {
+               /* TBD: RXFILTER-START */
+       }
+       else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) {
+               /* TBD: RXFILTER-STOP */
+       }
+       else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) {
+               /* TBD: BTCOEXSCAN-START */
+       }
+       else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) {
+               /* TBD: BTCOEXSCAN-STOP */
+       }
+       else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) {
+               /* TBD: BTCOEXMODE */
+       }
+       else {
+               printk("Unknown PRIVATE command %s - ignored\n", command);
+               snprintf(command, 3, "OK");
+               bytes_written = strlen("OK") + 1;
+       }
+
+       priv_cmd->used_len = bytes_written;
+       if (copy_to_user(priv_cmd->buf, command, bytes_written)) {
+               printk("%s: failed to copy data to user buffer\n", __FUNCTION__);
+       }
+
+exit:
+       /* net_os_wake_unlock(dev); */
+       if (command) {
+               kfree(command);
+       }
+
+       return ret;
+}
+
+static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len)
+{
+       int link_speed;
+       int bytes_written;
+
+       link_speed = wldev_get_link_speed(net);
+
+       /* Convert Kbps to Android Mbps */
+       link_speed = link_speed / 1000;
+       bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
+       printk("%s: command result is %s \n", __FUNCTION__, command);
+       return bytes_written;
+}
index 0af6073..a438cf6 100644 (file)
@@ -1631,8 +1631,8 @@ wl_iw_send_priv_event(
 int
 wl_control_wl_start(struct net_device *dev)
 {
-       int ret = 0;
        wl_iw_t *iw;
+       int ret = 0;
 
        WL_TRACE(("Enter %s \n", __FUNCTION__));
 
@@ -1680,8 +1680,8 @@ wl_iw_control_wl_off(
        struct iw_request_info *info
 )
 {
-       int ret = 0;
        wl_iw_t *iw;
+       int ret = 0;
 
        WL_TRACE(("Enter %s\n", __FUNCTION__));
 
@@ -1769,7 +1769,7 @@ wl_iw_control_wl_on(
        wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
 #endif
 
-       WL_TRACE(("Exited %s \n", __FUNCTION__));
+       WL_TRACE(("Exited %s\n", __FUNCTION__));
 
        return ret;
 }
@@ -1788,8 +1788,6 @@ static int set_ap_mac_list(struct net_device *dev, void *buf);
 static int get_parameter_from_string(
        char **str_ptr, const char *token, int param_type, void  *dst, int param_max_len);
 
-#endif 
-
 static int
 hex2num(char c)
 {
@@ -1826,7 +1824,6 @@ hstr_2_buf(const char *txt, u8 *buf, int len)
 
 
 
-#ifdef SOFTAP
 static int
 init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
 {
@@ -4323,10 +4320,6 @@ wl_iw_iscan_get_scan(
 
        WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
 
-       
-       if (!dwrq->length)
-               return -EAGAIN;
-
        return 0;
 }
 #endif 
index dbe30b2..4d36b8c 100644 (file)
@@ -53,7 +53,7 @@
 #define PNOSETUP_SET_CMD                       "PNOSETUP " 
 #define PNOENABLE_SET_CMD                      "PNOFORCE"
 #define PNODEBUG_SET_CMD                       "PNODEBUG"
-#define TXPOWER_SET_CMD                                "TXPOWER"
+#define TXPOWER_SET_CMD                        "TXPOWER"
 
 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
@@ -227,18 +227,6 @@ extern void get_customized_country_code(char *country_iso_code, wl_country_t *cs
        iwe_stream_add_point(stream, ends, iwe, extra)
 #endif
 
-extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
-extern int dhd_pno_clean(dhd_pub_t *dhd);
-extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid,
-                       ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
-extern int dhd_pno_get_status(dhd_pub_t *dhd);
-extern int dhd_dev_pno_reset(struct net_device *dev);
-extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local,
-                           int nssid, ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
-extern int dhd_dev_pno_enable(struct net_device *dev,  int pfn_enabled);
-extern int dhd_dev_get_pno_status(struct net_device *dev);
-extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
-
 void   dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec);
 
 #define PNO_TLV_PREFIX                 'S'
index c81fcca..1afb54c 100644 (file)
@@ -236,3 +236,19 @@ s32 wldev_iovar_getint_bsscfg(
        }
        return err;
 }
+
+int
+wldev_get_link_speed(
+       struct net_device *dev)
+{
+       int error;
+       int link_speed;
+
+       error = wldev_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed), 0);
+       if (error < 0)
+               return error;
+       /* Convert internal 500Kbps to Kbps */
+       link_speed *= 500;
+
+       return link_speed;
+}
index eae7d24..bb3a12e 100644 (file)
  *  netdev_ops->ndo_do_ioctl in new kernels)
  *  @dev: the net_device handle
  */
-
 s32 wldev_ioctl(
        struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set);
 
 /** Retrieve named IOVARs, this function calls wl_dev_ioctl with 
-    WLC_GET_VAR IOCTL code
+ *  WLC_GET_VAR IOCTL code
  */
 s32 wldev_iovar_getbuf(
        struct net_device *dev, s8 *iovar_name,
        void *param, s32 paramlen, void *buf, s32 buflen);
 
 /** Set named IOVARs, this function calls wl_dev_ioctl with
-    WLC_SET_VAR IOCTL code
+ *  WLC_SET_VAR IOCTL code
  */
 s32 wldev_iovar_setbuf(
        struct net_device *dev, s8 *iovar_name,
@@ -61,7 +60,7 @@ s32 wldev_mkiovar(
 
 
 /** The following function can be implemented if there is a need for bsscfg
-    indexed IOVARs
+ *  indexed IOVARs
  */
 
 s32 wldev_mkiovar_bsscfg(
@@ -69,14 +68,14 @@ s32 wldev_mkiovar_bsscfg(
        s8 *iovar_buf, s32 buflen, s32 bssidx);
 
 /** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
-    WLC_GET_VAR IOCTL code
+ *  WLC_GET_VAR IOCTL code
  */
 s32 wldev_iovar_getbuf_bsscfg(
        struct net_device *dev, s8 *iovar_name,
        void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx);
 
 /** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
-    WLC_SET_VAR IOCTL code
+ *  WLC_SET_VAR IOCTL code
  */
 s32 wldev_iovar_setbuf_bsscfg(
        struct net_device *dev, s8 *iovar_name,
@@ -88,4 +87,7 @@ s32 wldev_iovar_getint_bsscfg(
 s32 wldev_iovar_setint_bsscfg(
        struct net_device *dev, s8 *iovar, s32 val, s32 bssidx);
 
+/* Get the link speed from dongle, a minus number indicating an error, speed is in kpbs */ 
+int wldev_get_link_speed(struct net_device *dev);
+
 #endif /* __WLDEV_COMMON_H__ */