summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward M. Harte <hharte@broadcom.com>2011-05-27 16:07:36 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:38:34 -0800
commitf5b388b93f42eebbac05dc57373cc97542938ef9 (patch)
tree6c9f189ca481930b093ca11ca6ef9e270e8a8bcb
parent7972aa8f9ee3d3ddbf84e23bddecf361360e9cbe (diff)
Update to 5.90.125.22:
* Add support for SoftAP, keepalive, ARP offload. * Clean up cfg80211 and p2p code. * Update Makefile to support new features. Change-Id: I1e7a16acd400d7baf5625ca8ba6552a6f1c80661 Signed-off-by: Howard M. Harte <hharte@broadcom.com>
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile5
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h10
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cdc.c6
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c257
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_custom_gpio.c68
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c36
-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.h13
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c1108
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h72
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c495
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h30
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.c238
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.h91
15 files changed, 1451 insertions, 988 deletions
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index b9aaf79760e3..410f1f053ffb 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -6,13 +6,14 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Werror -Dlinux -DBCMDRIVER \
-DCUSTOMER_HW3 -DCUSTOM_OOB_GPIO_NUM=135 -DOOB_INTR_ONLY \
-DMMC_SDIO_ABORT -DCONFIG_FIRST_SCAN -DBCMSDIO -DBCMLXSDMMC \
-DBCMPLATFORM_BUS -DHW_OOB -DNEW_COMPAT_WIRELESS -DWL_CFG80211 \
- -DWLP2P -DWIFI_ACT_FRAME \
+ -DWLP2P -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DKEEP_ALIVE -DCSCAN \
-Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \
dhd_linux_sched.o wl_cfg80211.o bcmwifi.o dhd_sdio.o wl_cfgp2p.o \
bcmevent.o dhd_bta.o hndpmu.o bcmsdh.o dhd_cdc.o bcmsdh_linux.o \
- dhd_common.o linux_osl.o bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o
+ dhd_common.o linux_osl.o bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o \
+ wldev_common.o
obj-$(CONFIG_BCMDHD) += bcmdhd.o
bcmdhd-objs += $(DHDOFILES)
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index 961a66d71fa0..bb39913a4ec8 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -484,6 +484,9 @@ extern uint dhd_sdiod_drive_strength;
/* Override to force tx queueing all the time */
extern uint dhd_force_tx_queueing;
+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
+#define KEEP_ALIVE_PERIOD 55000
+#define NULL_PKT_STR "null_pkt"
#ifdef SDTEST
/* Echo packet generator (SDIO), pkts/s */
@@ -641,4 +644,11 @@ int dhd_os_wlfc_unblock(dhd_pub_t *pub);
extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
+#ifdef ARP_OFFLOAD_SUPPORT
+/* dhd_commn arp offload wrapers */
+void dhd_aoe_hostip_clr(dhd_pub_t *dhd);
+void dhd_aoe_arp_clr(dhd_pub_t *dhd);
+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen);
+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr);
+#endif /* ARP_OFFLOAD_SUPPORT */
#endif /* _dhd_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c
index b4270e02c840..fb0d5ad7f6b4 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cdc.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c
@@ -116,7 +116,7 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
return ret;
}
-static int
+int
dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
{
dhd_prot_t *prot = dhd->prot;
@@ -203,7 +203,7 @@ done:
return ret;
}
-static int
+int
dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
{
dhd_prot_t *prot = dhd->prot;
@@ -271,6 +271,7 @@ 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);
@@ -2294,6 +2295,7 @@ 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);
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index ae92489dcf15..b1d9e7c87601 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -41,8 +41,15 @@
#include <dhd_dbg.h>
#include <msgtrace.h>
+#ifdef WL_CFG80211
+#include <wl_cfg80211.h>
+#endif
#include <proto/bt_amp_hci.h>
#include <dhd_bta.h>
+#ifdef SET_RANDOM_MAC_SOFTAP
+#include <linux/random.h>
+#include <linux/jiffies.h>
+#endif
#ifdef PROP_TXSTATUS
#include <wlfc_proto.h>
@@ -80,6 +87,13 @@ extern int dhd_iscan_in_progress(void *h);
void dhd_iscan_lock(void);
void dhd_iscan_unlock(void);
extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx);
+#if defined(SOFTAP)
+extern bool ap_fw_loaded;
+#endif
+
+#if defined(KEEP_ALIVE)
+int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on);
+#endif /* KEEP_ALIVE */
/* Packet alignment for most efficient SDIO (can change based on platform) */
#ifndef DHD_SDALIGN
@@ -1025,12 +1039,30 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
}
#endif /* PROP_TXSTATUS */
- if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) {
+#ifdef WL_CFG80211
+ if (wl_cfg80211_is_progress_ifchange()) {
+ DHD_ERROR(("%s: ifidx %d for %s action %d\n",
+ __FUNCTION__, ifevent->ifidx,
+ event->ifname, ifevent->action));
if (ifevent->action == WLC_E_IF_ADD)
- dhd_add_if(dhd_pub->info, ifevent->ifidx,
- NULL, event->ifname,
- event->addr.octet,
- ifevent->flags, ifevent->bssidx);
+ wl_cfg80211_notify_ifchange();
+ return (BCME_OK);
+ }
+#endif /* WL_CFG80211 */
+ if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) {
+ if (ifevent->action == WLC_E_IF_ADD) {
+ if (dhd_add_if(dhd_pub->info, ifevent->ifidx,
+ NULL, event->ifname,
+ event->addr.octet,
+ ifevent->flags, ifevent->bssidx)) {
+ DHD_ERROR(("%s: dhd_add_if failed!!"
+ " ifidx: %d for %s\n",
+ __FUNCTION__,
+ ifevent->ifidx,
+ event->ifname));
+ return (BCME_ERROR);
+ }
+ }
else
dhd_del_if(dhd_pub->info, ifevent->ifidx);
} else {
@@ -1114,6 +1146,7 @@ wl_event_to_host_order(wl_event_msg_t * evt)
void
dhd_print_buf(void *pbuf, int len, int bytes_per_line)
{
+#ifdef DHD_DEBUG
int i, j = 0;
unsigned char *buf = pbuf;
@@ -1132,6 +1165,7 @@ dhd_print_buf(void *pbuf, int len, int bytes_per_line)
}
}
printf("\n");
+#endif /* DHD_DEBUG */
}
#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
@@ -1366,6 +1400,10 @@ fail:
MFREE(dhd->osh, buf, BUF_SIZE);
}
+/* ========================== */
+/* ==== ARP OFFLOAD SUPPORT = */
+/* ========================== */
+#ifdef ARP_OFFLOAD_SUPPORT
void
dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode)
{
@@ -1400,6 +1438,86 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
__FUNCTION__, arp_enable));
}
+void dhd_aoe_arp_clr(dhd_pub_t *dhd)
+{
+ int ret = 0;
+ int iov_len = 0;
+ char iovbuf[128];
+
+ if (dhd == NULL) return;
+
+ iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0) < 0))
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+}
+
+void dhd_aoe_hostip_clr(dhd_pub_t *dhd)
+{
+ int ret = 0;
+ int iov_len = 0;
+ char iovbuf[128];
+
+ if (dhd == NULL) return;
+
+ iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0)) < 0)
+ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+}
+
+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr)
+{
+ int iov_len = 0;
+ char iovbuf[32];
+ int retcode;
+
+ iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, 4, iovbuf, sizeof(iovbuf));
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0);
+
+ if (retcode)
+ DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n",
+ __FUNCTION__, retcode));
+ else
+ DHD_TRACE(("%s: sARP H ipaddr entry added \n",
+ __FUNCTION__));
+}
+
+
+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
+{
+#define MAX_IPV4_ENTRIES 8
+
+ int retcode, i;
+ int iov_len = 0;
+ uint32 *ptr32 = buf;
+ bool clr_bottom = FALSE;
+
+ if (!buf)
+ return -1;
+
+ iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen);
+ retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, TRUE, 0);
+
+ /* clean up the buf, ascii reminder */
+ for (i = 0; i < MAX_IPV4_ENTRIES; i++) {
+
+ if (!clr_bottom) {
+ if (*ptr32 == 0)
+ clr_bottom = TRUE;
+ } else {
+ *ptr32 = 0;
+ }
+ ptr32++;
+ }
+
+ if (retcode) {
+ DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n",
+ __FUNCTION__, retcode));
+
+ return -1;
+ }
+ return 0;
+}
+#endif /* ARP_OFFLOAD_SUPPORT */
int
dhd_preinit_ioctls(dhd_pub_t *dhd)
{
@@ -1411,10 +1529,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint power_mode = PM_FAST;
uint32 dongle_align = DHD_SDALIGN;
uint32 glom = 0;
+ uint bcn_timeout = 4;
int arpoe = 1;
int arp_ol = 0xf;
int scan_assoc_time = 40;
- int scan_unassoc_time = 80;
+ int scan_unassoc_time = 40;
const char *str;
wl_pkt_filter_t pkt_filter;
wl_pkt_filter_t *pkt_filterp;
@@ -1426,18 +1545,67 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
char *ptr;
uint filter_mode = 1;
uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
+#if defined(SOFTAP)
+ uint dtim = 1;
+#endif
#ifdef AP
uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
uint32 apsta = 1; /* Enable APSTA mode */
#endif
+#ifdef GET_CUSTOM_MAC_ENABLE
+ struct ether_addr ea_addr;
+#endif /* GET_CUSTOM_MAC_ENABLE */
- /* Get the device MAC address */
+#ifdef GET_CUSTOM_MAC_ENABLE
+ /*
+ ** Read MAC address from external customer place
+ ** NOTE that default mac address has to be present in otp or nvram file
+ ** to bring up firmware but unique per board mac address maybe provided
+ ** by customer code
+ */
+ ret = dhd_custom_get_mac_address(ea_addr.octet);
+ if (!ret) {
+ bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+ if (ret < 0) {
+ DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+ } else
+ memcpy(dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN);
+ }
+#else
+ /* Get the default device MAC address directly from firmware */
strcpy(iovbuf, "cur_etheraddr");
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
return BCME_NOTUP;
}
memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+#ifdef SET_RANDOM_MAC_SOFTAP
+ if (strstr(fw_path, "apsta") != NULL) {
+ uint rand_mac;
+
+ srandom32((uint)jiffies);
+ rand_mac = random32();
+ iovbuf[0] = 0x02; /* locally administered bit */
+ iovbuf[1] = 0x1A;
+ iovbuf[2] = 0x11;
+ iovbuf[3] = (unsigned char)(rand_mac & 0x0F) | 0xF0;
+ iovbuf[4] = (unsigned char)(rand_mac >> 8);
+ iovbuf[5] = (unsigned char)(rand_mac >> 16);
+
+ printk("Broadcom Dongle Host Driver mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ iovbuf[0], iovbuf[1], iovbuf[2], iovbuf[3], iovbuf[4], iovbuf[5]);
+
+ bcm_mkiovar("cur_etheraddr", (void *)iovbuf, ETHER_ADDR_LEN, buf, sizeof(buf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+ if (ret < 0) {
+ DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+ } else
+ memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
+ }
+#endif /* SET_RANDOM_MAC_SOFTAP */
/* Set Country code */
if (dhd->dhd_cspec.ccode[0] != 0) {
@@ -1472,6 +1640,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ /* Setup timeout if Beacons are lost and roam is off to report link down */
+ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
#ifdef AP
/* Turn off MPC in AP mode */
bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
@@ -1481,6 +1652,24 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
#endif
+#if defined(SOFTAP)
+ if (ap_fw_loaded == TRUE) {
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0);
+ }
+#endif
+
+#if defined(KEEP_ALIVE)
+ {
+ /* Set Keep Alive : be sure to use FW with -keepalive */
+ int res;
+
+ if (ap_fw_loaded == FALSE) {
+ if ((res = dhd_keep_alive_onoff(dhd, 1)) < 0)
+ DHD_ERROR(("%s set keeplive failed %d\n",
+ __FUNCTION__, res));
+ }
+ }
+#endif
/* Force STA UP */
ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0);
@@ -1518,6 +1707,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
sizeof(scan_assoc_time), TRUE, 0);
dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
@@ -1579,6 +1769,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
/* set mode to allow pattern */
bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#ifdef ARP_OFFLOAD_SUPPORT
+ /* Set and enable ARP offload feature */
+ if (dhd_arp_enable)
+ dhd_arp_offload_set(dhd, dhd_arp_mode);
+ dhd_arp_offload_enable(dhd, dhd_arp_enable);
+#endif /* ARP_OFFLOAD_SUPPORT */
done:
@@ -2030,6 +2226,53 @@ dhd_pno_get_status(dhd_pub_t *dhd)
#endif /* PNO_SUPPORT */
+#if defined(KEEP_ALIVE)
+int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on)
+{
+ char buf[256];
+ char *buf_ptr = buf;
+ wl_keep_alive_pkt_t keep_alive_pkt;
+ char * str;
+ int str_len, buf_len;
+ int res = -1;
+ int keep_alive_period = KEEP_ALIVE_PERIOD; /* in ms */
+
+ DHD_TRACE(("%s: param=%d\n", __FUNCTION__, ka_on));
+
+ if (ka_on) { /* on suspend */
+ keep_alive_pkt.period_msec = keep_alive_period;
+
+ } else {
+ /* on resume, turn off keep_alive packets */
+ keep_alive_pkt.period_msec = 0;
+ }
+
+ /* IOC var name */
+ str = "keep_alive";
+ str_len = strlen(str);
+ strncpy(buf, str, str_len);
+ buf[str_len] = '\0';
+ buf_len = str_len + 1;
+
+ /* set ptr to IOCTL payload after the var name */
+ buf_ptr += buf_len; /* include term Z */
+
+ /* copy Keep-alive attributes from local var keep_alive_pkt */
+ str = NULL_PKT_STR;
+ keep_alive_pkt.len_bytes = strlen(str);
+
+ memcpy(buf_ptr, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN);
+ buf_ptr += WL_KEEP_ALIVE_FIXED_LEN;
+
+ /* copy packet data */
+ memcpy(buf_ptr, str, keep_alive_pkt.len_bytes);
+ buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes);
+/*
+ res = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
+*/
+ return res;
+}
+#endif /* defined(KEEP_ALIVE) */
/* Android ComboSCAN support */
/*
diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
index b11e4b3b7339..88d0da2e3d22 100644
--- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
@@ -89,12 +89,12 @@ int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
#ifdef CUSTOMER_HW2
host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
-#else /* for NOT CUSTOMER_HW2 */
+#else
#if defined(CUSTOM_OOB_GPIO_NUM)
if (dhd_oob_gpio_num < 0) {
dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
}
-#endif
+#endif /* CUSTOMER_HW2 */
if (dhd_oob_gpio_num < 0) {
WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
@@ -199,18 +199,48 @@ dhd_custom_get_mac_address(unsigned char *buf)
const struct cntry_locales_custom translate_custom_table[] = {
/* Table should be filled out based on custom platform regulatory requirement */
#ifdef EXAMPLE_TABLE
+ {"", "XY", 4}, /* Universal if Country code is unknown or empty */
{"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
{"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
- {"EU", "EU", 05}, /* input ISO "CA" to : US regrev 69 */
- {"FR", "EU", 05},
- {"DE", "EU", 05},
- {"IE", "EU", 05},
- {"GB", "EU", 05}, /* input ISO "GB" to : EU regrev 05 */
- {"KR", "XY", 03},
- {"AU", "XY", 03},
- {"CN", "XY", 03}, /* input ISO "CN" to : XY regrev 03 */
- {"TW", "XY", 03},
- {"AR", "XY", 03}
+ {"EU", "EU", 5}, /* European union countries to : EU regrev 05 */
+ {"AT", "EU", 5},
+ {"BE", "EU", 5},
+ {"BG", "EU", 5},
+ {"CY", "EU", 5},
+ {"CZ", "EU", 5},
+ {"DK", "EU", 5},
+ {"EE", "EU", 5},
+ {"FI", "EU", 5},
+ {"FR", "EU", 5},
+ {"DE", "EU", 5},
+ {"GR", "EU", 5},
+ {"HU", "EU", 5},
+ {"IE", "EU", 5},
+ {"IT", "EU", 5},
+ {"LV", "EU", 5},
+ {"LI", "EU", 5},
+ {"LT", "EU", 5},
+ {"LU", "EU", 5},
+ {"MT", "EU", 5},
+ {"NL", "EU", 5},
+ {"PL", "EU", 5},
+ {"PT", "EU", 5},
+ {"RO", "EU", 5},
+ {"SK", "EU", 5},
+ {"SI", "EU", 5},
+ {"ES", "EU", 5},
+ {"SE", "EU", 5},
+ {"GB", "EU", 5},
+ {"KR", "XY", 3},
+ {"AU", "XY", 3},
+ {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
+ {"TW", "XY", 3},
+ {"AR", "XY", 3},
+ {"MX", "XY", 3},
+ {"IL", "IL", 0},
+ {"CH", "CH", 0},
+ {"TR", "TR", 0},
+ {"NO", "NO", 0},
#endif /* EXMAPLE_TABLE */
};
@@ -232,11 +262,17 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
return;
for (i = 0; i < size; i++) {
- if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
- memcpy(cspec->ccode, translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
- cspec->rev = translate_custom_table[i].custom_locale_rev;
- break;
+ if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
+ memcpy(cspec->ccode,
+ translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
+ cspec->rev = translate_custom_table[i].custom_locale_rev;
+ return;
}
}
+#ifdef EXAMPLE_TABLE
+ /* if no country code matched return first universal code from translate_custom_table */
+ memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ);
+ cspec->rev = translate_custom_table[0].custom_locale_rev;
+#endif /* EXMAPLE_TABLE */
return;
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index facf6c0b79e8..c51b8320294a 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -936,7 +936,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
int ret;
osl_t *osh;
uint8 *frame;
- uint16 len, pad = 0;
+ uint16 len, pad1 = 0;
uint32 swheader;
uint retries = 0;
bcmsdh_info_t *sdh;
@@ -972,10 +972,10 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
#endif /* WLMEDIA_HTSF */
/* Add alignment padding, allocate new packet if needed */
- if ((pad = ((uintptr)frame % DHD_SDALIGN))) {
- if (PKTHEADROOM(osh, pkt) < pad) {
- DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
- __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad));
+ if ((pad1 = ((uintptr)frame % DHD_SDALIGN))) {
+ if (PKTHEADROOM(osh, pkt) < pad1) {
+ DHD_INFO(("%s: insufficient headroom %d for %d pad1\n",
+ __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad1));
bus->dhd->tx_realloc++;
new = PKTGET(osh, (PKTLEN(osh, pkt) + DHD_SDALIGN), TRUE);
if (!new) {
@@ -994,16 +994,16 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
pkt = new;
frame = (uint8*)PKTDATA(osh, pkt);
ASSERT(((uintptr)frame % DHD_SDALIGN) == 0);
- pad = 0;
+ pad1 = 0;
} else {
- PKTPUSH(osh, pkt, pad);
+ PKTPUSH(osh, pkt, pad1);
frame = (uint8*)PKTDATA(osh, pkt);
- ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt));
- bzero(frame, pad + SDPCM_HDRLEN);
+ ASSERT((pad1 + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt));
+ bzero(frame, pad1 + SDPCM_HDRLEN);
}
}
- ASSERT(pad < DHD_SDALIGN);
+ ASSERT(pad1 < DHD_SDALIGN);
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
len = (uint16)PKTLEN(osh, pkt);
@@ -1012,7 +1012,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
/* Software tag: channel, sequence number, data offset */
swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
- (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+ (((pad1 + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
@@ -1029,12 +1029,12 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
/* Raise len to next SDIO block to eliminate tail command */
if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- uint16 pad = bus->blocksize - (len % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize))
+ uint16 pad2 = bus->blocksize - (len % bus->blocksize);
+ if ((pad2 <= bus->roundup) && (pad2 < bus->blocksize))
#ifdef NOTUSED
- if (pad <= PKTTAILROOM(osh, pkt))
+ if (pad2 <= PKTTAILROOM(osh, pkt))
#endif /* NOTUSED */
- len += pad;
+ len += pad2;
} else if (len % DHD_SDALIGN) {
len += DHD_SDALIGN - (len % DHD_SDALIGN);
}
@@ -1087,7 +1087,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
done:
/* restore pkt buffer pointer before calling tx complete routine */
- PKTPULL(osh, pkt, SDPCM_HDRLEN + pad);
+ PKTPULL(osh, pkt, SDPCM_HDRLEN + pad1);
#ifdef PROP_TXSTATUS
if (bus->dhd->wlfc_state) {
dhd_os_sdunlock(bus->dhd);
@@ -5791,7 +5791,7 @@ dhdsdio_download_code_array(struct dhd_bus *bus)
/* Download image */
while ((offset + MEMBLOCK) < sizeof(dlarray)) {
- bcmerror = dhdsdio_membytes(bus, TRUE, offset, dlarray + offset, MEMBLOCK);
+ bcmerror = dhdsdio_membytes(bus, TRUE, offset, (uint8 *) (dlarray + offset), MEMBLOCK);
if (bcmerror) {
DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
__FUNCTION__, bcmerror, MEMBLOCK, offset));
@@ -5803,7 +5803,7 @@ dhdsdio_download_code_array(struct dhd_bus *bus)
if (offset < sizeof(dlarray)) {
bcmerror = dhdsdio_membytes(bus, TRUE, offset,
- dlarray + offset, sizeof(dlarray) - offset);
+ (uint8 *) (dlarray + offset), sizeof(dlarray) - offset);
if (bcmerror) {
DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
__FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 1b8a3e8a5421..9a79a1e358c5 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 14
+#define EPI_INCREMENTAL_NUMBER 22
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 5, 90, 125, 14
+#define EPI_VERSION 5, 90, 125, 22
-#define EPI_VERSION_NUM 0x055a7d0e
+#define EPI_VERSION_NUM 0x055a7d16
#define EPI_VERSION_DEV 5.90.125
-#define EPI_VERSION_STR "5.90.125.14"
+#define EPI_VERSION_STR "5.90.125.22"
#endif
diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h
index ddcf8df60a39..fd399cbf2772 100644
--- a/drivers/net/wireless/bcmdhd/include/linuxver.h
+++ b/drivers/net/wireless/bcmdhd/include/linuxver.h
@@ -136,7 +136,7 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
#include <net/lib80211.h>
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
#include <linux/ieee80211.h>
#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index c824692b394b..d78ecfc2726b 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -633,8 +633,17 @@ typedef struct _pmkid_cand_list {
pmkid_cand_t pmkid_cand[1];
} pmkid_cand_list_t;
-
-
+typedef struct wl_assoc_info {
+ uint32 req_len;
+ uint32 resp_len;
+ uint32 flags;
+ struct dot11_assoc_req req;
+ struct ether_addr reassoc_bssid; /* used in reassoc's */
+ struct dot11_assoc_resp resp;
+} wl_assoc_info_t;
+
+/* flags */
+#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */
#define WLC_TXFILTER_OVERRIDE_DISABLED 0
#define WLC_TXFILTER_OVERRIDE_ENABLED 1
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index ce28a050728d..f2480e9c1016 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -29,6 +29,10 @@
#include <osl.h>
#include <linux/kernel.h>
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
+
#include <bcmutils.h>
#include <bcmwifi.h>
#include <bcmendian.h>
@@ -62,13 +66,14 @@
#include <bcmsdbus.h>
#include <wlioctl.h>
+#include <wldev_common.h>
#include <wl_cfg80211.h>
#include <wl_cfgp2p.h>
static struct sdio_func *cfg80211_sdio_func;
static struct wl_dev *wl_cfg80211_dev;
-u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
+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"
@@ -76,7 +81,44 @@ u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
#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 3000
+static s8 ioctlbuf[WLC_IOCTL_MAXLEN];
+
+#ifdef CONFIG_SYSCTL
+#define MAC_STRING_LEN (sizeof(u8) * 17)
+u8 wl_sysctl_macstring[2][MAC_STRING_LEN];
+static ctl_table wl_sysctl_child[] = {
+ {
+ .procname = "p2p_dev_addr",
+ .data = &wl_sysctl_macstring[0],
+ .maxlen = MAC_STRING_LEN,
+ .mode = 0444,
+ .child = NULL,
+ .proc_handler = proc_dostring,
+ },
+ {
+ .procname = "p2p_int_addr",
+ .data = &wl_sysctl_macstring[1],
+ .maxlen = MAC_STRING_LEN,
+ .mode = 0444,
+ .child = NULL,
+ .proc_handler = proc_dostring,
+ },
+ {0}
+};
+static ctl_table wl_sysctl_table[] = {
+ {
+ .procname = "wifi",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0555,
+ .child = wl_sysctl_child,
+ .proc_handler = proc_dostring,
+ },
+ {0}
+};
+static struct ctl_table_header *wl_sysctl_hdr;
+#endif /* CONFIG_SYSCTL */
/* Data Element Definitions */
#define WPS_ID_CONFIG_METHODS 0x1008
@@ -90,7 +132,9 @@ u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
/*
* cfg80211_ops api/callback list
*/
-
+static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
+ const struct ether_addr *sa, const struct ether_addr *bssid,
+ u8 **pheader, u32 *body_len, u8 *pbody);
static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid);
@@ -119,15 +163,9 @@ static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type,
s32 dbm);
static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
-#ifdef NEW_COMPAT_WIRELESS
static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx, bool unicast, bool multicast);
-#else
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
- struct net_device *dev,
- u8 key_idx);
-#endif /* NEW_COMPAT_WIRELESS */
static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params);
@@ -161,7 +199,7 @@ static void wl_init_eq_lock(struct wl_priv *wl);
static void wl_init_event_handler(struct wl_priv *wl);
static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type,
- const wl_event_msg_t *msg, void *data);
+ const wl_event_msg_t *msg, void *data, gfp_t gfp);
static void wl_put_event(struct wl_event_q *e);
static void wl_wakeup_event(struct wl_priv *wl);
static s32 wl_notify_connect_status(struct wl_priv *wl,
@@ -195,8 +233,6 @@ static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name,
static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name,
s32 *retval);
-static s32 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
- u32 len);
/*
* cfg80211 set_wiphy_params utilities
@@ -275,18 +311,18 @@ static void *wl_get_drvdata(struct wl_dev *dev);
/*
* ibss mode utilities
*/
-static bool wl_is_ibssmode(struct wl_priv *wl);
+static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev);
static __used bool wl_is_ibssstarter(struct wl_priv *wl);
/*
* dongle up/down , default configuration utilities
*/
static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
+static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev);
static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
static void wl_link_up(struct wl_priv *wl);
static void wl_link_down(struct wl_priv *wl);
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
+static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
static s32 __wl_cfg80211_up(struct wl_priv *wl);
static s32 __wl_cfg80211_down(struct wl_priv *wl);
static s32 wl_dongle_probecap(struct wl_priv *wl);
@@ -297,7 +333,6 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev);
* dongle configuration utilities
*/
#ifndef EMBEDDED_PLATFORM
-/* static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype); */
static s32 wl_dongle_country(struct net_device *ndev, u8 ccode);
static s32 wl_dongle_up(struct net_device *ndev, u32 up);
static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
@@ -325,12 +360,6 @@ static void wl_iscan_timer(unsigned long data);
static void wl_term_iscan(struct wl_priv *wl);
static s32 wl_init_iscan(struct wl_priv *wl);
static s32 wl_iscan_thread(void *data);
-static s32 wl_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
- void *param, s32 paramlen, void *bufptr,
- s32 buflen);
-static s32 wl_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
- void *param, s32 paramlen, void *bufptr,
- s32 buflen);
static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid,
u16 action);
static s32 wl_do_iscan(struct wl_priv *wl);
@@ -344,11 +373,7 @@ static s32 wl_iscan_done(struct wl_priv *wl);
static s32 wl_iscan_pending(struct wl_priv *wl);
static s32 wl_iscan_inprogress(struct wl_priv *wl);
static s32 wl_iscan_aborted(struct wl_priv *wl);
-#ifdef NOT_YET
-static s32 wl_dongle_save_eventmsg(struct wl_priv *wl);
-static s32 wl_dongle_disable_eventmsg(struct wl_priv *wl);
-static s32 wl_dongle_restore_eventmsg(struct wl_priv *wl);
-#endif /* NOT_YET */
+
/*
* fw/nvram downloading handler
*/
@@ -365,7 +390,7 @@ static __used u32 wl_find_msb(u16 bit16);
static __used s32 wl_update_pmklist(struct net_device *dev,
struct wl_pmk_list *pmk_list, s32 err);
-static void wl_set_mpc(struct net_device *ndev, int mpc);
+static void wl_set_mpc(struct net_device *ndev, s32 mpc);
/*
* debufs support
@@ -469,7 +494,7 @@ static struct ieee80211_rate __wl_rates[] = {
RATETAB_ENT(WLC_RATE_24M, 0),
RATETAB_ENT(WLC_RATE_36M, 0),
RATETAB_ENT(WLC_RATE_48M, 0),
- RATETAB_ENT(WLC_RATE_54M, 0),
+ RATETAB_ENT(WLC_RATE_54M, 0)
};
#define wl_a_rates (__wl_rates + 4)
@@ -491,7 +516,7 @@ static struct ieee80211_channel __wl_2ghz_channels[] = {
CHAN2G(11, 2462, 0),
CHAN2G(12, 2467, 0),
CHAN2G(13, 2472, 0),
- CHAN2G(14, 2484, 0),
+ CHAN2G(14, 2484, 0)
};
static struct ieee80211_channel __wl_5ghz_a_channels[] = {
@@ -513,7 +538,7 @@ static struct ieee80211_channel __wl_5ghz_a_channels[] = {
CHAN5G(192, 0), CHAN5G(196, 0),
CHAN5G(200, 0), CHAN5G(204, 0),
CHAN5G(208, 0), CHAN5G(212, 0),
- CHAN5G(216, 0),
+ CHAN5G(216, 0)
};
static struct ieee80211_channel __wl_5ghz_n_channels[] = {
@@ -571,7 +596,7 @@ static struct ieee80211_channel __wl_5ghz_n_channels[] = {
CHAN5G(214, 0), CHAN5G(216, 0),
CHAN5G(218, 0), CHAN5G(220, 0),
CHAN5G(222, 0), CHAN5G(224, 0),
- CHAN5G(226, 0), CHAN5G(228, 0),
+ CHAN5G(226, 0), CHAN5G(228, 0)
};
static struct ieee80211_supported_band __wl_band_2ghz = {
@@ -579,7 +604,7 @@ static struct ieee80211_supported_band __wl_band_2ghz = {
.channels = __wl_2ghz_channels,
.n_channels = ARRAY_SIZE(__wl_2ghz_channels),
.bitrates = wl_g_rates,
- .n_bitrates = wl_g_rates_size,
+ .n_bitrates = wl_g_rates_size
};
static struct ieee80211_supported_band __wl_band_5ghz_a = {
@@ -587,7 +612,7 @@ 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
};
static struct ieee80211_supported_band __wl_band_5ghz_n = {
@@ -595,7 +620,7 @@ static struct ieee80211_supported_band __wl_band_5ghz_n = {
.channels = __wl_5ghz_n_channels,
.n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
.bitrates = wl_a_rates,
- .n_bitrates = wl_a_rates_size,
+ .n_bitrates = wl_a_rates_size
};
static const u32 __wl_cipher_suites[] = {
@@ -603,7 +628,7 @@ static const u32 __wl_cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP104,
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
- WLAN_CIPHER_SUITE_AES_CMAC,
+ WLAN_CIPHER_SUITE_AES_CMAC
};
/* There isn't a lot of sense in it, but you can transmit anything you like */
@@ -653,7 +678,7 @@ wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
BIT(IEEE80211_STYPE_AUTH >> 4) |
BIT(IEEE80211_STYPE_DEAUTH >> 4) |
BIT(IEEE80211_STYPE_ACTION >> 4)
- },
+ }
};
static void swap_key_from_BE(struct wl_wsec_key *key)
@@ -678,33 +703,6 @@ static void swap_key_to_BE(struct wl_wsec_key *key)
key->iv_initialized = dtoh32(key->iv_initialized);
}
-static s32
-wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
-{
- struct ifreq ifr;
- struct wl_ioctl ioc;
- mm_segment_t fs;
- s32 err = 0;
-
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = cmd;
- ioc.buf = arg;
- ioc.len = len;
- strcpy(ifr.ifr_name, dev->name);
- ifr.ifr_data = (caddr_t)&ioc;
-
- fs = get_fs();
- set_fs(get_ds());
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
- err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#else
- err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
- set_fs(fs);
-
- return err;
-}
-
/* For debug: Dump the contents of the encoded wps ie buffe */
static void
wl_dbg_dump_wps_ie(char *wps_ie)
@@ -777,13 +775,14 @@ wl_dbg_dump_wps_ie(char *wps_ie)
static struct net_device *
wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params)
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
{
s32 err;
s32 timeout = -1;
s32 wlif_type;
s32 index = 0;
+ s32 mode = 0;
chanspec_t chspec;
struct wl_priv *wl = WL_PRIV_GET();
struct net_device *_ndev;
@@ -796,19 +795,19 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
WL_ERR(("Unsupported interface type\n"));
- wl->conf->mode = WL_MODE_IBSS;
+ mode = WL_MODE_IBSS;
return NULL;
case NL80211_IFTYPE_MONITOR:
return wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
- wlif_type = WL_P2P_IF_CLIENT;
- wl->conf->mode = WL_MODE_BSS;
+ wlif_type = WL_P2P_IF_CLIENT;
+ mode = WL_MODE_BSS;
break;
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_AP:
wlif_type = WL_P2P_IF_GO;
- wl->conf->mode = WL_MODE_AP;
+ mode = WL_MODE_AP;
break;
default:
WL_ERR(("Unsupported interface type\n"));
@@ -821,6 +820,26 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
return NULL;
}
+ if (test_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status) == 1) {
+ /* wait till IF_DEL is complete
+ * release the lock for the unregister to proceed
+ */
+ rtnl_unlock();
+ WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n", __func__));
+ timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
+ (test_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status) == FALSE),
+ msecs_to_jiffies(MAX_WAIT_TIME));
+
+ /* put back the rtnl_lock again */
+ rtnl_lock();
+ if (timeout > 0) {
+ WL_ERR(("IF DEL is Success\n"));
+
+ } else {
+ WL_ERR(("%s: timeount < 0, return -EAGAIN\n", __func__));
+ return ERR_PTR(-EAGAIN);
+ }
+ }
if (!wl->p2p_on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
wl->p2p_on = true;
wl_cfgp2p_init_discovery(wl);
@@ -836,16 +855,16 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
/* For P2P mode, use P2P-specific driver features to create the
* bss: "wl p2p_ifadd"
*/
- clear_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
+ set_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
err = wl_cfgp2p_ifadd(wl, &wl->p2p_int_addr, htod32(wlif_type), chspec);
if (unlikely(err))
return ERR_PTR(-ENOMEM);
timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
- (test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status) == TRUE),
+ (test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status) == FALSE),
msecs_to_jiffies(MAX_WAIT_TIME));
- if (timeout > 0 && test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status)) {
+ if (timeout > 0 && (!test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status))) {
struct wireless_dev *vwdev;
vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
@@ -859,17 +878,17 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
wl->vwdev[index] = vwdev;
vwdev->iftype =
(wlif_type == WL_P2P_IF_CLIENT) ? NL80211_IFTYPE_STATION
- : NL80211_IFTYPE_AP;
+ : NL80211_IFTYPE_AP;
_ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
_ndev->ieee80211_ptr = vwdev;
SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy));
vwdev->netdev = _ndev;
set_bit(WL_STATUS_READY, &wl->status);
wl->p2p_vif_created = TRUE;
+ set_mode_by_netdev(wl, _ndev, mode);
wl = wdev_to_wl(vwdev);
return _ndev;
-
} else {
clear_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
WL_ERR((" virtual interface(%s) is not created \n", wl->p2p_vir_ifname));
@@ -892,6 +911,9 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
wl_cfg80211_scan_abort(wl, dev);
}
wl_cfgp2p_ifdel(wl, &p2p_mac);
+ WL_ERR(("ifdel command sent to Firmware.. "
+ "and we just come out without waiting.."));
+ set_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status);
}
@@ -901,15 +923,16 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
static s32
wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params)
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
{
s32 ap = 0;
s32 infra = 0;
s32 err = BCME_OK;
- chanspec_t chspec;
s32 timeout = -1;
s32 wlif_type;
+ s32 mode = 0;
+ chanspec_t chspec;
struct wl_priv *wl = WL_PRIV_GET();
CHECK_SYS_UP();
switch (type) {
@@ -921,17 +944,17 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
type));
break;
case NL80211_IFTYPE_ADHOC:
- wl->conf->mode = WL_MODE_IBSS;
+ mode = WL_MODE_IBSS;
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
- wl->conf->mode = WL_MODE_BSS;
+ mode = WL_MODE_BSS;
infra = 1;
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_P2P_GO:
- wl->conf->mode = WL_MODE_AP;
+ mode = WL_MODE_AP;
ap = 1;
break;
default:
@@ -951,7 +974,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
(test_bit(WLP2P_STATUS_IF_CHANGED, &wl->p2p_status) == TRUE),
msecs_to_jiffies(MAX_WAIT_TIME));
-
+ set_mode_by_netdev(wl, ndev, mode);
clear_bit(WLP2P_STATUS_IF_CHANGING, &wl->p2p_status);
clear_bit(WLP2P_STATUS_IF_CHANGED, &wl->p2p_status);
}
@@ -971,12 +994,12 @@ wl_cfg80211_notify_ifadd(struct net_device *net)
}
WL_DBG(("IF_ADD event called from dongle, old interface name: %s, new name: %s\n",
- net->name, wl->p2p_vir_ifname));
+ net->name, wl->p2p_vir_ifname));
/* Assign the net device to CONNECT BSSCFG */
strncpy(net->name, wl->p2p_vir_ifname, IFNAMSIZ - 1);
wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = net;
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = P2PAPI_BSSCFG_CONNECTION;
- set_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
+ clear_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
wake_up_interruptible(&wl->dongle_event_wait);
return ret;
}
@@ -992,7 +1015,7 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
}
WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n",
- net->name, wl->p2p_vir_ifname));
+ net->name, wl->p2p_vir_ifname));
if (wl->p2p_vif_created) {
s32 index = 0;
memset(wl->p2p_vir_ifname, '\0', IFNAMSIZ);
@@ -1000,6 +1023,7 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
wl_to_p2p_bss_ndev(wl, index) = NULL;
wl_to_p2p_bss_bssidx(wl, index) = 0;
wl->p2p_vif_created = FALSE;
+ set_mode_by_netdev(wl, net, -1);
wl_cfgp2p_clear_management_ie(wl,
index);
index = get_idx_vwdev_by_netdev(wl, net);
@@ -1007,10 +1031,24 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
if (index >= 0) {
free_vwdev_by_index(wl, index);
}
+ /* Another option.. Make the IF_ADD wait, if the IF_DEL is not complete.. */
+ clear_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status);
+ WL_ERR(("Cleared IF_DELETING status bit\n"));
+ wake_up_interruptible(&wl->dongle_event_wait);
+ WL_ERR(("Cleared IF_DELETING status bit DONE WAKEUP Interruptible\n"));
}
return 0;
}
+s32
+wl_cfg80211_is_progress_ifadd(void)
+{
+ s32 is_progress = 0;
+ struct wl_priv *wl = WL_PRIV_GET();
+ if (test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status))
+ is_progress = 1;
+ return is_progress;
+}
s32
wl_cfg80211_is_progress_ifchange(void)
@@ -1055,42 +1093,18 @@ static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
}
static s32
-wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
- s32 paramlen, void *bufptr, s32 buflen)
-{
- s32 iolen;
-
- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
- BUG_ON(unlikely(!iolen));
-
- return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
-}
-
-static s32
-wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
- s32 paramlen, void *bufptr, s32 buflen)
-{
- s32 iolen;
-
- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
- BUG_ON(unlikely(!iolen));
-
- return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
-}
-
-static s32
wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
{
s32 params_size =
- (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
+ (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
struct wl_iscan_params *params;
s32 err = 0;
if (ssid && ssid->SSID_len)
- params_size += sizeof(struct wlc_ssid);
+ params_size += sizeof(struct wlc_ssid);
params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
if (unlikely(!params))
- return -ENOMEM;
+ return -ENOMEM;
memset(params, 0, params_size);
BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
@@ -1101,13 +1115,13 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
params->scan_duration = htod16(0);
/* params_size += offsetof(wl_iscan_params_t, params); */
- err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+ err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
iscan->ioctl_buf, WLC_IOCTL_SMLEN);
if (unlikely(err)) {
- if (err == -EBUSY) {
+ if (err == -EBUSY) {
WL_INFO(("system busy : iscan canceled\n"));
} else {
- WL_ERR(("error (%d)\n", err));
+ WL_ERR(("error (%d)\n", err));
}
}
kfree(params);
@@ -1128,8 +1142,8 @@ static s32 wl_do_iscan(struct wl_priv *wl)
iscan->state = WL_ISCAN_STATE_SCANING;
passive_scan = wl->active_scan ? 0 : 1;
- err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
+ err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+ &passive_scan, sizeof(passive_scan), FALSE);
if (unlikely(err)) {
WL_DBG(("error (%d)\n", err));
return err;
@@ -1185,8 +1199,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
params->version = htod32(ESCAN_REQ_VERSION);
params->action = htod16(action);
params->sync_id = htod16(0x1234);
- wl_dev_iovar_setbuf(ndev, "escan", params, params_size,
- wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN);
+ wldev_iovar_setbuf(ndev, "escan", params, params_size,
+ wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN);
kfree(params);
}
else if (wl->p2p_on && wl->p2p_scan) {
@@ -1195,7 +1209,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
num_chans = scan_request->n_channels;
WL_INFO((" chann number : %d\n", num_chans));
default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
- GFP_KERNEL);
+ GFP_KERNEL);
if (default_chan_list == NULL) {
WL_ERR(("channel list allocation failed \n"));
err = -ENOMEM;
@@ -1205,7 +1219,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
{
default_chan_list[i] =
ieee80211_frequency_to_channel(
- scan_request->channels[i]->center_freq);
+ scan_request->channels[i]->center_freq);
}
if (num_chans == 3 && (
(default_chan_list[0] == SOCIAL_CHAN_1) &&
@@ -1219,8 +1233,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
}
}
- err = wl_cfgp2p_escan(wl, wl->active_scan, num_chans, default_chan_list,
- search_state, action,
+ err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list,
+ search_state, action,
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
kfree(default_chan_list);
}
@@ -1242,8 +1256,8 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, wl
wl->escan_info.wiphy = wiphy;
wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
passive_scan = wl->active_scan ? 0 : 1;
- err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
+ err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+ &passive_scan, sizeof(passive_scan), FALSE);
if (unlikely(err)) {
WL_DBG(("error (%d)\n", err));
return err;
@@ -1346,7 +1360,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
if (wl->p2p_on && wl->p2p_scan) {
- err = wl_cfgp2p_enable_discovery(wl, request->ie, request->ie_len);
+ err = wl_cfgp2p_enable_discovery(wl, ndev, request->ie, request->ie_len);
if (unlikely(err)) {
goto scan_out;
@@ -1374,15 +1388,15 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
}
WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
passive_scan = wl->active_scan ? 0 : 1;
- err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
+ err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+ &passive_scan, sizeof(passive_scan), FALSE);
if (unlikely(err)) {
WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
goto scan_out;
}
wl_set_mpc(ndev, 0);
- err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
- sizeof(sr->ssid));
+ err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
+ sizeof(sr->ssid), FALSE);
if (err) {
if (err == -EBUSY) {
WL_INFO(("system busy : scan for \"%s\" "
@@ -1430,7 +1444,7 @@ static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
BUG_ON(unlikely(!len));
- err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
+ err = wldev_ioctl(dev, WLC_SET_VAR, buf, len, FALSE);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
}
@@ -1452,7 +1466,7 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
len = bcm_mkiovar(name, (char *)(&data_null), 0,
(char *)(&var), sizeof(var.buf));
BUG_ON(unlikely(!len));
- err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
+ err = wldev_ioctl(dev, WLC_GET_VAR, &var, len, FALSE);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
}
@@ -1491,7 +1505,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
retry = htod32(retry);
- err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
+ err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), FALSE);
if (unlikely(err)) {
WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
return err;
@@ -1507,14 +1521,14 @@ static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
CHECK_SYS_UP();
if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
- (wl->conf->rts_threshold != wiphy->rts_threshold)) {
+ (wl->conf->rts_threshold != wiphy->rts_threshold)) {
wl->conf->rts_threshold = wiphy->rts_threshold;
err = wl_set_rts(ndev, wl->conf->rts_threshold);
if (!err)
return err;
}
if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
- (wl->conf->frag_threshold != wiphy->frag_threshold)) {
+ (wl->conf->frag_threshold != wiphy->frag_threshold)) {
wl->conf->frag_threshold = wiphy->frag_threshold;
err = wl_set_frag(ndev, wl->conf->frag_threshold);
if (!err)
@@ -1563,14 +1577,14 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
ssid.ssid_len = params->ssid_len;
do {
if (unlikely
- (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
- -EBUSY)) {
+ (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
+ -EBUSY)) {
wl_delay(150);
} else {
break;
}
} while (++scan_retry < WL_SCAN_RETRY_MAX);
- /* to allow scan_inform to paropagate to cfg80211 plane */
+ /* to allow scan_inform to propagate to cfg80211 plane */
rtnl_unlock();
/* wait 4 secons till scan done.... */
@@ -1602,8 +1616,8 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
else
memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
- err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params,
- sizeof(join_params));
+ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
+ sizeof(join_params), FALSE);
if (unlikely(err)) {
WL_ERR(("Error (%d)\n", err));
return err;
@@ -1642,7 +1656,7 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
val = WPA_AUTH_DISABLED;
WL_DBG(("setting wpa_auth to 0x%0x\n", val));
- err = wl_cfgp2p_bssiovar_setint(dev, "wpa_auth", bssidx, val);
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
if (unlikely(err)) {
WL_ERR(("set wpa_auth failed (%d)\n", err));
return err;
@@ -1681,7 +1695,7 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
break;
}
- err = wl_cfgp2p_bssiovar_setint(dev, "auth", bssidx, val);
+ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
if (unlikely(err)) {
WL_ERR(("set auth failed (%d)\n", err));
return err;
@@ -1747,9 +1761,9 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
if (is_wps_conn(sme)) {
- err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, 4);
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
} else {
- err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, pval | gval);
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", pval | gval, bssidx);
}
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
@@ -1808,7 +1822,7 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
WL_DBG(("setting wpa_auth to %d\n", val));
- err = wl_cfgp2p_bssiovar_setint(dev, "wpa_auth", bssidx, val);
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
if (unlikely(err)) {
WL_ERR(("could not set wpa_auth (%d)\n", err));
return err;
@@ -1866,7 +1880,8 @@ wl_set_set_sharedkey(struct net_device *dev,
key.len, key.index, key.algo));
WL_DBG(("key \"%s\"\n", key.data));
swap_key_from_BE(&key);
- err = wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
+ ioctlbuf, sizeof(ioctlbuf), bssidx);
if (unlikely(err)) {
WL_ERR(("WLC_SET_KEY error (%d)\n", err));
return err;
@@ -1874,7 +1889,7 @@ wl_set_set_sharedkey(struct net_device *dev,
if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
WL_DBG(("set auth_type to shared key\n"));
val = 1; /* shared key */
- err = wl_cfgp2p_bssiovar_setint(dev, "auth", bssidx, val);
+ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
if (unlikely(err)) {
WL_ERR(("set auth failed (%d)\n", err));
return err;
@@ -1896,10 +1911,10 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
s32 err = 0;
WL_TRACE(("In\n"));
+ CHECK_SYS_UP();
if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) {
/* we only allow to connect using virtual interface in case of P2P */
if (wl->p2p_on && is_wps_conn(sme)) {
-
WL_DBG(("p2p index : %d\n", wl_cfgp2p_find_idx(wl, dev)));
/* Have to apply WPS IE + P2P IE in assoc req frame */
wl_cfgp2p_set_managment_ie(wl, dev,
@@ -1909,13 +1924,21 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len);
wl_cfgp2p_set_managment_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
+ } else if (wl->p2p_on && (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
+ /* This is the connect req after WPS is done [credentials exchanged]
+ * currently identified with WPA_VERSION_2 .
+ * Update the previously set IEs with
+ * the newly received IEs from Supplicant. This will remove the WPS IE from
+ * the Assoc Req.
+ */
+ wl_cfgp2p_set_managment_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
+ VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
}
+
} else {
WL_ERR(("No P2PIE in beacon \n"));
}
-
- CHECK_SYS_UP();
if (unlikely(!sme->ssid)) {
WL_ERR(("Invalid ssid\n"));
return -EOPNOTSUPP;
@@ -1967,7 +1990,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
WL_ERR(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
join_params.ssid.SSID_len));
}
- err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, FALSE);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
return err;
@@ -1993,8 +2016,8 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
scbval.val = reason_code;
memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
scbval.val = htod32(scbval.val);
- err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
- sizeof(scb_val_t));
+ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+ sizeof(scb_val_t), FALSE);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
return err;
@@ -2035,7 +2058,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 = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
+ err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), FALSE);
if (unlikely(err)) {
WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
return err;
@@ -2076,15 +2099,9 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
return err;
}
-#ifdef NEW_COMPAT_WIRELESS
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
- struct net_device *dev,
+static s32
+wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, bool unicast, bool multicast)
-#else
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
- struct net_device *dev,
- u8 key_idx)
-#endif /* NEW_COMPAT_WIRELESS */
{
struct wl_priv *wl = WL_PRIV_GET();
u32 index;
@@ -2094,23 +2111,17 @@ static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
WL_DBG(("key index (%d)\n", key_idx));
CHECK_SYS_UP();
- /* TODO: wl_cfgp2p_bssiovar_get seems to have a problem here
- * roll back to old way
- err = wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
- */
- UNUSED_PARAMETER(bssidx);
- err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
+ err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
if (unlikely(err)) {
WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
return err;
}
- wsec = dtoh32(wsec);
if (wsec & WEP_ENABLED) {
/* Just select a new current key */
index = (u32) key_idx;
index = htod32(index);
- err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
- sizeof(index));
+ err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
+ sizeof(index), FALSE);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
}
@@ -2138,7 +2149,8 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
if (key.len == 0) {
/* key delete */
swap_key_from_BE(&key);
- wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+ wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+ sizeof(ioctlbuf), bssidx);
if (unlikely(err)) {
WL_ERR(("key delete error (%d)\n", err));
return err;
@@ -2165,7 +2177,7 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
u8 *ivptr;
ivptr = (u8 *) params->seq;
key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
- (ivptr[3] << 8) | ivptr[2];
+ (ivptr[3] << 8) | ivptr[2];
key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
key.iv_initialized = true;
}
@@ -2199,7 +2211,8 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
#ifdef CONFIG_WIRELESS_EXT
dhd_wait_pend8021x(dev);
#endif
- wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+ wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+ sizeof(ioctlbuf), bssidx);
if (unlikely(err)) {
WL_ERR(("WLC_SET_KEY error (%d)\n", err));
return err;
@@ -2227,12 +2240,8 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
bssidx = wl_cfgp2p_find_idx(wl, dev);
if (mac_addr) {
-#if defined(P2P_CONFLICT_GONE)
wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
goto exit;
-#else
- return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
-#endif /* defined(P2P_CONFLICT_GONE) */
}
memset(&key, 0, sizeof(key));
@@ -2283,23 +2292,22 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
/* Set the new key/index */
swap_key_from_BE(&key);
- err = wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+ sizeof(ioctlbuf), bssidx);
if (unlikely(err)) {
WL_ERR(("WLC_SET_KEY error (%d)\n", err));
return err;
}
-#if defined(P2P_CONFLICT_GONE)
+
exit:
-#endif
- val = WEP_ENABLED;
- err = wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
+ err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
if (unlikely(err)) {
WL_ERR(("get wsec error (%d)\n", err));
return err;
}
- wsec &= ~(WEP_ENABLED);
+
wsec |= val;
- err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, wsec);
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
if (unlikely(err)) {
WL_ERR(("set wsec error (%d)\n", err));
return err;
@@ -2309,7 +2317,7 @@ exit:
/* TODO: Removed in P2P, check later --lm */
val = 1; /* assume shared key. otherwise 0 */
val = htod32(val);
- err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(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;
@@ -2325,8 +2333,6 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
struct wl_wsec_key key;
struct wl_priv *wl = WL_PRIV_GET();
s32 err = 0;
- s32 val;
- s32 wsec = 0;
s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
WL_DBG(("Enter\n"));
@@ -2340,7 +2346,8 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
WL_DBG(("key index (%d)\n", key_idx));
/* Set the new key/index */
swap_key_from_BE(&key);
- wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+ wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+ sizeof(ioctlbuf), bssidx);
if (unlikely(err)) {
if (err == -EINVAL) {
if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
@@ -2353,26 +2360,11 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
return err;
}
- val = 0;
- err = wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
- if (unlikely(err)) {
- WL_ERR(("get wsec error (%d)\n", err));
- return err;
- }
-
- wsec &= ~(WEP_ENABLED);
- wsec |= val;
- err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, wsec);
- if (unlikely(err)) {
- WL_ERR(("set wsec error (%d)\n", err));
- return err;
- }
-
#ifdef NOT_YET
/* TODO: Removed in P2P twig, check later --lin */
val = 0; /* assume open key. otherwise 1 */
val = htod32(val);
- err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(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;
@@ -2403,12 +2395,11 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
memcpy(params.key, key.data, params.key_len);
- wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
+ wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
if (unlikely(err)) {
WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
return err;
}
- wsec = dtoh32(wsec);
switch (wsec) {
case WEP_ENABLED:
sec = wl_read_prof(wl, WL_PROF_SEC);
@@ -2458,13 +2449,13 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
CHECK_SYS_UP();
if (unlikely
- (memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) {
+ (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 = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
+ err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), FALSE);
if (err) {
WL_ERR(("Could not get rate (%d)\n", err));
} else {
@@ -2477,8 +2468,8 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
memset(&scb_val, 0, sizeof(scb_val));
scb_val.val = 0;
- err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val,
- sizeof(scb_val_t));
+ 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));
return err;
@@ -2490,7 +2481,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
}
#if defined(ANDROID_WIRELESS_PATCH)
- err = wl_dev_ioctl(dev, WLC_GET_RATE, &sinfo->link_speed, sizeof(sinfo->link_speed));
+ 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;
@@ -2512,7 +2503,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
pm = enabled ? PM_FAST : PM_OFF;
pm = htod32(pm);
WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
- err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+ err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE);
if (unlikely(err)) {
if (err == -ENODEV)
WL_DBG(("net_device is not ready yet\n"));
@@ -2566,8 +2557,8 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
CHECK_SYS_UP();
/* addr param is always NULL. ignore it */
/* Get current rateset */
- err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
- sizeof(rateset));
+ err = wldev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
+ sizeof(rateset), FALSE);
if (unlikely(err)) {
WL_ERR(("could not get current rateset (%d)\n", err));
return err;
@@ -2808,14 +2799,20 @@ 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 = wl_dev_ioctl(ndev, WLC_SCAN, params, params_size);
+ err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, FALSE);
if (err < 0) {
WL_ERR(("scan abort failed \n"));
}
- clear_bit(WL_STATUS_SCANNING, &wl->status);
+ /* Report the scan abort to CFG driver too
+ * We will report it from the thread context, not from this context.
+ */
- if (wl->p2p_on && test_bit(WLP2P_STATUS_SCANNING, &wl->p2p_status))
- clear_bit(WLP2P_STATUS_SCANNING, &wl->p2p_status);
+ {
+ wl_event_msg_t msg;
+ msg.event_type = hton32(WLC_E_ESCAN_RESULT);
+ msg.status = WLC_E_STATUS_ABORT;
+ wl_cfg80211_event(ndev, &msg, NULL, GFP_ATOMIC);
+ }
return err;
}
static s32
@@ -2847,7 +2844,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
* without turning on P2P
*/
- err = wl_cfgp2p_enable_discovery(wl, NULL, 0);
+ err = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0);
if (unlikely(err)) {
goto exit;
@@ -2892,9 +2889,12 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
u32 p2pie_len = 0;
u32 wpsie_len = 0;
u16 fc;
+ bool ack = FALSE;
WL_DBG(("Enter \n"));
/* find bssidx based on ndev */
bssidx = wl_cfgp2p_find_idx(wl, dev);
+ /* cookie generation */
+ *cookie = (unsigned long) buf;
if (bssidx == -1) {
@@ -2908,47 +2908,16 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
* channel.
*/
wl_cfgp2p_discover_enable_search(wl, FALSE);
+ /* Abort the dwell time of any previous off-channel action frame that may
+ * be still in effect. Sending off-channel action frames relies on the
+ * driver's scan engine. If a previous off-channel action frame 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);
}
mgmt = (const struct ieee80211_mgmt *) buf;
fc = mgmt->frame_control;
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_ASSOC_REQ:
- WL_DBG(("packet type: IEEE80211_STYPE_ASSOC_REQ, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_ASSOC_RESP:
- WL_DBG(("packet type: IEEE80211_STYPE_ASSOC_RESP, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_REASSOC_REQ:
- WL_DBG(("packet type: IEEE80211_STYPE_REASSOC_REQ, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_REASSOC_RESP:
- WL_DBG(("packet type: IEEE80211_STYPE_REASSOC_RESP, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_PROBE_REQ:
- WL_DBG(("packet type: IEEE80211_STYPE_PROBE_REQ, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_PROBE_RESP:
- WL_DBG(("packet type: IEEE80211_STYPE_PROBE_RESP, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_BEACON:
- WL_DBG(("packet type: IEEE80211_STYPE_BEACON, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_ATIM:
- WL_DBG(("packet type: IEEE80211_STYPE_ATIM, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_DISASSOC:
- WL_DBG(("packet type: IEEE80211_STYPE_DISASSOC, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_AUTH:
- WL_DBG(("packet type: IEEE80211_STYPE_AUTH, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_DEAUTH:
- WL_DBG(("packet type: IEEE80211_STYPE_DEAUTH, bssidx : %d\n", bssidx));
- break;
- case IEEE80211_STYPE_ACTION:
- WL_DBG(("packet type: IEEE80211_STYPE_ACTION, bssidx : %d\n", bssidx));
- break;
- }
if (fc != IEEE80211_STYPE_ACTION) {
if (wl->p2p_on && (fc == IEEE80211_STYPE_PROBE_RESP)) {
s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
@@ -2960,8 +2929,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
/* Have to change p2p device address in dev_info attribute
* because Supplicant use primary eth0 address
*/
+ #ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */
wl_cfg80211_change_ifaddr((u8 *)p2p_ie,
&wl->p2p_dev_addr, P2P_SEID_DEV_INFO);
+ #endif
}
if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
!= NULL) {
@@ -3011,7 +2982,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
* Dwell time to stay off-channel to wait for a response action frame
* after transmitting an GO Negotiation action frame
*/
- af_params->dwell_time = 200;
+ af_params->dwell_time = WL_DWELL_TIME;
memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
@@ -3019,21 +2990,28 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
wifi_p2p_pub_act_frame_t *act_frm =
(wifi_p2p_pub_act_frame_t *) (action_frame->data);
/*
- * Have to change intented address from GO REQ or GO RSP
+ * Have to change intented address from GO REQ or GO RSP and INVITE REQ
* because wpa-supplicant use eth0 primary address
*/
- if (act_frm->subtype == P2P_PAF_GON_REQ || act_frm->subtype == P2P_PAF_GON_RSP) {
+ if ((act_frm->subtype == P2P_PAF_GON_REQ)||
+ (act_frm->subtype == P2P_PAF_GON_RSP)||
+ (act_frm->subtype == P2P_PAF_GON_CONF)||
+ (act_frm->subtype == P2P_PAF_INVITE_REQ)) {
p2p_ie = wl_cfgp2p_find_p2pie(act_frm->elts,
action_frame->len - P2P_PUB_AF_FIXED_LEN);
+ #ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */
wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_int_addr,
P2P_SEID_INTINTADDR);
wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr,
P2P_SEID_DEV_INFO);
+ wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr,
+ P2P_SEID_GROUP_ID);
+ #endif
}
}
- err = wl_cfgp2p_tx_action_frame(wl, af_params, bssidx);
- cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL);
+ ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? FALSE : TRUE;
+ cfg80211_mgmt_tx_status(dev, *cookie, buf, len, ack, GFP_KERNEL);
kfree(af_params);
exit:
@@ -3092,7 +3070,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));
- wl_dev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel));
+ wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), FALSE);
return err;
}
@@ -3179,17 +3157,17 @@ wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
break;
}
/* set auth */
- err = wl_cfgp2p_bssiovar_setint(dev, "auth", bssidx, auth);
+ err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
if (err < 0) {
WL_ERR(("auth error %d\n", err));
}
/* set wsec */
- err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, wsec);
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
if (err < 0) {
WL_ERR(("wsec error %d\n", err));
}
/* set upper-layer auth */
- err = wl_cfgp2p_bssiovar_setint(dev, "wpa_auth", bssidx, wpa_auth);
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
if (err < 0) {
WL_ERR(("wpa_auth error %d\n", err));
}
@@ -3230,62 +3208,70 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
info->interval, info->dtim_period, info->head_len, info->tail_len));
+
+ /*
+ * !!! The following code was NOT indented properly, PLEASE merge your code
+ * to SVN verion becuase your merger tool may IGNORE tabs/spaces
+ */
if (wl->p2p_on && (bssidx >= wl_to_p2p_bss_bssidx(wl,
P2PAPI_BSSCFG_CONNECTION))) {
- /* We don't need to set beacon for P2P_GO,
- * but need to parse ssid from beacon_parameters
- * because there is no way to set ssid
- */
- ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
- /* find the SSID */
- if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], info->head_len - ie_offset,
- DOT11_MNG_SSID_ID)) != NULL) {
- memcpy(wl->p2p_ssid.SSID, ssid_ie->data, ssid_ie->len);
- wl->p2p_ssid.SSID_len = ssid_ie->len;
- WL_DBG(("SSID (%s) in Head \n", ssid_ie->data));
+ /* We don't need to set beacon for P2P_GO,
+ * but need to parse ssid from beacon_parameters
+ * because there is no way to set ssid
+ */
+ ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
+ /* find the SSID */
+ if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
+ info->head_len - ie_offset,
+ DOT11_MNG_SSID_ID)) != NULL) {
+ memcpy(wl->p2p_ssid.SSID, ssid_ie->data, ssid_ie->len);
+ wl->p2p_ssid.SSID_len = ssid_ie->len;
+ WL_DBG(("SSID (%s) in Head \n", ssid_ie->data));
- } else {
- WL_ERR(("No SSID in beacon \n"));
- }
+ } else {
+ WL_ERR(("No SSID in beacon \n"));
+ }
- /* find the WPSIE */
- if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) {
- wpsie_len = wps_ie->length + sizeof(wps_ie->tag) + sizeof(wps_ie->length);
- /*
- * Should be compared with saved ie before saving it
- */
+ /* find the WPSIE */
+ if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) {
+ wpsie_len = wps_ie->length + sizeof(wps_ie->tag) + sizeof(wps_ie->length);
+ /*
+ * Should be compared with saved ie before saving it
+ */
if (wl_dbg_level & WL_DBG_INFO)
wl_dbg_dump_wps_ie((char *) wps_ie);
- memcpy(beacon_ie, wps_ie, wpsie_len);
- } else {
- WL_ERR(("No WPSIE in beacon \n"));
- }
+ memcpy(beacon_ie, wps_ie, wpsie_len);
+ } else {
+ WL_ERR(("No WPSIE in beacon \n"));
+ }
- /* find the P2PIE */
- if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)info->tail, info->tail_len)) != NULL) {
- /* Total length of P2P Information Element */
- p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
- /* Have to change device address in dev_id attribute because Supplicant
- * use primary eth0 address
- */
- wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr, P2P_SEID_DEV_ID);
- memcpy(&beacon_ie[wpsie_len], p2p_ie, p2pie_len);
+ /* find the P2PIE */
+ if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)info->tail, info->tail_len)) != NULL) {
+ /* Total length of P2P Information Element */
+ p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
+ #ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */
+ /* Have to change device address in dev_id attribute because Supplicant
+ * use primary eth0 address
+ */
+ wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr, P2P_SEID_DEV_ID);
+ #endif
+ memcpy(&beacon_ie[wpsie_len], p2p_ie, p2pie_len);
- } else {
- WL_ERR(("No P2PIE in beacon \n"));
- }
+ } else {
+ WL_ERR(("No P2PIE in beacon \n"));
+ }
wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
- beacon_ie, wpsie_len + p2pie_len);
+ beacon_ie, wpsie_len + p2pie_len);
wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_ASSOCRSP_FLAG,
- beacon_ie, wpsie_len + p2pie_len);
+ beacon_ie, wpsie_len + p2pie_len);
/* find the WPA_IE */
if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail, info->tail_len)) != NULL) {
WL_DBG((" WPA IE is found\n"));
}
/* find the RSN_IE */
if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
- DOT11_MNG_RSN_ID)) != NULL) {
+ DOT11_MNG_RSN_ID)) != NULL) {
WL_DBG((" WPA2 IE is found\n"));
}
is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
@@ -3294,16 +3280,16 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
wl_check_wpa2ie(dev, wpa2_ie, bssidx);
wl_check_wpaie(dev, (bcm_tlv_t *)wpa_ie, bssidx);
- err = wl_dev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32));
- if (err < 0) {
+ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), FALSE);
+ if (err < 0) {
WL_ERR(("SET INFRA error %d\n", err));
- }
+ }
- err = wl_cfgp2p_bssiovar_set(dev, "ssid", bssidx, &wl->p2p_ssid,
- sizeof(wl->p2p_ssid));
+ err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p_ssid,
+ sizeof(wl->p2p_ssid), ioctlbuf, sizeof(ioctlbuf), bssidx);
- wl_cfgp2p_bss(dev, bssidx, 1);
- }
+ wl_cfgp2p_bss(dev, bssidx, 1);
+ }
}
return 0;
}
@@ -3364,7 +3350,7 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.set_beacon = wl_cfg80211_set_beacon,
#if defined(ANDROID_WIRELESS_PATCH)
.drv_start = wl_cfg80211_drv_start,
- .drv_stop = wl_cfg80211_drv_stop,
+ .drv_stop = wl_cfg80211_drv_stop
#endif
};
@@ -3410,23 +3396,24 @@ static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
wdev->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) |
- (BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO));
+ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
+
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;
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);
-#ifdef NEW_COMPAT_WIRELESS
wdev->wiphy->max_remain_on_channel_duration = 5000;
-#endif
wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
#ifndef WL_POWERSAVE_DISABLED
wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
#else
wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
#endif /* !WL_POWERSAVE_DISABLED */
-
+ wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
+ WIPHY_FLAG_4ADDR_AP |
+ WIPHY_FLAG_4ADDR_STATION |
+ WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;
err = wiphy_register(wdev->wiphy);
if (unlikely(err < 0)) {
WL_ERR(("Couldn not register wiphy device (%d)\n", err));
@@ -3490,7 +3477,7 @@ static s32 wl_inform_bss(struct wl_priv *wl)
static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
{
- struct wiphy *wiphy = wl_to_wiphy(wl);
+ struct wiphy *wiphy = wiphy_from_scan(wl);
struct ieee80211_mgmt *mgmt;
struct ieee80211_channel *channel;
struct ieee80211_supported_band *band;
@@ -3548,7 +3535,11 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
offsetof(struct wl_cfg80211_bss_info, frame_buf));
notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
u.beacon.variable) + wl_get_ielen(wl);
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(COMPAT_WIRELESS)
+ freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+#else
freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
+#endif
channel = ieee80211_get_channel(wiphy, freq);
WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
@@ -3570,42 +3561,21 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
return err;
}
-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
+static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
{
- /* To SK, chagne NOT_YET to 1 if you don't like this
- * But in general WLC_E_SET_SSID is more reliable --lin
- */
-#ifdef NOT_YET
- u32 event = ntoh32(e->event_type);
- u16 flags = ntoh16(e->flags);
-
- if (event == WLC_E_LINK) {
- if (flags & WLC_EVENT_MSG_LINK) {
- if (wl_is_ibssmode(wl)) {
- if (wl_is_ibssstarter(wl)) {
- }
- } else {
- return true;
- }
- }
- }
- return false;
-#else
u32 event = ntoh32(e->event_type);
uint32 status = ntoh32(e->status);
- WL_DBG(("event %d\n", event));
- /* was WLC_E_LINK here, changed as WLC_E_SET_SSID is more reliable -- lin */
+ WL_DBG(("event %d, status %d\n", event, status));
if (event == WLC_E_SET_SSID) {
if (status == WLC_E_STATUS_SUCCESS) {
- if (!wl_is_ibssmode(wl))
+ if (!wl_is_ibssmode(wl, ndev))
return true;
}
}
WL_DBG(("wl_is_linkup false\n"));
return false;
-#endif /* NOT_YET */
}
static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
@@ -3636,39 +3606,91 @@ static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
return false;
}
-static bool wl_is_newsta(struct wl_priv *wl, const wl_event_msg_t *e)
-{
- u32 event = ntoh32(e->event_type);
- u32 status = ntoh32(e->status);
-
- if (event == WLC_E_ASSOC_IND && (status == WLC_E_STATUS_SUCCESS)) {
- return true;
- }
- return false;
-}
-
static s32
wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data)
{
bool act;
+ bool isfree = FALSE;
s32 err = 0;
+ s32 freq;
+ s32 channel;
u8 body[200];
+ u32 event = ntoh32(e->event_type);
+ u32 reason = ntoh32(e->reason);
+ u32 len = ntoh32(e->datalen);
+ u16 fc = 0;
+ u8 *mgmt_frame;
+ u8 bsscfgidx = e->bsscfgidx;
+ struct ieee80211_supported_band *band;
+ struct ether_addr da;
+ struct ether_addr bssid;
+ struct wiphy *wiphy = wl_to_wiphy(wl);
+ channel_info_t ci;
+ memset(body, 0, sizeof(body));
WL_DBG(("Enter \n"));
- if (wl->conf->mode == WL_MODE_AP) {
- if (wl_is_newsta(wl, e)) {
- u32 len = ntoh32(e->datalen);
- memcpy(body, e->addr.octet, ETHER_ADDR_LEN);
- memcpy(&body[ETHER_ADDR_LEN], data, len);
- cfg80211_send_rx_assoc(ndev, body, len + ETHER_ADDR_LEN);
+ 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);
+ wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE);
+ switch (event) {
+ case WLC_E_ASSOC_IND:
+ fc = FC_ASSOC_REQ;
+ break;
+ case WLC_E_REASSOC_IND:
+ fc = FC_REASSOC_REQ;
+ break;
+ case WLC_E_DISASSOC_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH_IND:
+ fc = FC_DEAUTH;
+ break;
+ case WLC_E_DEAUTH:
+ fc = FC_DEAUTH;
+ break;
+ default:
+ fc = 0;
+ goto exit;
}
+ if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), FALSE)))
+ return err;
+
+ channel = dtoh32(ci.hw_channel);
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(COMPAT_WIRELESS)
+ freq = ieee80211_channel_to_frequency(channel);
+#else
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+
+ err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
+ &mgmt_frame, &len, body);
+ if (err < 0)
+ goto exit;
+ isfree = TRUE;
+
+ if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+ } else if (event == WLC_E_DISASSOC_IND) {
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+ }
+
} else {
- WL_ERR(("event %d ", ntoh32(e->event_type)));
- if (wl_is_linkup(wl, e)) {
+ WL_DBG(("wl_notify_connect_status : event %d status : %d \n",
+ ntoh32(e->event_type), ntoh32(e->status)));
+ if (wl_is_linkup(wl, e, ndev)) {
wl_link_up(wl);
- if (wl_is_ibssmode(wl)) {
+ if (wl_is_ibssmode(wl, ndev)) {
printk("cfg80211_ibss_joined");
cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
GFP_KERNEL);
@@ -3684,14 +3706,14 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
wl_update_prof(wl, e, &act, WL_PROF_ACT);
} else if (wl_is_linkdown(wl, e)) {
if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
- printk("link down, call cfg80211_disconnected");
+ printk("link down, call cfg80211_disconnected ");
cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
clear_bit(WL_STATUS_CONNECTED, &wl->status);
wl_link_down(wl);
wl_init_prof(wl->profile);
}
} else if (wl_is_nonetwork(wl, e)) {
- printk("connect failed wl->status 0x%x", (int)wl->status);
+ printk("connect failed e->status 0x%x", (int)ntoh32(e->status));
if (test_bit(WL_STATUS_CONNECTING, &wl->status))
wl_bss_connect_done(wl, ndev, e, data, false);
} else {
@@ -3699,6 +3721,9 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
}
printk("\n");
}
+exit:
+ if (isfree)
+ kfree(mgmt_frame);
return err;
}
@@ -3726,7 +3751,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 wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
+ return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, FALSE);
}
static s32
@@ -3739,8 +3764,8 @@ wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
BUG_ON(unlikely(!len));
- err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
- WL_IOCTL_LEN_MAX);
+ err = wldev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
+ WL_IOCTL_LEN_MAX, FALSE);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
return err;
@@ -3752,10 +3777,8 @@ wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
{
- struct wl_assoc_ielen *assoc_info;
+ wl_assoc_info_t assoc_info;
struct wl_connect_info *conn_info = wl_to_conn(wl);
- u32 req_len;
- u32 resp_len;
s32 err = 0;
WL_DBG(("Enter \n"));
@@ -3765,31 +3788,35 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
WL_ERR(("could not get assoc info (%d)\n", err));
return err;
}
- assoc_info = (struct wl_assoc_ielen *)wl->extra_buf;
- req_len = assoc_info->req_len;
- resp_len = assoc_info->resp_len;
- if (req_len) {
+ memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
+ assoc_info.req_len = htod32(assoc_info.req_len);
+ assoc_info.resp_len = htod32(assoc_info.resp_len);
+ assoc_info.flags = htod32(assoc_info.flags);
+ if (assoc_info.req_len) {
err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf,
WL_ASSOC_INFO_MAX);
if (unlikely(err)) {
WL_ERR(("could not get assoc req (%d)\n", err));
return err;
}
- conn_info->req_ie_len = req_len;
+ conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
+ if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
+ conn_info->req_ie_len -= ETHER_ADDR_LEN;
+ }
conn_info->req_ie =
kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
} else {
conn_info->req_ie_len = 0;
conn_info->req_ie = NULL;
}
- if (resp_len) {
+ if (assoc_info.resp_len) {
err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf,
WL_ASSOC_INFO_MAX);
if (unlikely(err)) {
WL_ERR(("could not get assoc resp (%d)\n", err));
return err;
}
- conn_info->resp_ie_len = resp_len;
+ conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
conn_info->resp_ie =
kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
} else {
@@ -3803,7 +3830,7 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
}
static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
- size_t *join_params_size)
+ size_t *join_params_size)
{
chanspec_t chanspec = 0;
@@ -3832,6 +3859,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
WL_DBG(("%s join_params->params.chanspec_list[0]= %X\n",
__FUNCTION__, join_params->params.chanspec_list[0]));
+
}
}
@@ -3849,7 +3877,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
struct wiphy *wiphy;
wiphy = wl_to_wiphy(wl);
- if (wl_is_ibssmode(wl))
+ if (wl_is_ibssmode(wl, ndev))
return err;
ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID);
@@ -3861,8 +3889,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
if (unlikely(!bss)) {
WL_DBG(("Could not find the AP\n"));
*(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
- err = wl_dev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BSS_INFO,
- wl->extra_buf, WL_EXTRA_BUF_MAX);
+ err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BSS_INFO,
+ wl->extra_buf, WL_EXTRA_BUF_MAX, FALSE);
if (unlikely(err)) {
WL_ERR(("Could not get bss info %d\n", err));
goto update_bss_info_out;
@@ -3896,8 +3924,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
* information out of probe response.
* so we speficially query dtim information to dongle.
*/
- err = wl_dev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_DTIMPRD,
- &dtim_period, sizeof(dtim_period));
+ err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_DTIMPRD,
+ &dtim_period, sizeof(dtim_period), FALSE);
if (unlikely(err)) {
WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
goto update_bss_info_out;
@@ -4009,8 +4037,8 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
if (unlikely(!wl->scan_request)) {
}
rtnl_lock();
- err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
- sizeof(channel_inform));
+ err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
+ sizeof(channel_inform), FALSE);
if (unlikely(err)) {
WL_ERR(("scan busy (%d)\n", err));
goto scan_done_out;
@@ -4025,7 +4053,7 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
bss_list = wl->bss_list;
memset(bss_list, 0, len);
bss_list->buflen = htod32(len);
- err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len);
+ err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, FALSE);
if (unlikely(err)) {
WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
err = -EINVAL;
@@ -4049,40 +4077,111 @@ scan_done_out:
rtnl_unlock();
return err;
}
+static s32
+wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
+ const struct ether_addr *sa, const struct ether_addr *bssid,
+ u8 **pheader, u32 *body_len, u8 *pbody)
+{
+ struct dot11_management_header *hdr;
+ u32 totlen = 0;
+ s32 err = 0;
+ u8 *offset;
+ u32 prebody_len = *body_len;
+ switch (fc) {
+ case FC_ASSOC_REQ:
+ /* capability , listen interval */
+ totlen = DOT11_ASSOC_REQ_FIXED_LEN;
+ *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
+ break;
+ case FC_REASSOC_REQ:
+ /* capability, listen inteval, ap address */
+ totlen = DOT11_REASSOC_REQ_FIXED_LEN;
+ *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
+ break;
+ }
+ totlen += DOT11_MGMT_HDR_LEN + prebody_len;
+ *pheader = kzalloc(totlen, GFP_KERNEL);
+ if (*pheader == NULL) {
+ WL_ERR(("memory alloc failed \n"));
+ return -ENOMEM;
+ }
+ hdr = (struct dot11_management_header *) (*pheader);
+ hdr->fc = htol16(fc);
+ hdr->durid = 0;
+ hdr->seq = 0;
+ offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
+ bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
+ bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
+ bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
+ bcopy((const char*)pbody, offset, prebody_len);
+ *body_len = totlen;
+ return err;
+}
static s32
wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data)
{
struct ieee80211_supported_band *band;
- s32 freq;
struct wiphy *wiphy = wl_to_wiphy(wl);
-
+ struct ether_addr da;
+ struct ether_addr bssid;
+ bool isfree = FALSE;
+ s32 err = 0;
+ s32 freq;
wl_event_rx_frame_data_t *rxframe =
(wl_event_rx_frame_data_t*)data;
-
- u8 *mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
+ u32 event = ntoh32(e->event_type);
+ u8 *mgmt_frame;
+ u8 bsscfgidx = e->bsscfgidx;
u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
-
u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK) & 0x0f);
-
if (channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(COMPAT_WIRELESS)
+ freq = ieee80211_channel_to_frequency(channel);
+#else
freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+ if (event == WLC_E_ACTION_FRAME_RX) {
+ wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+ &da, sizeof(struct ether_addr), ioctlbuf, sizeof(ioctlbuf), bsscfgidx);
+ wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE);
+ 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));
+ if (err < 0) {
+ WL_ERR(("%s: Error in receiving action frame len %d channel %d freq %d\n",
+ __func__, mgmt_frame_len, channel, freq));
+ goto exit;
+ }
+ isfree = TRUE;
+ } else {
+ mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
+ }
cfg80211_rx_mgmt(ndev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
WL_DBG(("%s: mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", __func__,
mgmt_frame_len, ntoh32(e->datalen), channel, freq));
+
+ if (isfree)
+ kfree(mgmt_frame);
+exit:
return 0;
}
static void wl_init_conf(struct wl_conf *conf)
{
+ s32 i = 0;
WL_DBG(("Enter \n"));
- conf->mode = (u32)-1;
+ for (i = 0; i <= VWDEV_CNT; i++) {
+ conf->mode[i].type = -1;
+ conf->mode[i].ndev = NULL;
+ }
conf->frag_threshold = (u32)-1;
conf->rts_threshold = (u32)-1;
conf->retry_short = (u32)-1;
@@ -4100,9 +4199,10 @@ static void wl_init_event_handler(struct wl_priv *wl)
memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
- wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
+ /* wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status; */
wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
+ wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
@@ -4115,18 +4215,6 @@ static void wl_init_event_handler(struct wl_priv *wl)
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;
- /* Used to be like this...
- el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
- el->handler[WLC_E_JOIN] = wl_notify_connect_status;
- el->handler[WLC_E_LINK] = wl_notify_connect_status;
- el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
- el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
- el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
- el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
- el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
- el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
- el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
- */
}
static s32 wl_init_priv_mem(struct wl_priv *wl)
@@ -4307,7 +4395,7 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
memset(&list, 0, sizeof(list));
list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
- err = wl_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
+ err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
WL_ISCAN_BUF_MAX);
if (unlikely(err)) {
@@ -4557,6 +4645,15 @@ static s32 wl_escan_handler(struct wl_priv *wl,
rtnl_unlock();
}
}
+ else if (status == WLC_E_STATUS_ABORT) {
+ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+ if (likely(wl->scan_request)) {
+ rtnl_lock();
+ WL_INFO(("ESCAN COMPLETED\n"));
+ wl_notify_escan_complete(wl, true);
+ rtnl_unlock();
+ }
+ }
exit:
return err;
}
@@ -4603,8 +4700,8 @@ static s32 wl_init_priv(struct wl_priv *wl)
wl->scan_request = NULL;
wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
- wl->iscan_on = true;
- wl->escan_on = false;
+ wl->iscan_on = false;
+ wl->escan_on = true;
wl->roam_on = false;
wl->iscan_kickstart = false;
wl->active_scan = true;
@@ -4645,6 +4742,48 @@ static void wl_deinit_priv(struct wl_priv *wl)
wl_deinit_priv_mem(wl);
}
+#ifdef CONFIG_SYSCTL
+s32 wl_cfg80211_sysctl_export_devaddr(void *data)
+{
+ /* Export the p2p_dev_addr via sysctl interface
+ * so that wpa_supplicant can access it
+ */
+ dhd_pub_t *dhd = (dhd_pub_t *)data;
+ struct wl_priv *wl = WL_PRIV_GET();
+
+ wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p_dev_addr, &wl->p2p_int_addr);
+
+ sprintf((char *)&wl_sysctl_macstring[0], MACSTR, MAC2STR(wl->p2p_dev_addr.octet));
+ sprintf((char *)&wl_sysctl_macstring[1], MACSTR, MAC2STR(wl->p2p_int_addr.octet));
+
+ return 0;
+}
+#endif /* CONFIG_SYSCTL */
+
+s32 wl_cfg80211_attach_post(struct net_device *ndev)
+{
+ struct wl_priv * wl = NULL;
+ s32 err = 0;
+ WL_TRACE(("In\n"));
+ if (unlikely(!ndev)) {
+ WL_ERR(("ndev is invaild\n"));
+ return -ENODEV;
+ }
+ wl = WL_PRIV_GET();
+ if (wl && !test_bit(WL_STATUS_READY, &wl->status)) {
+ if (wl->wdev &&
+ wl_cfgp2p_is_p2p_supported(wl, ndev)) {
+ WL_INFO(("P2P is supported on Firmware \n"));
+ wl->wdev->wiphy->interface_modes |=
+ (BIT(NL80211_IFTYPE_P2P_CLIENT)|
+ BIT(NL80211_IFTYPE_P2P_GO));
+ }
+ } else
+ return -ENODEV;
+
+ set_bit(WL_STATUS_READY, &wl->status);
+ return err;
+}
s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
{
struct wireless_dev *wdev;
@@ -4690,9 +4829,13 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
goto cfg80211_attach_out;
}
+#ifdef CONFIG_SYSCTL
+ if (!(wl_sysctl_hdr = register_sysctl_table(wl_sysctl_table))) {
+ WL_ERR(("%s: sysctl register failed!! \n", __func__));
+ goto cfg80211_attach_out;
+ }
+#endif
wl_set_drvdata(wl_cfg80211_dev, ci);
- set_bit(WL_STATUS_READY, &wl->status);
-
return err;
cfg80211_attach_out:
@@ -4709,6 +4852,10 @@ void wl_cfg80211_detach(void)
WL_TRACE(("In\n"));
+#ifdef CONFIG_SYSCTL
+ if (wl_sysctl_hdr)
+ unregister_sysctl_table(wl_sysctl_hdr);
+#endif
rfkill_unregister(wl->rfkill);
rfkill_destroy(wl->rfkill);
@@ -4758,7 +4905,7 @@ static s32 wl_event_handler(void *data)
}
void
-wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data, gfp_t gfp)
{
u32 event_type = ntoh32(e->event_type);
struct wl_priv *wl = WL_PRIV_GET();
@@ -4769,7 +4916,7 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
#endif /* (WL_DBG_LEVEL > 0) */
- if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
+ if (likely(!wl_enq_event(wl, ndev, event_type, e, data, gfp)))
wl_wakeup_event(wl);
}
@@ -4816,7 +4963,7 @@ static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
static s32
wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
- void *data)
+ void *data, gfp_t gfp)
{
struct wl_event_q *e;
s32 err = 0;
@@ -4827,7 +4974,7 @@ wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_ev
if (data)
data_len = ntoh32(msg->datalen);
evtq_size = sizeof(struct wl_event_q) + data_len;
- e = kzalloc(evtq_size, GFP_KERNEL);
+ e = kzalloc(evtq_size, gfp);
if (unlikely(!e)) {
WL_ERR(("event alloc failed\n"));
return -ENOMEM;
@@ -4866,12 +5013,11 @@ struct sdio_func *wl_cfg80211_get_sdio_func(void)
return cfg80211_sdio_func;
}
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
+static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
{
s32 infra = 0;
- s32 ap = 0;
s32 err = 0;
-
+ s32 mode = 0;
switch (iftype) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_WDS:
@@ -4880,8 +5026,10 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
err = -EINVAL;
return err;
case NL80211_IFTYPE_ADHOC:
+ mode = WL_MODE_IBSS;
break;
case NL80211_IFTYPE_STATION:
+ mode = WL_MODE_BSS;
infra = 1;
break;
default:
@@ -4890,69 +5038,16 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
return err;
}
infra = htod32(infra);
- ap = htod32(ap);
- WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
- err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+ err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), FALSE);
if (unlikely(err)) {
WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
return err;
}
- err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
- if (unlikely(err)) {
- WL_ERR(("WLC_SET_AP error (%d)\n", err));
- return err;
- }
-
- return -EINPROGRESS;
-}
-#ifdef NOT_YET
-static s32 wl_dongle_save_eventmsg(struct wl_priv *wl)
-{
- s8 eventmask[WL_EVENTING_MASK_LEN];
- s32 err = 0;
- struct net_device *ndev = wl_to_prmry_ndev(wl);
- /* Room for "event_msgs" + '\0' + bitvec */
- err = wl_cfgp2p_bssiovar_get(ndev, "event_msgs", 0,
- eventmask, WL_EVENTING_MASK_LEN);
- if (unlikely(err)) {
- WL_ERR(("Get event_msgs error (%d)\n", err));
- } else {
- memcpy(wl->last_eventmask, eventmask, WL_EVENTING_MASK_LEN);
- }
- return err;
-}
-
-static s32 wl_dongle_disable_eventmsg(struct wl_priv *wl)
-{
- s8 eventmask[WL_EVENTING_MASK_LEN];
- s32 err = 0;
- struct net_device *ndev = wl_to_prmry_ndev(wl);
- /* Only Enable IF EVENT */
- setbit(eventmask, WLC_E_IF);
-
- err = wl_cfgp2p_bssiovar_set(ndev, "event_msgs", 0,
- eventmask, WL_EVENTING_MASK_LEN);
- if (unlikely(err)) {
- WL_ERR(("Get event_msgs error (%d)\n", err));
- }
- return err;
-}
+ set_mode_by_netdev(wl, ndev, mode);
-
-static s32 wl_dongle_restore_eventmsg(struct wl_priv *wl)
-{
- s32 err = 0;
- struct net_device *ndev = wl_to_prmry_ndev(wl);
- err = wl_cfgp2p_bssiovar_set(ndev, "event_msgs", 0,
- wl->last_eventmask, WL_EVENTING_MASK_LEN);
- if (unlikely(err)) {
- WL_ERR(("Get event_msgs error (%d)\n", err));
- }
-
- return err;
+ return 0;
}
-#endif /* NOT_YET */
static s32 wl_dongle_eventmsg(struct net_device *ndev)
{
@@ -4964,7 +5059,7 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev)
/* Setup event_msgs */
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
sizeof(iovbuf));
- err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (unlikely(err)) {
WL_ERR(("Get event_msgs error (%d)\n", err));
goto dongle_eventmsg_out;
@@ -4977,6 +5072,7 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev)
setbit(eventmask, WLC_E_REASSOC);
setbit(eventmask, WLC_E_REASSOC_IND);
setbit(eventmask, WLC_E_DEAUTH_IND);
+ setbit(eventmask, WLC_E_DEAUTH);
setbit(eventmask, WLC_E_DISASSOC_IND);
setbit(eventmask, WLC_E_DISASSOC);
setbit(eventmask, WLC_E_JOIN);
@@ -4991,12 +5087,13 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev)
setbit(eventmask, WLC_E_SCAN_COMPLETE);
setbit(eventmask, WLC_E_ACTION_FRAME_RX);
setbit(eventmask, WLC_E_ACTION_FRAME_COMPLETE);
+ setbit(eventmask, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE);
setbit(eventmask, WLC_E_P2P_PROBREQ_MSG);
setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE);
setbit(eventmask, WLC_E_ESCAN_RESULT);
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
sizeof(iovbuf));
- err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (unlikely(err)) {
WL_ERR(("Set event_msgs error (%d)\n", err));
goto dongle_eventmsg_out;
@@ -5019,7 +5116,7 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up)
{
s32 err = 0;
- err = wl_dev_ioctl(ndev, WLC_UP, &up, sizeof(up));
+ err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), FALSE);
if (unlikely(err)) {
WL_ERR(("WLC_UP error (%d)\n", err));
}
@@ -5031,7 +5128,7 @@ static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode)
s32 err = 0;
WL_TRACE(("In\n"));
- err = wl_dev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode));
+ err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), FALSE);
if (unlikely(err)) {
WL_ERR(("WLC_SET_PM error (%d)\n", err));
}
@@ -5048,14 +5145,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 = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
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 = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (unlikely(err)) {
WL_ERR(("txglom error (%d)\n", err));
goto dongle_glom_out;
@@ -5075,7 +5172,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 = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (unlikely(err)) {
WL_ERR(("bcn_timeout error (%d)\n", err));
goto dongle_rom_out;
@@ -5083,7 +5180,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 = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (unlikely(err)) {
WL_ERR(("roam_off error (%d)\n", err));
goto dongle_rom_out;
@@ -5098,8 +5195,8 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
{
s32 err = 0;
- err = wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
- sizeof(scan_assoc_time));
+ err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
+ sizeof(scan_assoc_time), FALSE);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("Scan assoc time is not supported\n"));
@@ -5108,8 +5205,8 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
}
goto dongle_scantime_out;
}
- err = wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
- sizeof(scan_unassoc_time));
+ err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
+ sizeof(scan_unassoc_time), FALSE);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("Scan unassoc time is not supported\n"));
@@ -5133,7 +5230,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 = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO(("arpoe is not supported\n"));
@@ -5143,7 +5240,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 = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO(("arp_ol is not supported\n"));
@@ -5242,7 +5339,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 = wl_dev_ioctl(ndev, WLC_SET_VAR, buf, buf_len);
+ err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, FALSE);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("filter not supported\n"));
@@ -5255,7 +5352,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 = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("filter_mode not supported\n"));
@@ -5315,8 +5412,7 @@ s32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
wl_dongle_filter(ndev, 1);
#endif /* !EMBEDDED_PLATFORM */
- /* TODO: Check if this is ever needed */
- err = wl_dongle_mode(ndev, wdev->iftype);
+ err = wl_dongle_mode(wl, ndev, wdev->iftype);
if (unlikely(err && err != -EINPROGRESS))
goto default_conf_out;
err = wl_dongle_probecap(wl);
@@ -5342,8 +5438,8 @@ static s32 wl_update_wiphybands(struct wl_priv *wl)
s8 phy;
s32 err = 0;
- err = wl_dev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, &phy_list,
- sizeof(phy_list));
+ err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, &phy_list,
+ sizeof(phy_list), FALSE);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
return err;
@@ -5402,6 +5498,8 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
clear_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl_cfgp2p_down(wl);
+
wl_debugfs_remove_netdev(wl);
return err;
@@ -5515,9 +5613,9 @@ void wl_cfg80211_dbg_level(u32 level)
/* wl_dbg_level = level; */
}
-static bool wl_is_ibssmode(struct wl_priv *wl)
+static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
{
- return wl->conf->mode == WL_MODE_IBSS;
+ return get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
}
static __used bool wl_is_ibssstarter(struct wl_priv *wl)
@@ -5594,6 +5692,7 @@ static void wl_link_down(struct wl_priv *wl)
{
struct wl_connect_info *conn_info = wl_to_conn(wl);
+ WL_DBG(("In\n"));
wl->link_up = false;
kfree(conn_info->req_ie);
conn_info->req_ie = NULL;
@@ -5731,8 +5830,19 @@ s8 *wl_cfg80211_get_nvramname(void)
return wl->fw->nvram_name;
}
-static void wl_set_mpc(struct net_device *ndev, int mpc)
+static void wl_set_mpc(struct net_device *ndev, s32 mpc)
{
+
+ s32 err = 0;
+
+ WL_TRACE(("In\n"));
+ err = wl_dev_intvar_set(ndev, "mpc", mpc);
+ if (unlikely(err)) {
+ WL_ERR(("fail to set mpc\n"));
+ return;
+ }
+ WL_DBG(("MPC : %d\n", mpc));
+
}
static int wl_debugfs_add_netdev_params(struct wl_priv *wl)
@@ -5798,7 +5908,7 @@ static __used void wl_dongle_poweroff(struct wl_priv *wl)
}
static const struct rfkill_ops wl_rfkill_ops = {
- .set_block = wl_rfkill_set,
+ .set_block = wl_rfkill_set
};
static int wl_rfkill_set(void *data, bool blocked)
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index bb2f0e40729c..4ec91e84de8f 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -110,13 +110,14 @@ do { \
* as kernel memory allows
*/
#define WL_FILE_NAME_MAX 256
+#define WL_DWELL_TIME 200
/* WiFi Direct */
#define WL_P2P_WILDCARD_SSID "DIRECT-"
#define WL_P2P_WILDCARD_SSID_LEN 7
#define WL_P2P_INTERFACE_PREFIX "p2p"
#define WL_P2P_TEMP_CHAN "11"
-
+#define VWDEV_CNT 3
/* dongle status */
enum wl_status {
WL_STATUS_READY = 0,
@@ -169,16 +170,12 @@ enum wl_cfgp2p_status {
WLP2P_STATUS_SEARCH_ENABLED,
WLP2P_STATUS_IF_ADD,
WLP2P_STATUS_IF_DEL,
+ WLP2P_STATUS_IF_DELETING,
WLP2P_STATUS_IF_CHANGING,
WLP2P_STATUS_IF_CHANGED,
WLP2P_STATUS_LISTEN_EXPIRED,
WLP2P_STATUS_ACTION_TX_COMPLETED,
- WLP2P_STATUS_GROUP_OWNER,
- WLP2P_STATUS_GROUP_CLIENT,
- WLP2P_STATUS_SCANNING,
- WLP2P_STATUS_SCAN_ABORTING,
- WLP2P_STATUS_CONNECTING,
- WLP2P_STATUS_CONNECTED
+ WLP2P_STATUS_SCANNING
};
/* beacon / probe_response */
struct beacon_proberesp {
@@ -190,7 +187,10 @@ struct beacon_proberesp {
/* dongle configuration */
struct wl_conf {
- u32 mode; /* adhoc , infrastructure or ap */
+ struct net_mode {
+ struct net_device *ndev;
+ s32 type;
+ } mode [VWDEV_CNT + 1]; /* adhoc , infrastructure or ap */
u32 frag_threshold;
u32 rts_threshold;
u32 retry_short;
@@ -354,7 +354,7 @@ struct escan_info {
u8 escan_buf[ESCAN_BUF_SIZE];
struct wiphy *wiphy;
};
-#define VWDEV_CNT 3
+
/* dongle private data of cfg80211 interface */
struct wl_priv {
struct wireless_dev *wdev; /* representing wl cfg80211 device */
@@ -457,9 +457,9 @@ static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct
return bss = bss ?
(struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info;
}
-static inline int alloc_idx_vwdev(struct wl_priv *wl)
+static inline s32 alloc_idx_vwdev(struct wl_priv *wl)
{
- int i = 0;
+ s32 i = 0;
for (i = 0; i < VWDEV_CNT; i++) {
if (wl->vwdev[i] == NULL)
return i;
@@ -467,9 +467,9 @@ static inline int alloc_idx_vwdev(struct wl_priv *wl)
return -1;
}
-static inline int get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device *ndev)
+static inline s32 get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device *ndev)
{
- int i = 0;
+ s32 i = 0;
for (i = 0; i < VWDEV_CNT; i++) {
if ((wl->vwdev[i] != NULL) && (wl->vwdev[i]->netdev == ndev))
return i;
@@ -477,6 +477,43 @@ static inline int get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device
return -1;
}
+static inline s32 get_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev)
+{
+ s32 i = 0;
+ for (i = 0; i <= VWDEV_CNT; i++) {
+ if (wl->conf->mode[i].ndev != NULL && (wl->conf->mode[i].ndev == ndev))
+ return wl->conf->mode[i].type;
+ }
+ return -1;
+}
+static inline void set_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev, s32 type)
+{
+ s32 i = 0;
+ for (i = 0; i <= VWDEV_CNT; i++) {
+ if (type == -1) {
+ /* free the info of netdev */
+ if (wl->conf->mode[i].ndev == ndev) {
+ wl->conf->mode[i].ndev = NULL;
+ wl->conf->mode[i].type = -1;
+ break;
+ }
+
+ } else {
+ if ((wl->conf->mode[i].ndev != NULL)&&
+ (wl->conf->mode[i].ndev == ndev)) {
+ /* update type of ndev */
+ wl->conf->mode[i].type = type;
+ break;
+ }
+ else if ((wl->conf->mode[i].ndev == NULL)&&
+ (wl->conf->mode[i].type == -1)) {
+ wl->conf->mode[i].ndev = ndev;
+ wl->conf->mode[i].type = type;
+ break;
+ }
+ }
+ }
+}
#define free_vwdev_by_index(wl, __i) do { \
if (wl->vwdev[__i] != NULL) \
kfree(wl->vwdev[__i]); \
@@ -494,16 +531,20 @@ static inline int get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device
(!_sme->crypto.n_ciphers_pairwise) && \
(!_sme->crypto.cipher_group))
extern s32 wl_cfg80211_attach(struct net_device *ndev, void *data);
+extern s32 wl_cfg80211_attach_post(struct net_device *ndev);
extern void wl_cfg80211_detach(void);
/* event handler from dongle */
-extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data);
+extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e,
+ void *data, gfp_t gfp);
extern void wl_cfg80211_set_sdio_func(void *func); /* set sdio function info */
extern struct sdio_func *wl_cfg80211_get_sdio_func(void); /* set sdio function info */
extern s32 wl_cfg80211_up(void); /* dongle up */
extern s32 wl_cfg80211_down(void); /* dongle down */
extern s32 wl_cfg80211_notify_ifadd(struct net_device *net);
extern s32 wl_cfg80211_notify_ifdel(struct net_device *net);
+extern s32 wl_cfg80211_is_progress_ifadd(void);
extern s32 wl_cfg80211_is_progress_ifchange(void);
+extern s32 wl_cfg80211_is_progress_ifadd(void);
extern s32 wl_cfg80211_notify_ifchange(void);
extern void wl_cfg80211_dbg_level(u32 level);
extern void *wl_cfg80211_request_fw(s8 *file_name);
@@ -511,6 +552,9 @@ extern s32 wl_cfg80211_read_fw(s8 *buf, u32 size);
extern void wl_cfg80211_release_fw(void);
extern s8 *wl_cfg80211_get_fwname(void);
extern s8 *wl_cfg80211_get_nvramname(void);
+#ifdef CONFIG_SYSCTL
+extern s32 wl_cfg80211_sysctl_export_devaddr(void *data);
+#endif
/* do scan abort */
extern s32
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index a87631ccd21d..730a25f45342 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -21,6 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
+ * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
* $Id$
*/
@@ -47,6 +48,7 @@
#include <wl_cfg80211.h>
#include <wl_cfgp2p.h>
+#include <wldev_common.h>
/* dword align allocation */
@@ -96,350 +98,12 @@ static s8 ioctlbuf[WLC_IOCTL_MAXLEN];
static s8 scanparambuf[WLC_IOCTL_SMLEN];
static s8 *smbuf = ioctlbuf;
+static bool
+wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
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);
-static s32
-wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
-{
- struct ifreq ifr;
- struct wl_ioctl ioc;
- mm_segment_t fs;
- s32 err = 0;
-
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = cmd;
- ioc.buf = arg;
- ioc.len = len;
- ioc.set = set;
- strcpy(ifr.ifr_name, dev->name);
- ifr.ifr_data = (caddr_t)&ioc;
- fs = get_fs();
- set_fs(get_ds());
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
- err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#else
- err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
- set_fs(fs);
-
- return err;
-}
-
-/*
- * Format an iovar buffer.
- * iovar name is converted to lower case
- */
-static s32
-wl_cfgp2p_iovar_mkbuf(const s8 *name, s8 *data, u32 datalen,
- s8 *iovar_buf, u32 buflen, u32 *perr)
-{
- u32 iovar_len;
- iovar_len = (u32) strlen(name) + 1;
-
- if ((iovar_len + datalen) > buflen) {
-
- CFGP2P_ERR(("buf too short, %u < %u\n", buflen, (iovar_len + datalen)));
- *perr = BCME_BUFTOOSHORT;
- return 0;
- }
-
- /* copy data to the buffer past the end of the iovar name string */
- if (datalen > 0) {
- memmove(&iovar_buf[iovar_len], data, datalen);
- }
-
- /* copy the name to the beginning of the buffer */
- strcpy(iovar_buf, name);
-
-
- *perr = 0;
- return (iovar_len + datalen);
-}
-
-/*
- * Format a bsscfg indexed iovar buffer.
- * This is a common implementation called by most OSL implementations of
- * p2posl_bssiovar_mkbuf(). DO NOT call this function directly from the
- * common code -- call p2posl_bssiovar_mkbuf() instead to allow the OSL to
- * override the common implementation if necessary.
- */
-static s32
-wl_cfgp2p_bssiovar_mkbuf(const s8 *iovar, s32 bssidx,
- void *param, s32 paramlen, void *bufptr, s32 buflen, s32 *perr)
-{
- const s8 *prefix = "bsscfg:";
- s8 *p;
- u32 prefixlen;
- u32 namelen;
- u32 iolen;
-
- if (bssidx == 0) {
- return wl_cfgp2p_iovar_mkbuf(iovar, (s8 *)param, paramlen,
- (s8 *) bufptr, buflen, perr);
- }
-
- prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
- namelen = (u32) strlen(iovar) + 1; /* lengh of iovar name + null */
- iolen = prefixlen + namelen + sizeof(u32) + paramlen;
-
- if (buflen < 0 || iolen > (u32)buflen) {
- CFGP2P_ERR(("buf too short, %u < %u\n", buflen, iolen));
- *perr = BCME_BUFTOOSHORT;
- return 0;
- }
- p = (s8 *)bufptr;
-
- /* copy prefix, no null */
- memcpy(p, prefix, prefixlen);
- p += prefixlen;
-
- /* copy iovar name including null */
- memcpy(p, iovar, namelen);
- p += namelen;
-
- /* bss config index as first param */
- bssidx = htod32(bssidx);
- memcpy(p, &bssidx, sizeof(u32));
- p += sizeof(u32);
-
- /* parameter buffer follows */
- if (paramlen)
- memcpy(p, param, paramlen);
-
- *perr = 0;
-
- return iolen;
-
-}
-
-/*
- * Set a bss-indexed iovar on the primary ioctl interface, providing both
- * parameter and i/o buffers.
- */
-
-static s32
-wl_cfgp2p_bssiovar_setbuf(struct net_device *dev, const s8 *iovar, s32 bssidx,
- void *param, s32 paramlen, void *bufptr, s32 buflen)
-{
- s32 iolen;
- s32 err;
- iolen = wl_cfgp2p_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr,
- buflen, &err);
-
- if (err)
- return err;
-
- return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen, TRUE);
-}
-/*
- * Get a named & bss indexed driver iovar using the primary ioctl interface.
- */
-static s32
-wl_cfgp2p_bssiovar_getbuf(struct net_device *dev, const s8 *iovar, int bssidx,
- void *param, s32 paramlen, void *bufptr, s32 buflen)
-{
- s32 err;
- s32 iolen;
- iolen = wl_cfgp2p_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &err);
-
- if (unlikely(err))
- return err;
-
- return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, iolen, FALSE);
-}
-
-
-/*
- * Get named & bss indexed driver variable to buffer value
- * using the primary ioctl interface.
- */
-s32
-wl_cfgp2p_bssiovar_get(struct net_device *dev, const s8 *iovar, s32 bssidx,
- void *outbuf, s32 len)
-{
- s32 err;
-
- if (len > (s32)sizeof(ioctlbuf)) {
- err = wl_cfgp2p_bssiovar_getbuf(dev, iovar, bssidx, NULL, 0,
- outbuf, len);
- } else {
- memset(smbuf, 0, sizeof(ioctlbuf));
-
- err = wl_cfgp2p_bssiovar_getbuf(dev, iovar, bssidx, NULL, 0,
- smbuf, sizeof(ioctlbuf));
-
- if (err == 0)
- memcpy(outbuf, smbuf, len);
- }
- return err;
-}
-/*
- * Set named & bss indexed driver variable to buffer value
- * on the primary ioctl interface.
- */
-s32
-wl_cfgp2p_bssiovar_set(struct net_device *dev, const s8 *iovar, s32 bssidx,
- void *param, s32 paramlen)
-{
-
- memset(smbuf, 0, sizeof(ioctlbuf));
-
- return wl_cfgp2p_bssiovar_setbuf(dev, iovar, bssidx, param, paramlen, smbuf,
- sizeof(ioctlbuf));
-}
-
-
-/*
- * Set named & bsscfg indexed driver variable to int value
- * on the primary ioctl interface.
- */
-
-s32
-wl_cfgp2p_bssiovar_setint(struct net_device *dev, const s8 *iovar, s32 bssidx,
- s32 val)
-{
-
- val = htod32(val);
-
- return wl_cfgp2p_bssiovar_set(dev, iovar, bssidx, &val, sizeof(int));
-}
-
-
-s32
-wl_cfgp2p_set_int_bss(struct net_device *dev, s32 ioctl_cmd, s32 val, s32 bssidx)
-{
- s32 setval = htod32(val);
- return wl_dev_ioctl(dev, WLC_SET_VAR, &setval, sizeof(setval), TRUE);
-}
-
-
-s32
-wl_cfgp2p_get_int_bss(struct net_device *dev, s32 ioctl_cmd, s32 *val, s32 bssidx)
-{
- s32 ret;
- ret = wl_dev_ioctl(dev, WLC_GET_VAR, val, sizeof(*val), FALSE);
- if (ret >= 0) {
- val = dtoh32(val);
- }
- return ret;
-}
-
-s32
-wl_cfgp2p_iovar_getbuf_bss(struct net_device *dev, const s8 *iovar, void *param,
- s32 paramlen, void *bufptr, s32 buflen, s32 bssidx)
-{
- s32 err;
-
- wl_cfgp2p_iovar_mkbuf(iovar, (s8 *)param, paramlen, (s8 *) bufptr, buflen,
- &err);
-
- if (unlikely(err)) {
- CFGP2P_ERR((" mkbuf err %d\n", err));
- }
-
- return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen, FALSE);
-}
-/*
- * Set a named iovar on a specified BSS, providing both parameter and i/o
- * buffers. The iovar name is converted to lower case.
- */
-s32
-wl_cfgp2p_iovar_setbuf_bss(struct net_device *dev, const s8 *iovar,
- void *param, s32 paramlen, void *bufptr, s32 buflen)
-{
- s32 err = BCME_OK;
- s32 iolen;
- CFGP2P_DBG((" enter\n"));
-
- iolen = wl_cfgp2p_iovar_mkbuf(iovar, (char *) param, paramlen, (s8 *)bufptr,
- buflen, &err);
-
- if (unlikely(err)) {
- CFGP2P_ERR(("iovar = %s\n", iovar));
- return err;
- }
- err = wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen, TRUE);
- CFGP2P_DBG((" leave\n"));
- return err;
-}
-
-/*
- * Set a named iovar given the parameter buffer, on a specified BSS.
- * The iovar name is converted to lower case.
- */
-s32
-wl_cfgp2p_iovar_set_bss(struct net_device *dev, const s8 *iovar, void *param,
- s32 paramlen)
-{
-
- s32 ret;
- memset(smbuf, 0, sizeof(ioctlbuf));
- CFGP2P_DBG((" enter\n"));
- ret = wl_cfgp2p_iovar_setbuf_bss(dev, iovar, param, paramlen, smbuf,
- sizeof(ioctlbuf));
-
- if (unlikely(ret != 0)) {
- CFGP2P_ERR(("set iovar %s failed (%d)\n",
- iovar, ret));
- }
- CFGP2P_DBG((" leave\n"));
- return ret;
-}
-/*
- * Get a parameterless iovar into a given buffer.
- * iovar name is converted to lower case
- */
-s32
-wl_cfgp2p_iovar_get_bss(struct net_device *dev, const s8 *iovar, void *outbuf, s32 len,
- s32 bssidx)
-{
- s32 err;
-
- /* use the return buffer if it is bigger than what we have on the stack */
- if (len > (s32)sizeof(ioctlbuf)) {
- err = wl_cfgp2p_iovar_getbuf_bss(dev, iovar, NULL, 0, outbuf, len, bssidx);
- } else {
- memset(smbuf, 0, sizeof(ioctlbuf));
- err = wl_cfgp2p_iovar_getbuf_bss(dev, iovar, NULL, 0, smbuf, sizeof(ioctlbuf),
- bssidx);
- if (err == 0)
- memcpy(outbuf, smbuf, len);
- }
-
- return err;
-}
-
-/*
- * Set named iovar given an integer parameter, on the specified BSS.
- * iovar name is converted to lower case
- */
-s32
-wl_cfgp2p_iovar_setint_bss(struct net_device *dev, const s8 *iovar, s32 val)
-{
- CFGP2P_DBG((" enter\n"));
- val = htod32(val);
- return wl_cfgp2p_iovar_set_bss(dev, iovar, &val, sizeof(int));
-}
-
-/*
- * Get the named integer iovar on the specified BSS.
- * iovar name is converted to lower case
- */
-s32
-wl_cfgp2p_iovar_getint_bss(struct net_device *dev, const s8*iovar, s32 *pval, s32 bssidx)
-{
- s32 ret;
-
- ret = wl_cfgp2p_iovar_get_bss(dev, iovar, pval, sizeof(s32), bssidx);
- if (ret >= 0)
- {
- *pval = dtoh32(*pval);
- }
- return ret;
-}
-
/*
* Initialize variables related to P2P
*
@@ -521,7 +185,8 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
(if_type == WL_P2P_IF_GO) ? "go" : "client",
(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
- err = wl_cfgp2p_iovar_set_bss(netdev, "p2p_ifadd", &ifreq, sizeof(ifreq));
+ err = wldev_iovar_setbuf(netdev, "p2p_ifadd", &ifreq, sizeof(ifreq),
+ ioctlbuf, sizeof(ioctlbuf));
return err;
}
@@ -540,7 +205,8 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac)
mac->octet[0], mac->octet[1], mac->octet[2],
mac->octet[3], mac->octet[4], mac->octet[5]));
- ret = wl_cfgp2p_iovar_set_bss(netdev, "p2p_ifdel", mac, sizeof(*mac));
+ ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
+ ioctlbuf, sizeof(ioctlbuf));
if (unlikely(ret < 0)) {
printk("'wl p2p_ifdel' error %d\n", ret);
@@ -571,7 +237,8 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
(if_type == WL_P2P_IF_GO) ? "go" : "client",
(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
- err = wl_cfgp2p_iovar_set_bss(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq));
+ err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
+ ioctlbuf, sizeof(ioctlbuf));
if (unlikely(err < 0)) {
printk("'wl p2p_ifupd' error %d\n", err);
@@ -597,7 +264,7 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index)
mac->octet[0], mac->octet[1], mac->octet[2],
mac->octet[3], mac->octet[4], mac->octet[5]));
- ret = wl_cfgp2p_iovar_getbuf_bss(dev, "p2p_if", mac, sizeof(*mac),
+ ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac),
getbuf, sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY));
if (ret == 0) {
@@ -615,7 +282,7 @@ wl_cfgp2p_set_discovery(struct wl_priv *wl, s32 on)
struct net_device *ndev = wl_to_prmry_ndev(wl);
CFGP2P_DBG(("enter\n"));
- ret = wl_cfgp2p_iovar_setint_bss(ndev, "p2p_disc", on);
+ ret = wldev_iovar_setint(ndev, "p2p_disc", on);
if (unlikely(ret < 0)) {
CFGP2P_ERR(("p2p_disc %d error %d\n", on, ret));
@@ -656,8 +323,8 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms,
discovery_mode.state = mode;
discovery_mode.chspec = CH20MHZ_CHSPEC(channel);
discovery_mode.dwell = listen_ms;
- ret = wl_cfgp2p_bssiovar_set(dev, "p2p_state", bssidx, &discovery_mode,
- sizeof(discovery_mode));
+ ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
+ sizeof(discovery_mode), ioctlbuf, sizeof(ioctlbuf), bssidx);
return ret;
}
@@ -669,7 +336,7 @@ wl_cfgp2p_get_disc_idx(struct wl_priv *wl, s32 *index)
s32 ret;
struct net_device *dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
- ret = wl_cfgp2p_iovar_getint_bss(dev, "p2p_dev", index, 0);
+ ret = wldev_iovar_getint(dev, "p2p_dev", index);
CFGP2P_INFO(("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret));
if (unlikely(ret < 0)) {
@@ -765,7 +432,7 @@ wl_cfgp2p_deinit_discovery(struct wl_priv *wl)
* Returns 0 if success.
*/
s32
-wl_cfgp2p_enable_discovery(struct wl_priv *wl, const u8 *ie, u32 ie_len)
+wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 *ie, u32 ie_len)
{
s32 ret = BCME_OK;
if (test_bit(WLP2P_STATUS_DISCOVERY_ON, &wl->p2p_status)) {
@@ -786,13 +453,13 @@ wl_cfgp2p_enable_discovery(struct wl_priv *wl, const u8 *ie, u32 ie_len)
* P2P probe responses have the privacy bit set in the 802.11 WPA IE.
* Some peer devices may not initiate WPS with us if this bit is not set.
*/
- ret = wl_cfgp2p_bssiovar_setint(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
- "wsec", wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), AES_ENABLED);
+ ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
+ "wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
if (unlikely(ret < 0)) {
CFGP2P_ERR((" wsec error %d\n", ret));
}
set_ie:
- ret = wl_cfgp2p_set_managment_ie(wl, wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
+ ret = wl_cfgp2p_set_managment_ie(wl, dev,
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE),
VNDR_IE_PRBREQ_FLAG, ie, ie_len);
@@ -844,7 +511,8 @@ exit:
}
s32
-wl_cfgp2p_escan(struct wl_priv *wl, u16 active, u32 num_chans, u16 *channels,
+wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
+ u32 num_chans, u16 *channels,
s32 search_state, u16 action, u32 bssidx)
{
s32 ret = BCME_OK;
@@ -933,10 +601,19 @@ wl_cfgp2p_escan(struct wl_priv *wl, u16 active, u32 num_chans, u16 *channels,
CFGP2P_INFO(("\n"));
- ret = wl_cfgp2p_bssiovar_setbuf(wl_to_p2p_bss_ndev(wl, bssidx), "p2p_scan", bssidx,
- memblk, memsize, smbuf, sizeof(ioctlbuf));
+ ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_scan",
+ memblk, memsize, smbuf, sizeof(ioctlbuf), bssidx);
return ret;
}
+/* Check whether pointed-to IE looks like WPA. */
+#define wl_cfgp2p_is_wpa_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
+/* Check whether pointed-to IE looks like WPS. */
+#define wl_cfgp2p_is_wps_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
+/* Check whether the given IE looks like WFA P2P IE. */
+#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
+ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
/* Delete and Set a management ie to firmware
* Parameters:
* @wl : wl_private data
@@ -965,7 +642,8 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
u8 delete = 0;
#define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie)
#define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len)
-
+ if (bssidx == -1)
+ return BCME_BADARG;
if (bssidx == P2PAPI_BSSCFG_PRIMARY)
bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
switch (pktflag) {
@@ -1019,9 +697,9 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
while (pos < *mgmt_ie_len) {
ie_id = ie_buf[pos++];
ie_len = ie_buf[pos++];
- CFGP2P_INFO(("DELELED ID(%d), Len(%d),\
- OUI(%02x:%02x:%02x)\n",\
- ie_id, ie_len, ie_buf[pos],\
+ CFGP2P_INFO(("DELELED ID(%d), Len(%d),"
+ "OUI(%02x:%02x:%02x)\n",
+ ie_id, ie_len, ie_buf[pos],
ie_buf[pos+1], ie_buf[pos+2]));
ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag,
ie_buf+pos, VNDR_SPEC_ELEMENT_ID,
@@ -1039,10 +717,15 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
while (pos < p2p_ie_len) {
ie_id = ie_buf[pos++];
ie_len = ie_buf[pos++];
- CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI : %02x:%02x:%02x\n",
- ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2]));
- ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag, ie_buf+pos,
- VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete);
+ if ((ie_id == DOT11_MNG_VS_ID) &&
+ (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
+ wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+ CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :"
+ "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
+ ie_buf[pos+1], ie_buf[pos+2]));
+ ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag, ie_buf+pos,
+ VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete);
+ }
pos += ie_len;
}
}
@@ -1083,15 +766,7 @@ wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx)
return BCME_OK;
}
-/* Check whether pointed-to IE looks like WPA. */
-#define wl_cfgp2p_is_wpa_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
- (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
-/* Check whether pointed-to IE looks like WPS. */
-#define wl_cfgp2p_is_wps_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
- (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
-/* Check whether the given IE looks like WFA P2P IE. */
-#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
- (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
+
/* Is any of the tlvs the expected entry? If
* not update the tlvs buffer pointer/length.
@@ -1106,6 +781,8 @@ wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u
return TRUE;
}
+ if (tlvs == NULL)
+ return FALSE;
/* point to the next ie */
ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
/* calculate the length of the rest of the buffer */
@@ -1196,7 +873,9 @@ wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag,
= (uchar)(data_len + VNDR_IE_MIN_LEN);
memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, oui, 3);
memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data, data, data_len);
- err = wl_cfgp2p_bssiovar_set(ndev, "vndr_ie", bssidx, ie_setbuf, buf_len);
+ err = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", ie_setbuf, buf_len,
+ ioctlbuf, sizeof(ioctlbuf), bssidx);
+
CFGP2P_INFO(("vndr_ie iovar returns %d\n", err));
kfree(ie_setbuf);
return err;
@@ -1255,24 +934,18 @@ 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,
+ * so lets do it from thread context.
*/
static void
wl_cfgp2p_listen_expired(unsigned long data)
{
+ wl_event_msg_t msg;
struct wl_priv *wl = (struct wl_priv *) data;
CFGP2P_DBG((" Enter\n"));
-
- if (test_bit(WLP2P_STATUS_LISTEN_EXPIRED, &wl->p2p_status) == 0) {
- CFGP2P_ERR((" WLC_E_P2P_DISC_LISTEN_COMPLETE does not occur\n"));
- set_bit(WLP2P_STATUS_LISTEN_EXPIRED, &wl->p2p_status);
-
- cfg80211_remain_on_channel_expired(
- wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
- wl->cache_cookie, &wl->remain_on_chan,
- wl->remain_on_chan_type, GFP_KERNEL);
- }
-
+ msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
+ wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL, GFP_ATOMIC);
}
/*
@@ -1300,6 +973,7 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
s32 ret = BCME_OK;
CFGP2P_DBG((" Enter\n"));
+ CFGP2P_INFO(("Channel : %d, Duration : %d\n", channel, duration_ms));
if (unlikely(test_bit(WLP2P_STATUS_DISCOVERY_ON, &wl->p2p_status) == 0)) {
CFGP2P_ERR((" Discovery is not set, so we have noting to do\n"));
@@ -1371,19 +1045,21 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
{
s32 ret = BCME_OK;
u32 event_type = ntoh32(e->event_type);
-
+ u32 status = ntoh32(e->status);
CFGP2P_DBG((" Enter\n"));
if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
- CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received\n"));
+ CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
+ if (status == WLC_E_STATUS_SUCCESS)
+ set_bit(WLP2P_STATUS_ACTION_TX_COMPLETED, &wl->p2p_status);
+ else
+ CFGP2P_ERR(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
+ wake_up_interruptible(&wl->dongle_event_wait);
+ } else {
+ CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
+ "status : %d\n", status));
- }else {
- CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received\n"));
}
- set_bit(WLP2P_STATUS_ACTION_TX_COMPLETED, &wl->p2p_status);
-
- wake_up_interruptible(&wl->dongle_event_wait);
-
return ret;
}
@@ -1396,7 +1072,8 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
* 802.11 ack has been received for the sent action frame.
*/
s32
-wl_cfgp2p_tx_action_frame(struct wl_priv *wl, wl_af_params_t *af_params, s32 bssidx)
+wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
+ wl_af_params_t *af_params, s32 bssidx)
{
s32 ret = BCME_OK;
s32 timeout = 0;
@@ -1411,8 +1088,9 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, wl_af_params_t *af_params, s32 bss
if (bssidx == P2PAPI_BSSCFG_PRIMARY)
bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
- ret = wl_cfgp2p_bssiovar_setbuf(wl_to_p2p_bss_ndev(wl, bssidx), "actframe",
- bssidx, af_params, sizeof(*af_params), ioctlbuf, sizeof(ioctlbuf));
+ ret = wldev_iovar_setbuf_bsscfg(dev, "actframe",
+ af_params, sizeof(*af_params), ioctlbuf, sizeof(ioctlbuf), bssidx);
+
if (ret < 0) {
CFGP2P_ERR((" sending action frame is failed\n"));
@@ -1499,9 +1177,11 @@ wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_i
CFGP2P_INFO(("Device ID ATTR FOUND\n"));
} else if (subelt_id == P2P_SEID_DEV_INFO) {
memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
- CFGP2P_INFO(("Device ID ATTR FOUND\n"));
- }
- return;
+ CFGP2P_INFO(("Device INFO ATTR FOUND\n"));
+ } else if (subelt_id == P2P_SEID_GROUP_ID) {
+ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
+ CFGP2P_INFO(("GROUP ID ATTR FOUND\n"));
+ } return;
} else {
CFGP2P_DBG(("OTHER id : %d\n", subelt_id));
}
@@ -1524,7 +1204,7 @@ wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
/* Check if the BSS is up */
*(int*)getbuf = -1;
- result = wl_cfgp2p_iovar_getbuf_bss(ndev, "bss", &bsscfg_idx,
+ result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0);
if (result != 0) {
CFGP2P_ERR(("'wl bss -C %d' failed: %d\n", bsscfg_idx, result));
@@ -1555,7 +1235,8 @@ wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up)
bss_setbuf.cfg = htod32(bsscfg_idx);
bss_setbuf.val = htod32(val);
CFGP2P_INFO(("---wl bss -C %d %s\n", bsscfg_idx, up ? "up" : "down"));
- ret = wl_cfgp2p_iovar_set_bss(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf));
+ ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+ ioctlbuf, sizeof(ioctlbuf));
if (ret != 0) {
CFGP2P_ERR(("'bss %d' failed with %d\n", up, ret));
@@ -1566,12 +1247,12 @@ wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up)
/* Check if 'p2p' is supported in the driver */
s32
-wl_cfgp2p_is_p2p_supported(struct wl_priv *wl)
+wl_cfgp2p_is_p2p_supported(struct wl_priv *wl, struct net_device *ndev)
{
s32 ret = BCME_OK;
s32 is_p2p_supported = 0;
- ret = wl_cfgp2p_iovar_getint_bss(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY), "p2p",
- &is_p2p_supported, wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY));
+ ret = wldev_iovar_getint(ndev, "p2p",
+ &is_p2p_supported);
if (ret < 0) {
CFGP2P_ERR(("wl p2p error %d\n", ret));
return 0;
@@ -1581,3 +1262,11 @@ wl_cfgp2p_is_p2p_supported(struct wl_priv *wl)
return is_p2p_supported;
}
+
+s32
+wl_cfgp2p_down(struct wl_priv *wl)
+{
+ if (wl->listen_timer)
+ del_timer_sync(wl->listen_timer);
+ return 0;
+}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index b208f255f90d..9fb2c9e53ab3 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -23,7 +23,6 @@
*
* $Id: wl_cfg80211.h,v 1.1.4.1.2.8 2011/02/09 01:37:52 Exp $
*/
-
#ifndef _wl_cfgp2p_h_
#define _wl_cfgp2p_h_
#include <proto/802.11.h>
@@ -50,12 +49,13 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index);
extern s32
wl_cfgp2p_init_discovery(struct wl_priv *wl);
extern s32
-wl_cfgp2p_enable_discovery(struct wl_priv *wl, const u8 *ie, u32 ie_len);
+wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 *ie, u32 ie_len);
extern s32
wl_cfgp2p_disable_discovery(struct wl_priv *wl);
extern s32
-wl_cfgp2p_escan(struct wl_priv *wl, u16 active, u32 num_chans, u16 *channels,
- s32 search_state, u16 action, u32 bssidx);
+wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, u32 num_chans,
+ u16 *channels,
+ s32 search_state, u16 action, u32 bssidx);
extern wpa_ie_fixed_t *
wl_cfgp2p_find_wpaie(u8 *parse, u32 len);
@@ -89,7 +89,8 @@ extern s32
wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
const wl_event_msg_t *e, void *data);
extern s32
-wl_cfgp2p_tx_action_frame(struct wl_priv *wl, wl_af_params_t *af_params, s32 bssidx);
+wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
+ wl_af_params_t *af_params, s32 bssidx);
extern void
wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr, struct ether_addr *out_dev_addr,
@@ -97,20 +98,6 @@ wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr, struct ether_addr *o
extern void
wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id);
-
-extern s32
-wl_cfgp2p_bssiovar_set(struct net_device *dev, const s8 *iovar, s32 bssidx,
- void *param, s32 paramlen);
-extern s32
-wl_cfgp2p_bssiovar_get(struct net_device *dev, const s8 *iovar, s32 bssidx,
- void *outbuf, s32 len);
-extern s32
-wl_cfgp2p_bssiovar_setint(struct net_device *dev, const s8 *iovar, s32 bssidx, s32 val);
-extern s32
-wl_cfgp2p_iovar_set_bss(struct net_device *dev, const s8 *iovar, void *param, s32 paramlen);
-extern s32
-wl_cfgp2p_iovar_get_bss(struct net_device *dev, const s8 *iovar, void *outbuf, s32 len, s32 bssidx);
-
extern bool
wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx);
@@ -119,7 +106,10 @@ wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up);
extern s32
-wl_cfgp2p_is_p2p_supported(struct wl_priv *wl);
+wl_cfgp2p_is_p2p_supported(struct wl_priv *wl, struct net_device *ndev);
+
+extern s32
+wl_cfgp2p_down(struct wl_priv *wl);
/* WiFi Direct */
#define SOCIAL_CHAN_1 1
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
new file mode 100644
index 000000000000..c81fccad6c2d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -0,0 +1,238 @@
+/*
+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers
+ *
+ * Copyright (C) 1999-2011, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
+ */
+
+#include <wlioctl.h>
+#include <bcmutils.h>
+
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+#define htodchanspec(i) i
+#define dtohchanspec(i) i
+
+s32 wldev_ioctl(
+ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
+{
+ s32 ret = 0;
+ struct ifreq ifr;
+ struct wl_ioctl ioc;
+ mm_segment_t fs;
+ s32 err = 0;
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+ ioc.set = set;
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t)&ioc;
+
+ fs = get_fs();
+ set_fs(get_ds());
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+ err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#else
+ err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
+ set_fs(fs);
+
+ return ret;
+}
+
+/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be
+ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
+ * wl_iw, wl_cfg80211 and wl_cfgp2p
+ */
+s32 wldev_mkiovar(
+ s8 *iovar_name, s8 *param, s32 paramlen,
+ s8 *iovar_buf, u32 buflen)
+{
+ s32 iolen = 0;
+
+ iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen);
+ return iolen;
+}
+
+s32 wldev_iovar_getbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen)
+{
+ s32 ret = 0;
+ 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);
+ return ret;
+}
+
+
+s32 wldev_iovar_setbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen)
+{
+ s32 ret = 0;
+ s32 iovar_len;
+
+ iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
+ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+ return ret;
+}
+
+s32 wldev_iovar_setint(
+ struct net_device *dev, s8 *iovar, s32 val)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+ val = htod32(val);
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf,
+ sizeof(iovar_buf));
+}
+
+
+s32 wldev_iovar_getint(
+ struct net_device *dev, s8 *iovar, s32 *pval)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ s32 err;
+
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf,
+ sizeof(iovar_buf));
+ if (err == 0)
+ {
+ memcpy(pval, iovar_buf, sizeof(*pval));
+ *pval = dtoh32(*pval);
+ }
+ return err;
+}
+
+/** Format a bsscfg indexed iovar buffer. The bsscfg index will be
+ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
+ * wl_iw, wl_cfg80211 and wl_cfgp2p
+ */
+s32 wldev_mkiovar_bsscfg(
+ const s8 *iovar_name, s8 *param, s32 paramlen,
+ s8 *iovar_buf, s32 buflen, s32 bssidx)
+{
+ const s8 *prefix = "bsscfg:";
+ s8 *p;
+ u32 prefixlen;
+ u32 namelen;
+ u32 iolen;
+
+ if (bssidx == 0) {
+ return wldev_mkiovar((s8*)iovar_name, (s8 *)param, paramlen,
+ (s8 *) iovar_buf, buflen);
+ }
+
+ prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
+ namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar name + null */
+ iolen = prefixlen + namelen + sizeof(u32) + paramlen;
+
+ if (buflen < 0 || iolen > (u32)buflen)
+ {
+ printk("wldev_mkiovar_bsscfg buffer is too short\n");
+ return BCME_BUFTOOSHORT;
+ }
+
+ p = (s8 *)iovar_buf;
+
+ /* copy prefix, no null */
+ memcpy(p, prefix, prefixlen);
+ p += prefixlen;
+
+ /* copy iovar name including null */
+ memcpy(p, iovar_name, namelen);
+ p += namelen;
+
+ /* bss config index as first param */
+ bssidx = htod32(bssidx);
+ memcpy(p, &bssidx, sizeof(u32));
+ p += sizeof(u32);
+
+ /* parameter buffer follows */
+ if (paramlen)
+ memcpy(p, param, paramlen);
+
+ return iolen;
+
+}
+
+s32 wldev_iovar_getbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx)
+{
+ s32 ret = 0;
+ 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);
+ return ret;
+
+}
+
+s32 wldev_iovar_setbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx)
+{
+ s32 ret = 0;
+ s32 iovar_len;
+
+ iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
+ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+ return ret;
+}
+
+s32 wldev_iovar_setint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+ val = htod32(val);
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf,
+ sizeof(iovar_buf), bssidx);
+}
+
+
+s32 wldev_iovar_getint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ s32 err;
+
+ memset(iovar_buf, 0, sizeof(iovar_buf));
+ err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf,
+ sizeof(iovar_buf), bssidx);
+ if (err == 0)
+ {
+ memcpy(pval, iovar_buf, sizeof(*pval));
+ *pval = dtoh32(*pval);
+ }
+ return err;
+}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h
new file mode 100644
index 000000000000..eae7d24f9e38
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wldev_common.h
@@ -0,0 +1,91 @@
+/*
+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers
+ *
+ * Copyright (C) 1999-2011, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: wldev_common.h,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
+ */
+#ifndef __WLDEV_COMMON_H__
+#define __WLDEV_COMMON_H__
+
+/** wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or
+ * netdev_ops->ndo_do_ioctl in new kernels)
+ * @dev: the net_device handle
+ */
+
+s32 wldev_ioctl(
+ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set);
+
+/** Retrieve named IOVARs, this function calls wl_dev_ioctl with
+ WLC_GET_VAR IOCTL code
+ */
+s32 wldev_iovar_getbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen);
+
+/** Set named IOVARs, this function calls wl_dev_ioctl with
+ WLC_SET_VAR IOCTL code
+ */
+s32 wldev_iovar_setbuf(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen);
+
+s32 wldev_iovar_setint(
+ struct net_device *dev, s8 *iovar, s32 val);
+
+s32 wldev_iovar_getint(
+ struct net_device *dev, s8 *iovar, s32 *pval);
+
+
+s32 wldev_mkiovar(
+ s8 *iovar_name, s8 *param, s32 paramlen,
+ s8 *iovar_buf, u32 buflen);
+
+
+/** The following function can be implemented if there is a need for bsscfg
+ indexed IOVARs
+ */
+
+s32 wldev_mkiovar_bsscfg(
+ const s8 *iovar_name, s8 *param, s32 paramlen,
+ s8 *iovar_buf, s32 buflen, s32 bssidx);
+
+/** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
+ WLC_GET_VAR IOCTL code
+ */
+s32 wldev_iovar_getbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx);
+
+/** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
+ WLC_SET_VAR IOCTL code
+ */
+s32 wldev_iovar_setbuf_bsscfg(
+ struct net_device *dev, s8 *iovar_name,
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx);
+
+s32 wldev_iovar_getint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx);
+
+s32 wldev_iovar_setint_bsscfg(
+ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx);
+
+#endif /* __WLDEV_COMMON_H__ */