summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward M. Harte <hharte@broadcom.com>2011-10-09 02:33:08 +0100
committerAndy Green <andy.green@linaro.org>2011-10-09 02:33:08 +0100
commit1eb9f78e6f5a5ffb196e07a01f51c3226cbdefea (patch)
treeda530948d453456c3d264c92552b6328c4e382d4
parent57dfe636caf846442c78963155e3883e76ce5763 (diff)
net: wireless: bcmdhd: Update to 5.90.125.74
Change-Id: I427ee7a07e794b228e58fa2edbaa127481b67398 Signed-off-by: Howard M. Harte <hharte@broadcom.com> Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h21
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cdc.c9
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c405
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c376
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c13
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h8
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c153
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c37
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c141
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.h6
10 files changed, 618 insertions, 551 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index 281e047af85..454213b25e4 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -52,6 +52,9 @@
#include <linux/wakelock.h>
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
/* The kernel threading is sdio-specific */
+struct task_struct;
+struct sched_param;
+int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
#define ALL_INTERFACES 0xff
@@ -114,6 +117,10 @@ void dhd_os_prefree(void *osh, void *addr, uint size);
#endif /* defined(DHD_USE_STATIC_BUF) */
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#ifndef DHD_SDALIGN
+#define DHD_SDALIGN 32
+#endif
/* Common structure for module and instance linkage */
typedef struct dhd_pub {
/* Linkage ponters */
@@ -413,12 +420,6 @@ extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
extern void dhd_os_sdtxlock(dhd_pub_t * pub);
extern void dhd_os_sdtxunlock(dhd_pub_t * pub);
-#if defined(DHDTHREAD)
-struct task_struct;
-struct sched_param;
-int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
-#endif /* DHDTHREAD && DHD_GPL */
-
typedef struct {
uint32 limit; /* Expiration time (usec) */
uint32 increment; /* Current expiration increment (usec) */
@@ -466,6 +467,14 @@ extern uint dhd_bus_status(dhd_pub_t *dhdp);
extern int dhd_bus_start(dhd_pub_t *dhdp);
extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
+#if defined(KEEP_ALIVE)
+extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
+#endif /* KEEP_ALIVE */
+
+#ifdef ARP_OFFLOAD_SUPPORT
+extern void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode);
+extern void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable);
+#endif /* ARP_OFFLOAD_SUPPORT */
typedef enum cust_gpio_modes {
diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c
index 0f9893a1537..54ce6ff6d8b 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cdc.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c
@@ -47,13 +47,6 @@
#include <dhd_wlfc.h>
#endif
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN 32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
#define BUS_HEADER_LEN (16+DHD_SDALIGN) /* Must be at least SDPCM_RESERVE
@@ -587,7 +580,7 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
return;
}
-/* Create a place to store all packet pointers submitted to the firmware until
+/* Create a place to store all packet pointers submitted to the firmware until
a status comes back, suppress or otherwise.
hang-er: noun, a contrivance on which things are hung, as a hook.
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index f6bb8e5bb56..13791cdcbb8 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -88,21 +88,9 @@ 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);
-
bool ap_cfg_running = FALSE;
bool ap_fw_loaded = FALSE;
-#if defined(KEEP_ALIVE)
-int dhd_keep_alive_onoff(dhd_pub_t *dhd);
-#endif /* KEEP_ALIVE */
-
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN 32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
#ifdef DHD_DEBUG
const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on "
@@ -1522,331 +1510,6 @@ int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
}
#endif /* ARP_OFFLOAD_SUPPORT */
-int
-dhd_preinit_ioctls(dhd_pub_t *dhd)
-{
- int ret = 0;
- char eventmask[WL_EVENTING_MASK_LEN];
- char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
-
- uint up = 0;
- uint power_mode = PM_FAST;
- uint32 dongle_align = DHD_SDALIGN;
- uint32 glom = 0;
- uint bcn_timeout = 4;
- uint retry_max = 3;
-#if defined(ARP_OFFLOAD_SUPPORT)
- int arpoe = 1;
-#endif
- int scan_assoc_time = 40;
- int scan_unassoc_time = 40;
- const char *str;
- wl_pkt_filter_t pkt_filter;
- wl_pkt_filter_t *pkt_filterp;
- int buf_len;
- int str_len;
- uint32 mask_size;
- uint32 pattern_size;
- char buf[WLC_IOCTL_SMLEN];
- char *ptr;
- uint filter_mode = 1;
- uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
-#if defined(SOFTAP)
- uint dtim = 1;
-#endif
-#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211))
- uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
-#endif /* AP */
-#if defined(AP) || defined(WLP2P)
- uint32 apsta = 1; /* Enable APSTA mode */
-#endif /* defined(AP) || defined(WLP2P) */
-#ifdef GET_CUSTOM_MAC_ENABLE
- struct ether_addr ea_addr;
-#endif /* GET_CUSTOM_MAC_ENABLE */
-
- dhd->op_mode = 0;
-#ifdef GET_CUSTOM_MAC_ENABLE
- ret = dhd_custom_get_mac_address(ea_addr.octet);
- if (!ret) {
- memset(buf, 0, sizeof(buf));
- 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));
- return BCME_NOTUP;
- }
- } else {
-#endif /* GET_CUSTOM_MAC_ENABLE */
- /* Get the default device MAC address directly from firmware */
- memset(buf, 0, sizeof(buf));
- bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
- FALSE, 0)) < 0) {
- DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
- return BCME_NOTUP;
- }
- /* Update public MAC address after reading from Firmware */
- memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
-#ifdef GET_CUSTOM_MAC_ENABLE
- }
-#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);
-
- 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 */
-
- DHD_TRACE(("Firmware = %s\n", fw_path));
-#if !defined(AP) && defined(WLP2P)
- /* Check if firmware with WFD support used */
- if (strstr(fw_path, "_p2p") != NULL) {
- bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
- iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
- DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret));
- } else {
- dhd->op_mode |= WFD_MASK;
-#if defined(ARP_OFFLOAD_SUPPORT)
- arpoe = 0;
-#endif /* (ARP_OFFLOAD_SUPPORT) */
- dhd_pkt_filter_enable = FALSE;
- }
- }
-#endif /* !defined(AP) && defined(WLP2P) */
-
-#if !defined(AP) && defined(WL_CFG80211)
- /* Check if firmware with HostAPD support used */
- if (strstr(fw_path, "_apsta") != NULL) {
- /* Turn off MPC in AP mode */
- bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf), TRUE, 0)) < 0) {
- DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret));
- } else {
- dhd->op_mode |= HOSTAPD_MASK;
-#if defined(ARP_OFFLOAD_SUPPORT)
- arpoe = 0;
-#endif /* (ARP_OFFLOAD_SUPPORT) */
- dhd_pkt_filter_enable = FALSE;
- }
- }
-#endif /* !defined(AP) && defined(WL_CFG80211) */
-
- if ((dhd->op_mode != WFD_MASK) && (dhd->op_mode != HOSTAPD_MASK)) {
- /* STA only operation mode */
- dhd->op_mode |= STA_MASK;
- dhd_pkt_filter_enable = TRUE;
- }
- DHD_ERROR(("Firmware up: op_mode=%d, "
- "Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
- dhd->op_mode,
- dhd->mac.octet[0], dhd->mac.octet[1], dhd->mac.octet[2],
- dhd->mac.octet[3], dhd->mac.octet[4], dhd->mac.octet[5]));
-
- /* Set Country code */
- if (dhd->dhd_cspec.ccode[0] != 0) {
- bcm_mkiovar("country", (char *)&dhd->dhd_cspec,
- sizeof(wl_country_t), iovbuf, sizeof(iovbuf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
- DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
- }
-
- /* Set Listen Interval */
- bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
- DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret));
-
- /* query for 'ver' to get version info from firmware */
- memset(buf, 0, sizeof(buf));
- ptr = buf;
- bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
- DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
- else {
- bcmstrtok(&ptr, "\n", 0);
- /* Print fw version info */
- DHD_ERROR(("Firmware version = %s\n", buf));
- }
- /* Set PowerSave mode */
- dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
-
- /* Match Host and Dongle rx alignment */
- bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-
- /* disable glom option per default */
- 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);
- /* Setup assoc_retry_max count to reconnect target AP in dongle */
- bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#if defined(AP) && !defined(WLP2P)
- /* Turn off MPC in AP mode */
- bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* defined(AP) && !defined(WLP2P) */
-#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 defined(SOFTAP)
- if (ap_fw_loaded == FALSE)
-#endif
- if ((res = dhd_keep_alive_onoff(dhd)) < 0)
- DHD_ERROR(("%s set keeplive failed %d\n",
- __FUNCTION__, res));
- }
-#endif /* defined(KEEP_ALIVE) */
-
- /* Force STA UP */
- ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0);
- if (ret < 0)
- goto done;
-
- /* Setup event_msgs */
- bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
- if (ret < 0)
- goto done;
- bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
-
- /* Setup event_msgs */
- setbit(eventmask, WLC_E_SET_SSID);
- setbit(eventmask, WLC_E_PRUNE);
- setbit(eventmask, WLC_E_AUTH);
- setbit(eventmask, WLC_E_REASSOC);
- setbit(eventmask, WLC_E_REASSOC_IND);
- setbit(eventmask, WLC_E_DEAUTH_IND);
- setbit(eventmask, WLC_E_DISASSOC_IND);
- setbit(eventmask, WLC_E_DISASSOC);
- setbit(eventmask, WLC_E_JOIN);
- setbit(eventmask, WLC_E_ASSOC_IND);
- setbit(eventmask, WLC_E_PSK_SUP);
- setbit(eventmask, WLC_E_LINK);
- setbit(eventmask, WLC_E_NDIS_LINK);
- setbit(eventmask, WLC_E_MIC_ERROR);
- setbit(eventmask, WLC_E_PMKID_CACHE);
- setbit(eventmask, WLC_E_TXFAIL);
- setbit(eventmask, WLC_E_JOIN_START);
- setbit(eventmask, WLC_E_SCAN_COMPLETE);
-#ifdef WLMEDIA_HTSF
- setbit(eventmask, WLC_E_HTSFSYNC);
-#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,
- sizeof(scan_unassoc_time), TRUE, 0);
-
- /* add a default packet filter pattern */
- str = "pkt_filter_add";
- str_len = strlen(str);
- strncpy(buf, str, str_len);
- buf[ str_len ] = '\0';
- buf_len = str_len + 1;
-
- pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
-
- /* Parse packet filter id. */
- pkt_filter.id = htod32(100);
-
- /* Parse filter polarity. */
- pkt_filter.negate_match = htod32(0);
-
- /* Parse filter type. */
- pkt_filter.type = htod32(0);
-
- /* Parse pattern filter offset. */
- pkt_filter.u.pattern.offset = htod32(0);
-
- /* Parse pattern filter mask. */
- mask_size = htod32(wl_pattern_atoh("0x01",
- (char *) pkt_filterp->u.pattern.mask_and_pattern));
-
- /* Parse pattern filter pattern. */
- pattern_size = htod32(wl_pattern_atoh("0x00",
- (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
-
- if (mask_size != pattern_size) {
- DHD_ERROR(("Mask and pattern not the same size\n"));
- return -EINVAL;
- }
-
- pkt_filter.u.pattern.size_bytes = mask_size;
- buf_len += WL_PKT_FILTER_FIXED_LEN;
- buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
-
- /* Keep-alive attributes are set in local variable (keep_alive_pkt), and
- ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
- ** guarantee that the buffer is properly aligned.
- */
- memcpy((char *)pkt_filterp, &pkt_filter,
- WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
-
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
-
- /* 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 for STA only */
- if (arpoe && !ap_fw_loaded) {
- dhd_arp_offload_set(dhd, dhd_arp_mode);
- dhd_arp_offload_enable(dhd, arpoe);
- } else {
- dhd_arp_offload_set(dhd, 0);
- dhd_arp_offload_enable(dhd, FALSE);
- }
-#endif /* ARP_OFFLOAD_SUPPORT */
-
-#ifdef PKT_FILTER_SUPPORT
- if (ap_fw_loaded) {
- int i;
- for (i = 0; i < dhd->pktfilter_count; i++) {
- dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
- 0, dhd_master_mode);
- }
- }
-#endif /* PKT_FILTER_SUPPORT */
-
-
-done:
- return ret;
-}
-
/* send up locally generated event */
void
dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
@@ -2050,13 +1713,48 @@ fail:
#endif /* SIMPLE_ISCAN */
+/*
+ * returns = TRUE if associated, FALSE if not associated
+ */
+bool is_associated(dhd_pub_t *dhd, void *bss_buf)
+{
+ char bssid[6], zbuf[6];
+ int ret = -1;
+
+ bzero(bssid, 6);
+ bzero(zbuf, 6);
+
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, (char *)&bssid, ETHER_ADDR_LEN, FALSE, 0);
+ DHD_TRACE((" %s WLC_GET_BSSID ioctl res = %d\n", __FUNCTION__, ret));
+
+ if (ret == BCME_NOTASSOCIATED) {
+ DHD_TRACE(("%s: not associated! res:%d\n", __FUNCTION__, ret));
+ }
+
+ if (ret < 0)
+ return FALSE;
+
+ if ((memcmp(bssid, zbuf, ETHER_ADDR_LEN) != 0)) {
+ /* STA is assocoated BSSID is non zero */
+
+ if (bss_buf) {
+ /* return bss if caller provided buf */
+ memcpy(bss_buf, bssid, ETHER_ADDR_LEN);
+ }
+ return TRUE;
+ } else {
+ DHD_TRACE(("%s: WLC_GET_BSSID ioctl returned zero bssid\n", __FUNCTION__));
+ return FALSE;
+ }
+}
+
+
/* Function to estimate possible DTIM_SKIP value */
int
dhd_get_dtim_skip(dhd_pub_t *dhd)
{
int bcn_li_dtim;
- int ret;
- uint8 bssid[6];
+ int ret = -1;
int dtim_assoc = 0;
if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1))
@@ -2065,8 +1763,7 @@ dhd_get_dtim_skip(dhd_pub_t *dhd)
bcn_li_dtim = dhd->dtim_skip;
/* Check if associated */
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID,
- (char *)&bssid, ETHER_ADDR_LEN, FALSE, 0)) == BCME_NOTASSOCIATED) {
+ if (is_associated(dhd, NULL) == FALSE) {
DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret));
goto exit;
}
@@ -2152,7 +1849,6 @@ int
dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
{
char iovbuf[128];
- uint8 bssid[6];
int ret = -1;
if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
@@ -2162,28 +1858,25 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
return (ret);
+
memset(iovbuf, 0, sizeof(iovbuf));
- /* Check if disassoc to enable pno */
- if ((pfn_enabled) &&
- ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID,
- (char *)&bssid, ETHER_ADDR_LEN, TRUE, 0)) == BCME_NOTASSOCIATED)) {
- DHD_TRACE(("%s pno enable called in disassoc mode\n", __FUNCTION__));
- }
- else if (pfn_enabled) {
- DHD_ERROR(("%s pno enable called in assoc mode ret=%d\n",
- __FUNCTION__, ret));
- return ret;
- }
+
+ if ((pfn_enabled) && (is_associated(dhd, NULL) == TRUE)) {
+ DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
+ return ret;
+}
+
/* Enable/disable PNO */
if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
- sizeof(iovbuf), TRUE, 0)) < 0) {
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
+ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
DHD_ERROR(("%s failed for error=%d\n", __FUNCTION__, ret));
return ret;
}
else {
dhd->pno_enable = pfn_enabled;
- DHD_TRACE(("%s set pno as %d\n", __FUNCTION__, dhd->pno_enable));
+ DHD_TRACE(("%s set pno as %s\n",
+ __FUNCTION__, dhd->pno_enable ? "Enable" : "Disable"));
}
}
else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, ret));
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 03ba34a2c82..d869be4ef07 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -86,6 +86,9 @@ typedef struct histo_ {
uint32 bin[NUMBIN];
} histo_t;
+#if !ISPOWEROF2(DHD_SDALIGN)
+#error DHD_SDALIGN is not a power of 2!
+#endif
static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
#endif /* WLMEDIA_HTSF */
@@ -170,6 +173,7 @@ typedef struct dhd_if {
bool txflowcontrol; /* Per interface flow control indicator */
char name[IFNAMSIZ+1]; /* linux interface name */
uint8 bssidx; /* bsscfg index for the interface */
+ bool set_multicast;
} dhd_if_t;
#ifdef WLMEDIA_HTSF
@@ -257,7 +261,6 @@ typedef struct dhd_info {
int hang_was_sent;
/* Thread to issue ioctl for multicast */
- bool set_multicast;
bool set_macaddress;
struct ether_addr macvalue;
wait_queue_head_t ctrl_wait;
@@ -1018,6 +1021,7 @@ dhd_op_if(dhd_if_t *ifp)
}
if (ret < 0) {
+ ifp->set_multicast = FALSE;
if (ifp->net) {
free_netdev(ifp->net);
}
@@ -1074,13 +1078,13 @@ _dhd_sysioc_thread(void *data)
#endif /* SOFTAP */
if (dhd->iflist[i]->state)
dhd_op_if(dhd->iflist[i]);
-#ifdef SOFTAP
+
if (dhd->iflist[i] == NULL) {
DHD_TRACE(("\n\n %s: interface %d just been removed,"
"!\n\n", __FUNCTION__, i));
continue;
}
-
+#ifdef SOFTAP
if (in_ap && dhd->set_macaddress) {
DHD_TRACE(("attempt to set MAC for %s in AP Mode,"
"blocked. \n", dhd->iflist[i]->net->name));
@@ -1088,15 +1092,15 @@ _dhd_sysioc_thread(void *data)
continue;
}
- if (in_ap && dhd->set_multicast) {
+ if (in_ap && dhd->iflist[i]->set_multicast) {
DHD_TRACE(("attempt to set MULTICAST list for %s"
"in AP Mode, blocked. \n", dhd->iflist[i]->net->name));
- dhd->set_multicast = FALSE;
+ dhd->iflist[i]->set_multicast = FALSE;
continue;
}
#endif /* SOFTAP */
- if (dhd->set_multicast) {
- dhd->set_multicast = FALSE;
+ if (dhd->iflist[i]->set_multicast) {
+ dhd->iflist[i]->set_multicast = FALSE;
_dhd_set_multicast_list(dhd, i);
}
if (dhd->set_macaddress) {
@@ -1145,7 +1149,7 @@ dhd_set_multicast_list(struct net_device *dev)
return;
ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0);
- dhd->set_multicast = TRUE;
+ dhd->iflist[ifidx]->set_multicast = TRUE;
up(&dhd->thr_sysioc_ctl.sema);
}
@@ -1605,14 +1609,12 @@ dhd_watchdog_thread(void *data)
/* This thread doesn't need any user-level access,
* so get rid of all our resources
*/
-#ifdef DHD_SCHED
if (dhd_watchdog_prio > 0) {
struct sched_param param;
param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO)?
dhd_watchdog_prio:(MAX_RT_PRIO-1);
setScheduler(current, SCHED_FIFO, &param);
}
-#endif /* DHD_SCHED */
DAEMONIZE("dhd_watchdog");
@@ -1698,14 +1700,12 @@ dhd_dpc_thread(void *data)
/* This thread doesn't need any user-level access,
* so get rid of all our resources
*/
-#ifdef DHD_SCHED
if (dhd_dpc_prio > 0)
{
struct sched_param param;
param.sched_priority = (dhd_dpc_prio < MAX_RT_PRIO)?dhd_dpc_prio:(MAX_RT_PRIO-1);
setScheduler(current, SCHED_FIFO, &param);
}
-#endif /* DHD_SCHED */
DAEMONIZE("dhd_dpc");
/* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */
@@ -2605,9 +2605,6 @@ dhd_bus_start(dhd_pub_t *dhdp)
int ret = -1;
dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
unsigned long flags;
-#ifdef EMBEDDED_PLATFORM
- char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
-#endif /* EMBEDDED_PLATFORM */
ASSERT(dhd);
@@ -2674,50 +2671,6 @@ dhd_bus_start(dhd_pub_t *dhdp)
dhd_os_sdunlock(dhdp);
-#ifdef EMBEDDED_PLATFORM
- bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
- bcopy(iovbuf, dhdp->eventmask, WL_EVENTING_MASK_LEN);
-
- setbit(dhdp->eventmask, WLC_E_SET_SSID);
- setbit(dhdp->eventmask, WLC_E_PRUNE);
- setbit(dhdp->eventmask, WLC_E_AUTH);
- setbit(dhdp->eventmask, WLC_E_REASSOC);
- setbit(dhdp->eventmask, WLC_E_REASSOC_IND);
- setbit(dhdp->eventmask, WLC_E_DEAUTH_IND);
- setbit(dhdp->eventmask, WLC_E_DISASSOC_IND);
- setbit(dhdp->eventmask, WLC_E_DISASSOC);
- setbit(dhdp->eventmask, WLC_E_JOIN);
- setbit(dhdp->eventmask, WLC_E_ASSOC_IND);
- setbit(dhdp->eventmask, WLC_E_PSK_SUP);
- setbit(dhdp->eventmask, WLC_E_LINK);
- setbit(dhdp->eventmask, WLC_E_NDIS_LINK);
- setbit(dhdp->eventmask, WLC_E_MIC_ERROR);
- setbit(dhdp->eventmask, WLC_E_PMKID_CACHE);
- setbit(dhdp->eventmask, WLC_E_TXFAIL);
- setbit(dhdp->eventmask, WLC_E_JOIN_START);
- setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
- setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_RX);
- setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_COMPLETE);
-#if defined(WLP2P)
- setbit(dhdp->eventmask, WLC_E_P2P_PROBREQ_MSG);
-#endif /* WLP2P */
-#ifdef PNO_SUPPORT
- setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
-#endif /* PNO_SUPPORT */
-
-/* enable dongle roaming event */
- setbit(dhdp->eventmask, WLC_E_ROAM);
-
-
- dhdp->pktfilter_count = 4;
- /* Setup filter to allow only unicast */
- dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00";
- dhdp->pktfilter[1] = NULL;
- dhdp->pktfilter[2] = NULL;
- dhdp->pktfilter[3] = NULL;
-#endif /* EMBEDDED_PLATFORM */
-
#ifdef READ_MACADDR
dhd_read_macaddr(dhd);
#endif
@@ -2734,6 +2687,311 @@ dhd_bus_start(dhd_pub_t *dhdp)
}
int
+dhd_preinit_ioctls(dhd_pub_t *dhd)
+{
+ int ret = 0;
+ char eventmask[WL_EVENTING_MASK_LEN];
+ char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
+
+ uint up = 0;
+ uint power_mode = PM_FAST;
+ uint32 dongle_align = DHD_SDALIGN;
+ uint32 glom = 0;
+ uint bcn_timeout = 4;
+ uint retry_max = 3;
+#if defined(ARP_OFFLOAD_SUPPORT)
+ int arpoe = 1;
+#endif
+ int scan_assoc_time = 40;
+ int scan_unassoc_time = 40;
+ char buf[WLC_IOCTL_SMLEN];
+ char *ptr;
+ uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
+#if defined(SOFTAP)
+ uint dtim = 1;
+#endif
+#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211))
+ uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
+#endif
+
+#if defined(AP) || defined(WLP2P)
+ uint32 apsta = 1; /* Enable APSTA mode */
+#endif /* defined(AP) || defined(WLP2P) */
+#ifdef GET_CUSTOM_MAC_ENABLE
+ struct ether_addr ea_addr;
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+ DHD_TRACE(("Enter %s\n", __FUNCTION__));
+ dhd->op_mode = 0;
+#ifdef GET_CUSTOM_MAC_ENABLE
+ ret = dhd_custom_get_mac_address(ea_addr.octet);
+ if (!ret) {
+ memset(buf, 0, sizeof(buf));
+ 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));
+ return BCME_NOTUP;
+ }
+ } else {
+#endif /* GET_CUSTOM_MAC_ENABLE */
+ /* Get the default device MAC address directly from firmware */
+ memset(buf, 0, sizeof(buf));
+ bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
+ FALSE, 0)) < 0) {
+ DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
+ return BCME_NOTUP;
+ }
+ /* Update public MAC address after reading from Firmware */
+ memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+#ifdef GET_CUSTOM_MAC_ENABLE
+ }
+#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);
+
+ 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 */
+
+ DHD_TRACE(("Firmware = %s\n", fw_path));
+#if !defined(AP) && defined(WLP2P)
+ /* Check if firmware with WFD support used */
+ if (strstr(fw_path, "_p2p") != NULL) {
+ bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
+ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret));
+ } else {
+ dhd->op_mode |= WFD_MASK;
+#if defined(ARP_OFFLOAD_SUPPORT)
+ arpoe = 0;
+#endif /* (ARP_OFFLOAD_SUPPORT) */
+ dhd_pkt_filter_enable = FALSE;
+ }
+ }
+#endif
+
+#if !defined(AP) && defined(WL_CFG80211)
+ /* Check if firmware with HostAPD support used */
+ if (strstr(fw_path, "_apsta") != NULL) {
+ /* Turn off MPC in AP mode */
+ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret));
+ } else {
+ dhd->op_mode |= HOSTAPD_MASK;
+#if defined(ARP_OFFLOAD_SUPPORT)
+ arpoe = 0;
+#endif /* (ARP_OFFLOAD_SUPPORT) */
+ dhd_pkt_filter_enable = FALSE;
+ }
+ }
+#endif
+
+ if ((dhd->op_mode != WFD_MASK) && (dhd->op_mode != HOSTAPD_MASK)) {
+ /* STA only operation mode */
+ dhd->op_mode |= STA_MASK;
+ dhd_pkt_filter_enable = TRUE;
+ }
+
+ DHD_ERROR(("Firmware up: op_mode=%d, "
+ "Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ dhd->op_mode,
+ dhd->mac.octet[0], dhd->mac.octet[1], dhd->mac.octet[2],
+ dhd->mac.octet[3], dhd->mac.octet[4], dhd->mac.octet[5]));
+
+ /* Set Country code */
+ if (dhd->dhd_cspec.ccode[0] != 0) {
+ bcm_mkiovar("country", (char *)&dhd->dhd_cspec,
+ sizeof(wl_country_t), iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
+ }
+
+ /* Set Listen Interval */
+ bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret));
+
+ /* query for 'ver' to get version info from firmware */
+ memset(buf, 0, sizeof(buf));
+ ptr = buf;
+ bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
+ DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
+ else {
+ bcmstrtok(&ptr, "\n", 0);
+ /* Print fw version info */
+ DHD_ERROR(("Firmware version = %s\n", buf));
+ }
+ /* Set PowerSave mode */
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
+
+ /* Match Host and Dongle rx alignment */
+ bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
+ /* disable glom option per default */
+ 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);
+ /* Setup assoc_retry_max count to reconnect target AP in dongle */
+ bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#if defined(AP) && !defined(WLP2P)
+ /* Turn off MPC in AP mode */
+ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif /* defined(AP) && !defined(WLP2P) */
+
+#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 defined(SOFTAP)
+ if (ap_fw_loaded == FALSE)
+#endif
+ if ((res = dhd_keep_alive_onoff(dhd)) < 0)
+ DHD_ERROR(("%s set keeplive failed %d\n",
+ __FUNCTION__, res));
+ }
+#endif /* defined(KEEP_ALIVE) */
+
+
+ /* Read event_msgs mask */
+ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
+ DHD_ERROR(("%s read Event mask failed %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+ bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
+
+ /* Setup event_msgs */
+ setbit(eventmask, WLC_E_SET_SSID);
+ setbit(eventmask, WLC_E_PRUNE);
+ setbit(eventmask, WLC_E_AUTH);
+ setbit(eventmask, WLC_E_REASSOC);
+ setbit(eventmask, WLC_E_REASSOC_IND);
+ setbit(eventmask, WLC_E_DEAUTH_IND);
+ setbit(eventmask, WLC_E_DISASSOC_IND);
+ setbit(eventmask, WLC_E_DISASSOC);
+ setbit(eventmask, WLC_E_JOIN);
+ setbit(eventmask, WLC_E_ASSOC_IND);
+ setbit(eventmask, WLC_E_PSK_SUP);
+ setbit(eventmask, WLC_E_LINK);
+ setbit(eventmask, WLC_E_NDIS_LINK);
+ setbit(eventmask, WLC_E_MIC_ERROR);
+ setbit(eventmask, WLC_E_PMKID_CACHE);
+ setbit(eventmask, WLC_E_TXFAIL);
+ setbit(eventmask, WLC_E_JOIN_START);
+ setbit(eventmask, WLC_E_SCAN_COMPLETE);
+#ifdef WLMEDIA_HTSF
+ setbit(eventmask, WLC_E_HTSFSYNC);
+#endif /* WLMEDIA_HTSF */
+#ifdef PNO_SUPPORT
+ setbit(eventmask, WLC_E_PFN_NET_FOUND);
+#endif /* PNO_SUPPORT */
+ /* enable dongle roaming event */
+ setbit(eventmask, WLC_E_ROAM);
+#ifdef WL_CFG80211
+ 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);
+#endif /* WL_CFG80211 */
+
+ /* Write updated Event mask */
+ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set Event mask failed %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+
+ 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,
+ sizeof(scan_unassoc_time), TRUE, 0);
+
+#ifdef ARP_OFFLOAD_SUPPORT
+ /* Set and enable ARP offload feature for STA only */
+ if (arpoe
+#if defined(SOFTAP)
+ && (!ap_fw_loaded)
+#endif /* (OEM_ANDROID) && defined(SOFTAP) */
+ ) {
+ dhd_arp_offload_set(dhd, dhd_arp_mode);
+ dhd_arp_offload_enable(dhd, arpoe);
+ } else {
+ dhd_arp_offload_set(dhd, 0);
+ dhd_arp_offload_enable(dhd, FALSE);
+ }
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+#ifdef PKT_FILTER_SUPPORT
+ /* Setup defintions for pktfilter , enable in suspend */
+ dhd->pktfilter_count = 4;
+ /* Setup filter to allow only unicast */
+ dhd->pktfilter[0] = "100 0 0 0 0x01 0x00";
+ dhd->pktfilter[1] = NULL;
+ dhd->pktfilter[2] = NULL;
+ dhd->pktfilter[3] = NULL;
+
+#if defined(SOFTAP)
+ if (ap_fw_loaded) {
+ int i;
+ for (i = 0; i < dhd->pktfilter_count; i++) {
+ dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
+ 0, dhd_master_mode);
+ }
+ }
+#endif /* (SOFTAP) */
+#endif /* PKT_FILTER_SUPPORT */
+
+ /* Force STA UP */
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0);
+ if (ret < 0)
+ goto done;
+
+
+done:
+ return ret;
+}
+
+
+int
dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set)
{
char buf[strlen(name) + 1 + cmd_len];
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index 6d89f6b984a..c412edd4f16 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -87,14 +87,6 @@
#define MAX_NVRAMBUF_SIZE 4096 /* max nvram buf size */
#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold biggest possible glom */
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN 32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
-
#ifndef DHD_FIRSTREAD
#define DHD_FIRSTREAD 32
#endif
@@ -357,7 +349,7 @@ static const uint retry_limit = 2;
static bool forcealign;
/* Flag to indicate if we should download firmware on driver load */
-uint dhd_download_fw_on_driverload = FALSE;
+uint dhd_download_fw_on_driverload = TRUE;
#define ALIGNMENT 4
@@ -389,7 +381,7 @@ static bool dhd_readahead;
/* To check if there's window offered */
#define DATAOK(bus) \
- (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
+ (((uint8)(bus->tx_max - bus->tx_seq) > 2) && \
(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
/* To check if there's window offered for ctrl frame */
@@ -6220,6 +6212,7 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
dhd_os_sdunlock(dhdp);
} else {
+ bcmerror = BCME_SDIO_ERROR;
DHD_INFO(("%s called when dongle is not in reset\n",
__FUNCTION__));
DHD_INFO(("Will call dhd_bus_start instead\n"));
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index f474dfa482a..ec060c91d42 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 69
+#define EPI_INCREMENTAL_NUMBER 74
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 5, 90, 125, 69
+#define EPI_VERSION 5, 90, 125, 74
-#define EPI_VERSION_NUM 0x055a7d45
+#define EPI_VERSION_NUM 0x055a7d4a
#define EPI_VERSION_DEV 5.90.125
-#define EPI_VERSION_STR "5.90.125.69"
+#define EPI_VERSION_STR "5.90.125.74"
#endif
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 09529136787..0ab5235228b 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -380,7 +380,6 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl);
static s32 wl_dongle_probecap(struct wl_priv *wl);
static void wl_init_conf(struct wl_conf *conf);
static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add);
-static s32 wl_dongle_eventmsg(struct net_device *ndev);
/*
* dongle configuration utilities
@@ -393,7 +392,6 @@ static s32 wl_dongle_glom(struct net_device *ndev, u32 glom,
u32 dongle_align);
static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar,
u32 bcn_timeout);
-static s32 wl_dongle_eventmsg(struct net_device *ndev);
static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
s32 scan_unassoc_time);
static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe,
@@ -926,16 +924,19 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
if (wl_get_drv_status(wl, SCANNING)) {
wl_cfg80211_scan_abort(wl, dev);
}
-
+ wldev_iovar_setint(dev, "mpc", 1);
ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
wl_set_p2p_status(wl, IF_DELETING);
if (ret) {
- /* Firmware could not delete the interface so we will not get WLC_E_IF event for cleaning the dhd virtual nw interace
- * So lets do it here. Failures from fw will ensure the application to do ifconfig <inter> down and up sequnce, which will reload the fw
- * however we should cleanup the linux network virtual interfaces
- */
+ /* Firmware could not delete the interface so we will not get WLC_E_IF
+ * event for cleaning the dhd virtual nw interace
+ * So lets do it here. Failures from fw will ensure the application to do
+ * ifconfig <inter> down and up sequnce, which will reload the fw
+ * however we should cleanup the linux network virtual interfaces
+ */
dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
- WL_ERR(("Firmware returned an error from p2p_ifdel, try to remove linux virtual network interface dev->name %s\n", dev->name));
+ WL_ERR(("Firmware returned an error from p2p_ifdel\n"));
+ WL_ERR(("try to remove linux virtual interface %s\n", dev->name));
dhd_del_if(dhd->info, dhd_net2idx(dhd->info, dev));
}
@@ -1336,6 +1337,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
s32 search_state = WL_P2P_DISC_ST_SCAN;
u32 i;
u16 *default_chan_list = NULL;
+ struct net_device *dev = NULL;
WL_DBG(("Enter \n"));
@@ -1402,6 +1404,11 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
/* SOCIAL CHANNELS 1, 6, 11 */
search_state = WL_P2P_DISC_ST_SEARCH;
WL_INFO(("P2P SEARCH PHASE START \n"));
+ } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) &&
+ (get_mode_by_netdev(wl, dev) == WL_MODE_AP)) {
+ /* If you are already a GO, then do SEARCH only */
+ WL_INFO(("Already a GO. Do SEARCH Only"));
+ search_state = WL_P2P_DISC_ST_SEARCH;
} else {
WL_INFO(("P2P SCAN STATE START \n"));
}
@@ -2797,7 +2804,7 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
#endif
{
struct wl_priv *wl = wiphy_priv(wiphy);
- s32 err = 0;
+ struct net_device *ndev = wl_to_prmry_ndev(wl);
if (unlikely(!wl_get_drv_status(wl, READY))) {
WL_INFO(("device is not ready : status (%d)\n",
(int)wl->status));
@@ -2806,14 +2813,22 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
wl_set_drv_status(wl, SCAN_ABORTING);
wl_term_iscan(wl);
+ if (wl_get_drv_status(wl, CONNECTING)) {
+ wl_bss_connect_done(wl, ndev, NULL, NULL, false);
+ wl_delay(500);
+ return -EAGAIN;
+ }
if (wl->scan_request) {
cfg80211_scan_done(wl->scan_request, true);
wl->scan_request = NULL;
+ /* Make sure WPA_supplicant receives scan abort event */
+ wl_delay(500);
+ return -EAGAIN;
}
wl_clr_drv_status(wl, SCANNING);
wl_clr_drv_status(wl, SCAN_ABORTING);
- return err;
+ return 0;
}
static __used s32
@@ -3183,23 +3198,13 @@ 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 and INVITE REQ
- * because wpa-supplicant use eth0 primary address
+ * To make sure to send successfully action frame, we have to turn off mpc
*/
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
+ (act_frm->subtype == P2P_PAF_GON_RSP)) {
+ wldev_iovar_setint(dev, "mpc", 0);
+ } else if (act_frm->subtype == P2P_PAF_GON_CONF) {
+ wldev_iovar_setint(dev, "mpc", 1);
}
}
@@ -3545,7 +3550,7 @@ 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));
if (wl->p2p_supported && p2p_on(wl) &&
- (bssidx >= wl_to_p2p_bss_bssidx(wl,
+ (bssidx == wl_to_p2p_bss_bssidx(wl,
P2PAPI_BSSCFG_CONNECTION))) {
memset(beacon_ie, 0, sizeof(beacon_ie));
/* We don't need to set beacon for P2P_GO,
@@ -3606,24 +3611,25 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
if (!is_bssup && (wpa2_ie != NULL)) {
+ wldev_iovar_setint(dev, "mpc", 0);
if ((err = wl_validate_wpa2ie(dev, wpa2_ie, bssidx)) < 0) {
- WL_ERR(("WPA2 IE parsing error"));
- return BCME_ERROR;
+ WL_ERR(("WPA2 IE parsing error"));
+ goto exit;
}
err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false);
if (err < 0) {
WL_ERR(("SET INFRA error %d\n", err));
- return err;
+ goto exit;
}
err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
sizeof(wl->p2p->ssid), ioctlbuf, sizeof(ioctlbuf), bssidx);
if (err < 0) {
WL_ERR(("GO SSID setting error %d\n", err));
- return err;
+ goto exit;
}
if ((err = wl_cfgp2p_bss(dev, bssidx, 1)) < 0) {
WL_ERR(("GO Bring up error %d\n", err));
- return err;
+ goto exit;
}
}
} else if (wl_get_drv_status(wl, AP_CREATING)) {
@@ -3811,7 +3817,10 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
WL_ERR(("No WPSIE in beacon \n"));
}
}
- return 0;
+exit:
+ if (err)
+ wldev_iovar_setint(dev, "mpc", 1);
+ return err;
}
#if defined(ANDROID_WIRELESS_PATCH)
@@ -4154,13 +4163,14 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
channel_info_t ci;
memset(body, 0, sizeof(body));
+ memset(&bssid, 0, ETHER_ADDR_LEN);
WL_DBG(("Enter \n"));
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);
+ err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
switch (event) {
case WLC_E_ASSOC_IND:
fc = FC_ASSOC_REQ;
@@ -4398,7 +4408,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
join_params->params.chanspec_num = 1;
join_params->params.chanspec_list[0] = ch;
- if (join_params->params.chanspec_list[0])
+ if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
chanspec |= WL_CHANSPEC_BAND_2G;
else
chanspec |= WL_CHANSPEC_BAND_5G;
@@ -4690,6 +4700,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
bool isfree = false;
s32 err = 0;
s32 freq;
+ wifi_p2p_pub_act_frame_t *act_frm;
wl_event_rx_frame_data_t *rxframe =
(wl_event_rx_frame_data_t*)data;
u32 event = ntoh32(e->event_type);
@@ -4697,6 +4708,8 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
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);
+
+ memset(&bssid, 0, ETHER_ADDR_LEN);
if (channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
@@ -4720,6 +4733,14 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
goto exit;
}
isfree = true;
+ act_frm =
+ (wifi_p2p_pub_act_frame_t *) (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
+ /*
+ * After complete GO Negotiation, roll back to mpc mode
+ */
+ if (act_frm->subtype == P2P_PAF_GON_CONF) {
+ wldev_iovar_setint(ndev, "mpc", 1);
+ }
} else {
mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
}
@@ -5489,6 +5510,8 @@ 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 (event_type == WLC_E_PFN_NET_FOUND)
+ WL_ERR((" PNO Event\n"));
if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
wl_wakeup_event(wl);
}
@@ -5658,57 +5681,6 @@ dongle_eventmsg_out:
}
-static s32 wl_dongle_eventmsg(struct net_device *ndev)
-{
- s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
-
- s8 eventmask[WL_EVENTING_MASK_LEN];
- s32 err = 0;
-
- /* Setup event_msgs */
- bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, 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;
- }
- memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-
- setbit(eventmask, WLC_E_SET_SSID);
- setbit(eventmask, WLC_E_PRUNE);
- setbit(eventmask, WLC_E_AUTH);
- 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);
- setbit(eventmask, WLC_E_ROAM);
- setbit(eventmask, WLC_E_ASSOC_IND);
- setbit(eventmask, WLC_E_LINK);
- setbit(eventmask, WLC_E_MIC_ERROR);
- setbit(eventmask, WLC_E_PMKID_CACHE);
- setbit(eventmask, WLC_E_TXFAIL);
- 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 = 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;
- }
-
-dongle_eventmsg_out:
- return err;
-}
#ifndef EMBEDDED_PLATFORM
static s32 wl_dongle_country(struct net_device *ndev, u8 ccode)
@@ -5993,11 +5965,6 @@ s32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
wdev = ndev->ieee80211_ptr;
if (need_lock)
rtnl_lock();
- err = wl_dongle_eventmsg(ndev);
- if (unlikely(err)) {
- WL_ERR(("wl_dongle_eventmsg failed\n"));
- goto default_conf_out;
- }
#ifndef EMBEDDED_PLATFORM
err = wl_dongle_up(ndev, 0);
if (unlikely(err)) {
@@ -6024,12 +5991,6 @@ s32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
WL_ERR(("wl_dongle_roam failed\n"));
goto default_conf_out;
}
- err = wl_dongle_eventmsg(ndev);
- if (unlikely(err)) {
- WL_ERR(("wl_dongle_eventmsg failed\n"));
- goto default_conf_out;
- }
-
wl_dongle_scantime(ndev, 40, 80);
wl_dongle_offload(ndev, 1, 0xf);
wl_dongle_filter(ndev, 1);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index 98271c28658..a5ad9e03094 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -122,6 +122,7 @@ s32
wl_cfgp2p_set_firm_p2p(struct wl_priv *wl)
{
struct net_device *ndev = wl_to_prmry_ndev(wl);
+ struct ether_addr null_eth_addr = { { 0, 0, 0, 0, 0, 0 } };
s32 ret = BCME_OK;
s32 val = 0;
/* Do we have to check whether APSTA is enabled or not ? */
@@ -132,6 +133,18 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl)
wldev_iovar_setint(ndev, "apsta", val);
wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), false);
}
+ val = 1;
+ /* Disable firmware roaming for P2P */
+ wldev_iovar_setint(ndev, "roam_off", val);
+ /* In case of COB type, firmware has default mac address
+ * After Initializing firmware, we have to set current mac address to
+ * firmware for P2P device address
+ */
+ ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr,
+ sizeof(null_eth_addr), ioctlbuf, sizeof(ioctlbuf), 0);
+ if (ret && ret != BCME_UNSUPPORTED) {
+ CFGP2P_ERR(("failed to update device address\n"));
+ }
return ret;
}
@@ -179,10 +192,8 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac)
CFGP2P_INFO(("------primary idx %d : wl p2p_ifdel %02x:%02x:%02x:%02x:%02x:%02x\n",
netdev->ifindex, mac->octet[0], mac->octet[1], mac->octet[2],
mac->octet[3], mac->octet[4], mac->octet[5]));
-
ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
ioctlbuf, sizeof(ioctlbuf));
-
if (unlikely(ret < 0)) {
printk("'wl p2p_ifdel' error %d\n", ret);
}
@@ -499,10 +510,11 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
wl_escan_params_t *eparams;
wlc_ssid_t ssid;
/* Scan parameters */
-#define P2PAPI_SCAN_NPROBES 1
-#define P2PAPI_SCAN_DWELL_TIME_MS 40
+#define P2PAPI_SCAN_NPROBES 4
+#define P2PAPI_SCAN_DWELL_TIME_MS 80
+#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 100
#define P2PAPI_SCAN_HOME_TIME_MS 10
-
+ struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
wl_set_p2p_status(wl, SCANNING);
/* Allocate scan params which need space for 3 channels and 0 ssids */
eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
@@ -556,7 +568,12 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
eparams->params.nprobes = htod32(P2PAPI_SCAN_NPROBES);
eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
- eparams->params.active_time = htod32(-1);
+ if (wl_get_drv_status(wl, CONNECTED))
+ eparams->params.active_time = htod32(-1);
+ else if (num_chans == 3)
+ eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
+ else
+ eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
eparams->params.passive_time = htod32(-1);
eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
(num_chans & WL_SCAN_PARAMS_COUNT_MASK));
@@ -576,7 +593,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
CFGP2P_INFO(("\n"));
- ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_scan",
+ ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
memblk, memsize, smbuf, sizeof(ioctlbuf), bssidx);
return ret;
}
@@ -1058,9 +1075,7 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
} else {
CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
"status : %d\n", status));
-
}
-
return ret;
}
/* Send an action frame immediately without doing channel synchronization.
@@ -1098,8 +1113,8 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
goto exit;
}
timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
- (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||wl_get_p2p_status(wl, ACTION_TX_NOACK)),
- msecs_to_jiffies(MAX_WAIT_TIME));
+ (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)),
+ msecs_to_jiffies(MAX_WAIT_TIME));
if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) {
CFGP2P_INFO(("tx action frame operation is completed\n"));
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index 6d546fcd396..f74115cc85a 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -179,6 +179,11 @@ static wlc_ssid_t g_specific_ssid;
static wlc_ssid_t g_ssid;
+#ifdef CONFIG_WPS2
+static char *g_wps_probe_req_ie;
+static int g_wps_probe_req_ie_len;
+#endif
+
bool btcoex_is_sco_active(struct net_device *dev);
static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
#if defined(CONFIG_FIRST_SCAN)
@@ -6242,6 +6247,118 @@ exit_proc:
#endif
+#ifdef CONFIG_WPS2
+static int
+wl_iw_del_wps_probe_req_ie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int ret;
+ vndr_ie_setbuf_t *ie_delbuf;
+
+ if (g_wps_probe_req_ie) {
+ ie_delbuf = (vndr_ie_setbuf_t *)(g_wps_probe_req_ie + strlen("vndr_ie "));
+ strncpy(ie_delbuf->cmd, "del", 3);
+ ie_delbuf->cmd[3] = '\0';
+
+ ret = dev_wlc_ioctl(dev, WLC_SET_VAR, g_wps_probe_req_ie, g_wps_probe_req_ie_len);
+ if (ret) {
+ WL_ERROR(("ioctl failed %d \n", ret));
+ }
+
+ kfree(g_wps_probe_req_ie);
+ g_wps_probe_req_ie = NULL;
+ g_wps_probe_req_ie_len = 0;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_add_wps_probe_req_ie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ char *str_ptr = NULL;
+ char *bufptr = NULL;
+ uint buflen, datalen, iecount, pktflag, iolen, total_len;
+ int ret = 0;
+ vndr_ie_setbuf_t *ie_setbuf = NULL;
+
+ if (!g_wps_probe_req_ie) {
+ ret = -1;
+ str_ptr = extra;
+ str_ptr += WPS_PROBE_REQ_IE_CMD_LENGTH;
+ datalen = wrqu->data.length - WPS_PROBE_REQ_IE_CMD_LENGTH;
+
+ buflen = sizeof(vndr_ie_setbuf_t) + datalen - sizeof(vndr_ie_t);
+ ie_setbuf = (vndr_ie_setbuf_t *)kmalloc(buflen, GFP_KERNEL);
+ if (!ie_setbuf) {
+ WL_ERROR(("memory alloc failure ie_setbuf\n"));
+ return ret;
+ }
+
+ memset(ie_setbuf, 0x00, buflen);
+
+ strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
+ ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ iecount = htod32(1);
+ memcpy((void *)&ie_setbuf->vndr_ie_buffer.iecount, &iecount, sizeof(int));
+
+ pktflag = 0x10;
+ memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag, sizeof(uint32));
+
+ memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data, str_ptr, datalen);
+
+ total_len = strlen("vndr_ie ") + buflen;
+ bufptr = (char *)kmalloc(total_len, GFP_KERNEL);
+ if (!bufptr) {
+ WL_ERROR(("memory alloc failure bufptr\n"));
+ goto fail;
+ }
+
+ iolen = bcm_mkiovar("vndr_ie", (char *)ie_setbuf, buflen, bufptr, total_len);
+ if (iolen == 0) {
+ WL_ERROR(("Buffer length is illegal\n"));
+ goto fail2;
+ }
+
+ ret = dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
+ if (ret) {
+ WL_ERROR(("ioctl failed\n"));
+ goto fail2;
+ }
+
+ g_wps_probe_req_ie = (char *)kmalloc(iolen, GFP_KERNEL);
+ if (!g_wps_probe_req_ie) {
+ WL_ERROR(("memory alloc failure g_wps_probe_req_ie\n"));
+ goto fail2;
+ }
+
+ memcpy(g_wps_probe_req_ie, bufptr, iolen);
+ g_wps_probe_req_ie_len = iolen;
+ }
+
+fail2:
+ if (bufptr) {
+ kfree(bufptr);
+ bufptr = NULL;
+ }
+fail:
+ if (ie_setbuf) {
+ kfree(ie_setbuf);
+ ie_setbuf = NULL;
+ }
+ return ret;
+}
+#endif
#ifdef SOFTAP
@@ -6345,11 +6462,14 @@ get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
return res;
}
#endif
+
memset(&null_ssid, 0, sizeof(wlc_ssid_t));
res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
+
#ifdef AP_ONLY
res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
#else
+
iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid),
null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
ASSERT(iolen);
@@ -6660,6 +6780,7 @@ wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
WL_SOFTAP((" channel = %d\n", ap->channel));
WL_SOFTAP((" max scb = %d\n", ap->max_scb));
+
if (strnicmp(ap->sec, "open", strlen("open")) == 0) {
@@ -7406,6 +7527,12 @@ wl_iw_set_priv(
else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
#endif
+#ifdef CONFIG_WPS2
+ else if (strnicmp(extra, WPS_ADD_PROBE_REQ_IE_CMD, strlen(WPS_ADD_PROBE_REQ_IE_CMD)) == 0)
+ ret = wl_iw_add_wps_probe_req_ie(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, WPS_DEL_PROBE_REQ_IE_CMD, strlen(WPS_DEL_PROBE_REQ_IE_CMD)) == 0)
+ ret = wl_iw_del_wps_probe_req_ie(dev, info, (union iwreq_data *)dwrq, extra);
+#endif
else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0)
@@ -7420,7 +7547,7 @@ wl_iw_set_priv(
WL_SOFTAP(("penguin, set AP_MAC_LIST_SET\n"));
set_ap_mac_list(dev, (extra + PROFILE_OFFSET));
}
-#endif
+#endif
else {
WL_ERROR(("Unknown PRIVATE command %s - ignored\n", extra));
snprintf(extra, MAX_WX_STRING, "OK");
@@ -8546,6 +8673,10 @@ wl_iw_attach(struct net_device *dev, void * dhdp)
g_iscan->scan_flag = 0;
#endif
+#ifdef CONFIG_WPS2
+ g_wps_probe_req_ie = NULL;
+ g_wps_probe_req_ie_len = 0;
+#endif
iscan->timer_ms = 8000;
init_timer(&iscan->timer);
@@ -8613,6 +8744,14 @@ wl_iw_detach(void)
kfree(g_scan);
g_scan = NULL;
+#ifdef CONFIG_WPS2
+
+ if (g_wps_probe_req_ie) {
+ kfree(g_wps_probe_req_ie);
+ g_wps_probe_req_ie = NULL;
+ g_wps_probe_req_ie_len = 0;
+ }
+#endif
#if !defined(CSCAN)
wl_iw_release_ss_cache_ctrl();
#endif
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h
index a34472f95b4..e013b92178c 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.h
+++ b/drivers/net/wireless/bcmdhd/wl_iw.h
@@ -297,4 +297,10 @@ extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int c
#define NETDEV_PRIV(dev) (*(wl_iw_t **)netdev_priv(dev))
+#ifdef CONFIG_WPS2
+#define WPS_ADD_PROBE_REQ_IE_CMD "ADD_WPS_PROBE_REQ_IE "
+#define WPS_DEL_PROBE_REQ_IE_CMD "DEL_WPS_PROBE_REQ_IE "
+#define WPS_PROBE_REQ_IE_CMD_LENGTH 21
+#endif
+
#endif