diff options
author | Howard M. Harte <hharte@broadcom.com> | 2011-10-09 02:33:08 +0100 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2011-10-09 02:33:08 +0100 |
commit | 1eb9f78e6f5a5ffb196e07a01f51c3226cbdefea (patch) | |
tree | da530948d453456c3d264c92552b6328c4e382d4 /drivers/net/wireless/bcmdhd | |
parent | 57dfe636caf846442c78963155e3883e76ce5763 (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>
Diffstat (limited to 'drivers/net/wireless/bcmdhd')
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_cdc.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_common.c | 405 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_linux.c | 376 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_sdio.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/include/epivers.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfg80211.c | 153 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 37 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_iw.c | 141 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_iw.h | 6 |
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, ¶m); } -#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, ¶m); } -#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 |