aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-07-26 13:10:39 +0200
committerDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-07-26 13:10:39 +0200
commit079c8bf723b03ac908b3c17b8223ffbc3bb670ce (patch)
tree5125ede6f1f86e5d79740ec16b47f72d7c697809
parentba8ce2ed8f562b1397834abe23ada742d03f0d31 (diff)
downloadkernel_samsung_espresso10-079c8bf723b03ac908b3c17b8223ffbc3bb670ce.tar.gz
kernel_samsung_espresso10-079c8bf723b03ac908b3c17b8223ffbc3bb670ce.tar.bz2
kernel_samsung_espresso10-079c8bf723b03ac908b3c17b8223ffbc3bb670ce.zip
bcmdhd: driver from t1, fixes tethering
-rw-r--r--drivers/net/wireless/bcmdhd/Kconfig5
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile34
-rw-r--r--drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c122
-rw-r--r--drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c92
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h22
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c11
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c36
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_gpio.c10
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c319
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c215
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_proto.h2
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c151
-rw-r--r--drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h43
-rw-r--r--drivers/net/wireless/bcmdhd/src/include/epivers.h10
-rw-r--r--drivers/net/wireless/bcmdhd/src/include/linuxver.h1
-rw-r--r--drivers/net/wireless/bcmdhd/src/include/proto/p2p.h2
-rw-r--r--drivers/net/wireless/bcmdhd/src/include/wlioctl.h7
-rw-r--r--drivers/net/wireless/bcmdhd/src/shared/siutils.c5
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/bcmwifi/include/bcmwifi_channels.h4
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c345
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c1389
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h129
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c112
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h8
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wl_linux_mon.c11
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wl_roam.c32
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c9
-rw-r--r--drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.h3
28 files changed, 2343 insertions, 786 deletions
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig
index 4cc0264a0cc..d01c045a198 100644
--- a/drivers/net/wireless/bcmdhd/Kconfig
+++ b/drivers/net/wireless/bcmdhd/Kconfig
@@ -23,6 +23,11 @@ config BROADCOM_WIFI_RESERVED_MEM
---help---
This is a configuration for broadcom WLAN driver.
+config WLAN_COUNTRY_CODE
+ tristate "---Broadcom WiFi Driver for 5GH channel setting"
+ depends on WLAN
+ default n
+
config WLAN_REGION_CODE
int "---Region codes for Broadcom WiFi Driver"
depends on (BCM4330 || BCM4334 || BCM43241)
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index 11a4b676260..8558f2440fe 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -14,23 +14,23 @@ ifeq ($(CONFIG_BCM4334),m)
DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DBCM4334_CHECK_CHIP_REV
DHDCFLAGS += -DUSE_CID_CHECK -DCONFIG_CONTROL_PM
DHDCFLAGS += -DPROP_TXSTATUS
-DHDCFLAGS += -DVSDB
-DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE
+DHDCFLAGS += -DVSDB -DHT40_GO
+DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+DHDCFLAGS += -DDHD_USE_IDLECOUNT
endif
ifeq ($(CONFIG_BCM4334),y)
DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DBCM4334_CHECK_CHIP_REV
DHDCFLAGS += -DUSE_CID_CHECK -DCONFIG_CONTROL_PM
DHDCFLAGS += -DPROP_TXSTATUS
-DHDCFLAGS += -DVSDB
+DHDCFLAGS += -DVSDB -DHT40_GO
DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE
+DHDCFLAGS += -DDHD_USE_IDLECOUNT
endif
ifeq ($(CONFIG_BCM4330),m)
-DHDCFLAGS += -DBCM4330_CHIP
+DHDCFLAGS += -DBCM4330_CHIP -DHW_OOB
DHDCFLAGS += -DMCAST_LIST_ACCUMULATION
DHDCFLAGS += -DCONFIG_CONTROL_PM
DHDCFLAGS += -DDHD_USE_IDLECOUNT
-DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE
endif
ifeq ($(CONFIG_BCM4330),y)
@@ -38,18 +38,15 @@ DHDCFLAGS += -DBCM4330_CHIP
DHDCFLAGS += -DMCAST_LIST_ACCUMULATION
DHDCFLAGS += -DCONFIG_CONTROL_PM
DHDCFLAGS += -DDHD_USE_IDLECOUNT
-DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE
endif
ifeq ($(CONFIG_BCM43241),m)
DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB
DHDCFLAGS += -DMCAST_LIST_ACCUMULATION
-DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE
DHDCFLAGS += -fno-pic
endif
ifeq ($(CONFIG_BCM43241),y)
DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB
DHDCFLAGS += -DMCAST_LIST_ACCUMULATION
-DHDCFLAGS += -DROAM_ENABLE -DROAM_API -DROAM_CHANNEL_CACHE
endif
# For p2p connection issue
@@ -59,11 +56,21 @@ DHDCFLAGS += -DWL_CFG80211_SYNC_GON_TIME
# For Passing all multicast packets to host when not in suspend mode.
DHDCFLAGS += -DPASS_ALL_MCAST_PKTS
+
+#For INITIAL 2G scan features
+#select only one from USE_INIITAL_2G_SCAN and INITIAL_2G_SCAN_ORG
+
DHDCFLAGS += -DUSE_INITIAL_2G_SCAN
+#DHDCFLAGS += -DUSE_INITIAL_2G_SCAN_ORG
+
+DHDCFLAGS +=-DINITIAL_2G_SCAN_BY_ESCAN
# For Scan result patch
DHDCFLAGS += -DESCAN_RESULT_PATCH
+
+DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API
+
# For Static Buffer
ifeq ($(CONFIG_BROADCOM_WIFI_RESERVED_MEM),y)
DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF
@@ -74,6 +81,15 @@ ifeq ($(CONFIG_BRCM_CCX),y)
DHDCFLAGS += -DBCMCCX
endif
+# For SLP feature
+ifeq ($(CONFIG_SLP),y)
+DHDCFLAGS += -DSLP_PATH -DWRITE_MACADDR
+endif
+
+# 5GHz channels setting
+ifeq ($(CONFIG_WLAN_COUNTRY_CODE),y)
+DHDCFLAGS += -DGLOBALCONFIG_WLAN_COUNTRY_CODE
+endif
# For ICS SEC Features
ifneq ($(findstring GlobalConfig, $(wildcard $(srctree)/include/sec_feature/*)),)
diff --git a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c
index 5eae9936d7e..7fdc1665363 100644
--- a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc.c
@@ -63,8 +63,11 @@ extern int sdio_reset_comm(struct mmc_card *card);
extern PBCMSDH_SDMMC_INSTANCE gInstance;
uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */
+#if defined(SDIO_F2_BLKSIZE)
+uint sd_f2_blocksize = SDIO_F2_BLKSIZE;
+#else
uint sd_f2_blocksize = 512; /* Default blocksize */
-
+#endif
uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */
uint sd_power = 1; /* Default to SD Slot powered ON */
@@ -154,16 +157,22 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
gInstance->sd = sd;
/* Claim host controller */
- sdio_claim_host(gInstance->func[1]);
+ if (gInstance->func[1]) {
+ sdio_claim_host(gInstance->func[1]);
- sd->client_block_size[1] = 64;
- err_ret = sdio_set_block_size(gInstance->func[1], 64);
- if (err_ret) {
- sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
- }
+ sd->client_block_size[1] = 64;
+ err_ret = sdio_set_block_size(gInstance->func[1], 64);
+ if (err_ret) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
+ }
- /* Release host controller F1 */
- sdio_release_host(gInstance->func[1]);
+ /* Release host controller F1 */
+ sdio_release_host(gInstance->func[1]);
+ }else {
+ sd_err(("%s:gInstance->func[1] is null\n", __FUNCTION__));
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ return NULL;
+ }
if (gInstance->func[2]) {
/* Claim host controller F2 */
@@ -178,6 +187,10 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
/* Release host controller F2 */
sdio_release_host(gInstance->func[2]);
+ }else {
+ sd_err(("%s:gInstance->func[2] is null\n", __FUNCTION__));
+ MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+ return NULL;
}
sdioh_sdmmc_card_enablefuncs(sd);
@@ -803,41 +816,49 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
#if defined(MMC_SDIO_ABORT)
/* to allow abort command through F1 */
else if (regaddr == SDIOD_CCCR_IOABORT) {
- sdio_claim_host(gInstance->func[func]);
- /*
- * this sdio_f0_writeb() can be replaced with another api
- * depending upon MMC driver change.
- * As of this time, this is temporaray one
- */
- sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
+ if (gInstance->func[func]){
+ sdio_claim_host(gInstance->func[func]);
+ /*
+ * this sdio_f0_writeb() can be replaced with another api
+ * depending upon MMC driver change.
+ * As of this time, this is temporaray one
+ */
+ sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
+ sdio_release_host(gInstance->func[func]);
+ }
}
#endif /* MMC_SDIO_ABORT */
else if (regaddr < 0xF0) {
sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
} else {
/* Claim host controller, perform F0 write, and release */
- sdio_claim_host(gInstance->func[func]);
- sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
+ if (gInstance->func[func]){
+ sdio_claim_host(gInstance->func[func]);
+ sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
+ sdio_release_host(gInstance->func[func]);
+ }
}
} else {
/* Claim host controller, perform Fn write, and release */
- sdio_claim_host(gInstance->func[func]);
- sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
+ if (gInstance->func[func]){
+ sdio_claim_host(gInstance->func[func]);
+ sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
+ sdio_release_host(gInstance->func[func]);
+ }
}
} else { /* CMD52 Read */
/* Claim host controller, perform Fn read, and release */
- sdio_claim_host(gInstance->func[func]);
+ if (gInstance->func[func]){
+ sdio_claim_host(gInstance->func[func]);
- if (func == 0) {
- *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
- } else {
- *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
- }
+ if (func == 0) {
+ *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
+ } else {
+ *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
+ }
- sdio_release_host(gInstance->func[func]);
+ sdio_release_host(gInstance->func[func]);
+ }
}
if (err_ret) {
@@ -1016,7 +1037,13 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
pkt_len -= xfred_len;
xfred_len = 0;
}
- pkt_len = (pkt_len + 3) & 0xFFFFFFFC;
+
+ /* Align Patch */
+ if (write == 0 || pkt_len < 32) // read or small packet(ex-BDC header) skip 32 byte align
+ pkt_len = (pkt_len + 3) & 0xFFFFFFFC;
+ else if(pkt_len % DHD_SDALIGN) // write
+ pkt_len += DHD_SDALIGN - (pkt_len % DHD_SDALIGN);
+
#ifdef CONFIG_MMC_MSM7X00A
if ((pkt_len % 64) == 32) {
sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__));
@@ -1303,12 +1330,14 @@ sdioh_start(sdioh_info_t *si, int stage)
int ret;
sdioh_info_t *sd = gInstance->sd;
+ if (!sd) return (0);
+
/* Need to do this stages as we can't enable the interrupt till
downloading of the firmware is complete, other wise polling
sdio access will come in way
*/
if (gInstance->func[0]) {
- if (stage == 0) {
+ if (stage == 0) {
/* Since the power to the chip is killed, we will have
re enumerate the device again. Set the block size
and enable the fucntion 1 for in preparation for
@@ -1328,17 +1357,18 @@ sdioh_start(sdioh_info_t *si, int stage)
sd->use_client_ints = TRUE;
sd->client_block_size[0] = 64;
- /* Claim host controller */
- sdio_claim_host(gInstance->func[1]);
+ if(gInstance->func[1]) {
+ /* Claim host controller */
+ sdio_claim_host(gInstance->func[1]);
- sd->client_block_size[1] = 64;
- if (sdio_set_block_size(gInstance->func[1], 64)) {
- sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
+ sd->client_block_size[1] = 64;
+ if (sdio_set_block_size(gInstance->func[1], 64)) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
+ }
+ /* Release host controller F1 */
+ sdio_release_host(gInstance->func[1]);
}
- /* Release host controller F1 */
- sdio_release_host(gInstance->func[1]);
-
if (gInstance->func[2]) {
/* Claim host controller F2 */
sdio_claim_host(gInstance->func[2]);
@@ -1359,8 +1389,10 @@ sdioh_start(sdioh_info_t *si, int stage)
} else {
#if !defined(OOB_INTR_ONLY)
sdio_claim_host(gInstance->func[0]);
- sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
- sdio_claim_irq(gInstance->func[1], IRQHandler);
+ if (gInstance->func[2])
+ sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
+ if (gInstance->func[1])
+ sdio_claim_irq(gInstance->func[1], IRQHandler);
sdio_release_host(gInstance->func[0]);
#else /* defined(OOB_INTR_ONLY) */
#if defined(HW_OOB)
@@ -1388,8 +1420,10 @@ sdioh_stop(sdioh_info_t *si)
if (gInstance->func[0]) {
#if !defined(OOB_INTR_ONLY)
sdio_claim_host(gInstance->func[0]);
- sdio_release_irq(gInstance->func[1]);
- sdio_release_irq(gInstance->func[2]);
+ if (gInstance->func[1])
+ sdio_release_irq(gInstance->func[1]);
+ if (gInstance->func[2])
+ sdio_release_irq(gInstance->func[2]);
sdio_release_host(gInstance->func[0]);
#else /* defined(OOB_INTR_ONLY) */
#if defined(HW_OOB)
diff --git a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
index 0b35efb4bff..0ee8d1beeaa 100644
--- a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
+++ b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
@@ -109,31 +109,36 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
{
int ret = 0;
static struct sdio_func sdio_func_0;
- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
- sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class));
- sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
- sd_trace(("sdio_device: 0x%04x\n", func->device));
- sd_trace(("Function#: 0x%04x\n", func->num));
-
- if (func->num == 1) {
- sdio_func_0.num = 0;
- sdio_func_0.card = func->card;
- gInstance->func[0] = &sdio_func_0;
- if(func->device == 0x4) { /* 4318 */
- gInstance->func[2] = NULL;
- sd_trace(("NIC found, calling bcmsdh_probe...\n"));
- ret = bcmsdh_probe(&func->dev);
+
+ if (func) {
+ sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
+ sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class));
+ sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
+ sd_trace(("sdio_device: 0x%04x\n", func->device));
+ sd_trace(("Function#: 0x%04x\n", func->num));
+
+ if (func->num == 1) {
+ sdio_func_0.num = 0;
+ sdio_func_0.card = func->card;
+ gInstance->func[0] = &sdio_func_0;
+ if(func->device == 0x4) { /* 4318 */
+ gInstance->func[2] = NULL;
+ sd_trace(("NIC found, calling bcmsdh_probe...\n"));
+ ret = bcmsdh_probe(&func->dev);
+ }
}
- }
- gInstance->func[func->num] = func;
+ gInstance->func[func->num] = func;
- if (func->num == 2) {
+ if (func->num == 2) {
#ifdef WL_CFG80211
- wl_cfg80211_set_parent_dev(&func->dev);
+ wl_cfg80211_set_parent_dev(&func->dev);
#endif
- sd_trace(("F2 found, calling bcmsdh_probe...\n"));
- ret = bcmsdh_probe(&func->dev);
+ sd_trace(("F2 found, calling bcmsdh_probe...\n"));
+ ret = bcmsdh_probe(&func->dev);
+ }
+ }else {
+ ret = -ENODEV;
}
return ret;
@@ -141,20 +146,22 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
static void bcmsdh_sdmmc_remove(struct sdio_func *func)
{
- sd_err(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
- sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
- sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
- sd_info(("sdio_device: 0x%04x\n", func->device));
- sd_info(("Function#: 0x%04x\n", func->num));
-
- if (func->num == 2) {
- sd_err(("F2 found, calling bcmsdh_remove...\n"));
- bcmsdh_remove(&func->dev);
- } else if (func->num == 1) {
- sdio_claim_host(func);
- sdio_disable_func(func);
- sdio_release_host(func);
- gInstance->func[1] = NULL;
+ if (func) {
+ sd_err(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
+ sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
+ sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
+ sd_info(("sdio_device: 0x%04x\n", func->device));
+ sd_info(("Function#: 0x%04x\n", func->num));
+
+ if (func->num == 2) {
+ sd_err(("F2 found, calling bcmsdh_remove...\n"));
+ bcmsdh_remove(&func->dev);
+ } else if (func->num == 1) {
+ sdio_claim_host(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+ gInstance->func[1] = NULL;
+ }
}
}
@@ -183,13 +190,15 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev)
if (func->num != 2)
return 0;
- sd_trace(("%s Enter\n", __FUNCTION__));
+ sd_err(("%s Enter\n", __FUNCTION__));
if (dhd_os_check_wakelock(bcmsdh_get_drvdata()))
return -EBUSY;
+#if !defined(CUSTOMER_HW_SAMSUNG)
#if defined(OOB_INTR_ONLY)
bcmsdh_oob_intr_set(0);
#endif /* defined(OOB_INTR_ONLY) */
+#endif /* !CUSTOMER_HW_SAMSUNG */
dhd_mmc_suspend = TRUE;
smp_mb();
@@ -201,12 +210,15 @@ static int bcmsdh_sdmmc_resume(struct device *pdev)
#if defined(OOB_INTR_ONLY)
struct sdio_func *func = dev_to_sdio_func(pdev);
#endif
- sd_trace(("%s Enter\n", __FUNCTION__));
+ if (func->num == 2)
+ sd_err(("%s Enter\n", __FUNCTION__));
dhd_mmc_suspend = FALSE;
+#if !defined(CUSTOMER_HW_SAMSUNG)
#if defined(OOB_INTR_ONLY)
if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata()))
bcmsdh_oob_intr_set(1);
#endif /* (OOB_INTR_ONLY) */
+#endif /* !CUSTOMER_HW_SAMSUNG */
smp_mb();
return 0;
@@ -257,13 +269,11 @@ static struct sdio_driver bcmsdh_sdmmc_driver = {
.remove = bcmsdh_sdmmc_remove,
.name = "bcmsdh_sdmmc",
.id_table = bcmsdh_sdmmc_ids,
-#if 0
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM)
.drv = {
.pm = &bcmsdh_sdmmc_pm_ops,
},
#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */
-#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */
};
struct sdos_info {
@@ -277,6 +287,9 @@ sdioh_sdmmc_osinit(sdioh_info_t *sd)
{
struct sdos_info *sdos;
+ if(!sd)
+ return BCME_BADARG;
+
sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info));
sd->sdos_info = (void*)sdos;
if (sdos == NULL)
@@ -304,6 +317,9 @@ sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
ulong flags;
struct sdos_info *sdos;
+ if(!sd)
+ return BCME_BADARG;
+
sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling"));
sdos = (struct sdos_info *)sd->sdos_info;
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h
index 7d59cc6f7c5..af523b8d021 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h
@@ -253,6 +253,7 @@ typedef struct dhd_pub {
void* wlfc_state;
#endif
bool dongle_isolation;
+ bool dongle_trap_occured; /* flag for forcible sending HANG event whenever trap occured */
int hang_was_sent;
int rxcnt_timeout; /* counter rxcnt timeout to send HANG */
int txcnt_timeout; /* counter txcnt timeout to send HANG */
@@ -260,6 +261,9 @@ typedef struct dhd_pub {
uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */
#endif
struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS];
+#if defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK)
+ struct wake_lock pno_wakelock;
+#endif
} dhd_pub_t;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
@@ -273,9 +277,19 @@ typedef struct dhd_pub {
wait_event_interruptible_timeout(a, !dhd_mmc_suspend, HZ/100); \
} \
} while (0)
+#ifdef CUSTOMER_HW_SAMSUNG
+ #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 500)
+#else
#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200)
+#endif /* CUSTOMER_HW_SAMSUNG */
#define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
- #define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0)
+ #define DHD_PM_RESUME_RETURN_ERROR(a) do { \
+ if (dhd_mmc_suspend) { \
+ printf("mmc in suspend yet!!!: %s %d\n", \
+ __FUNCTION__, __LINE__); \
+ return a; \
+ } \
+ } while (0)
#define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0)
#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
@@ -555,7 +569,7 @@ extern uint dhd_bus_status(dhd_pub_t *dhdp);
extern int dhd_bus_start(dhd_pub_t *dhdp);
extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
-extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf);
+extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval);
#if defined(KEEP_ALIVE)
extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
@@ -657,13 +671,13 @@ extern char fw_path2[MOD_PARAM_PATHLEN];
/* Flag to indicate if we should download firmware on driver load */
extern uint dhd_download_fw_on_driverload;
-#if defined(CUSTOMER_HW_SAMSUNG) && defined(WL_CFG80211)
+#if defined(WL_CFG80211) && defined(CUSTOMER_HW_SAMSUNG)
/* CSP#505233: Flags to indicate if we distingish power off policy when
* user set the memu "Keep Wi-Fi on during sleep" to "Never"
*/
extern int sleep_never;
int dhd_deepsleep(struct net_device *dev, int flag);
-#endif /* CUSTOMER_HW_SAMSUNG && WL_CFG80211 */
+#endif /* WL_CFG80211 && CUSTOMER_HW_SAMSUNG */
#ifdef BCM4334_CHECK_CHIP_REV
/* Check chip revision */
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c
index 1df4f6c2712..2bac067b68f 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cdc.c
@@ -113,12 +113,20 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+#ifdef CUSTOMER_HW_SAMSUNG
+ DHD_OS_WAKE_LOCK(dhd);
+#endif /* CUSTOMER_HW_SAMSUNG */
+
do {
ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
if (ret < 0)
break;
} while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id);
+#ifdef CUSTOMER_HW_SAMSUNG
+ DHD_OS_WAKE_UNLOCK(dhd);
+#endif /* CUSTOMER_HW_SAMSUNG */
+
return ret;
}
@@ -2203,6 +2211,9 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd)
for (i = 0; i < h->max_items; i++) {
if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) {
PKTFREE(wlfc->osh, h->items[i].pkt, TRUE);
+ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE;
+ h->items[i].pkt = NULL;
+ h->items[i].identifier = 0;
}
}
return;
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c
index 59bf314b6ee..18a94bdc33d 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c
@@ -267,13 +267,36 @@ int
dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int ifindex)
{
wl_ioctl_t ioc;
+#ifdef CUSTOMER_HW_SAMSUNG
+ int ret;
+#endif /* CUSTOMER_HW_SAMSUNG */
ioc.cmd = cmd;
ioc.buf = arg;
ioc.len = len;
ioc.set = set;
+#ifdef CUSTOMER_HW_SAMSUNG
+ ret = dhd_wl_ioctl(dhd_pub, ifindex, &ioc, arg, len);
+ if (ret < 0) {
+ if (ioc.cmd == WLC_GET_VAR) {
+ DHD_ERROR(("%s: WLC_GET_VAR: %s, error = %d\n",
+ __FUNCTION__, (char *)ioc.buf, ret));
+ } else if (ioc.cmd == WLC_SET_VAR) {
+ char pkt_filter[] = "pkt_filter_add";
+ if (strncmp(pkt_filter, ioc.buf, sizeof(pkt_filter)) != 0) {
+ DHD_ERROR(("%s: WLC_SET_VAR: %s, error = %d\n",
+ __FUNCTION__, (char *)ioc.buf, ret));
+ }
+ } else {
+ DHD_ERROR(("%s: WLC_IOCTL: cmd:%d, error = %d\n",
+ __FUNCTION__, ioc.cmd, ret));
+ }
+ }
+ return ret;
+#else
return dhd_wl_ioctl(dhd_pub, ifindex, &ioc, arg, len);
+#endif /* CUSTOMER_HW_SAMSUNG */
}
@@ -285,7 +308,7 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le
dhd_os_proto_block(dhd_pub);
ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len);
- if (!ret)
+ if (!ret || ret == -ETIMEDOUT)
dhd_os_check_hang(dhd_pub, ifindex, ret);
dhd_os_proto_unblock(dhd_pub);
@@ -933,7 +956,7 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data)
p = (char *)&buf[MSGTRACE_HDRLEN];
while ((s = strstr(p, "\n")) != NULL) {
*s = '\0';
- printf("%s\n", p);
+ printf("FW: %s\n", p);
p = s+1;
}
printf("%s\n", p);
@@ -1742,7 +1765,7 @@ fail:
/*
* returns = TRUE if associated, FALSE if not associated
*/
-bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf)
+bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval)
{
char bssid[6], zbuf[6];
int ret = -1;
@@ -1757,6 +1780,9 @@ bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf)
DHD_TRACE(("%s: not associated! res:%d\n", __FUNCTION__, ret));
}
+ if (retval)
+ *retval = ret;
+
if (ret < 0)
return FALSE;
@@ -1789,7 +1815,7 @@ dhd_get_dtim_skip(dhd_pub_t *dhd)
bcn_li_dtim = dhd->dtim_skip;
/* Check if associated */
- if (dhd_is_associated(dhd, NULL) == FALSE) {
+ if (dhd_is_associated(dhd, NULL, NULL) == FALSE) {
DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret));
goto exit;
}
@@ -1889,7 +1915,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
memset(iovbuf, 0, sizeof(iovbuf));
- if ((pfn_enabled) && (dhd_is_associated(dhd, NULL) == TRUE)) {
+ if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) {
DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
return ret;
}
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_gpio.c
index e33ab5dbaad..edb203e15fb 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_gpio.c
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_gpio.c
@@ -210,6 +210,7 @@ const struct cntry_locales_custom translate_custom_table[] = {
{"BN", "BN", 1},
{"CA", "CA", 2},
{"CH", "CH", 1},
+ {"CN", "CN", 0},
{"CY", "CY", 1},
{"CZ", "CZ", 1},
{"DE", "DE", 3},
@@ -246,6 +247,15 @@ const struct cntry_locales_custom translate_custom_table[] = {
{"SK", "SK", 1},
{"TR", "TR", 7},
{"TW", "TW", 2},
+#ifdef CUSTOMER_HW_SAMSUNG
+ {"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */
+ {"SD", "XZ", 11}, /* Universal if Country code is SUDAN */
+ {"SY", "XZ", 11}, /* Universal if Country code is SYRIAN ARAB REPUBLIC */
+ {"GL", "XZ", 11}, /* Universal if Country code is GREENLAND */
+ {"PS", "XZ", 11}, /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */
+ {"TL", "XZ", 11}, /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */
+ {"MH", "XZ", 11}, /* Universal if Country code is MARSHALL ISLANDS */
+#endif
#ifdef BCM4334_CHIP
{"RU", "RU", 5},
{"SG", "SG", 4},
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c
index 9591f10347a..a651884babd 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c
@@ -18,7 +18,10 @@ extern int _dhd_set_mac_address(struct dhd_info *dhd,
#ifdef SLP_PATH
#define CIDINFO "/opt/etc/.cid.info"
#define PSMINFO "/opt/etc/.psm.info"
+#define MACINFO "/opt/etc/.mac.info"
+#define REVINFO "/data/.rev"
#else
+#define REVINFO "/data/.rev"
#define CIDINFO "/data/.cid.info"
#define PSMINFO "/data/.psm.info"
#endif /*SLP_PATH*/
@@ -32,52 +35,46 @@ int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac)
char randommac[3] = {0};
char buf[18] = {0};
char *filepath = "/efs/wifi/.mac.info";
+#ifdef CONFIG_TARGET_LOCALE_VZW
+ char *nvfilepath = "/data/misc/wifi/.nvmac.info";
+#else
+ char *nvfilepath = "/data/.nvmac.info";
+#endif
int ret = 0;
- struct dentry *parent;
- struct dentry *dentry;
- struct inode *p_inode;
- struct inode *c_inode;
- fp = filp_open(filepath, O_RDONLY, 0);
- if (IS_ERR(fp)) {
-start_readmac:
- /* File Doesn't Exist. Create and write mac addr.*/
- fp = filp_open(filepath, O_RDWR | O_CREAT, 0666);
+ fp = filp_open(filepath, O_RDONLY, 0);
if (IS_ERR(fp)) {
+start_readmac:
+ /* File Doesn't Exist. Create and write mac addr.*/
+ fp = filp_open(filepath, O_RDWR | O_CREAT, 0666);
+ if (IS_ERR(fp)) {
DHD_ERROR(("[WIFI] %s: File open error\n", filepath));
- return -1;
- }
- oldfs = get_fs();
- set_fs(get_ds());
- /* set uid , gid of parent directory */
- dentry = fp->f_path.dentry;
- parent = dget_parent(dentry);
- c_inode = dentry->d_inode;
- p_inode = parent->d_inode;
- c_inode->i_uid = p_inode->i_uid;
- c_inode->i_gid = p_inode->i_gid;
+ return -1;
+ }
+ oldfs = get_fs();
+ set_fs(get_ds());
/* Generating the Random Bytes for 3 last octects of the MAC address */
- get_random_bytes(randommac, 3);
+ get_random_bytes(randommac, 3);
- sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n",
0x00, 0x12, 0x34, randommac[0], randommac[1], randommac[2]);
DHD_ERROR(("[WIFI]The Random Generated MAC ID: %s\n", macbuffer));
- if (fp->f_mode & FMODE_WRITE) {
+ if (fp->f_mode & FMODE_WRITE) {
ret = fp->f_op->write(fp, (const char *)macbuffer, sizeof(macbuffer), &fp->f_pos);
- if (ret < 0)
+ if (ret < 0)
DHD_ERROR(("[WIFI]MAC address [%s] Failed to write into File: %s\n", macbuffer, filepath));
- else
+ else
DHD_ERROR(("[WIFI]MAC address [%s] written into File: %s\n", macbuffer, filepath));
- }
- set_fs(oldfs);
+ }
+ set_fs(oldfs);
/* Reading the MAC Address from .mac.info file( the existed file or just created file)*/
ret = kernel_read(fp, 0, buf, 18);
} else {
/* Reading the MAC Address from .mac.info file( the existed file or just created file)*/
ret = kernel_read(fp, 0, buf, 18);
- /* to prevent abnormal string display when mac address is displayed on the screen. */
+/* to prevent abnormal string display when mac address is displayed on the screen. */
buf[17] = '\0';
DHD_INFO(("Read MAC : [%s] [%d] \r\n" , buf, strncmp(buf , "00:00:00:00:00:00" , 17)));
if (strncmp(buf , "00:00:00:00:00:00" , 17) < 1) {
@@ -112,7 +109,7 @@ start_readmac:
static int g_imac_flag;
enum {
- MACADDR_NONE =0 ,
+ MACADDR_NONE = 0 ,
MACADDR_MOD,
MACADDR_MOD_RANDOM,
MACADDR_MOD_NONE,
@@ -122,31 +119,54 @@ enum {
int dhd_write_rdwr_macaddr(struct ether_addr *mac)
{
- char *filepath = "/efs/wifi/.mac.info";
- struct file *fp_mac = NULL;
- char buf[18] = {0};
- mm_segment_t oldfs = {0};
+ char *filepath_old = "/data/.mac.info";
+ char *filepath = "/efs/wifi/.mac.info";
+ struct file *fp_mac = NULL;
+ char buf[18] = {0};
+ mm_segment_t oldfs = {0};
int ret = -1;
if ((g_imac_flag != MACADDR_COB) && (g_imac_flag != MACADDR_MOD))
return 0;
- sprintf(buf,"%02X:%02X:%02X:%02X:%02X:%02X\n",
- mac->octet[0],mac->octet[1],mac->octet[2],
- mac->octet[3],mac->octet[4],mac->octet[5]);
+ sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ mac->octet[0], mac->octet[1], mac->octet[2],
+ mac->octet[3], mac->octet[4], mac->octet[5]);
+
+ /* /data/.mac.info will be created */
+ fp_mac = filp_open(filepath_old, O_RDWR | O_CREAT, 0666);
+ if (IS_ERR(fp_mac)) {
+ DHD_ERROR(("[WIFI] %s: File open error\n", filepath_old));
+ return -1;
+ } else {
+ oldfs = get_fs();
+ set_fs(get_ds());
- /* File is always created. */
+ if (fp_mac->f_mode & FMODE_WRITE) {
+ ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
+ sizeof(buf), &fp_mac->f_pos);
+ if (ret < 0)
+ DHD_ERROR(("[WIFI] Mac address [%s] Failed"
+ " to write into File: %s\n", buf, filepath_old));
+ else
+ DHD_INFO(("[WIFI] Mac address [%s] written"
+ " into File: %s\n", buf, filepath_old));
+ }
+ set_fs(oldfs);
+ filp_close(fp_mac, NULL);
+ }
+ /* /efs/wifi/.mac.info will be created */
fp_mac = filp_open(filepath, O_RDWR | O_CREAT, 0666);
if (IS_ERR(fp_mac)) {
DHD_ERROR(("[WIFI] %s: File open error\n", filepath));
return -1;
- } else {
+ } else {
oldfs = get_fs();
set_fs(get_ds());
if (fp_mac->f_mode & FMODE_WRITE) {
ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
- sizeof(buf), &fp_mac->f_pos);
+ sizeof(buf), &fp_mac->f_pos);
if (ret < 0)
DHD_ERROR(("[WIFI] Mac address [%s] Failed"
" to write into File: %s\n", buf, filepath));
@@ -163,32 +183,39 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac)
}
int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp,
- struct ether_addr *mac)
+ struct ether_addr *mac)
{
struct file *fp_mac = NULL;
struct file *fp_nvm = NULL;
- char macbuffer[18]= {0};
- char randommac[3] = {0};
- char buf[18] = {0};
- char *filepath = "/data/.mac.info";
+ char macbuffer[18] = {0};
+ char randommac[3] = {0};
+ char buf[18] = {0};
+ char *filepath_old = "/data/.mac.info";
+ char *filepath = "/efs/wifi/.mac.info";
#ifdef CONFIG_TARGET_LOCALE_NA
- char* nvfilepath = "/data/misc/wifi/.nvmac.info";
+ char *nvfilepath = "/data/misc/wifi/.nvmac.info";
#else
- char* nvfilepath = "/data/.nvmac.info";
+ char *nvfilepath = "/data/.nvmac.info";
#endif
- char cur_mac[128] = {0};
+ char cur_mac[128] = {0};
char dummy_mac[ETHER_ADDR_LEN] = {0x00, 0x90, 0x4C, 0xC5, 0x12, 0x38};
- char cur_macbuffer[18] = {0};
+ char cur_macbuffer[18] = {0};
int ret = -1;
g_imac_flag = MACADDR_NONE;
fp_nvm = filp_open(nvfilepath, O_RDONLY, 0);
if (IS_ERR(fp_nvm)) { /* file does not exist */
+
+ /* Create the .nvmac.info */
+ fp_nvm = filp_open(nvfilepath, O_RDWR | O_CREAT, 0666);
+ if (!IS_ERR(fp_nvm))
+ filp_close(fp_nvm, NULL);
+
/* read MAC Address */
strcpy(cur_mac, "cur_etheraddr");
ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, cur_mac,
- sizeof(cur_mac), 0, 0);
+ sizeof(cur_mac), 0, 0);
if (ret < 0) {
DHD_ERROR(("Current READ MAC error \r\n"));
memset(cur_mac , 0 , ETHER_ADDR_LEN);
@@ -200,10 +227,59 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp,
cur_mac[4], cur_mac[5]));
}
- sprintf(cur_macbuffer,"%02X:%02X:%02X:%02X:%02X:%02X\n",
+ sprintf(cur_macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n",
cur_mac[0], cur_mac[1], cur_mac[2],
cur_mac[3], cur_mac[4], cur_mac[5]);
+ fp_mac = filp_open(filepath_old, O_RDONLY, 0);
+ if (IS_ERR(fp_mac)) { /* file does not exist */
+ /* read mac is the dummy mac (00:90:4C:C5:12:38) */
+ if (memcmp(cur_mac, dummy_mac, ETHER_ADDR_LEN) == 0)
+ g_imac_flag = MACADDR_MOD_RANDOM;
+ else if (strncmp(buf, "00:00:00:00:00:00", 17) == 0)
+ g_imac_flag = MACADDR_MOD_RANDOM;
+ else
+ g_imac_flag = MACADDR_MOD;
+ } else {
+ int is_zeromac;
+
+ ret = kernel_read(fp_mac, 0, buf, 18);
+ filp_close(fp_mac, NULL);
+ buf[17] = '\0';
+
+ is_zeromac = strncmp(buf, "00:00:00:00:00:00", 17);
+ DHD_ERROR(("MAC (FILE): [%s] [%d] \r\n",
+ buf, is_zeromac));
+
+ if (is_zeromac == 0) {
+ DHD_ERROR(("Zero MAC detected."
+ " Trying Random MAC.\n"));
+ g_imac_flag = MACADDR_MOD_RANDOM;
+ } else {
+ sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+ (unsigned int *)&(mac->octet[0]),
+ (unsigned int *)&(mac->octet[1]),
+ (unsigned int *)&(mac->octet[2]),
+ (unsigned int *)&(mac->octet[3]),
+ (unsigned int *)&(mac->octet[4]),
+ (unsigned int *)&(mac->octet[5]));
+ /* current MAC address is same as previous one */
+ if(memcmp(cur_mac,mac->octet,ETHER_ADDR_LEN) == 0) {
+ g_imac_flag = MACADDR_NONE;
+ } else { /* change MAC address */
+ if (0 == _dhd_set_mac_address(dhd, 0, mac)) {
+ DHD_INFO(("%s: MACID is"
+ " overwritten\n", __FUNCTION__));
+ g_imac_flag = MACADDR_MOD;
+ } else {
+ DHD_ERROR(("%s: "
+ "_dhd_set_mac_address()"
+ " failed\n", __FUNCTION__));
+ g_imac_flag = MACADDR_NONE;
+ }
+ }
+ }
+ }
fp_mac = filp_open(filepath, O_RDONLY, 0);
if (IS_ERR(fp_mac)) { /* file does not exist */
/* read mac is the dummy mac (00:90:4C:C5:12:38) */
@@ -218,7 +294,7 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp,
ret = kernel_read(fp_mac, 0, buf, 18);
filp_close(fp_mac, NULL);
- buf[17] ='\0';
+ buf[17] = '\0';
is_zeromac = strncmp(buf, "00:00:00:00:00:00", 17);
DHD_ERROR(("MAC (FILE): [%s] [%d] \r\n",
@@ -229,14 +305,14 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp,
" Trying Random MAC.\n"));
g_imac_flag = MACADDR_MOD_RANDOM;
} else {
- sscanf(buf,"%02X:%02X:%02X:%02X:%02X:%02X",
+ sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
(unsigned int *)&(mac->octet[0]),
(unsigned int *)&(mac->octet[1]),
(unsigned int *)&(mac->octet[2]),
(unsigned int *)&(mac->octet[3]),
(unsigned int *)&(mac->octet[4]),
(unsigned int *)&(mac->octet[5]));
- /* current MAC address is same as previous one */
+ /* current MAC address is same as previous one */
if(memcmp(cur_mac,mac->octet,ETHER_ADDR_LEN) == 0) {
g_imac_flag = MACADDR_NONE;
} else { /* change MAC address */
@@ -263,14 +339,14 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp,
/* to prevent abnormal string display when mac address
* is displayed on the screen.
*/
- buf[17] ='\0';
+ buf[17] = '\0';
DHD_ERROR(("Read MAC : [%s] [%d] \r\n", buf,
strncmp(buf, "00:00:00:00:00:00", 17)));
if ((buf[0] == '\0') ||
(strncmp(buf, "00:00:00:00:00:00", 17) == 0)) {
g_imac_flag = MACADDR_COB_RANDOM;
} else {
- sscanf(buf,"%02X:%02X:%02X:%02X:%02X:%02X",
+ sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
(unsigned int *)&(mac->octet[0]),
(unsigned int *)&(mac->octet[1]),
(unsigned int *)&(mac->octet[2]),
@@ -293,12 +369,12 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp,
if ((g_imac_flag == MACADDR_COB_RANDOM) ||
(g_imac_flag == MACADDR_MOD_RANDOM)) {
get_random_bytes(randommac, 3);
- sprintf(macbuffer,"%02X:%02X:%02X:%02X:%02X:%02X\n",
+ sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n",
0x60, 0xd0, 0xa9, randommac[0], randommac[1],
randommac[2]);
DHD_ERROR(("[WIFI] The Random Generated MAC ID : %s\n",
macbuffer));
- sscanf(macbuffer,"%02X:%02X:%02X:%02X:%02X:%02X",
+ sscanf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X",
(unsigned int *)&(mac->octet[0]),
(unsigned int *)&(mac->octet[1]),
(unsigned int *)&(mac->octet[2]),
@@ -456,33 +532,15 @@ int dhd_check_module_cid(dhd_pub_t *dhd)
int ret = -1;
#ifdef BCM4334_CHIP
unsigned char cis_buf[250] = {0};
+ const char *revfilepath = REVINFO;
+ int flag_b3 = 0;
#else
unsigned char cis_buf[128] = {0};
#endif
- unsigned char cid_buf[10] = {0};
- const char* cidfilepath = "/data/.cid.info";
+ const char *cidfilepath = CIDINFO;
/* Try reading out from CIS */
cis_rw_t *cish = (cis_rw_t *)&cis_buf[8];
- struct file *fp_cid = NULL;
-
- fp_cid = filp_open(cidfilepath, O_RDONLY, 0);
- if (!IS_ERR(fp_cid)) {
- kernel_read(fp_cid, fp_cid->f_pos, cid_buf, sizeof(cid_buf));
- if (strstr(cid_buf, "samsung") ||
- strstr(cid_buf, "murata")
-#ifdef BCM4330_CHIP
- || strstr(cid_buf, "semcove")
-#endif
- ) {
- /* file does exist, just return */
- filp_close(fp_cid, NULL);
- return 0;
- }
-
- DHD_ERROR(("[WIFI].cid.info file already exists but"
- " it contains an unknown id [%s]\n", cid_buf));
- }
cish->source = 0;
cish->byteoff = 0;
@@ -494,9 +552,11 @@ int dhd_check_module_cid(dhd_pub_t *dhd)
if (ret < 0) {
DHD_ERROR(("%s: CIS reading failed, err=%d\n",
__FUNCTION__, ret));
+ return ret;
} else {
#ifdef BCM4334_CHIP
unsigned char semco_id[4] = {0x00, 0x00, 0x33, 0x33};
+ unsigned char semco_id_sh[4] = {0x00, 0x00, 0xFB, 0x50}; //for SHARP FEM(new)
DHD_ERROR(("%s: CIS reading success, err=%d\n",
__FUNCTION__, ret));
#ifdef DUMP_CIS
@@ -507,7 +567,13 @@ int dhd_check_module_cid(dhd_pub_t *dhd)
0x%02X 0x%02X\n", cis_buf[CIS_CID_OFFSET],
cis_buf[CIS_CID_OFFSET+1], cis_buf[CIS_CID_OFFSET+2],
cis_buf[CIS_CID_OFFSET+3]));
- dhd_write_cid_file(cidfilepath, "samsung", 7);
+ dhd_write_cid_file(cidfilepath, "semco", 5);
+ } else if (memcmp(&cis_buf[CIS_CID_OFFSET], semco_id_sh, 4) == 0) {
+ DHD_ERROR(("CIS MATCH FOUND : Semco_sh, 0x%02X 0x%02X \
+ 0x%02X 0x%02X\n", cis_buf[CIS_CID_OFFSET],
+ cis_buf[CIS_CID_OFFSET+1], cis_buf[CIS_CID_OFFSET+2],
+ cis_buf[CIS_CID_OFFSET+3]));
+ dhd_write_cid_file(cidfilepath, "semcosh", 7);
} else {
DHD_ERROR(("CID MATCH FOUND : Murata, 0x%02X 0x%02X \
0x%02X 0x%02X\n", cis_buf[CIS_CID_OFFSET],
@@ -516,6 +582,31 @@ int dhd_check_module_cid(dhd_pub_t *dhd)
dhd_write_cid_file(cidfilepath, "murata", 6);
}
+ /* Try reading out from OTP to distinguish B2 or B3 */
+ memset(cis_buf, 0, sizeof(cis_buf));
+ cish = (cis_rw_t *)&cis_buf[8];
+
+ cish->source = 0;
+ cish->byteoff = 0;
+ cish->nbytes = sizeof(cis_buf);
+
+ strcpy(cis_buf, "otpdump");
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf,
+ sizeof(cis_buf), 0, 0);
+ if (ret < 0) {
+ DHD_ERROR(("%s: OTP reading failed, err=%d\n",
+ __FUNCTION__, ret));
+ return ret;
+ }
+
+ /* otp 33th character is identifier for 4334B3 */
+ cis_buf[34] = '\0';
+ flag_b3 = bcm_atoi(&cis_buf[33]);
+ if(flag_b3 & 0x1){
+ DHD_ERROR(("REV MATCH FOUND : 4334B3, %c\n", cis_buf[33]));
+ dhd_write_cid_file(revfilepath, "4334B3", 6);
+ }
+
#else /* BCM4330_CHIP */
unsigned char murata_id[4] = {0x80, 0x06, 0x81, 0x00};
unsigned char semco_ve[4] = {0x80, 0x02, 0x81, 0x99};
@@ -635,20 +726,14 @@ int dhd_check_module_mac(dhd_pub_t *dhd)
#ifdef WRITE_MACADDR
int dhd_write_macaddr(struct ether_addr *mac)
{
-#ifdef U1_MACADDR
- char *filepath = "/data/.mac.info";
-#else
+ char *filepath_old = "/data/.mac.info";
char *filepath = "/efs/wifi/.mac.info";
-#endif
- struct file *fp_mac = NULL;
- char buf[18] = {0};
- mm_segment_t oldfs = {0};
+
+ struct file *fp_mac = NULL;
+ char buf[18] = {0};
+ mm_segment_t oldfs = {0};
int ret = -1;
int retry_count = 0;
- struct dentry *parent;
- struct dentry *dentry;
- struct inode *p_inode;
- struct inode *c_inode;
startwrite:
@@ -656,7 +741,42 @@ startwrite:
mac->octet[0], mac->octet[1], mac->octet[2],
mac->octet[3], mac->octet[4], mac->octet[5]);
- /*File is always created.*/
+ /* File will be created /data/.mac.info. */
+ fp_mac = filp_open(filepath_old, O_RDWR | O_CREAT, 0666);
+
+ if (IS_ERR(fp_mac)) {
+ DHD_ERROR(("[WIFI] %s: File open error\n", filepath_old));
+ return -1;
+ } else {
+ oldfs = get_fs();
+ set_fs(get_ds());
+
+ if (fp_mac->f_mode & FMODE_WRITE) {
+ ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
+ sizeof(buf), &fp_mac->f_pos);
+ if (ret < 0)
+ DHD_ERROR(("[WIFI] Mac address [%s] Failed to"
+ " write into File: %s\n", buf, filepath_old));
+ else
+ DHD_INFO(("[WIFI] Mac address [%s] written"
+ " into File: %s\n", buf, filepath_old));
+ }
+ set_fs(oldfs);
+ filp_close(fp_mac, NULL);
+ }
+ /* check .mac.info file is 0 byte */
+ fp_mac = filp_open(filepath_old, O_RDONLY, 0);
+ ret = kernel_read(fp_mac, 0, buf, 18);
+
+ if ((ret == 0) && (retry_count++ < 3)) {
+ filp_close(fp_mac, NULL);
+ goto startwrite;
+ }
+
+ filp_close(fp_mac, NULL);
+ /* end of /data/.mac.info */
+
+ /* File will be created /efs/wifi/.mac.info. */
fp_mac = filp_open(filepath, O_RDWR | O_CREAT, 0666);
if (IS_ERR(fp_mac)) {
@@ -665,13 +785,6 @@ startwrite:
} else {
oldfs = get_fs();
set_fs(get_ds());
- /* set uid , gid of parent directory */
- dentry = fp_mac->f_path.dentry;
- parent = dget_parent(dentry);
- c_inode = dentry->d_inode;
- p_inode = parent->d_inode;
- c_inode->i_uid = p_inode->i_uid;
- c_inode->i_gid = p_inode->i_gid;
if (fp_mac->f_mode & FMODE_WRITE) {
ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
@@ -726,14 +839,6 @@ void sec_control_pm(dhd_pub_t *dhd, uint *power_mode)
__FUNCTION__, __LINE__));
return;
} else {
- struct dentry *dentry;
- struct inode *c_inode;
- /* set uid , gid to system id(1000) */
- dentry = fp->f_path.dentry;
- c_inode = dentry->d_inode;
- c_inode->i_uid = (uid_t)1000;
- c_inode->i_gid = (uid_t)1000;
-
oldfs = get_fs();
set_fs(get_ds());
@@ -779,7 +884,7 @@ void sec_control_pm(dhd_pub_t *dhd, uint *power_mode)
filp_close(fp, NULL);
}
#endif
-#ifdef CUSTOMER_SET_COUNTRY
+#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE
int dhd_customer_set_country(dhd_pub_t *dhd)
{
struct file *fp = NULL;
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c
index ed840bc00fd..02b4d65e655 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c
@@ -194,7 +194,7 @@ extern int dhd_check_module_mac(dhd_pub_t *dhd);
#endif
#endif /* CUSTOMER_HW_SAMSUNG */
-#ifdef CUSTOMER_SET_COUNTRY
+#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE
int dhd_customer_set_country(dhd_pub_t *dhd);
#endif
@@ -213,6 +213,7 @@ typedef struct dhd_if {
char name[IFNAMSIZ+1]; /* linux interface name */
uint8 bssidx; /* bsscfg index for the interface */
bool set_multicast;
+ bool event2cfg80211; /* To determine if pass event to cfg80211 */
} dhd_if_t;
#ifdef WLMEDIA_HTSF
@@ -336,6 +337,7 @@ char firmware_path[MOD_PARAM_PATHLEN];
char nvram_path[MOD_PARAM_PATHLEN];
int op_mode = 0;
+int disable_proptx = 0;
module_param(op_mode, int, 0644);
extern int wl_control_wl_start(struct net_device *dev);
extern int net_os_send_hang_message(struct net_device *dev);
@@ -354,12 +356,15 @@ module_param(dhd_sysioc, uint, 0);
/* Error bits */
module_param(dhd_msg_level, int, 0);
+/* Disable Prop tx */
+module_param(disable_proptx, int, 0);
+
/* load firmware and/or nvram values from the filesystem */
module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
/* Watchdog interval */
-uint dhd_watchdog_ms = 100;
+uint dhd_watchdog_ms = 10;
module_param(dhd_watchdog_ms, uint, 0);
#if defined(DHD_DEBUG)
@@ -549,7 +554,7 @@ static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored)
{
int ret = NOTIFY_DONE;
-
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
switch (action) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
@@ -563,7 +568,7 @@ static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long actio
break;
}
smp_mb();
-
+#endif
return ret;
}
@@ -922,7 +927,10 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
#endif /* MCAST_LIST_ACCUMULATION */
#ifdef PASS_ALL_MCAST_PKTS
- allmulti = TRUE;
+#ifdef PKT_FILTER_SUPPORT
+ if (!dhd->pub.early_suspended)
+ allmulti = TRUE;
+#endif
#endif /* PASS_ALL_MCAST_PKTS */
/* Send down the multicast list first. */
@@ -1156,6 +1164,7 @@ dhd_op_if(dhd_if_t *ifp)
if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, ifp->bssidx,
(void*)dhd_net_attach)) {
ifp->state = DHD_IF_NONE;
+ ifp->event2cfg80211 = TRUE;
return;
}
#endif
@@ -1502,7 +1511,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
DHD_OS_WAKE_UNLOCK(&dhd->pub);
return -ENODEV;
}
-#endif
+#endif /* CUSTOMER_HW_SAMSUNG */
ifidx = dhd_net2idx(dhd, net);
if (ifidx == DHD_BAD_IF) {
@@ -2312,8 +2321,8 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
{
if (!dhdp)
return FALSE;
- if ((error == -ETIMEDOUT) || ((dhdp->busstate == DHD_BUS_DOWN) &&
- (!dhdp->dongle_reset))) {
+ if ((error == -ETIMEDOUT) || (error == -EREMOTEIO)
+ || ((dhdp->busstate == DHD_BUS_DOWN)&&(!dhdp->dongle_reset))) {
DHD_ERROR(("%s: Event HANG send up due to re=%d te=%d e=%d s=%d\n", __FUNCTION__,
dhdp->rxcnt_timeout, dhdp->txcnt_timeout, error, dhdp->busstate));
net_os_send_hang_message(net);
@@ -2631,8 +2640,9 @@ dhd_stop(struct net_device *net)
wl_android_wifi_off(net);
#ifdef CUSTOMER_HW_SAMSUNG
else {
- /* CSP#505233: Flags to indicate if we distingish power off policy when
- * user set the memu "Keep Wi-Fi on during sleep" to "Never"
+ /* CSP#505233: Flags to indicate if we distingish
+ * power off policy when user set the memu
+ * "Keep Wi-Fi on during sleep" to "Never"
*/
if (sleep_never) {
dhd_deepsleep(net, 1);
@@ -2642,6 +2652,7 @@ dhd_stop(struct net_device *net)
#endif /* CUSTOMER_HW_SAMSUNG */
}
#endif /* WL_CFG80211 */
+ dhd->pub.dongle_trap_occured = 0;
dhd->pub.hang_was_sent = 0;
dhd->pub.rxcnt_timeout = 0;
dhd->pub.txcnt_timeout = 0;
@@ -2655,9 +2666,6 @@ static int
dhd_open(struct net_device *net)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
-#ifdef PROP_TXSTATUS
- uint up = 0;
-#endif
#ifdef TOE
uint32 toe_ol;
#endif
@@ -2668,22 +2676,22 @@ dhd_open(struct net_device *net)
#endif
DHD_OS_WAKE_LOCK(&dhd->pub);
/* Update FW path if it was changed */
- if ((firmware_path != NULL) && (firmware_path[0] != '\0')) {
+ if ((strlen(firmware_path) != 0) && (firmware_path[0] != '\0')) {
if (firmware_path[strlen(firmware_path)-1] == '\n')
firmware_path[strlen(firmware_path)-1] = '\0';
#ifdef WL_CFG80211
- if (dhd_download_fw_on_driverload &&
+ if (dhd_download_fw_on_driverload &&
strcmp(fw_path, firmware_path))
{
- DHD_ERROR(("firmware path changed:%s --> %s\n",
- fw_path, firmware_path));
- fw_changed = TRUE;
- }
-#endif
- strcpy(fw_path, firmware_path);
+ DHD_ERROR(("firmware path changed:%s --> %s\n",
+ fw_path, firmware_path));
+ fw_changed = TRUE;
+ }
+#endif /* WL_CFG80211 */
+ strcpy(fw_path, firmware_path);
#if defined(BCM4334_CHECK_CHIP_REV)
- strcpy(fw_down_path, fw_path);
- strcat(fw_down_path, chipver_tag);
+ strcpy(fw_down_path, fw_path);
+ strcat(fw_down_path, chipver_tag);
#endif
firmware_path[0] = '\0';
}
@@ -2724,8 +2732,9 @@ dhd_open(struct net_device *net)
}
} else {
#ifdef CUSTOMER_HW_SAMSUNG
- /* CSP#505233: Flags to indicate if we distingish power off policy when
- * user set the memu "Keep Wi-Fi on during sleep" to "Never"
+ /* CSP#505233: Flags to indicate if we distingish
+ * power off policy when user set the memu
+ * "Keep Wi-Fi on during sleep" to "Never"
*/
if (sleep_never) {
dhd_deepsleep(net, 0);
@@ -2733,12 +2742,12 @@ dhd_open(struct net_device *net)
} else {
#endif /* CUSTOMER_HW_SAMSUNG */
if (fw_changed) {
- wl_android_wifi_off(net);
- msleep(300);
- ret = wl_android_wifi_on(net);
- if (ret != 0) {
- DHD_ERROR(("wl_android_wifi_on failed (%d)\n", ret));
- goto exit;
+ wl_android_wifi_off(net);
+ msleep(300);
+ ret = wl_android_wifi_on(net);
+ if (ret != 0) {
+ DHD_ERROR(("wl_android_wifi_on failed (%d)\n", ret));
+ goto exit;
}
}
#ifdef CUSTOMER_HW_SAMSUNG
@@ -2781,7 +2790,6 @@ dhd_open(struct net_device *net)
/* Allow transmit calls */
netif_start_queue(net);
dhd->pub.up = 1;
-
#ifdef BCMDBGFS
dhd_dbg_init(&dhd->pub);
#endif
@@ -2862,6 +2870,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
}
memset(ifp, 0, sizeof(dhd_if_t));
+ ifp->event2cfg80211 = FALSE;
ifp->info = dhd;
dhd->iflist[ifidx] = ifp;
strncpy(ifp->name, name, IFNAMSIZ);
@@ -2877,6 +2886,9 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
up(&dhd->thr_sysioc_ctl.sema);
} else
ifp->net = (struct net_device *)handle;
+ if (ifidx == 0) {
+ ifp->event2cfg80211 = TRUE;
+ }
return 0;
}
@@ -2931,27 +2943,27 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
#ifdef BCM4334_CHECK_CHIP_REV
- DHD_ERROR(("CHIP VER = [0x%x]\n", g_chipver));
- if (g_chipver == 1) {
- DHD_ERROR(("----- CHIP bcm4334_B0 -----\n"));
- strcpy(chipver_tag, "_b0");
- } else if (g_chipver == 2) {
- DHD_ERROR(("----- CHIP bcm4334_B1 -----\n"));
- strcpy(chipver_tag, "_b1");
- } else if (g_chipver == 3) {
- DHD_ERROR(("----- CHIP bcm4334_B2 -----\n"));
- strcpy(chipver_tag, "_b2");
+ DHD_ERROR(("CHIP VER = [0x%x]\n", g_chipver));
+ if (g_chipver == 1) {
+ DHD_ERROR(("----- CHIP bcm4334_B0 -----\n"));
+ strcpy(chipver_tag, "_b0");
+ } else if (g_chipver == 2) {
+ DHD_ERROR(("----- CHIP bcm4334_B1 -----\n"));
+ strcpy(chipver_tag, "_b1");
+ } else if (g_chipver == 3) {
+ DHD_ERROR(("----- CHIP bcm4334_B2 -----\n"));
+ strcpy(chipver_tag, "_b2");
}
else {
- DHD_ERROR(("----- Invalid chip version -----\n"));
- goto fail;
- }
+ DHD_ERROR(("----- Invalid chip version -----\n"));
+ goto fail;
+ }
#endif /* BCM4334_CHECK_CHIP_REV */
/* updates firmware nvram path if it was provided as module parameters */
- if ((firmware_path != NULL) && (firmware_path[0] != '\0'))
+ if ((strlen(firmware_path) != 0) && (firmware_path[0] != '\0'))
strcpy(fw_path, firmware_path);
- if ((nvram_path != NULL) && (nvram_path[0] != '\0'))
+ if ((strlen(nvram_path) != 0) && (nvram_path[0] != '\0'))
strcpy(nv_path, nvram_path);
/* Allocate etherdev, including space for private structure */
@@ -3033,6 +3045,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
+#ifdef PNO_SUPPORT
+ wake_lock_init(&dhd->pub.pno_wakelock, WAKE_LOCK_SUSPEND, "pno_wake_lock");
+#endif
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
mutex_init(&dhd->dhd_net_if_mutex);
@@ -3174,15 +3189,15 @@ dhd_bus_start(dhd_pub_t *dhdp)
if ((dhd->pub.busstate == DHD_BUS_DOWN) &&
(fw_path[0] != '\0') &&
(nv_path[0] != '\0')) {
- down_path = fw_path;
+ down_path = fw_path;
#if defined(BCM4334_CHECK_CHIP_REV)
- strcpy(fw_down_path, fw_path);
- strcat(fw_down_path, chipver_tag);
- down_path = fw_down_path;
+ strcpy(fw_down_path, fw_path);
+ strcat(fw_down_path, chipver_tag);
+ down_path = fw_down_path;
#endif
/* wake lock moved to dhdsdio_download_firmware */
if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
- down_path, nv_path))) {
+ down_path, nv_path))) {
DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
__FUNCTION__, down_path, nv_path));
#ifdef DHDTHREAD
@@ -3285,7 +3300,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
#ifdef RDWR_KORICS_MACADDR
dhd_write_rdwr_korics_macaddr(dhd, &dhd->pub.mac);
-#endif
+#endif /* CUSTOMER_HW_SAMSUNG */
#ifdef ARP_OFFLOAD_SUPPORT
if (dhd->pend_ipaddr) {
@@ -3352,7 +3367,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#else
uint32 glom = 0;
#endif
-#ifdef VSDB
+#if defined(VSDB) || defined(ROAM_ENABLE)
uint bcn_timeout = 8;
#else
uint bcn_timeout = 4;
@@ -3410,13 +3425,16 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
int vlanmode = 0;
#endif /* VLAN_MODE_OFF */
#ifdef BCM43241_CHIP
- int mimo_bw_cap = 1;
+ int mimo_bw_cap = 2;
#endif /* BCM43241_CHIP */
-
+#ifdef AUTOCOUNTRY
+ int autocountry = 1;
+#endif
#ifdef PROP_TXSTATUS
dhd->wlfc_enabled = FALSE;
/* enable WLFC only if the firmware is VSDB */
#endif /* PROP_TXSTATUS */
+
DHD_TRACE(("Enter %s\n", __FUNCTION__));
dhd->op_mode = 0;
#ifdef GET_CUSTOM_MAC_ENABLE
@@ -3544,10 +3562,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_pkt_filter_enable = TRUE;
if (dhd_concurrent_fw(dhd)) {
dhd->op_mode |= WFD_MASK;
-#ifdef PROP_TXSTATUS
- dhd->wlfc_enabled = TRUE;
- /* enable WLFC only if the firmware is VSDB */
-#endif /* PROP_TXSTATUS */
}
}
@@ -3585,6 +3599,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
#endif
+#ifdef AUTOCOUNTRY
+ bcm_mkiovar("autocountry", (char *)&autocountry, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif
+
#endif /* CUSTOMER_HW_SAMSUNG */
#ifdef CONFIG_CONTROL_PM
@@ -3635,9 +3654,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#if defined(SOFTAP)
if (ap_fw_loaded == FALSE)
#endif
+ if ((dhd->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) {
if ((res = dhd_keep_alive_onoff(dhd)) < 0)
DHD_ERROR(("%s set keeplive failed %d\n",
__FUNCTION__, res));
+ }
}
#endif /* defined(KEEP_ALIVE) */
@@ -3677,6 +3698,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#ifdef PNO_SUPPORT
setbit(eventmask, WLC_E_PFN_NET_FOUND);
#endif /* PNO_SUPPORT */
+#ifdef USE_FW_TRACE
+ setbit(eventmask, WLC_E_TRACE);
+#endif
/* enable dongle roaming event */
setbit(eventmask, WLC_E_ROAM);
#ifdef WL_CFG80211
@@ -3734,10 +3758,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#else
/* Setup filter to allow only unicast */
#if defined(CUSTOMER_HW_SAMSUNG)
+ dhd->pktfilter_count = 5;
dhd->pktfilter[0] = "100 0 0 0 "
HEX_PREF_STR UNI_FILTER_STR ZERO_ADDR_STR ETHER_TYPE_STR IPV6_FILTER_STR
" "
HEX_PREF_STR ZERO_ADDR_STR ZERO_ADDR_STR ETHER_TYPE_STR ZERO_TYPE_STR;
+ dhd->pktfilter[4] = "104 0 0 0 0xFFFFFF 0x01005E";
+ /* customer want to get IPV4 multicast packets */
#else
#error Customer want to filter out all IPV6 packets
dhd->pktfilter[0] = "100 0 0 0 0x01 0x00";
@@ -3761,7 +3788,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
bcm_mkiovar("vlan_mode", (char *)&vlanmode, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
#endif /* VLAN_MODE_OFF */
-#ifdef CUSTOMER_SET_COUNTRY
+#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE
if (dhd_customer_set_country(dhd) < 0)
DHD_ERROR(("%s: can't set country \n", __FUNCTION__));
#endif
@@ -3928,13 +3955,16 @@ static int dhd_device_event(struct notifier_block *this,
}
#ifdef AOE_IP_ALIAS_SUPPORT
- if (ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a) {
- DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n",
- __FUNCTION__));
- aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
+ if ((dhd_pub->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) {
+ if (ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a) {
+ /* 0x3a = ':' */
+ DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n",
+ __FUNCTION__));
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
+ }
+ else
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
}
- else
- aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
#endif
break;
@@ -3943,13 +3973,16 @@ static int dhd_device_event(struct notifier_block *this,
__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
dhd->pend_ipaddr = 0;
#ifdef AOE_IP_ALIAS_SUPPORT
- if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) {
- DHD_ARPOE(("%s: primary interface is down, AOE clr all\n",
+ if ((dhd_pub->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) {
+ if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) {
+ /* 0x3a = ':' */
+ DHD_ARPOE(("%s: primary interface is down, AOE clr all\n",
__FUNCTION__));
- dhd_aoe_hostip_clr(&dhd->pub);
- dhd_aoe_arp_clr(&dhd->pub);
- } else
- aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE);
+ dhd_aoe_hostip_clr(&dhd->pub);
+ dhd_aoe_arp_clr(&dhd->pub);
+ } else
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE);
+ }
#else
dhd_aoe_hostip_clr(&dhd->pub);
dhd_aoe_arp_clr(&dhd->pub);
@@ -3965,7 +3998,6 @@ static int dhd_device_event(struct notifier_block *this,
return NOTIFY_DONE;
}
#endif /* ARP_OFFLOAD_SUPPORT */
-
int
dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
{
@@ -4005,6 +4037,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
#else
net->netdev_ops = &dhd_ops_pri;
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
+ memcpy(temp_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN);
} else {
/*
* We have to use the primary MAC for virtual interfaces
@@ -4249,6 +4282,9 @@ void dhd_detach(dhd_pub_t *dhdp)
dhd->wakelock_timeout_enable = 0;
wake_lock_destroy(&dhd->wl_wifi);
wake_lock_destroy(&dhd->wl_rxwake);
+#ifdef PNO_SUPPORT
+ wake_lock_destroy(&dhdp->pno_wakelock);
+#endif
#endif
}
}
@@ -4336,8 +4372,10 @@ dhd_module_init(void)
dhd_bus_reg_sdio_notify(&dhd_chipup_sem);
dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON);
#if defined(CONFIG_WIFI_CONTROL_FUNC)
- if (wl_android_wifictrl_func_add() < 0)
+ if (wl_android_wifictrl_func_add() < 0) {
+ dhd_bus_unreg_sdio_notify();
goto fail_1;
+ }
#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */
if (down_timeout(&dhd_chipup_sem,
msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) {
@@ -4372,7 +4410,7 @@ dhd_module_init(void)
error = dhd_bus_register();
if (!error)
- printf("\n%s\n", dhd_version);
+ DHD_TRACE(("%s: \n%s\n", __FUNCTION__, dhd_version));
else {
DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__));
goto fail_1;
@@ -4538,6 +4576,7 @@ dhd_os_wd_timer(void *bus, uint wdtick)
if (!wdtick && dhd->wd_timer_valid == TRUE) {
dhd->wd_timer_valid = FALSE;
dhd_os_spin_unlock(pub, flags);
+ if (dhd)
#ifdef DHDTHREAD
del_timer_sync(&dhd->timer);
#else
@@ -4743,7 +4782,7 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
ASSERT(dhd->iflist[*ifidx] != NULL);
ASSERT(dhd->iflist[*ifidx]->net != NULL);
- if (dhd->iflist[*ifidx]->net) {
+ if (dhd->iflist[*ifidx]->event2cfg80211 && dhd->iflist[*ifidx]->net) {
wl_cfg80211_event(dhd->iflist[*ifidx]->net, event, *data);
}
#endif /* defined(WL_CFG80211) */
@@ -5053,9 +5092,12 @@ int net_os_send_hang_message(struct net_device *dev)
#endif
#if defined(WL_CFG80211)
ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
- //dev_close(dev);
- //dev_open(dev);
+#if !defined(CUSTOMER_HW_SAMSUNG)
+#error do not use these it cause kernel panic
+ dev_close(dev);
+ dev_open(dev);
#endif
+#endif /* WL_CFG80211 */
}
}
return ret;
@@ -5210,6 +5252,21 @@ int net_os_wake_lock_timeout(struct net_device *dev)
ret = dhd_os_wake_lock_timeout(&dhd->pub);
return ret;
}
+#if defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK)
+int net_os_wake_lock_timeout_for_pno(struct net_device *dev, int sec)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+ unsigned long flags;
+
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ wake_lock_timeout(&dhd->pub.pno_wakelock, HZ * sec);
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
+}
+#endif
int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub, int val)
{
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_proto.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_proto.h
index b597cc6fd23..8cc2542cf34 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_proto.h
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_proto.h
@@ -34,7 +34,7 @@
#include <wlioctl.h>
#ifndef IOCTL_RESP_TIMEOUT
-#define IOCTL_RESP_TIMEOUT 20000 /* In milli second */
+#define IOCTL_RESP_TIMEOUT 5000 /* In milli second */
#endif /* IOCTL_RESP_TIMEOUT */
/*
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c
index 8d89377716d..25cbc700c49 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c
@@ -145,6 +145,10 @@ extern void bcmsdh_set_irq(int flag);
extern void dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success);
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+DEFINE_MUTEX(_dhd_sdio_mutex_lock_);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
+
#ifdef DHD_DEBUG
/* Device console log buffer state */
#define CONSOLE_LINE_MAX 192
@@ -337,6 +341,7 @@ typedef struct dhd_bus {
bool _slpauto;
bool _oobwakeup;
bool _srenab;
+ bool readframes;
} dhd_bus_t;
/* clkstate */
@@ -420,7 +425,7 @@ static bool dhd_readahead;
/* To check if there's window offered */
#define DATAOK(bus) \
- (((uint8)(bus->tx_max - bus->tx_seq) > 2) && \
+ (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
/* To check if there's window offered for ctrl frame */
@@ -599,6 +604,7 @@ dhdsdio_oobwakeup_init(dhd_bus_t *bus)
}
#endif /* USE_OOB_GPIO1 */
+#ifdef BCM4334_CHIP
/*
* Query if FW is in SR mode
*/
@@ -650,7 +656,6 @@ dhdsdio_sr_init(dhd_bus_t *bus)
if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2))
dhdsdio_srwar_init(bus);
- bus->srmemsize = si_socram_srmem_size(bus->sih);
val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
@@ -671,6 +676,7 @@ dhdsdio_sr_init(dhd_bus_t *bus)
return 0;
}
+#endif /* BCM4334_CHIP */
/*
* FIX: Be sure KSO bit is enabled
@@ -1171,7 +1177,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
ret = dhdsdio_htclk(bus, TRUE, pendok);
if (ret == BCME_OK) {
dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
- bus->activity = TRUE;
+ bus->activity = TRUE;
#ifdef DHD_USE_IDLECOUNT
bus->dhd_idlecount = 0;
#endif /* DHD_USE_IDLECOUNT */
@@ -1230,7 +1236,7 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
/* Going to sleep: set the alarm and turn off the lights... */
if (sleep) {
/* Don't sleep if something is pending */
- if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
+ if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq) || bus->readframes)
return BCME_BUSY;
@@ -1859,7 +1865,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__));
} else if (ret < 0) {
/* On failure, abort the command and terminate the frame */
- DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
+ DHD_ERROR(("%s: sdio error %d, abort command and terminate frame.\n",
__FUNCTION__, ret));
bus->tx_sderrs++;
@@ -1930,13 +1936,21 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
__FUNCTION__, rxlen, msglen));
} else if (timeleft == 0) {
- DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
+ u32 status;
+ int retry = 0;
+ R_SDREG(status, &bus->regs->intstatus, retry);
+ DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n", __FUNCTION__, status));
#ifdef DHD_DEBUG
+#if !defined(CUSTOMER_HW_SAMSUNG)
+#error need debug message if dongle trap occured
if (!SLPAUTO_ENAB(bus)) {
+#endif
dhd_os_sdlock(bus->dhd);
dhdsdio_checkdied(bus, NULL, 0);
dhd_os_sdunlock(bus->dhd);
+#if !defined(CUSTOMER_HW_SAMSUNG)
}
+#endif
#endif /* DHD_DEBUG */
} else if (pending == TRUE) {
DHD_CTL(("%s: canceled\n", __FUNCTION__));
@@ -1964,6 +1978,9 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
if (bus->dhd->rxcnt_timeout >= MAX_CNTL_TIMEOUT)
return -ETIMEDOUT;
+ if (bus->dhd->dongle_trap_occured)
+ return -EREMOTEIO;
+
return rxlen ? (int)rxlen : -EIO;
}
@@ -2303,26 +2320,36 @@ static int
dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
{
uint32 addr;
- int rv;
+ int rv, i;
uint32 shaddr = 0;
- shaddr = bus->ramsize - bus->srmemsize - 4;
- /* Read last word in memory to determine address of sdpcm_shared structure */
- if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
- return rv;
+ shaddr = bus->ramsize - 4;
+
+ i = 0;
+ do {
+ /* Read last word in memory to determine address of sdpcm_shared structure */
+ if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
+ return rv;
addr = ltoh32(addr);
DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
- /*
- * Check if addr is valid.
- * NVRAM length at the end of memory should have been overwritten.
- */
- if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
- DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n", __FUNCTION__, addr));
- return BCME_ERROR;
- }
+ /*
+ * Check if addr is valid.
+ * NVRAM length at the end of memory should have been overwritten.
+ */
+ if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
+ if ((bus->srmemsize > 0) && (i++ == 0)) {
+ shaddr -= bus->srmemsize;
+ } else {
+ DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
+ __FUNCTION__, addr));
+ return BCME_ERROR;
+ }
+ } else
+ break;
+ } while (i < 2);
/* Read hndrte_shared structure */
if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
@@ -2517,6 +2544,7 @@ dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size)
}
if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
+ bus->dhd->dongle_trap_occured = TRUE;
if ((bcmerror = dhdsdio_membytes(bus, FALSE,
sdpcm_shared.trap_addr,
(uint8*)&tr, sizeof(trap_t))) < 0)
@@ -3722,9 +3750,11 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
}
+#ifdef BCM4334_CHIP
if (dhdsdio_sr_cap(bus))
dhdsdio_sr_init(bus);
else
+#endif /* BCM4334_CHIP */
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
@@ -4365,8 +4395,10 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ bus->readframes = TRUE;
if (!KSO_ENAB(bus)) {
DHD_ERROR(("%s: KSO off\n", __FUNCTION__));
+ bus->readframes = FALSE;
return 0;
}
@@ -4934,6 +4966,7 @@ deliver:
if (bus->rxskip)
rxseq--;
bus->rx_seq = rxseq;
+ bus->readframes = FALSE;
return rxcount;
}
@@ -4990,6 +5023,8 @@ dhdsdio_hostmail(dhd_bus_t *bus)
#ifdef DHD_DEBUG
/* Retrieve console state address now that firmware should have updated it */
+ // Kent: tempoprary rollback - firmware should be modified for a correct dconpoll operation
+ // if(dhd_console_ms > 0)
{
sdpcm_shared_t shared;
if (dhdsdio_readshared(bus, &shared) == 0)
@@ -5221,6 +5256,22 @@ clkwait:
bcmsdh_intr_enable(sdh);
}
+#if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
+ /* In case of SW-OOB(using edge trigger),
+ * Check interrupt status in the dongle again after enable irq on the host.
+ * and rechedule dpc if interrupt is pended in the dongle.
+ * There is a chance to miss OOB interrupt while irq is disabled on the host.
+ * No need to do this with HW-OOB(level trigger)
+ */
+ R_SDREG(newstatus, &regs->intstatus, retries);
+ if (bcmsdh_regfail(bus->sdh))
+ newstatus = 0;
+ if (newstatus & bus->hostintmask) {
+ bus->ipend = TRUE;
+ resched = TRUE;
+ }
+#endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */
+
if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
int ret, i;
@@ -5745,10 +5796,9 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
if (bus->dhd_idlecount >= (DHD_IDLE_TIMEOUT_MS/dhd_watchdog_ms)) {
DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
- if (SLPAUTO_ENAB(bus)) {
- if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
- dhd_os_wd_timer(bus->dhd, 0);
- } else
+ if (SLPAUTO_ENAB(bus))
+ dhdsdio_bussleep(bus, TRUE);
+ else
dhdsdio_clkctl(bus, CLK_NONE, FALSE);
bus->dhd_idlecount = 0;
@@ -5904,6 +5954,17 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
struct ether_addr ea_addr;
#endif /* GET_CUSTOM_MAC_ENABLE */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+
+ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
+ DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
+ }
+ else {
+ DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
+ }
+ mutex_lock(&_dhd_sdio_mutex_lock_);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
+
/* Init global variables at run-time, not as part of the declaration.
* This is required to support init/de-init of the driver. Initialization
* of globals as part of the declaration results in non-deterministic
@@ -5940,7 +6001,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
default:
DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
__FUNCTION__, venid));
- return NULL;
+ goto forcereturn;
}
/* Check the Device ID and make sure it's one that we support */
@@ -5974,14 +6035,14 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
default:
DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
__FUNCTION__, venid, devid));
- return NULL;
+ goto forcereturn;
}
if (osh == NULL) {
/* Ask the OS interface part for an OSL handle */
if (!(osh = dhd_osl_attach(sdh, DHD_BUS))) {
DHD_ERROR(("%s: osl_attach failed!\n", __FUNCTION__));
- return NULL;
+ goto forcereturn;
}
}
@@ -6062,10 +6123,22 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
goto fail;
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_unlock(&_dhd_sdio_mutex_lock_);
+ DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+
return bus;
fail:
dhdsdio_release(bus, osh);
+
+forcereturn:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_unlock(&_dhd_sdio_mutex_lock_);
+ DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+
return NULL;
}
@@ -6213,6 +6286,8 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
bus->ramsize, bus->orig_ramsize));
+
+ bus->srmemsize = si_socram_srmem_size(bus->sih);
}
/* ...but normally deal with the SDPCMDEV core */
@@ -6406,13 +6481,16 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
if (bus) {
ASSERT(osh);
+ if (bus->dhd) {
+ dongle_isolation = bus->dhd->dongle_isolation;
+ dhd_detach(bus->dhd);
+ }
+
/* De-register interrupt handler */
bcmsdh_intr_disable(bus->sdh);
bcmsdh_intr_dereg(bus->sdh);
if (bus->dhd) {
- dongle_isolation = bus->dhd->dongle_isolation;
- dhd_detach(bus->dhd);
dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
dhd_free(bus->dhd);
bus->dhd = NULL;
@@ -6499,6 +6577,17 @@ dhdsdio_disconnect(void *ptr)
{
dhd_bus_t *bus = (dhd_bus_t *)ptr;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+
+ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
+ DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
+ }
+ else {
+ DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
+ }
+ mutex_lock(&_dhd_sdio_mutex_lock_);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
+
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
if (bus) {
@@ -6507,6 +6596,12 @@ dhdsdio_disconnect(void *ptr)
}
DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
+ mutex_unlock(&_dhd_sdio_mutex_lock_);
+ DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
+
}
diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h
index 5ead9f32efd..41f6e2c8a53 100644
--- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h
+++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h
@@ -1,4 +1,33 @@
-#ifdef USE_SECFEATURE
+/*
+ * Header file describing the internal (inter-module) DHD interfaces.
+ *
+ * Provides type definitions and function prototypes used to link the
+ * DHD OS, bus, and protocol modules.
+ *
+ * Copyright (C) 1999-2012, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: dhd_sec_feature.h 309548 2012-01-20 01:13:08Z $
+ */
+
+#ifdef USE_SECFEATURE
#include <sec_feature/GlobalConfig.h>
#include <sec_feature/CustFeature.h>
#endif
@@ -12,9 +41,8 @@
#define HW_OOB
#endif
-#ifdef CONFIG_MACH_U1
+#ifdef CONFIG_MACH_U1 /* Q1 also uses this feature */
#define USE_CID_CHECK
-#define U1_MACADDR
#define WRITE_MACADDR
#endif
@@ -23,6 +51,13 @@
#define WRITE_MACADDR
#endif
+/* Temporary roaming undef of D2_ATT models for the ATT hotspot connection problem */
+#if defined (CONFIG_MACH_M2_ATT)
+#undef ROAM_ENABLE
+#undef ROAM_CHANNEL_CACHE
+#undef ROAM_API
+#endif
+
/* REGION CODE */
#if (WLAN_REGION_CODE >= 100) && (WLAN_REGION_CODE < 200) /*EUR*/
@@ -33,7 +68,7 @@
#endif
#if (WLAN_REGION_CODE >= 200) && (WLAN_REGION_CODE < 300) /* KOR */
-#undef USE_INITIAL_2G_SCAN
+#undef USE_INITIAL_2G_SCAN_ORG
#ifndef ROAM_ENABLE
#define ROAM_ENABLE
#endif
diff --git a/drivers/net/wireless/bcmdhd/src/include/epivers.h b/drivers/net/wireless/bcmdhd/src/include/epivers.h
index c6354cfc551..058f1d458f8 100644
--- a/drivers/net/wireless/bcmdhd/src/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/src/include/epivers.h
@@ -30,19 +30,19 @@
#define EPI_MINOR_VERSION 15
-#define EPI_RC_NUMBER 2
+#define EPI_RC_NUMBER 11
#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 1, 15, 2, 0
+#define EPI_VERSION 1, 15, 11, 0
-#define EPI_VERSION_NUM 0x010f0200
+#define EPI_VERSION_NUM 0x010f0900
-#define EPI_VERSION_DEV 1.15.2
+#define EPI_VERSION_DEV 1.15.11
-#define EPI_VERSION_STR "1.15.2"
+#define EPI_VERSION_STR "1.15.11"
#endif /* _epivers_h_ */
diff --git a/drivers/net/wireless/bcmdhd/src/include/linuxver.h b/drivers/net/wireless/bcmdhd/src/include/linuxver.h
index 1a5d27b9f8d..40830d922f8 100644
--- a/drivers/net/wireless/bcmdhd/src/include/linuxver.h
+++ b/drivers/net/wireless/bcmdhd/src/include/linuxver.h
@@ -500,6 +500,7 @@ typedef struct {
(tsk_ctl)->parent = owner; \
(tsk_ctl)->terminated = FALSE; \
(tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \
+ DBG_THR(("%s thr:%lx created\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
if ((tsk_ctl)->thr_pid > 0) \
wait_for_completion(&((tsk_ctl)->completed)); \
DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
diff --git a/drivers/net/wireless/bcmdhd/src/include/proto/p2p.h b/drivers/net/wireless/bcmdhd/src/include/proto/p2p.h
index d3e138b154f..0c974c7c0a4 100644
--- a/drivers/net/wireless/bcmdhd/src/include/proto/p2p.h
+++ b/drivers/net/wireless/bcmdhd/src/include/proto/p2p.h
@@ -85,7 +85,7 @@ typedef struct wifi_p2p_ie wifi_p2p_ie_t;
#define P2P_SEID_INVITE_FLAGS 18
#define P2P_SEID_VNDR 221 /* Vendor-specific subelement */
-#define P2P_SE_VS_ID_SERVICES 0x1b /* BRCM proprietary subel: L2 Services */
+#define P2P_SE_VS_ID_SERVICES 0x1b /* BRCM subel: L2 Services */
/* WiFi P2P IE subelement: P2P Capability (capabilities info) */
diff --git a/drivers/net/wireless/bcmdhd/src/include/wlioctl.h b/drivers/net/wireless/bcmdhd/src/include/wlioctl.h
index c6b9eb4604f..72a54ce7db8 100644
--- a/drivers/net/wireless/bcmdhd/src/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/src/include/wlioctl.h
@@ -1674,7 +1674,12 @@ typedef struct {
/* WLC_GET_AUTH, WLC_SET_AUTH values */
#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
-#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */
+#ifdef BCM4330_CHIP
+#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */
+#else
+/* BCM4334(Phoenex branch) value changed to 3 */
+#define WL_AUTH_OPEN_SHARED 3 /* try open, then shared if open failed w/rc 13 */
+#endif
/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
#define WL_RADIO_SW_DISABLE (1<<0)
diff --git a/drivers/net/wireless/bcmdhd/src/shared/siutils.c b/drivers/net/wireless/bcmdhd/src/shared/siutils.c
index b6dbda9e451..0c8a9fe3df8 100644
--- a/drivers/net/wireless/bcmdhd/src/shared/siutils.c
+++ b/drivers/net/wireless/bcmdhd/src/shared/siutils.c
@@ -1934,6 +1934,11 @@ si_socram_srmem_size(si_t *sih)
uint32 coreinfo;
uint memsize = 0;
+ if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) {
+ return (32 * 1024);
+ }
+
+
sii = SI_INFO(sih);
/* Block ints and save current core */
diff --git a/drivers/net/wireless/bcmdhd/src/wl/bcmwifi/include/bcmwifi_channels.h b/drivers/net/wireless/bcmdhd/src/wl/bcmwifi/include/bcmwifi_channels.h
index 4491348f291..a62c16d153c 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/bcmwifi/include/bcmwifi_channels.h
+++ b/drivers/net/wireless/bcmdhd/src/wl/bcmwifi/include/bcmwifi_channels.h
@@ -65,7 +65,7 @@ typedef uint16 chanspec_t;
#define WL_CHANSPEC_BAND_SHIFT 12
#define WL_CHANSPEC_BAND_5G 0x1000
#define WL_CHANSPEC_BAND_2G 0x2000
-#define INVCHANSPEC (-1)
+#define INVCHANSPEC 255
#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0)
@@ -162,7 +162,7 @@ typedef uint16 chanspec_t;
#define WL_CHANSPEC_BAND_3G 0x4000
#define WL_CHANSPEC_BAND_4G 0x8000
#define WL_CHANSPEC_BAND_5G 0xc000
-#define INVCHANSPEC (-1)
+#define INVCHANSPEC 255
#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \
((channel) - CH_10MHZ_APART) : 0)
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c
index 0238a63b060..916509d5cb4 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c
@@ -73,13 +73,23 @@
#define CMD_GETBAND "GETBAND"
#define CMD_COUNTRY "COUNTRY"
#define CMD_P2P_SET_NOA "P2P_SET_NOA"
+#define CMD_P2P_GET_NOA "P2P_GET_NOA"
#define CMD_P2P_SET_PS "P2P_SET_PS"
#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE"
/* Hostapd private command */
+#define CMD_SET_HAPD_AUTO_CHANNEL "HAPD_AUTO_CHANNEL"
#define CMD_SET_HAPD_MAX_NUM_STA "HAPD_MAX_NUM_STA"
#define CMD_SET_HAPD_SSID "HAPD_SSID"
#define CMD_SET_HAPD_HIDE_SSID "HAPD_HIDE_SSID"
+#define CMD_HAPD_STA_DISASSOC "HAPD_STA_DISASSOC"
+
+/* CCX Private Commands */
+#ifdef BCMCCX
+#define CMD_GETCCKM_RN "get cckm_rn"
+#define CMD_SETCCKM_KRK "set cckm_krk"
+#define CMD_GET_ASSOC_RES_IES "get assoc_res_ies"
+#endif
#ifdef PNO_SUPPORT
#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR"
@@ -118,7 +128,11 @@ typedef struct cmd_tlv {
#ifdef OKC_SUPPORT
#define CMD_OKC_SET_PMK "SET_PMK"
#define CMD_OKC_ENABLE "OKC_ENABLE"
-#endif
+#endif /* OKC_SUPPORT */
+
+#ifdef CUSTOMER_HW_SAMSUNG
+#define CMD_AMPDU_MPDU "AMPDU_MPDU"
+#endif /* CUSTOMER_HW_SAMSUNG */
typedef struct android_wifi_priv_cmd {
char *buf;
@@ -214,6 +228,9 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int
int ret_now;
int ret = 0;
+#ifdef CUSTOMER_HW_SAMSUNG
+ if (!dhd_download_fw_on_driverload) {
+#endif /* CUSTOMER_HW_SAMSUNG */
suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0';
if (suspend_flag != 0)
@@ -227,6 +244,9 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int
else
DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
}
+#ifdef CUSTOMER_HW_SAMSUNG
+ }
+#endif /* CUSTOMER_HW_SAMSUNG */
return ret;
}
@@ -517,6 +537,90 @@ static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, i
return bytes_written;
}
+#ifdef BCMCCX
+static int wl_android_get_cckm_rn(struct net_device *dev, char *command)
+{
+ int error, rn;
+
+ WL_TRACE(("%s:wl_android_get_cckm_rn\n", dev->name));
+
+ error = wldev_iovar_getint(dev, "cckm_rn", &rn);
+ if (unlikely(error)) {
+ WL_ERR(("wl_android_get_cckm_rn error (%d)\n", error));
+ return -1;
+ }
+ //WL_ERR(("wl_android_get_cckm_rn = %d\n", rn));
+ memcpy(command, &rn, sizeof(int));
+
+ return sizeof(int);
+}
+
+static int wl_android_set_cckm_krk(struct net_device *dev, char *command)
+{
+ int error;
+ unsigned char key[16];
+
+ static char iovar_buf[WLC_IOCTL_MEDLEN];
+
+ WL_TRACE(("%s: wl_iw_set_cckm_krk\n", dev->name));
+
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ memcpy(key, command+strlen("set cckm_krk")+1, 16);
+
+ error = wldev_iovar_setbuf(dev, "cckm_krk",key, sizeof(key), iovar_buf, WLC_IOCTL_MEDLEN,NULL);
+ if (unlikely(error))
+ {
+ WL_ERR((" cckm_krk set error (%d)\n", error));
+ return -1;
+ }
+ return 0;
+}
+
+static int wl_android_get_assoc_res_ies(struct net_device *dev, char *command)
+{
+ int error;
+ u8 buf[WL_ASSOC_INFO_MAX];
+ wl_assoc_info_t assoc_info;
+ u32 resp_ies_len = 0;
+ int bytes_written = 0;
+
+ WL_TRACE(("%s: wl_iw_get_assoc_res_ies\n", dev->name));
+
+ error = wldev_iovar_getbuf(dev, "assoc_info", NULL, 0, buf,WL_ASSOC_INFO_MAX, NULL);
+ if (unlikely(error)) {
+ WL_ERR(("could not get assoc info (%d)\n", error));
+ return -1;
+ }
+
+ memcpy(&assoc_info, buf, sizeof(wl_assoc_info_t));
+ assoc_info.req_len = htod32(assoc_info.req_len);
+ assoc_info.resp_len = htod32(assoc_info.resp_len);
+ assoc_info.flags = htod32(assoc_info.flags);
+
+ if (assoc_info.resp_len) {
+ resp_ies_len = assoc_info.resp_len - sizeof(struct dot11_assoc_resp);
+ }
+
+ /* first 4 bytes are ie len */
+ memcpy(command, &resp_ies_len, sizeof(u32));
+ bytes_written= sizeof(u32);
+
+ /* get the association resp IE's if there are any */
+ if (resp_ies_len) {
+ error = wldev_iovar_getbuf(dev, "assoc_resp_ies", NULL, 0, buf,WL_ASSOC_INFO_MAX, NULL);
+ if (unlikely(error)) {
+ WL_ERR(("could not get assoc resp_ies (%d)\n", error));
+ return -1;
+ }
+
+ memcpy(command+sizeof(u32), buf, resp_ies_len);
+ bytes_written += resp_ies_len;
+ }
+ return bytes_written;
+}
+
+#endif /* BCMCCX */
+
/**
* Global function definitions (declared in wl_android.h)
*/
@@ -537,7 +641,7 @@ int wl_android_wifi_on(struct net_device *dev)
do {
dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
if (dhd_download_fw_on_driverload)
- msleep(100);
+ msleep(300);
ret = sdioh_start(NULL, 0);
if (ret == 0)
@@ -617,7 +721,74 @@ static int my_atoi(const char *string_num)
return int_val;
}
-static int wl_android_set_max_num_sta(struct net_device *dev, const char* string_num)
+static int
+wl_android_set_auto_channel(struct net_device *dev, const char* string_num,
+ char* command, int total_len)
+{
+ int channel;
+ int chosen = 0;
+ int retry = 0;
+ int ret = 0;
+
+ /* Restrict channel to 1 - 7: 2GHz, 20MHz BW, No SB */
+ u32 req_buf[8] = {7, 0x2B01, 0x2B02, 0x2B03, 0x2B04, 0x2B05, 0x2B06,
+ 0x2B07};
+
+ /* Auto channel select */
+ wl_uint32_list_t request;
+
+ channel = my_atoi(string_num);
+ DHD_INFO(("%s : HAPD_AUTO_CHANNEL = %d\n", __FUNCTION__, channel));
+
+ if (channel == 20)
+ ret = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, (void *)&req_buf,
+ sizeof(req_buf), true);
+ else { /* channel == 0 */
+ request.count = htod32(0);
+ ret = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, (void *)&request,
+ sizeof(request), true);
+ }
+
+ if (ret < 0) {
+ DHD_ERROR(("%s: can't start auto channel scan, err = %d\n",
+ __FUNCTION__, ret));
+ channel = 0;
+ goto done;
+ }
+
+ /* Wait for auto channel selection, max 2500 ms */
+ bcm_mdelay(500);
+
+ retry = 10;
+ while(retry--) {
+ ret = wldev_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
+ false);
+ if (ret < 0 || dtoh32(chosen) == 0) {
+ DHD_INFO(("%s: %d tried, ret = %d, chosen = %d\n",
+ __FUNCTION__, (10 - retry), ret, chosen));
+ bcm_mdelay(200);
+ }
+ else {
+ channel = (u16)chosen & 0x00FF;
+ DHD_ERROR(("%s: selected channel = %d\n", __FUNCTION__, channel));
+ break;
+ }
+ }
+
+ if (retry == 0) {
+ DHD_ERROR(("%s: auto channel timed out, failed\n", __FUNCTION__));
+ channel = 0;
+ }
+
+done:
+ snprintf(command, total_len, "%d", channel);
+ DHD_INFO(("%s: command result is %s\n", __FUNCTION__, command));
+
+ return 1;
+}
+
+static int
+wl_android_set_max_num_sta(struct net_device *dev, const char* string_num)
{
int max_assoc;
@@ -627,19 +798,25 @@ static int wl_android_set_max_num_sta(struct net_device *dev, const char* string
return 1;
}
-static int wl_android_set_ssid (struct net_device *dev, const char* hapd_ssid)
+static int
+wl_android_set_ssid (struct net_device *dev, const char* hapd_ssid)
{
wlc_ssid_t ssid;
+ s32 ret;
ssid.SSID_len = strlen(hapd_ssid);
bcm_strncpy_s(ssid.SSID, sizeof(ssid.SSID), hapd_ssid, ssid.SSID_len);
DHD_INFO(("%s: HAPD_SSID = %s\n", __FUNCTION__, ssid.SSID));
- wldev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t), true);
+ ret = wldev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t), true);
+ if (ret < 0) {
+ DHD_ERROR(("%s : WLC_SET_SSID Error:%d\n", __FUNCTION__, ret));
+ }
return 1;
}
-static int wl_android_set_hide_ssid(struct net_device *dev, const char* string_num)
+static int
+wl_android_set_hide_ssid(struct net_device *dev, const char* string_num)
{
int hide_ssid;
int enable = 0;
@@ -652,6 +829,30 @@ static int wl_android_set_hide_ssid(struct net_device *dev, const char* string_n
return 1;
}
+static int
+wl_android_sta_diassoc(struct net_device *dev, const char* straddr)
+{
+ scb_val_t scbval;
+ s32 ret;
+
+ DHD_INFO(("%s: deauth STA %s\n", __FUNCTION__, straddr));
+
+ /* Unspecified reason */
+ scbval.val = htod32(1);
+ bcm_ether_atoe(straddr, &scbval.ea);
+
+ DHD_INFO(("%s: deauth STA: %02X:%02X:%02X:%02X:%02X:%02X\n", __FUNCTION__,
+ scbval.ea.octet[0], scbval.ea.octet[1], scbval.ea.octet[2],
+ scbval.ea.octet[3], scbval.ea.octet[4], scbval.ea.octet[5]));
+
+ if ((ret = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
+ sizeof(scb_val_t), true)) < 0) {
+ DHD_ERROR(("%s : WLC_SCB_DEAUTHENTICATE_FOR_REASON error:%d\n", __FUNCTION__ , ret));
+ }
+
+ return 1;
+}
+
#ifdef OKC_SUPPORT
static int
@@ -698,6 +899,31 @@ wl_android_okc_enable(struct net_device *dev, char *command, int total_len)
#endif /* OKC_ SUPPORT */
+#ifdef CUSTOMER_HW_SAMSUNG
+/* CMD_AMPDU_MPDU */
+static int
+wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num)
+{
+ int err = 0;
+ int ampdu_mpdu;
+
+ ampdu_mpdu = bcm_atoi(string_num);
+
+ if (ampdu_mpdu > 32) {
+ DHD_ERROR(("%s : ampdu_mpdu MAX value is 32.\n", __FUNCTION__));
+ return -1;
+ }
+
+ DHD_ERROR(("%s : ampdu_mpdu = %d\n", __FUNCTION__, ampdu_mpdu));
+ err = wldev_iovar_setint(dev, "ampdu_mpdu", ampdu_mpdu);
+ if (err < 0) {
+ DHD_ERROR(("%s : ampdu_mpdu set error. %d\n", __FUNCTION__, err));
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* CUSTOMER_HW_SAMSUNG*/
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
{
@@ -810,46 +1036,48 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
}
-#ifndef CUSTOMER_SET_COUNTRY /*CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
+#ifndef GLOBALCONFIG_WLAN_COUNTRY_CODE
else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
char *country_code = command + strlen(CMD_COUNTRY) + 1;
bytes_written = wldev_set_country(net, country_code);
+ wl_update_wiphybands(NULL);
}
#endif
#ifdef ROAM_API
else if (strnicmp(command, CMD_ROAMTRIGGER_SET,
- strlen(CMD_ROAMTRIGGER_SET)) == 0) {
+ strlen(CMD_ROAMTRIGGER_SET)) == 0) {
bytes_written = wl_android_set_roam_trigger(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
} else if (strnicmp(command, CMD_ROAMTRIGGER_GET,
- strlen(CMD_ROAMTRIGGER_GET)) == 0) {
+ strlen(CMD_ROAMTRIGGER_GET)) == 0) {
bytes_written = wl_android_get_roam_trigger(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
} else if (strnicmp(command, CMD_ROAMDELTA_SET,
- strlen(CMD_ROAMDELTA_SET)) == 0) {
+ strlen(CMD_ROAMDELTA_SET)) == 0) {
bytes_written = wl_android_set_roam_delta(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
} else if (strnicmp(command, CMD_ROAMDELTA_GET,
- strlen(CMD_ROAMDELTA_GET)) == 0) {
+ strlen(CMD_ROAMDELTA_GET)) == 0) {
bytes_written = wl_android_get_roam_delta(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
} else if (strnicmp(command, CMD_ROAMSCANPERIOD_SET,
- strlen(CMD_ROAMSCANPERIOD_SET)) == 0) {
+ strlen(CMD_ROAMSCANPERIOD_SET)) == 0) {
bytes_written = wl_android_set_roam_scan_period(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
} else if (strnicmp(command, CMD_ROAMSCANPERIOD_GET,
- strlen(CMD_ROAMSCANPERIOD_GET)) == 0) {
+ strlen(CMD_ROAMSCANPERIOD_GET)) == 0) {
bytes_written = wl_android_get_roam_scan_period(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
} else if (strnicmp(command, CMD_COUNTRYREV_SET,
- strlen(CMD_COUNTRYREV_SET)) == 0) {
+ strlen(CMD_COUNTRYREV_SET)) == 0) {
bytes_written = wl_android_set_country_rev(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
+ wl_update_wiphybands(NULL);
} else if (strnicmp(command, CMD_COUNTRYREV_GET,
- strlen(CMD_COUNTRYREV_GET)) == 0) {
+ strlen(CMD_COUNTRYREV_GET)) == 0) {
bytes_written = wl_android_get_country_rev(net, command,
- priv_cmd.total_len);
+ priv_cmd.total_len);
}
#endif /* ROAM_API */
#ifdef PNO_SUPPORT
@@ -872,6 +1100,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
priv_cmd.total_len - skip);
}
+ else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
+ bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
+ }
else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
int skip = strlen(CMD_P2P_SET_PS) + 1;
bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
@@ -885,27 +1116,60 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
priv_cmd.total_len - skip, *(command + skip - 2) - '0');
}
#endif /* WL_CFG80211 */
- else if (strnicmp(command, CMD_SET_HAPD_MAX_NUM_STA, strlen(CMD_SET_HAPD_MAX_NUM_STA)) == 0) {
+ else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL,
+ strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) {
+ int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 3;
+ wl_android_set_auto_channel(net, (const char*)command+skip, command,
+ priv_cmd.total_len);
+ }
+ else if (strnicmp(command, CMD_SET_HAPD_MAX_NUM_STA,
+ strlen(CMD_SET_HAPD_MAX_NUM_STA)) == 0) {
int skip = strlen(CMD_SET_HAPD_MAX_NUM_STA) + 3;
wl_android_set_max_num_sta(net, (const char*)command+skip);
}
- else if (strnicmp(command, CMD_SET_HAPD_SSID, strlen(CMD_SET_HAPD_SSID)) == 0) {
+ else if (strnicmp(command, CMD_SET_HAPD_SSID,
+ strlen(CMD_SET_HAPD_SSID)) == 0) {
int skip = strlen(CMD_SET_HAPD_SSID) + 3;
wl_android_set_ssid(net, (const char*)command+skip);
}
- else if (strnicmp(command, CMD_SET_HAPD_HIDE_SSID, strlen(CMD_SET_HAPD_HIDE_SSID)) == 0) {
+ else if (strnicmp(command, CMD_SET_HAPD_HIDE_SSID,
+ strlen(CMD_SET_HAPD_HIDE_SSID)) == 0) {
int skip = strlen(CMD_SET_HAPD_HIDE_SSID) + 3;
wl_android_set_hide_ssid(net, (const char*)command+skip);
}
+ else if (strnicmp(command, CMD_HAPD_STA_DISASSOC,
+ strlen(CMD_HAPD_STA_DISASSOC)) == 0) {
+ int skip = strlen(CMD_HAPD_STA_DISASSOC) + 1;
+ wl_android_sta_diassoc(net, (const char*)command+skip);
+ }
#ifdef OKC_SUPPORT
else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0)
bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len);
else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0)
bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len);
#endif /* OKC_SUPPORT */
-
+#ifdef BCMCCX
+ else if (strnicmp(command, CMD_GETCCKM_RN, strlen(CMD_GETCCKM_RN)) == 0) {
+ bytes_written = wl_android_get_cckm_rn(net, command);
+ }
+ else if (strnicmp(command, CMD_SETCCKM_KRK, strlen(CMD_SETCCKM_KRK)) == 0) {
+ bytes_written = wl_android_set_cckm_krk(net, command);
+ }
+ else if (strnicmp(command, CMD_GET_ASSOC_RES_IES, strlen(CMD_GET_ASSOC_RES_IES)) == 0) {
+ bytes_written = wl_android_get_assoc_res_ies(net, command);
+ }
+#endif /* BCMCCX */
+#ifdef CUSTOMER_HW_SAMSUNG
+ /* CMD_AMPDU_MPDU */
+ else if (strnicmp(command, CMD_AMPDU_MPDU,strlen(CMD_AMPDU_MPDU)) == 0) {
+ int skip = strlen(CMD_AMPDU_MPDU) + 1;
+ bytes_written = wl_android_set_ampdu_mpdu(net, (const char*)command+skip);
+ }
+#endif /* CUSTOMER_HW_SAMSUNG */
else {
- DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
+ if ((strnicmp(command, CMD_START, strlen(CMD_START)) != 0) &&
+ (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) != 0))
+ DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
snprintf(command, 3, "OK");
bytes_written = strlen("OK");
}
@@ -1116,7 +1380,7 @@ static int wifi_remove(struct platform_device *pdev)
DHD_ERROR(("## %s\n", __FUNCTION__));
wifi_control_data = wifi_ctrl;
- wifi_set_power(0, 0); /* Power Off */
+ wifi_set_power(0, 100); /* Power Off */
wifi_set_carddetect(0); /* CardDetect (1->0) */
up(&wifi_control_sem);
@@ -1126,37 +1390,20 @@ int dhd_os_check_wakelock(void *dhdp);
static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
{
- DHD_ERROR(("##> %s\n", __FUNCTION__));
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && 1
- if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
- bcmsdh_oob_intr_set(0);
+ bcmsdh_oob_intr_set(0);
#endif /* (OOB_INTR_ONLY) */
- if (dhd_os_check_if_up(bcmsdh_get_drvdata()) &&
- dhd_os_check_wakelock(bcmsdh_get_drvdata())) {
- DHD_ERROR(("%s no driver data\n", __FUNCTION__));
- return -EBUSY;
- }
-#if defined(OOB_INTR_ONLY)
- if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
- bcmsdh_oob_intr_set(0);
-#endif /* defined(OOB_INTR_ONLY) */
- smp_mb();
return 0;
}
static int wifi_resume(struct platform_device *pdev)
{
- DHD_ERROR(("##> %s\n", __FUNCTION__));
-
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && 1
if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
bcmsdh_oob_intr_set(1);
#endif /* (OOB_INTR_ONLY) */
-#if defined(OOB_INTR_ONLY)
- if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
- bcmsdh_oob_intr_set(1);
-#endif /* (OOB_INTR_ONLY) */
- smp_mb();
return 0;
}
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c
index db09ae139f6..1d6ba3a90ed 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c
@@ -117,6 +117,26 @@ u32 wl_dbg_level = WL_DBG_ERR;
#define WL_SCAN_ACTIVE_TIME 40 /* ms : Embedded default Active setting from DHD Driver */
#define WL_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD Driver */
+#ifdef VSDB
+/* ms : default wait time to keep STA's connecting or connection during continuous af tx */
+#define DEFAULT_SLEEP_TIME_VSDB 200
+#define WL_CHANNEL_SYNC_RETRY_VSDB 3
+
+/* if sta is connected or connecting, sleep for a while before retry for VSDB */
+#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl) \
+ do { \
+ if (wl_get_drv_status(wl, CONNECTED, wl_to_prmry_ndev(wl)) || \
+ wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) { \
+ msleep(DEFAULT_SLEEP_TIME_VSDB); \
+ } \
+ } while (0)
+#define WL_AF_TX_REDUCE_RETRY_VSDB(wl, max_retry)
+#else /* VSDB */
+/* if not VSDB, do nothing */
+#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl)
+#define WL_AF_TX_REDUCE_RETRY_VSDB(wl, max_retry)
+#endif /* VSDB */
+
#ifdef D11AC_IOTYPES
#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
#endif /* D11AC_IOTYPES */
@@ -144,16 +164,12 @@ static const struct ieee80211_regdomain brcm_regdom = {
/* IEEE 802.11b/g, channels 12..13. No HT40
* channel fits here.
*/
- REG_RULE(2467-10, 2472+10, 20, 6, 20,
- NL80211_RRF_PASSIVE_SCAN |
- NL80211_RRF_NO_IBSS),
+ REG_RULE(2467-10, 2472+10, 20, 6, 20, 0),
/* IEEE 802.11 channel 14 - Only JP enables
* this and for 802.11b only
*/
- REG_RULE(2484-10, 2484+10, 20, 6, 20,
- NL80211_RRF_PASSIVE_SCAN |
- NL80211_RRF_NO_IBSS |
- NL80211_RRF_NO_OFDM),
+ REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
+
/* IEEE 802.11a, channel 36..64 */
REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
/* IEEE 802.11a, channel 100..165 */
@@ -194,6 +210,9 @@ static const struct ieee80211_regdomain brcm_regdom = {
#define WPS_CONFIG_VIRT_DISPLAY 0x2008
#define WPS_CONFIG_PHY_DISPLAY 0x4008
+#define PM_BLOCK 1
+#define PM_ENABLE 0
+
#ifdef BCMCCX
#ifndef WLAN_AKM_SUITE_CCKM
#define WLAN_AKM_SUITE_CCKM 0x000FAC04
@@ -291,6 +310,8 @@ static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data);
static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data);
+static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
+ enum wl_status state, bool set);
/*
* register/deregister parent device
*/
@@ -390,7 +411,7 @@ static void wl_link_up(struct wl_priv *wl);
static void wl_link_down(struct wl_priv *wl);
static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
static void wl_init_conf(struct wl_conf *conf);
-static s32 wl_update_wiphybands(struct wl_priv *wl);
+
/*
* iscan handler
@@ -441,6 +462,7 @@ void reset_roam_cache(void);
void add_roam_cache(wl_bss_info_t *bi);
int get_roam_channel_list(int target_chan, chanspec_t *channels, const wlc_ssid_t *ssid);
void print_roam_cache(void);
+void set_roam_band(int band);
#endif
#define CHECK_SYS_UP(wlpriv) \
do { \
@@ -459,6 +481,7 @@ do { \
extern int dhd_wait_pend8021x(struct net_device *dev);
#ifdef PROP_TXSTATUS
+extern int disable_proptx;
extern int dhd_wlfc_init(dhd_pub_t *dhd);
extern void dhd_wlfc_deinit(dhd_pub_t *dhd);
#endif
@@ -759,13 +782,13 @@ wl_chspec_driver_to_host(chanspec_t chanspec)
}
#else /* not D11AC_IOTYPES */
-
+#ifndef ROAM_CHANNEL_CACHE
static chanspec_t
wl_chspec_host_to_driver(chanspec_t chanspec)
{
return htodchanspec(chanspec);
}
-
+#endif
static chanspec_t
wl_chspec_driver_to_host(chanspec_t chanspec)
{
@@ -947,7 +970,7 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
*(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
- sizeof(WL_EXTRA_BUF_MAX), false))) {
+ WL_EXTRA_BUF_MAX, false))) {
WL_ERR(("Failed to get associated bss info, use temp channel \n"));
chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN);
}
@@ -958,7 +981,7 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
}
return chspec;
-}
+ }
}
static struct net_device* wl_cfg80211_add_monitor_if(char *name)
@@ -979,15 +1002,26 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
s32 timeout = -1;
s32 wlif_type = -1;
s32 mode = 0;
- s32 up = 1;
+ s32 val = 0;
chanspec_t chspec;
struct wl_priv *wl = wiphy_priv(wiphy);
struct net_device *_ndev;
struct ether_addr primary_mac;
- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
int (*net_attach)(void *dhdp, int ifidx);
bool rollback_lock = false;
+#ifdef PROP_TXSTATUS
+ s32 up = 1;
+ dhd_pub_t *dhd;
+#endif /* PROP_TXSTATUS */
+
+ if (!wl)
+ return ERR_PTR(-EINVAL);
+
+#ifdef PROP_TXSTATUS
+ dhd = (dhd_pub_t *)(wl->pub);
+#endif /* PROP_TXSTATUS */
+
/* Use primary I/F for to send commands down */
_ndev = wl_to_prmry_ndev(wl);
@@ -1052,7 +1086,16 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
return ERR_PTR(-EAGAIN);
}
}
- if (!p2p_is_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
+
+ /* sanity check */
+#ifdef PROP_TXSTATUS
+ if (!dhd)
+ return ERR_PTR(-ENODEV);
+#endif
+ if (!wl->p2p || !wl->p2p->vir_ifname)
+ return ERR_PTR(-ENODEV);
+
+ if (!wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
p2p_on(wl) = true;
wl_cfgp2p_set_firm_p2p(wl);
wl_cfgp2p_init_discovery(wl);
@@ -1063,11 +1106,15 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
+ WL_SCAN2((" Scan Abort %p(id %d)\n", _ndev, wl->escan_info.cur_sync_id));
wl_cfg80211_scan_abort(wl, _ndev);
#ifdef PROP_TXSTATUS
- if (dhd->wlfc_enabled && !wl->wlfc_on) {
+ if (!wl->wlfc_on && !disable_proptx) {
+ dhd->wlfc_enabled = true;
dhd_wlfc_init(dhd);
- wldev_ioctl(_ndev, WLC_UP, &up, sizeof(s32), true);
+ err = wldev_ioctl(_ndev, WLC_UP, &up, sizeof(s32), true);
+ if (err < 0)
+ WL_ERR(("WLC_UP return err:%d\n", err));
wl->wlfc_on = true;
}
#endif
@@ -1082,6 +1129,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
* bss: "wl p2p_ifadd"
*/
wl_set_p2p_status(wl, IF_ADD);
+ if (wlif_type == WL_P2P_IF_GO)
+ wldev_iovar_setint(_ndev, "mpc", 0);
err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
if (unlikely(err)) {
@@ -1117,9 +1166,14 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
rollback_lock = true;
}
if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) {
- wl_alloc_netinfo(wl, _ndev, vwdev, mode);
+ wl_alloc_netinfo(wl, _ndev, vwdev, mode, PM_BLOCK);
WL_DBG((" virtual interface(%s) is "
"created net attach done\n", wl->p2p->vir_ifname));
+ val = 1;
+ /* Disable firmware roaming for P2P interface */
+ wldev_iovar_setint(_ndev, "roam_off", val);
+ if (mode == WL_MODE_AP)
+ wl_set_drv_status(wl, CONNECTED, _ndev);
} else {
/* put back the rtnl_lock again */
if (rollback_lock)
@@ -1137,14 +1191,17 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
wl->p2p->vif_created = false;
#ifdef PROP_TXSTATUS
- if (dhd->wlfc_enabled && wl->wlfc_on) {
- dhd_wlfc_deinit(dhd);
- wl->wlfc_on = false;
- }
+ if (dhd->wlfc_enabled && wl->wlfc_on) {
+ dhd->wlfc_enabled = false;
+ dhd_wlfc_deinit(dhd);
+ wl->wlfc_on = false;
+ }
#endif
}
}
fail:
+ if (wlif_type == WL_P2P_IF_GO)
+ wldev_iovar_setint(_ndev, "mpc", 1);
return ERR_PTR(-ENODEV);
}
@@ -1156,7 +1213,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
s32 timeout = -1;
s32 ret = 0;
WL_DBG(("Enter\n"));
-
+ WL_SCAN2(("Enter\n"));
if (wl->p2p_net == dev) {
/* Since there is no ifidx corresponding to p2p0,
* all commands should be routed through primary I/F
@@ -1171,7 +1228,28 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
wl_cfg80211_scan_abort(wl, dev);
}
wldev_iovar_setint(dev, "mpc", 1);
+
+ /* for GC */
+ if (wl_get_drv_status(wl, DISCONNECTING, dev) &&
+ (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) {
+ WL_ERR(("Wait for Link Down event for GC !\n"));
+ wait_for_completion_timeout(&wl->iface_disable, msecs_to_jiffies(500));
+ }
wl_set_p2p_status(wl, IF_DELETING);
+
+ /* for GO */
+ if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
+ /* disable interface before bsscfg free */
+ ret = wl_cfgp2p_ifdisable(wl, &p2p_mac);
+ /* if fw doesn't support "ifdis", do not wait for link down of ap mode */
+ if (ret == 0) {
+ WL_ERR(("Wait for Link Down event for GO !!!\n"));
+ wait_for_completion_timeout(&wl->iface_disable, msecs_to_jiffies(500));
+ } else {
+ msleep(300);
+ }
+ }
+ /* delete interface after link down */
ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
/* Firmware could not delete the interface so we will not get WLC_E_IF
* event for cleaning the dhd virtual nw interace
@@ -1199,6 +1277,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
ret = dhd_del_monitor(dev);
}
}
+ WL_SCAN2(("Exit\n"));
return ret;
}
@@ -1251,6 +1330,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
* channel. so retrieve the current channel of primary interface and
* then start the virtual interface on that.
*/
+ WL_SCAN2(("Scan Abort %p(id %d)\n", ndev, wl->escan_info.cur_sync_id));
wl_cfg80211_scan_abort(wl, ndev);
chspec = wl_cfg80211_get_shared_freq(wiphy);
@@ -1266,6 +1346,8 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
wl_set_mode_by_netdev(wl, ndev, mode);
wl_clr_p2p_status(wl, IF_CHANGING);
wl_clr_p2p_status(wl, IF_CHANGED);
+ if (mode == WL_MODE_AP)
+ wl_set_drv_status(wl, CONNECTED, ndev);
} else if (ndev == wl_to_prmry_ndev(wl) &&
!wl_get_drv_status(wl, AP_CREATED, ndev)) {
wl_set_drv_status(wl, AP_CREATING, ndev);
@@ -1317,9 +1399,12 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev)
{
struct wl_priv *wl = wlcfg_drv_priv;
bool rollback_lock = false;
- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
s32 index = 0;
- if (!ndev || !ndev->name) {
+#ifdef PROP_TXSTATUS
+ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
+#endif /* PROP_TXSTATUS */
+
+ if (!ndev || (strlen(ndev->name) == 0)) {
WL_ERR(("net is NULL\n"));
return 0;
}
@@ -1328,17 +1413,19 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev)
wl_get_p2p_status(wl, IF_DELETING)) {
if (wl->scan_request &&
(wl->escan_info.ndev == ndev)) {
- /* Abort any pending scan requests */
- wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
- if (!rtnl_is_locked()) {
- rtnl_lock();
+ /* Abort any pending scan requests */
+ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ if (!rtnl_is_locked()) {
+ rtnl_lock();
rollback_lock = true;
- }
+ }
WL_DBG(("ESCAN COMPLETED\n"));
+ WL_SCAN2(("Send Notify Complete %p(id %d)\n",
+ ndev, wl->escan_info.cur_sync_id));
wl_notify_escan_complete(wl, ndev, true);
- if (rollback_lock)
- rtnl_unlock();
- }
+ if (rollback_lock)
+ rtnl_unlock();
+ }
WL_ERR(("IF_DEL event called from dongle, net %x, vif name: %s\n",
(unsigned int)ndev, wl->p2p->vir_ifname));
@@ -1354,10 +1441,12 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev)
WL_DBG(("index : %d\n", index));
#ifdef PROP_TXSTATUS
if (dhd->wlfc_enabled && wl->wlfc_on) {
+ dhd->wlfc_enabled = false;
dhd_wlfc_deinit(dhd);
wl->wlfc_on = false;
}
#endif
+ wl_clr_drv_status(wl, CONNECTED, ndev);
}
/* Wake up any waiting thread */
wake_up_interruptible(&wl->netif_change_event);
@@ -1453,21 +1542,23 @@ static s32 wl_find_my_listen_channel(struct wl_priv *wl,
return 0;
}
-static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
+static void wl_scan_prep(struct wl_scan_params *params,
+ struct cfg80211_scan_request *request, int32 active_time)
{
u32 n_ssids;
u32 n_channels;
u16 channel;
chanspec_t chanspec;
- s32 i, offset;
+ s32 i = 0;
+ s32 offset;
char *ptr;
wlc_ssid_t ssid;
-
+ struct wl_priv *wl = wlcfg_drv_priv;
memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
params->bss_type = DOT11_BSSTYPE_ANY;
params->scan_type = 0;
params->nprobes = -1;
- params->active_time = -1;
+ params->active_time = active_time;
params->passive_time = -1;
params->home_time = -1;
params->channel_num = 0;
@@ -1488,6 +1579,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req
if (!request)
return;
+ /* TODO: validity check for null dereference is necessary. */
n_ssids = request->n_ssids;
n_channels = request->n_channels;
@@ -1496,34 +1588,36 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req
if (n_channels > 0) {
for (i = 0; i < n_channels; i++) {
chanspec = 0;
- channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
- if (request->channels[i]->band == IEEE80211_BAND_2GHZ)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
+ if (!request->channels[i] || !request->channels[i]->center_freq) {
+ break;
+ }
+ else {
+ channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
+ /* SKIP DFS channels for Secondary interface */
+ if ((wl->escan_info.ndev != wl_to_prmry_ndev(wl)) &&
+ (request->channels[i]->flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
+ continue;
+
+ if (request->channels[i]->band == IEEE80211_BAND_2GHZ)
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ else
+ chanspec |= WL_CHANSPEC_BAND_5G;
- if (request->channels[i]->flags & IEEE80211_CHAN_NO_HT40) {
chanspec |= WL_CHANSPEC_BW_20;
chanspec |= WL_CHANSPEC_CTL_SB_NONE;
- } else {
- chanspec |= WL_CHANSPEC_BW_40;
- if (request->channels[i]->flags & IEEE80211_CHAN_NO_HT40PLUS)
- chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
- else
- chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
- }
- params->channel_list[i] = channel;
- params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK;
- params->channel_list[i] |= chanspec;
- WL_SCAN(("Chan : %d, Channel spec: %x \n",
- channel, params->channel_list[i]));
- params->channel_list[i] = htod16(params->channel_list[i]);
+ params->channel_list[i] = channel;
+ params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK;
+ params->channel_list[i] |= chanspec;
+ WL_SCAN(("Chan : %d, Channel spec: %x \n",
+ channel, params->channel_list[i]));
+ params->channel_list[i] = htod16(params->channel_list[i]);
+ }
}
} else {
WL_SCAN(("Scanning all channels\n"));
}
-
+ n_channels = i;
/* Copy ssid array if applicable */
WL_SCAN(("### List of SSIDs to scan ###\n"));
if (n_ssids > 0) {
@@ -1532,8 +1626,14 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req
ptr = (char*)params + offset;
for (i = 0; i < n_ssids; i++) {
memset(&ssid, 0, sizeof(wlc_ssid_t));
- ssid.SSID_len = request->ssids[i].ssid_len;
- memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
+ if(request->ssids && request->ssids[i].ssid) {
+ ssid.SSID_len = request->ssids[i].ssid_len;
+ memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
+ }
+ else {
+ ssid.SSID_len = 0;
+ ssid.SSID[0] = '\0';
+ }
if (!ssid.SSID_len)
WL_SCAN(("%d: Broadcast scan\n", i));
else
@@ -1549,6 +1649,10 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req
params->channel_num =
htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
(n_channels & WL_SCAN_PARAMS_COUNT_MASK));
+
+ if (n_channels == 1 && wl_get_drv_status_all(wl, CONNECTED)) {
+ params->active_time = WL_SCAN_CONNECT_DWELL_TIME_MS;
+ }
}
static s32
@@ -1561,7 +1665,10 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
struct wl_iscan_params *params = NULL;
s32 err = 0;
- if (request != NULL) {
+ if (!request) {
+ err = -EINVAL;
+ goto done;
+ }else {
n_channels = request->n_channels;
n_ssids = request->n_ssids;
/* Allocate space for populating ssids in wl_iscan_params struct */
@@ -1574,14 +1681,14 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
/* Allocate space for populating ssids in wl_iscan_params struct */
params_size += sizeof(struct wlc_ssid) * n_ssids;
}
+
params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
if (!params) {
err = -ENOMEM;
goto done;
}
- if (request != NULL)
- wl_scan_prep(&params->params, request);
+ wl_scan_prep(&params->params, request, -1);
params->version = htod32(ISCAN_REQ_VERSION);
params->action = htod16(action);
@@ -1602,7 +1709,7 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
}
}
done:
- if(params)
+ if (params)
kfree(params);
return err;
}
@@ -1649,9 +1756,10 @@ wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
return err;
}
-#ifdef USE_INITIAL_2G_SCAN
+#ifdef USE_INITIAL_2G_SCAN_ORG
+#define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
static bool g_first_broadcast_scan = TRUE;
-#endif /* USE_INITIAL_2G_SCAN */
+#endif /* USE_INITIAL_2G_SCAN_ORG */
static s32
wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
@@ -1662,7 +1770,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
u32 n_ssids;
s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
wl_escan_params_t *params = NULL;
- struct cfg80211_scan_request *scan_request = wl->scan_request;
+
u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
u32 num_chans = 0;
s32 channel;
@@ -1673,61 +1781,70 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
wl_uint32_list_t *list;
struct net_device *dev = NULL;
WL_DBG(("Enter \n"));
- WL_DBG(("p2p_supported ? %s, ndev is %s, p2p_scan ? %s, p2p_is_on ? %s\n",
- (wl->p2p_supported) ? "YES":"NO",
- (ndev == wl_to_prmry_ndev(wl)) ? "Primary":"P2P",
- p2p_scan(wl) ? "YES":"NO",
- p2p_is_on(wl) ? "YES":"NO"));
-
- if (!wl->p2p_supported || ((ndev == wl_to_prmry_ndev(wl)) &&
- !p2p_scan(wl))) {
+
+ /* sanity check for pointer dereference */
+ if (!request || !wl) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ if (!wl->p2p_supported)
+ WL_SCAN2(("P2P is not supported\n"));
+ else
+ WL_SCAN2(("P2P is supported, ndev is %s, "
+ "p2p_scan ? %s, p2p_is_on ? %s\n",
+ (ndev == wl_to_prmry_ndev(wl)) ? "Primary" : "P2P",
+ p2p_scan(wl) ? "YES" : "NO",
+ p2p_is_on(wl) ? "YES" : "NO"));
+
+ if (!wl->p2p_supported || !p2p_scan(wl)) {
+ s32 active_time = -1;
+
/* LEGACY SCAN TRIGGER */
WL_SCAN((" LEGACY E-SCAN START\n"));
- if (request != NULL) {
-#ifdef USE_INITIAL_2G_SCAN
- if (g_first_broadcast_scan == TRUE) {
- j = 0;
- if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
- list = (wl_uint32_list_t *) chan_buf;
- n_valid_chan = dtoh32(list->count);
- for (i = 0; i < n_valid_chan; i++) {
-#if defined(BCM4334_CHIP)
- request->channels[i]->flags |=
- IEEE80211_CHAN_NO_HT40;
-#endif
- WL_SCAN(("list->element[%d]=%d\n",
- i, list->element[i]));
- if (list->element[i] > CH_MAX_2G_CHANNEL)
- break;
- j++;
- }
- request->n_channels = j;
- WL_SCAN(("request->n_channels=%d\n", request->n_channels));
- g_first_broadcast_scan = FALSE;
+#ifdef USE_INITIAL_2G_SCAN_ORG
+ if (ndev == wl_to_prmry_ndev(wl) && g_first_broadcast_scan == true) {
+ j = 0;
+ if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
+ list = (wl_uint32_list_t *) chan_buf;
+ n_valid_chan = dtoh32(list->count);
+ for (i = 0; i < n_valid_chan; i++) {
+
+ WL_SCAN(("list->element[%d]=%d\n",
+ i, list->element[i]));
+ if (list->element[i] > CH_MAX_2G_CHANNEL)
+ break;
+ j++;
}
- }
-#endif /* USE_INITIAL_2G_SCAN */
- n_channels = request->n_channels;
- n_ssids = request->n_ssids;
- /* Allocate space for populating ssids in wl_iscan_params struct */
- if (n_channels % 2)
- /* If n_channels is odd, add a padd of u16 */
- params_size += sizeof(u16) * (n_channels + 1);
- else
- params_size += sizeof(u16) * n_channels;
+ request->n_channels = j;
- /* Allocate space for populating ssids in wl_iscan_params struct */
- params_size += sizeof(struct wlc_ssid) * n_ssids;
+ active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
+ WL_SCAN(("request->n_channels=%d\n", request->n_channels));
+ g_first_broadcast_scan = false;
+ }
}
+#endif /* USE_INITIAL_2G_SCAN_ORG */
+
+ n_channels = request->n_channels;
+ n_ssids = request->n_ssids;
+ /* Allocate space for populating ssids in wl_iscan_params struct */
+ if (n_channels % 2)
+ /* If n_channels is odd, add a padd of u16 */
+ params_size += sizeof(u16) * (n_channels + 1);
+ else
+ params_size += sizeof(u16) * n_channels;
+
+ /* Allocate space for populating ssids in wl_iscan_params struct */
+ params_size += sizeof(struct wlc_ssid) * n_ssids;
+
params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
if (params == NULL) {
err = -ENOMEM;
goto exit;
}
- if (request != NULL)
- wl_scan_prep(&params->params, request);
+ wl_scan_prep(&params->params, request, active_time);
params->version = htod32(ESCAN_REQ_VERSION);
params->action = htod16(action);
params->sync_id = wl->escan_info.cur_sync_id;
@@ -1752,8 +1869,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
WL_DBG((" P2P E-SCAN START\n"));
- if (scan_request && scan_request->n_channels) {
- num_chans = scan_request->n_channels;
+ if (request->n_channels) {
+ num_chans = request->n_channels;
WL_SCAN((" chann number : %d\n", num_chans));
default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
GFP_KERNEL);
@@ -1767,10 +1884,11 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
n_valid_chan = dtoh32(list->count);
for (i = 0; i < num_chans; i++)
{
- _freq = scan_request->channels[i]->center_freq;
+ _freq = request->channels[i]->center_freq;
channel = ieee80211_frequency_to_channel(_freq);
/* remove DFS channels */
- if (channel < 52 || channel > 140) {
+ if (!(request->channels[i]->flags &
+ (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN))) {
for (j = 0; j < n_valid_chan; j++) {
/* allows only supported channel on
* current reguatory
@@ -1824,6 +1942,13 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
s32 passive_scan;
wl_scan_results_t *results;
WL_SCAN(("Enter \n"));
+
+ WL_SCAN2(("scan result set to sync id :%d\n", wl->escan_info.cur_sync_id%2));
+ results = (wl_scan_results_t *) wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2];
+ results->version = 0;
+ results->count = 0;
+ results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
+
wl->escan_info.ndev = ndev;
wl->escan_info.wiphy = wiphy;
wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
@@ -1834,10 +1959,6 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
WL_ERR(("error (%d)\n", err));
return err;
}
- results = (wl_scan_results_t *) wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2];
- results->version = 0;
- results->count = 0;
- results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
return err;
@@ -1853,15 +1974,19 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct wl_scan_req *sr = wl_to_sr(wl);
struct ether_addr primary_mac;
wpa_ie_fixed_t *wps_ie;
+ wifi_p2p_ie_t *p2p_ie;
s32 passive_scan;
bool iscan_req;
bool escan_req = false;
bool p2p_ssid;
s32 err = 0;
+ s32 bssidx = -1;
s32 i;
u32 wpsie_len = 0;
+ u32 p2pie_len = 0;
u8 wpsie[IE_MAX_LEN];
unsigned long flags;
+ static s32 busy_count = 0;
/* If scan req comes for p2p0, send it over primary I/F
* Scan results will be delivered corresponding to cfg80211_scan_request
@@ -1870,11 +1995,26 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
ndev = wl_to_prmry_ndev(wl);
}
+ if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)
+#ifdef WL_CFG80211_SYNC_GON_TIME
+ || wl_get_drv_status_all(wl, WAITING_MORE_TIME_NEXT_ACT_FRM)
+#endif /* WL_CFG80211_SYNC_GON_TIME */
+ ) {
+ WL_ERR(("Sending Action Frames. Try it again.\n"));
+ return -EAGAIN;
+ }
+
WL_DBG(("Enter wiphy (%p)\n", wiphy));
if (wl_get_drv_status_all(wl, SCANNING)) {
- WL_ERR(("Scanning already\n"));
- return -EAGAIN;
+ if(wl->scan_request == NULL) {
+ wl_clr_drv_status_all(wl, SCANNING);
+ WL_DBG(( "<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
+ } else {
+ WL_ERR(("Scanning already\n"));
+ return -EAGAIN;
+ }
}
+
if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) {
WL_ERR(("Scanning being aborted\n"));
return -EAGAIN;
@@ -1888,6 +2028,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) {
+ WL_SCAN2(("request scan abort: %p(%d)\n", ndev, wl->escan_info.cur_sync_id));
wl_cfg80211_scan_abort(wl, ndev);
}
#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
@@ -1903,7 +2044,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
escan_req = true;
p2p_ssid = false;
for (i = 0; i < request->n_ssids; i++) {
- if (ssids[i].ssid_len && IS_P2P_SSID(ssids[i].ssid)) {
+ if (ssids[i].ssid_len && IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
p2p_ssid = true;
break;
}
@@ -1930,8 +2071,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
/* If Netdevice is not equals to primary and p2p is on
* , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
*/
- if (p2p_on(wl) && (ndev != wl_to_prmry_ndev(wl)))
- p2p_scan(wl) = true;
if (p2p_scan(wl) == false) {
if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
@@ -1945,24 +2084,31 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
}
}
if (!wl->p2p_supported || !p2p_scan(wl)) {
- if (ndev == wl_to_prmry_ndev(wl)) {
- /* find the WPSIE */
- memset(wpsie, 0, sizeof(wpsie));
- if ((wps_ie = wl_cfgp2p_find_wpsie(
- (u8 *)request->ie,
- request->ie_len)) != NULL) {
- wpsie_len =
- wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
- memcpy(wpsie, wps_ie, wpsie_len);
- } else {
- wpsie_len = 0;
- }
- err = wl_cfgp2p_set_management_ie(wl, ndev, -1,
+ /* find the WPSIE */
+ memset(wpsie, 0, sizeof(wpsie));
+ if ((wps_ie = wl_cfgp2p_find_wpsie(
+ (u8 *)request->ie,
+ request->ie_len)) != NULL) {
+ wpsie_len =
+ wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
+ memcpy(wpsie, wps_ie, wpsie_len);
+ } else {
+ wpsie_len = 0;
+ }
+ if ((p2p_ie = wl_cfgp2p_find_p2pie(
+ (u8 *)request->ie,
+ request->ie_len)) != NULL && (ndev != wl_to_prmry_ndev(wl))) {
+ p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
+ memcpy(wpsie + wpsie_len, p2p_ie, p2pie_len);
+ wpsie_len += p2pie_len;
+ bssidx = wl_cfgp2p_find_idx(wl, ndev);
+ }
+ err = wl_cfgp2p_set_management_ie(wl, ndev, bssidx,
VNDR_IE_PRBREQ_FLAG, wpsie, wpsie_len);
- if (unlikely(err)) {
- goto scan_out;
- }
+ if (unlikely(err)) {
+ goto scan_out;
}
+
}
}
}
@@ -1975,7 +2121,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
if (iscan_req) {
err = wl_do_iscan(wl, request);
if (likely(!err))
- return err;
+ goto scan_success;
else
goto scan_out;
} else if (escan_req) {
@@ -1995,7 +2141,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
}
err = wl_do_escan(wl, wiphy, ndev, request);
if (likely(!err))
- return err;
+ goto scan_success;
else
goto scan_out;
@@ -2033,6 +2179,10 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
}
}
+scan_success:
+
+ busy_count = 0;
+
return 0;
scan_out:
@@ -2042,10 +2192,21 @@ scan_out:
err = -EBUSY;
}
+ /*if continuous busy state , abort scan */
+ if (err == -EBUSY) {
+ if (busy_count++ > 5) {
+ busy_count = 0;
+ wl_cfg80211_scan_abort(wl, ndev);
+ }
+ } else {
+ busy_count = 0;
+ }
+
wl_clr_drv_status(wl, SCANNING, ndev);
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
wl->scan_request = NULL;
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ WL_SCAN2(("remove scan request:%p %d \n", ndev, wl->escan_info.cur_sync_id));
return err;
}
@@ -2057,6 +2218,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct wl_priv *wl = wiphy_priv(wiphy);
WL_DBG(("Enter \n"));
+ WL_SCAN2(("start %p\n", ndev));
CHECK_SYS_UP(wl);
err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
@@ -2313,15 +2475,15 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
switch (sme->auth_type) {
case NL80211_AUTHTYPE_OPEN_SYSTEM:
- val = 0;
+ val = WL_AUTH_OPEN_SYSTEM;
WL_DBG(("open system\n"));
break;
case NL80211_AUTHTYPE_SHARED_KEY:
- val = 1;
+ val = WL_AUTH_SHARED_KEY;
WL_DBG(("shared key\n"));
break;
case NL80211_AUTHTYPE_AUTOMATIC:
- val = 2;
+ val = WL_AUTH_OPEN_SHARED;
WL_DBG(("automatic\n"));
break;
case NL80211_AUTHTYPE_NETWORK_EAP:
@@ -2331,7 +2493,7 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
break;
#endif
default:
- val = 2;
+ val = WL_AUTH_OPEN_SHARED;
WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
break;
}
@@ -2417,7 +2579,11 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
if (is_wps_conn(sme)) {
- err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
+ if(sme->privacy)
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
+ else
+ /* WPS-2.0 allows no security */
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
} else {
#ifdef BCMWAPI_WPI
if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) {
@@ -2644,10 +2810,11 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
#ifdef ROAM_CHANNEL_CACHE
chanspec_t chanspec_list[MAX_ROAM_CACHE_NUM];
#endif
+ int ret;
WL_DBG(("In\n"));
- if (unlikely(!sme->ssid) || unlikely(!sme->bssid)) {
+ if (unlikely(!sme->ssid)) {
WL_ERR(("Invalid ssid\n"));
return -EOPNOTSUPP;
}
@@ -2657,8 +2824,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
/*
* Cancel ongoing scan to sync up with sme state machine of cfg80211.
*/
-#ifndef ESCAN_RESULT_PATCH
+#if (defined (BCM4334_CHIP) || !defined(ESCAN_RESULT_PATCH))
if (wl->scan_request) {
+ WL_SCAN2(("Abort Scan %p(%d)\n", dev, wl->escan_info.cur_sync_id));
wl_cfg80211_scan_abort(wl, dev);
}
#endif
@@ -2668,20 +2836,54 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
wl->block_gon_req_tx_count = 0;
wl->block_gon_req_rx_count = 0;
#endif /* WL_CFG80211_GON_COLLISION */
- WL_DBG(("Connect Request: \"%s\" %02x:%02x:%02x:%02x:%02x:%02x\n",
- sme->ssid, sme->bssid[0], sme->bssid[1], sme->bssid[2],
- sme->bssid[3], sme->bssid[4], sme->bssid[5]));
+ if (sme->bssid) {
+ WL_SCAN2(("Connect Request: \"%s\"" MACSTR "\n",
+ sme->ssid, MAC2STR(sme->bssid)));
#ifdef ESCAN_RESULT_PATCH
- memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
+ memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
+ }else {
+ bzero(connect_req_bssid, ETHER_ADDR_LEN);
+ }
bzero(broad_bssid, ETHER_ADDR_LEN);
+#else
+ }
#endif
+ bzero(&bssid, sizeof(bssid));
+ if (!wl_get_drv_status(wl, CONNECTED, dev)&&
+ (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
+ if(!ETHER_ISNULLADDR(&bssid)) {
+ scb_val_t scbval;
+ wl_set_drv_status(wl, DISCONNECTING, dev);
+ scbval.val = DOT11_RC_DISASSOC_LEAVING;
+ memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+
+ WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACSTR "/n"
+ , MAC2STR(bssid.octet)));
+ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), true);
+ if (unlikely(err)) {
+ wl_clr_drv_status(wl, DISCONNECTING, dev);
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ while (wl_get_drv_status(wl, DISCONNECTING, dev)) {
+ WL_ERR(("Waiting for disconnection terminated.\n"));
+ msleep(20);
+ }
+ } else
+ WL_DBG(("Currently not associated!\n"));
+ }
+
/* Clean BSSID */
bzero(&bssid, sizeof(bssid));
- wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
+ if (!wl_get_drv_status(wl, DISCONNECTING, dev))
+ wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
- if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) {
+ if (!memcmp(sme->ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) &&
+ (dev != wl_to_prmry_ndev(wl))) {
/* we only allow to connect using virtual interface in case of P2P */
if (p2p_is_on(wl) && is_wps_conn(sme)) {
WL_DBG(("ASSOC1 p2p index : %d sme->ie_len %d\n",
@@ -2744,13 +2946,16 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return err;
}
}
- if (unlikely(!sme->ssid)) {
- WL_ERR(("Invalid ssid\n"));
- return -EOPNOTSUPP;
- }
+
if (chan) {
#ifdef ROAM_CHANNEL_CACHE
wlc_ssid_t ssid;
+ int band;
+
+ err = wldev_get_band(dev, &band);
+ if (!err) {
+ set_roam_band(band);
+ }
wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
memcpy(ssid.SSID, sme->ssid, sme->ssid_len);
@@ -2787,11 +2992,11 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
else {
WL_DBG(("4. wl_set_auth_type\n"));
#endif
- err = wl_set_auth_type(dev, sme);
- if (unlikely(err)) {
- WL_ERR(("Invalid auth type\n"));
- return err;
- }
+ err = wl_set_auth_type(dev, sme);
+ if (unlikely(err)) {
+ WL_ERR(("Invalid auth type\n"));
+ return err;
+ }
#ifdef BCMWAPI_WPI
}
#endif
@@ -2829,14 +3034,14 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
- /* Set up join scan parameters */
- ext_join_params->scan.scan_type = -1;
- ext_join_params->scan.nprobes = 2;
/* increate dwell time to receive probe response or detect Beacon
* from target AP at a noisy air only during connect command
*/
- ext_join_params->scan.active_time = WL_SCAN_ACTIVE_TIME*3;
+ ext_join_params->scan.active_time = WL_SCAN_ACTIVE_TIME*8;
ext_join_params->scan.passive_time = WL_SCAN_PASSIVE_TIME*3;
+ /* Set up join scan parameters */
+ ext_join_params->scan.scan_type = -1;
+ ext_join_params->scan.nprobes = (ext_join_params->scan.active_time/(WL_SCAN_ACTIVE_TIME *2));
ext_join_params->scan.home_time = -1;
if (sme->bssid)
@@ -2932,9 +3137,10 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
/*
* Cancel ongoing scan to sync up with sme state machine of cfg80211.
*/
-#ifndef ESCAN_RESULT_PATCH
+#if (defined (BCM4334_CHIP) || !defined (ESCAN_RESULT_PATCH))
/* Let scan aborted by F/W */
if (wl->scan_request) {
+ WL_SCAN2(("Abort scan : %p(%d)\n", dev, wl->escan_info.cur_sync_id));
wl_cfg80211_scan_abort(wl, dev);
}
#endif /* ESCAN_RESULT_PATCH */
@@ -3412,8 +3618,10 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
} else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {
u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
if (!wl_get_drv_status(wl, CONNECTED, dev) ||
- (dhd_is_associated(dhd, NULL) == FALSE)) {
+ (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
WL_ERR(("NOT assoc\n"));
+ if(err == -ERESTARTSYS)
+ return err;
#ifdef ESCAN_RESULT_PATCH
return -ENODEV;
#else
@@ -3451,7 +3659,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
WL_DBG(("RSSI %d dBm\n", rssi));
get_station_err:
- if (err) {
+ if (err && (err != -ERESTARTSYS)) {
/* Disconnect due to zero BSSID or error to get RSSI */
WL_ERR(("force cfg80211_disconnected\n"));
wl_clr_drv_status(wl, CONNECTED, dev);
@@ -3469,18 +3677,20 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
{
s32 pm;
s32 err = 0;
+
struct wl_priv *wl = wiphy_priv(wiphy);
+ struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev);
CHECK_SYS_UP(wl);
- if (wl->p2p_net == dev) {
+ if (wl->p2p_net == dev || _net_info == NULL) {
return err;
}
pm = enabled ? PM_FAST : PM_OFF;
/* Do not enable the power save after assoc if it is p2p interface */
- if (wl->p2p && wl->p2p->vif_created) {
- WL_DBG(("Do not enable the power save for p2p interfaces even after assoc\n"));
+ if (_net_info->pm_block || wl->vsdb_mode) {
+ WL_DBG(("Do not enable the power save\n"));
pm = PM_OFF;
}
pm = htod32(pm);
@@ -3562,12 +3772,15 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
if (wl->scan_request) {
cfg80211_scan_done(wl->scan_request, true);
wl->scan_request = NULL;
+ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ WL_SCAN2(("remove scan_request %p, %d\n", ndev, wl->escan_info.cur_sync_id));
+ } else {
+ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
}
for_each_ndev(wl, iter, next) {
wl_clr_drv_status(wl, SCANNING, iter->ndev);
wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
}
- spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
for_each_ndev(wl, iter, next) {
if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) {
wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false);
@@ -3769,13 +3982,21 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev)
}
}
del_timer_sync(&wl->scan_timeout);
+#if defined(BCM4334_CHIP)
+ if (wl->scan_request) {
+ u8 temp_id = wl->escan_info.cur_sync_id;
+ wl->bss_list = (wl_scan_results_t *) wl->escan_info.escan_buf[(temp_id+1)%2];
+ wl_inform_bss(wl);
+ }
+#endif
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
if (wl->scan_request) {
cfg80211_scan_done(wl->scan_request, true);
wl->scan_request = NULL;
}
- wl_clr_drv_status(wl, SCANNING, ndev);
+
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ wl_clr_drv_status(wl, SCANNING, ndev);
if (params)
kfree(params);
return err;
@@ -3791,9 +4012,10 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
u32 id;
struct ether_addr primary_mac;
struct net_device *ndev = NULL;
-
s32 err = BCME_OK;
struct wl_priv *wl = wiphy_priv(wiphy);
+
+ WL_SCAN2(("duration :%d\n", duration));
WL_DBG(("Enter, ifindex: %d, channel: %d, duration ms (%d) SCANNING ?? %s \n",
dev->ifindex, ieee80211_frequency_to_channel(channel->center_freq),
duration, (wl_get_drv_status(wl, SCANNING, ndev)) ? "YES":"NO"));
@@ -3810,6 +4032,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
}
#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
if (wl_get_drv_status(wl, SCANNING, ndev)) {
+ WL_SCAN2(("Abort Scan : %p(%d)\n", ndev, wl->escan_info.cur_sync_id));
wl_cfg80211_scan_abort(wl, ndev);
}
#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
@@ -3861,7 +4084,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
}
#endif /* WL_CFG80211_SYNC_GON_TIME */
- if (!p2p_is_on(wl)) {
+ if (wl->p2p && !wl->p2p->on) {
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
@@ -3890,6 +4113,8 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
/* if failed, firmware may be internal scanning state.
so other scan request shall not abort it */
wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
+ /* set err = ok to prevent cookie mismatch */
+ err = BCME_OK;
}
#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
}
@@ -3911,6 +4136,10 @@ wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl)
{
wl_af_params_t *tx_act_frm;
struct net_device *dev = wl->afx_hdl->dev;
+
+ if (dev == NULL)
+ return -1;
+
if (!p2p_is_on(wl))
return -1;
@@ -3930,7 +4159,10 @@ wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl)
wl_clr_drv_status(wl, SENDING_ACT_FRM, wl->afx_hdl->dev);
#endif
wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
+/* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary */
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
wl_cfg80211_scan_abort(wl, dev);
+#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
wl_cfgp2p_discover_enable_search(wl, false);
tx_act_frm->channel = wl->afx_hdl->peer_chan;
wl->afx_hdl->ack_recv = (wl_cfgp2p_tx_action_frame(wl, dev,
@@ -3947,9 +4179,9 @@ wl_cfg80211_afx_handler(struct work_struct *work)
s32 ret = BCME_OK;
afx_instance = container_of(work, struct afx_hdl, work);
- if (afx_instance != NULL) {
+ if (afx_instance != NULL && wl->afx_hdl->is_active) {
if (wl->afx_hdl->is_listen && wl->afx_hdl->my_listen_chan) {
- ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan, 100);
+ ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan, 200);
} else {
ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev,
wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan);
@@ -3967,6 +4199,8 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
struct net_device *dev,
wl_af_params_t *af_params)
{
+ u32 max_retry = WL_CHANNEL_SYNC_RETRY;
+
WL_DBG((" enter ) \n"));
/* initialize afx_hdl */
wl->afx_hdl->pending_tx_act_frm = af_params;
@@ -3976,11 +4210,15 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
wl->afx_hdl->peer_chan = WL_INVALID;
wl->afx_hdl->ack_recv = false;
+ WL_AF_TX_REDUCE_RETRY_VSDB(wl, max_retry);
+
wl_set_drv_status(wl, SCANNING_PEER_CHANNEL, dev);
+ wl->afx_hdl->is_active = TRUE;
+
/* Loop to wait until we have sent the pending tx action frame or the
* pending action frame tx is cancelled.
*/
- while ((wl->afx_hdl->retry < WL_CHANNEL_SYNC_RETRY) &&
+ while ((wl->afx_hdl->retry < max_retry) &&
(wl->afx_hdl->peer_chan == WL_INVALID)) {
wl->afx_hdl->is_listen = FALSE;
wl_set_drv_status(wl, SCANNING, dev);
@@ -3992,7 +4230,7 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
msecs_to_jiffies(MAX_WAIT_TIME));
if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
- !(wl_get_drv_status_all(wl, SCANNING_PEER_CHANNEL)))
+ !(wl_get_drv_status(wl, SCANNING_PEER_CHANNEL, dev)))
break;
if (wl->afx_hdl->my_listen_chan) {
@@ -4004,12 +4242,17 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
wait_for_completion_timeout(&wl->act_frm_scan,
msecs_to_jiffies(MAX_WAIT_TIME));
}
- if (!wl_get_drv_status_all(wl, SCANNING_PEER_CHANNEL))
+ if (!wl_get_drv_status(wl, SCANNING_PEER_CHANNEL, dev))
break;
wl->afx_hdl->retry++;
+
+ WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
}
- wl_clr_drv_status(wl, SCANNING_PEER_CHANNEL, wl->afx_hdl->dev);
+ wl->afx_hdl->is_active = FALSE;
+
+ wl_clr_drv_status(wl, SCANNING, dev);
+ wl_clr_drv_status(wl, SCANNING_PEER_CHANNEL, dev);
if (wl->afx_hdl->peer_chan != WL_INVALID)
wl_cfg80211_send_pending_tx_act_frm(wl);
@@ -4134,18 +4377,18 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
add_len = customer_ie->len + sizeof(customer_ie->len)
+ sizeof(customer_ie->id);
customer_ie_len += add_len;
- ptr = (u8 *)customer_ie + add_len;
+ ptr = (u8*)customer_ie + add_len;
remain_len -= add_len;
WL_INFO(("Customer IE exist(len:%d)\n", add_len));
}
else
break;
}
- /* Order of Vendor IE is 1) WPS IE +
- * 2) P2P IE created by supplicant
- * So, it is ok to find start address of WPS IE
- * to save IEs
- */
+ /* Order of Vendor IE is 1) WPS IE +
+ * 2) P2P IE created by supplicant
+ * So, it is ok to find start address of WPS IE
+ * to save IEs
+ */
wl_cfgp2p_set_management_ie(wl, dev, bssidx,
VNDR_IE_PRBRSP_FLAG,
@@ -4157,8 +4400,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
ieee80211_is_deauth(mgmt->frame_control)) {
memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
scb_val.val = mgmt->u.disassoc.reason_code;
- wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
- sizeof(scb_val_t), true);
+ if (wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
+ sizeof(scb_val_t), true) < 0)
+ WL_ERR(("Connect Status check is required\n"));
WL_DBG(("Disconnect STA : %s\n",
bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf)));
cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
@@ -4172,8 +4416,14 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
* tx is still in progress (including the dwell time),
* then this new action frame will not be sent out.
*/
- wl_cfg80211_scan_abort(wl, dev);
+/* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
+ * And previous off-channel action frame must be ended before new af tx.
+ */
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ WL_SCAN2(("Abort scan: %p(%d)\n", dev, wl->escan_info.cur_sync_id));
+ wl_cfg80211_scan_abort(wl, dev);
+#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
}
} else {
@@ -4210,13 +4460,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
wl->afx_hdl->peer_listen_chan = af_params->channel;
WL_DBG(("channel from upper layer %d\n", wl->afx_hdl->peer_listen_chan));
- if (channel->band == IEEE80211_BAND_5GHZ) {
- err = wldev_ioctl(dev, WLC_SET_CHANNEL,
- &af_params->channel, sizeof(af_params->channel), true);
- if (err < 0) {
- WL_ERR(("WLC_SET_CHANNEL error %d\n", err));
- }
- }
+
/* Add the dwell time
* Dwell time to stay off-channel to wait for a response action frame
@@ -4226,10 +4470,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
if (wl_cfgp2p_is_pub_action(action_frame->data, action_frame->len)) {
- act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data);
+ act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data);
WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n",
- action_frame->len, af_params->channel,
- act_frm->category, act_frm->subtype));
+ action_frame->len, af_params->channel,
+ act_frm->category, act_frm->subtype));
} else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) {
p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data);
WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n",
@@ -4307,6 +4551,18 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
}
+#ifdef VSDB
+ /* if connecting, sleep for a while before retry for VSDB */
+ if (wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) {
+ msleep(50);
+ }
+#endif
+
+ /* if scanning, abort current scan. */
+ if (wl_get_drv_status_all(wl, SCANNING)) {
+ wl_cfg80211_scan_abort(wl, dev);
+ }
+
/* Set SENDING_ACT_FRM and destinatio address for sending af */
wl_set_drv_status(wl, SENDING_ACT_FRM, dev);
memcpy(wl->afx_hdl->tx_dst_addr.octet,
@@ -4325,8 +4581,16 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
/* channel offload for action request frame */
ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
} else {
+ if (!wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len)
+ WL_ERR(("<<<< TX action frame without probe req ie >>>>\n"));
+ if (!IS_P2P_SOCIAL(af_params->channel))
+ WL_ERR(("<<<< TX action frame with (CH %d) >>>>\n",
+ af_params->channel));
ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true;
if (!ack) {
+ u32 max_retry = WL_CHANNEL_SYNC_RETRY;
+ WL_AF_TX_REDUCE_RETRY_VSDB(wl, max_retry);
+
if (wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
/* if the NO ACK occurs, the peer device will be on
* listen channel of the peer
@@ -4340,7 +4604,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
!IS_P2P_PUB_ACT_RSP_SUBTYPE(act_frm->subtype)) {
ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
} else {
- for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) {
+ for (retry = 0; retry < max_retry; retry++) {
+ WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
ack = (wl_cfgp2p_tx_action_frame(wl, dev,
af_params, bssidx)) ? false : true;
if (ack)
@@ -4348,7 +4613,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
}
}
} else {
- for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) {
+ for (retry = 0; retry < max_retry; retry++) {
+ WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
ack = (wl_cfgp2p_tx_action_frame(wl, dev,
af_params, bssidx)) ? false : true;
if (ack)
@@ -4382,10 +4648,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
wait_for_completion_timeout(&wl->wait_next_af,
msecs_to_jiffies(extar_listen_time + 100 + 300));
}
+ wl_clr_drv_status(wl, WAITING_MORE_TIME_NEXT_ACT_FRM, dev);
}
}
wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
- wl_clr_drv_status(wl, WAITING_MORE_TIME_NEXT_ACT_FRM, dev);
WL_INFO(("-- sending Action Frame is %s, af sent chan: %d, my listen chan: %d\n",
(ack) ? "Succeeded!!":"Failed!!", wl->af_sent_channel, wl->afx_hdl->my_listen_chan));
@@ -4460,20 +4726,75 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
- s32 channel;
+ s32 _chan;
+#ifdef HT40_GO
+ s32 center_chan;
+ chanspec_t chspec = 0;
+#endif
s32 err = BCME_OK;
struct wl_priv *wl = wiphy_priv(wiphy);
if (wl->p2p_net == dev) {
dev = wl_to_prmry_ndev(wl);
}
- channel = ieee80211_frequency_to_channel(chan->center_freq);
- WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
- dev->ifindex, channel_type, channel));
- err = wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), true);
+ _chan = ieee80211_frequency_to_channel(chan->center_freq);
+ WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
+ dev->ifindex, channel_type, _chan));
+
+#ifdef NOT_YET
+ switch (channel_type) {
+ case NL80211_CHAN_HT40MINUS:
+ /* secondary channel is below the control channel */
+ chspec = CH40MHZ_CHSPEC(channel, WL_CHANSPEC_CTL_SB_UPPER);
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ /* secondary channel is above the control channel */
+ chspec = CH40MHZ_CHSPEC(channel, WL_CHANSPEC_CTL_SB_LOWER);
+ break;
+ default:
+ chspec = CH20MHZ_CHSPEC(channel);
+
+ }
+#endif
+#ifdef HT40_GO
+ switch(_chan) {
+ /* adjust channel to center of 40MHz band */
+ case 40:
+ case 48:
+ case 153:
+ case 161:
+ if (_chan <= (MAXCHANNEL - CH_20MHZ_APART))
+ center_chan = _chan - CH_10MHZ_APART;
+ chspec = CH40MHZ_CHSPEC(center_chan, WL_CHANSPEC_CTL_SB_UPPER);
+ break;
+ case 36:
+ case 44:
+ case 149:
+ case 157:
+ if (_chan <= (MAXCHANNEL - CH_20MHZ_APART))
+ center_chan = _chan + CH_10MHZ_APART;
+ chspec = CH40MHZ_CHSPEC(center_chan, WL_CHANSPEC_CTL_SB_LOWER);
+ break;
+ default:
+ chspec = CH20MHZ_CHSPEC(_chan);
+ break;
+ }
+
+
+ if ((err = wldev_iovar_setint(dev, "chanspec", chspec)) == BCME_BADCHAN) {
+ err = wldev_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), true);
+ if (err < 0) {
+ WL_ERR(("WLC_SET_CHANNEL error %d"
+ "chip may not be supporting this channel\n", err));
+ }
+ }
+#else
+ err = wldev_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), true);
if (err < 0) {
- WL_ERR(("WLC_SET_CHANNEL error %d chip may not be supporting this channel\n", err));
+ WL_ERR(("WLC_SET_CHANNEL error %d"
+ "chip may not be supporting this channel\n", err));
}
+#endif
return err;
}
@@ -4487,7 +4808,6 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
u32 pval = 0;
u32 gval = 0;
u32 wpa_auth = 0;
- u8* tmp;
wpa_suite_mcast_t *mcast;
wpa_suite_ucast_t *ucast;
wpa_suite_auth_key_mgmt_t *mgmt;
@@ -4498,8 +4818,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
len = wpa2ie->len;
/* check the mcast cipher */
mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
- tmp = mcast->oui;
- switch (tmp[DOT11_OUI_LEN]) {
+ switch (mcast->type) {
case WPA_CIPHER_NONE:
gval = 0;
break;
@@ -4526,8 +4845,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
/* check the unicast cipher */
ucast = (wpa_suite_ucast_t *)&mcast[1];
ltoh16_ua(&ucast->count);
- tmp = ucast->list[0].oui;
- switch (tmp[DOT11_OUI_LEN]) {
+ switch (ucast->list[0].type) {
case WPA_CIPHER_NONE:
pval = 0;
break;
@@ -4554,8 +4872,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
/* check the AKM */
mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[1];
ltoh16_ua(&mgmt->count);
- tmp = (u8 *)&mgmt->list[0];
- switch (tmp[DOT11_OUI_LEN]) {
+ switch (mgmt->list[0].type) {
case RSN_AKM_NONE:
wpa_auth = WPA_AUTH_NONE;
break;
@@ -4875,8 +5192,16 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
WL_DBG(("SSID is (%s) in Head \n", ssid.SSID));
ssid.SSID_len = ssid_ie->len;
wldev_iovar_setint(dev, "mpc", 0);
- wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
- wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
+ if (err < 0) {
+ WL_ERR(("WLC_DOWN error %d\n", err));
+ goto exit;
+ }
+ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ if (err < 0) {
+ WL_ERR(("SET INFRA error %d\n", err));
+ goto exit;
+ }
if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
WL_ERR(("setting AP mode failed %d \n", err));
return err;
@@ -4936,7 +5261,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
memcpy(beacon_ie, wps_ie, wpsie_len);
wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
beacon_ie, wpsie_len);
- wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
+ wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
} else {
@@ -4989,12 +5314,12 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
memcmp(wl->ap_info->wps_ie, wps_ie, wpsie_len)) {
WL_DBG((" WPS IE is changed\n"));
kfree(wl->ap_info->wps_ie);
- wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
+ wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
} else if (wl->ap_info->wps_ie == NULL) {
WL_DBG((" WPS IE is added\n"));
- wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
+ wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
}
@@ -5152,10 +5477,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
| BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR);
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
-#ifndef CUSTOMER_HW_SAMSUNG
-#error 5ghz cause p2p connection error
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;
-#endif
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wdev->wiphy->cipher_suites = __wl_cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
@@ -5202,8 +5524,8 @@ static void wl_free_wdev(struct wl_priv *wl)
wl_delete_all_netinfo(wl);
wiphy_free(wiphy);
/* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
- * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
- */
+ * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
+ */
}
static s32 wl_inform_bss(struct wl_priv *wl)
@@ -5247,13 +5569,16 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
s32 signal;
u32 freq;
s32 err = 0;
+ gfp_t aflags;
if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
WL_DBG(("Beacon is larger than buffer. Discarding\n"));
return err;
}
+
+ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
- - sizeof(u8) + WL_BSS_INFO_MAX, GFP_KERNEL);
+ - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
if (unlikely(!notif_bss_info)) {
WL_ERR(("notif_bss_info alloc failed\n"));
return -ENOMEM;
@@ -5267,7 +5592,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
- if (band == NULL) {
+ if(band==NULL) {
kfree(notif_bss_info);
return err;
}
@@ -5314,7 +5639,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
signal = notif_bss_info->rssi * 100;
#if defined(WLP2P) && (ENABLE_P2P_INTERFACE)
if (wl->p2p_net && wl->scan_request &&
- wl->scan_request->dev == wl->p2p_net) {
+ wl->scan_request->dev == wl->p2p_net) {
#else
if (p2p_is_on(wl) && p2p_scan(wl)) {
#endif
@@ -5427,11 +5752,18 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
struct station_info sinfo;
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE */
+ /* if link down, bsscfg is disabled. */
+ if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
+ wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) {
+ WL_INFO(("AP mode link down !! \n"));
+ complete(&wl->iface_disable);
+ return 0;
+ }
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE
body=kzalloc(len, GFP_KERNEL);
- WL_DBG(("Enter\n"));
- if (body == NULL) {
+ WL_DBG(("Enter \n"));
+ if(body==NULL) {
WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
return WL_INVALID;
}
@@ -5443,62 +5775,68 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
return WL_INVALID;
}
- memcpy(body, data, len);
- wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
- NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync);
- memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
- err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
- switch (event) {
- case WLC_E_ASSOC_IND:
- fc = FC_ASSOC_REQ;
- break;
- case WLC_E_REASSOC_IND:
- fc = FC_REASSOC_REQ;
- break;
- case WLC_E_DISASSOC_IND:
- fc = FC_DISASSOC;
- break;
- case WLC_E_DEAUTH_IND:
- fc = FC_DISASSOC;
- break;
- case WLC_E_DEAUTH:
- fc = FC_DISASSOC;
- break;
- default:
- fc = 0;
- goto exit;
- }
- if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
- kfree(body);
- return err;
- }
+ memcpy(body, data, len);
+ wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+ NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync);
+ memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
+ err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
+ switch (event) {
+ case WLC_E_ASSOC_IND:
+ fc = FC_ASSOC_REQ;
+ break;
+ case WLC_E_REASSOC_IND:
+ fc = FC_REASSOC_REQ;
+ break;
+ case WLC_E_DISASSOC_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH:
+ fc = FC_DISASSOC;
+ break;
+ default:
+ fc = 0;
+ goto exit;
+ }
+ if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
+ kfree (body);
+ return err;
+ }
- channel = dtoh32(ci.hw_channel);
- if (channel <= CH_MAX_2G_CHANNEL)
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- else
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
+ channel = dtoh32(ci.hw_channel);
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ if(band == NULL) {
+ WL_ERR(("band is null(channel=%d)\n", channel));
+ kfree(body);
+ return WL_INVALID;
+ }
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
- freq = ieee80211_channel_to_frequency(channel);
- (void)band->band;
+ freq = ieee80211_channel_to_frequency(channel);
+ (void)band->band;
#else
- freq = ieee80211_channel_to_frequency(channel, band->band);
+ freq = ieee80211_channel_to_frequency(channel, band->band);
#endif
- err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
- &mgmt_frame, &len, body);
- if (err < 0)
- goto exit;
- isfree = true;
+ err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
+ &mgmt_frame, &len, body);
+ if (err < 0)
+ goto exit;
+ isfree = true;
- if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
- cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
- } else if (event == WLC_E_DISASSOC_IND) {
- cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
- } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
- cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
- }
+ if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+ } else if (event == WLC_E_DISASSOC_IND) {
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+ }
exit:
if (isfree)
@@ -5540,7 +5878,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
} else {
WL_DBG(("wl_notify_connect_status : event %d status : %d \n",
ntoh32(e->event_type), ntoh32(e->status)));
-//chanyun TBD from DHD 15 no p2p firmware exist should change to interface
+ /* chanyun TBD from DHD 15 no p2p firmware exist should change to interface */
if (strstr(fw_path, "_p2p") == NULL && event == WLC_E_DEAUTH) {
WL_DBG(("unexpected event WLC_E_DEAUTH\n"));
return WL_INVALID;
@@ -5569,6 +5907,18 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
if (wl->scan_request) {
del_timer_sync(&wl->scan_timeout);
if (wl->escan_on) {
+ WL_SCAN2(("link down notify escan complete: %p(%d)\n",
+ ndev, wl->escan_info.cur_sync_id));
+#ifndef CUSTOMER_HW_SAMSUNG
+#error inform bss will be done at notify function
+ {
+ u8 temp_id = wl->escan_info.cur_sync_id;
+ wl->bss_list =
+ (wl_scan_results_t *)
+ wl->escan_info.escan_buf[(temp_id+1)%2];
+ wl_inform_bss(wl);
+ }
+#endif
wl_notify_escan_complete(wl, ndev, true);
} else
wl_iscan_aborted(wl);
@@ -5594,8 +5944,10 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
scbval.val = WLAN_REASON_DEAUTH_LEAVING;
memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
scbval.val = htod32(scbval.val);
- wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
+ err =wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
sizeof(scb_val_t), true);
+ if (err < 0)
+ WL_ERR(("Check Assoc Status : %d\n", err));
cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
wl_link_down(wl);
wl_init_prof(wl, ndev);
@@ -5615,17 +5967,25 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
}
wl_clr_drv_status(wl, DISCONNECTING, ndev);
+ /* if link down, bsscfg is diabled */
+ if (ndev != wl_to_prmry_ndev(wl))
+ complete(&wl->iface_disable);
+
} else if (wl_is_nonetwork(wl, e)) {
printk("connect failed event=%d e->status 0x%x\n",
event, (int)ntoh32(e->status));
/* Clean up any pending scan request */
+
if (wl->scan_request) {
del_timer_sync(&wl->scan_timeout);
if (wl->escan_on) {
+ WL_SCAN2((" send noti due to connect fail : %p(%d)\n",
+ ndev, wl->escan_info.cur_sync_id));
wl_notify_escan_complete(wl, ndev, true);
} else
wl_iscan_aborted(wl);
}
+
if (wl_get_drv_status(wl, CONNECTING, ndev))
wl_bss_connect_done(wl, ndev, e, data, false);
} else {
@@ -5895,11 +6255,24 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
WL_DBG(("copy bssid\n"));
memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
}
- WL_DBG(("Connect done bssid=%02x:%02x:%02x:%02x:%02x:%02x\n",
- curbssid[0], curbssid[1], curbssid[2],
- curbssid[3], curbssid[4], curbssid[5]));
+ if (wl_get_drv_status(wl, CONNECTED, ndev)) {
+ if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
+ WL_ERR((" Connected event of connected device, ignore it\n"));
+ return err;
+ }
+ }
+
+
+ WL_SCAN2(("Connect done \n"));
+#if defined(BCM4334_CHIP)
+ if (wl->scan_request) {
+ WL_SCAN2(("Abort scan : %p(%d)\n", ndev, wl->escan_info.cur_sync_id));
+ wl_cfg80211_scan_abort(wl, ndev);
+ }
+#endif
#else
if (wl->scan_request) {
+ WL_SCAN2(("Abort scan : %p(%d)\n", ndev, wl->escan_info.cur_sync_id));
wl_cfg80211_scan_abort(wl, ndev);
}
#endif /* ESCAN_RESULT_PATCH */
@@ -5926,7 +6299,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT,
GFP_KERNEL);
if (completed)
- WL_INFO(("Report connect result - connection succeeded(%d)\n",
+ WL_SCAN2(("Report connect result - connection succeeded(%d)\n",
conn_info->resp_ie_len));
else
WL_ERR(("Report connect result - connection failed\n"));
@@ -6010,11 +6383,14 @@ scan_done_out:
del_timer_sync(&wl->scan_timeout);
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
if (wl->scan_request) {
- WL_DBG(("cfg80211_scan_done\n"));
cfg80211_scan_done(wl->scan_request, false);
wl->scan_request = NULL;
+ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ WL_DBG(("cfg80211_scan_done\n"));
+ WL_SCAN2(("Remove Scan Request %p, %d\n", ndev, wl->escan_info.cur_sync_id));
+ } else {
+ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
}
- spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
mutex_unlock(&wl->usr_sync);
return err;
}
@@ -6116,6 +6492,11 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
+ if(band == NULL) {
+ WL_ERR(("band is null(channel=%d)\n", channel));
+ return WL_INVALID;
+ }
+
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
freq = ieee80211_channel_to_frequency(channel);
(void)band->band;
@@ -6126,7 +6507,11 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr",
NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync);
- wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
+ err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
+ if( err < 0) {
+ bzero (&bssid, ETHER_ADDR_LEN);
+ WL_ERR (("NO Connected BSSID set to zero\n"));
+ }
memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
&mgmt_frame, &mgmt_frame_len,
@@ -6211,11 +6596,12 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
if (wl_get_drv_status_all(wl, SENDING_ACT_FRM) &&
(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||
wl_get_p2p_status(wl, ACTION_TX_NOACK))) {
- /* do not wait more time for OFF_CHAN_COMPLETE !!!
- * we already have the next frame!!
- */
- WL_DBG(("*** Wake UP ** send_af_done_event ** \n"));
- wake_up_interruptible(&wl->send_af_done_event);
+ WL_DBG(("*** Wake UP ** abort actframe ** \n"));
+ //wake_up_interruptible(&wl->send_af_done_event);
+ /* if channel is not zero, "actfame" uses off channel scan.
+ * So abort scan for off channel completion. */
+ if (wl->af_sent_channel)
+ wl_cfg80211_scan_abort(wl, dev);
} else if (wl_get_drv_status_all(wl, WAITING_MORE_TIME_NEXT_ACT_FRM)) {
WL_DBG(("*** Wake UP ** wait_next_af ** \n"));
complete(&wl->wait_next_af);
@@ -6390,17 +6776,14 @@ static s32 wl_init_priv_mem(struct wl_priv *wl)
#ifdef CONFIG_DHD_USE_STATIC_BUF
wl->escan_info.escan_buf[0] = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0);
bzero(wl->escan_info.escan_buf[0], ESCAN_BUF_SIZE);
+ wl->escan_info.escan_buf[1] = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN1, 0);
+ bzero(wl->escan_info.escan_buf[1], ESCAN_BUF_SIZE);
#else
wl->escan_info.escan_buf[0] = (void *)kzalloc(ESCAN_BUF_SIZE, GFP_KERNEL);
if (unlikely(!wl->escan_info.escan_buf[0])) {
WL_ERR(("wl->escan_info.escan_buf[0] alloc failed\n"));
goto init_priv_mem_out;
}
-#endif
-#ifdef CONFIG_DHD_USE_STATIC_BUF
- wl->escan_info.escan_buf[1] = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN1, 0);
- bzero(wl->escan_info.escan_buf[1], ESCAN_BUF_SIZE);
-#else
wl->escan_info.escan_buf[1] = (void *)kzalloc(ESCAN_BUF_SIZE, GFP_KERNEL);
if (unlikely(!wl->escan_info.escan_buf[1])) {
WL_ERR(("wl->escan_info.escan_buf[1] alloc failed\n"));
@@ -6518,12 +6901,12 @@ static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
return;
}
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
- wl_clr_drv_status(wl, SCANNING, ndev);
if (likely(wl->scan_request)) {
cfg80211_scan_done(wl->scan_request, aborted);
wl->scan_request = NULL;
}
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ wl_clr_drv_status(wl, SCANNING, ndev);
wl->iscan_kickstart = false;
}
@@ -6666,13 +7049,28 @@ static s32 wl_iscan_thread(void *data)
static void wl_scan_timeout(unsigned long data)
{
- struct wl_priv *wl = (struct wl_priv *)data;
-
+ struct wl_priv *wl = (struct wl_priv *) data;
+ wl_event_msg_t msg;
+ wl_escan_result_t *escan_results;
if (wl->scan_request) {
WL_ERR(("timer expired\n"));
- if (wl->escan_on)
- wl_notify_escan_complete(wl, wl->escan_info.ndev, true);
- else
+ if (wl->escan_on) {
+ msg.event_type = hton32(WLC_E_ESCAN_RESULT);
+ msg.status = hton32(WLC_E_STATUS_SUCCESS);
+ escan_results = kzalloc(sizeof(wl_escan_result_t), GFP_ATOMIC);
+ if (escan_results != NULL) {
+ msg.datalen = hton32(sizeof(wl_escan_result_t));
+ escan_results->sync_id = htod16(wl->escan_info.cur_sync_id);
+ escan_results->bss_count =htod16(0);
+ escan_results->buflen = htod32(WL_ESCAN_RESULTS_FIXED_SIZE);
+ escan_results->version =htod32(WL_BSS_INFO_VERSION);
+ wl_cfg80211_event(wl->escan_info.ndev, &msg, escan_results);
+ kfree(escan_results);
+ } else {
+ wl_notify_escan_complete(wl, wl->escan_info.ndev, true);
+ }
+
+ } else
wl_notify_iscan_complete(wl_to_iscan(wl), true);
}
}
@@ -6724,11 +7122,23 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
struct net_device *dev = ndev;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wl_priv *wl = wlcfg_drv_priv;
+ int refcnt = 0;
WL_DBG(("Enter \n"));
if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
return NOTIFY_DONE;
switch (state) {
+ case NETDEV_DOWN:
+ while(work_pending(&wdev->cleanup_work)) {
+ WL_ERR(("%s : [NETDEV_DOWN] work_pending (%d th)\n",
+ __FUNCTION__, refcnt));
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(100);
+ set_current_state(TASK_RUNNING);
+ refcnt++;
+ }
+ break;
+
case NETDEV_UNREGISTER:
/* after calling list_del_rcu(&wdev->list) */
wl_dealloc_netinfo(wl, ndev);
@@ -6741,6 +7151,7 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
* make the scan done forcibly.
*/
if (wl_get_drv_status(wl, SCANNING, dev)) {
+ WL_SCAN2(("Abort Scan and send result\n"));
wl_cfg80211_scan_abort(wl, dev);
if (wl->escan_on) {
wl_notify_escan_complete(wl, dev, true);
@@ -6760,19 +7171,36 @@ static void wl_notify_escan_complete(struct wl_priv *wl,
unsigned long flags;
WL_DBG(("Enter \n"));
+
if (wl->escan_info.ndev != ndev)
+ {
+ WL_SCAN2(("ndev is different %p %p\n", wl->escan_info.ndev, ndev));
return;
-
+ }
wl_clr_drv_status(wl, SCANNING, ndev);
if (p2p_is_on(wl))
wl_clr_p2p_status(wl, SCANNING);
+ if(likely(wl->scan_request)) {
+ u8 temp_id = wl->escan_info.cur_sync_id;
+ if (aborted)
+ wl->bss_list =
+ (wl_scan_results_t *)wl->escan_info.escan_buf[(temp_id+1)%2];
+ else
+ wl->bss_list =
+ (wl_scan_results_t *)wl->escan_info.escan_buf[(temp_id)%2];
+ wl_inform_bss(wl);
+ }
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
if (likely(wl->scan_request)) {
cfg80211_scan_done(wl->scan_request, aborted);
wl->scan_request = NULL;
+ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ }
+ else {
+ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ WL_SCAN2(("no scan request is existed\n"));
}
- spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
WL_DBG(("Exit \n"));
}
@@ -6832,13 +7260,15 @@ static s32 wl_escan_handler(struct wl_priv *wl,
goto exit;
}
- if (escan_result->sync_id != wl->escan_info.cur_sync_id)
+ if (dtoh16(escan_result->sync_id) != wl->escan_info.cur_sync_id) {
WL_ERR(("Escan sync id mismatch: status %d cur_sync_id %d coming_sync_id %d\n"
- , status, wl->escan_info.cur_sync_id, escan_result->sync_id));
+ , status, wl->escan_info.cur_sync_id, dtoh16(escan_result->sync_id)));
+ goto exit;
+ }
if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
- WL_ERR(("Ignoring IBSS result\n"));
+ WL_DBG(("Ignoring IBSS result\n"));
goto exit;
}
}
@@ -6859,6 +7289,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
}
} else {
+ int cur_len = 0;
list = (wl_scan_results_t *)wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2];
if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
WL_ERR(("Buffer is too small: ignoring\n"));
@@ -6868,11 +7299,29 @@ static s32 wl_escan_handler(struct wl_priv *wl,
for (i = 0; i < list->count; i++) {
bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
: list->bss_info;
-
if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
CHSPEC_BAND(bi->chanspec) == CHSPEC_BAND(bss->chanspec) &&
bi->SSID_len == bss->SSID_len &&
- !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
+ !bcmp(bi->SSID, bss->SSID, bi->SSID_len)
+ && (bi->length == bss->length)) {
+ if (p2p_is_on(wl) && p2p_scan(wl)) {
+ if (bss->dtoh32(ie_length)< bi_length) {
+ int prev_len = dtoh32(bss->length);
+ WL_SCAN2(("bss info replacement is occured(bcast:%d->probresp%d)\n",
+ bss->ie_length, bi->ie_length));
+ /* prev : broadcast, cur : prob_resp */
+ if (list->count != 1 && i < list->count -1) {
+ /* memory copy required by this case only */
+ memcpy((u8 *)bss,
+ (u8 *)bss + prev_len, list->buflen - cur_len - prev_len);
+ }
+ list->buflen -= prev_len;
+ memcpy(&(((u8 *)list)[list->buflen]), bi, bi_length);
+ list->version = dtoh32(bi->version);
+ list->buflen += bi_length;
+ goto exit;
+ }
+ }
if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
(bi->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
/* preserve max RSSI if the measurements are
@@ -6890,6 +7339,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
goto exit;
}
+ cur_len += dtoh32(bss->length);
}
memcpy(&(wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2][list->buflen]), bi, bi_length);
list->version = dtoh32(bi->version);
@@ -6901,9 +7351,9 @@ static s32 wl_escan_handler(struct wl_priv *wl,
}
else if (status == WLC_E_STATUS_SUCCESS) {
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
- if (escan_result->sync_id != wl->escan_info.cur_sync_id)
+ if (dtoh16(escan_result->sync_id) != wl->escan_info.cur_sync_id)
WL_ERR(("Escan sync id mismatch: status %d cur_sync_id %d coming_sync_id %d\n"
- , status, wl->escan_info.cur_sync_id, escan_result->sync_id));
+ , status, wl->escan_info.cur_sync_id, dtoh16(escan_result->sync_id)));
if (wl_get_drv_status_all(wl, SCANNING_PEER_CHANNEL)) {
WL_INFO(("ACTION FRAME SCAN DONE\n"));
wl_clr_p2p_status(wl, SCANNING);
@@ -6913,9 +7363,12 @@ static s32 wl_escan_handler(struct wl_priv *wl,
} else if (likely(wl->scan_request)) {
mutex_lock(&wl->usr_sync);
del_timer_sync(&wl->scan_timeout);
- WL_INFO(("ESCAN COMPLETED\n"));
+ WL_SCAN2(("ESCAN COMPLETED\n"));
+#ifndef CUSTOMER_HW_SAMSUNG
+#error bss list is informed at notify function
wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2];
wl_inform_bss(wl);
+#endif
wl_notify_escan_complete(wl, ndev, false);
mutex_unlock(&wl->usr_sync);
}
@@ -6923,9 +7376,9 @@ static s32 wl_escan_handler(struct wl_priv *wl,
}
else if (status == WLC_E_STATUS_ABORT) {
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
- if (escan_result->sync_id!=wl->escan_info.cur_sync_id)
+ if (dtoh16(escan_result->sync_id) !=wl->escan_info.cur_sync_id)
WL_ERR(("Escan sync id mismatch: status %d cur_sync_id %d coming_sync_id %d\n"
- , status, wl->escan_info.cur_sync_id, escan_result->sync_id));
+ , status, wl->escan_info.cur_sync_id, dtoh16(escan_result->sync_id)));
if (wl_get_drv_status_all(wl, SCANNING_PEER_CHANNEL)) {
WL_INFO(("ACTION FRAME SCAN DONE\n"));
wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
@@ -6935,9 +7388,12 @@ static s32 wl_escan_handler(struct wl_priv *wl,
} else if (likely(wl->scan_request)) {
mutex_lock(&wl->usr_sync);
del_timer_sync(&wl->scan_timeout);
- WL_INFO(("ESCAN ABORTED\n"));
+ WL_SCAN2(("ESCAN ABORTED\n"));
+#ifndef CUSTOMER_HW_SAMSUNG
+#error bss list is informed at notify function
wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf[(wl->escan_info.cur_sync_id+1)%2];
wl_inform_bss(wl);
+#endif
wl_notify_escan_complete(wl, ndev, true);
mutex_unlock(&wl->usr_sync);
}
@@ -6946,9 +7402,9 @@ static s32 wl_escan_handler(struct wl_priv *wl,
else {
WL_ERR(("unexpected Escan Event %d : abort\n", status));
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
- if (escan_result->sync_id!=wl->escan_info.cur_sync_id)
+ if (dtoh16(escan_result->sync_id) != wl->escan_info.cur_sync_id)
WL_ERR(("Escan sync id mismatch: status %d cur_sync_id %d coming_sync_id %d\n"
- , status, wl->escan_info.cur_sync_id, escan_result->sync_id));
+ , status, wl->escan_info.cur_sync_id, dtoh16(escan_result->sync_id)));
if (wl_get_drv_status_all(wl, SCANNING_PEER_CHANNEL)) {
WL_INFO(("ACTION FRAME SCAN DONE\n"));
wl_clr_p2p_status(wl, SCANNING);
@@ -6958,8 +7414,11 @@ static s32 wl_escan_handler(struct wl_priv *wl,
} else if (likely(wl->scan_request)) {
mutex_lock(&wl->usr_sync);
del_timer_sync(&wl->scan_timeout);
+#ifndef CUSTOMER_HW_SAMSUNG
+#error bss list is informed at notify function
wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf[(wl->escan_info.cur_sync_id+1)%2];
wl_inform_bss(wl);
+#endif
wl_notify_escan_complete(wl, ndev, true);
mutex_unlock(&wl->usr_sync);
}
@@ -6968,7 +7427,79 @@ static s32 wl_escan_handler(struct wl_priv *wl,
exit:
return err;
}
-
+static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, enum wl_status state, bool set)
+{
+ s32 pm = PM_FAST;
+ s32 err = BCME_OK;
+ struct net_info *iter, *next;
+ if (set) { /* set */
+ switch (state) {
+ case WL_STATUS_CONNECTED: {
+ if (wl_get_drv_status_all(wl, CONNECTED) > 1) {
+ wl->vsdb_mode = true;
+ pm = PM_OFF;
+ WL_INFO(("Do not enable the power save for VSDB mode\n"));
+ } else if (_net_info->pm_block) {
+ pm = PM_OFF;
+ } else {
+ pm = PM_FAST;
+ }
+ for_each_ndev(wl, iter, next) {
+ if (!wl->vsdb_mode && (iter->ndev != _net_info->ndev))
+ continue;
+ if (wl_get_drv_status(wl, CONNECTED, iter->ndev) &&
+ (wl_get_mode_by_netdev(wl, iter->ndev) == WL_MODE_BSS)) {
+ pm = htod32(pm);
+ WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
+ err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, sizeof(pm), true);
+ if (unlikely(err)) {
+ if (err == -ENODEV)
+ WL_DBG(("net_device is not ready yet\n"));
+ else
+ WL_ERR(("error (%d)\n", err));
+ break;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ } else { /* clear */
+ switch (state) {
+ case WL_STATUS_CONNECTED: {
+ if (wl_get_drv_status_all(wl, CONNECTED) == 1) {
+ wl->vsdb_mode = false;
+ for_each_ndev(wl, iter, next) {
+ if (wl_get_drv_status(wl, CONNECTED, iter->ndev) &&
+ (wl_get_mode_by_netdev(wl, iter->ndev) == WL_MODE_BSS)) {
+ if (wl_get_netinfo_by_netdev(wl, iter->ndev)->pm_block)
+ pm = PM_OFF;
+ else
+ pm = PM_FAST;
+ pm = htod32(pm);
+ WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
+ err = wldev_ioctl(iter->ndev, WLC_SET_PM,
+ &pm, sizeof(pm), true);
+ if (unlikely(err)) {
+ if (err == -ENODEV)
+ WL_DBG(("net_device is not ready yet\n"));
+ else
+ WL_ERR(("error (%d)\n", err));
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return err;
+}
static s32 wl_init_scan(struct wl_priv *wl)
{
struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
@@ -7019,10 +7550,13 @@ static s32 wl_init_priv(struct wl_priv *wl)
wl->rf_blocked = false;
wl->first_remain = true;
wl->wlfc_on = false;
+ /* register interested state */
+ set_bit(WL_STATUS_CONNECTED, &wl->interrested_state);
spin_lock_init(&wl->cfgdrv_lock);
mutex_init(&wl->ioctl_buf_sync);
init_waitqueue_head(&wl->netif_change_event);
- init_waitqueue_head(&wl->send_af_done_event);
+ init_completion(&wl->send_af_done);
+ init_completion(&wl->iface_disable);
wl_init_eq(wl);
err = wl_init_priv_mem(wl);
if (err)
@@ -7168,7 +7702,8 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
ndev->ieee80211_ptr = wdev;
SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
wdev->netdev = ndev;
- err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS);
+ wl->state_notifier = wl_notifier_change_state;
+ err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE);
if (err) {
WL_ERR(("Failed to alloc net_info (%d)\n", err));
goto cfg80211_attach_out;
@@ -7178,7 +7713,6 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
WL_ERR(("Failed to init iwm_priv (%d)\n", err));
goto cfg80211_attach_out;
}
-
err = wl_setup_rfkill(wl, TRUE);
if (err) {
WL_ERR(("Failed to setup rfkill %d\n", err));
@@ -7227,8 +7761,10 @@ void wl_cfg80211_detach(void *para)
wl_cfg80211_detach_p2p();
#endif
wl_setup_rfkill(wl, FALSE);
- if (wl->p2p_supported)
- wl_cfgp2p_deinit_priv(wl);
+ if (wl->p2p_supported) {
+ WL_ERR(("wl_cfgp2p_down() is not called yet\n"));
+ wl_cfgp2p_down(wl);
+ }
wl_deinit_priv(wl);
wlcfg_drv_priv = NULL;
wl_cfg80211_clear_parent_dev();
@@ -7293,12 +7829,13 @@ static s32 wl_event_handler(void *data)
wl = (struct wl_priv *)tsk->parent;
DAEMONIZE("dhd_cfg80211_event");
complete(&tsk->completed);
+ WL_ERR(("%s: tsk completed\n", __func__));
while ((ret = down_interruptible (&tsk->sema)) == 0) {
WL_DBG(("down the event sema\n"));
SMP_RD_BARRIER_DEPENDS();
if (tsk->terminated) {
- WL_ERR(("%s was terminated[%d] ret=%d\n",
+ WL_DBG(("%s was terminated[%d] ret=%d\n",
__func__, __LINE__, ret));
break;
}
@@ -7336,6 +7873,9 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
{
u32 event_type = ntoh32(e->event_type);
struct wl_priv *wl = wlcfg_drv_priv;
+#if defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK)
+ int pno_wakelock_timeout = 10; /* 10 second */
+#endif
#if (WL_DBG_LEVEL > 0)
s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
@@ -7344,7 +7884,12 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
#endif /* (WL_DBG_LEVEL > 0) */
if (event_type == WLC_E_PFN_NET_FOUND)
- WL_ERR((" PNOEVENT: PNO_NET_FOUND\n"));
+ {
+#if defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK)
+ net_os_wake_lock_timeout_for_pno(ndev, pno_wakelock_timeout);
+#endif
+ WL_ERR((" PNO Event\n"));
+ }
else if (event_type == WLC_E_PFN_NET_LOST)
WL_ERR((" PNOEVENT: PNO_NET_LOST\n"));
@@ -7509,31 +8054,187 @@ eventmsg_out:
}
+static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
+{
+ struct net_device *dev = wl_to_prmry_ndev(wl);
+ struct ieee80211_channel *band_chan_arr = NULL;
+ wl_uint32_list_t *list;
+ u32 i, j, index, n_2g, n_5g, band, channel, array_size;
+ u32 *n_cnt = NULL;
+ chanspec_t c = 0;
+ s32 err = BCME_OK;
+ bool update;
+ bool ht40_allowed;
+ u8 *pbuf = NULL;
+#define LOCAL_BUF_LEN 1024
+ pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
+
+ if (pbuf == NULL) {
+ WL_ERR(("failed to allocate local buf\n"));
+ return -ENOMEM;
+ }
+ list = (wl_uint32_list_t *)(void *) pbuf;
+ list->count = htod32(WL_NUMCHANSPECS);
+
+
+ err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
+ 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
+ if (err != 0) {
+ WL_ERR(("get chanspecs failed with %d\n", err));
+ kfree(pbuf);
+ return err;
+ }
+#undef LOCAL_BUF_LEN
+ list = (wl_uint32_list_t *)(void *)pbuf;
+ band = array_size = n_2g = n_5g = 0;
+ for (i = 0; i < dtoh32(list->count); i++) {
+ index = 0;
+ update = false;
+ ht40_allowed = false;
+ c = (chanspec_t)dtoh32(list->element[i]);
+ channel = CHSPEC_CHANNEL(c);
+ if (CHSPEC_IS40(c)) {
+ if (CHSPEC_SB_UPPER(c))
+ channel += CH_10MHZ_APART;
+ else
+ channel -= CH_10MHZ_APART;
+ }
+ if (CHSPEC_IS2G(c) && channel <= CH_MAX_2G_CHANNEL) {
+ band_chan_arr = __wl_2ghz_channels;
+ array_size = ARRAYSIZE(__wl_2ghz_channels);
+ n_cnt = &n_2g;
+ band = IEEE80211_BAND_2GHZ;
+ ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
+ } else if (CHSPEC_IS5G(c) && channel > CH_MAX_2G_CHANNEL) {
+ band_chan_arr = __wl_5ghz_a_channels;
+ array_size = ARRAYSIZE(__wl_5ghz_a_channels);
+ n_cnt = &n_5g;
+ band = IEEE80211_BAND_5GHZ;
+ ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
+ }
+ for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
+ if (band_chan_arr[j].hw_value == channel) {
+ update = true;
+ break;
+ }
+ }
+ if (update)
+ index = j;
+ else
+ index = *n_cnt;
+ if (index < array_size) {
+ band_chan_arr[index].center_freq =
+ ieee80211_channel_to_frequency(channel, band);
+ band_chan_arr[index].hw_value = channel;
+
+ if (CHSPEC_IS40(c) && ht40_allowed) {
+ /* assuming the order is HT20, HT40 Upper, HT40 lower from chanspecs */
+ u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
+ if (CHSPEC_SB_UPPER(c)) {
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
+ band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
+ } else {
+ /* It should be one of
+ IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
+ */
+ band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40MINUS;
+ }
+ } else {
+ band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
+ if (band == IEEE80211_BAND_2GHZ)
+ channel |= WL_CHANSPEC_BAND_2G;
+ else
+ channel |= WL_CHANSPEC_BAND_5G;
+ err = wldev_iovar_getint(dev, "per_chan_info", &channel);
+ if (!err) {
+ if (channel & WL_CHAN_RADAR)
+ band_chan_arr[index].flags |= (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS);
+ if (channel & WL_CHAN_PASSIVE)
+ band_chan_arr[index].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+ }
+ }
+ if (!update)
+ (*n_cnt)++;
+ }
+
+ }
+ __wl_band_2ghz.n_channels = n_2g;
+ __wl_band_5ghz_a.n_channels = n_5g;
+ kfree(pbuf);
+ return err;
+}
+
s32 wl_update_wiphybands(struct wl_priv *wl)
{
struct wiphy *wiphy;
+ struct net_device *dev;
u32 bandlist[3];
u32 nband = 0;
u32 i = 0;
s32 err = 0;
+ s32 index = 0;
+ s32 nmode = 0;
+ s32 bw_cap = 0;
+ if (wl == NULL)
+ wl = wlcfg_drv_priv;
+ dev = wl_to_prmry_ndev(wl);
+
+
memset(bandlist, 0, sizeof(bandlist));
- err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist,
+ err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
sizeof(bandlist), false);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
return err;
}
+ err = wldev_iovar_getint(dev, "nmode", &nmode);
+ if (err) {
+ return err;
+ }
+
+ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+ if (err) {
+ return err;
+ }
+
+ err = wl_construct_reginfo(wl, bw_cap);
+ if (err) {
+ WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
+ return err;
+ }
+
wiphy = wl_to_wiphy(wl);
nband = bandlist[0];
wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
- for (i = 1; i <= nband && i < sizeof(bandlist); i++) {
- if (bandlist[i] == WLC_BAND_5G)
+ for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
+ index = -1;
+ if (bandlist[i] == WLC_BAND_5G) {
wiphy->bands[IEEE80211_BAND_5GHZ] =
&__wl_band_5ghz_a;
- else if (bandlist[i] == WLC_BAND_2G)
+ index = IEEE80211_BAND_5GHZ;
+ if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
+ wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+ }
+ else if (bandlist[i] == WLC_BAND_2G) {
wiphy->bands[IEEE80211_BAND_2GHZ] =
&__wl_band_2ghz;
+ index = IEEE80211_BAND_2GHZ;
+ if (bw_cap == WLC_N_BW_40ALL)
+ wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+
+ }
+ if ((index >= 0) && nmode) {
+ wiphy->bands[index]->ht_cap.cap |=
+ (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
+ wiphy->bands[index]->ht_cap.ht_supported = TRUE;
+ wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+ }
+
}
wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
return err;
@@ -7581,11 +8282,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
wl_term_iscan(wl);
- spin_lock_irqsave(&wl->cfgdrv_lock, flags);
- if (wl->scan_request) {
- cfg80211_scan_done(wl->scan_request, true);
- wl->scan_request = NULL;
- }
+
for_each_ndev(wl, iter, next) {
wl_clr_drv_status(wl, READY, iter->ndev);
wl_clr_drv_status(wl, SCANNING, iter->ndev);
@@ -7596,6 +8293,11 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
}
+ spin_lock_irqsave(&wl->cfgdrv_lock, flags);
+ if (wl->scan_request) {
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ }
wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
NL80211_IFTYPE_STATION;
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
@@ -7615,6 +8317,7 @@ s32 wl_cfg80211_up(void *para)
struct wl_priv *wl;
s32 err = 0;
int val = 1;
+ dhd_pub_t *dhd;
(void)para;
WL_TRACE(("In\n"));
@@ -7635,7 +8338,10 @@ s32 wl_cfg80211_up(void *para)
WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
mutex_lock(&wl->usr_sync);
- wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
+ dhd = (dhd_pub_t *)(wl->pub);
+ if ((dhd->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) {
+ wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
+ }
err = __wl_cfg80211_up(wl);
if (err)
WL_ERR(("__wl_cfg80211_up failed\n"));
@@ -7741,11 +8447,14 @@ wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
profile->dtim_period = *(u8 *)data;
break;
default:
- WL_ERR(("unsupported item (%d)\n", item));
err = -EOPNOTSUPP;
break;
}
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+
+ if (err == EOPNOTSUPP)
+ WL_ERR(("unsupported item (%d)\n", item));
+
return err;
}
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h
index 9880fea975c..503d3eb31e7 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h
@@ -52,6 +52,7 @@ struct wl_ibss;
#define dtohchanspec(i) i
#define WL_DBG_NONE 0
+#define WL_DBG_SCAN2 (1 <<5)
#define WL_DBG_TRACE (1 << 4)
#define WL_DBG_SCAN (1 << 3)
#define WL_DBG_DBG (1 << 2)
@@ -64,7 +65,7 @@ struct wl_ibss;
#define WL_ERR(args) \
do { \
if (wl_dbg_level & WL_DBG_ERR) { \
- printk(KERN_ERR "CFG80211-ERROR) %s : ", __func__); \
+ printk(KERN_ERR "CFG80211-INF02) %s : ", __func__); \
printk args; \
} \
} while (0)
@@ -111,12 +112,23 @@ do { \
#endif /* (WL_DBG_LEVEL > 0) */
+#if (WL_DBG_LEVEL > 0)
+#define WL_SCAN2(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_SCAN2) { \
+ printk(KERN_ERR "CFG80211-SCAN) %s :", __func__); \
+ printk args; \
+ } \
+} while (0)
+#else /* !(WL_DBG_LEVEL > 0) */
+#define WL_DBG(args)
+#endif /* (WL_DBG_LEVEL > 0) */
+
#define WL_SCAN_RETRY_MAX 3
#define WL_NUM_PMKIDS_MAX MAXPMKID
#define WL_SCAN_BUF_MAX (1024 * 8)
-/* customer want to large size IE, so increase ie length */
-#define WL_TLV_INFO_MAX 1500
-#define WL_SCAN_IE_LEN_MAX 2048
+#define WL_TLV_INFO_MAX 1500 /* customer want to large size IE, so increase ie length */
+#define WL_SCAN_IE_LEN_MAX 2048
#define WL_BSS_INFO_MAX 2048
#define WL_ASSOC_INFO_MAX 512
#define WL_IOCTL_LEN_MAX 1024
@@ -126,14 +138,15 @@ do { \
#define WL_SCAN_ERSULTS_LAST (WL_SCAN_RESULTS_NO_MEM+1)
#define WL_AP_MAX 256
#define WL_FILE_NAME_MAX 256
-#define WL_DWELL_TIME 200
-#define WL_MED_DWELL_TIME 400
-#define WL_LONG_DWELL_TIME 1000
-#define IFACE_MAX_CNT 2
+#define WL_DWELL_TIME 200
+#define WL_MED_DWELL_TIME 400
+#define WL_LONG_DWELL_TIME 1000
+#define IFACE_MAX_CNT 2
+#define WL_SCAN_CONNECT_DWELL_TIME_MS 100
#define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */
#define WL_CHANNEL_SYNC_RETRY 5
-#define WL_INVALID -1
+#define WL_INVALID -1
/* driver status */
enum wl_status {
@@ -294,6 +307,7 @@ struct net_info {
struct wl_profile profile;
s32 mode;
unsigned long sme_state;
+ bool pm_block;
struct list_head list; /* list of all net_info structure */
};
typedef s32(*ISCAN_HANDLER) (struct wl_priv *wl);
@@ -399,6 +413,7 @@ struct afx_hdl {
s32 my_listen_chan; /* my listen channel in GON Req frame */
bool is_listen;
bool ack_recv;
+ bool is_active;
};
/* private data of cfg80211 interface */
@@ -416,6 +431,7 @@ struct wl_priv {
spinlock_t eq_lock; /* for event queue synchronization */
spinlock_t cfgdrv_lock; /* to protect scan status (and others if needed) */
struct completion act_frm_scan;
+ struct completion iface_disable;
#ifdef WL_CFG80211_SYNC_GON_TIME
struct completion wait_next_af;
#endif /* WL_CFG80211_SYNC_GON_TIME */
@@ -458,6 +474,7 @@ struct wl_priv {
bool roam_on; /* on/off switch for self-roaming */
bool scan_tried; /* indicates if first scan attempted */
bool wlfc_on;
+ bool vsdb_mode;
u8 *ioctl_buf; /* ioctl buffer */
struct mutex ioctl_buf_sync;
u8 *escan_ioctl_buf;
@@ -470,7 +487,7 @@ struct wl_priv {
u64 send_action_id;
u64 last_roc_id;
wait_queue_head_t netif_change_event;
- wait_queue_head_t send_af_done_event;
+ struct completion send_af_done;
struct afx_hdl *afx_hdl;
struct ap_info *ap_info;
struct sta_info *sta_info;
@@ -483,6 +500,8 @@ struct wl_priv {
u8 block_gon_req_tx_count;
u8 block_gon_req_rx_count;
#endif /* WL_CFG80211_GON_COLLISION */
+ s32 (*state_notifier) (struct wl_priv *wl, struct net_info *_net_info, enum wl_status state, bool set);
+ unsigned long interrested_state;
};
@@ -493,7 +512,7 @@ static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct
}
static inline s32
wl_alloc_netinfo(struct wl_priv *wl, struct net_device *ndev,
- struct wireless_dev * wdev, s32 mode)
+ struct wireless_dev * wdev, s32 mode, bool pm_block)
{
struct net_info *_net_info;
s32 err = 0;
@@ -506,6 +525,7 @@ wl_alloc_netinfo(struct wl_priv *wl, struct net_device *ndev,
_net_info->mode = mode;
_net_info->ndev = ndev;
_net_info->wdev = wdev;
+ _net_info->pm_block = pm_block;
wl->iface_cnt++;
list_add(&_net_info->list, &wl->net_list);
}
@@ -542,7 +562,7 @@ wl_delete_all_netinfo(struct wl_priv *wl)
}
wl->iface_cnt = 0;
}
-static inline bool
+static inline u32
wl_get_status_all(struct wl_priv *wl, s32 status)
{
@@ -553,23 +573,87 @@ wl_get_status_all(struct wl_priv *wl, s32 status)
test_bit(status, &_net_info->sme_state))
cnt++;
}
- return cnt? true: false;
+ return cnt;
+}
+
+static inline void
+wl_set_status_all(struct wl_priv *wl, s32 status, u32 op)
+{
+ struct net_info *_net_info, *next;
+ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) {
+ switch (op) {
+ case 1:
+ return; /* set all status is not allowed */
+ case 2:
+ clear_bit(status, &_net_info->sme_state);
+ if (wl->state_notifier && test_bit(status, &(wl->interrested_state)))
+ wl->state_notifier(wl, _net_info, status, false);
+ break;
+ case 4:
+ return; /* change all status is not allowed */
+ default:
+ return; /*unknown operation */
+ }
+ }
+}
+#define wl_set_status_by_netdev(wl, status, _ndev, op) \
+{ \
+ struct net_info *_net_info, *next;\
+ int found = 0;\
+ list_for_each_entry_safe(_net_info, next, &(wl)->net_list, list) {\
+ if(_ndev && ((_net_info->ndev) == _ndev)) { \
+ found = 1;\
+ switch(op){\
+ case 1: \
+ set_bit(status, &(_net_info->sme_state));\
+ if (wl->state_notifier && test_bit(status, &(wl->interrested_state))) \
+ wl->state_notifier(wl, _net_info, status, true); \
+ if(status == WL_STATUS_SCANNING)\
+ WL_SCAN2(("<<<Set SCANNING bit %p>>>\n", _ndev));\
+ break;\
+ case 2:\
+ clear_bit(status, &(_net_info->sme_state)); \
+ if (wl->state_notifier && test_bit(status, &(wl->interrested_state))) \
+ wl->state_notifier(wl, _net_info, status, false); \
+ if(status == WL_STATUS_SCANNING) \
+ WL_SCAN2(("<<<Clear SCANNING bit %p>>>\n", _ndev)); \
+ break;\
+ case 4:\
+ change_bit(status, &(_net_info->sme_state));\
+ break;\
+ }\
+ }\
+ }\
+ if(found == 0)\
+ WL_ERR(("<<<Set Status command with not eixst device %p>>>\n", _ndev));\
}
+
+#if 0
static inline void
wl_set_status_by_netdev(struct wl_priv *wl, s32 status,
struct net_device *ndev, u32 op)
{
struct net_info *_net_info, *next;
+ int found = 0;
list_for_each_entry_safe(_net_info, next, &wl->net_list, list) {
if (ndev && (_net_info->ndev == ndev)) {
+ found = 1;
switch (op) {
case 1:
set_bit(status, &_net_info->sme_state);
+#if (WL_DBG_LEVEL > 0)
+ if(status == WL_STATUS_SCANNING )
+ WL_SCAN2(("<<<Set SCANNING bit %p >>>\n", ndev));
+#endif
break;
case 2:
clear_bit(status, &_net_info->sme_state);
+#if (WL_DBG_LEVEL > 0)
+ if(status == WL_STATUS_SCANNING )
+ WL_SCAN2(("<<<Clear SCANNING bit %p >>>\n", ndev));
+#endif
break;
case 4:
change_bit(status, &_net_info->sme_state);
@@ -578,9 +662,11 @@ wl_set_status_by_netdev(struct wl_priv *wl, s32 status,
}
}
+ if(found ==0 )
+ WL_ERR(("<<Set Status command with not exist device %p>>\n", ndev));
}
-
+#endif
static inline u32
wl_get_status_by_netdev(struct wl_priv *wl, s32 status,
struct net_device *ndev)
@@ -629,6 +715,17 @@ wl_get_profile_by_netdev(struct wl_priv *wl, struct net_device *ndev)
}
return NULL;
}
+static inline struct net_info *
+wl_get_netinfo_by_netdev(struct wl_priv *wl, struct net_device *ndev)
+{
+ struct net_info *_net_info, *next;
+
+ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) {
+ if (ndev && (_net_info->ndev == ndev))
+ return _net_info;
+ }
+ return NULL;
+}
#define wl_to_wiphy(w) (w->wdev->wiphy)
#define wl_to_prmry_ndev(w) (w->wdev->netdev)
#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr))
@@ -646,6 +743,8 @@ wl_get_profile_by_netdev(struct wl_priv *wl, struct net_device *ndev)
(wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 1))
#define wl_clr_drv_status(wl, stat, ndev) \
(wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 2))
+#define wl_clr_drv_status_all(wl, stat) \
+ (wl_set_status_all(wl, WL_STATUS_ ## stat, 2))
#define wl_chg_drv_status(wl, stat, ndev) \
(wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 4))
@@ -693,7 +792,7 @@ extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
extern s32 wl_mode_to_nl80211_iftype(s32 mode);
int wl_cfg80211_do_driver_init(struct net_device *net);
void wl_cfg80211_enable_trace(int level);
-
+extern s32 wl_update_wiphybands(struct wl_priv *wl);
/* do scan abort */
extern s32 wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev);
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c
index c9218bd84fd..e9d68548141 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c
@@ -134,12 +134,12 @@ void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len)
wifi_p2p_pub_act_frame_t *pact_frm;
wifi_p2p_action_frame_t *act_frm;
wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
- if (!frame || frame_len <= 2)
+ if(!frame || frame_len <= 2)
return;
if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
- switch (pact_frm->subtype) {
+ switch(pact_frm->subtype) {
case P2P_PAF_GON_REQ:
CFGP2P_ERR(("%s P2P Group Owner Negotiation Req Frame\n",
(tx)? "TX": "RX"));
@@ -208,7 +208,7 @@ void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len)
} else if (wl_cfgp2p_is_gas_action(frame, frame_len)) {
sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
- switch (sd_act_frm->action) {
+ switch(sd_act_frm->action) {
case P2PSD_ACTION_ID_GAS_IREQ:
CFGP2P_ERR(("%s P2P GAS Initial Request\n",
(tx)? "TX" : "RX"));
@@ -307,13 +307,19 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl)
wldev_iovar_getint(ndev, "apsta", &val);
if (val == 0) {
val = 1;
- wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
+ ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
+ if (ret < 0) {
+ CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
+ return ret;
+ }
wldev_iovar_setint(ndev, "apsta", val);
- wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
+ ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
+ if (ret < 0) {
+ CFGP2P_ERR(("WLC_UP error %d\n", ret));
+ return ret;
+ }
}
- val = 1;
- /* Disable firmware roaming for P2P */
- wldev_iovar_setint(ndev, "roam_off", val);
+
/* In case of COB type, firmware has default mac address
* After Initializing firmware, we have to set current mac address to
* firmware for P2P device address
@@ -339,7 +345,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
{
wl_p2p_if_t ifreq;
s32 err;
- u32 scb_timeout = 10;
+ u32 scb_timeout=10;
struct net_device *ndev = wl_to_prmry_ndev(wl);
ifreq.type = if_type;
@@ -366,6 +372,28 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
return err;
}
+/* Disable a P2P BSS.
+ * Parameters:
+ * @mac : MAC address of the BSS to create
+ * Returns 0 if success.
+ */
+s32
+wl_cfgp2p_ifdisable(struct wl_priv *wl, struct ether_addr *mac)
+{
+ s32 ret;
+ struct net_device *netdev = wl_to_prmry_ndev(wl);
+
+ CFGP2P_INFO(("------primary idx %d : wl p2p_ifdis %02x:%02x:%02x:%02x:%02x:%02x\n",
+ netdev->ifindex, mac->octet[0], mac->octet[1], mac->octet[2],
+ mac->octet[3], mac->octet[4], mac->octet[5]));
+ ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
+ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
+ if (unlikely(ret < 0)) {
+ printk("'wl p2p_ifdis' error %d\n", ret);
+ }
+ return ret;
+}
+
/* Delete a P2P BSS.
* Parameters:
* @mac : MAC address of the BSS to create
@@ -399,7 +427,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
{
wl_p2p_if_t ifreq;
s32 err;
- u32 scb_timeout = 10;
+ u32 scb_timeout=10;
struct net_device *netdev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
ifreq.type = if_type;
@@ -408,9 +436,9 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
CFGP2P_INFO(("---wl p2p_ifchange %02x:%02x:%02x:%02x:%02x:%02x %s %u"
" chanspec 0x%04x\n",
- ifreq.addr.octet[0], ifreq.addr.octet[1], ifreq.addr.octet[2],
- ifreq.addr.octet[3], ifreq.addr.octet[4], ifreq.addr.octet[5],
- (if_type == WL_P2P_IF_GO) ? "go" : "client",
+ ifreq.addr.octet[0], ifreq.addr.octet[1], ifreq.addr.octet[2],
+ ifreq.addr.octet[3], ifreq.addr.octet[4], ifreq.addr.octet[5],
+ (if_type == WL_P2P_IF_GO) ? "go" : "client",
(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT,
ifreq.chspec));
@@ -449,7 +477,7 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index)
sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY), NULL);
if (ret == 0) {
- memcpy(index, getbuf, sizeof(index));
+ memcpy(index, getbuf, sizeof(s32));
CFGP2P_INFO(("---wl p2p_if ==> %d\n", *index));
}
@@ -488,8 +516,7 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms,
s32 ret;
struct net_device *dev;
CFGP2P_DBG(("enter\n"));
-
- if (unlikely(bssidx >= P2PAPI_BSSCFG_MAX)) {
+ if (unlikely(bssidx == WL_INVALID || bssidx >= P2PAPI_BSSCFG_MAX)) {
CFGP2P_ERR((" %d index out of range\n", bssidx));
return -1;
}
@@ -711,8 +738,8 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
#define P2PAPI_SCAN_DWELL_TIME_MS 80
#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
#define P2PAPI_SCAN_HOME_TIME_MS 60
-#define P2PAPI_SCAN_NPROBS_TIME_MS 25
-#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS (P2PAPI_SCAN_NPROBS_TIME_MS + 5)
+#define P2PAPI_SCAN_NPROBS_TIME_MS 30
+#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
//wl_set_p2p_status(wl, SCANNING);
@@ -767,12 +794,15 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t));
eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
- if (wl_get_drv_status_all(wl, CONNECTED))
- eparams->params.active_time = htod32(-1);
- else if (num_chans == SOCIAL_CHAN_CNT)
+
+ if (num_chans == SOCIAL_CHAN_CNT)
eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
else if (num_chans == AF_PEER_SEARCH_CNT)
eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS);
+ else if (num_chans == 1)
+ eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
+ else if (wl_get_drv_status_all(wl, CONNECTED))
+ eparams->params.active_time = -1;
else
eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
eparams->params.nprobes = htod32((eparams->params.active_time /
@@ -819,7 +849,7 @@ wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev,
s32 ret = 0;
u32 chan_cnt = 0;
u16 *default_chan_list = NULL;
- if (!p2p_is_on(wl))
+ if (!p2p_is_on(wl) || ndev == NULL || bssidx == WL_INVALID)
return -BCME_ERROR;
CFGP2P_DBG((" Enter\n"));
if (bssidx == P2PAPI_BSSCFG_PRIMARY)
@@ -865,7 +895,7 @@ exit:
#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
/* Check whether the given IE looks like WFA WFDisplay IE. */
-#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
+#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
@@ -984,7 +1014,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
ret = -ENOMEM;
} else {
if (mgmt_ie_buf != NULL) {
- if (vndr_ie_len && (vndr_ie_len == *mgmt_ie_len) &&
+ if (vndr_ie && vndr_ie_len && (vndr_ie_len == *mgmt_ie_len) &&
(memcmp(mgmt_ie_buf, vndr_ie, vndr_ie_len) == 0)) {
CFGP2P_INFO(("Previous mgmt IE is equals to current IE"));
goto exit;
@@ -1013,7 +1043,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
}
*mgmt_ie_len = 0;
/* Add if there is any extra IE */
- if (vndr_ie && vndr_ie_len) {
+ if (mgmt_ie_buf && vndr_ie && vndr_ie_len) {
/* save the current IE in wl struct */
memcpy(mgmt_ie_buf, vndr_ie, vndr_ie_len);
*mgmt_ie_len = vndr_ie_len;
@@ -1038,6 +1068,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
pos += ie_len;
}
}
+
}
#undef IE_TYPE
#undef IE_TYPE_LEN
@@ -1356,8 +1387,11 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
CFGP2P_DBG(("previous LISTEN is not completed yet\n"));
goto exit;
- } else
+ }
+#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ else
wl_clr_p2p_status(wl, LISTEN_EXPIRED);
+#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
@@ -1367,14 +1401,17 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
* otherwise we will wait up to duration_ms + 100ms + duration / 20
*/
if (ret == BCME_OK) {
- extra_delay = EXTRA_DEAY_TIME + (duration_ms / 20);
+ extra_delay = EXTRA_DEAY_TIME + (duration_ms / 10);
} else {
/* if failed to set listen, it doesn't need to wait whole duration. */
- duration_ms = 50 + duration_ms / 20;
+ duration_ms = 100 + duration_ms / 20;
extra_delay = 0;
}
INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, extra_delay);
+#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+ wl_clr_p2p_status(wl, LISTEN_EXPIRED);
+#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
#undef EXTRA_DEAY_TIME
exit:
@@ -1437,7 +1474,7 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
"status : %d\n", status));
if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
- wake_up_interruptible(&wl->send_af_done_event);
+ complete(&wl->send_af_done);
}
return ret;
}
@@ -1481,9 +1518,7 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
goto exit;
}
- timeout = wait_event_interruptible_timeout(wl->send_af_done_event,
- (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)),
- msecs_to_jiffies(MAX_WAIT_TIME));
+ timeout = wait_for_completion_timeout(&wl->send_af_done, msecs_to_jiffies(MAX_WAIT_TIME));
if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) {
CFGP2P_INFO(("tx action frame operation is completed\n"));
@@ -1492,6 +1527,10 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
ret = BCME_ERROR;
CFGP2P_INFO(("tx action frame operation is failed\n"));
}
+ /* clear status bit for action tx */
+ wl_clr_p2p_status(wl, ACTION_TX_COMPLETED);
+ wl_clr_p2p_status(wl, ACTION_TX_NOACK);
+
exit:
CFGP2P_INFO((" via act frame iovar : status = %d\n", ret));
#undef MAX_WAIT_TIME
@@ -1654,6 +1693,9 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev)
s32
wl_cfgp2p_down(struct wl_priv *wl)
{
+ if (wl->p2p == NULL)
+ return 0;
+
if (timer_pending(&wl->p2p->listen_timer))
del_timer_sync(&wl->p2p->listen_timer);
wl_cfgp2p_deinit_priv(wl);
@@ -1831,11 +1873,11 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
return 0;
}
- ie = (wifi_p2p_ie_t*) buf;
+ ie = (wifi_p2p_ie_t *) buf;
len = ie->len;
/* Point subel to the P2P IE's subelt field.
- * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
+ * Subtract the preceding fields (id,len,OUI,oui_type) from the length.
*/
subel = ie->subelts;
len -= 4; /* exclude OUI + OUI_TYPE */
@@ -1872,7 +1914,7 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
u8 *
wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
{
- wifi_p2p_ie_t * p2p_ie = NULL;
+ wifi_p2p_ie_t *p2p_ie = NULL;
u8 *capability = NULL;
bool p2p_go = 0;
u8 *ptr = NULL;
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h
index 182b0b2ecf1..bd4d388255f 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h
@@ -123,7 +123,7 @@ enum wl_cfgp2p_status {
#define CFGP2P_ERR(args) \
do { \
if (wl_dbg_level & WL_DBG_ERR) { \
- printk(KERN_ERR "CFGP2P-ERROR) %s : ", __func__); \
+ printk(KERN_ERR "CFGP2P-INF02) %s : ", __func__); \
printk args; \
} \
} while (0)
@@ -172,6 +172,8 @@ extern s32
wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
chanspec_t chspec);
extern s32
+wl_cfgp2p_ifdisable(struct wl_priv *wl, struct ether_addr *mac);
+extern s32
wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac);
extern s32
wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, chanspec_t chspec);
@@ -279,7 +281,7 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl);
#define SOCIAL_CHAN_2 6
#define SOCIAL_CHAN_3 11
#define SOCIAL_CHAN_CNT 3
-#define AF_PEER_SEARCH_CNT (SOCIAL_CHAN_CNT + 1)
+#define AF_PEER_SEARCH_CNT 2
#define WL_P2P_WILDCARD_SSID "DIRECT-"
#define WL_P2P_WILDCARD_SSID_LEN 7
#define WL_P2P_INTERFACE_PREFIX "p2p"
@@ -298,5 +300,5 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl);
(subtype == P2P_PAF_INVITE_RSP) || \
(subtype == P2P_PAF_PROVDIS_RSP)))
#define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3))
-#define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0)
+#define IS_P2P_SSID(ssid, len) (!memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) && (len == WL_P2P_WILDCARD_SSID_LEN))
#endif /* _wl_cfgp2p_h_ */
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_linux_mon.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_linux_mon.c
index dcdd83d9a00..8a29599ffc6 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_linux_mon.c
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_linux_mon.c
@@ -59,8 +59,15 @@ int dhd_monitor_uninit(void);
#ifndef DHD_MAX_IFS
#define DHD_MAX_IFS 16
#endif
-#define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__)
-#define MON_TRACE MON_PRINT
+
+#define MON_DEBUG 0
+#if MON_DEBUG
+ #define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__)
+ #define MON_TRACE MON_PRINT
+#else
+ #define MON_PRINT(format, ...)
+ #define MON_TRACE MON_PRINT
+#endif
typedef struct monitor_interface {
int radiotap_enabled;
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_roam.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_roam.c
index 9829b8f7fc4..5b77c5c94bd 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_roam.c
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_roam.c
@@ -2,13 +2,13 @@
* Linux Wireless Extensions support
*
* Copyright (C) 1999-2012, Broadcom Corporation
- *
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -16,7 +16,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -31,7 +31,6 @@
#define WL_DBG(x)
#define MAX_ROAM_CACHE 100
-#define WL_CHANSPEC_CTL_SB_NONE 0x0300 /*chanyun temp : fix chan spec*/
typedef struct {
chanspec_t chanspec;
@@ -40,8 +39,14 @@ typedef struct {
} roam_channel_cache;
static int n_roam_cache = 0;
+static int roam_band = WLC_BAND_AUTO;
static roam_channel_cache roam_cache[MAX_ROAM_CACHE];
+void set_roam_band(int band)
+{
+ roam_band = band;
+}
+
void reset_roam_cache(void)
{
n_roam_cache = 0;
@@ -55,10 +60,10 @@ void add_roam_cache(wl_bss_info_t *bi)
if (n_roam_cache == MAX_ROAM_CACHE)
return;
- for(i=0; i<n_roam_cache; i++) {
+ for (i = 0; i < n_roam_cache; i++) {
if ((roam_cache[i].ssid_len == bi->SSID_len) &&
- (roam_cache[i].chanspec == bi->chanspec) &&
- (memcmp(roam_cache[i].ssid, bi->SSID, bi->SSID_len) == 0)) {
+ (roam_cache[i].chanspec == bi->chanspec) &&
+ (memcmp(roam_cache[i].ssid, bi->SSID, bi->SSID_len) == 0)) {
/* identical one found, just return */
return;
}
@@ -74,7 +79,7 @@ void add_roam_cache(wl_bss_info_t *bi)
int get_roam_channel_list(int target_chan, chanspec_t *channels, const wlc_ssid_t *ssid)
{
- int i, n=1;
+ int i, n = 1;
uint band;
WL_DBG((" %s: %02d\n", __FUNCTION__, target_chan));
@@ -86,17 +91,18 @@ int get_roam_channel_list(int target_chan, chanspec_t *channels, const wlc_ssid_
*channels++ = (target_chan & WL_CHANSPEC_CHAN_MASK) | band | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
for(i=0; i<n_roam_cache; i++) {
+ chanspec_t ch = roam_cache[i].chanspec;
if ((roam_cache[i].ssid_len == ssid->SSID_len) &&
- ((roam_cache[i].chanspec & WL_CHANSPEC_CHAN_MASK) != target_chan) &&
+ ((ch & WL_CHANSPEC_CHAN_MASK) != target_chan) &&
+ ((roam_band == WLC_BAND_AUTO) || ((roam_band == WLC_BAND_2G) && CHSPEC_IS2G(ch)) || ((roam_band == WLC_BAND_5G) && CHSPEC_IS5G(ch))) &&
(memcmp(roam_cache[i].ssid, ssid->SSID, ssid->SSID_len) == 0)) {
/* match found, add it */
- *channels = roam_cache[i].chanspec & WL_CHANSPEC_CHAN_MASK;
- WL_DBG((" %s: %02d\n", __FUNCTION__, *channels));
+ *channels = ch & WL_CHANSPEC_CHAN_MASK;
if (*channels <= 14)
*channels |= WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
else
*channels |= WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
-
+ WL_DBG((" %s: %02d 0x%04X\n", __FUNCTION__, ch & WL_CHANSPEC_CHAN_MASK, *channels));
channels++; n++;
}
}
@@ -111,7 +117,7 @@ void print_roam_cache(void)
WL_DBG((" %d cache\n", n_roam_cache));
- for(i=0; i<n_roam_cache; i++) {
+ for (i = 0; i < n_roam_cache; i++) {
roam_cache[i].ssid[roam_cache[i].ssid_len] = 0;
WL_DBG(("0x%02X %02d %s\n", roam_cache[i].chanspec, roam_cache[i].ssid_len, roam_cache[i].ssid));
}
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c
index f46c061332b..d19d64d7840 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.c
@@ -220,7 +220,14 @@ s32 wldev_iovar_setbuf_bsscfg(
mutex_lock(buf_sync);
}
iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
- ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+ if (iovar_len > 0)
+ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+ else {
+ if (buf_sync) {
+ mutex_unlock(buf_sync);
+ }
+ return BCME_BUFTOOSHORT;
+ }
if (buf_sync) {
mutex_unlock(buf_sync);
}
diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.h b/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.h
index c383aab9f91..6f7f1d6f078 100644
--- a/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.h
+++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wldev_common.h
@@ -95,6 +95,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 wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid,
int max, int *bytes_left);
+#if defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK)
+int net_os_wake_lock_timeout_for_pno(struct net_device *dev, int sec);
+#endif
/* Get the link speed from dongle, speed is in kpbs */
int wldev_get_link_speed(struct net_device *dev, int *plink_speed);