net: wireless: bcmdhd: Update to 5.90.125.74
authorHoward M. Harte <hharte@broadcom.com>
Tue, 30 Aug 2011 02:01:55 +0000 (19:01 -0700)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 20:23:27 +0000 (12:23 -0800)
Change-Id: I427ee7a07e794b228e58fa2edbaa127481b67398
Signed-off-by: Howard M. Harte <hharte@broadcom.com>
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_cdc.c
drivers/net/wireless/bcmdhd/dhd_common.c
drivers/net/wireless/bcmdhd/dhd_linux.c
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd/include/epivers.h
drivers/net/wireless/bcmdhd/wl_cfg80211.c
drivers/net/wireless/bcmdhd/wl_cfgp2p.c
drivers/net/wireless/bcmdhd/wl_iw.c
drivers/net/wireless/bcmdhd/wl_iw.h

index 281e047..454213b 100644 (file)
@@ -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 {
index 0f9893a..54ce6ff 100644 (file)
 #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.
index f6bb8e5..13791cd 100644 (file)
@@ -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));
index 03ba34a..d869be4 100644 (file)
@@ -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];
index 6d89f6b..c412edd 100644 (file)
 #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"));
index f474dfa..ec060c9 100644 (file)
 
 #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 
index 0952913..0ab5235 100644 (file)
@@ -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);
index 98271c2..a5ad9e0 100644 (file)
@@ -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"));
index 6d546fc..f74115c 100644 (file)
@@ -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 
index a34472f..e013b92 100644 (file)
@@ -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