summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2011-09-13 15:51:00 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:39:05 -0800
commit09a6b855bd70cca4bcbb1b4602b079b27ea369c8 (patch)
tree7fa8a9ab7cdc6eadaae85f5d6f0300b128b39d46
parent7ca8f00d682d3a73250b415ddd96fb34624742f2 (diff)
net: wireless: bcmdhd: Update to Version 5.90.125.84
- Fix no scan problem for cfg80211 when Scan Event missed - Improve logic to generate Event via cfg80211 when FW hangs - Fix a crash on Android driver removal - DHD read has chance to crash under long stress : fix (dhd_sdio.c) - Fix power consumption issue as sending disassoc explicitly - Change the logic for listen timer to solve memory leak and guarantee listen timing - Adding wl_cfg80211_get_station for HostAPD Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c11
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c8
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cdc.c13
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c12
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c39
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c40
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h8
-rw-r--r--drivers/net/wireless/bcmdhd/include/linuxver.h2
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h43
-rw-r--r--drivers/net/wireless/bcmdhd/linux_osl.c34
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c54
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c397
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h15
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c53
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h15
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.c9
16 files changed, 512 insertions, 241 deletions
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
index 8c328b88e3e5..a48e85c774dc 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
@@ -198,9 +198,14 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd)
sdio_release_host(gInstance->func[2]);
/* Disable Function 1 */
- sdio_claim_host(gInstance->func[1]);
- sdio_disable_func(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
+ if (gInstance->func[1]) {
+ sdio_claim_host(gInstance->func[1]);
+ sdio_disable_func(gInstance->func[1]);
+ sdio_release_host(gInstance->func[1]);
+ }
+
+ gInstance->func[1] = NULL;
+ gInstance->func[2] = NULL;
/* deregister irq */
sdioh_sdmmc_osfree(sd);
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
index c73e04cd635c..8baa60bf24f2 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
@@ -26,7 +26,7 @@
#include <typedefs.h>
#include <bcmutils.h>
-#include <sdio.h> /* SDIO Specs */
+#include <sdio.h> /* SDIO Device and Protocol Specs */
#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
#include <sdiovar.h> /* to get msglevel bit values */
@@ -133,6 +133,11 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func)
if (func->num == 2) {
sd_trace(("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;
}
}
@@ -259,7 +264,6 @@ int sdio_function_init(void)
error = sdio_register_driver(&bcmsdh_sdmmc_driver);
-
return error;
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c
index 67d9481a21be..3a4de96c0028 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cdc.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c
@@ -53,7 +53,7 @@
* defined in dhd_sdio.c (amount of header tha might be added)
* plus any space that might be needed for alignment padding.
*/
-#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for
+#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for
* round off at the end of buffer
*/
@@ -68,6 +68,7 @@ typedef struct dhd_wlfc_commit_info {
void* p;
} dhd_wlfc_commit_info_t;
#endif /* PROP_TXSTATUS */
+
typedef struct dhd_prot {
uint16 reqid;
uint8 pending;
@@ -218,6 +219,7 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len));
+
if (dhd->busstate == DHD_BUS_DOWN) {
DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
return -EIO;
@@ -287,7 +289,6 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
goto done;
}
-
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
ASSERT(len <= WLC_IOCTL_MAXLEN);
@@ -1333,6 +1334,7 @@ _dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, uint8 available_credit_map
return rc;
}
+
int
dhd_wlfc_interface_entry_update(void* state,
ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea)
@@ -1444,6 +1446,7 @@ _dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac,
return rc;
}
+
int
dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx)
{
@@ -1808,6 +1811,7 @@ dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info)
/* pick up the implicit credit from this packet */
if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) {
if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) {
+
int lender, credit_returned = 0; /* Note that borrower is fifo_id */
/* Return credits to highest priority lender first */
@@ -2227,7 +2231,7 @@ dhd_wlfc_enable(dhd_pub_t *dhd)
wlfc->hostif_flow_state[i] = OFF;
}
- /*
+ /*
create the SENDQ containing
sub-queues for all AC precedences + 1 for bc/mc traffic
*/
@@ -2497,7 +2501,6 @@ dhd_prot_init(dhd_pub_t *dhd)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
/* Get the device rev info */
memset(&revinfo, 0, sizeof(revinfo));
ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
@@ -2509,7 +2512,7 @@ dhd_prot_init(dhd_pub_t *dhd)
ret = dhd_wlfc_init(dhd);
#endif
-#ifndef WL_CFG80211
+#if !defined(WL_CFG80211)
ret = dhd_preinit_ioctls(dhd);
#endif /* WL_CFG80211 */
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index 94d32627132b..99962671ae47 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -1432,7 +1432,8 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
__FUNCTION__, arp_enable));
}
-void dhd_aoe_arp_clr(dhd_pub_t *dhd)
+void
+dhd_aoe_arp_clr(dhd_pub_t *dhd)
{
int ret = 0;
int iov_len = 0;
@@ -1445,7 +1446,8 @@ void dhd_aoe_arp_clr(dhd_pub_t *dhd)
DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
}
-void dhd_aoe_hostip_clr(dhd_pub_t *dhd)
+void
+dhd_aoe_hostip_clr(dhd_pub_t *dhd)
{
int ret = 0;
int iov_len = 0;
@@ -1458,7 +1460,8 @@ void dhd_aoe_hostip_clr(dhd_pub_t *dhd)
DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
}
-void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr)
+void
+dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr)
{
int iov_len = 0;
char iovbuf[32];
@@ -1475,7 +1478,8 @@ void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr)
__FUNCTION__));
}
-int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
+int
+dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
{
int retcode, i;
int iov_len = 0;
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 6f19cb726490..42f3528dba88 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -89,6 +89,7 @@ typedef struct histo_ {
#if !ISPOWEROF2(DHD_SDALIGN)
#error DHD_SDALIGN is not a power of 2!
#endif
+
static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
#endif /* WLMEDIA_HTSF */
@@ -1412,7 +1413,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
continue;
}
-
pnext = PKTNEXT(dhdp->osh, pktbuf);
PKTSETNEXT(wl->sh.osh, pktbuf, NULL);
@@ -2192,6 +2192,7 @@ done:
return OSL_ERROR(bcmerror);
}
+#ifdef WL_CFG80211
static int
dhd_cleanup_virt_ifaces(dhd_info_t *dhd)
{
@@ -2226,6 +2227,7 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd)
return 0;
}
+#endif /* WL_CFG80211 */
static int
dhd_stop(struct net_device *net)
@@ -2666,7 +2668,9 @@ dhd_bus_start(dhd_pub_t *dhdp)
DHD_TRACE(("Enter %s:\n", __FUNCTION__));
+#ifdef DHDTHREAD
dhd_os_sdlock(dhdp);
+#endif /* DHDTHREAD */
/* try to download image and nvram to the dongle */
if ((dhd->pub.busstate == DHD_BUS_DOWN) &&
@@ -2677,12 +2681,16 @@ dhd_bus_start(dhd_pub_t *dhdp)
fw_path, nv_path))) {
DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
__FUNCTION__, fw_path, nv_path));
+#ifdef DHDTHREAD
dhd_os_sdunlock(dhdp);
+#endif /* DHDTHREAD */
return -1;
}
}
if (dhd->pub.busstate != DHD_BUS_LOAD) {
+#ifdef DHDTHREAD
dhd_os_sdunlock(dhdp);
+#endif /* DHDTHREAD */
return -ENETDOWN;
}
@@ -2692,21 +2700,27 @@ dhd_bus_start(dhd_pub_t *dhdp)
/* Bring up the bus */
if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) {
+
DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret));
+#ifdef DHDTHREAD
dhd_os_sdunlock(dhdp);
+#endif /* DHDTHREAD */
return ret;
}
#if defined(OOB_INTR_ONLY)
/* Host registration for OOB interrupt */
if (bcmsdh_register_oob_intr(dhdp)) {
/* deactivate timer and wait for the handler to finish */
+
flags = dhd_os_spin_lock(&dhd->pub);
dhd->wd_timer_valid = FALSE;
dhd_os_spin_unlock(&dhd->pub, flags);
del_timer_sync(&dhd->timer);
DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__));
+#ifdef DHDTHREAD
dhd_os_sdunlock(dhdp);
+#endif /* DHDTHREAD */
return -ENODEV;
}
@@ -2721,11 +2735,15 @@ dhd_bus_start(dhd_pub_t *dhdp)
dhd_os_spin_unlock(&dhd->pub, flags);
del_timer_sync(&dhd->timer);
DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
+#ifdef DHDTHREAD
dhd_os_sdunlock(dhdp);
+#endif /* DHDTHREAD */
return -ENODEV;
}
+#ifdef DHDTHREAD
dhd_os_sdunlock(dhdp);
+#endif /* DHDTHREAD */
#ifdef READ_MACADDR
dhd_read_macaddr(dhd);
@@ -2960,6 +2978,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
setbit(eventmask, WLC_E_AUTH);
setbit(eventmask, WLC_E_REASSOC);
setbit(eventmask, WLC_E_REASSOC_IND);
+ setbit(eventmask, WLC_E_DEAUTH);
setbit(eventmask, WLC_E_DEAUTH_IND);
setbit(eventmask, WLC_E_DISASSOC_IND);
setbit(eventmask, WLC_E_DISASSOC);
@@ -3195,6 +3214,12 @@ static int dhd_device_event(struct notifier_block *this,
DHD_ARPOE(("%s: [%s] Up IP: 0x%x\n",
__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
+ /* firmware not downloaded, do nothing */
+ if (dhd->pub.busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s: bus is down, exit\n", __FUNCTION__));
+ break;
+ }
+
#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",
@@ -3415,10 +3440,16 @@ void dhd_detach(dhd_pub_t *dhdp)
/* delete all interfaces, start with virtual */
if (dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) {
+ int i = 1;
dhd_if_t *ifp;
- /* Cleanup all virtual Interfaces */
- dhd_cleanup_virt_ifaces(dhd);
+ /* Cleanup virtual interfaces */
+ for (i = 1; i < DHD_MAX_IFS; i++)
+ if (dhd->iflist[i]) {
+ dhd->iflist[i]->state = WLC_E_IF_DEL;
+ dhd->iflist[i]->idx = i;
+ dhd_op_if(dhd->iflist[i]);
+ }
/* delete primary interface 0 */
ifp = dhd->iflist[0];
@@ -4348,7 +4379,7 @@ int dhd_os_wake_lock_timeout(dhd_pub_t *pub)
#ifdef CONFIG_HAS_WAKELOCK
if (dhd->wakelock_timeout_enable)
wake_lock_timeout(&dhd->wl_rxwake,
- dhd->wakelock_timeout_enable * HZ);
+ dhd->wakelock_timeout_enable * HZ);
#endif
dhd->wakelock_timeout_enable = 0;
spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index cdb244837c01..37ab6805d6d9 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -380,7 +380,6 @@ static const uint max_roundup = 512;
/* Try doing readahead */
static bool dhd_readahead;
-
/* To check if there's window offered */
#define DATAOK(bus) \
(((uint8)(bus->tx_max - bus->tx_seq) > 2) && \
@@ -2021,7 +2020,8 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
bcm_bprintf(&strbuf,
"Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
"lp 0x%x, rpc 0x%x Trap offset 0x%x, "
- "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
+ "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
+ "r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr),
ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc),
ltoh32(sdpcm_shared.trap_addr),
@@ -2029,30 +2029,35 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7));
addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log);
- if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr,
+ (uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
goto printbuf;
addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.buf_size);
- if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&console_size, sizeof(console_size))) < 0)
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr,
+ (uint8 *)&console_size, sizeof(console_size))) < 0)
goto printbuf;
addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.idx);
- if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&console_index, sizeof(console_index))) < 0)
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr,
+ (uint8 *)&console_index, sizeof(console_index))) < 0)
goto printbuf;
console_ptr = ltoh32(console_ptr);
console_size = ltoh32(console_size);
console_index = ltoh32(console_index);
- if (console_size > CONSOLE_BUFFER_MAX || !(console_buffer = MALLOC(bus->dhd->osh, console_size)))
+ if (console_size > CONSOLE_BUFFER_MAX ||
+ !(console_buffer = MALLOC(bus->dhd->osh, console_size)))
goto printbuf;
- if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr, (uint8 *)console_buffer, console_size)) < 0)
+ if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr,
+ (uint8 *)console_buffer, console_size)) < 0)
goto printbuf;
- for ( i = 0, n = 0; i < console_size; i += n + 1 ) {
+ for (i = 0, n = 0; i < console_size; i += n + 1) {
for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
- ch = console_buffer[ (console_index + i + n) % console_size];
+ ch = console_buffer[(console_index + i + n) % console_size];
if (ch == '\n')
break;
line[n] = ch;
@@ -2063,8 +2068,10 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
if (line[n - 1] == '\r')
n--;
line[n] = 0;
- /* Don't use DHD_ERROR macro since we print a lot of information quickly */
- /* The macro will truncate a lot of the printfs */
+ /* Don't use DHD_ERROR macro since we print
+ * a lot of information quickly. The macro
+ * will truncate a lot of the printfs
+ */
if (dhd_msg_level & DHD_ERROR_VAL)
printf("CONSOLE: %s\n", line);
@@ -3541,7 +3548,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
if ((uint8)(txmax - bus->tx_seq) > 0x40) {
DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
__FUNCTION__, txmax, bus->tx_seq));
- txmax = bus->tx_seq + 2;
+ txmax = bus->tx_seq;
}
bus->tx_max = txmax;
@@ -3962,7 +3969,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
if ((uint8)(txmax - bus->tx_seq) > 0x40) {
DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
__FUNCTION__, txmax, bus->tx_seq));
- txmax = bus->tx_seq + 2;
+ txmax = bus->tx_seq;
}
bus->tx_max = txmax;
@@ -4119,7 +4126,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
if ((uint8)(txmax - bus->tx_seq) > 0x40) {
DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
__FUNCTION__, txmax, bus->tx_seq));
- txmax = bus->tx_seq + 2;
+ txmax = bus->tx_seq;
}
bus->tx_max = txmax;
@@ -6182,8 +6189,9 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
if (bus->dhd->dongle_reset) {
/* Turn on WLAN */
+#ifdef DHDTHREAD
dhd_os_sdlock(dhdp);
-
+#endif /* DHDTHREAD */
/* Reset SD client */
bcmsdh_reset(bus->sdh);
@@ -6223,7 +6231,9 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
} else
bcmerror = BCME_SDIO_ERROR;
+#ifdef DHDTHREAD
dhd_os_sdunlock(dhdp);
+#endif /* DHDTHREAD */
} else {
bcmerror = BCME_SDIO_ERROR;
DHD_INFO(("%s called when dongle is not in reset\n",
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index ab96c0740e5a..60f842c6d968 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 125
-#define EPI_INCREMENTAL_NUMBER 78
+#define EPI_INCREMENTAL_NUMBER 84
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 5, 90, 125, 78
+#define EPI_VERSION 5, 90, 125, 84
-#define EPI_VERSION_NUM 0x055a7d4e
+#define EPI_VERSION_NUM 0x055a7d54
#define EPI_VERSION_DEV 5.90.125
-#define EPI_VERSION_STR "5.90.125.78"
+#define EPI_VERSION_STR "5.90.125.84"
#endif
diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h
index e1c62b73f155..96844db2f059 100644
--- a/drivers/net/wireless/bcmdhd/include/linuxver.h
+++ b/drivers/net/wireless/bcmdhd/include/linuxver.h
@@ -70,7 +70,9 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
#include <linux/semaphore.h>
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
#undef IP_TOS
#endif
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index 1059de147efd..9357552c9194 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -657,6 +657,49 @@ typedef struct wl_assoc_info {
#define WLC_ASSOC_REQ_IS_REASSOC 0x01
+typedef struct {
+ uint16 ver;
+ uint16 len;
+ uint16 cap;
+ uint32 flags;
+ uint32 idle;
+ struct ether_addr ea;
+ wl_rateset_t rateset;
+ uint32 in;
+ uint32 listen_interval_inms;
+ uint32 tx_pkts;
+ uint32 tx_failures;
+ uint32 rx_ucast_pkts;
+ uint32 rx_mcast_pkts;
+ uint32 tx_rate;
+ uint32 rx_rate;
+ uint32 rx_decrypt_succeeds;
+ uint32 rx_decrypt_failures;
+} sta_info_t;
+
+#define WL_OLD_STAINFO_SIZE OFFSETOF(sta_info_t, tx_pkts)
+
+#define WL_STA_VER 3
+
+
+#define WL_STA_BRCM 0x1
+#define WL_STA_WME 0x2
+#define WL_STA_ABCAP 0x4
+#define WL_STA_AUTHE 0x8
+#define WL_STA_ASSOC 0x10
+#define WL_STA_AUTHO 0x20
+#define WL_STA_WDS 0x40
+#define WL_STA_WDS_LINKUP 0x80
+#define WL_STA_PS 0x100
+#define WL_STA_APSD_BE 0x200
+#define WL_STA_APSD_BK 0x400
+#define WL_STA_APSD_VI 0x800
+#define WL_STA_APSD_VO 0x1000
+#define WL_STA_N_CAP 0x2000
+#define WL_STA_SCBSTATS 0x4000
+
+#define WL_WDS_LINKUP WL_STA_WDS_LINKUP
+
#define WLC_TXFILTER_OVERRIDE_DISABLED 0
#define WLC_TXFILTER_OVERRIDE_ENABLED 1
diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c
index 17b68e5d3e55..1a544378c1e6 100644
--- a/drivers/net/wireless/bcmdhd/linux_osl.c
+++ b/drivers/net/wireless/bcmdhd/linux_osl.c
@@ -68,6 +68,7 @@ typedef struct bcm_static_pkt {
struct semaphore osl_pkt_sem;
unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2];
} bcm_static_pkt_t;
+
static bcm_static_pkt_t *bcm_static_skb = 0;
#endif
@@ -169,10 +170,14 @@ osl_t *
osl_attach(void *pdev, uint bustype, bool pkttag)
{
osl_t *osh;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
gfp_t flags;
flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
osh = kmalloc(sizeof(osl_t), flags);
+#else
+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
+#endif
ASSERT(osh);
bzero(osh, sizeof(osl_t));
@@ -218,13 +223,10 @@ osl_attach(void *pdev, uint bustype, bool pkttag)
sema_init(&bcm_static_buf->static_sem, 1);
-
bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
-
}
- if (!bcm_static_skb)
- {
+ if (!bcm_static_skb) {
int i;
void *skb_buff_ptr = 0;
bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
@@ -251,7 +253,7 @@ osl_detach(osl_t *osh)
kfree(osh);
}
-struct sk_buff *osl_alloc_skb(unsigned int len)
+static struct sk_buff *osl_alloc_skb(unsigned int len)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
@@ -325,10 +327,14 @@ osl_ctfpool_replenish(osl_t *osh, uint thresh)
int32
osl_ctfpool_init(osl_t *osh, uint numobj, uint size)
{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
gfp_t flags;
flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
osh->ctfpool = kmalloc(sizeof(ctfpool_t), flags);
+#else
+ osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC);
+#endif
ASSERT(osh->ctfpool);
bzero(osh->ctfpool, sizeof(ctfpool_t));
@@ -543,20 +549,17 @@ osl_pktfree(osl_t *osh, void *p, bool send)
}
#ifdef DHD_USE_STATIC_BUF
-void*
+void *
osl_pktget_static(osl_t *osh, uint len)
{
- int i = 0;
+ int i;
struct sk_buff *skb;
-
if (len > (PAGE_SIZE * 2)) {
printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len);
- printk("Do we really need this big skb??\n");
return osl_pktget(osh, len);
}
-
down(&bcm_static_skb->osl_pkt_sem);
if (len <= PAGE_SIZE) {
@@ -614,7 +617,6 @@ osl_pktfree_static(osl_t *osh, void *p, bool send)
down(&bcm_static_skb->osl_pkt_sem);
bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0;
up(&bcm_static_skb->osl_pkt_sem);
-
return;
}
}
@@ -622,6 +624,7 @@ osl_pktfree_static(osl_t *osh, void *p, bool send)
return osl_pktfree(osh, p, send);
}
#endif
+
uint32
osl_pci_read_config(osl_t *osh, uint offset, uint size)
{
@@ -702,13 +705,18 @@ void *
osl_malloc(osl_t *osh, uint size)
{
void *addr;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
gfp_t flags;
+
if (osh)
ASSERT(osh->magic == OS_HANDLE_MAGIC);
flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
if ((addr = kmalloc(size, flags)) == NULL) {
+#else
+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
+#endif
if (osh)
osh->failed++;
return (NULL);
@@ -836,10 +844,14 @@ void *
osl_pktdup(osl_t *osh, void *skb)
{
void * p;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
gfp_t flags;
flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
if ((p = skb_clone((struct sk_buff *)skb, flags)) == NULL)
+#else
+ if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL)
+#endif
return NULL;
#ifdef CTFPOOL
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 36110f954b5f..8bc6b361e868 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -110,7 +110,8 @@ void dhd_dev_init_ioctl(struct net_device *dev);
int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command);
#else
-int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) { return 0; }
+int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
+{ return 0; }
#endif
extern bool ap_fw_loaded;
@@ -158,6 +159,7 @@ static int wl_android_get_rssi(struct net_device *net, char *command, int total_
error = wldev_get_rssi(net, &rssi);
if (error)
return -1;
+
error = wldev_get_ssid(net, &ssid);
if (error)
return -1;
@@ -187,7 +189,7 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int
if (ret_now != suspend_flag) {
if (!(ret = net_os_set_suspend(dev, ret_now)))
DHD_INFO(("%s: Suspend Flag %d -> %d\n",
- __FUNCTION__, ret_now, suspend_flag));
+ __FUNCTION__, ret_now, suspend_flag));
else
DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
}
@@ -220,6 +222,27 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t
int pno_repeat = 0;
int pno_freq_expo_max = 0;
+#ifdef PNO_SET_DEBUG
+ int i;
+ char pno_in_example[] = {
+ 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
+ 'S', '1', '2', '0',
+ 'S',
+ 0x05,
+ 'd', 'l', 'i', 'n', 'k',
+ 'S',
+ 0x04,
+ 'G', 'O', 'O', 'G',
+ 'T',
+ '0', 'B',
+ 'R',
+ '2',
+ 'M',
+ '2',
+ 0x00
+ };
+#endif /* PNO_SET_DEBUG */
+
DHD_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
@@ -227,6 +250,14 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t
goto exit_proc;
}
+#ifdef PNO_SET_DEBUG
+ memcpy(command, pno_in_example, sizeof(pno_in_example));
+ for (i = 0; i < sizeof(pno_in_example); i++)
+ printf("%02X ", command[i]);
+ printf("\n");
+ total_len = sizeof(pno_in_example);
+#endif
+
str_ptr = command + strlen(CMD_PNOSETUP_SET);
tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
@@ -448,7 +479,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
/* TBD: BTCOEXSCAN-STOP */
}
else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) {
- /* TBD: BTCOEXMODE */
uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
if (mode == 1)
@@ -527,8 +557,10 @@ int wl_android_init(void)
dhd_download_fw_on_driverload = FALSE;
#endif /* ENABLE_INSMOD_NO_FW_LOAD */
#ifdef CUSTOMER_HW2
- if (!iface_name[0])
+ if (!iface_name[0]) {
+ memset(iface_name, 0, IFNAMSIZ);
bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
+ }
#endif /* CUSTOMER_HW2 */
return ret;
}
@@ -542,12 +574,24 @@ int wl_android_exit(void)
int wl_android_post_init(void)
{
+ struct net_device *ndev;
int ret = 0;
+ char buf[IFNAMSIZ];
if (!dhd_download_fw_on_driverload) {
/* Call customer gpio to turn off power with WL_REG_ON signal */
dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
g_wifi_on = 0;
-
+ } else {
+ memset(buf, 0, IFNAMSIZ);
+#ifdef CUSTOMER_HW2
+ snprintf(buf, IFNAMSIZ, "%s%d", iface_name, 0);
+#else
+ snprintf(buf, IFNAMSIZ, "%s%d", "eth", 0);
+#endif
+ if ((ndev = dev_get_by_name (&init_net, buf)) != NULL) {
+ dhd_dev_init_ioctl(ndev);
+ dev_put(ndev);
+ }
}
return ret;
}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 8a77231d5a32..13530d2063db 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -52,7 +52,6 @@
#include <proto/ethernet.h>
#include <dngl_stats.h>
#include <dhd.h>
-
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/netdevice.h>
@@ -80,7 +79,6 @@ u32 wl_dbg_level = WL_DBG_ERR;
#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4-218-248-5.bin"
#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4-218-248-5.txt"
-#define WL_TRACE(a) printk("%s ", __FUNCTION__); printk a
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAX_WAIT_TIME 1500
@@ -1318,7 +1316,7 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
iscan->ioctl_buf, WLC_IOCTL_MEDLEN);
if (unlikely(err)) {
if (err == -EBUSY) {
- WL_INFO(("system busy : iscan canceled\n"));
+ WL_ERR(("system busy : iscan canceled\n"));
} else {
WL_ERR(("error (%d)\n", err));
}
@@ -1498,6 +1496,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
s32 i;
u32 wpsie_len = 0;
u8 wpsie[IE_MAX_LEN];
+
+ WL_DBG(("Enter wiphy (%p)\n", wiphy));
if (unlikely(wl_get_drv_status(wl, SCANNING))) {
WL_ERR(("Scanning already : status (%d)\n", (int)wl->status));
return -EAGAIN;
@@ -1512,8 +1512,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
return -EOPNOTSUPP;
}
- WL_DBG(("wiphy (%p)\n", wiphy));
-
+ /* Arm scan timeout timer */
+ mod_timer(&wl->scan_timeout, jiffies + WL_SCAN_TIMER_INTERVAL_MS * HZ / 1000);
iscan_req = false;
spec_scan = false;
if (request) { /* scan bss */
@@ -1640,7 +1640,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
sizeof(sr->ssid), false);
if (err) {
if (err == -EBUSY) {
- WL_INFO(("system busy : scan for \"%s\" "
+ WL_ERR(("system busy : scan for \"%s\" "
"canceled\n", sr->ssid.SSID));
} else {
WL_ERR(("WLC_SCAN error (%d)\n", err));
@@ -2240,24 +2240,34 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
wl->channel = 0;
WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
err = wl_set_wpa_version(dev, sme);
- if (unlikely(err))
+ if (unlikely(err)) {
+ WL_ERR(("Invalid wpa_version\n"));
return err;
+ }
err = wl_set_auth_type(dev, sme);
- if (unlikely(err))
+ if (unlikely(err)) {
+ WL_ERR(("Invalid auth type\n"));
return err;
+ }
err = wl_set_set_cipher(dev, sme);
- if (unlikely(err))
+ if (unlikely(err)) {
+ WL_ERR(("Invalid ciper\n"));
return err;
+ }
err = wl_set_key_mgmt(dev, sme);
- if (unlikely(err))
+ if (unlikely(err)) {
+ WL_ERR(("Invalid key mgmt\n"));
return err;
+ }
err = wl_set_set_sharedkey(dev, sme);
- if (unlikely(err))
+ if (unlikely(err)) {
+ WL_ERR(("Invalid shared key\n"));
return err;
+ }
wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
/*
@@ -2284,7 +2294,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
join_params.ssid.SSID_len));
}
wl_set_drv_status(wl, CONNECTING);
- err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, false);
+ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
wl_clr_drv_status(wl, CONNECTING);
@@ -2317,7 +2327,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
scbval.val = htod32(scbval.val);
err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
- sizeof(scb_val_t), false);
+ sizeof(scb_val_t), true);
if (unlikely(err)) {
wl_clr_drv_status(wl, DISCONNECTING);
WL_ERR(("error (%d)\n", err));
@@ -2359,7 +2369,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
/* Make sure radio is off or on as far as software is concerned */
disable = WL_RADIO_SW_DISABLE << 16;
disable = htod32(disable);
- err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), false);
+ err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
return err;
@@ -2422,7 +2432,7 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
index = (u32) key_idx;
index = htod32(index);
err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
- sizeof(index), false);
+ sizeof(index), true);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
}
@@ -2616,16 +2626,6 @@ exit:
return err;
}
-#ifdef NOT_YET
- /* TODO: Removed in P2P, check later --lm */
- val = 1; /* assume shared key. otherwise 0 */
- val = htod32(val);
- err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), false);
- if (unlikely(err)) {
- WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
- return err;
- }
-#endif
return err;
}
@@ -2734,51 +2734,72 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
{
struct wl_priv *wl = wiphy_priv(wiphy);
scb_val_t scb_val;
- int rssi;
+ s32 rssi;
s32 rate;
s32 err = 0;
+ sta_info_t *sta;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+ s8 eabuf[ETHER_ADDR_STR_LEN];
+#endif
CHECK_SYS_UP(wl);
- if (unlikely
- (memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) {
- WL_ERR(("Wrong Mac address\n"));
- return -ENOENT;
- }
-
- /* 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)));
- }
-
- if (wl_get_drv_status(wl, CONNECTED)) {
- 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 (unlikely(err)) {
- WL_ERR(("Could not get rssi (%d)\n", err));
+ if (get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
+ err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
+ ETHER_ADDR_LEN, ioctlbuf, sizeof(ioctlbuf));
+ if (err < 0) {
+ WL_ERR(("GET STA INFO failed, %d\n", err));
return err;
}
- rssi = dtoh32(scb_val.val);
- sinfo->filled |= STATION_INFO_SIGNAL;
- sinfo->signal = rssi;
- WL_DBG(("RSSI %d dBm\n", rssi));
- }
-
-#if defined(ANDROID_WIRELESS_PATCH)
- err = wldev_ioctl(dev, WLC_GET_RATE, &sinfo->link_speed, sizeof(sinfo->link_speed), false);
- sinfo->link_speed = sinfo->link_speed / 2; /* Convert internal 500Kbps to Mpbs */
- if (!err)
- sinfo->filled |= STATION_LINK_SPEED;
- else
- WL_ERR(("WLC_GET_RATE failed\n"));
+ sinfo->filled = STATION_INFO_INACTIVE_TIME;
+ sta = (sta_info_t *)ioctlbuf;
+ sta->len = dtoh16(sta->len);
+ sta->cap = dtoh16(sta->cap);
+ sta->flags = dtoh32(sta->flags);
+ sta->idle = dtoh32(sta->idle);
+ sta->in = dtoh32(sta->in);
+ sinfo->inactive_time = sta->idle * 1000;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+ if (sta->flags & WL_STA_ASSOC) {
+ sinfo->filled |= STATION_INFO_CONNECTED_TIME;
+ sinfo->connected_time = sta->in;
+ }
+ WL_INFO(("STA %s : idle time : %d sec, connected time :%d ms\n",
+ bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
+ sta->idle * 1000));
#endif
+ } else if (get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {
+ if (memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID),
+ ETHER_ADDR_LEN)) {
+ WL_ERR(("Wrong Mac address\n"));
+ return -ENOENT;
+ }
+
+ /* 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)));
+ }
+
+ if (wl_get_drv_status(wl, CONNECTED)) {
+ 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));
+ return err;
+ }
+ rssi = dtoh32(scb_val.val);
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ sinfo->signal = rssi;
+ WL_DBG(("RSSI %d dBm\n", rssi));
+ }
+ }
return err;
}
@@ -2800,7 +2821,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
}
pm = htod32(pm);
WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
- err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), false);
+ err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
if (unlikely(err)) {
if (err == -ENODEV)
WL_DBG(("net_device is not ready yet\n"));
@@ -2862,6 +2883,8 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
{
struct wl_priv *wl = wiphy_priv(wiphy);
struct net_device *ndev = wl_to_prmry_ndev(wl);
+ unsigned long flags;
+
if (unlikely(!wl_get_drv_status(wl, READY))) {
WL_INFO(("device is not ready : status (%d)\n",
(int)wl->status));
@@ -2875,16 +2898,14 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
wl_delay(500);
return -EAGAIN;
}
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
if (wl->scan_request) {
cfg80211_scan_done(wl->scan_request, true);
wl->scan_request = NULL;
- /* Make sure WPA_supplicant receives scan abort event */
- wl_delay(500);
- return -EAGAIN;
}
wl_clr_drv_status(wl, SCANNING);
wl_clr_drv_status(wl, SCAN_ABORTING);
-
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
return 0;
}
@@ -3054,12 +3075,14 @@ wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
*out_params_size = params_size; /* rtn size to the caller */
return params;
}
+
s32
wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev)
{
wl_scan_params_t *params;
s32 params_size;
s32 err = BCME_OK;
+ unsigned long flags;
WL_DBG(("Enter\n"));
@@ -3070,13 +3093,22 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev)
err = -ENOMEM;
}
/* Do a scan abort to stop the driver's scan engine */
- err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, false);
+ err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, true);
if (err < 0) {
WL_ERR(("scan abort failed \n"));
}
+ del_timer_sync(&wl->scan_timeout);
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
+ if (wl->scan_request) {
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ }
+ wl_clr_drv_status(wl, SCANNING);
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
return err;
}
+
static s32
wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel * channel,
@@ -3322,7 +3354,7 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
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));
- wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), false);
+ wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), true);
return err;
}
@@ -3578,7 +3610,7 @@ exit:
}
static s32
-wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
struct beacon_parameters *info)
{
s32 err = BCME_OK;
@@ -3654,8 +3686,6 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
}
wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
beacon_ie, wpsie_len + p2pie_len);
- wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_ASSOCRSP_FLAG,
- beacon_ie, wpsie_len + p2pie_len);
/* find the RSN_IE */
if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
@@ -3670,7 +3700,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
WL_ERR(("WPA2 IE parsing error"));
goto exit;
}
- err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false);
+ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
if (err < 0) {
WL_ERR(("SET INFRA error %d\n", err));
goto exit;
@@ -3698,9 +3728,9 @@ wl_cfg80211_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), false);
- wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false);
- if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), false)) < 0) {
+ wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
+ wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+ if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
WL_ERR(("setting AP mode failed %d \n", err));
return err;
}
@@ -3756,7 +3786,21 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
} else {
WL_DBG(("No WPSIE in beacon \n"));
}
- err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), false);
+ if (info->interval) {
+ if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
+ &info->interval, sizeof(s32), true)) < 0) {
+ WL_ERR(("Beacon Interval Set Error, %d\n", err));
+ return err;
+ }
+ }
+ if (info->dtim_period) {
+ if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
+ &info->dtim_period, sizeof(s32), true)) < 0) {
+ WL_ERR(("DTIM Interval Set Error, %d\n", err));
+ return err;
+ }
+ }
+ err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
if (unlikely(err)) {
WL_ERR(("WLC_UP error (%d)\n", err));
return err;
@@ -3768,7 +3812,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
join_params.ssid.SSID_len = htod32(ssid.SSID_len);
/* create softap */
if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
- join_params_size, false)) == 0) {
+ join_params_size, true)) == 0) {
wl_clr_drv_status(wl, AP_CREATING);
wl_set_drv_status(wl, AP_CREATED);
}
@@ -3880,26 +3924,6 @@ exit:
return err;
}
-#if defined(ANDROID_WIRELESS_PATCH)
-static s32
-wl_cfg80211_drv_start(struct wiphy *wiphy, struct net_device *dev)
-{
- s32 err = 0;
-
- printk("Android driver start command\n");
- return err;
-}
-
-static s32
-wl_cfg80211_drv_stop(struct wiphy *wiphy, struct net_device *dev)
-{
- s32 err = 0;
-
- printk("Android driver stop command\n");
- return err;
-}
-#endif /* defined(ANDROID_WIRELESS_PATCH) */
-
static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = wl_cfg80211_add_virtual_iface,
.del_virtual_intf = wl_cfg80211_del_virtual_iface,
@@ -3930,11 +3954,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
.change_bss = wl_cfg80211_change_bss,
.set_channel = wl_cfg80211_set_channel,
- .set_beacon = wl_cfg80211_set_beacon,
-#if defined(ANDROID_WIRELESS_PATCH)
- .drv_start = wl_cfg80211_drv_start,
- .drv_stop = wl_cfg80211_drv_stop
-#endif
+ .set_beacon = wl_cfg80211_add_set_beacon,
+ .add_beacon = wl_cfg80211_add_set_beacon,
};
static s32 wl_mode_to_nl80211_iftype(s32 mode)
@@ -4132,9 +4153,21 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
mgmt->u.beacon.capab_info, &bi->BSSID));
signal = notif_bss_info->rssi * 100;
+
+ if (wl->p2p_supported && p2p_on(wl)) {
+ /* &&TODO !memcmp(mgmt->bssid, wl_to_p2p_bss(wl, P2PAPI_BSSCFG_DEVICE), bi->SSID_len) */
+ /* && TODO !memcmp(bi->SSID, wl_to_p2p_bss(wl, P2PAPI_BSSCFG_CONNECTION), bi->SSID_len) */
+ /* find the P2PIE, if we do not find it, we will discard this frame */
+ wifi_p2p_ie_t * p2p_ie;
+ if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)beacon_proberesp->variable,
+ wl_get_ielen(wl))) == NULL) {
+ WL_ERR(("Couldn't find P2PIE in probe response/beacon\n"));
+ kfree(notif_bss_info);
+ return err;
+ }
+ }
if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
- le16_to_cpu
- (notif_bss_info->frame_len),
+ le16_to_cpu(notif_bss_info->frame_len),
signal, GFP_KERNEL))) {
WL_ERR(("cfg80211_inform_bss_frame error\n"));
kfree(notif_bss_info);
@@ -4226,7 +4259,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
if (get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
memcpy(body, data, len);
wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
- &da, sizeof(struct ether_addr), ioctlbuf, sizeof(ioctlbuf), bsscfgidx);
+ NULL, 0, ioctlbuf, sizeof(ioctlbuf), bsscfgidx);
+ memcpy(da.octet, ioctlbuf, ETHER_ADDR_LEN);
err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
switch (event) {
case WLC_E_ASSOC_IND:
@@ -4239,10 +4273,10 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
fc = FC_DISASSOC;
break;
case WLC_E_DEAUTH_IND:
- fc = FC_DEAUTH;
+ fc = FC_DISASSOC;
break;
case WLC_E_DEAUTH:
- fc = FC_DEAUTH;
+ fc = FC_DISASSOC;
break;
default:
fc = 0;
@@ -4274,7 +4308,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
} else if (event == WLC_E_DISASSOC_IND) {
cfg80211_send_disassoc(ndev, mgmt_frame, len);
} else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
- cfg80211_send_deauth(ndev, mgmt_frame, len);
+ cfg80211_send_disassoc(ndev, mgmt_frame, len);
}
} else {
@@ -4285,13 +4319,14 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
act = true;
wl_update_prof(wl, e, &act, WL_PROF_ACT);
if (wl_is_ibssmode(wl, ndev)) {
- printk("cfg80211_ibss_joined");
+ printk("cfg80211_ibss_joined\n");
cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
GFP_KERNEL);
WL_DBG(("joined in IBSS network\n"));
} else {
if (!wl_get_drv_status(wl, DISCONNECTING)) {
- printk("wl_bss_connect_done succeeded");
+ printk("wl_bss_connect_done succeeded status=(0x%x)\n",
+ (int)wl->status);
wl_bss_connect_done(wl, ndev, e, data, true);
WL_DBG(("joined in BSS network \"%s\"\n",
((struct wlc_ssid *)
@@ -4301,31 +4336,49 @@ 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, true);
} else
wl_iscan_aborted(wl);
}
if (wl_get_drv_status(wl, CONNECTED)) {
- printk("link down, call cfg80211_disconnected ");
+ scb_val_t scbval;
+ printk("link down, call cfg80211_disconnected\n");
wl_clr_drv_status(wl, CONNECTED);
+ /* 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, &wl->bssid, 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->profile);
} else if (wl_get_drv_status(wl, CONNECTING)) {
- printk("link down, during connecting");
+ printk("link down, during connecting\n");
wl_bss_connect_done(wl, ndev, e, data, false);
}
wl_clr_drv_status(wl, DISCONNECTING);
} else if (wl_is_nonetwork(wl, e)) {
- printk("connect failed e->status 0x%x", (int)ntoh32(e->status));
+ 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_notify_escan_complete(wl, true);
+ } else
+ wl_iscan_aborted(wl);
+ }
if (wl_get_drv_status(wl, CONNECTING))
wl_bss_connect_done(wl, ndev, e, data, false);
} else {
printk("%s nothing\n", __FUNCTION__);
}
- printk("\n");
}
exit:
if (isfree)
@@ -4362,7 +4415,7 @@ wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
BUG_ON(unlikely(!buflen));
- return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, false);
+ return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, true);
}
static s32
@@ -4620,8 +4673,10 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
conn_info->resp_ie_len,
completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT,
GFP_KERNEL);
- WL_DBG(("Report connect result - connection %s\n",
- completed ? "succeeded" : "failed"));
+ if (completed)
+ WL_INFO(("Report connect result - connection succeeded\n"));
+ else
+ WL_ERR(("Report connect result - connection failed\n"));
}
return err;
}
@@ -4654,6 +4709,7 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
struct wl_scan_results *bss_list;
u32 len = WL_SCAN_BUF_MAX;
s32 err = 0;
+ unsigned long flags;
WL_DBG(("Enter \n"));
if (wl->iscan_on && wl->iscan_kickstart)
@@ -4697,11 +4753,14 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
goto scan_done_out;
scan_done_out:
+ del_timer_sync(&wl->scan_timeout);
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
if (wl->scan_request) {
WL_DBG(("cfg80211_scan_done\n"));
cfg80211_scan_done(wl->scan_request, false);
wl->scan_request = NULL;
}
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
rtnl_unlock();
return err;
}
@@ -4779,8 +4838,9 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
#endif
if (event == WLC_E_ACTION_FRAME_RX) {
wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
- &da, sizeof(struct ether_addr), ioctlbuf, sizeof(ioctlbuf), bsscfgidx);
+ NULL, 0, ioctlbuf, sizeof(ioctlbuf), bsscfgidx);
wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
+ memcpy(da.octet, ioctlbuf, ETHER_ADDR_LEN);
err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
&mgmt_frame, &mgmt_frame_len,
(u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
@@ -4999,6 +5059,7 @@ static void wl_term_iscan(struct wl_priv *wl)
static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
{
struct wl_priv *wl = iscan_to_wl(iscan);
+ unsigned long flags;
WL_DBG(("Enter \n"));
if (unlikely(!wl_get_drv_status(wl, SCANNING))) {
@@ -5006,11 +5067,13 @@ static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
WL_ERR(("Scan complete while device not scanning\n"));
return;
}
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
wl_clr_drv_status(wl, SCANNING);
if (likely(wl->scan_request)) {
cfg80211_scan_done(wl->scan_request, aborted);
wl->scan_request = NULL;
}
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
wl->iscan_kickstart = false;
}
@@ -5153,6 +5216,16 @@ static s32 wl_iscan_thread(void *data)
return 0;
}
+static void wl_scan_timeout(unsigned long data)
+{
+ struct wl_priv *wl = (struct wl_priv *)data;
+
+ if (wl->scan_request) {
+ WL_ERR(("timer expired\n"));
+ wl_notify_escan_complete(wl, true);
+ }
+}
+
static void wl_iscan_timer(unsigned long data)
{
struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
@@ -5195,6 +5268,8 @@ static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted)
{
+ unsigned long flags;
+
WL_DBG(("Enter \n"));
if (unlikely(!wl_get_drv_status(wl, SCANNING))) {
wl_clr_drv_status(wl, SCANNING);
@@ -5206,10 +5281,12 @@ static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted)
if (wl->p2p_supported && p2p_on(wl))
wl_clr_p2p_status(wl, SCANNING);
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
if (likely(wl->scan_request)) {
cfg80211_scan_done(wl->scan_request, aborted);
wl->scan_request = NULL;
}
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
}
static s32 wl_escan_handler(struct wl_priv *wl,
@@ -5295,6 +5372,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
if (likely(wl->scan_request)) {
rtnl_lock();
+ 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);
@@ -5306,6 +5384,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
if (likely(wl->scan_request)) {
rtnl_lock();
+ 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);
@@ -5313,6 +5392,18 @@ static s32 wl_escan_handler(struct wl_priv *wl,
rtnl_unlock();
}
}
+ else {
+ WL_ERR(("unexpected Escan Event %d : abort\n", status));
+ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ if (likely(wl->scan_request)) {
+ rtnl_lock();
+ 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, true);
+ rtnl_unlock();
+ }
+ }
exit:
return err;
}
@@ -5342,6 +5433,10 @@ static s32 wl_init_scan(struct wl_priv *wl)
wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
}
+ /* Init scan_timeout timer */
+ init_timer(&wl->scan_timeout);
+ wl->scan_timeout.data = (unsigned long) wl;
+ wl->scan_timeout.function = wl_scan_timeout;
return err;
}
@@ -5396,6 +5491,7 @@ static void wl_deinit_priv(struct wl_priv *wl)
wl->dongle_up = false; /* dongle down */
wl_flush_eq(wl);
wl_link_down(wl);
+ del_timer_sync(&wl->scan_timeout);
wl_term_iscan(wl);
wl_deinit_priv_mem(wl);
}
@@ -5589,6 +5685,7 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
if (event_type == WLC_E_PFN_NET_FOUND)
WL_ERR((" PNO Event\n"));
+
if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
wl_wakeup_event(wl);
}
@@ -5714,7 +5811,7 @@ static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftyp
return err;
}
infra = htod32(infra);
- err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), false);
+ err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
return err;
@@ -5747,7 +5844,7 @@ static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, boo
}
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("Set event_msgs error (%d)\n", err));
goto dongle_eventmsg_out;
@@ -5772,7 +5869,7 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up)
{
s32 err = 0;
- err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), false);
+ err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true);
if (unlikely(err)) {
WL_ERR(("WLC_UP error (%d)\n", err));
}
@@ -5784,7 +5881,7 @@ static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode)
s32 err = 0;
WL_TRACE(("In\n"));
- err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), false);
+ err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_PM error (%d)\n", err));
}
@@ -5801,14 +5898,14 @@ wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align)
/* Match Host and Dongle rx alignment */
bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("txglomalign error (%d)\n", err));
goto dongle_glom_out;
}
/* disable glom option per default */
bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("txglom error (%d)\n", err));
goto dongle_glom_out;
@@ -5828,7 +5925,7 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
if (roamvar) {
bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("bcn_timeout error (%d)\n", err));
goto dongle_rom_out;
@@ -5836,7 +5933,7 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
}
/* Enable/Disable built-in roaming to allow supplicant to take care of roaming */
bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("roam_off error (%d)\n", err));
goto dongle_rom_out;
@@ -5852,7 +5949,7 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
s32 err = 0;
err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
- sizeof(scan_assoc_time), false);
+ sizeof(scan_assoc_time), true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("Scan assoc time is not supported\n"));
@@ -5862,7 +5959,7 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
goto dongle_scantime_out;
}
err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
- sizeof(scan_unassoc_time), false);
+ sizeof(scan_unassoc_time), true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("Scan unassoc time is not supported\n"));
@@ -5886,7 +5983,7 @@ wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
/* Set ARP offload */
bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO(("arpoe is not supported\n"));
@@ -5896,7 +5993,7 @@ wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
goto dongle_offload_out;
}
bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO(("arp_ol is not supported\n"));
@@ -5995,7 +6092,7 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
memcpy((char *)pkt_filterp, &pkt_filter,
WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
- err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("filter not supported\n"));
@@ -6008,7 +6105,7 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
/* set mode to allow pattern */
bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf,
sizeof(iovbuf));
- err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("filter_mode not supported\n"));
@@ -6139,6 +6236,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl)
static s32 __wl_cfg80211_down(struct wl_priv *wl)
{
s32 err = 0;
+ unsigned long flags;
WL_TRACE(("In\n"));
/* Check if cfg80211 interface is already down */
@@ -6148,6 +6246,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
wl_set_drv_status(wl, SCAN_ABORTING);
wl_term_iscan(wl);
+ flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub));
if (wl->scan_request) {
cfg80211_scan_done(wl->scan_request, true);
wl->scan_request = NULL;
@@ -6158,6 +6257,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
wl_clr_drv_status(wl, CONNECTING);
wl_clr_drv_status(wl, CONNECTED);
wl_clr_drv_status(wl, DISCONNECTING);
+ dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
if (wl_get_drv_status(wl, AP_CREATED)) {
wl_clr_drv_status(wl, AP_CREATED);
wl_clr_drv_status(wl, AP_CREATING);
@@ -6220,6 +6320,7 @@ s32 wl_cfg80211_down(void)
return err;
}
+
static s32 wl_dongle_probecap(struct wl_priv *wl)
{
s32 err = 0;
@@ -6669,7 +6770,7 @@ dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len)
bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
- return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf, sizeof(ioctlbuf), false));
+ return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf, sizeof(ioctlbuf), true));
}
/*
get named driver variable to uint register value and return error indication
@@ -6699,7 +6800,7 @@ static bool btcoex_is_sco_active(struct net_device *dev)
ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, &param27);
- WL_INFO(("%s, sample[%d], btc params: 27:%x\n",
+ WL_TRACE(("%s, sample[%d], btc params: 27:%x\n",
__FUNCTION__, i, param27));
if (ioc_res < 0) {
@@ -6712,7 +6813,7 @@ static bool btcoex_is_sco_active(struct net_device *dev)
}
if (sco_id_cnt > 2) {
- WL_INFO(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n",
+ WL_TRACE(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n",
__FUNCTION__, sco_id_cnt, i));
res = TRUE;
break;
@@ -6753,7 +6854,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
*/
/* 1st save current */
- WL_INFO(("Do new SCO/eSCO coex algo {save &"
+ WL_TRACE(("Do new SCO/eSCO coex algo {save &"
"override}\n"));
if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
@@ -6761,7 +6862,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
(!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
saved_status = TRUE;
- WL_INFO(("%s saved bt_params[50,51,64,65,71]:"
+ WL_TRACE(("%s saved bt_params[50,51,64,65,71]:"
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
__FUNCTION__, saved_reg50, saved_reg51,
saved_reg64, saved_reg65, saved_reg71));
@@ -6772,7 +6873,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
return -1;
}
- WL_INFO(("override with [50,51,64,65,71]:"
+ WL_TRACE(("override with [50,51,64,65,71]:"
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
*(u32 *)(buf_reg50va_dhcp_on+4),
*(u32 *)(buf_reg51va_dhcp_on+4),
@@ -6794,7 +6895,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
saved_status = TRUE;
} else if (saved_status) {
/* restore previously saved bt params */
- WL_INFO(("Do new SCO/eSCO coex algo {save &"
+ WL_TRACE(("Do new SCO/eSCO coex algo {save &"
"override}\n"));
regaddr = 50;
@@ -6813,7 +6914,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg71);
- WL_INFO(("restore bt_params[50,51,64,65,71]:"
+ WL_TRACE(("restore bt_params[50,51,64,65,71]:"
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
saved_reg50, saved_reg51, saved_reg64,
saved_reg65, saved_reg71));
@@ -6989,7 +7090,7 @@ wl_cfg80211_btcoex_deinit(struct wl_priv *wl)
kfree(wl->btcoex_info);
wl->btcoex_info = NULL;
}
-#endif /* OEM_ANDROID */
+#endif /* COEX_DHCP */
int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
{
@@ -7022,7 +7123,7 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
(!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
saved_status = TRUE;
- WL_INFO(("Saved 0x%x 0x%x 0x%x\n",
+ WL_TRACE(("Saved 0x%x 0x%x 0x%x\n",
saved_reg66, saved_reg41, saved_reg68));
/* Disable PM mode during dhpc session */
@@ -7048,7 +7149,7 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
btco_inf->bt_state = BT_DHCP_START;
btco_inf->timer_on = 1;
mod_timer(&btco_inf->timer, btco_inf->timer.expires);
- WL_INFO(("%s enable BT DHCP Timer\n",
+ WL_TRACE(("%s enable BT DHCP Timer\n",
__FUNCTION__));
}
#endif /* COEX_DHCP */
@@ -7064,14 +7165,14 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
#ifdef COEX_DHCP
/* Stop any bt timer because DHCP session is done */
- WL_INFO(("%s disable BT DHCP Timer\n", __FUNCTION__));
+ WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__));
if (btco_inf->timer_on) {
btco_inf->timer_on = 0;
del_timer_sync(&btco_inf->timer);
if (btco_inf->bt_state != BT_DHCP_IDLE) {
/* need to restore original btc flags & extra btc params */
- WL_INFO(("%s bt->bt_state:%d\n",
+ WL_TRACE(("%s bt->bt_state:%d\n",
__FUNCTION__, btco_inf->bt_state));
/* wake up btcoex thread to restore btlags+params */
schedule_work(&btco_inf->work);
@@ -7096,7 +7197,7 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg68);
- WL_INFO(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
+ WL_TRACE(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
saved_reg66, saved_reg41, saved_reg68));
}
saved_status = FALSE;
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 4159bd7e8c56..9fae79ed83dc 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -52,11 +52,11 @@ struct wl_ibss;
#define dtohchanspec(i) i
#define WL_DBG_NONE 0
+#define WL_DBG_TRACE (1 << 4)
#define WL_DBG_SCAN (1 << 3)
#define WL_DBG_DBG (1 << 2)
#define WL_DBG_INFO (1 << 1)
#define WL_DBG_ERR (1 << 0)
-#define WL_DBG_MASK ((WL_DBG_DBG | WL_DBG_INFO | WL_DBG_ERR) << 1)
/* 0 invalidates all debug messages. default is 1 */
#define WL_DBG_LEVEL 0xFF
@@ -82,6 +82,13 @@ do { \
printk args; \
} \
} while (0)
+#define WL_TRACE(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_TRACE) { \
+ printk(KERN_ERR "CFG80211-TRACE) %s :", __func__); \
+ printk args; \
+ } \
+} while (0)
#if (WL_DBG_LEVEL > 0)
#define WL_DBG(args) \
do { \
@@ -94,6 +101,7 @@ do { \
#define WL_DBG(args)
#endif /* (WL_DBG_LEVEL > 0) */
+
#define WL_SCAN_RETRY_MAX 3 /* used for ibss scan */
#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used
* for 2.6.33 kernel
@@ -122,6 +130,9 @@ do { \
#define WL_FILE_NAME_MAX 256
#define WL_DWELL_TIME 200
#define VWDEV_CNT 3
+
+#define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */
+
/* dongle status */
enum wl_status {
WL_STATUS_READY = 0,
@@ -196,7 +207,6 @@ struct wl_conf {
typedef s32(*EVENT_HANDLER) (struct wl_priv *wl,
struct net_device *ndev, const wl_event_msg_t *e, void *data);
-
/* bss inform structure for cfg80211 interface */
struct wl_cfg80211_bss_info {
u16 band;
@@ -408,6 +418,7 @@ struct wl_priv {
struct p2p_info *p2p;
bool p2p_supported;
struct btcoex_info *btcoex_info;
+ struct timer_list scan_timeout; /* Timer for catch scan event timeout */
};
#define wl_to_wiphy(w) (w->wdev->wiphy)
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index 2487a679f082..dd5f5facd728 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -59,7 +59,7 @@ wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u
static s32
wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag,
s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete);
-/*
+/*
* Initialize variables related to P2P
*
*/
@@ -99,7 +99,7 @@ wl_cfgp2p_init_priv(struct wl_priv *wl)
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0;
wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL;
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0;
-
+ spin_lock_init(&wl->p2p->timer_lock);
return BCME_OK;
}
@@ -129,9 +129,9 @@ 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), false);
+ wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
wldev_iovar_setint(ndev, "apsta", val);
- wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), false);
+ wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
}
val = 1;
/* Disable firmware roaming for P2P */
@@ -958,13 +958,15 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev,
CFGP2P_DBG((" Enter\n"));
if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) {
wl_set_p2p_status(wl, LISTEN_EXPIRED);
-
- if (wl->p2p->listen_timer)
- del_timer_sync(wl->p2p->listen_timer);
-
+ if (timer_pending(&wl->p2p->listen_timer)) {
+ spin_lock_bh(&wl->p2p->timer_lock);
+ del_timer_sync(&wl->p2p->listen_timer);
+ spin_unlock_bh(&wl->p2p->timer_lock);
+ }
cfg80211_remain_on_channel_expired(ndev, wl->cache_cookie, &wl->remain_on_chan,
wl->remain_on_chan_type, GFP_KERNEL);
- }
+ } else
+ wl_clr_p2p_status(wl, LISTEN_EXPIRED);
return ret;
@@ -972,7 +974,7 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev,
/*
* Timer expire callback function for LISTEN
- * We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
+ * We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
* so lets do it from thread context.
*/
static void
@@ -986,7 +988,7 @@ wl_cfgp2p_listen_expired(unsigned long data)
wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
}
-/*
+/*
* Do a P2P Listen on the given channel for the given duration.
* A listen consists of sitting idle and responding to P2P probe requests
* with a P2P probe response.
@@ -1010,6 +1012,7 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
} while (0);
s32 ret = BCME_OK;
+ struct timer_list *_timer;
CFGP2P_DBG((" Enter Channel : %d, Duration : %d\n", channel, duration_ms));
if (unlikely(wl_get_p2p_status(wl, DISCOVERY_ON) == 0)) {
@@ -1018,26 +1021,24 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
ret = BCME_NOTREADY;
goto exit;
}
-
+ if (!wl_get_p2p_status(wl, LISTEN_EXPIRED)) {
+ wl_set_p2p_status(wl, LISTEN_EXPIRED);
+ if (timer_pending(&wl->p2p->listen_timer)) {
+ spin_lock_bh(&wl->p2p->timer_lock);
+ del_timer_sync(&wl->p2p->listen_timer);
+ spin_unlock_bh(&wl->p2p->timer_lock);
+ }
+ } else
wl_clr_p2p_status(wl, LISTEN_EXPIRED);
wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
+ _timer = &wl->p2p->listen_timer;
- if (wl->p2p->listen_timer)
- del_timer_sync(wl->p2p->listen_timer);
-
- wl->p2p->listen_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
-
- if (wl->p2p->listen_timer == NULL) {
- CFGP2P_ERR(("listen_timer allocation failed\n"));
- return -ENOMEM;
- }
-
- /* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle ,
+ /* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle ,
* otherwise we will wait up to duration_ms + 200ms
*/
- INIT_TIMER(wl->p2p->listen_timer, wl_cfgp2p_listen_expired, duration_ms, 200);
+ INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, 200);
#undef INIT_TIMER
exit:
@@ -1308,7 +1309,7 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev)
s32
wl_cfgp2p_down(struct wl_priv *wl)
{
- if (wl->p2p->listen_timer)
- del_timer_sync(wl->p2p->listen_timer);
+ if (timer_pending(&wl->p2p->listen_timer))
+ del_timer_sync(&wl->p2p->listen_timer);
return 0;
}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index b08504d8f950..5aff46831f85 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -45,11 +45,11 @@ typedef enum {
#define IE_MAX_LEN 300
/* Structure to hold all saved P2P and WPS IEs for a BSSCFG */
struct p2p_saved_ie {
- u8 p2p_probe_req_ie[IE_MAX_LEN];
- u8 p2p_probe_res_ie[IE_MAX_LEN];
- u8 p2p_assoc_req_ie[IE_MAX_LEN];
- u8 p2p_assoc_res_ie[IE_MAX_LEN];
- u8 p2p_beacon_ie[IE_MAX_LEN];
+ u8 p2p_probe_req_ie[IE_MAX_LEN];
+ u8 p2p_probe_res_ie[IE_MAX_LEN];
+ u8 p2p_assoc_req_ie[IE_MAX_LEN];
+ u8 p2p_assoc_res_ie[IE_MAX_LEN];
+ u8 p2p_beacon_ie[IE_MAX_LEN];
u32 p2p_probe_req_ie_len;
u32 p2p_probe_res_ie_len;
u32 p2p_assoc_req_ie_len;
@@ -73,8 +73,9 @@ struct p2p_info {
struct ether_addr dev_addr;
struct ether_addr int_addr;
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
- struct timer_list *listen_timer;
+ struct timer_list listen_timer;
wlc_ssid_t ssid;
+ spinlock_t timer_lock;
};
/* dongle status */
@@ -96,7 +97,7 @@ enum wl_cfgp2p_status {
#define wl_to_p2p_bss_ndev(w, type) ((wl)->p2p->bss_idx[type].dev)
#define wl_to_p2p_bss_bssidx(w, type) ((wl)->p2p->bss_idx[type].bssidx)
#define wl_to_p2p_bss_saved_ie(w, type) ((wl)->p2p->bss_idx[type].saved_ie)
-#define wl_to_p2p_bss_private(w, type) ((wl)->p2p->bss_idx[type].private_data)
+#define wl_to_p2p_bss_private(w, type) ((wl)->p2p->bss_idx[type].private_data)
#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type])
#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
index e69561e1bf34..92c419863764 100644
--- a/drivers/net/wireless/bcmdhd/wldev_common.c
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -37,7 +37,6 @@
#define dtoh16(i) i
#define htodchanspec(i) i
#define dtohchanspec(i) i
-
extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd);
s32 wldev_ioctl(
@@ -78,7 +77,7 @@ s32 wldev_iovar_getbuf(
s32 iovar_len = 0;
iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
- ret = wldev_ioctl(dev, WLC_GET_VAR, buf, iovar_len, FALSE);
+ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
return ret;
}
@@ -184,7 +183,7 @@ s32 wldev_iovar_getbuf_bsscfg(
s32 iovar_len = 0;
iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
- ret = wldev_ioctl(dev, WLC_GET_VAR, buf, iovar_len, FALSE);
+ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
return ret;
}
@@ -310,7 +309,7 @@ int wldev_set_country(
return error;
error = wldev_iovar_getbuf(dev, "country", &cspec, sizeof(cspec),
- smbuf, sizeof(smbuf));
+ smbuf, sizeof(smbuf));
if (error < 0)
DHD_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error));
@@ -328,7 +327,7 @@ int wldev_set_country(
memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
get_customized_country_code((char *)&cspec.country_abbrev, &cspec);
error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec),
- smbuf, sizeof(smbuf));
+ smbuf, sizeof(smbuf));
if (error < 0) {
DHD_ERROR(("%s: set country for %s as %s rev %d failed\n",
__FUNCTION__, country_code, cspec.ccode, cspec.rev));