summaryrefslogtreecommitdiffstats
path: root/bcm4329
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2010-12-13 10:14:41 -0800
committerDmitry Shmidt <dimitrysh@google.com>2010-12-13 10:14:41 -0800
commit65cd10f45530f4fec55626eea045ca1687caada2 (patch)
tree0aab48b17ea333a63e2d0e7cf46c4bc8730296f0 /bcm4329
parent18a209f7ff1acb82ed370c5853369e5eb454fb06 (diff)
downloadhardware_broadcom_wlan-65cd10f45530f4fec55626eea045ca1687caada2.zip
hardware_broadcom_wlan-65cd10f45530f4fec55626eea045ca1687caada2.tar.gz
hardware_broadcom_wlan-65cd10f45530f4fec55626eea045ca1687caada2.tar.bz2
bcm4329: Update to Version 4.218.248-17
=== Firmware ============ 1) Increase internal Memory Heap for dual-band STA 2) Fix problem with PNO for -minioctl- firmware flavor 3) Fix SoftAP white list MAC filtering 4) Fix problem with timer for 11N/AMPDU 5) Added FW flavor "sdio-ag-cdc-full11n-minioctl-roml-wme-aoe-pktfilter-keepalive.bin" (w/o PNO) === Driver ============ 1) Add CONFIG_FIRST_SCAN option with special CONFIG_FIRST_SCAN compilation flag 2) Fix SoftAP white list MAC filtering 3) Fix watchdog synchronization during start/stop Change-Id: Icc470d9b18fd86f928abdef5cfdad4031a8e3b3e Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'bcm4329')
-rw-r--r--bcm4329/firmware/fw_bcm4329.binbin249144 -> 249060 bytes
-rw-r--r--bcm4329/firmware/fw_bcm4329_abg.binbin266219 -> 263547 bytes
-rw-r--r--bcm4329/firmware/fw_bcm4329_apsta.binbin249503 -> 249371 bytes
-rw-r--r--bcm4329/src/bcmsdio/linux/Makefile2
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_linux.c5
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c1
-rw-r--r--bcm4329/src/dhd/linux/Makefile4
-rw-r--r--bcm4329/src/dhd/sys/dhd.h16
-rw-r--r--bcm4329/src/dhd/sys/dhd_bus.h4
-rw-r--r--bcm4329/src/dhd/sys/dhd_common.c137
-rw-r--r--bcm4329/src/dhd/sys/dhd_linux.c266
-rw-r--r--bcm4329/src/dhd/sys/dhd_sdio.c94
-rw-r--r--bcm4329/src/include/epivers.h10
-rw-r--r--bcm4329/src/include/proto/bcmevent.h11
-rw-r--r--bcm4329/src/include/wlioctl.h3
-rw-r--r--bcm4329/src/wl/sys/wl_iw.c1076
-rw-r--r--bcm4329/src/wl/sys/wl_iw.h36
17 files changed, 1174 insertions, 491 deletions
diff --git a/bcm4329/firmware/fw_bcm4329.bin b/bcm4329/firmware/fw_bcm4329.bin
index a9bf2b7..1418c79 100644
--- a/bcm4329/firmware/fw_bcm4329.bin
+++ b/bcm4329/firmware/fw_bcm4329.bin
Binary files differ
diff --git a/bcm4329/firmware/fw_bcm4329_abg.bin b/bcm4329/firmware/fw_bcm4329_abg.bin
index 8cf8423..928308f 100644
--- a/bcm4329/firmware/fw_bcm4329_abg.bin
+++ b/bcm4329/firmware/fw_bcm4329_abg.bin
Binary files differ
diff --git a/bcm4329/firmware/fw_bcm4329_apsta.bin b/bcm4329/firmware/fw_bcm4329_apsta.bin
index 74b70da..a84bc8c 100644
--- a/bcm4329/firmware/fw_bcm4329_apsta.bin
+++ b/bcm4329/firmware/fw_bcm4329_apsta.bin
Binary files differ
diff --git a/bcm4329/src/bcmsdio/linux/Makefile b/bcm4329/src/bcmsdio/linux/Makefile
index 41ed016..0b507ff 100644
--- a/bcm4329/src/bcmsdio/linux/Makefile
+++ b/bcm4329/src/bcmsdio/linux/Makefile
@@ -21,7 +21,7 @@
# 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: Makefile,v 1.5.8.4.6.1 2009/01/26 20:28:33 Exp $
+# $Id: Makefile,v 1.5.8.4.6.2 2010/04/09 23:54:38 Exp $
#
# Try a couple of places for LINUXDIR if not specified
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
index 559f481..3b7da42 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
@@ -581,8 +581,6 @@ bcmsdh_unregister(void)
#endif /* BCMPLATFORM_BUS */
}
-
-
#if defined(OOB_INTR_ONLY)
void bcmsdh_oob_intr_set(bool enable)
{
@@ -624,6 +622,9 @@ int bcmsdh_register_oob_intr(void * dhdp)
SDLX_MSG(("%s Enter\n", __FUNCTION__));
+/* Example of HW_OOB for HW2: please refer to your host specifiction */
+/* sdhcinfo->oob_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; */
+
dev_set_drvdata(sdhcinfo->dev, dhdp);
if (!sdhcinfo->oob_irq_registered) {
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
index bda9193..031367b 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
@@ -675,7 +675,6 @@ sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
data = 3; /* enable hw oob interrupt */
else
data = 4; /* disable hw oob interrupt */
-
data |= 4; /* Active HIGH */
status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
diff --git a/bcm4329/src/dhd/linux/Makefile b/bcm4329/src/dhd/linux/Makefile
index 4d5a957..224b41e 100644
--- a/bcm4329/src/dhd/linux/Makefile
+++ b/bcm4329/src/dhd/linux/Makefile
@@ -21,7 +21,7 @@
# 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: Makefile,v 1.55.2.6.2.10.6.42 2010/08/20 00:15:16 Exp $
+# $Id: Makefile,v 1.55.2.6.2.10.6.42.4.2 2010/12/02 01:23:07 Exp $
#
# Try a couple of places for LINUXDIR if not specified
@@ -237,7 +237,9 @@ DFLAGS += -DCUSTOM_OOB_GPIO_NUM=152
DFLAGS += -DOOB_INTR_ONLY
DFLAGS += -DMMC_SDIO_ABORT
DFLAGS += -DSOFTAP
+DFLAGS += -DKEEP_ALIVE
DFLAGS += -DPNO_SUPPORT
+DFLAGS += -DCONFIG_FIRST_SCAN
else
ifneq ($(findstring -oob-,-$(TARGET)-),)
DFLAGS += -DOOB_INTR_ONLY
diff --git a/bcm4329/src/dhd/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h
index cc7e8cb..1ddf1ff 100644
--- a/bcm4329/src/dhd/sys/dhd.h
+++ b/bcm4329/src/dhd/sys/dhd.h
@@ -24,7 +24,7 @@
* 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: dhd.h,v 1.32.4.7.2.4.14.49 2010/08/20 17:32:48 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.7 2010/11/12 22:48:36 Exp $
*/
/****************
@@ -86,9 +86,11 @@ enum dhd_bus_wake_state {
WAKE_LOCK_TMOUT,
WAKE_LOCK_WATCHDOG,
WAKE_LOCK_LINK_DOWN_TMOUT,
+ WAKE_LOCK_PNO_FIND_TMOUT,
WAKE_LOCK_SOFTAP_SET,
WAKE_LOCK_SOFTAP_STOP,
WAKE_LOCK_SOFTAP_START,
+ WAKE_LOCK_SOFTAP_THREAD,
WAKE_LOCK_MAX
};
enum dhd_prealloc_index {
@@ -218,6 +220,11 @@ 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);
+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);
+
typedef struct dhd_if_event {
uint8 ifidx;
uint8 action;
@@ -345,8 +352,11 @@ typedef enum cust_gpio_modes {
WLAN_POWER_ON,
WLAN_POWER_OFF
} cust_gpio_modes_t;
+
extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
extern int wl_iw_send_priv_event(struct net_device *dev, char *flag);
+extern int net_os_send_hang_message(struct net_device *dev);
+
/*
* Insmod parameters for debug/test
*/
@@ -396,6 +406,10 @@ extern uint dhd_sdiod_drive_strength;
/* Override to force tx queueing all the time */
extern uint dhd_force_tx_queueing;
+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
+#define KEEP_ALIVE_PERIOD 55000
+#define NULL_PKT_STR "null_pkt"
+
#ifdef SDTEST
/* Echo packet generator (SDIO), pkts/s */
extern uint dhd_pktgen;
diff --git a/bcm4329/src/dhd/sys/dhd_bus.h b/bcm4329/src/dhd/sys/dhd_bus.h
index 9e29fb9..97af41b 100644
--- a/bcm4329/src/dhd/sys/dhd_bus.h
+++ b/bcm4329/src/dhd/sys/dhd_bus.h
@@ -24,7 +24,7 @@
* 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: dhd_bus.h,v 1.4.6.3.2.3.6.6 2010/05/17 18:18:13 Exp $
+ * $Id: dhd_bus.h,v 1.4.6.3.2.3.6.7 2010/08/13 01:35:24 Exp $
*/
#ifndef _dhd_bus_h_
@@ -63,7 +63,7 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
#ifdef DHD_DEBUG
/* Device console input function */
extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
-#endif
+#endif /* DHD_DEBUG */
/* Deferred processing for the bus, return TRUE requests reschedule */
extern bool dhd_bus_dpc(struct dhd_bus *bus);
diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c
index bea33b6..b8bab30 100644
--- a/bcm4329/src/dhd/sys/dhd_common.c
+++ b/bcm4329/src/dhd/sys/dhd_common.c
@@ -21,7 +21,7 @@
* 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: dhd_common.c,v 1.5.6.8.2.6.6.69.4.3 2010/09/10 21:30:16 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.16 2010/11/18 03:53:32 Exp $
*/
#include <typedefs.h>
#include <osl.h>
@@ -71,6 +71,11 @@ extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen);
void dhd_iscan_lock(void);
void dhd_iscan_unlock(void);
+#if defined(KEEP_ALIVE)
+extern bool ap_fw_loaded;
+int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on);
+#endif /* KEEP_ALIVE */
+
/* Packet alignment for most efficient SDIO (can change based on platform) */
#ifndef DHD_SDALIGN
#define DHD_SDALIGN 32
@@ -1225,8 +1230,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint bcn_timeout = 3;
int scan_assoc_time = 40;
int scan_unassoc_time = 40;
+ uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
+ int ret = 0;
#ifdef GET_CUSTOM_MAC_ENABLE
- int ret;
struct ether_addr ea_addr;
#endif /* GET_CUSTOM_MAC_ENABLE */
@@ -1253,7 +1259,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#ifdef SET_RANDOM_MAC_SOFTAP
if (strstr(fw_path, "apsta") != NULL) {
uint rand_mac;
- int ret;
srandom32((uint)jiffies);
rand_mac = random32();
@@ -1284,6 +1289,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
}
}
+ /* Set Listen Interval */
+ bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0)
+ DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret));
+
/* query for 'ver' to get version info from firmware */
memset(buf, 0, sizeof(buf));
ptr = buf;
@@ -1392,6 +1402,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
}
#endif /* PKT_FILTER_SUPPORT */
+#if defined(KEEP_ALIVE)
+ {
+ /* Set Keep Alive : be sure to use FW with -keepalive */
+ int res;
+
+ if (ap_fw_loaded == FALSE) {
+ if ((res = dhd_keep_alive_onoff(dhd, 1)) < 0)
+ DHD_ERROR(("%s set keeplive failed %d\n", \
+ __FUNCTION__, res));
+ }
+ }
+#endif
+
dhd_os_proto_unblock(dhd);
return 0;
@@ -1446,7 +1469,7 @@ dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
dhd_pub_t *dhd = dhd_bus_pub(dhdp);
dhd_iscan_lock();
- /* If iscan_delete is null then delete the entire
+ /* If iscan_delete is null then delete the entire
* chain or else delete specific one provided
*/
if (!iscan_delete) {
@@ -1779,6 +1802,57 @@ fail:
#endif
+/* Function to estimate possible DTIM_SKIP value */
+int dhd_get_dtim_skip(dhd_pub_t *dhd)
+{
+ int bcn_li_dtim;
+ char buf[128];
+ int ret;
+ int dtim_assoc = 0;
+
+ if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1))
+ bcn_li_dtim = 3;
+ else
+ bcn_li_dtim = dhd->dtim_skip;
+
+ /* Read DTIM value if associated */
+ memset(buf, 0, sizeof(buf));
+ bcm_mkiovar("dtim_assoc", 0, 0, buf, sizeof(buf));
+ if ((ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf))) < 0) {
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+ bcn_li_dtim = 1;
+ goto exit;
+ }
+ else
+ dtim_assoc = dtoh32(*(int *)buf);
+
+ DHD_ERROR(("%s bcn_li_dtim=%d DTIM=%d Listen=%d\n", \
+ __FUNCTION__, bcn_li_dtim, dtim_assoc, LISTEN_INTERVAL));
+
+ /* if not assocated just eixt */
+ if (dtim_assoc == 0) {
+ goto exit;
+ }
+
+ /* check if sta listen interval fits into AP dtim */
+ if (dtim_assoc > LISTEN_INTERVAL) {
+ /* AP DTIM to big for our Listen Interval : no dtim skiping */
+ bcn_li_dtim = 1;
+ DHD_ERROR(("%s DTIM=%d > Listen=%d : too big ...\n", \
+ __FUNCTION__, dtim_assoc, LISTEN_INTERVAL));
+ goto exit;
+ }
+
+ if ((bcn_li_dtim * dtim_assoc) > LISTEN_INTERVAL) {
+ /* Round up dtim_skip to fit into STAs Listen Interval */
+ bcn_li_dtim = (int)(LISTEN_INTERVAL / dtim_assoc);
+ DHD_TRACE(("%s agjust dtim_skip as %d\n", __FUNCTION__, bcn_li_dtim));
+ }
+
+exit:
+ return bcn_li_dtim;
+}
+
#ifdef PNO_SUPPORT
int dhd_pno_clean(dhd_pub_t *dhd)
{
@@ -1885,6 +1959,11 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr)
if (scan_fr != 0)
pfn_param.scan_freq = htod32(scan_fr);
+ if (pfn_param.scan_freq > PNO_SCAN_MAX_FW) {
+ DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW));
+ return err;
+ }
+
bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
@@ -1909,6 +1988,9 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr)
__FUNCTION__, i, err));
return err;
}
+ else
+ DHD_ERROR(("%s set OK with PNO time=%d\n", __FUNCTION__, \
+ pfn_param.scan_freq));
}
else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err));
}
@@ -1930,6 +2012,53 @@ int dhd_pno_get_status(dhd_pub_t *dhd)
#endif /* PNO_SUPPORT */
+#if defined(KEEP_ALIVE)
+int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on)
+{
+ char buf[256];
+ char *buf_ptr = buf;
+ wl_keep_alive_pkt_t keep_alive_pkt;
+ char * str;
+ int str_len, buf_len;
+ int res = 0;
+ int keep_alive_period = KEEP_ALIVE_PERIOD; /* in ms */
+
+ DHD_TRACE(("%s: ka:%d\n", __FUNCTION__, ka_on));
+
+ if (ka_on) { /* on suspend */
+ keep_alive_pkt.period_msec = keep_alive_period;
+
+ } else {
+ /* on resume, turn off keep_alive packets */
+ keep_alive_pkt.period_msec = 0;
+ }
+
+ /* IOC var name */
+ str = "keep_alive";
+ str_len = strlen(str);
+ strncpy(buf, str, str_len);
+ buf[str_len] = '\0';
+ buf_len = str_len + 1;
+
+ /* set ptr to IOCTL payload after the var name */
+ buf_ptr += buf_len; /* include term Z */
+
+ /* copy Keep-alive attributes from local var keep_alive_pkt */
+ str = NULL_PKT_STR;
+ keep_alive_pkt.len_bytes = strlen(str);
+
+ memcpy(buf_ptr, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN);
+ buf_ptr += WL_KEEP_ALIVE_FIXED_LEN;
+
+ /* copy packet data */
+ memcpy(buf_ptr, str, keep_alive_pkt.len_bytes);
+ buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes);
+
+ res = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+ return res;
+}
+#endif /* defined(KEEP_ALIVE) */
+
#if defined(CSCAN)
/* Androd ComboSCAN support */
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index f687b31..c7ef3ed 100644
--- a/bcm4329/src/dhd/sys/dhd_linux.c
+++ b/bcm4329/src/dhd/sys/dhd_linux.c
@@ -22,7 +22,7 @@
* 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: dhd_linux.c,v 1.65.4.9.2.12.2.104 2010/08/20 19:15:40 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.35 2010/11/17 03:13:21 Exp $
*/
#ifdef CONFIG_WIFI_CONTROL_FUNC
@@ -106,7 +106,7 @@ int wifi_set_power(int on, unsigned long msec)
int wifi_set_reset(int on, unsigned long msec)
{
- printk("%s = %d\n", __FUNCTION__, on);
+ DHD_TRACE(("%s = %d\n", __FUNCTION__, on));
if (wifi_control_data && wifi_control_data->set_reset) {
wifi_control_data->set_reset(on);
}
@@ -117,7 +117,7 @@ int wifi_set_reset(int on, unsigned long msec)
int wifi_get_mac_addr(unsigned char *buf)
{
- printk("%s\n", __FUNCTION__);
+ DHD_TRACE(("%s\n", __FUNCTION__));
if (!buf)
return -EINVAL;
if (wifi_control_data && wifi_control_data->get_mac_addr) {
@@ -217,9 +217,10 @@ print_tainted()
#include <wl_iw.h>
#endif /* defined(CONFIG_WIRELESS_EXT) */
+extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
+
#if defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
#ifdef PKT_FILTER_SUPPORT
@@ -260,6 +261,8 @@ typedef struct dhd_info {
struct tasklet_struct tasklet;
spinlock_t sdlock;
spinlock_t txqlock;
+ spinlock_t dhd_lock;
+
/* Thread based operation */
bool threads_only;
struct semaphore sdsem;
@@ -279,8 +282,10 @@ typedef struct dhd_info {
int wl_count;
int wl_packet;
- int hang_was_sent;
-
+ int hang_was_sent; /* flag that message was send at least once */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ struct mutex wl_start_lock; /* mutex when START called to prevent any other Linux calls */
+#endif
/* Thread to issue ioctl for multicast */
long sysioc_pid;
struct semaphore sysioc_sem;
@@ -304,7 +309,7 @@ char nvram_path[MOD_PARAM_PATHLEN];
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
struct semaphore dhd_registration_sem;
-#define DHD_REGISTRATION_TIMEOUT 8000 /* msec : allowed time to finished dhd registration */
+#define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
/* load firmware and/or nvram values from the filesystem */
module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
@@ -518,6 +523,8 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
#endif
}
+
+
#if defined(CONFIG_HAS_EARLYSUSPEND)
static int dhd_set_suspend(int value, dhd_pub_t *dhd)
{
@@ -536,7 +543,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
if (value && dhd->in_suspend) {
/* Kernel suspended */
- DHD_TRACE(("%s: force extra Suspend setting \n", __FUNCTION__));
+ DHD_TRACE(("%s: force extra Suspend setting \n", __FUNCTION__));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
(char *)&power_mode, sizeof(power_mode));
@@ -544,26 +551,24 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
/* Enable packet filter, only allow unicast packet to send up */
dhd_set_packet_filter(1, dhd);
- /* if dtim skip setup as default force it to wake each thrid dtim
- * for better power saving.
- * Note that side effect is chance to miss BC/MC packet
- */
- if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1))
- bcn_li_dtim = 3;
- else
- bcn_li_dtim = dhd->dtim_skip;
+ /* if dtim skip setup as default force it to wake each thrid dtim
+ * for better power saving.
+ * Note that side effect is chance to miss BC/MC packet
+ */
+ bcn_li_dtim = dhd_get_dtim_skip(dhd);
bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
4, iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
#ifdef CUSTOMER_HW2
- /* Disable build-in roaming to allowed ext supplicant to take of roaming */
+ /* Disable build-in roaming during suspend */
bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
#endif /* CUSTOMER_HW2 */
+
} else {
/* Kernel resumed */
- DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__));
+ DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__));
power_mode = PM_FAST;
dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
@@ -572,11 +577,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
/* disable pkt filter */
dhd_set_packet_filter(0, dhd);
- /* restore pre-suspend setting for dtim_skip */
- bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
- 4, iovbuf, sizeof(iovbuf));
+ /* restore pre-suspend setting for dtim_skip */
+ bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
+ 4, iovbuf, sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
#ifdef CUSTOMER_HW2
roamvar = dhd_roam;
bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
@@ -898,13 +903,18 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr)
#ifdef SOFTAP
extern struct net_device *ap_net_dev;
+/* semaphore that the soft AP CODE waits on */
+extern struct semaphore ap_eth_sema;
#endif
static void
dhd_op_if(dhd_if_t *ifp)
{
- dhd_info_t *dhd;
- int ret = 0, err = 0;
+ dhd_info_t *dhd;
+ int ret = 0, err = 0;
+#ifdef SOFTAP
+ unsigned long flags;
+#endif
ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */
@@ -939,13 +949,12 @@ dhd_op_if(dhd_if_t *ifp)
ret = -EOPNOTSUPP;
} else {
#ifdef SOFTAP
- /* semaphore that the soft AP CODE waits on */
- extern struct semaphore ap_eth_sema;
-
+ flags = dhd_os_spin_lock(&dhd->pub);
/* save ptr to wl0.1 netdev for use in wl_iw.c */
ap_net_dev = ifp->net;
/* signal to the SOFTAP 'sleeper' thread, wl0.1 is ready */
up(&ap_eth_sema);
+ dhd_os_spin_unlock(&dhd->pub, flags);
#endif
DHD_TRACE(("\n ==== pid:%x, net_device for if:%s created ===\n\n",
current->pid, ifp->net->name));
@@ -974,8 +983,10 @@ dhd_op_if(dhd_if_t *ifp)
dhd->iflist[ifp->idx] = NULL;
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
#ifdef SOFTAP
+ flags = dhd_os_spin_lock(&dhd->pub);
if (ifp->net == ap_net_dev)
ap_net_dev = NULL; /* NULL SOFTAP global as well */
+ dhd_os_spin_unlock(&dhd->pub, flags);
#endif /* SOFTAP */
}
}
@@ -987,16 +998,21 @@ _dhd_sysioc_thread(void *data)
int i;
#ifdef SOFTAP
bool in_ap = FALSE;
+ unsigned long flags;
#endif
DAEMONIZE("dhd_sysioc");
while (down_interruptible(&dhd->sysioc_sem) == 0) {
+ dhd_os_start_lock(&dhd->pub);
dhd_os_wake_lock(&dhd->pub);
for (i = 0; i < DHD_MAX_IFS; i++) {
if (dhd->iflist[i]) {
+ DHD_TRACE(("%s: interface %d\n",__FUNCTION__, i));
#ifdef SOFTAP
+ flags = dhd_os_spin_lock(&dhd->pub);
in_ap = (ap_net_dev != NULL);
+ dhd_os_spin_unlock(&dhd->pub, flags);
#endif /* SOFTAP */
if (dhd->iflist[i]->state)
dhd_op_if(dhd->iflist[i]);
@@ -1029,7 +1045,9 @@ _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(&dhd->sysioc_exited, 0);
}
@@ -1042,6 +1060,7 @@ dhd_set_mac_address(struct net_device *dev, void *addr)
struct sockaddr *sa = (struct sockaddr *)addr;
int ifidx;
+ DHD_TRACE(("%s: Enter\n",__FUNCTION__));
ifidx = dhd_net2idx(dhd, dev);
if (ifidx == DHD_BAD_IF)
return -1;
@@ -1060,6 +1079,7 @@ dhd_set_multicast_list(struct net_device *dev)
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
int ifidx;
+ DHD_TRACE(("%s: Enter\n",__FUNCTION__));
ifidx = dhd_net2idx(dhd, dev);
if (ifidx == DHD_BAD_IF)
return;
@@ -1379,22 +1399,24 @@ dhd_watchdog_thread(void *data)
/* Run until signal received */
while (1) {
if (down_interruptible (&dhd->watchdog_sem) == 0) {
-
+ dhd_os_sdlock(&dhd->pub);
if (dhd->pub.dongle_reset == FALSE) {
+ DHD_TIMER(("%s:\n", __FUNCTION__));
/* Call the bus module watchdog */
dhd_bus_watchdog(&dhd->pub);
- }
- /* Count the tick for reference */
- dhd->pub.tickcnt++;
- /* Reschedule the watchdog */
- if (dhd->wd_timer_valid)
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ /* Count the tick for reference */
+ dhd->pub.tickcnt++;
+ /* Reschedule the watchdog */
+ if (dhd->wd_timer_valid)
+ mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ }
+ dhd_os_sdunlock(&dhd->pub);
dhd_os_wake_unlock(&dhd->pub);
- }
- else
+ } else {
break;
+ }
}
complete_and_exit(&dhd->watchdog_exited, 0);
@@ -1406,11 +1428,17 @@ dhd_watchdog(ulong data)
dhd_info_t *dhd = (dhd_info_t *)data;
dhd_os_wake_lock(&dhd->pub);
+ if (dhd->pub.dongle_reset) {
+ dhd_os_wake_unlock(&dhd->pub);
+ return;
+ }
+
if (dhd->watchdog_pid >= 0) {
up(&dhd->watchdog_sem);
return;
}
+ dhd_os_sdlock(&dhd->pub);
/* Call the bus module watchdog */
dhd_bus_watchdog(&dhd->pub);
@@ -1420,6 +1448,7 @@ dhd_watchdog(ulong data)
/* Reschedule the watchdog */
if (dhd->wd_timer_valid)
mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ dhd_os_sdunlock(&dhd->pub);
dhd_os_wake_unlock(&dhd->pub);
}
@@ -1844,7 +1873,7 @@ dhd_stop(struct net_device *net)
#if !defined(IGNORE_ETH0_DOWN)
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
- DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ DHD_TRACE(("%s: Enter %s\n", __FUNCTION__, net->name));
if (dhd->pub.up == 0) {
return 0;
}
@@ -1869,7 +1898,8 @@ dhd_open(struct net_device *net)
#endif
int ifidx;
- wl_control_wl_start(net); /* start if needed */
+ /* Force start if ifconfig_up gets called before START command */
+ wl_control_wl_start(net);
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
@@ -1879,7 +1909,6 @@ dhd_open(struct net_device *net)
return -1;
}
-
if (ifidx == 0) { /* do it only for primary eth0 */
atomic_set(&dhd->pend_8021x_cnt, 0);
@@ -2037,6 +2066,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
/* Initialize the spinlocks */
spin_lock_init(&dhd->sdlock);
spin_lock_init(&dhd->txqlock);
+ spin_lock_init(&dhd->dhd_lock);
/* Initialize Wakelock stuff */
spin_lock_init(&dhd->wl_lock);
@@ -2046,7 +2076,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
#endif
-
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_init(&dhd->wl_start_lock);
+#endif
/* Link to info module */
dhd->pub.info = dhd;
@@ -2175,8 +2207,8 @@ dhd_bus_start(dhd_pub_t *dhdp)
#if defined(OOB_INTR_ONLY)
/* Host registration for OOB interrupt */
if (bcmsdh_register_oob_intr(dhdp)) {
- del_timer_sync(&dhd->timer);
dhd->wd_timer_valid = FALSE;
+ del_timer_sync(&dhd->timer);
DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__));
return -ENODEV;
}
@@ -2187,8 +2219,8 @@ dhd_bus_start(dhd_pub_t *dhdp)
/* If bus is not ready, can't come up */
if (dhd->pub.busstate != DHD_BUS_DATA) {
- del_timer_sync(&dhd->timer);
dhd->wd_timer_valid = FALSE;
+ del_timer_sync(&dhd->timer);
DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
return -ENODEV;
}
@@ -2216,6 +2248,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
setbit(dhdp->eventmask, WLC_E_TXFAIL);
setbit(dhdp->eventmask, WLC_E_JOIN_START);
setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
+ setbit(dhdp->eventmask, WLC_E_RELOAD);
#ifdef PNO_SUPPORT
setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
#endif /* PNO_SUPPORT */
@@ -2353,6 +2386,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
#if defined(CONFIG_WIRELESS_EXT)
+#if defined(CONFIG_FIRST_SCAN)
#ifdef SOFTAP
if (ifidx == 0)
/* Don't call for SOFTAP Interface in SOFTAP MODE */
@@ -2360,6 +2394,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
#else
wl_iw_iscan_set_scan_broadcast_prep(net, 1);
#endif /* SOFTAP */
+#endif /* CONFIG_FIRST_SCAN */
#endif /* CONFIG_WIRELESS_EXT */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
@@ -2396,8 +2431,8 @@ dhd_bus_detach(dhd_pub_t *dhdp)
#endif /* defined(OOB_INTR_ONLY) */
/* Clear the watchdog timer */
- del_timer_sync(&dhd->timer);
dhd->wd_timer_valid = FALSE;
+ del_timer_sync(&dhd->timer);
}
}
}
@@ -2423,16 +2458,18 @@ dhd_detach(dhd_pub_t *dhdp)
/* Attach and link in the iw */
wl_iw_detach();
#endif
-
- for (i = 1; i < DHD_MAX_IFS; i++)
- if (dhd->iflist[i])
- dhd_del_if(dhd, i);
-
if (dhd->sysioc_pid >= 0) {
KILL_PROC(dhd->sysioc_pid, SIGTERM);
wait_for_completion(&dhd->sysioc_exited);
}
+ for (i = 1; i < DHD_MAX_IFS; i++)
+ if (dhd->iflist[i]) {
+ dhd->iflist[i]->state = WLC_E_IF_DEL;
+ dhd->iflist[i]->idx = i;
+ dhd_op_if(dhd->iflist[i]);
+ }
+
ifp = dhd->iflist[0];
ASSERT(ifp);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
@@ -2661,29 +2698,28 @@ void
dhd_os_wd_timer(void *bus, uint wdtick)
{
dhd_pub_t *pub = bus;
- static uint save_dhd_watchdog_ms = 0;
dhd_info_t *dhd = (dhd_info_t *)pub->info;
+ unsigned long flags;
+ int del_timer_flag = FALSE;
- /* don't start the wd until fw is loaded */
- if (pub->busstate == DHD_BUS_DOWN)
- return;
+ flags = dhd_os_spin_lock(pub);
- /* Totally stop the timer */
- if (!wdtick && dhd->wd_timer_valid == TRUE) {
- del_timer_sync(&dhd->timer);
- dhd->wd_timer_valid = FALSE;
- save_dhd_watchdog_ms = wdtick;
- return;
+ /* don't start the wd until fw is loaded */
+ if (pub->busstate != DHD_BUS_DOWN) {
+ if (wdtick) {
+ dhd_watchdog_ms = (uint)wdtick;
+ dhd->wd_timer_valid = TRUE;
+ /* Re arm the timer, at last watchdog period */
+ mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ } else if (dhd->wd_timer_valid == TRUE) {
+ /* Totally stop the timer */
+ dhd->wd_timer_valid = FALSE;
+ del_timer_flag = TRUE;
+ }
}
-
- if (wdtick) {
- dhd_watchdog_ms = (uint)wdtick;
-
- /* Re arm the timer, at last watchdog period */
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-
- dhd->wd_timer_valid = TRUE;
- save_dhd_watchdog_ms = wdtick;
+ dhd_os_spin_unlock(pub, flags);
+ if (del_timer_flag) {
+ del_timer_sync(&dhd->timer);
}
}
@@ -2897,20 +2933,18 @@ void dhd_wait_event_wakeup(dhd_pub_t *dhd)
int
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);
+ int ret;
- dhd_bus_devreset(&dhd->pub, flag);
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- /* Turning on watchdog back */
- if (!flag)
- dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
- DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__));
+ ret = dhd_bus_devreset(&dhd->pub, flag);
+ if (ret) {
+ DHD_ERROR(("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret));
+ return ret;
+ }
+ DHD_ERROR(("%s: WLAN %s DONE\n", __FUNCTION__, flag ? "OFF" : "ON"));
- return 1;
+ return ret;
}
int net_os_set_suspend_disable(struct net_device *dev, int val)
@@ -3021,6 +3055,57 @@ dhd_dev_get_pno_status(struct net_device *dev)
#endif /* PNO_SUPPORT */
+int net_os_send_hang_message(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd) {
+ if (!dhd->hang_was_sent) {
+ dhd->hang_was_sent = 1;
+ ret = wl_iw_send_priv_event(dev, "HANG");
+ }
+ }
+ return ret;
+}
+
+void dhd_bus_country_set(struct net_device *dev, char *country_code)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (dhd && dhd->pub.up)
+ strncpy(dhd->pub.country_code, country_code, WLC_CNTRY_BUF_SZ);
+}
+
+char *dhd_bus_country_get(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (dhd && (dhd->pub.country_code[0] != 0))
+ return dhd->pub.country_code;
+ return NULL;
+}
+
+void dhd_os_start_lock(dhd_pub_t *pub)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd)
+ mutex_lock(&dhd->wl_start_lock);
+#endif
+}
+
+void dhd_os_start_unlock(dhd_pub_t *pub)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd)
+ mutex_unlock(&dhd->wl_start_lock);
+#endif
+}
+
static int
dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
{
@@ -3203,16 +3288,21 @@ int net_os_wake_unlock(struct net_device *dev)
return ret;
}
-int net_os_send_hang_message(struct net_device *dev)
+unsigned long dhd_os_spin_lock(dhd_pub_t *pub)
{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int ret = 0;
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags = 0;
- if (dhd) {
- if (!dhd->hang_was_sent) {
- dhd->hang_was_sent = 1;
- ret = wl_iw_send_priv_event(dev, "HANG");
- }
- }
- return ret;
+ if (dhd)
+ spin_lock_irqsave(&dhd->dhd_lock, flags);
+
+ return flags;
+}
+
+void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd)
+ spin_unlock_irqrestore(&dhd->dhd_lock, flags);
}
diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c
index ff1bded..ac46ca9 100644
--- a/bcm4329/src/dhd/sys/dhd_sdio.c
+++ b/bcm4329/src/dhd/sys/dhd_sdio.c
@@ -438,7 +438,7 @@ static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
void * regsva, uint16 devid);
static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
-static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh);
+static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, int reset_flag);
static uint process_nvram_vars(char *varbuf, uint len);
@@ -705,6 +705,7 @@ dhdsdio_sdclk(dhd_bus_t *bus, bool on)
static int
dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
{
+ int ret = BCME_OK;
#ifdef DHD_DEBUG
uint oldstate = bus->clkstate;
#endif /* DHD_DEBUG */
@@ -717,7 +718,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
bus->activity = TRUE;
}
- return BCME_OK;
+ return ret;
}
switch (target) {
@@ -726,29 +727,32 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
if (bus->clkstate == CLK_NONE)
dhdsdio_sdclk(bus, TRUE);
/* Now request HT Avail on the backplane */
- dhdsdio_htclk(bus, TRUE, pendok);
- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
- bus->activity = TRUE;
+ ret = dhdsdio_htclk(bus, TRUE, pendok);
+ if (ret == BCME_OK) {
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ bus->activity = TRUE;
+ }
break;
case CLK_SDONLY:
/* Remove HT request, or bring up SD clock */
if (bus->clkstate == CLK_NONE)
- dhdsdio_sdclk(bus, TRUE);
+ ret = dhdsdio_sdclk(bus, TRUE);
else if (bus->clkstate == CLK_AVAIL)
- dhdsdio_htclk(bus, FALSE, FALSE);
+ ret = dhdsdio_htclk(bus, FALSE, FALSE);
else
DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
bus->clkstate, target));
- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+ if (ret == BCME_OK)
+ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
break;
case CLK_NONE:
/* Make sure to remove HT request */
if (bus->clkstate == CLK_AVAIL)
- dhdsdio_htclk(bus, FALSE, FALSE);
+ ret = dhdsdio_htclk(bus, FALSE, FALSE);
/* Now remove the SD clock */
- dhdsdio_sdclk(bus, FALSE);
+ ret = dhdsdio_sdclk(bus, FALSE);
dhd_os_wd_timer(bus->dhd, 0);
break;
}
@@ -756,7 +760,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
#endif /* DHD_DEBUG */
- return BCME_OK;
+ return ret;
}
int
@@ -2719,6 +2723,9 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
BUS_WAKE(bus);
+ /* Change our idea of bus state */
+ bus->dhd->busstate = DHD_BUS_DOWN;
+
/* Enable clock for device interrupts */
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
@@ -2727,9 +2734,6 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
local_hostintmask = bus->hostintmask;
bus->hostintmask = 0;
- /* Change our idea of bus state */
- bus->dhd->busstate = DHD_BUS_DOWN;
-
/* Force clocks on backplane to be sure F2 interrupt propagates */
saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (!err) {
@@ -2782,23 +2786,24 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
dhd_timeout_t tmo;
uint retries = 0;
uint8 ready, enable;
- int err, ret = 0;
+ int err, ret = BCME_ERROR;
uint8 saveclk;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
ASSERT(bus->dhd);
if (!bus->dhd)
- return 0;
+ return BCME_OK;
if (enforce_mutex)
dhd_os_sdlock(bus->dhd);
/* Make sure backplane clock is on, needed to generate F2 interrupt */
- dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
- if (bus->clkstate != CLK_AVAIL)
+ err = dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ if ((err != BCME_OK) || (bus->clkstate != CLK_AVAIL)) {
+ DHD_ERROR(("%s: Failed to set backplane clock: err %d\n", __FUNCTION__, err));
goto exit;
-
+ }
/* Force clocks on backplane to be sure F2 interrupt propagates */
saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
@@ -2873,6 +2878,7 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
if (dhdp->busstate != DHD_BUS_DATA)
dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+ ret = BCME_OK;
exit:
if (enforce_mutex)
dhd_os_sdunlock(bus->dhd);
@@ -4631,8 +4637,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
if (bus->sleeping)
return FALSE;
- dhd_os_sdlock(bus->dhd);
-
/* Poll period: check device if appropriate. */
if (bus->poll && (++bus->polltick >= bus->pollrate)) {
uint32 intstatus = 0;
@@ -4702,8 +4706,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
}
}
- dhd_os_sdunlock(bus->dhd);
-
return bus->ipend;
}
@@ -5299,7 +5301,7 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
if (bus->dhd) {
- dhdsdio_release_dongle(bus, osh);
+ dhdsdio_release_dongle(bus, osh, TRUE);
dhd_detach(bus->dhd);
bus->dhd = NULL;
@@ -5343,11 +5345,11 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
static void
-dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh)
+dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, int reset_flag)
{
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
- if (bus->dhd && bus->dhd->dongle_reset)
+ if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
return;
if (bus->sih) {
@@ -5797,27 +5799,22 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
if (flag == TRUE) {
if (!bus->dhd->dongle_reset) {
+ dhd_os_sdlock(dhdp);
+ /* Turning off watchdog */
+ dhd_os_wd_timer(dhdp, 0);
#if !defined(IGNORE_ETH0_DOWN)
/* Force flow control as protection when stop come before ifconfig_down */
dhd_txflowcontrol(bus->dhd, 0, ON);
#endif /* !defined(IGNORE_ETH0_DOWN) */
- /* save country settinng if was pre-setup with priv ioctl */
- dhd_os_proto_block(dhdp);
- dhdcdc_query_ioctl(bus->dhd, 0, WLC_GET_COUNTRY,
- bus->dhd->country_code, sizeof(bus->dhd->country_code));
- dhd_os_proto_unblock(dhdp);
/* Expect app to have torn down any connection before calling */
/* Stop the bus, disable F2 */
- dhd_os_sdlock(dhdp);
-
dhd_bus_stop(bus, FALSE);
/* Clean tx/rx buffer pointers, detach from the dongle */
- dhdsdio_release_dongle(bus, bus->dhd->osh);
+ dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE);
bus->dhd->dongle_reset = TRUE;
bus->dhd->up = FALSE;
-
dhd_os_sdunlock(dhdp);
DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__));
@@ -5845,25 +5842,30 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh)) {
/* Re-init bus, enable F2 transfer */
- dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
-
+ bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
+ if (bcmerror == BCME_OK) {
#if defined(OOB_INTR_ONLY)
- dhd_enable_oob_intr(bus, TRUE);
+ dhd_enable_oob_intr(bus, TRUE);
#endif /* defined(OOB_INTR_ONLY) */
-
- bus->dhd->dongle_reset = FALSE;
- bus->dhd->up = TRUE;
-
+ bus->dhd->dongle_reset = FALSE;
+ bus->dhd->up = TRUE;
#if !defined(IGNORE_ETH0_DOWN)
- /* Restore flow control */
- dhd_txflowcontrol(bus->dhd, 0, OFF);
-#endif
+ /* Restore flow control */
+ dhd_txflowcontrol(bus->dhd, 0, OFF);
+#endif
+ /* Turning on watchdog back */
+ dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
- DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
+ DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
+ } else {
+ dhd_bus_stop(bus, FALSE);
+ dhdsdio_release_dongle(bus, bus->dhd->osh, FALSE);
+ }
} else
bcmerror = BCME_SDIO_ERROR;
} else
bcmerror = BCME_SDIO_ERROR;
+
dhd_os_sdunlock(dhdp);
} else {
bcmerror = BCME_NOTDOWN;
diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h
index 92dc326..6d5adf2 100644
--- a/bcm4329/src/include/epivers.h
+++ b/bcm4329/src/include/epivers.h
@@ -33,16 +33,16 @@
#define EPI_RC_NUMBER 248
-#define EPI_INCREMENTAL_NUMBER 6
+#define EPI_INCREMENTAL_NUMBER 17
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 218, 248, 6
+#define EPI_VERSION 4, 218, 248, 17
-#define EPI_VERSION_NUM 0x04daf806
+#define EPI_VERSION_NUM 0x04daf811
-#define EPI_VERSION_STR "4.218.248.6"
-#define EPI_ROUTER_VERSION_STR "4.219.248.6"
+#define EPI_VERSION_STR "4.218.248.17"
+#define EPI_ROUTER_VERSION_STR "4.219.248.17"
#endif
diff --git a/bcm4329/src/include/proto/bcmevent.h b/bcm4329/src/include/proto/bcmevent.h
index 46c04d3..1f8ecb1 100644
--- a/bcm4329/src/include/proto/bcmevent.h
+++ b/bcm4329/src/include/proto/bcmevent.h
@@ -24,7 +24,7 @@
*
* Dependencies: proto/bcmeth.h
*
- * $Id: bcmevent.h,v 9.34.4.1.20.16 2009/09/25 23:52:38 Exp $
+ * $Id: bcmevent.h,v 9.34.4.1.20.16.64.1 2010/11/08 21:57:03 Exp $
*
*/
@@ -131,10 +131,10 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
#define WLC_E_ACTION_FRAME 58
#define WLC_E_ACTION_FRAME_COMPLETE 59
-#define WLC_E_ESCAN_RESULT 69
-#define WLC_E_WAKE_EVENT 70
-#define WLC_E_LAST 71
-
+#define WLC_E_ESCAN_RESULT 69
+#define WLC_E_WAKE_EVENT 70
+#define WLC_E_RELOAD 71
+#define WLC_E_LAST 72
@@ -205,6 +205,7 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
#define WLC_E_IF_ADD 1
#define WLC_E_IF_DEL 2
+#define WLC_E_RELOAD_STATUS1 1
#include <packed_section_end.h>
diff --git a/bcm4329/src/include/wlioctl.h b/bcm4329/src/include/wlioctl.h
index 345ba34..cd7725a 100644
--- a/bcm4329/src/include/wlioctl.h
+++ b/bcm4329/src/include/wlioctl.h
@@ -24,7 +24,7 @@
* 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: wlioctl.h,v 1.601.4.15.2.14.2.62 2010/08/19 01:20:12 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.62.4.1 2010/11/17 03:09:28 Exp $
*/
@@ -857,6 +857,7 @@ typedef struct wl_ioctl {
#define PM_MAX 1
#define PM_FAST 2
+#define LISTEN_INTERVAL 20
#define INTERFERE_NONE 0
#define NON_WLAN 1
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index 2cd629c..8adf2d8 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.c
@@ -21,7 +21,7 @@
* 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_iw.c,v 1.51.4.9.2.6.4.142.4.13 2010/09/15 03:34:56 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.61 2010/12/03 22:09:41 Exp $
*/
@@ -54,6 +54,7 @@ typedef const struct si_pub si_t;
#define WL_INFORM(x)
#define WL_WSEC(x)
#define WL_SCAN(x)
+#define WL_TRACE_COEX(x)
#include <wl_iw.h>
@@ -96,11 +97,13 @@ typedef const struct si_pub si_t;
#define WL_SOFTAP(x) printk x
static struct net_device *priv_dev;
static bool ap_cfg_running = FALSE;
-static bool ap_fw_loaded = FALSE;
+bool ap_fw_loaded = FALSE;
+static long ap_cfg_pid = -1;
struct net_device *ap_net_dev = NULL;
struct semaphore ap_eth_sema;
+static struct completion ap_cfg_exited;
static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap);
-static int wl_iw_softap_deassoc_stations(struct net_device *dev);
+static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac);
#endif
#define WL_IW_IOCTL_CALL(func_call) \
@@ -109,10 +112,13 @@ static int wl_iw_softap_deassoc_stations(struct net_device *dev);
} while (0)
static int g_onoff = G_WLAN_SET_ON;
-wl_iw_extra_params_t g_wl_iw_params;
-static struct mutex wl_start_lock;
+wl_iw_extra_params_t g_wl_iw_params;
static struct mutex wl_cache_lock;
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+static bool use_non_dfs_channels = true;
+#endif
+
extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
uint32 reason, char* stringBuf, uint buflen);
#include <bcmsdbus.h>
@@ -161,9 +167,11 @@ static wlc_ssid_t g_specific_ssid;
static wlc_ssid_t g_ssid;
static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
+#if defined(CONFIG_FIRST_SCAN)
static volatile uint g_first_broadcast_scan;
static volatile uint g_first_counter_scans;
#define MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN 3
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
@@ -184,7 +192,9 @@ static volatile uint g_first_counter_scans;
static void wl_iw_free_ss_cache(void);
static int wl_iw_run_ss_cache_timer(int kick_off);
#endif
+#if defined(CONFIG_FIRST_SCAN)
int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
+#endif
static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len);
#define ISCAN_STATE_IDLE 0
#define ISCAN_STATE_SCANING 1
@@ -219,6 +229,11 @@ typedef struct iscan_info {
int iscan_ex_param_size;
} iscan_info_t;
#define COEX_DHCP 1
+
+#define BT_DHCP_eSCO_FIX
+#define BT_DHCP_USE_FLAGS
+#define BT_DHCP_OPPORTUNITY_WINDOW_TIME 2500
+#define BT_DHCP_FLAG_FORCE_TIME 5500
static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
static void wl_iw_bt_release(void);
@@ -228,18 +243,16 @@ typedef enum bt_coex_status {
BT_DHCP_OPPORTUNITY_WINDOW,
BT_DHCP_FLAG_FORCE_TIMEOUT
} coex_status_t;
-#define BT_DHCP_OPPORTUNITY_WINDOW_TIEM 2500
-#define BT_DHCP_FLAG_FORCE_TIME 5500
typedef struct bt_info {
struct net_device *dev;
struct timer_list timer;
uint32 timer_ms;
uint32 timer_on;
- int bt_state;
+ bool dhcp_done;
+ int bt_state;
-
- long bt_pid;
+ long bt_pid;
struct semaphore bt_sem;
struct completion bt_exited;
} bt_info_t;
@@ -606,6 +619,31 @@ wl_iw_get_macaddr(
return error;
}
+static int
+wl_iw_set_country_code(struct net_device *dev, char *ccode)
+{
+ char country_code[WLC_CNTRY_BUF_SZ];
+ int ret = -1;
+
+ WL_TRACE(("%s\n", __FUNCTION__));
+ if (!ccode)
+ ccode = dhd_bus_country_get(dev);
+ strncpy(country_code, ccode, sizeof(country_code));
+ if (ccode && (country_code[0] != 0)) {
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+ if (use_non_dfs_channels && !strncmp(country_code, "US", 2))
+ strncpy(country_code, "Q2", WLC_CNTRY_BUF_SZ);
+ if (!use_non_dfs_channels && !strncmp(country_code, "Q2", 2))
+ strncpy(country_code, "US", WLC_CNTRY_BUF_SZ);
+#endif
+ ret = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, &country_code, sizeof(country_code));
+ if (ret >= 0) {
+ WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
+ dhd_bus_country_set(dev, &country_code[0]);
+ }
+ }
+ return ret;
+}
static int
wl_iw_set_country(
@@ -627,14 +665,11 @@ wl_iw_set_country(
country_offset = strcspn(extra, " ");
country_code_size = strlen(extra) - country_offset;
-
if (country_offset != 0) {
strncpy(country_code, extra + country_offset + 1,
MIN(country_code_size, sizeof(country_code)));
-
-
- if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY,
- &country_code, sizeof(country_code))) >= 0) {
+ error = wl_iw_set_country_code(dev, country_code);
+ if (error >= 0) {
p += snprintf(p, MAX_WX_STRING, "OK");
WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
goto exit;
@@ -664,29 +699,34 @@ wl_iw_set_power_mode(
int pm_local = PM_OFF;
char powermode_val = 0;
+ WL_TRACE_COEX(("%s: DHCP session cmd:%s\n", __FUNCTION__, extra));
+
strncpy((char *)&powermode_val, extra + strlen("POWERMODE") + 1, 1);
if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
- WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
-
dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm));
dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
/* Disable packet filtering if necessary */
net_os_set_packet_filter(dev, 0);
- } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
+ g_bt->dhcp_done = false;
+ WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n",
+ __FUNCTION__, pm, pm_local));
- WL_TRACE(("%s: DHCP session done\n", __FUNCTION__));
+ } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
/* Enable packet filtering if was turned off */
net_os_set_packet_filter(dev, 1);
+ g_bt->dhcp_done = true;
+
} else {
- WL_ERROR(("Unkwown yet power setting, ignored\n"));
+ WL_ERROR(("%s Unkwown yet power setting, ignored\n",
+ __FUNCTION__));
}
p += snprintf(p, MAX_WX_STRING, "OK");
@@ -697,6 +737,122 @@ wl_iw_set_power_mode(
}
#endif
+
+static bool btcoex_is_sco_active(struct net_device *dev)
+{
+ int ioc_res = 0;
+ bool res = false;
+ int temp = 0;
+
+ ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 4, &temp);
+
+ if (ioc_res == 0) {
+ WL_TRACE_COEX(("%s: read btc_params[4] = %x\n", __FUNCTION__, temp));
+
+ if (temp > 0xea0) {
+ WL_TRACE_COEX(("%s: BT SCO/eSCO is ACTIVE\n", __FUNCTION__));
+ res = true;
+ } else {
+ WL_TRACE_COEX(("%s: BT SCO/eSCO is NOT detected\n", __FUNCTION__));
+ }
+ } else {
+ WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__));
+ }
+ return res;
+}
+
+#if defined(BT_DHCP_eSCO_FIX)
+
+static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
+{
+ static bool saved_status = false;
+
+ char buf_reg50va_dhcp_on[8] = { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
+ char buf_reg51va_dhcp_on[8] = { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+ char buf_reg64va_dhcp_on[8] = { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+ char buf_reg65va_dhcp_on[8] = { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+ char buf_reg71va_dhcp_on[8] = { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
+
+ uint32 regaddr;
+ static uint32 saved_reg50;
+ static uint32 saved_reg51;
+ static uint32 saved_reg64;
+ static uint32 saved_reg65;
+ static uint32 saved_reg71;
+
+ if (trump_sco) {
+
+ WL_TRACE_COEX(("Do new SCO/eSCO coex algo {save & override} \n"));
+
+ if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
+
+ saved_status = TRUE;
+ WL_TRACE_COEX(("%s saved bt_params[50,51,64,65,71]:"
+ " 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ __FUNCTION__, saved_reg50, saved_reg51,
+ saved_reg64, saved_reg65, saved_reg71));
+
+ } else {
+ WL_ERROR((":%s: save btc_params failed\n",
+ __FUNCTION__));
+ saved_status = false;
+ return -1;
+ }
+
+ WL_TRACE_COEX(("override with [50,51,64,65,71]:"
+ " 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ *(u32 *)(buf_reg50va_dhcp_on+4),
+ *(u32 *)(buf_reg51va_dhcp_on+4),
+ *(u32 *)(buf_reg64va_dhcp_on+4),
+ *(u32 *)(buf_reg65va_dhcp_on+4),
+ *(u32 *)(buf_reg71va_dhcp_on+4)));
+
+ dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg50va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg51va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg64va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg65va_dhcp_on[0], 8);
+ dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg71va_dhcp_on[0], 8);
+
+ saved_status = true;
+
+ } else if (saved_status) {
+
+ WL_TRACE_COEX(("Do new SCO/eSCO coex algo {save & override} \n"));
+
+ regaddr = 50;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg50);
+ regaddr = 51;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg51);
+ regaddr = 64;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg64);
+ regaddr = 65;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg65);
+ regaddr = 71;
+ dev_wlc_intvar_set_reg(dev, "btc_params",
+ (char *)&regaddr, (char *)&saved_reg71);
+
+ WL_TRACE_COEX(("restore bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ saved_reg50, saved_reg51, saved_reg64,
+ saved_reg65, saved_reg71));
+
+ saved_status = false;
+ } else {
+ WL_ERROR((":%s att to restore not saved BTCOEX params\n",
+ __FUNCTION__));
+ return -1;
+ }
+ return 0;
+}
+#endif
+
static int
wl_iw_get_power_mode(
struct net_device *dev,
@@ -752,9 +908,6 @@ wl_iw_set_btcoex_dhcp(
static bool saved_status = FALSE;
char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
-#ifndef CUSTOMER_HW2
- uint32 temp1, temp2;
-#endif
#ifdef CUSTOMER_HW2
strncpy((char *)&powermode_val, extra + strlen("BTCOEXMODE") + 1, 1);
@@ -764,44 +917,37 @@ wl_iw_set_btcoex_dhcp(
if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
- WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
+ WL_TRACE_COEX(("%s: DHCP session start, cmd:%s\n", __FUNCTION__, extra));
if ((saved_status == FALSE) &&
#ifndef CUSTOMER_HW2
- (!dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))) &&
+ (!dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))) &&
#endif
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
- saved_status = TRUE;
- WL_TRACE(("Saved 0x%x 0x%x 0x%x\n", \
- saved_reg66, saved_reg41, saved_reg68));
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
+ (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
+ saved_status = TRUE;
+ WL_TRACE_COEX(("save regs {66,41,68} ->: 0x%x 0x%x 0x%x\n", \
+ saved_reg66, saved_reg41, saved_reg68));
#ifndef CUSTOMER_HW2
- dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
+ dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
#endif
- dev_wlc_bufvar_set(dev, "btc_params", \
- (char *)&buf_reg66va_dhcp_on[0], sizeof(buf_reg66va_dhcp_on));
- dev_wlc_bufvar_set(dev, "btc_params", \
- (char *)&buf_reg41va_dhcp_on[0], sizeof(buf_reg41va_dhcp_on));
- dev_wlc_bufvar_set(dev, "btc_params", \
- (char *)&buf_reg68va_dhcp_on[0], sizeof(buf_reg68va_dhcp_on));
-#ifndef CUSTOMER_HW2
- if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 12, &temp1)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 13, &temp2)))
- {
- if ((temp1 != 0) && (temp2 != 0)) {
-#endif
- g_bt->bt_state = BT_DHCP_START;
- g_bt->timer_on = 1;
- mod_timer(&g_bt->timer, g_bt->timer.expires);
- WL_TRACE(("%s enable BT DHCP Timer\n", \
- __FUNCTION__));
-#ifndef CUSTOMER_HW2
- }
- }
-#endif
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg66va_dhcp_on[0], sizeof(buf_reg66va_dhcp_on));
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg41va_dhcp_on[0], sizeof(buf_reg41va_dhcp_on));
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg68va_dhcp_on[0], sizeof(buf_reg68va_dhcp_on));
+
+ if (btcoex_is_sco_active(dev)) {
+ g_bt->bt_state = BT_DHCP_START;
+ g_bt->timer_on = 1;
+ mod_timer(&g_bt->timer, g_bt->timer.expires);
+ WL_TRACE_COEX(("%s enable BT DHCP Timer\n", \
+ __FUNCTION__));
+ }
}
else if (saved_status == TRUE) {
WL_ERROR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__));
@@ -812,16 +958,22 @@ wl_iw_set_btcoex_dhcp(
#else
else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
#endif
- WL_TRACE(("%s: DHCP session done\n", __FUNCTION__));
#ifndef CUSTOMER_HW2
dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
#endif
- WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__));
+ WL_TRACE_COEX(("%s disable BT DHCP Timer\n", __FUNCTION__));
if (g_bt->timer_on) {
g_bt->timer_on = 0;
del_timer_sync(&g_bt->timer);
+
+ if (g_bt->bt_state != BT_DHCP_IDLE) {
+ WL_TRACE_COEX(("%s bt->bt_state:%d\n",
+ __FUNCTION__, g_bt->bt_state));
+
+ up(&g_bt->bt_sem);
+ }
}
dev_wlc_bufvar_set(dev, "btc_flags", \
@@ -837,11 +989,15 @@ wl_iw_set_btcoex_dhcp(
regaddr = 68;
dev_wlc_intvar_set_reg(dev, "btc_params", \
(char *)&regaddr, (char *)&saved_reg68);
+
+ WL_TRACE_COEX(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n", \
+ saved_reg66, saved_reg41, saved_reg68));
}
saved_status = FALSE;
}
else {
- WL_ERROR(("Unkwown yet power setting, ignored\n"));
+ WL_ERROR(("%s Unkwown yet power setting, ignored\n",
+ __FUNCTION__));
}
p += snprintf(p, MAX_WX_STRING, "OK");
@@ -881,6 +1037,22 @@ wl_iw_set_suspend(
return ret;
}
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+static int
+wl_iw_set_dfs_channels(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ use_non_dfs_channels = *(extra + strlen(SETDFSCHANNELS_CMD) + 1) - '0';
+ use_non_dfs_channels = (use_non_dfs_channels != 0) ? false : true;
+ wl_iw_set_country_code(dev, NULL);
+ return 0;
+}
+#endif
+
int
wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
{
@@ -1063,7 +1235,6 @@ wl_iw_set_band(
if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
-
if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND,
&band, sizeof(band))) >= 0) {
p += snprintf(p, MAX_WX_STRING, "OK");
@@ -1165,15 +1336,15 @@ wl_iw_set_pno_set(
wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
int nssid = 0;
cmd_tlv_t *cmd_tlv_temp;
- char type;
char *str_ptr;
+ char *str_ptr_end;
int tlv_size_left;
int pno_time;
#ifdef PNO_SET_DEBUG
int i;
char pno_in_example[] = {'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ', \
- 'S', 0x01, 0x01, 0x00,
+ 'S', '1', '2', '0',
'S',
0x04,
'B', 'R', 'C', 'M',
@@ -1181,8 +1352,8 @@ wl_iw_set_pno_set(
0x04,
'G', 'O', 'O', 'G',
'T',
- 0x00,
- 0x0A
+ '1','E',
+ 0x00
};
#endif
@@ -1239,29 +1410,15 @@ wl_iw_set_pno_set(
goto exit_proc;
}
else {
- while (tlv_size_left > 0)
- {
- type = str_ptr[0];
- switch (type) {
- case PNO_TLV_TYPE_TIME:
-
- if ((res = wl_iw_parse_data_tlv(&str_ptr, \
- &pno_time, \
- sizeof(pno_time), \
- type, sizeof(short), &tlv_size_left)) == -1) {
- WL_ERROR(("%s return %d\n", \
- __FUNCTION__, res));
- goto exit_proc;
- }
- break;
-
- default:
- WL_ERROR(("%s get unkwown type %X\n", \
- __FUNCTION__, type));
- goto exit_proc;
- break;
- }
+ if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
+ WL_ERROR(("%s scan duration corrupted field size %d\n", \
+ __FUNCTION__, tlv_size_left));
+ goto exit_proc;
}
+ str_ptr++;
+ pno_time = simple_strtoul(str_ptr, &str_ptr_end, 16);
+ WL_ERROR((" got %d bytes left pno_time %d or %#x\n", \
+ tlv_size_left, pno_time, pno_time));
}
}
else {
@@ -1300,19 +1457,24 @@ wl_iw_get_rssi(
error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
if (error) {
WL_ERROR(("%s: Fails %d\n", __FUNCTION__, error));
- net_os_wake_unlock(dev);
- return error;
- }
- rssi = dtoh32(scb_val.val);
+ } else {
+ rssi = dtoh32(scb_val.val);
- error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
- if (!error) {
- ssid.SSID_len = dtoh32(ssid.SSID_len);
- wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
+ error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
+ if (!error) {
+ ssid.SSID_len = dtoh32(ssid.SSID_len);
+ wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
+ }
}
}
- p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
+ WL_ASSOC(("%s ssid_len:%d, rssi:%d\n", __FUNCTION__, ssid.SSID_len, rssi));
+
+ if (error || (ssid.SSID_len == 0)) {
+ p += snprintf(p, MAX_WX_STRING, "FAIL");
+ } else {
+ p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
+ }
wrqu->data.length = p - extra + 1;
net_os_wake_unlock(dev);
@@ -1348,6 +1510,7 @@ int
wl_control_wl_start(struct net_device *dev)
{
int ret = 0;
+ wl_iw_t *iw;
WL_TRACE(("Enter %s \n", __FUNCTION__));
@@ -1356,7 +1519,13 @@ wl_control_wl_start(struct net_device *dev)
return -1;
}
- mutex_lock(&wl_start_lock);
+ iw = *(wl_iw_t **)netdev_priv(dev);
+
+ if (!iw) {
+ WL_ERROR(("%s: wl is null\n", __FUNCTION__));
+ return -1;
+ }
+ dhd_os_start_lock(iw->pub);
if (g_onoff == G_WLAN_SET_OFF) {
dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
@@ -1365,19 +1534,19 @@ wl_control_wl_start(struct net_device *dev)
sdioh_start(NULL, 0);
#endif
- dhd_dev_reset(dev, 0);
+ ret = dhd_dev_reset(dev, 0);
+ if (ret == BCME_OK) {
#if defined(BCMLXSDMMC)
- sdioh_start(NULL, 1);
+ sdioh_start(NULL, 1);
#endif
-
- dhd_dev_init_ioctl(dev);
-
- g_onoff = G_WLAN_SET_ON;
+ dhd_dev_init_ioctl(dev);
+ g_onoff = G_WLAN_SET_ON;
+ }
}
WL_TRACE(("Exited %s \n", __FUNCTION__));
- mutex_unlock(&wl_start_lock);
+ dhd_os_start_unlock(iw->pub);
return ret;
}
@@ -1389,6 +1558,8 @@ wl_iw_control_wl_off(
)
{
int ret = 0;
+ wl_iw_t *iw;
+
WL_TRACE(("Enter %s\n", __FUNCTION__));
if (!dev) {
@@ -1396,7 +1567,12 @@ wl_iw_control_wl_off(
return -1;
}
- mutex_lock(&wl_start_lock);
+ iw = *(wl_iw_t **)netdev_priv(dev);
+ if (!iw) {
+ WL_ERROR(("%s: dev is null\n", __FUNCTION__));
+ return -1;
+ }
+ dhd_os_start_lock(iw->pub);
#ifdef SOFTAP
ap_cfg_running = FALSE;
@@ -1419,10 +1595,11 @@ wl_iw_control_wl_off(
#endif
memset(g_scan, 0, G_SCAN_RESULTS);
g_scan_specified_ssid = 0;
-
+#if defined(CONFIG_FIRST_SCAN)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
g_first_counter_scans = 0;
#endif
+#endif
#if defined(BCMLXSDMMC)
sdioh_stop(NULL);
@@ -1435,7 +1612,7 @@ wl_iw_control_wl_off(
wl_iw_send_priv_event(dev, "STOP");
}
- mutex_unlock(&wl_start_lock);
+ dhd_os_start_unlock(iw->pub);
WL_TRACE(("Exited %s\n", __FUNCTION__));
@@ -1452,7 +1629,15 @@ wl_iw_control_wl_on(
WL_TRACE(("Enter %s \n", __FUNCTION__));
- ret = wl_control_wl_start(dev);
+ if ((ret = wl_control_wl_start(dev)) != BCME_OK) {
+ WL_ERROR(("%s failed first attemp\n", __FUNCTION__));
+ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
+ if ((ret = wl_control_wl_start(dev)) != BCME_OK) {
+ WL_ERROR(("%s failed second attemp\n", __FUNCTION__));
+ net_os_send_hang_message(dev);
+ return ret;
+ }
+ }
wl_iw_send_priv_event(dev, "START");
@@ -1473,7 +1658,7 @@ wl_iw_control_wl_on(
static struct ap_profile my_ap;
static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap);
static int get_assoc_sta_list(struct net_device *dev, char *buf, int len);
-static int set_ap_mac_list(struct net_device *dev, char *buf);
+static int set_ap_mac_list(struct net_device *dev, void *buf);
#define PTYPE_STRING 0
#define PTYPE_INTDEC 1
@@ -1555,9 +1740,13 @@ int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
ret |= get_parmeter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5);
- ret |= get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5);
+ get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5);
+
+ get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5);
- ret |= get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5);
+ get_parmeter_from_string(&str_ptr, "HIDDEN=", PTYPE_INTDEC, &ap_cfg->closednet, 5);
+
+ get_parmeter_from_string(&str_ptr, "COUNTRY=", PTYPE_STRING, &ap_cfg->country_code, 3);
return ret;
}
@@ -1574,7 +1763,8 @@ static int iwpriv_set_ap_config(struct net_device *dev,
char *extra = NULL;
struct ap_profile *ap_cfg = &my_ap;
- WL_TRACE(("> Got IWPRIV SET_AP IOCTL: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
+ WL_TRACE(("%s: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
+ __FUNCTION__,
info->cmd, info->flags,
wrqu->data.pointer, wrqu->data.length));
@@ -1628,52 +1818,86 @@ static int iwpriv_get_assoc_list(struct net_device *dev,
char mac_buf[256];
struct maclist *sta_maclist = (struct maclist *)mac_buf;
- char mac_lst[256];
+ char mac_lst[384];
char *p_mac_str;
+ char *p_mac_str_end;
+
+ if ((!dev) || (!extra)) {
+ return -EINVAL;
+ }
+
+ net_os_wake_lock(dev);
WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d, \
iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags, \
extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags));
- WL_SOFTAP(("extra:%s\n", extra));
- print_buf((u8 *)p_iwrq, 16, 0);
-
memset(sta_maclist, 0, sizeof(mac_buf));
sta_maclist->count = 8;
- WL_TRACE((" net device:%s, buf_sz:%d\n", dev->name, sizeof(mac_buf)));
- get_assoc_sta_list(dev, mac_buf, 256);
- WL_TRACE((" got %d stations\n", sta_maclist->count));
+ WL_SOFTAP(("%s: net device:%s, buf_sz:%d\n",
+ __FUNCTION__, dev->name, sizeof(mac_buf)));
+
+ if ((ret = get_assoc_sta_list(dev, mac_buf, sizeof(mac_buf))) < 0) {
+ WL_ERROR(("%s: sta list ioctl error:%d\n",
+ __FUNCTION__, ret));
+ goto func_exit;
+ }
+
+ WL_SOFTAP(("%s: got %d stations\n", __FUNCTION__,
+ sta_maclist->count));
memset(mac_lst, 0, sizeof(mac_lst));
p_mac_str = mac_lst;
+ p_mac_str_end = &mac_lst[sizeof(mac_lst)-1];
for (i = 0; i < 8; i++) {
struct ether_addr *id = &sta_maclist->ea[i];
+ if (!ETHER_ISNULLADDR(id->octet)) {
+ scb_val_t scb_val;
+ int rssi = 0;
+
+ bzero(&scb_val, sizeof(scb_val_t));
- WL_SOFTAP(("dhd_drv>> sta_mac[%d] :", i));
- print_buf((unsigned char *)&sta_maclist->ea[i], 6, 0);
+ if ((p_mac_str_end - p_mac_str) <= 36) {
+ WL_ERROR(("%s: mac list buf is < 36 for item[%i] item\n",
+ __FUNCTION__, i));
+ break;
+ }
- p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
- "Mac[%d]=%02X:%02X:%02X:%02X:%02X:%02X\n", i,
+ p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
+ "\nMac[%d]=%02X:%02X:%02X:%02X:%02X:%02X,", i,
id->octet[0], id->octet[1], id->octet[2],
id->octet[3], id->octet[4], id->octet[5]);
+ bcopy(id->octet, &scb_val.ea, 6);
+ ret = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
+ if (ret < 0) {
+ snprintf(p_mac_str, MAX_WX_STRING, "RSSI:ERR");
+ WL_ERROR(("%s: RSSI ioctl error:%d\n",
+ __FUNCTION__, ret));
+ break;
+ }
+
+ rssi = dtoh32(scb_val.val);
+ p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
+ "RSSI:%d", rssi);
+ }
}
- p_iwrq->data.length = strlen(mac_lst);
+ p_iwrq->data.length = strlen(mac_lst) + 1;
- WL_TRACE(("u.pointer:%p\n", p_iwrq->data.pointer));
- WL_TRACE(("resulting str:\n%s \n len:%d\n\n", mac_lst, p_iwrq->data.length));
+ WL_SOFTAP(("%s: data to user:\n%s\n usr_ptr:%p\n", __FUNCTION__,
+ mac_lst, p_iwrq->data.pointer));
if (p_iwrq->data.length) {
- if (copy_to_user(p_iwrq->data.pointer, mac_lst, p_iwrq->data.length)) {
- WL_ERROR(("%s: Can't copy to user\n", __FUNCTION__));
- return -EFAULT;
- }
+ bcopy(mac_lst, extra, p_iwrq->data.length);
}
+func_exit:
+ net_os_wake_unlock(dev);
+
WL_TRACE(("Exited %s \n", __FUNCTION__));
return ret;
}
@@ -1681,19 +1905,20 @@ static int iwpriv_get_assoc_list(struct net_device *dev,
#ifdef SOFTAP
+#define MAC_FILT_MAX 8
static int iwpriv_set_mac_filters(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *ext)
{
-
int i, ret = -1;
- char *extra = NULL;
- u8 macfilt[8][6];
+ char * extra = NULL;
int mac_cnt = 0;
- char sub_cmd[16];
+ int mac_mode = 0;
+ struct ether_addr *p_ea;
+ struct mac_list_set mflist_set;
- WL_TRACE((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x, \
+ WL_SOFTAP((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x, \
info->flags:%x, u.data:%p, u.len:%d\n",
info->cmd, info->flags,
wrqu->data.pointer, wrqu->data.length));
@@ -1713,25 +1938,21 @@ static int iwpriv_set_mac_filters(struct net_device *dev,
extra[wrqu->data.length] = 0;
WL_SOFTAP((" Got parameter string in iw_point:\n %s \n", extra));
- memset(macfilt, 0, sizeof(macfilt));
- memset(sub_cmd, 0, sizeof(sub_cmd));
+ memset(&mflist_set, 0, sizeof(mflist_set));
str_ptr = extra;
- if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=", PTYPE_STRING, sub_cmd, 15) != 0) {
+ if (get_parmeter_from_string(&str_ptr, "MAC_MODE=",
+ PTYPE_INTDEC, &mac_mode, 4) != 0) {
+ WL_ERROR(("ERROR: 'MAC_MODE=' token is missing\n"));
goto exit_proc;
}
-#define MAC_FILT_MAX 8
-
- if (strncmp(sub_cmd, "MAC_FLT_W", strlen("MAC_FLT_W"))) {
- WL_ERROR(("ERROR: sub_cmd:%s != 'MAC_FLT_W'!\n", sub_cmd));
- goto exit_proc;
- }
+ p_ea = &mflist_set.mac_list.ea[0];
if (get_parmeter_from_string(&str_ptr, "MAC_CNT=",
PTYPE_INTDEC, &mac_cnt, 4) != 0) {
- WL_ERROR(("ERROR: MAC_CNT param is missing \n"));
+ WL_ERROR(("ERROR: 'MAC_CNT=' token param is missing \n"));
goto exit_proc;
}
@@ -1740,19 +1961,23 @@ static int iwpriv_set_mac_filters(struct net_device *dev,
goto exit_proc;
}
- for (i = 0; i < mac_cnt; i++) {
+ for (i=0; i < mac_cnt; i++)
if (get_parmeter_from_string(&str_ptr, "MAC=",
- PTYPE_STR_HEX, macfilt[i], 12) != 0) {
+ PTYPE_STR_HEX, &p_ea[i], 12) != 0) {
WL_ERROR(("ERROR: MAC_filter[%d] is missing !\n", i));
goto exit_proc;
}
- }
+ WL_SOFTAP(("MAC_MODE=:%d, MAC_CNT=%d, MACs:..\n", mac_mode, mac_cnt));
for (i = 0; i < mac_cnt; i++) {
- WL_SOFTAP(("mac_filt[%d]:", i));
- print_buf(macfilt[i], 6, 0);
+ WL_SOFTAP(("mac_filt[%d]:", i));
+ print_buf(&p_ea[i], 6, 0);
}
+ mflist_set.mode = mac_mode;
+ mflist_set.mac_list.count = mac_cnt;
+ set_ap_mac_list(dev, &mflist_set);
+
wrqu->data.pointer = NULL;
wrqu->data.length = 0;
ret = 0;
@@ -1768,8 +1993,44 @@ static int iwpriv_set_mac_filters(struct net_device *dev,
}
#endif
+
+#ifdef SOFTAP
+static int iwpriv_set_ap_sta_disassoc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *ext)
+{
+ int res = 0;
+ char sta_mac[6] = {0, 0, 0, 0, 0, 0};
+ char cmd_buf[256];
+ char *str_ptr = cmd_buf;
+
+ WL_SOFTAP((">>%s called\n args: info->cmd:%x,"
+ " info->flags:%x, u.data.p:%p, u.data.len:%d\n",
+ __FUNCTION__, info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length));
+
+ if (wrqu->data.length != 0) {
+
+ if (copy_from_user(cmd_buf, wrqu->data.pointer, wrqu->data.length)) {
+ return -EFAULT;
+ }
+
+ if (get_parmeter_from_string(&str_ptr,
+ "MAC=", PTYPE_STR_HEX, sta_mac, 12) == 0) {
+ res = wl_iw_softap_deassoc_stations(dev, sta_mac);
+ } else {
+ WL_ERROR(("ERROR: STA_MAC= token not found\n"));
+ }
+ }
+
+ return res;
+}
+#endif
+
#endif
+
#if WIRELESS_EXT < 13
struct iw_request_info
{
@@ -2296,7 +2557,7 @@ wl_iw_set_wap(
join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN);
- WL_TRACE(("%s target_channel=%d\n", __FUNCTION__, g_wl_iw_params.target_channel));
+ WL_ASSOC(("%s target_channel=%d\n", __FUNCTION__, g_wl_iw_params.target_channel));
wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
@@ -2305,7 +2566,7 @@ wl_iw_set_wap(
}
if (g_ssid.SSID_len) {
- WL_TRACE(("%s: join SSID=%s BSSID="MACSTR" ch=%d\n", __FUNCTION__, \
+ WL_ASSOC(("%s: join SSID=%s BSSID="MACSTR" ch=%d\n", __FUNCTION__, \
g_ssid.SSID, MAC2STR((u8 *)awrq->sa_data), \
g_wl_iw_params.target_channel));
}
@@ -2411,7 +2672,7 @@ wl_iw_get_aplist(
list->version = dtoh32(list->version);
list->count = dtoh32(list->count);
if (list->version != WL_BSS_INFO_VERSION) {
- WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
+ WL_ERROR(("%s: list->version %d != WL_BSS_INFO_VERSION\n", \
__FUNCTION__, list->version));
kfree(list);
return -EINVAL;
@@ -2419,21 +2680,23 @@ wl_iw_get_aplist(
for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
- ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
- buflen));
-
+ if ((dtoh32(bi->length) > buflen) ||
+ (((uintptr)bi + dtoh32(bi->length)) > ((uintptr)list + buflen))) {
+ WL_ERROR(("%s: Scan results out of bounds: %u\n",__FUNCTION__,dtoh32(bi->length)));
+ kfree(list);
+ return -E2BIG;
+ }
+
if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
continue;
-
memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
addr[dwrq->length].sa_family = ARPHRD_ETHER;
qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
qual[dwrq->length].noise = 0x100 + bi->phy_noise;
-
#if WIRELESS_EXT > 18
qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
#else
@@ -2496,21 +2759,22 @@ wl_iw_iscan_get_aplist(
for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length))
: list->bss_info;
- ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
- WLC_IW_ISCAN_MAXLEN));
-
+ if ((dtoh32(bi->length) > WLC_IW_ISCAN_MAXLEN) ||
+ (((uintptr)bi + dtoh32(bi->length)) > ((uintptr)list + WLC_IW_ISCAN_MAXLEN))) {
+ WL_ERROR(("%s: Scan results out of bounds: %u\n",__FUNCTION__,dtoh32(bi->length)));
+ return -E2BIG;
+ }
+
if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
continue;
-
memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
addr[dwrq->length].sa_family = ARPHRD_ETHER;
qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
qual[dwrq->length].noise = 0x100 + bi->phy_noise;
-
#if WIRELESS_EXT > 18
qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
#else
@@ -2542,7 +2806,10 @@ wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
params->passive_time = -1;
params->home_time = -1;
params->channel_num = 0;
-
+#if defined(CONFIG_FIRST_SCAN)
+ if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
+ params->passive_time = 30;
+#endif
params->nprobes = htod32(params->nprobes);
params->active_time = htod32(params->active_time);
params->passive_time = htod32(params->passive_time);
@@ -2569,7 +2836,6 @@ wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type));
-
if ((err = dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \
iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
@@ -2672,7 +2938,7 @@ wl_iw_iscan_get(iscan_info_t *iscan)
static void wl_iw_force_specific_scan(iscan_info_t *iscan)
{
- WL_TRACE(("%s force Specific SCAN for %s\n", __FUNCTION__, g_specific_ssid.SSID));
+ WL_SCAN(("%s force Specific SCAN for %s\n", __FUNCTION__, g_specific_ssid.SSID));
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_lock();
#endif
@@ -2690,9 +2956,11 @@ static void wl_iw_send_scan_complete(iscan_info_t *iscan)
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
+#if defined(CONFIG_FIRST_SCAN)
if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
- WL_TRACE(("Send Event ISCAN complete\n"));
+#endif
+ WL_SCAN(("Send Event ISCAN complete\n"));
#endif
}
@@ -2997,7 +3265,7 @@ __u16 *merged_len)
mutex_lock(&wl_cache_lock);
node = g_ss_cache_ctrl.m_cache_head;
for (;node;) {
- list_merge = (wl_scan_results_t *)node;
+ list_merge = (wl_scan_results_t *)&node->buflen;
WL_TRACE(("%s: Cached Specific APs list=%d\n", __FUNCTION__, list_merge->count));
if (buflen_from_user - *merged_len > 0) {
*merged_len += (__u16) wl_iw_get_scan_prep(list_merge, info,
@@ -3087,14 +3355,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;
+#if defined(CONFIG_FIRST_SCAN)
if (g_first_broadcast_scan != BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
- WL_TRACE(("%s Ignoring SC %s first BC is not done = %d\n", \
+ WL_ERROR(("%s Ignoring SC %s first BC is not done = %d\n", \
__FUNCTION__, req->essid, \
g_first_broadcast_scan));
return -EBUSY;
}
+#endif
if (g_scan_specified_ssid) {
- WL_TRACE(("%s Specific SCAN is not done ignore scan for = %s \n", \
+ WL_SCAN(("%s Specific SCAN is not done ignore scan for = %s \n", \
__FUNCTION__, req->essid));
return -EBUSY;
}
@@ -3112,7 +3382,7 @@ wl_iw_set_scan(
#endif
if ((error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)))) {
- WL_TRACE(("#### Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error));
+ WL_SCAN(("Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error));
g_scan_specified_ssid = 0;
return -EBUSY;
}
@@ -3127,14 +3397,16 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
wlc_ssid_t ssid;
iscan_info_t *iscan = g_iscan;
+#if defined(CONFIG_FIRST_SCAN)
if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) {
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED;
- WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__));
+ WL_SCAN(("%s: First Brodcast scan was forced\n", __FUNCTION__));
}
else if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) {
- WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
+ WL_SCAN(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
return 0;
}
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
if (flag)
@@ -3144,7 +3416,7 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
wl_iw_set_event_mask(dev);
- WL_TRACE(("+++: Set Broadcast ISCAN\n"));
+ WL_SCAN(("+++: Set Broadcast ISCAN\n"));
memset(&ssid, 0, sizeof(ssid));
@@ -3179,7 +3451,7 @@ wl_iw_iscan_set_scan(
iscan_info_t *iscan = g_iscan;
int ret = 0;
- WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
+ WL_SCAN(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
#if defined(CSCAN)
WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
@@ -3190,19 +3462,19 @@ wl_iw_iscan_set_scan(
#if defined(SOFTAP)
if (ap_cfg_running) {
- WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
+ WL_SCAN(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
goto set_scan_end;
}
#endif
if (g_onoff == G_WLAN_SET_OFF) {
- WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+ WL_SCAN(("%s: driver is not up yet after START\n", __FUNCTION__));
goto set_scan_end;
}
#ifdef PNO_SUPPORT
if (dhd_dev_get_pno_status(dev)) {
- WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
+ WL_SCAN(("%s: Scan called when PNO is active\n", __FUNCTION__));
}
#endif
@@ -3212,7 +3484,7 @@ wl_iw_iscan_set_scan(
}
if (g_scan_specified_ssid) {
- WL_TRACE(("%s Specific SCAN already running ignoring BC scan\n", \
+ WL_SCAN(("%s Specific SCAN already running ignoring BC scan\n", \
__FUNCTION__));
ret = EBUSY;
goto set_scan_end;
@@ -3238,14 +3510,14 @@ wl_iw_iscan_set_scan(
g_scan_specified_ssid = 0;
if (iscan->iscan_state == ISCAN_STATE_SCANING) {
- WL_TRACE(("%s ISCAN already in progress \n", __FUNCTION__));
+ WL_SCAN(("%s ISCAN already in progress \n", __FUNCTION__));
goto set_scan_end;
}
}
}
#endif
-#if !defined(CSCAN)
+#if defined(CONFIG_FIRST_SCAN) && !defined(CSCAN)
if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
@@ -3431,8 +3703,12 @@ wl_iw_get_scan_prep(
wl_bss_info_t *bi = NULL;
char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
int ret = 0;
+ int channel;
- ASSERT(list);
+ if (!list) {
+ WL_ERROR(("%s: Null list pointer",__FUNCTION__));
+ return ret;
+ }
for (i = 0; i < list->count && i < IW_MAX_AP; i++)
{
@@ -3440,7 +3716,7 @@ wl_iw_get_scan_prep(
WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
__FUNCTION__, list->version));
return ret;
- }
+ }
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
@@ -3456,7 +3732,6 @@ wl_iw_get_scan_prep(
iwe.u.data.flags = 1;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
-
if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
iwe.cmd = SIOCGIWMODE;
if (dtoh16(bi->capability) & DOT11_CAP_ESS)
@@ -3466,15 +3741,14 @@ wl_iw_get_scan_prep(
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
}
-
iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
- CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
+ channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
+ iwe.u.freq.m = wf_channel2mhz(channel,
+ channel <= CH_MAX_2G_CHANNEL ?
WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
iwe.u.freq.e = 6;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
-
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
@@ -3491,7 +3765,6 @@ wl_iw_get_scan_prep(
iwe.u.data.length = 0;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
-
if (bi->rateset.count) {
if (((event -extra) + IW_EV_LCP_LEN) <= (uintptr)end) {
value = event + IW_EV_LCP_LEN;
@@ -3548,7 +3821,6 @@ wl_iw_get_scan(
return -EINVAL;
}
-
if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
return error;
ci.scan_channel = dtoh32(ci.scan_channel);
@@ -3718,7 +3990,7 @@ wl_iw_iscan_get_scan(
uint buflen_from_user = dwrq->length;
#endif
- WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
+ WL_SCAN(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
#if defined(SOFTAP)
if (ap_cfg_running) {
@@ -3732,11 +4004,13 @@ wl_iw_iscan_get_scan(
return -EINVAL;
}
+#if defined(CONFIG_FIRST_SCAN)
if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) {
WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \
dev->name, __FUNCTION__));
return -EAGAIN;
}
+#endif
if ((!iscan) || (iscan->sysioc_pid < 0)) {
WL_ERROR(("%ssysioc_pid\n", __FUNCTION__));
@@ -3783,26 +4057,27 @@ wl_iw_iscan_get_scan(
bi = NULL;
for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
- ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
- WLC_IW_ISCAN_MAXLEN));
-
+ if ((dtoh32(bi->length) > WLC_IW_ISCAN_MAXLEN) ||
+ (((uintptr)bi + dtoh32(bi->length)) > ((uintptr)list + WLC_IW_ISCAN_MAXLEN))) {
+ WL_ERROR(("%s: Scan results out of bounds: %u\n",__FUNCTION__,dtoh32(bi->length)));
+ return -E2BIG;
+ }
+
if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
IW_EV_QUAL_LEN >= end)
return -E2BIG;
-
+
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
-
iwe.u.data.length = dtoh32(bi->SSID_len);
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
-
if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
iwe.cmd = SIOCGIWMODE;
if (dtoh16(bi->capability) & DOT11_CAP_ESS)
@@ -3812,7 +4087,6 @@ wl_iw_iscan_get_scan(
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
}
-
iwe.cmd = SIOCGIWFREQ;
channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
iwe.u.freq.m = wf_channel2mhz(channel,
@@ -3821,17 +4095,14 @@ wl_iw_iscan_get_scan(
iwe.u.freq.e = 6;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
-
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
iwe.u.qual.noise = 0x100 + bi->phy_noise;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
-
wl_iw_handle_scanresults_ies(&event, end, info, bi);
-
iwe.cmd = SIOCGIWENCODE;
if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
@@ -3840,7 +4111,6 @@ wl_iw_iscan_get_scan(
iwe.u.data.length = 0;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
-
if (bi->rateset.count) {
if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
return -E2BIG;
@@ -3869,7 +4139,9 @@ wl_iw_iscan_get_scan(
wl_iw_run_ss_cache_timer(0);
wl_iw_run_ss_cache_timer(1);
#endif /* CSCAN */
+#if defined(CONFIG_FIRST_SCAN)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
+#endif
WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
@@ -4592,7 +4864,7 @@ wl_iw_set_encodeext(
int error;
struct iw_encode_ext *iwe;
- WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
+ WL_WSEC(("%s: SIOCSIWENCODEEXT\n", dev->name));
CHECK_EXTRA_FOR_NULL(extra);
@@ -4822,7 +5094,7 @@ wl_iw_get_encodeext(
char *extra
)
{
- WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
+ WL_WSEC(("%s: SIOCGIWENCODEEXT\n", dev->name));
return 0;
}
@@ -4840,7 +5112,7 @@ wl_iw_set_wpaauth(
int val = 0;
wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
- WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
+ WL_WSEC(("%s: SIOCSIWAUTH\n", dev->name));
#if defined(SOFTAP)
if (ap_cfg_running) {
@@ -4852,7 +5124,7 @@ wl_iw_set_wpaauth(
paramid = vwrq->flags & IW_AUTH_INDEX;
paramval = vwrq->value;
- WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
+ WL_WSEC(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
dev->name, paramid, paramval));
switch (paramid) {
@@ -4868,7 +5140,7 @@ wl_iw_set_wpaauth(
#endif
else if (paramval & IW_AUTH_WAPI_VERSION_1)
val = WPA_AUTH_WAPI;
- WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
+ WL_WSEC(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
return error;
break;
@@ -4898,24 +5170,28 @@ wl_iw_set_wpaauth(
WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
"we're a WPS enrollee\n", dev->name, __FUNCTION__));
if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
- WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
+ WL_ERROR(("Failed to set iovar is_WPS_enrollee\n"));
return error;
}
} else if (val) {
if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
- WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ WL_ERROR(("Failed to clear iovar is_WPS_enrollee\n"));
return error;
}
}
- if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
+ if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
+ WL_ERROR(("Failed to set 'wsec'iovar\n"));
return error;
+ }
break;
case IW_AUTH_KEY_MGMT:
- if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) {
+ WL_ERROR(("Failed to get 'wpa_auth'iovar\n"));
return error;
+ }
if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
if (paramval & IW_AUTH_KEY_MGMT_PSK)
@@ -4933,18 +5209,22 @@ wl_iw_set_wpaauth(
#endif
if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT))
val = WPA_AUTH_WAPI;
- WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
- if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ WL_WSEC(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) {
+ WL_ERROR(("Failed to set 'wpa_auth'iovar\n"));
return error;
+ }
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
- dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ if ((error = dev_wlc_bufvar_set(dev, "tkip_countermeasures", \
+ (char *)&paramval, sizeof(paramval))))
+ WL_WSEC(("%s: tkip_countermeasures failed %d\n", __FUNCTION__, error));
break;
case IW_AUTH_80211_AUTH_ALG:
- WL_INFORM(("Setting the D11auth %d\n", paramval));
+ WL_WSEC(("Setting the D11auth %d\n", paramval));
if (paramval == IW_AUTH_ALG_OPEN_SYSTEM)
val = 0;
else if (paramval == IW_AUTH_ALG_SHARED_KEY)
@@ -4961,15 +5241,21 @@ wl_iw_set_wpaauth(
if (paramval == 0) {
iw->pwsec = 0;
iw->gwsec = 0;
- if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) {
+ WL_ERROR(("Failed to get 'wsec'iovar\n"));
return error;
+ }
if (val & (TKIP_ENABLED | AES_ENABLED)) {
val &= ~(TKIP_ENABLED | AES_ENABLED);
dev_wlc_intvar_set(dev, "wsec", val);
}
val = 0;
- WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
- dev_wlc_intvar_set(dev, "wpa_auth", 0);
+
+ WL_INFORM(("%s: %d: setting wpa_auth to %d\n",
+ __FUNCTION__, __LINE__, val));
+ error = dev_wlc_intvar_set(dev, "wpa_auth", 0);
+ if (error)
+ WL_ERROR(("Failed to set 'wpa_auth'iovar\n"));
return error;
}
@@ -4977,11 +5263,17 @@ wl_iw_set_wpaauth(
break;
case IW_AUTH_DROP_UNENCRYPTED:
- dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
+ error = dev_wlc_bufvar_set(dev, "wsec_restrict", \
+ (char *)&paramval, sizeof(paramval));
+ if (error)
+ WL_ERROR(("%s: wsec_restrict %d\n", __FUNCTION__, error));
break;
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ error = dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", \
+ (char *)&paramval, sizeof(paramval));
+ if (error)
+ WL_WSEC(("%s: rx_unencrypted_eapol %d\n", __FUNCTION__, error));
break;
#if WIRELESS_EXT > 17
@@ -5110,15 +5402,24 @@ wl_iw_get_wpaauth(
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
- dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ error = dev_wlc_bufvar_get(dev, "tkip_countermeasures", \
+ (char *)&paramval, sizeof(paramval));
+ if (error)
+ WL_ERROR(("%s get tkip_countermeasures %d\n", __FUNCTION__, error));
break;
case IW_AUTH_DROP_UNENCRYPTED:
- dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
+ error = dev_wlc_bufvar_get(dev, "wsec_restrict", \
+ (char *)&paramval, sizeof(paramval));
+ if (error)
+ WL_ERROR(("%s get wsec_restrict %d\n", __FUNCTION__, error));
break;
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ error = dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", \
+ (char *)&paramval, sizeof(paramval));
+ if (error)
+ WL_ERROR(("%s get rx_unencrypted_eapol %d\n", __FUNCTION__, error));
break;
case IW_AUTH_80211_AUTH_ALG:
@@ -5347,7 +5648,7 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
int i;
iscan_info_t *iscan = g_iscan;
- WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
+ WL_SCAN(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) {
WL_ERROR(("%s error exit\n", __FUNCTION__));
@@ -5379,7 +5680,6 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
}
-
iscan->iscan_ex_params_p->params.channel_num = \
htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
(nchan & WL_SCAN_PARAMS_COUNT_MASK));
@@ -5388,7 +5688,6 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
(uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \
WL_SCAN_PARAMS_COUNT_MASK);
-
params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t));
iscan->iscan_ex_param_size = params_size;
@@ -5495,8 +5794,12 @@ static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info
return -1;
}
+ if (iscan->iscan_ex_param_size > WLC_IOCTL_MAXLEN) {
+ WL_ERROR(("%s wrong ex_param_size %d", \
+ __FUNCTION__, iscan->iscan_ex_param_size));
+ return -1;
+ }
memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
- ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN);
wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
@@ -5716,6 +6019,7 @@ wl_iw_set_cscan(
goto exit_proc;
}
+#if defined(CONFIG_FIRST_SCAN)
if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
@@ -5730,6 +6034,7 @@ wl_iw_set_cscan(
goto exit_proc;
}
}
+#endif
res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
@@ -5745,21 +6050,36 @@ exit_proc:
static int thr_wait_for_2nd_eth_dev(void *data)
{
+ struct net_device *dev = (struct net_device *)data;
+ wl_iw_t *iw;
int ret = 0;
+ unsigned long flags;
+
+ net_os_wake_lock(dev);
DAEMONIZE("wl0_eth_wthread");
- WL_TRACE(("\n>%s threda started:, PID:%x\n", __FUNCTION__, current->pid));
+ WL_TRACE(("\n>%s thread started:, PID:%x\n", __FUNCTION__, current->pid));
+ iw = *(wl_iw_t **)netdev_priv(dev);
+ if (!iw) {
+ WL_ERROR(("%s: dev is null\n", __FUNCTION__));
+ ret = -1;
+ goto fail;
+ }
+#ifndef BCMSDIOH_STD
if (down_timeout(&ap_eth_sema, msecs_to_jiffies(5000)) != 0) {
WL_ERROR(("\n%s: sap_eth_sema timeout \n", __FUNCTION__));
ret = -1;
goto fail;
}
+#endif
+ flags = dhd_os_spin_lock(iw->pub);
if (!ap_net_dev) {
WL_ERROR((" ap_net_dev is null !!!"));
ret = -1;
+ dhd_os_spin_unlock(iw->pub, flags);
goto fail;
}
@@ -5768,6 +6088,8 @@ static int thr_wait_for_2nd_eth_dev(void *data)
ap_cfg_running = TRUE;
+ dhd_os_spin_unlock(iw->pub, flags);
+
bcm_mdelay(500);
wl_iw_send_priv_event(priv_dev, "AP_SET_CFG_OK");
@@ -5775,6 +6097,9 @@ static int thr_wait_for_2nd_eth_dev(void *data)
fail:
WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__));
+ net_os_wake_unlock(dev);
+
+ complete_and_exit(&ap_cfg_exited, 0);
return ret;
}
#endif
@@ -5889,15 +6214,14 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
#ifdef AP_ONLY
if (ap_cfg_running) {
- wl_iw_softap_deassoc_stations(dev);
+ wl_iw_softap_deassoc_stations(dev, NULL);
ap_cfg_running = FALSE;
}
-#endif
+#endif
if (ap_cfg_running == FALSE) {
#ifndef AP_ONLY
-
sema_init(&ap_eth_sema, 0);
mpc = 0;
@@ -5930,7 +6254,10 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
iolen = wl_bssiovar_mkbuf("apsta",
bsscfg_index, &apsta_var, sizeof(apsta_var)+4,
buf, sizeof(buf), &mkvar_err);
- ASSERT(iolen);
+
+ if (iolen <= 0)
+ goto fail;
+
if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) {
WL_ERROR(("%s fail to set apsta \n", __FUNCTION__));
goto fail;
@@ -5951,7 +6278,7 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
goto fail;
}
- res = wl_iw_softap_deassoc_stations(ap_net_dev);
+ res = wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
if ((res = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
@@ -5960,6 +6287,32 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
}
}
+ if (strlen(ap->country_code)) {
+ int error = 0;
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY,
+ ap->country_code, sizeof(ap->country_code))) >= 0) {
+ WL_SOFTAP(("%s: set country %s OK\n",
+ __FUNCTION__, ap->country_code));
+ dhd_bus_country_set(dev, &ap->country_code[0]);
+ } else {
+ WL_ERROR(("%s: ERROR:%d setting country %s\n",
+ __FUNCTION__, error, ap->country_code));
+ }
+ } else {
+ WL_SOFTAP(("%s: Country code is not specified,"
+ " will use Radio's default\n",
+ __FUNCTION__));
+ }
+
+ iolen = wl_bssiovar_mkbuf("closednet",
+ bsscfg_index, &ap->closednet, sizeof(ap->closednet)+4,
+ buf, sizeof(buf), &mkvar_err);
+ ASSERT(iolen);
+ if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) {
+ WL_ERROR(("%s failed to set 'closednet'for apsta \n", __FUNCTION__));
+ goto fail;
+ }
+
if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) {
ap->channel = 1;
@@ -6008,8 +6361,10 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
goto fail;
}
if (ap_cfg_running == FALSE) {
- kernel_thread(thr_wait_for_2nd_eth_dev, 0, 0);
+ init_completion(&ap_cfg_exited);
+ ap_cfg_pid = kernel_thread(thr_wait_for_2nd_eth_dev, dev, 0);
} else {
+ ap_cfg_pid = -1;
if (ap_net_dev == NULL) {
WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__));
goto fail;
@@ -6055,8 +6410,9 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
WL_SOFTAP(("wl_iw: set ap profile:\n"));
WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
WL_SOFTAP((" security = '%s'\n", ap->sec));
- if (ap->key[0] != '\0')
+ if (ap->key[0] != '\0') {
WL_SOFTAP((" key = '%s'\n", ap->key));
+ }
WL_SOFTAP((" channel = %d\n", ap->channel));
WL_SOFTAP((" max scb = %d\n", ap->max_scb));
@@ -6157,6 +6513,7 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
if (key_len < WSEC_MAX_PSK_LEN) {
unsigned char output[2*SHA1HashSize];
char key_str_buf[WSEC_MAX_PSK_LEN+1];
+ bzero(output, 2*SHA1HashSize);
WL_SOFTAP(("%s: do passhash...\n", __FUNCTION__));
@@ -6212,7 +6569,6 @@ int get_parmeter_from_string(
int parm_str_len;
char *param_str_begin;
char *param_str_end;
- char *orig_str = *str_ptr;
if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) {
@@ -6269,27 +6625,36 @@ int get_parmeter_from_string(
return 0;
} else {
- WL_ERROR(("\n %s: ERROR: can't find token:%s in str:%s \n",
- __FUNCTION__, token, orig_str));
+ WL_ERROR(("\n %s: No token:%s in str:%s\n",
+ __FUNCTION__, token, *str_ptr));
return -1;
}
}
-
-static int wl_iw_softap_deassoc_stations(struct net_device *dev)
+static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac)
{
int i;
int res = 0;
char mac_buf[128] = {0};
- struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+ char z_mac[6] = {0, 0, 0, 0, 0, 0};
+ char *sta_mac;
+ struct maclist *assoc_maclist = (struct maclist *) mac_buf;
+ bool deauth_all = false;
+
+ if (mac == NULL) {
+ deauth_all = true;
+ sta_mac = z_mac;
+ } else {
+ sta_mac = mac;
+ }
memset(assoc_maclist, 0, sizeof(mac_buf));
assoc_maclist->count = 8;
res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 128);
if (res != 0) {
- WL_SOFTAP((" Error:%d in :%s, Couldn't get ASSOC List\n", res, __FUNCTION__));
+ WL_SOFTAP(("%s: Error:%d Couldn't get ASSOC List\n", __FUNCTION__, res));
return res;
}
@@ -6300,18 +6665,19 @@ static int wl_iw_softap_deassoc_stations(struct net_device *dev)
scbval.val = htod32(1);
bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN);
- WL_SOFTAP(("deauth STA:%d \n", i));
- res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
+ if (deauth_all || (memcmp(&scbval.ea, sta_mac, ETHER_ADDR_LEN) == 0)) {
+ WL_SOFTAP(("%s, deauth STA:%d \n", __FUNCTION__, i));
+ res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
&scbval, sizeof(scb_val_t));
+ }
}
} else {
WL_SOFTAP((" STA ASSOC list is empty\n"));
}
- if (res != 0)
- WL_SOFTAP((" Error:%d in :%s\n", res, __FUNCTION__));
- else if (assoc_maclist->count) {
-
+ if (res != 0) {
+ WL_ERROR(("%s: Error:%d\n", __FUNCTION__, res));
+ } else if (assoc_maclist->count) {
bcm_mdelay(200);
}
return res;
@@ -6336,9 +6702,9 @@ static int iwpriv_softap_stop(struct net_device *dev,
if ((ap_cfg_running == TRUE)) {
#ifdef AP_ONLY
- wl_iw_softap_deassoc_stations(dev);
+ wl_iw_softap_deassoc_stations(dev, NULL);
#else
- wl_iw_softap_deassoc_stations(ap_net_dev);
+ wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0)
WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res));
@@ -6468,9 +6834,14 @@ iwpriv_en_ap_bss(
net_os_wake_lock(dev);
- WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
+ WL_SOFTAP(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
#ifndef AP_ONLY
+ if (ap_cfg_pid >= 0) {
+ wait_for_completion(&ap_cfg_exited);
+ ap_cfg_pid = -1;
+ }
+
if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res));
}
@@ -6492,84 +6863,108 @@ iwpriv_en_ap_bss(
static int
get_assoc_sta_list(struct net_device *dev, char *buf, int len)
{
- WL_TRACE(("calling dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n",
- dev, WLC_GET_ASSOCLIST, buf, len));
+ WL_TRACE(("%s: dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n",
+ __FUNCTION__, dev, WLC_GET_ASSOCLIST, buf, len));
- dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len);
+ return dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len);
- return 0;
}
+void check_error(int res, const char *msg, const char *func, int line)
+{
+ if (res != 0)
+ WL_ERROR(("%s, %d function:%s, line:%d\n", msg, res, func, line));
+}
+
static int
-set_ap_mac_list(struct net_device *dev, char *buf)
+set_ap_mac_list(struct net_device *dev, void *buf)
{
struct mac_list_set *mac_list_set = (struct mac_list_set *)buf;
- struct maclist *white_maclist = (struct maclist *)&mac_list_set->white_list;
- struct maclist *black_maclist = (struct maclist *)&mac_list_set->black_list;
- int mac_mode = mac_list_set->mode;
+ struct maclist *maclist = (struct maclist *)&mac_list_set->mac_list;
int length;
int i;
+ int mac_mode = mac_list_set->mode;
+ int ioc_res = 0;
+ ap_macmode = mac_list_set->mode;
- ap_macmode = mac_mode;
- if (mac_mode == MACLIST_MODE_DISABLED) {
+ bzero(&ap_black_list, sizeof(struct mflist));
- bzero(&ap_black_list, sizeof(struct mflist));
+ if (mac_mode == MACLIST_MODE_DISABLED) {
- dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
+ ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
+ check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
+ WL_SOFTAP(("%s: MAC filtering disabled\n", __FUNCTION__));
} else {
+
scb_val_t scbval;
char mac_buf[256] = {0};
struct maclist *assoc_maclist = (struct maclist *) mac_buf;
- mac_mode = MACLIST_MODE_ALLOW;
+ bcopy(maclist, &ap_black_list, sizeof(ap_black_list));
+
+ ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
+ check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
- dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
+ length = sizeof(maclist->count) + maclist->count*ETHER_ADDR_LEN;
+ dev_wlc_ioctl(dev, WLC_SET_MACLIST, maclist, length);
- length = sizeof(white_maclist->count)+white_maclist->count*ETHER_ADDR_LEN;
- dev_wlc_ioctl(dev, WLC_SET_MACLIST, white_maclist, length);
- WL_SOFTAP(("White List, length %d:\n", length));
- for (i = 0; i < white_maclist->count; i++)
+ WL_SOFTAP(("%s: applied MAC List, mode:%d, length %d:\n",
+ __FUNCTION__, mac_mode, length));
+ for (i = 0; i < maclist->count; i++)
WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
- i, white_maclist->ea[i].octet[0], white_maclist->ea[i].octet[1],
- white_maclist->ea[i].octet[2],
- white_maclist->ea[i].octet[3], white_maclist->ea[i].octet[4],
- white_maclist->ea[i].octet[5]));
+ i, maclist->ea[i].octet[0], maclist->ea[i].octet[1], \
+ maclist->ea[i].octet[2], \
+ maclist->ea[i].octet[3], maclist->ea[i].octet[4], \
+ maclist->ea[i].octet[5]));
- bcopy(black_maclist, &ap_black_list, sizeof(ap_black_list));
+ assoc_maclist->count = 8;
+ ioc_res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256);
+ check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
+ WL_SOFTAP((" Cur assoc clients:%d\n", assoc_maclist->count));
- WL_SOFTAP(("Black List, size %d:\n", sizeof(ap_black_list)));
- for (i = 0; i < ap_black_list.count; i++)
- WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
- i, ap_black_list.ea[i].octet[0], ap_black_list.ea[i].octet[1],
- ap_black_list.ea[i].octet[2],
- ap_black_list.ea[i].octet[3],
- ap_black_list.ea[i].octet[4], ap_black_list.ea[i].octet[5]));
-
- dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256);
- if (assoc_maclist->count) {
- int j;
+ if (assoc_maclist->count)
for (i = 0; i < assoc_maclist->count; i++) {
- for (j = 0; j < white_maclist->count; j++) {
- if (!bcmp(&assoc_maclist->ea[i], &white_maclist->ea[j],
+ int j;
+ bool assoc_mac_matched = false;
+
+ WL_SOFTAP(("\n Cheking assoc STA: "));
+ print_buf(&assoc_maclist->ea[i], 6, 7);
+ WL_SOFTAP(("with the b/w list:"));
+
+ for (j = 0; j < maclist->count; j++)
+ if (!bcmp(&assoc_maclist->ea[i], &maclist->ea[j],
ETHER_ADDR_LEN)) {
- WL_SOFTAP(("match allow, let it be\n"));
+
+ assoc_mac_matched = true;
break;
}
- }
- if (j == white_maclist->count) {
- WL_SOFTAP(("match black, deauth it\n"));
- scbval.val = htod32(1);
- bcopy(&assoc_maclist->ea[i], &scbval.ea,
+
+ if (((mac_mode == MACLIST_MODE_ALLOW) && !assoc_mac_matched) ||
+ ((mac_mode == MACLIST_MODE_DENY) && assoc_mac_matched)) {
+
+ WL_SOFTAP(("b-match or w-mismatch,"
+ " do deauth/disassoc \n"));
+ scbval.val = htod32(1);
+ bcopy(&assoc_maclist->ea[i], &scbval.ea, \
ETHER_ADDR_LEN);
- dev_wlc_ioctl(dev,
- WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
- sizeof(scb_val_t));
+ ioc_res = dev_wlc_ioctl(dev,
+ WLC_SCB_DEAUTHENTICATE_FOR_REASON,
+ &scbval, sizeof(scb_val_t));
+ check_error(ioc_res,
+ "ioctl ERROR:",
+ __FUNCTION__, __LINE__);
+
+ } else {
+ WL_SOFTAP((" no b/w list hits, let it be\n"));
}
- }
+ } else {
+ WL_SOFTAP(("No ASSOC CLIENTS\n"));
}
- }
- return 0;
+ }
+
+ WL_SOFTAP(("%s iocres:%d\n", __FUNCTION__, ioc_res));
+ return ioc_res;
}
#endif
@@ -6702,22 +7097,26 @@ static int wl_iw_set_priv(
ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
ret = wl_iw_control_wl_off(dev, info);
- else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
+ else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
+ else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0)
+ else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0)
ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
+ else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
+ else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+ else if (strnicmp(extra, SETDFSCHANNELS_CMD, strlen(SETDFSCHANNELS_CMD)) == 0)
+ ret = wl_iw_set_dfs_channels(dev, info, (union iwreq_data *)dwrq, extra);
+#endif
#if defined(PNO_SUPPORT)
- else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
+ else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0)
+ else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0)
ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0)
+ else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0)
ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
#endif
#if defined(CSCAN)
@@ -6884,6 +7283,9 @@ static const iw_handler wl_iw_priv_handler[] = {
NULL,
(iw_handler)iwpriv_fw_reload,
+
+ NULL,
+ (iw_handler)iwpriv_set_ap_sta_disassoc,
#endif
#if defined(CSCAN)
@@ -6946,8 +7348,8 @@ static const struct iw_priv_args wl_iw_priv_args[] = {
{
WL_AP_STA_LIST,
- 0,
IW_PRIV_TYPE_CHAR | 0,
+ IW_PRIV_TYPE_CHAR | 1024,
"AP_GET_STA_LIST"
},
@@ -6985,6 +7387,13 @@ static const struct iw_priv_args wl_iw_priv_args[] = {
IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
"WL_FW_RELOAD"
},
+
+ {
+ WL_AP_STA_DISASSOC,
+ IW_PRIV_TYPE_CHAR | 256,
+ IW_PRIV_TYPE_CHAR | 0,
+ "AP_STA_DISASSOC"
+ },
#endif
#if defined(CSCAN)
{
@@ -7262,6 +7671,12 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type));
switch (event_type) {
+
+ case WLC_E_RELOAD:
+ WL_ERROR(("%s: Firmware ERROR %d\n", __FUNCTION__, status));
+ net_os_send_hang_message(dev);
+ goto wl_iw_event_end;
+
#if defined(SOFTAP)
case WLC_E_PRUNE:
if (ap_cfg_running) {
@@ -7312,10 +7727,14 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
cmd = IWEVREGISTERED;
break;
case WLC_E_ROAM:
- if (status != WLC_E_STATUS_SUCCESS) {
+ if (status == WLC_E_STATUS_SUCCESS) {
+ memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ cmd = SIOCGIWAP;
+ }
+ else if (status == WLC_E_STATUS_NO_NETWORKS) {
roam_no_success++;
- if ((roam_no_success == 3) && (roam_no_success_send == FALSE)) {
-
+ if ((roam_no_success == 5) && (roam_no_success_send == FALSE)) {
roam_no_success_send = TRUE;
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
bzero(&extra, ETHER_ADDR_LEN);
@@ -7326,10 +7745,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
WL_TRACE(("##### ROAMING did not succeeded %d\n", roam_no_success));
goto wl_iw_event_end;
}
- } else {
- memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
- wrqu.addr.sa_family = ARPHRD_ETHER;
- cmd = SIOCGIWAP;
}
break;
case WLC_E_DEAUTH_IND:
@@ -7618,13 +8033,21 @@ wl_iw_bt_flag_set(
struct net_device *dev,
bool set)
{
+#if defined(BT_DHCP_USE_FLAGS)
char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_lock();
#endif
+#if defined(BT_DHCP_eSCO_FIX)
+ set_btc_esco_params(dev, set);
+#endif
+
+#if defined(BT_DHCP_USE_FLAGS)
+ WL_TRACE_COEX(("WI-FI priority boost via bt flags, set:%d\n", set));
if (set == TRUE) {
dev_wlc_bufvar_set(dev, "btc_flags",
(char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on));
@@ -7633,6 +8056,7 @@ wl_iw_bt_flag_set(
dev_wlc_bufvar_set(dev, "btc_flags",
(char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
}
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_unlock();
@@ -7665,14 +8089,23 @@ _bt_dhcp_sysioc_thread(void *data)
switch (g_bt->bt_state) {
case BT_DHCP_START:
+ WL_TRACE_COEX(("%s bt_dhcp stm: started \n", __FUNCTION__));
g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW;
- mod_timer(&g_bt->timer, jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000);
+ mod_timer(&g_bt->timer, jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIME*HZ/1000);
g_bt->timer_on = 1;
break;
case BT_DHCP_OPPORTUNITY_WINDOW:
- WL_TRACE(("%s waiting for %d msec expired, force bt flag\n", \
- __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIEM));
+ if (g_bt->dhcp_done) {
+ WL_TRACE_COEX(("%s DHCP Done before T1 expiration\n", \
+ __FUNCTION__));
+ g_bt->bt_state = BT_DHCP_IDLE;
+ g_bt->timer_on = 0;
+ break;
+ }
+
+ WL_TRACE_COEX(("%s DHCP T1:%d expired\n", \
+ __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIME));
if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE);
g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000);
@@ -7680,9 +8113,14 @@ _bt_dhcp_sysioc_thread(void *data)
break;
case BT_DHCP_FLAG_FORCE_TIMEOUT:
- WL_TRACE(("%s waiting for %d msec expired remove bt flag\n", \
+ if (g_bt->dhcp_done) {
+ WL_TRACE_COEX(("%s DHCP Done before T2 expiration\n", \
+ __FUNCTION__));
+ } else {
+ WL_TRACE_COEX(("%s DHCP wait interval T2:%d msec expired\n",
__FUNCTION__, BT_DHCP_FLAG_FORCE_TIME));
-
+ }
+
if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
g_bt->bt_state = BT_DHCP_IDLE;
g_bt->timer_on = 0;
@@ -7757,7 +8195,7 @@ wl_iw_bt_init(struct net_device *dev)
return 0;
}
-int wl_iw_attach(struct net_device *dev, void * dhdp)
+int wl_iw_attach(struct net_device *dev, void *dhdp)
{
int params_size;
wl_iw_t *iw;
@@ -7766,7 +8204,6 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
#endif
mutex_init(&wl_cache_lock);
- mutex_init(&wl_start_lock);
#if defined(WL_IW_USE_ISCAN)
if (!dev)
@@ -7794,9 +8231,11 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
g_iscan = iscan;
iscan->dev = dev;
iscan->iscan_state = ISCAN_STATE_IDLE;
+#if defined(CONFIG_FIRST_SCAN)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
g_first_counter_scans = 0;
g_iscan->scan_flag = 0;
+#endif
iscan->timer_ms = 8000;
init_timer(&iscan->timer);
@@ -7871,5 +8310,4 @@ void wl_iw_detach(void)
wl_iw_send_priv_event(priv_dev, "AP_DOWN");
}
#endif
-
}
diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h
index 43088cf..928291f 100644
--- a/bcm4329/src/wl/sys/wl_iw.h
+++ b/bcm4329/src/wl/sys/wl_iw.h
@@ -21,7 +21,7 @@
* 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_iw.h,v 1.5.34.1.6.36.4.1 2010/09/10 19:24:30 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.36.4.15 2010/11/17 03:13:51 Exp $
*/
@@ -52,6 +52,7 @@
#define PNOSETUP_SET_CMD "PNOSETUP "
#define PNOENABLE_SET_CMD "PNOFORCE"
#define PNODEBUG_SET_CMD "PNODEBUG"
+#define SETDFSCHANNELS_CMD "SETDFSCHANNELS"
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
@@ -87,8 +88,9 @@ typedef struct wl_iw_extra_params {
#define AP_LPB_CMD (SIOCIWFIRSTPRIV+23)
#define WL_AP_STOP (SIOCIWFIRSTPRIV+25)
#define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27)
-#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+29)
-#define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31)
+#define WL_AP_STA_DISASSOC (SIOCIWFIRSTPRIV+29)
+#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+31)
+
#define G_SCAN_RESULTS (8*1024)
#define WE_ADD_EVENT_FIX 0x80
#define G_WLAN_SET_ON 0
@@ -116,19 +118,18 @@ typedef struct wl_iw {
dhd_pub_t * pub;
} wl_iw_t;
-#define WLC_IW_SS_CACHE_MAXLEN 512
+#define WLC_IW_SS_CACHE_MAXLEN 2048
#define WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN 32
#define WLC_IW_BSS_INFO_MAXLEN \
(WLC_IW_SS_CACHE_MAXLEN - WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN)
typedef struct wl_iw_ss_cache {
+ struct wl_iw_ss_cache *next;
+ int dirty;
uint32 buflen;
uint32 version;
uint32 count;
wl_bss_info_t bss_info[1];
- char dummy[WLC_IW_BSS_INFO_MAXLEN - sizeof(wl_bss_info_t)];
- int dirty;
- struct wl_iw_ss_cache *next;
} wl_iw_ss_cache_t;
typedef struct wl_iw_ss_cache_ctrl {
@@ -140,6 +141,7 @@ typedef struct wl_iw_ss_cache_ctrl {
uint m_cons_br_scan_cnt;
struct timer_list *m_timer;
} wl_iw_ss_cache_ctrl_t;
+
typedef enum broadcast_first_scan {
BROADCAST_SCAN_FIRST_IDLE = 0,
BROADCAST_SCAN_FIRST_STARTED,
@@ -158,12 +160,14 @@ struct ap_profile {
uint32 channel;
uint32 preamble;
uint32 max_scb;
+ uint32 closednet;
+ char country_code[WLC_CNTRY_BUF_SZ];
};
#define MACLIST_MODE_DISABLED 0
-#define MACLIST_MODE_ENABLED 1
-#define MACLIST_MODE_ALLOW 2
+#define MACLIST_MODE_DENY 1
+#define MACLIST_MODE_ALLOW 2
struct mflist {
uint count;
struct ether_addr ea[16];
@@ -171,8 +175,7 @@ struct mflist {
struct mac_list_set {
uint32 mode;
- struct mflist white_list;
- struct mflist black_list;
+ struct mflist mac_list;
};
#endif
@@ -196,7 +199,9 @@ extern int net_os_set_suspend_disable(struct net_device *dev, int val);
extern int net_os_set_suspend(struct net_device *dev, int val);
extern int net_os_set_dtim_skip(struct net_device *dev, int val);
extern int net_os_set_packet_filter(struct net_device *dev, int val);
-extern int net_os_send_hang_message(struct net_device *dev);
+extern void dhd_bus_country_set(struct net_device *dev, char *country_code);
+extern char *dhd_bus_country_get(struct net_device *dev);
+extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
@@ -225,12 +230,13 @@ extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled);
extern int dhd_dev_get_pno_status(struct net_device *dev);
#define PNO_TLV_PREFIX 'S'
-#define PNO_TLV_VERSION 1
-#define PNO_TLV_SUBVERSION 1
-#define PNO_TLV_RESERVED 0
+#define PNO_TLV_VERSION '1'
+#define PNO_TLV_SUBVERSION '2'
+#define PNO_TLV_RESERVED '0'
#define PNO_TLV_TYPE_SSID_IE 'S'
#define PNO_TLV_TYPE_TIME 'T'
#define PNO_EVENT_UP "PNO_EVENT"
+#define PNO_SCAN_MAX_FW 508
typedef struct cmd_tlv {
char prefix;