summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2012-02-27 12:35:15 -0800
committerDmitry Shmidt <dimitrysh@google.com>2012-02-29 10:46:07 -0800
commit1282ad1837801103f42b4a7b8de4f231907bd4ef (patch)
tree7f1bfe2b5bc7893c4ca0bfbaa5dba8dd184a903d /drivers/net
parent254c20edd7eeda7b0acc379cc30c0ecccce39a66 (diff)
net: wireless: bcmdhd: Update to Version 5.90.195.28
- Improve scan for p2p - Use use_rxchain support - Use WL_WIRELESS_EXT instead of CONFIG_WIRELESS_EXT - Initial sched_scan support Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile2
-rw-r--r--drivers/net/wireless/bcmdhd/aiutils.c2
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh.c2
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_linux.c18
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c204
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c6
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cfg80211.c2
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c76
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c2
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h9
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h8
-rw-r--r--drivers/net/wireless/bcmdhd/include/linuxver.h7
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbchipc.h5
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h4
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c6
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c599
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h4
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c3
18 files changed, 695 insertions, 264 deletions
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index 17f07ca3a307..9828de6fad9d 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -19,7 +19,7 @@ obj-$(CONFIG_BCMDHD) += bcmdhd.o
bcmdhd-objs += $(DHDOFILES)
ifneq ($(CONFIG_WIRELESS_EXT),)
bcmdhd-objs += wl_iw.o
-DHDCFLAGS += -DSOFTAP
+DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT
endif
ifneq ($(CONFIG_CFG80211),)
bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o
diff --git a/drivers/net/wireless/bcmdhd/aiutils.c b/drivers/net/wireless/bcmdhd/aiutils.c
index 059df8907928..5ca0993c9333 100644
--- a/drivers/net/wireless/bcmdhd/aiutils.c
+++ b/drivers/net/wireless/bcmdhd/aiutils.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: aiutils.c,v 1.26.2.1 2010-03-09 18:41:21 Exp $
+ * $Id: aiutils.c,v 1.26.2.1 2010-03-09 18:41:21 $
*/
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c
index 918c8e648f13..f67b13a03a1c 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh.c 275784 2011-08-04 22:41:49Z $
+ * $Id: bcmsdh.c 300445 2011-12-03 05:37:20Z $
*/
/**
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
index e01b6f8a2d4f..d257ddab84a3 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_linux.c 308641 2012-01-17 02:18:02Z $
+ * $Id: bcmsdh_linux.c 312788 2012-02-03 23:06:32Z $
*/
/**
@@ -620,13 +620,6 @@ int bcmsdh_register_oob_intr(void * dhdp)
return 0;
}
-void *bcmsdh_get_drvdata(void)
-{
- if (!sdhcinfo)
- return NULL;
- return dev_get_drvdata(sdhcinfo->dev);
-}
-
void bcmsdh_set_irq(int flag)
{
if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) {
@@ -654,6 +647,15 @@ void bcmsdh_unregister_oob_intr(void)
}
#endif /* defined(OOB_INTR_ONLY) */
+#if defined(BCMLXSDMMC)
+void *bcmsdh_get_drvdata(void)
+{
+ if (!sdhcinfo)
+ return NULL;
+ return dev_get_drvdata(sdhcinfo->dev);
+}
+#endif
+
/* Module parameters specific to each host-controller driver */
extern uint sd_msglevel; /* Debug message level */
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
index 6a8ff9431e92..b88e57a5203b 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc.c 301794 2011-12-08 20:41:35Z $
+ * $Id: bcmsdh_sdmmc.c 314904 2012-02-14 21:36:04Z $
*/
#include <typedefs.h>
@@ -35,6 +35,7 @@
#include <sdiovar.h> /* ioctl/iovars */
#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
@@ -148,6 +149,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
sd->sd_blockmode = TRUE;
sd->use_client_ints = TRUE;
sd->client_block_size[0] = 64;
+ sd->use_rxchain = FALSE;
gInstance->sd = sd;
@@ -512,7 +514,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
}
case IOV_GVAL(IOV_RXCHAIN):
- int_val = FALSE;
+ int_val = (int32)si->use_rxchain;
bcopy(&int_val, arg, val_size);
break;
@@ -902,8 +904,12 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
bool fifo = (fix_inc == SDIOH_DATA_FIX);
uint32 SGCount = 0;
int err_ret = 0;
-
- void *pnext;
+ void *pnext, *pprev;
+ uint ttl_len, dma_len, lft_len, xfred_len, pkt_len;
+ uint blk_num;
+ struct mmc_request mmc_req;
+ struct mmc_command mmc_cmd;
+ struct mmc_data mmc_dat;
sd_trace(("%s: Enter\n", __FUNCTION__));
@@ -911,66 +917,148 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
- /* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
- for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
- uint pkt_len = PKTLEN(sd->osh, pnext);
- pkt_len += 3;
- pkt_len &= 0xFFFFFFFC;
+ ttl_len = xfred_len = 0;
+ /* at least 4 bytes alignment of skb buff is guaranteed */
+ for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext))
+ ttl_len += PKTLEN(sd->osh, pnext);
-#ifdef CONFIG_MMC_MSM7X00A
- if ((pkt_len % 64) == 32) {
- sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__));
- pkt_len += 32;
- }
-#endif /* CONFIG_MMC_MSM7X00A */
- /* Make sure the packet is aligned properly. If it isn't, then this
- * is the fault of sdioh_request_buffer() which is supposed to give
- * us something we can work with.
- */
- ASSERT(((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) == 0);
-
- if ((write) && (!fifo)) {
- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
- ((uint8*)PKTDATA(sd->osh, pnext)),
- pkt_len);
- } else if (write) {
- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
- ((uint8*)PKTDATA(sd->osh, pnext)),
- pkt_len);
- } else if (fifo) {
- err_ret = sdio_readsb(gInstance->func[func],
- ((uint8*)PKTDATA(sd->osh, pnext)),
- addr,
- pkt_len);
- } else {
- err_ret = sdio_memcpy_fromio(gInstance->func[func],
- ((uint8*)PKTDATA(sd->osh, pnext)),
- addr,
+ if (!sd->use_rxchain || ttl_len <= sd->client_block_size[func]) {
+ blk_num = 0;
+ dma_len = 0;
+ } else {
+ blk_num = ttl_len / sd->client_block_size[func];
+ dma_len = blk_num * sd->client_block_size[func];
+ }
+ lft_len = ttl_len - dma_len;
+
+ sd_trace(("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n",
+ __FUNCTION__, write ? "W" : "R",
+ ttl_len, func, addr, blk_num, lft_len));
+
+ if (0 != dma_len) {
+ memset(&mmc_req, 0, sizeof(struct mmc_request));
+ memset(&mmc_cmd, 0, sizeof(struct mmc_command));
+ memset(&mmc_dat, 0, sizeof(struct mmc_data));
+
+ /* Set up DMA descriptors */
+ pprev = pkt;
+ for (pnext = pkt;
+ pnext && dma_len;
+ pnext = PKTNEXT(sd->osh, pnext)) {
+ pkt_len = PKTLEN(sd->osh, pnext);
+
+ if (dma_len > pkt_len)
+ dma_len -= pkt_len;
+ else {
+ pkt_len = xfred_len = dma_len;
+ dma_len = 0;
+ pkt = pnext;
+ }
+
+ sg_set_buf(&sd->sg_list[SGCount++],
+ (uint8*)PKTDATA(sd->osh, pnext),
pkt_len);
- }
- if (err_ret) {
- sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
- __FUNCTION__,
- (write) ? "TX" : "RX",
- pnext, SGCount, addr, pkt_len, err_ret));
- } else {
- sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
- __FUNCTION__,
- (write) ? "TX" : "RX",
- pnext, SGCount, addr, pkt_len));
+ if (SGCount >= SDIOH_SDMMC_MAX_SG_ENTRIES) {
+ sd_err(("%s: sg list entries exceed limit\n",
+ __FUNCTION__));
+ return (SDIOH_API_RC_FAIL);
+ }
}
- if (!fifo) {
- addr += pkt_len;
- }
- SGCount ++;
+ mmc_dat.sg = sd->sg_list;
+ mmc_dat.sg_len = SGCount;
+ mmc_dat.blksz = sd->client_block_size[func];
+ mmc_dat.blocks = blk_num;
+ mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+ mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */
+ mmc_cmd.arg = write ? 1<<31 : 0;
+ mmc_cmd.arg |= (func & 0x7) << 28;
+ mmc_cmd.arg |= 1<<27;
+ mmc_cmd.arg |= fifo ? 0 : 1<<26;
+ mmc_cmd.arg |= (addr & 0x1FFFF) << 9;
+ mmc_cmd.arg |= blk_num & 0x1FF;
+ mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+
+ mmc_req.cmd = &mmc_cmd;
+ mmc_req.data = &mmc_dat;
+
+ sdio_claim_host(gInstance->func[func]);
+ mmc_set_data_timeout(&mmc_dat, gInstance->func[func]->card);
+ mmc_wait_for_req(gInstance->func[func]->card->host, &mmc_req);
+ sdio_release_host(gInstance->func[func]);
+
+ err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error;
+ if (0 != err_ret) {
+ sd_err(("%s:CMD53 %s failed with code %d\n",
+ __FUNCTION__,
+ write ? "write" : "read",
+ err_ret));
+ sd_err(("%s:Disabling rxchain and fire it with PIO\n",
+ __FUNCTION__));
+ sd->use_rxchain = FALSE;
+ pkt = pprev;
+ lft_len = ttl_len;
+ } else if (!fifo) {
+ addr = addr + ttl_len - lft_len - dma_len;
+ }
}
- /* Release host controller */
- sdio_release_host(gInstance->func[func]);
+ /* PIO mode */
+ if (0 != lft_len) {
+ /* Claim host controller */
+ sdio_claim_host(gInstance->func[func]);
+ for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
+ uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext) +
+ xfred_len;
+ pkt_len = PKTLEN(sd->osh, pnext);
+ if (0 != xfred_len) {
+ pkt_len -= xfred_len;
+ xfred_len = 0;
+ }
+ pkt_len = (pkt_len + 3) & 0xFFFFFFFC;
+#ifdef CONFIG_MMC_MSM7X00A
+ if ((pkt_len % 64) == 32) {
+ sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__));
+ pkt_len += 32;
+ }
+#endif /* CONFIG_MMC_MSM7X00A */
+
+ if ((write) && (!fifo))
+ err_ret = sdio_memcpy_toio(
+ gInstance->func[func],
+ addr, buf, pkt_len);
+ else if (write)
+ err_ret = sdio_memcpy_toio(
+ gInstance->func[func],
+ addr, buf, pkt_len);
+ else if (fifo)
+ err_ret = sdio_readsb(
+ gInstance->func[func],
+ buf, addr, pkt_len);
+ else
+ err_ret = sdio_memcpy_fromio(
+ gInstance->func[func],
+ buf, addr, pkt_len);
+
+ if (err_ret)
+ sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n",
+ __FUNCTION__,
+ (write) ? "TX" : "RX",
+ pnext, SGCount, addr, pkt_len, err_ret));
+ else
+ sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
+ __FUNCTION__,
+ (write) ? "TX" : "RX",
+ pnext, SGCount, addr, pkt_len));
+
+ if (!fifo)
+ addr += pkt_len;
+ SGCount ++;
+ }
+ sdio_release_host(gInstance->func[func]);
+ }
sd_trace(("%s: Exit\n", __FUNCTION__));
return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
@@ -1232,8 +1320,10 @@ sdioh_start(sdioh_info_t *si, int stage)
2.6.27. The implementation prior to that is buggy, and needs broadcom's
patch for it
*/
- if ((ret = sdio_reset_comm(gInstance->func[0]->card)))
+ if ((ret = sdio_reset_comm(gInstance->func[0]->card))) {
sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
+ return ret;
+ }
else {
sd->num_funcs = 2;
sd->sd_blockmode = TRUE;
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
index 83f4d3df671f..f296dd382b5c 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc_linux.c 308645 2012-01-17 02:33:26Z $
+ * $Id: bcmsdh_sdmmc_linux.c 312783 2012-02-03 22:53:56Z $
*/
#include <typedefs.h>
@@ -98,7 +98,6 @@ PBCMSDH_SDMMC_INSTANCE gInstance;
extern int bcmsdh_probe(struct device *dev);
extern int bcmsdh_remove(struct device *dev);
-
extern volatile bool dhd_mmc_suspend;
static int bcmsdh_sdmmc_probe(struct sdio_func *func,
@@ -194,8 +193,9 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev)
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__));
dhd_mmc_suspend = FALSE;
#if defined(OOB_INTR_ONLY)
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
index 800590cca653..917b09b35a35 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
@@ -467,7 +467,6 @@ void wl_cfg80211_btcoex_deinit(struct wl_priv *wl)
kfree(wl->btcoex_info);
wl->btcoex_info = NULL;
}
-#endif
int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
{
@@ -591,3 +590,4 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
return (strlen("OK"));
}
+#endif
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 0c34e79bf2ca..597d12560c19 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c 308879 2012-01-17 22:03:47Z $
+ * $Id: dhd_linux.c 314746 2012-02-14 03:45:02Z $
*/
#include <typedefs.h>
@@ -149,10 +149,10 @@ print_tainted()
#endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */
/* Linux wireless extension support */
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
#include <wl_iw.h>
extern wl_iw_extra_params_t g_wl_iw_params;
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
#if defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
@@ -212,9 +212,9 @@ static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0;
/* Local private structure (extension of pub) */
typedef struct dhd_info {
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
wl_iw_t iw; /* wireless extensions state (must be first) */
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
dhd_pub_t pub;
@@ -359,12 +359,6 @@ uint dhd_radio_up = 1;
char iface_name[IFNAMSIZ] = {'\0'};
module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
-#define BLOCKABLE() (!in_atomic())
-#else
-#define BLOCKABLE() (!in_interrupt())
-#endif
-
/* The following are specific to the SDIO dongle */
/* IOCTL response timeout */
@@ -451,9 +445,9 @@ int dhd_monitor_init(void *dhd_pub);
int dhd_monitor_uninit(void);
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
static void dhd_dpc(ulong data);
/* forward decl */
@@ -2053,7 +2047,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
return -1;
}
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
/* linux wireless extensions */
if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
/* may recurse, do NOT lock */
@@ -2061,7 +2055,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
DHD_OS_WAKE_UNLOCK(&dhd->pub);
return ret;
}
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
if (cmd == SIOCETHTOOL) {
@@ -2338,7 +2332,6 @@ dhd_open(struct net_device *net)
}
dhd->pub.hang_was_sent = 0;
-
#if !defined(WL_CFG80211)
/*
* Force start if ifconfig_up gets called before START command
@@ -2672,7 +2665,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
dhd_monitor_init(&dhd->pub);
dhd_state |= DHD_ATTACH_STATE_CFG80211;
#endif
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
/* Attach and link in the iw */
if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) {
if (wl_iw_attach(net, (void *)&dhd->pub) != 0) {
@@ -2681,7 +2674,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
}
dhd_state |= DHD_ATTACH_STATE_WL_ATTACH;
}
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
/* Set up the watchdog timer */
@@ -2934,6 +2927,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#if defined(ARP_OFFLOAD_SUPPORT)
int arpoe = 1;
#endif
+#if defined(KEEP_ALIVE)
+ int res;
+#endif /* defined(KEEP_ALIVE) */
int scan_assoc_time = DHD_SCAN_ACTIVE_TIME;
int scan_unassoc_time = 40;
int scan_passive_time = DHD_SCAN_PASSIVE_TIME;
@@ -2946,14 +2942,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211))
uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
#endif
-
#if defined(AP) || defined(WLP2P)
uint32 apsta = 1; /* Enable APSTA mode */
#endif /* defined(AP) || defined(WLP2P) */
#ifdef GET_CUSTOM_MAC_ENABLE
struct ether_addr ea_addr;
#endif /* GET_CUSTOM_MAC_ENABLE */
-
DHD_TRACE(("Enter %s\n", __FUNCTION__));
dhd->op_mode = 0;
#ifdef GET_CUSTOM_MAC_ENABLE
@@ -3083,6 +3077,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
/* Setup assoc_retry_max count to reconnect target AP in dongle */
bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
#if defined(AP) && !defined(WLP2P)
/* Turn off MPC in AP mode */
bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
@@ -3098,17 +3093,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif
#if defined(KEEP_ALIVE)
- {
/* Set Keep Alive : be sure to use FW with -keepalive */
- int res;
-
#if defined(SOFTAP)
if (ap_fw_loaded == FALSE)
#endif
if ((res = dhd_keep_alive_onoff(dhd)) < 0)
DHD_ERROR(("%s set keeplive failed %d\n",
__FUNCTION__, res));
- }
#endif /* defined(KEEP_ALIVE) */
/* Read event_msgs mask */
@@ -3471,14 +3462,14 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
net->ethtool_ops = &dhd_ethtool_ops;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
#if WIRELESS_EXT < 19
net->get_wireless_stats = dhd_get_wireless_stats;
#endif /* WIRELESS_EXT < 19 */
#if WIRELESS_EXT > 12
net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def;
#endif /* WIRELESS_EXT > 12 */
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net);
@@ -3494,7 +3485,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
net->dev_addr[0], net->dev_addr[1], net->dev_addr[2],
net->dev_addr[3], net->dev_addr[4], net->dev_addr[5]);
-#if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211)
+#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211)
wl_iw_iscan_set_scan_broadcast_prep(net, 1);
#endif
@@ -3579,12 +3570,12 @@ void dhd_detach(dhd_pub_t *dhdp)
}
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) {
/* Detatch and unlink in the iw */
wl_iw_detach();
}
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
if (dhd->thr_sysioc_ctl.thr_pid >= 0) {
PROC_STOP(&dhd->thr_sysioc_ctl);
@@ -3748,20 +3739,20 @@ dhd_module_init(void)
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
- /*
- * Wait till MMC sdio_register_driver callback called and made driver attach.
- * It's needed to make sync up exit from dhd insmod and
- * Kernel MMC sdio device callback registration
- */
+ /*
+ * Wait till MMC sdio_register_driver callback called and made driver attach.
+ * It's needed to make sync up exit from dhd insmod and
+ * Kernel MMC sdio device callback registration
+ */
if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) {
- error = -EINVAL;
+ error = -ENODEV;
DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__));
goto fail_2;
}
#endif
#if defined(WL_CFG80211)
wl_android_post_init();
-#endif
+#endif /* defined(WL_CFG80211) */
return error;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
@@ -4037,7 +4028,7 @@ void dhd_os_prefree(void *osh, void *addr, uint size)
}
#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
struct iw_statistics *
dhd_get_wireless_stats(struct net_device *dev)
{
@@ -4055,7 +4046,7 @@ dhd_get_wireless_stats(struct net_device *dev)
else
return NULL;
}
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
static int
dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
@@ -4068,7 +4059,7 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
if (bcmerror != BCME_OK)
return (bcmerror);
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
if (event->bsscfgidx == 0) {
/*
* Wireless ext is on primary interface only
@@ -4081,7 +4072,7 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
}
}
-#endif /* defined(CONFIG_WIRELESS_EXT) */
+#endif /* defined(WL_WIRELESS_EXT) */
#ifdef WL_CFG80211
if ((ntoh32(event->event_type) == WLC_E_IF) &&
@@ -4386,6 +4377,8 @@ dhd_dev_get_pno_status(struct net_device *dev)
#endif /* PNO_SUPPORT */
+struct work_struct work;
+
int net_os_send_hang_message(struct net_device *dev)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
@@ -4402,7 +4395,7 @@ int net_os_send_hang_message(struct net_device *dev)
dev_close(dev);
if (need_unlock)
rtnl_unlock();
-#if defined(CONFIG_WIRELESS_EXT)
+#if defined(WL_WIRELESS_EXT)
ret = wl_iw_send_priv_event(dev, "HANG");
#endif
#if defined(WL_CFG80211)
@@ -4421,7 +4414,6 @@ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec)
memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t));
}
-
void dhd_net_if_lock(struct net_device *dev)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index 53eff583c381..282a7179540b 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_sdio.c 309234 2012-01-19 01:44:16Z $
+ * $Id: dhd_sdio.c 314732 2012-02-14 03:22:42Z $
*/
#include <typedefs.h>
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h
index bea97b610a8e..db8ea596304c 100644
--- a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc.h 277737 2011-08-16 17:54:59Z $
+ * $Id: bcmsdh_sdmmc.h 314048 2012-02-09 20:31:56Z $
*/
#ifndef __BCMSDH_SDMMC_H__
@@ -82,9 +82,10 @@ struct sdioh_info {
uint8 num_funcs; /* Supported funcs on client */
uint32 com_cis_ptr;
uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
- uint max_dma_len;
- uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */
-// SDDMA_DESCRIPTOR SGList[32]; /* Scatter/Gather DMA List */
+
+#define SDIOH_SDMMC_MAX_SG_ENTRIES 32
+ struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES];
+ bool use_rxchain;
};
/************************************************************
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 53dd2f736734..0e720456f582 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -33,17 +33,17 @@
#define EPI_RC_NUMBER 195
-#define EPI_INCREMENTAL_NUMBER 23
+#define EPI_INCREMENTAL_NUMBER 28
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 5, 90, 195, 23
+#define EPI_VERSION 5, 90, 195, 28
-#define EPI_VERSION_NUM 0x055ac317
+#define EPI_VERSION_NUM 0x055ac31c
#define EPI_VERSION_DEV 5.90.195
-#define EPI_VERSION_STR "5.90.195.23"
+#define EPI_VERSION_STR "5.90.195.28"
#endif
diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h
index d269e66f7fb8..54d88ee923b2 100644
--- a/drivers/net/wireless/bcmdhd/include/linuxver.h
+++ b/drivers/net/wireless/bcmdhd/include/linuxver.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: linuxver.h 280266 2011-08-28 04:18:20Z $
+ * $Id: linuxver.h 312264 2012-02-02 00:49:43Z $
*/
@@ -524,6 +524,11 @@ typedef struct {
} while (0);
#endif /* LINUX_VERSION_CODE */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define BLOCKABLE() (!in_atomic())
+#else
+#define BLOCKABLE() (!in_interrupt())
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
#define KILL_PROC(nr, sig) \
diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h
index 3fe2a5a49d30..8f757509b95d 100644
--- a/drivers/net/wireless/bcmdhd/include/sbchipc.h
+++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h
@@ -5,7 +5,7 @@
* JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer,
* GPIO interface, extbus, and support for serial and parallel flashes.
*
- * $Id: sbchipc.h 277737 2011-08-16 17:54:59Z $
+ * $Id: sbchipc.h 311371 2012-01-28 05:47:25Z $
*
* Copyright (C) 1999-2011, Broadcom Corporation
*
@@ -1659,6 +1659,9 @@ typedef volatile struct {
#define CCTRL_4330_JTAG_DISABLE 0x00000008
+#define CCTRL_43239_GPIO_SEL 0x00000002
+#define CCTRL_43239_SDIO_HOST_WAKE 0x00000004
+
#define RES4313_BB_PU_RSRC 0
#define RES4313_ILP_REQ_RSRC 1
#define RES4313_XTAL_PU_RSRC 2
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index e31bfa94c006..91274a0c680b 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -24,7 +24,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wlioctl.h 307468 2012-01-11 18:29:27Z $
+ * $Id: wlioctl.h 312596 2012-02-03 02:53:30Z $
*/
@@ -1213,7 +1213,7 @@ typedef struct {
#define WL_AUTH_OPEN_SYSTEM 0
#define WL_AUTH_SHARED_KEY 1
-#define WL_AUTH_OPEN_SHARED 3
+#define WL_AUTH_OPEN_SHARED 2
#define WL_RADIO_SW_DISABLE (1<<0)
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 2cbe333b0dd6..8f6b1988180e 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -223,7 +223,7 @@ static int wl_android_get_band(struct net_device *dev, char *command, int total_
return bytes_written;
}
-#ifdef PNO_SUPPORT
+#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN)
static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
{
wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
@@ -329,7 +329,7 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t
exit_proc:
return res;
}
-#endif /* PNO_SUPPORT */
+#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */
static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
{
@@ -516,7 +516,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
char *country_code = command + strlen(CMD_COUNTRY) + 1;
bytes_written = wldev_set_country(net, country_code);
}
-#ifdef PNO_SUPPORT
+#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN)
else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
bytes_written = dhd_dev_pno_reset(net);
}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 125888d028fa..c910fc59407b 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -202,7 +202,8 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_pmksa *pmksa);
static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
struct net_device *dev);
-static void wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, bool aborted);
+static s32 wl_notify_escan_complete(struct wl_priv *wl,
+ struct net_device *ndev, bool aborted, bool fw_abort);
/*
* event & event Q handlers for cfg80211 interfaces
*/
@@ -236,8 +237,15 @@ 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);
+#ifdef WL_SCHED_SCAN
+static s32
+wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+#endif /* WL_SCHED_SCAN */
+#ifdef PNO_SUPPORT
static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data);
+#endif /* PNO_SUPPORT */
/*
* register/deregister parent device
*/
@@ -516,11 +524,11 @@ static struct ieee80211_supported_band __wl_band_2ghz = {
* doesn't match with the IE present in the 3/4 EAPOL msg.
*/
.ht_cap = {
- IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU,
- .ht_supported = TRUE,
- .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
- .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU,
+ .ht_supported = TRUE,
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16
}
#endif
};
@@ -530,7 +538,22 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
.channels = __wl_5ghz_a_channels,
.n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
.bitrates = wl_a_rates,
- .n_bitrates = wl_a_rates_size
+ .n_bitrates = wl_a_rates_size,
+#if ENABLE_P2P_INTERFACE
+ /* wpa_supplicant sets wmm_enabled based on whether ht_cap
+ * is present or not. The wmm_enabled is inturn used to
+ * set the replay counters in the RSN IE. Without this
+ * the 4way handshake will fail complaining that IE in beacon
+ * doesn't match with the IE present in the 3/4 EAPOL msg.
+ */
+ .ht_cap = {
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU,
+ .ht_supported = TRUE,
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16
+ }
+#endif
};
static const u32 __wl_cipher_suites[] = {
@@ -918,8 +941,8 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
if (wl->p2p_supported) {
memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
if (wl->p2p->vif_created) {
- if (wl_get_drv_status(wl, SCANNING, dev)) {
- wl_cfg80211_scan_abort(wl, dev);
+ if (wl->scan_request) {
+ wl_notify_escan_complete(wl, dev, true, true);
}
wldev_iovar_setint(dev, "mpc", 1);
wl_set_p2p_status(wl, IF_DELETING);
@@ -1088,7 +1111,7 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev)
rollback_lock = true;
}
WL_DBG(("ESCAN COMPLETED\n"));
- wl_notify_escan_complete(wl, ndev, true);
+ wl_notify_escan_complete(wl, ndev, true, false);
if (rollback_lock)
rtnl_unlock();
}
@@ -1508,7 +1531,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
wpa_ie_fixed_t *wps_ie;
s32 passive_scan;
bool iscan_req;
- bool escan_req;
+ bool escan_req = false;
bool p2p_ssid;
s32 err = 0;
s32 i;
@@ -1907,21 +1930,21 @@ 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:
WL_DBG(("network eap\n"));
default:
- val = 2;
+ val = WL_AUTH_OPEN_SHARED;
WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
break;
}
@@ -2119,9 +2142,9 @@ wl_set_set_sharedkey(struct net_device *dev,
WL_ERR(("WLC_SET_KEY error (%d)\n", err));
return err;
}
- if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
+ if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
WL_DBG(("set auth_type to shared key\n"));
- val = 1; /* shared key */
+ val = WL_AUTH_SHARED_KEY; /* shared key */
err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
if (unlikely(err)) {
WL_ERR(("set auth failed (%d)\n", err));
@@ -2160,7 +2183,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
* Cancel ongoing scan to sync up with sme state machine of cfg80211.
*/
if (wl->scan_request) {
- wl_cfg80211_scan_abort(wl, dev);
+ wl_notify_escan_complete(wl, dev, true, true);
}
/* Clean BSSID */
bzero(&bssid, sizeof(bssid));
@@ -2382,7 +2405,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
* Cancel ongoing scan to sync up with sme state machine of cfg80211.
*/
if (wl->scan_request) {
- wl_cfg80211_scan_abort(wl, dev);
+ wl_notify_escan_complete(wl, dev, true, true);
}
wl_set_drv_status(wl, DISCONNECTING, dev);
scbval.val = reason_code;
@@ -2581,9 +2604,6 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL;
}
swap_key_from_BE(&key);
-#if defined(CONFIG_WIRELESS_EXT)
- dhd_wait_pend8021x(dev);
-#endif
wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
if (unlikely(err)) {
@@ -2831,42 +2851,42 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
sta->idle * 1000));
#endif
} 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)) {
- WL_ERR(("NOT assoc\n"));
- err = -ENODEV;
- goto get_station_err;
- }
- if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
- WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n",
- MAC2STR(mac), MAC2STR(curmacp)));
- }
+ u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
+ if (!wl_get_drv_status(wl, CONNECTED, dev) ||
+ (dhd_is_associated(dhd, NULL) == FALSE)) {
- /* Report the current tx rate */
- err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
- if (err) {
- WL_ERR(("Could not get rate (%d)\n", err));
- } else {
- rate = dtoh32(rate);
- sinfo->filled |= STATION_INFO_TX_BITRATE;
- sinfo->txrate.legacy = rate * 5;
- WL_DBG(("Rate %d Mbps\n", (rate / 2)));
- }
+ WL_ERR(("NOT assoc\n"));
+ err = -ENODEV;
+ goto get_station_err;
+ }
+ if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
+ WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n",
+ MAC2STR(mac), MAC2STR(curmacp)));
+ }
- memset(&scb_val, 0, sizeof(scb_val));
- scb_val.val = 0;
- err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
- sizeof(scb_val_t), false);
- if (err) {
- WL_ERR(("Could not get rssi (%d)\n", err));
- goto get_station_err;
- }
+ /* Report the current tx rate */
+ err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
+ if (err) {
+ WL_ERR(("Could not get rate (%d)\n", err));
+ } else {
+ rate = dtoh32(rate);
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+ sinfo->txrate.legacy = rate * 5;
+ WL_DBG(("Rate %d Mbps\n", (rate / 2)));
+ }
- rssi = dtoh32(scb_val.val);
- sinfo->filled |= STATION_INFO_SIGNAL;
- sinfo->signal = rssi;
- WL_DBG(("RSSI %d dBm\n", rssi));
+ memset(&scb_val, 0, sizeof(scb_val));
+ scb_val.val = 0;
+ err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
+ sizeof(scb_val_t), false);
+ if (err) {
+ WL_ERR(("Could not get rssi (%d)\n", err));
+ goto get_station_err;
+ }
+ rssi = dtoh32(scb_val.val);
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ sinfo->signal = rssi;
+ WL_DBG(("RSSI %d dBm\n", rssi));
get_station_err:
if (err) {
@@ -3009,8 +3029,8 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
return -EINVAL;
}
/* pmk list is supported only for STA interface i.e. primary interface
- * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
- */
+ * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
+ */
if (primary_dev != dev) {
WL_INFO(("Not supporting Flushing pmklist on virtual"
" interfaces than primary interface\n"));
@@ -3173,8 +3193,21 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev)
s32 params_size = 0;
s32 err = BCME_OK;
unsigned long flags;
+ struct net_device *dev;
WL_DBG(("Enter\n"));
+ if (wl->scan_request) {
+ if (wl->scan_request->dev == wl->p2p_net)
+ dev = wl_to_prmry_ndev(wl);
+ else
+ dev = wl->scan_request->dev;
+ }
+ else {
+ WL_ERR(("wl->scan_request is NULL did we already do scan_abort?"
+ "Now scan_abort for ndev %p primary %p p2p_net %p",
+ ndev, wl_to_prmry_ndev(wl), wl->p2p_net));
+ dev = ndev;
+ }
/* Our scan params only need space for 1 channel and 0 ssids */
params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
@@ -3183,18 +3216,26 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev)
err = -ENOMEM;
} else {
/* Do a scan abort to stop the driver's scan engine */
- err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, true);
+ err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
if (err < 0) {
WL_ERR(("scan abort failed \n"));
}
}
del_timer_sync(&wl->scan_timeout);
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
+
+#ifdef WL_SCHED_SCAN
+ if (wl->sched_scan_req && !wl->scan_request) {
+ cfg80211_sched_scan_stopped(wl_to_wiphy(wl));
+ wl->sched_scan_req = NULL;
+ }
+#endif /* WL_SCHED_SCAN */
+
if (wl->scan_request) {
cfg80211_scan_done(wl->scan_request, true);
wl->scan_request = NULL;
}
- wl_clr_drv_status(wl, SCANNING, ndev);
+ wl_clr_drv_status(wl, SCANNING, dev);
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
if (params)
kfree(params);
@@ -3222,10 +3263,9 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
ndev = dev;
}
- if (wl_get_drv_status(wl, SCANNING, ndev)) {
- wl_cfg80211_scan_abort(wl, ndev);
+ if (wl->scan_request) {
+ wl_notify_escan_complete(wl, ndev, true, true);
}
-
target_channel = ieee80211_frequency_to_channel(channel->center_freq);
memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel));
wl->remain_on_chan_type = channel_type;
@@ -3288,7 +3328,7 @@ wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl)
*/
wl_clr_drv_status(wl, SENDING_ACT_FRM, wl->afx_hdl->dev);
wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
- wl_cfg80211_scan_abort(wl, dev);
+ wl_notify_escan_complete(wl, dev, true, true);
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,
@@ -3442,8 +3482,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
scb_val.val = mgmt->u.disassoc.reason_code;
wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
sizeof(scb_val_t), true);
- WL_DBG(("Disconnect STA : %s\n",
- bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf)));
+ WL_DBG(("Disconnect STA : %s scb_val.val %d\n",
+ bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val));
cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
goto exit;
@@ -3455,7 +3495,7 @@ 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);
+ wl_notify_escan_complete(wl, dev, true, true);
}
@@ -3490,6 +3530,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
ieee80211_frequency_to_channel(channel->center_freq);
if (channel->band == IEEE80211_BAND_5GHZ) {
+ WL_DBG(("5GHz channel %d", af_params->channel));
err = wldev_ioctl(dev, WLC_SET_CHANNEL,
&af_params->channel, sizeof(af_params->channel), true);
if (err < 0) {
@@ -3653,7 +3694,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
{
s32 len = 0;
s32 err = BCME_OK;
- u16 auth = 0; /* d11 open authentication */
+ u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */
u32 wsec;
u32 pval = 0;
u32 gval = 0;
@@ -3757,7 +3798,7 @@ wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
wpa_suite_mcast_t *mcast;
wpa_suite_ucast_t *ucast;
wpa_suite_auth_key_mgmt_t *mgmt;
- u16 auth = 0; /* d11 open authentication */
+ u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */
u16 count;
s32 err = BCME_OK;
s32 len = 0;
@@ -4080,7 +4121,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 {
@@ -4133,12 +4174,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);
}
@@ -4224,6 +4265,105 @@ exit:
return err;
}
+#ifdef WL_SCHED_SCAN
+#define PNO_TIME 30
+#define PNO_REPEAT 4
+#define PNO_FREQ_EXPO_MAX 3
+int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_sched_scan_request *request)
+{
+ ushort pno_time = PNO_TIME;
+ int pno_repeat = PNO_REPEAT;
+ int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
+ wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+ struct wl_priv *wl = wiphy_priv(wiphy);
+ struct cfg80211_ssid *ssid = NULL;
+ int ssid_count = 0;
+ int i;
+ int ret = 0;
+
+ WL_DBG(("Enter n_match_sets:%d n_ssids:%d \n",
+ request->n_match_sets, request->n_ssids));
+ WL_DBG(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
+ request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
+
+ if (wl_get_drv_status_all(wl, SCANNING)) {
+ WL_ERR(("Scanning already\n"));
+ return -EAGAIN;
+ }
+
+ if (!request || !request->n_ssids || !request->n_match_sets) {
+ WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
+ return -EINVAL;
+ }
+
+ memset(&ssids_local, 0, sizeof(ssids_local));
+
+ if (request->n_match_sets > 0) {
+ for (i = 0; i < request->n_match_sets; i++) {
+ ssid = &request->match_sets[i].ssid;
+ memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
+ ssids_local[i].SSID_len = ssid->ssid_len;
+ WL_DBG((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
+ ssid_count++;
+ }
+ }
+
+ if (request->n_ssids > 0) {
+ for (i = 0; i < request->n_ssids; i++) {
+ /* Active scan req for ssids */
+ WL_DBG((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
+
+ /* match_set ssids is a supert set of n_ssid list, so we need
+ * not add these set seperately
+ */
+ }
+ }
+
+ if (ssid_count) {
+ if ((ret = dhd_dev_pno_set(dev, ssids_local, request->n_match_sets,
+ pno_time, pno_repeat, pno_freq_expo_max)) < 0) {
+ WL_ERR(("PNO setup failed!! ret=%d \n", ret));
+ return -EINVAL;
+ }
+
+ /* Enable the PNO */
+ if (dhd_dev_pno_enable(dev, 1) < 0) {
+ WL_ERR(("PNO enable failed!! ret=%d \n", ret));
+ return -EINVAL;
+ }
+ wl->sched_scan_req = request;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct wl_priv *wl = wiphy_priv(wiphy);
+
+ WL_DBG(("Enter \n"));
+
+ if (dhd_dev_pno_enable(dev, 0) < 0)
+ WL_ERR(("PNO disable failed"));
+
+ if (dhd_dev_pno_reset(dev) < 0)
+ WL_ERR(("PNO reset failed"));
+
+ if (wl->scan_request && wl->sched_scan_running) {
+ wl_cfg80211_scan_abort(wl, dev);
+ }
+
+ wl->sched_scan_req = NULL;
+ wl->sched_scan_running = FALSE;
+
+ return 0;
+}
+#endif /* WL_SCHED_SCAN */
+
static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = wl_cfg80211_add_virtual_iface,
.del_virtual_intf = wl_cfg80211_del_virtual_iface,
@@ -4256,6 +4396,10 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.set_channel = wl_cfg80211_set_channel,
.set_beacon = wl_cfg80211_add_set_beacon,
.add_beacon = wl_cfg80211_add_set_beacon,
+#ifdef WL_SCHED_SCAN
+ .sched_scan_start = wl_cfg80211_sched_scan_start,
+ .sched_scan_stop = wl_cfg80211_sched_scan_stop,
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
};
s32 wl_mode_to_nl80211_iftype(s32 mode)
@@ -4291,12 +4435,18 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
/* Report how many SSIDs Driver can support per Scan request */
wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+#ifdef WL_SCHED_SCAN
+ wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
+ wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
+ wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
+ wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+#endif /* WL_SCHED_SCAN */
wdev->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION)
| BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR);
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;
+ /* wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - set in runtime */
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);
@@ -4314,7 +4464,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
#endif
WIPHY_FLAG_4ADDR_STATION;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
- wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+ wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
#endif
WL_DBG(("Registering custom regulatory)\n"));
wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
@@ -4469,7 +4619,7 @@ static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net
u32 status = ntoh32(e->status);
u16 flags = ntoh16(e->flags);
- WL_DBG(("event %d, status %d\n", event, status));
+ WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
if (event == WLC_E_SET_SSID) {
if (status == WLC_E_STATUS_SUCCESS) {
if (!wl_is_ibssmode(wl, ndev))
@@ -4552,7 +4702,7 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE
memset(body, 0, sizeof(body));
memset(&bssid, 0, ETHER_ADDR_LEN);
- WL_DBG(("Enter \n"));
+ WL_DBG(("Enter event %d ndev %p\n", event, ndev));
if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID)
return WL_INVALID;
@@ -4646,8 +4796,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
wl_notify_connect_status_ap(wl, ndev, e, data);
} else {
- WL_DBG(("wl_notify_connect_status : event %d status : %d \n",
- ntoh32(e->event_type), ntoh32(e->status)));
+ WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
+ ntoh32(e->event_type), ntoh32(e->status), ndev));
if (wl_is_linkup(wl, e, ndev)) {
wl_link_up(wl);
act = true;
@@ -4670,30 +4820,34 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
} else if (wl_is_linkdown(wl, e)) {
if (wl->scan_request) {
- del_timer_sync(&wl->scan_timeout);
if (wl->escan_on) {
- wl_notify_escan_complete(wl, ndev, true);
- } else
+ wl_notify_escan_complete(wl, ndev, true, true);
+ } else {
+ del_timer_sync(&wl->scan_timeout);
wl_iscan_aborted(wl);
+ }
}
if (wl_get_drv_status(wl, CONNECTED, ndev)) {
scb_val_t scbval;
u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
printk("link down, call cfg80211_disconnected\n");
wl_clr_drv_status(wl, CONNECTED, ndev);
- /* To make sure disconnect, explictly send dissassoc
- * for BSSID 00:00:00:00:00:00 issue
- */
- scbval.val = WLAN_REASON_DEAUTH_LEAVING;
-
- memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
- scbval.val = htod32(scbval.val);
- wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
- sizeof(scb_val_t), true);
- cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
- wl_link_down(wl);
- wl_init_prof(wl, ndev);
- } else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
+ if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
+ /* To make sure disconnect, explictly send dissassoc
+ * for BSSID 00:00:00:00:00:00 issue
+ */
+ scbval.val = WLAN_REASON_DEAUTH_LEAVING;
+
+ memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+ wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), true);
+ cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
+ wl_link_down(wl);
+ wl_init_prof(wl, ndev);
+ }
+ }
+ else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
printk("link down, during connecting\n");
wl_bss_connect_done(wl, ndev, e, data, false);
}
@@ -4704,11 +4858,12 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
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_notify_escan_complete(wl, ndev, true);
- } else
+ wl_notify_escan_complete(wl, ndev, true, true);
+ } else {
+ del_timer_sync(&wl->scan_timeout);
wl_iscan_aborted(wl);
+ }
}
if (wl_get_drv_status(wl, CONNECTING, ndev))
wl_bss_connect_done(wl, ndev, e, data, false);
@@ -4857,6 +5012,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
u8 *curbssid;
s32 err = 0;
struct wiphy *wiphy;
+
wiphy = wl_to_wiphy(wl);
if (wl_is_ibssmode(wl, ndev))
@@ -4960,7 +5116,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
WL_DBG((" enter\n"));
if (wl->scan_request) {
- wl_cfg80211_scan_abort(wl, ndev);
+ wl_notify_escan_complete(wl, ndev, true, true);
}
if (wl_get_drv_status(wl, CONNECTING, ndev)) {
wl_clr_drv_status(wl, CONNECTING, ndev);
@@ -5008,6 +5164,7 @@ wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
return 0;
}
+#ifdef PNO_SUPPORT
static s32
wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data)
@@ -5015,11 +5172,19 @@ wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev,
WL_ERR((" PNO Event\n"));
mutex_lock(&wl->usr_sync);
+#ifndef WL_SCHED_SCAN
/* TODO: Use cfg80211_sched_scan_results(wiphy); */
cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
+#else
+ /* If cfg80211 scheduled scan is supported, report the pno results via sched
+ * scan results
+ */
+ wl_notify_sched_scan_results(wl, ndev, e, data);
+#endif /* WL_SCHED_SCAN */
mutex_unlock(&wl->usr_sync);
return 0;
}
+#endif /* PNO_SUPPORT */
static s32
wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
@@ -5199,7 +5364,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
* After complete GO Negotiation, roll back to mpc mode
*/
if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
- (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
+ (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
wldev_iovar_setint(dev, "mpc", 1);
}
} else {
@@ -5217,6 +5382,127 @@ exit:
return 0;
}
+#ifdef WL_SCHED_SCAN
+/* If target scan is not reliable, set the below define to "0" to do a
+ * full escan
+ */
+#define FULL_ESCAN_ON_PFN_NET_FOUND 1
+static s32
+wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ wl_pfn_net_info_t *netinfo, *pnetinfo;
+ struct cfg80211_scan_request request;
+ struct wiphy *wiphy = wl_to_wiphy(wl);
+ int err = 0;
+ struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
+ struct ieee80211_channel *channel = NULL;
+ int channel_req = 0;
+ int band = 0;
+ struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
+
+ WL_DBG(("Enter\n"));
+
+ if (e->event_type == WLC_E_PFN_NET_LOST) {
+ WL_DBG(("PFN NET LOST event. Do Nothing \n"));
+ return 0;
+ } else {
+ WL_DBG(("PFN NET FOUND event. count:%d \n", pfn_result->count));
+
+
+ if (pfn_result->count > 0) {
+ int i;
+
+ memset(&request, 0x00, sizeof(struct cfg80211_scan_request));
+ memset(&ssid, 0x00, sizeof(ssid));
+ request.wiphy = wiphy;
+
+ pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
+ - sizeof(wl_pfn_net_info_t));
+
+ channel = (struct ieee80211_channel *)kzalloc(
+ (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT),
+ GFP_KERNEL);
+ if (!channel) {
+ WL_ERR(("No memory"));
+ err = -ENOMEM;
+ goto out_err;
+ }
+
+ for (i = 0; i < pfn_result->count; i++) {
+ netinfo = &pnetinfo[i];
+ if (!netinfo) {
+ WL_ERR(("Invalid netinfo ptr. index:%d", i));
+ err = -EINVAL;
+ goto out_err;
+ }
+
+ WL_DBG(("SSID:%s Channel:%d \n",
+ netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
+ /* PFN result doesn't have all the info which are required by the supplicant
+ * (For e.g IEs) Do a target Escan so that sched scan results are reported
+ * via wl_inform_single_bss in the required format. Escan does require the
+ * scan request in the form of cfg80211_scan_request. For timebeing, create
+ * cfg80211_scan_request one out of the received PNO event.
+ */
+ memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
+ netinfo->pfnsubnet.SSID_len);
+ ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
+ request.n_ssids++;
+
+ channel_req = netinfo->pfnsubnet.channel;
+ band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
+ : NL80211_BAND_2GHZ;
+ channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
+ channel[i].band = band;
+ channel[i].flags |= IEEE80211_CHAN_NO_HT40;
+ request.channels[i] = &channel[i];
+ request.n_channels++;
+ }
+
+ /* assign parsed ssid array */
+ if (request.n_ssids)
+ request.ssids = &ssid[0];
+
+ if (wl_get_drv_status_all(wl, SCANNING)) {
+ /* Abort any on-going scan */
+ wl_cfg80211_scan_abort(wl, ndev);
+ }
+
+ if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
+ err = wl_cfgp2p_discover_enable_search(wl, false);
+ if (unlikely(err)) {
+ wl_clr_drv_status(wl, SCANNING, ndev);
+ goto out_err;
+ }
+ }
+
+ wl_set_drv_status(wl, SCANNING, ndev);
+#if FULL_ESCAN_ON_PFN_NET_FOUND
+ err = wl_do_escan(wl, wiphy, ndev, &request);
+#else
+ err = wl_do_escan(wl, wiphy, ndev, NULL);
+#endif
+ if (err) {
+ wl_clr_drv_status(wl, SCANNING, ndev);
+ goto out_err;
+ }
+ } else {
+ WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
+ }
+ wl->sched_scan_running = TRUE;
+ }
+
+ kfree(channel);
+ return 0;
+
+out_err:
+ if (channel)
+ kfree(channel);
+ return err;
+}
+#endif /* WL_SCHED_SCAN */
+
static void wl_init_conf(struct wl_conf *conf)
{
WL_DBG(("Enter \n"));
@@ -5257,7 +5543,9 @@ static void wl_init_event_handler(struct wl_priv *wl)
wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
+#ifdef PNO_SUPPORT
wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
+#endif /* PNO_SUPPORT */
}
static s32 wl_init_priv_mem(struct wl_priv *wl)
@@ -5559,7 +5847,7 @@ static void wl_scan_timeout(unsigned long data)
if (wl->scan_request) {
WL_ERR(("timer expired\n"));
if (wl->escan_on)
- wl_notify_escan_complete(wl, wl->escan_info.ndev, true);
+ wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
else
wl_notify_iscan_complete(wl_to_iscan(wl), true);
}
@@ -5629,23 +5917,70 @@ static struct notifier_block wl_cfg80211_netdev_notifier = {
.notifier_call = wl_cfg80211_netdev_notifier_call,
};
-static void wl_notify_escan_complete(struct wl_priv *wl,
+static s32 wl_notify_escan_complete(struct wl_priv *wl,
struct net_device *ndev,
- bool aborted)
+ bool aborted, bool fw_abort)
{
+ wl_scan_params_t *params = NULL;
+ s32 params_size = 0;
+ s32 err = BCME_OK;
unsigned long flags;
+ struct net_device *dev;
WL_DBG(("Enter \n"));
- wl_clr_drv_status(wl, SCANNING, ndev);
- if (p2p_is_on(wl))
- wl_clr_p2p_status(wl, SCANNING);
+
+ if (wl->scan_request) {
+ if (wl->scan_request->dev == wl->p2p_net)
+ dev = wl_to_prmry_ndev(wl);
+ else
+ dev = wl->scan_request->dev;
+ }
+ else {
+ WL_ERR(("wl->scan_request is NULL may be internal scan."
+ "doing scan_abort for ndev %p primary %p p2p_net %p",
+ ndev, wl_to_prmry_ndev(wl), wl->p2p_net));
+ dev = ndev;
+ }
+ if (fw_abort) {
+ /* Our scan params only need space for 1 channel and 0 ssids */
+ params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
+ if (params == NULL) {
+ WL_ERR(("scan params allocation failed \n"));
+ err = -ENOMEM;
+ } else {
+ /* Do a scan abort to stop the driver's scan engine */
+ err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
+ if (err < 0) {
+ WL_ERR(("scan abort failed \n"));
+ }
+ }
+ }
+ del_timer_sync(&wl->scan_timeout);
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
+
+#ifdef WL_SCHED_SCAN
+ if (wl->sched_scan_req && wl->sched_scan_running && !wl->scan_request) {
+ WL_DBG((" REPORTING SCHED SCAN RESULTS \n"));
+ cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
+ wl->sched_scan_running = FALSE;
+ wl->sched_scan_req = NULL;
+ wl->scan_request = NULL;
+ }
+#endif /* WL_SCHED_SCAN */
+
if (likely(wl->scan_request)) {
cfg80211_scan_done(wl->scan_request, aborted);
wl->scan_request = NULL;
}
+ if (p2p_is_on(wl))
+ wl_clr_p2p_status(wl, SCANNING);
+ wl_clr_drv_status(wl, SCANNING, dev);
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+ if (params)
+ kfree(params);
+
+ return err;
}
static s32 wl_escan_handler(struct wl_priv *wl,
@@ -5769,13 +6104,12 @@ static s32 wl_escan_handler(struct wl_priv *wl,
wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
if (wl->afx_hdl->peer_chan == WL_INVALID)
complete(&wl->act_frm_scan);
- } else if (likely(wl->scan_request)) {
+ } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
mutex_lock(&wl->usr_sync);
- del_timer_sync(&wl->scan_timeout);
WL_INFO(("ESCAN COMPLETED\n"));
wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
wl_inform_bss(wl);
- wl_notify_escan_complete(wl, ndev, false);
+ wl_notify_escan_complete(wl, ndev, false, false);
mutex_unlock(&wl->usr_sync);
}
}
@@ -5787,13 +6121,12 @@ static s32 wl_escan_handler(struct wl_priv *wl,
wl_clr_p2p_status(wl, SCANNING);
if (wl->afx_hdl->peer_chan == WL_INVALID)
complete(&wl->act_frm_scan);
- } else if (likely(wl->scan_request)) {
+ } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
mutex_lock(&wl->usr_sync);
- del_timer_sync(&wl->scan_timeout);
WL_INFO(("ESCAN ABORTED\n"));
wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
wl_inform_bss(wl);
- wl_notify_escan_complete(wl, ndev, true);
+ wl_notify_escan_complete(wl, ndev, true, false);
mutex_unlock(&wl->usr_sync);
}
}
@@ -5806,12 +6139,11 @@ static s32 wl_escan_handler(struct wl_priv *wl,
wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
if (wl->afx_hdl->peer_chan == WL_INVALID)
complete(&wl->act_frm_scan);
- } else if (likely(wl->scan_request)) {
+ } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
mutex_lock(&wl->usr_sync);
- del_timer_sync(&wl->scan_timeout);
wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
wl_inform_bss(wl);
- wl_notify_escan_complete(wl, ndev, true);
+ wl_notify_escan_complete(wl, ndev, true, false);
mutex_unlock(&wl->usr_sync);
}
}
@@ -6135,9 +6467,7 @@ static s32 wl_event_handler(void *data)
tsk_ctl_t *tsk = (tsk_ctl_t *)data;
wl = (struct wl_priv *)tsk->parent;
-
- DAEMONIZE("wl_event_handler");
-
+ DAEMONIZE("dhd_cfg80211_event");
complete(&tsk->completed);
while (down_interruptible (&tsk->sema) == 0) {
@@ -6166,7 +6496,7 @@ static s32 wl_event_handler(void *data)
}
DHD_OS_WAKE_UNLOCK(wl->pub);
}
- WL_DBG(("%s was terminated\n", __func__));
+ WL_ERR(("%s was terminated\n", __func__));
complete_and_exit(&tsk->completed, 0);
return 0;
}
@@ -6346,24 +6676,31 @@ eventmsg_out:
s32 wl_update_wiphybands(struct wl_priv *wl)
{
struct wiphy *wiphy;
- s8 phylist_buf[128];
- s8 *phy;
+ u32 bandlist[3];
+ u32 nband = 0;
+ u32 i = 0;
s32 err = 0;
-
- err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, phylist_buf,
- sizeof(phylist_buf), false);
+ WL_DBG(("Entry"));
+ memset(bandlist, 0, sizeof(bandlist));
+ err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist,
+ sizeof(bandlist), false);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
return err;
}
- phy = phylist_buf;
- for (; *phy; phy++) {
- if (*phy == 'a' || *phy == 'n') {
- wiphy = wl_to_wiphy(wl);
+ 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)
wiphy->bands[IEEE80211_BAND_5GHZ] =
&__wl_band_5ghz_a;
- }
+ else if (bandlist[i] == WLC_BAND_2G)
+ wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &__wl_band_2ghz;
}
+ wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
return err;
}
@@ -6373,7 +6710,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl)
struct net_device *ndev = wl_to_prmry_ndev(wl);
struct wireless_dev *wdev = ndev->ieee80211_ptr;
- WL_TRACE(("In\n"));
+ WL_DBG(("In\n"));
err = dhd_config_dongle(wl, false);
if (unlikely(err))
@@ -6401,7 +6738,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
struct net_info *iter, *next;
struct net_device *ndev = wl_to_prmry_ndev(wl);
- WL_TRACE(("In\n"));
+ WL_DBG(("In\n"));
/* Check if cfg80211 interface is already down */
if (!wl_get_drv_status(wl, READY, ndev))
return err; /* it is even not ready */
@@ -6443,7 +6780,7 @@ s32 wl_cfg80211_up(void *para)
struct wl_priv *wl;
s32 err = 0;
- WL_TRACE(("In\n"));
+ WL_DBG(("In\n"));
wl = wlcfg_drv_priv;
mutex_lock(&wl->usr_sync);
wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
@@ -6473,7 +6810,7 @@ s32 wl_cfg80211_down(void *para)
struct wl_priv *wl;
s32 err = 0;
- WL_TRACE(("In\n"));
+ WL_DBG(("In\n"));
wl = wlcfg_drv_priv;
mutex_lock(&wl->usr_sync);
err = __wl_cfg80211_down(wl);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 2b8e66413f23..435d61833f1a 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -442,6 +442,10 @@ struct wl_priv {
bool p2p_supported;
struct btcoex_info *btcoex_info;
struct timer_list scan_timeout; /* Timer for catch scan event timeout */
+#ifdef WL_SCHED_SCAN
+ struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */
+#endif /* WL_SCHED_SCAN */
+ bool sched_scan_running; /* scheduled scan req status */
};
static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index d09448a7932f..e724aa3ec725 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -162,11 +162,8 @@ uint wl_msg_level = WL_ERROR_VAL;
#define htodchanspec(i) i
#define dtohchanspec(i) i
-#ifdef CONFIG_WIRELESS_EXT
-
extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
extern int dhd_wait_pend8021x(struct net_device *dev);
-#endif
#if WIRELESS_EXT < 19
#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)