summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward M. Harte <hharte@broadcom.com>2011-06-15 18:52:15 -0700
committerDmitry Shmidt <dimitrysh@google.com>2011-06-17 10:42:54 -0700
commit0d9f3c2791c1e19796d3a41d8ec45093583817e7 (patch)
treee39143aca1da3943af7945677dd79f1ae6811ebf
parent097d39641dc94f9e5891481e066ef14b12cca408 (diff)
net: wireless: bcmdhd: Combined patch from 4.218.248-31
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>
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile7
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h18
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_custom_gpio.c10
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c99
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c18
-rw-r--r--drivers/net/wireless/bcmdhd/include/linuxver.h4
-rw-r--r--drivers/net/wireless/bcmdhd/linux_osl.c4
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c160
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c13
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.h14
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.c16
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.h14
12 files changed, 268 insertions, 109 deletions
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index b476372772f..fc5a02f2e32 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -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)
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index 9033da9f717..f7a103acc44 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -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 */
diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
index 76587a15710..9958513cfef 100644
--- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
@@ -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)) */
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 7d78bae0df0..57f38ee40fa 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -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)
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index f3e53bf4559..30a1cc22b26 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -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;
diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h
index fd399cbf277..b64d0bb6a00 100644
--- a/drivers/net/wireless/bcmdhd/include/linuxver.h
+++ b/drivers/net/wireless/bcmdhd/include/linuxver.h
@@ -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) \
diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c
index bfbfc88342a..eda5ddffd32 100644
--- a/drivers/net/wireless/bcmdhd/linux_osl.c
+++ b/drivers/net/wireless/bcmdhd/linux_osl.c
@@ -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
index 00000000000..fbae30cd695
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -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;
+}
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index 0af60732dca..a438cf6f1e7 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -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
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h
index dbe30b20df0..4d36b8c0aee 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.h
+++ b/drivers/net/wireless/bcmdhd/wl_iw.h
@@ -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'
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
index c81fccad6c2..1afb54c1454 100644
--- a/drivers/net/wireless/bcmdhd/wldev_common.c
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -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;
+}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h
index eae7d24f9e3..bb3a12eda94 100644
--- a/drivers/net/wireless/bcmdhd/wldev_common.h
+++ b/drivers/net/wireless/bcmdhd/wldev_common.h
@@ -30,19 +30,18 @@
* 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__ */