net: wireless: bcmdhd: Update to 5.90.195.75
Narayan Reddy [Fri, 27 Jul 2012 09:57:53 +0000 (14:57 +0530)]
Bug 1023045

Change-Id: Id6e43c852a90cbd5445daf38279ed690712c3332
Signed-off-by: Narayan Reddy <narayanr@nvidia.com>
Reviewed-on: http://git-master/r/117637
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Rakesh Kumar <krakesh@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

15 files changed:
drivers/net/wireless/bcmdhd/Makefile
drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_common.c
drivers/net/wireless/bcmdhd/dhd_linux.c
drivers/net/wireless/bcmdhd/include/bcmdevs.h
drivers/net/wireless/bcmdhd/include/epivers.h
drivers/net/wireless/bcmdhd/include/hndpmu.h
drivers/net/wireless/bcmdhd/include/sbchipc.h
drivers/net/wireless/bcmdhd/include/siutils.h
drivers/net/wireless/bcmdhd/include/wlioctl.h
drivers/net/wireless/bcmdhd/wl_cfg80211.c
drivers/net/wireless/bcmdhd/wl_cfg80211.h
drivers/net/wireless/bcmdhd/wl_cfgp2p.c
drivers/net/wireless/bcmdhd/wl_cfgp2p.h
drivers/net/wireless/bcmdhd/wl_iw.c

index 2851388..50fac43 100644 (file)
@@ -8,9 +8,15 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER                     \
        -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT          \
        -DKEEP_ALIVE -DPKT_FILTER_SUPPORT     \
        -DEMBEDDED_PLATFORM           \
-       -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT                       \
        -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
 
+# Only for JB (disable on ICS)
+DHDCFLAGS += -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT
+
+# for WFD IE support
+DHDCFLAGS += -DWLWFDIE
+
+
 ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y)
 DHDCFLAGS += -DCONFIG_WIFI_CONTROL_FUNC
 else
index 5ff5c21..871c2bf 100644 (file)
@@ -24,7 +24,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd.h 328934 2012-04-23 05:15:42Z $
+ * $Id: dhd.h 333052 2012-05-12 02:09:28Z $
  */
 
 /****************
@@ -437,10 +437,14 @@ extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
 extern int dhd_pno_clean(dhd_pub_t *dhd);
 extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid,
                        ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
+extern int dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid,
+                               ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time);
 extern int dhd_pno_get_status(dhd_pub_t *dhd);
 extern int dhd_dev_pno_reset(struct net_device *dev);
 extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local,
                            int nssid, ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
+extern int dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid,
+                               ushort  pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time);
 extern int dhd_dev_pno_enable(struct net_device *dev,  int pfn_enabled);
 extern int dhd_dev_get_pno_status(struct net_device *dev);
 #endif /* PNO_SUPPORT */
index d9810ac..3ccc55d 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd_common.c 329682 2012-04-26 09:20:38Z $
+ * $Id: dhd_common.c 331276 2012-05-04 08:05:57Z $
  */
 #include <typedefs.h>
 #include <osl.h>
@@ -1890,12 +1890,13 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
                return ret;
        }
 
-       if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
-               return (ret);
 
        memset(iovbuf, 0, sizeof(iovbuf));
 
 #ifndef WL_SCHED_SCAN
+       if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
+               return (ret);
+
        if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) {
                DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
                return ret;
@@ -1939,9 +1940,10 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
                err = -1;
                return err;
        }
-
+#ifndef WL_SCHED_SCAN
        if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
                return (err);
+#endif /* !WL_SCHED_SCAN */
 
        /* Check for broadcast ssid */
        for (k = 0; k < nssid; k++) {
@@ -2035,6 +2037,123 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
 }
 
 int
+dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid, ushort pno_interval,
+       int pno_repeat, int pno_expo_max, int pno_lost_time)
+{
+       int err = -1;
+       char iovbuf[128];
+       int k, i;
+       wl_pfn_param_t pfn_param;
+       wl_pfn_t        pfn_element;
+       uint len = 0;
+
+       DHD_TRACE(("%s nssid=%d pno_interval=%d\n", __FUNCTION__, nssid, pno_interval));
+
+       if ((!dhd) && (!ssidnet)) {
+               DHD_ERROR(("%s error exit\n", __FUNCTION__));
+               err = -1;
+               return err;
+       }
+
+       if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
+               return (err);
+
+       /* Check for broadcast ssid */
+       for (k = 0; k < nssid; k++) {
+               if (!ssidnet[k].ssid.SSID_len) {
+                       DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", k));
+                       return err;
+               }
+       }
+/* #define  PNO_DUMP 1 */
+#ifdef PNO_DUMP
+       {
+               int j;
+               for (j = 0; j < nssid; j++) {
+                       DHD_ERROR(("%d: scan  for  %s size =%d\n", j,
+                               ssidnet[j].ssid.SSID, ssidnet[j].ssid.SSID_len));
+               }
+       }
+#endif /* PNO_DUMP */
+
+       /* clean up everything */
+       if  ((err = dhd_pno_clean(dhd)) < 0) {
+               DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err));
+               return err;
+       }
+       memset(iovbuf, 0, sizeof(iovbuf));
+       memset(&pfn_param, 0, sizeof(pfn_param));
+       memset(&pfn_element, 0, sizeof(pfn_element));
+
+       /* set pfn parameters */
+       pfn_param.version = htod32(PFN_VERSION);
+       pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
+
+       /* check and set extra pno params */
+       if ((pno_repeat != 0) || (pno_expo_max != 0)) {
+               pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
+               pfn_param.repeat = (uchar) (pno_repeat);
+               pfn_param.exp = (uchar) (pno_expo_max);
+       }
+
+       /* set up pno scan fr */
+       if (pno_interval  != 0)
+               pfn_param.scan_freq = htod32(pno_interval);
+
+       if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) {
+               DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC));
+               return err;
+       }
+       if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) {
+               DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC));
+               return err;
+       }
+
+       /* network lost time */
+       pfn_param.lost_network_timeout = htod32(pno_lost_time);
+
+       len = bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf));
+       if ((err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) {
+                               DHD_ERROR(("%s pfn_set failed for error=%d\n",
+                                       __FUNCTION__, err));
+                               return err;
+       } else {
+               DHD_TRACE(("%s pfn_set OK with PNO time=%d repeat=%d max_adjust=%d\n",
+                       __FUNCTION__, pfn_param.scan_freq,
+                       pfn_param.repeat, pfn_param.exp));
+       }
+
+       /* set all pfn ssid */
+       for (i = 0; i < nssid; i++) {
+               pfn_element.flags = htod32(ssidnet[i].flags);
+               pfn_element.infra = htod32(ssidnet[i].infra);
+               pfn_element.auth = htod32(ssidnet[i].auth);
+               pfn_element.wpa_auth = htod32(ssidnet[i].wpa_auth);
+               pfn_element.wsec = htod32(ssidnet[i].wsec);
+
+               memcpy((char *)pfn_element.ssid.SSID, ssidnet[i].ssid.SSID, ssidnet[i].ssid.SSID_len);
+               pfn_element.ssid.SSID_len = htod32(ssidnet[i].ssid.SSID_len);
+
+               if ((len =
+                       bcm_mkiovar("pfn_add", (char *)&pfn_element,
+                       sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) {
+                       if ((err =
+                               dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) {
+                               DHD_ERROR(("%s pfn_add failed with ssidnet[%d] error=%d\n",
+                                       __FUNCTION__, i, err));
+                               return err;
+                       } else {
+                               DHD_TRACE(("%s pfn_add OK with ssidnet[%d]\n", __FUNCTION__, i));
+                       }
+               } else {
+                       DHD_ERROR(("%s bcm_mkiovar failed with ssidnet[%d]\n", __FUNCTION__, i));
+               }
+       }
+
+       return err;
+}
+
+int
 dhd_pno_get_status(dhd_pub_t *dhd)
 {
        int ret = -1;
index 6ba7df1..44879e4 100644 (file)
@@ -22,7 +22,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd_linux.c 329682 2012-04-26 09:20:38Z $
+ * $Id: dhd_linux.c 333885 2012-05-18 00:39:03Z $
  */
 
 #include <typedefs.h>
@@ -42,7 +42,6 @@
 #include <linux/ethtool.h>
 #include <linux/fcntl.h>
 #include <linux/fs.h>
-#include <linux/device.h>
 
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
@@ -1526,9 +1525,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
                                tout_ctrl = DHD_PACKET_TIMEOUT_MS;
                        if (event.event_type == WLC_E_BTA_HCI_EVENT) {
                                dhd_bta_doevt(dhdp, data, event.datalen);
-                       } else if (event.event_type == WLC_E_PFN_NET_FOUND) {
+                       }
+#ifdef PNO_SUPPORT
+                       if (event.event_type == WLC_E_PFN_NET_FOUND) {
                                tout_ctrl *= 2;
                        }
+#endif /* PNO_SUPPORT */
                } else {
                        tout_rx = DHD_PACKET_TIMEOUT_MS;
                }
@@ -2603,7 +2605,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev)
        }
        dhd_state |= DHD_ATTACH_STATE_NET_ALLOC;
 
-       SET_NETDEV_DEV(net, (struct device *)dev);
        /* Allocate primary dhd_info */
        if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) {
                DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__));
@@ -2941,16 +2942,20 @@ dhd_concurrent_fw(dhd_pub_t *dhd)
                bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf));
                if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
                        FALSE, 0)) < 0) {
-                       DHD_TRACE(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
+                       DHD_ERROR(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
                } else if (buf[0] == 1) {
                        DHD_TRACE(("%s: P2P is supported\n", __FUNCTION__));
                        return 1;
                }
        }
-       return 0;
+       return ret;
 }
 #endif 
 
+/*
+ *   dhd_preinit_ioctls makes special pre-setting in the firmware before radio turns on
+ *   returns : 0 if all settings passed or negative value if anything failed
+*/
 int
 dhd_preinit_ioctls(dhd_pub_t *dhd)
 {
@@ -2959,7 +2964,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        char iovbuf[WL_EVENTING_MASK_LEN + 12]; /*  Room for "event_msgs" + '\0' + bitvec  */
 #if !defined(WL_CFG80211)
        uint up = 0;
-#endif
+#endif /* defined(WL_CFG80211) */
        uint power_mode = PM_FAST;
        uint32 dongle_align = DHD_SDALIGN;
        uint32 glom = 0;
@@ -3043,19 +3048,31 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 #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 defined(WL_ENABLE_P2P_IF)
+       if ((ret = dhd_concurrent_fw(dhd)) < 0) {
+               DHD_ERROR(("%s error : firmware can't support p2p mode\n", __FUNCTION__));
+               goto done;
+       }
+#endif /* (WL_ENABLE_P2P_IF) */
+
        if ((!op_mode && strstr(fw_path, "_p2p") != NULL)
 #if defined(WL_ENABLE_P2P_IF)
-                       || (op_mode == 0x04) ||(dhd_concurrent_fw(dhd))
+                       || (op_mode == WFD_MASK) || (dhd_concurrent_fw(dhd) == 1)
 #endif
                ) {
                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));
+                       DHD_ERROR(("%s APSTA setting failed ret= %d\n", __FUNCTION__, ret));
                } else {
                        dhd->op_mode |= WFD_MASK;
+#if !defined(WL_ENABLE_P2P_IF)
+                       /* ICS back capability : disable any packet filtering for p2p only mode */
+                       dhd_pkt_filter_enable = FALSE;
+#endif /*!defined(WL_ENABLE_P2P_IF) */
                }
        }
 #endif
@@ -3100,16 +3117,20 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 #if defined(ARP_OFFLOAD_SUPPORT)
                                arpoe = 0;
 #endif /* (ARP_OFFLOAD_SUPPORT) */
+                               /* disable any filtering for SoftAP mode */
                                dhd_pkt_filter_enable = FALSE;
                        }
        }
 #endif
 
+#if !defined(WL_ENABLE_P2P_IF)
+       /* ICS mode setting for sta */
        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;
        }
+#endif /* !defined(WL_ENABLE_P2P_IF) */
 
        DHD_ERROR(("Firmware up: fw_path=%s op_mode=%d, "
                        "Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
@@ -3262,6 +3283,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        dhd->pktfilter[1] = NULL;
        dhd->pktfilter[2] = NULL;
        dhd->pktfilter[3] = NULL;
+       /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */
        dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB";
 #if defined(SOFTAP)
        if (ap_fw_loaded) {
@@ -4448,6 +4470,17 @@ dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
        return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max));
 }
 
+/* Linux wrapper to call common dhd_pno_set_ex */
+int
+dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid,
+       ushort  pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time)
+{
+       dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+       return (dhd_pno_set_ex(&dhd->pub, ssidnet, nssid,
+                                       pno_interval, pno_repeat, pno_expo_max, pno_lost_time));
+}
+
 /* Linux wrapper to get  pno status */
 int
 dhd_dev_get_pno_status(struct net_device *dev)
@@ -4466,9 +4499,9 @@ static void dhd_hang_process(struct work_struct *work)
        struct net_device *dev;
 
        dhd = (dhd_info_t *)container_of(work, dhd_info_t, work_hang);
-               dev = dhd->iflist[0]->net;
+       dev = dhd->iflist[0]->net;
 
-               if (dev) {
+       if (dev) {
                rtnl_lock();
                dev_close(dev);
                rtnl_unlock();
@@ -4478,7 +4511,7 @@ static void dhd_hang_process(struct work_struct *work)
 #if defined(WL_CFG80211)
                wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
 #endif
-       }
+       }
 }
 
 int net_os_send_hang_message(struct net_device *dev)
index 287f1c6..4d2f576 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: bcmdevs.h 295140 2011-11-09 17:22:01Z $
+ * $Id: bcmdevs.h 332966 2012-05-11 22:40:21Z $
  */
 
 
 #define BFL2_EXTLNA_TX         0x08000000  
                                                
 #define BFL2_4313_RADIOREG     0x10000000
+#define BFL2_SECI_LOPWR_DIS    0x20000000
                                                                           
 
 
index 3bff73e..5df25c1 100644 (file)
@@ -23,6 +23,7 @@
  *
 */
 
+
 #ifndef _epivers_h_
 #define _epivers_h_
 
 
 #define        EPI_RC_NUMBER           195
 
-#define        EPI_INCREMENTAL_NUMBER  61
+#define        EPI_INCREMENTAL_NUMBER  75
 
 #define        EPI_BUILD_NUMBER        0
 
-#define        EPI_VERSION             5, 90, 195, 61
+#define        EPI_VERSION             5, 90, 195, 75
 
-#define        EPI_VERSION_NUM         0x055ac33d
+#define        EPI_VERSION_NUM         0x055ac34b
 
 #define EPI_VERSION_DEV                5.90.195
 
 
-#define        EPI_VERSION_STR         "5.90.195.61"
+#define        EPI_VERSION_STR         "5.90.195.75"
 
 #endif 
index 69a834c..9bfc8c9 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: hndpmu.h 277737 2011-08-16 17:54:59Z $
+ * $Id: hndpmu.h 335486 2012-05-28 09:47:55Z $
  */
 
 #ifndef _hndpmu_h_
@@ -31,4 +31,7 @@
 extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on);
 extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength);
 
+extern void si_pmu_set_otp_wr_volts(si_t *sih);
+extern void si_pmu_set_otp_rd_volts(si_t *sih);
+
 #endif /* _hndpmu_h_ */
index 8f75750..53bd2a1 100644 (file)
@@ -5,7 +5,7 @@
  * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer,
  * GPIO interface, extbus, and support for serial and parallel flashes.
  *
- * $Id: sbchipc.h 311371 2012-01-28 05:47:25Z $
+ * $Id: sbchipc.h 333924 2012-05-18 04:48:52Z $
  *
  * Copyright (C) 1999-2011, Broadcom Corporation
  * 
@@ -1441,18 +1441,18 @@ typedef volatile struct {
 #define CCTRL4331_EXT_LNA_G            (1<<2)  
 #define CCTRL4331_SPROM_GPIO13_15       (1<<3)  
 #define CCTRL4331_EXTPA_EN             (1<<4)  
-#define CCTRL4331_GPIOCLK_ON_SPROMCS   <1<<5)  
+#define CCTRL4331_GPIOCLK_ON_SPROMCS   (1<<5)
 #define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6)  
 #define CCTRL4331_EXTPA_ON_GPIO2_5     (1<<7)  
 #define CCTRL4331_OVR_PIPEAUXCLKEN     (1<<8)  
 #define CCTRL4331_OVR_PIPEAUXPWRDOWN   (1<<9)  
-#define CCTRL4331_PCIE_AUXCLKEN                <1<<10) 
-#define CCTRL4331_PCIE_PIPE_PLLDOWN    <1<<11) 
-#define CCTRL4331_EXTPA_EN2            (1<<12) 
-#define CCTRL4331_EXT_LNA_A            (1<<13) 
-#define CCTRL4331_BT_SHD0_ON_GPIO4     <1<<16) 
-#define CCTRL4331_BT_SHD1_ON_GPIO5     <1<<17) 
-#define CCTRL4331_EXTPA_ANA_EN         (1<<24) 
+#define CCTRL4331_PCIE_AUXCLKEN                (1<<10)
+#define CCTRL4331_PCIE_PIPE_PLLDOWN    (1<<11)
+#define CCTRL4331_EXTPA_EN2            (1<<12)
+#define CCTRL4331_EXT_LNA_A            (1<<13)
+#define CCTRL4331_BT_SHD0_ON_GPIO4     (1<<16)
+#define CCTRL4331_BT_SHD1_ON_GPIO5     (1<<17)
+#define CCTRL4331_EXTPA_ANA_EN         (1<<24)
 
 
 #define        CST4331_XTAL_FREQ               0x00000001      
index 6a7b93c..4e7aeb7 100644 (file)
@@ -22,7 +22,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: siutils.h 285387 2011-09-21 18:38:37Z $
+ * $Id: siutils.h 335486 2012-05-28 09:47:55Z $
  */
 
 
@@ -222,6 +222,8 @@ static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;}
 extern bool si_is_otp_disabled(si_t *sih);
 extern bool si_is_otp_powered(si_t *sih);
 extern void si_otp_power(si_t *sih, bool on);
+extern void si_set_otp_wr_volts(si_t *sih);
+extern void si_set_otp_rd_volts(si_t *sih);
 
 
 extern bool si_is_sprom_available(si_t *sih);
index 91274a0..5ec0c9a 100644 (file)
@@ -24,7 +24,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: wlioctl.h 312596 2012-02-03 02:53:30Z $
+ * $Id: wlioctl.h 331292 2012-05-04 09:04:23Z $
  */
 
 
@@ -1460,6 +1460,14 @@ typedef struct wl_sampledata {
 } wl_sampledata_t;
 
 
+#define WL_CHAN_VALID_HW    (1 << 0)
+#define WL_CHAN_VALID_SW    (1 << 1)
+#define WL_CHAN_BAND_5G     (1 << 2)
+#define WL_CHAN_RADAR       (1 << 3)
+#define WL_CHAN_INACTIVE    (1 << 4)
+#define WL_CHAN_PASSIVE     (1 << 5)
+#define WL_CHAN_RESTRICTED  (1 << 6)
+
 
 #define WL_ERROR_VAL        0x00000001
 #define WL_TRACE_VAL        0x00000002
index f728c14..7f3e332 100644 (file)
@@ -84,17 +84,15 @@ u32 wl_dbg_level = WL_DBG_ERR;
  * All the chnages in world regulatory domain are to be done here.
  */
 static const struct ieee80211_regdomain brcm_regdom = {
-       .n_reg_rules = 5,
+       .n_reg_rules = 4,
        .alpha2 =  "99",
        .reg_rules = {
                /* IEEE 802.11b/g, channels 1..11 */
-               REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
+               REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
                /* IEEE 802.11b/g, channels 12..13. No HT40
                 * channel fits here.
                 */
-               REG_RULE(2467-10, 2472+10, 20, 6, 20,
-               NL80211_RRF_PASSIVE_SCAN |
-               NL80211_RRF_NO_IBSS),
+               /* If any */
                /*
                 * IEEE 802.11 channel 14 - is for JP only,
                 * we need cfg80211 to allow it (reg_flags = 0); so that
@@ -231,6 +229,8 @@ static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
        const wl_event_msg_t *e, void *data);
 static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
        const wl_event_msg_t *e, void *data, bool completed);
+static s32 wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev,
+       const wl_event_msg_t *e, void *data, bool completed);
 static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
        const wl_event_msg_t *e, void *data);
 static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
@@ -296,6 +296,7 @@ static void wl_free_wdev(struct wl_priv *wl);
 
 static s32 wl_inform_bss(struct wl_priv *wl);
 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
+static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid);
 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
 
@@ -335,7 +336,6 @@ static void wl_link_up(struct wl_priv *wl);
 static void wl_link_down(struct wl_priv *wl);
 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
 static void wl_init_conf(struct wl_conf *conf);
-static s32 wl_update_wiphybands(struct wl_priv *wl);
 
 /*
  * iscan handler
@@ -704,7 +704,7 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
 
                *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
                if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
-                       sizeof(WL_EXTRA_BUF_MAX), false))) {
+                       WL_EXTRA_BUF_MAX, false))) {
                                WL_ERR(("Failed to get associated bss info, use temp channel \n"));
                                chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN);
                }
@@ -925,6 +925,11 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
 
        if (wl->p2p_supported) {
                memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
+
+               /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
+                */
+               WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
+               wl_clr_p2p_status(wl, GO_NEG_PHASE);
                if (wl->p2p->vif_created) {
                        if (wl_get_drv_status(wl, SCANNING, dev)) {
                                wl_notify_escan_complete(wl, dev, true, true);
@@ -1004,6 +1009,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
        default:
                return -EINVAL;
        }
+       WL_DBG(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type));
 
        if (ap) {
                wl_set_mode_by_netdev(wl, ndev, mode);
@@ -1019,7 +1025,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
                         */
                        chspec = wl_cfg80211_get_shared_freq(wiphy);
 
-                       wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT;
+                       wlif_type = WL_P2P_IF_GO;
                        WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
                                ndev->name, ap, infra, type));
                        wl_set_p2p_status(wl, IF_CHANGING);
@@ -1043,6 +1049,14 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
                        WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
                        return -EINVAL;
                }
+       } else {
+               infra = htod32(infra);
+               err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
+               if (err) {
+                       WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+                       return -EAGAIN;
+               }
+               wl_set_mode_by_netdev(wl, ndev, mode);
        }
 
        ndev->ieee80211_ptr->iftype = type;
@@ -1587,6 +1601,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                                                wl_cfgp2p_generate_bss_mac(&primary_mac,
                                                        &wl->p2p->dev_addr, &wl->p2p->int_addr);
                                        }
+                                       wl_clr_p2p_status(wl, GO_NEG_PHASE);
+                                       WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
                                        p2p_scan(wl) = true;
                                }
                        } else {
@@ -1625,10 +1641,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                                                } else {
                                                        wpsie_len = 0;
                                                }
-                                               err = wl_cfgp2p_set_management_ie(wl, ndev, -1,
-                                                       VNDR_IE_PRBREQ_FLAG, wpsie, wpsie_len);
-                                               if (unlikely(err)) {
-                                                       goto scan_out;
+                                               if (wpsie_len > 0) {
+                                                       err = wl_cfgp2p_set_management_ie(wl,
+                                                               ndev, -1, VNDR_IE_PRBREQ_FLAG,
+                                                               wpsie, wpsie_len);
+                                                       if (unlikely(err)) {
+                                                               goto scan_out;
+                                                       }
                                                }
                                        }
                                }
@@ -1808,86 +1827,192 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
        struct cfg80211_ibss_params *params)
 {
        struct wl_priv *wl = wiphy_priv(wiphy);
-       struct cfg80211_bss *bss;
-       struct ieee80211_channel *chan;
        struct wl_join_params join_params;
-       struct cfg80211_ssid ssid;
-       s32 scan_retry = 0;
+       struct wlc_ssid ssid;
+       struct ether_addr bssid;
+       size_t join_params_size = 0;
+       s32 wsec = 0;
+       s32 bcnprd;
        s32 err = 0;
-       bool rollback_lock = false;
 
        WL_TRACE(("In\n"));
        CHECK_SYS_UP(wl);
-       if (params->bssid) {
-               WL_ERR(("Invalid bssid\n"));
-               return -EOPNOTSUPP;
-       }
-       bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
-       if (!bss) {
-               memcpy(ssid.ssid, params->ssid, params->ssid_len);
-               ssid.ssid_len = params->ssid_len;
-               do {
-                       if (unlikely
-                               (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
-                                -EBUSY)) {
-                               wl_delay(150);
-                       } else {
-                               break;
-                       }
-               } while (++scan_retry < WL_SCAN_RETRY_MAX);
-               /* to allow scan_inform to propagate to cfg80211 plane */
-               if (rtnl_is_locked()) {
-                       rtnl_unlock();
-                       rollback_lock = true;
-               }
-
-               /* wait 4 secons till scan done.... */
-               schedule_timeout_interruptible(4 * HZ);
-               if (rollback_lock)
-                       rtnl_lock();
-               bss = cfg80211_get_ibss(wiphy, NULL,
-                       params->ssid, params->ssid_len);
-       }
-       if (bss) {
-               wl->ibss_starter = false;
-               WL_DBG(("Found IBSS\n"));
-       } else {
-               wl->ibss_starter = true;
-       }
-       chan = params->channel;
-       if (chan)
-               wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
+
        /*
-        * Join with specific BSSID and cached SSID
-        * If SSID is zero join based on BSSID only
+        * Cancel ongoing scan to sync up with sme state machine of cfg80211.
         */
-       memset(&join_params, 0, sizeof(join_params));
-       memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
-               params->ssid_len);
-       join_params.ssid.SSID_len = htod32(params->ssid_len);
+       if (wl->scan_request) {
+               wl_notify_escan_complete(wl, dev, true, true);
+       }
+       /* Clean BSSID */
+       bzero(&bssid, sizeof(bssid));
+       wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
+
+       if (params->ssid)
+               WL_INFO(("SSID: %s\n", params->ssid));
+       else {
+               WL_ERR(("SSID: NULL, Not supported\n"));
+               err = -EOPNOTSUPP;
+               goto CleanUp;
+       }
+
        if (params->bssid)
-               memcpy(&join_params.params.bssid, params->bssid,
-                       ETHER_ADDR_LEN);
+               WL_INFO(("BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n",
+                       params->bssid[0], params->bssid[1], params->bssid[2],
+                       params->bssid[3], params->bssid[4], params->bssid[5]));
+
+       if (params->channel)
+               WL_INFO(("channel: %d\n", params->channel->center_freq));
+
+       if (params->channel_fixed)
+               WL_INFO(("fixed channel required\n"));
+
+       if (params->ie && params->ie_len)
+               WL_INFO(("ie len: %d\n", params->ie_len));
+
+       if (params->beacon_interval)
+               WL_INFO(("beacon interval: %d\n", params->beacon_interval));
+
+       if (params->basic_rates)
+               WL_INFO(("basic rates: %08X\n", params->basic_rates));
+
+       if (params->privacy)
+               WL_INFO(("privacy required\n"));
+
+       wl_set_drv_status(wl, CONNECTING, dev);
+
+       /* Configure Privacy for starter */
+       if (params->privacy)
+               wsec |= WEP_ENABLED;
+
+       err = wldev_iovar_setint(dev, "wsec", wsec);
+       if (err) {
+               WL_ERR(("wsec failed (%d)\n", err));
+               goto CleanUp;
+       }
+
+       err = wldev_iovar_setint(dev, "auth", WL_AUTH_OPEN_SYSTEM);
+       if (err) {
+               WL_ERR(("auth failed (%d)\n", err));
+               goto CleanUp;
+       }
+
+       err = wldev_iovar_setint(dev, "wpa_auth", 0);
+       if (err) {
+               WL_ERR(("wpa_auth failed (%d)\n", err));
+               goto CleanUp;
+       }
+
+       /* Configure Beacon Interval for starter */
+       if (params->beacon_interval)
+               bcnprd = params->beacon_interval;
        else
-               memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
+               bcnprd = 100;
 
-       err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
-               sizeof(join_params), false);
-       if (unlikely(err)) {
-               WL_ERR(("Error (%d)\n", err));
-               return err;
+       bcnprd = htod32(bcnprd);
+       err = wldev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd), true);
+       if (err) {
+               WL_ERR(("WLC_SET_BCNPRD failed (%d)\n", err));
+               goto CleanUp;
+       }
+
+       /* Configure required join parameter */
+       memset(&join_params, 0, sizeof(struct wl_join_params));
+
+       /* SSID */
+       memset(&ssid, 0, sizeof(struct wlc_ssid));
+       ssid.SSID_len = MIN(params->ssid_len, 32);
+       join_params.ssid.SSID_len = htod32(ssid.SSID_len);
+       memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
+       memcpy(join_params.ssid.SSID, params->ssid, ssid.SSID_len);
+       join_params_size = sizeof(join_params.ssid);
+
+       wl_update_prof(wl, dev, NULL, &ssid, WL_PROF_SSID);
+
+       /* BSSID */
+       if (params->bssid) {
+               memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
+               join_params_size = sizeof(join_params.ssid) +
+                       WL_ASSOC_PARAMS_FIXED_SIZE;
+
+               wl_update_prof(wl, dev, NULL, params->bssid, WL_PROF_BSSID);
+       } else {
+               memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+       }
+
+       /* Channel */
+       if (params->channel) {
+               u32 target_channel;
+
+               target_channel = ieee80211_frequency_to_channel(
+                                                       params->channel->center_freq);
+               if (params->channel_fixed) {
+                       /* adding chanspec */
+                       wl_ch_to_chanspec(target_channel,
+                               &join_params, &join_params_size);
+               }
+
+               /* set channel for starter */
+               target_channel = htod32(target_channel);
+               err = wldev_ioctl(dev, WLC_SET_CHANNEL,
+                       &target_channel, sizeof(target_channel), true);
+               if (err) {
+                       WL_ERR(("WLC_SET_CHANNEL failed (%d)\n", err));
+                       goto CleanUp;
+               }
        }
+
+       wl->ibss_starter = false;
+
+       err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
+       if (err) {
+               WL_ERR(("WLC_SET_SSID failed (%d)\n", err));
+               goto CleanUp;
+       }
+
+CleanUp:
+
+       if (err)
+               wl_clr_drv_status(wl, CONNECTING, dev);
+
+       WL_TRACE(("Exit\n"));
        return err;
 }
 
 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
        struct wl_priv *wl = wiphy_priv(wiphy);
+       scb_val_t scbval;
+       bool act = false;
        s32 err = 0;
+       u8 *curbssid;
+
+       WL_TRACE(("Enter\n"));
 
        CHECK_SYS_UP(wl);
-       wl_link_down(wl);
+       act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
+       curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
+       if (act) {
+               /*
+               * Cancel ongoing scan to sync up with sme state machine of cfg80211.
+               */
+               if (wl->scan_request) {
+                       wl_notify_escan_complete(wl, dev, true, true);
+               }
+               wl_set_drv_status(wl, DISCONNECTING, dev);
+               scbval.val = DOT11_RC_DISASSOC_LEAVING;
+               memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
+               scbval.val = htod32(scbval.val);
+               err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+                               sizeof(scb_val_t), true);
+               if (unlikely(err)) {
+                       wl_clr_drv_status(wl, DISCONNECTING, dev);
+                       WL_ERR(("error (%d)\n", err));
+                       return err;
+               }
+       }
 
+       WL_TRACE(("Exit\n"));
        return err;
 }
 
@@ -2216,8 +2341,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                         */
                        WL_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n",
                                wl_cfgp2p_find_idx(wl, dev), sme->ie_len));
-                       wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
-                               VNDR_IE_PRBREQ_FLAG, sme->ie, sme->ie_len);
+                       wl_cfgp2p_set_management_ie(wl, dev,
+                               wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG,
+                               sme->ie, sme->ie_len);
                        wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
                                VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
                }
@@ -3328,8 +3454,8 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
        if (wl->afx_hdl->peer_chan != WL_INVALID)
                wl_cfg80211_send_pending_tx_act_frm(wl);
        else {
-               WL_ERR(("Couldn't find the peer after %d retries\n",
-                       wl->afx_hdl->retry));
+               WL_ERR(("Couldn't find the peer " MACSTR " after %d retries\n",
+                       MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), wl->afx_hdl->retry));
        }
        wl->afx_hdl->dev = NULL;
        wl->afx_hdl->bssidx = WL_INVALID;
@@ -3355,7 +3481,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
        wl_af_params_t *af_params;
        wifi_p2p_ie_t *p2p_ie;
        wpa_ie_fixed_t *wps_ie;
+#ifdef WLWFDIE
        wifi_wfd_ie_t *wfd_ie;
+#endif /* WLWFDIE */
        scb_val_t scb_val;
        const struct ieee80211_mgmt *mgmt;
        struct wl_priv *wl = wiphy_priv(wiphy);
@@ -3364,7 +3492,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
        s32 bssidx = 0;
        u32 p2pie_len = 0;
        u32 wpsie_len = 0;
+#ifdef WLWFDIE
        u32 wfdie_len = 0;
+#endif /* WLWFDIE */
        u32 id;
        u32 retry = 0;
        bool ack = false;
@@ -3414,11 +3544,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                                /* Total length of P2P Information Element */
                                p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
                        }
+#ifdef WLWFDIE
                        if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)(buf + ie_offset), ie_len))
                                != NULL) {
                                /* Total length of WFD Information Element */
                                wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
                        }
+#endif /* WLWFDIE */
                        if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
                                != NULL) {
                                /* Order of Vendor IE is 1) WPS IE +
@@ -3430,7 +3562,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                                        sizeof(wps_ie->tag);
                                wl_cfgp2p_set_management_ie(wl, dev, bssidx,
                                        VNDR_IE_PRBRSP_FLAG,
+#ifdef WLWFDIE
                                        (u8 *)wps_ie, wpsie_len + p2pie_len + wfdie_len);
+#else
+                                       (u8 *)wps_ie, wpsie_len + p2pie_len);
+#endif /* WLWFDIE */
                        }
                        cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
                        goto exit;
@@ -3443,8 +3579,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                        WL_DBG(("Disconnect STA : %s scb_val.val %d\n",
                                bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
                                scb_val.val));
-                       /* Wait for the deauth event to come, supplicant will do the delete iface immediately
-                        * and we will have problem in sending deauth frame if we delete the bss in firmware
+                       /* Wait for the deauth event to come, supplicant will do the
+                        * delete iface immediately and we will have problem in sending
+                        * deauth frame if we delete the bss in firmware
                         */
                        wl_delay(400);
                        cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
@@ -3513,6 +3650,36 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n",
                        action_frame->len, af_params->channel,
                        act_frm->category, act_frm->subtype));
+               if (act_frm && ((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_PROVDIS_REQ))) {
+                       wldev_iovar_setint(dev, "mpc", 0);
+               }
+
+               if (act_frm->subtype == P2P_PAF_GON_REQ) {
+                       WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
+                       wl_set_p2p_status(wl, GO_NEG_PHASE);
+               } else if (act_frm->subtype == P2P_PAF_GON_CONF) {
+                       /* If we reached till GO Neg confirmation
+                        * reset the filter
+                        */
+                       WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
+                       wl_clr_p2p_status(wl, GO_NEG_PHASE);
+               }
+
+               if (act_frm->subtype == P2P_PAF_GON_RSP)
+                       retry_cnt = 1;
+               else retry_cnt = WL_ACT_FRAME_RETRY;
+
+               if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) {
+                       af_params->dwell_time = WL_LONG_DWELL_TIME;
+               } else if (act_frm &&
+                       (act_frm->subtype == P2P_PAF_PROVDIS_REQ ||
+                       act_frm->subtype == P2P_PAF_PROVDIS_RSP ||
+                       act_frm->subtype == P2P_PAF_GON_RSP)) {
+                       af_params->dwell_time = WL_MED_DWELL_TIME;
+               }
        } else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) {
                p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data);
                WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n",
@@ -3523,32 +3690,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n",
                        action_frame->len, af_params->channel,
                        sd_act_frm->category, sd_act_frm->action));
-
+               af_params->dwell_time = WL_MED_DWELL_TIME;
+               retry_cnt = WL_ACT_FRAME_RETRY;
        }
        wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len);
        /*
         * To make sure to send successfully action frame, we have to turn off mpc
         */
-
-       if (act_frm && ((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_PROVDIS_REQ))) {
-               wldev_iovar_setint(dev, "mpc", 0);
-       }
-       if (act_frm->subtype == P2P_PAF_GON_RSP)
-               retry_cnt = 1;
-       else retry_cnt = WL_ACT_FRAME_RETRY;
-
-       if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) {
-               af_params->dwell_time = WL_LONG_DWELL_TIME;
-       } else if (act_frm &&
-               (act_frm->subtype == P2P_PAF_PROVDIS_REQ ||
-               act_frm->subtype == P2P_PAF_PROVDIS_RSP ||
-               act_frm->subtype == P2P_PAF_GON_RSP)) {
-               af_params->dwell_time = WL_MED_DWELL_TIME;
-       }
-
        if (IS_P2P_SOCIAL(af_params->channel) &&
                (IS_P2P_PUB_ACT_REQ(act_frm, &act_frm->elts[0], action_frame->len) ||
                IS_GAS_REQ(sd_act_frm, action_frame->len)) &&
@@ -3560,6 +3708,18 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
 
                /* channel offload for action request frame */
                ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
+               /* We need to retry Service discovery frames as they don't get retried immediately by supplicant*/
+               if ((!ack) && (IS_GAS_REQ(sd_act_frm, action_frame->len))) {
+                       for (retry = 1; retry < retry_cnt; retry++) {
+                               WL_DBG(("Service Discovery action_frame retry %d len: %d chan %d category %d action %d\n",
+                                       retry, action_frame->len, af_params->channel,
+                                       sd_act_frm->category, sd_act_frm->action));
+                               ack = (wl_cfgp2p_tx_action_frame(wl, dev,
+                                       af_params, bssidx)) ? false : true;
+                               if (ack)
+                                       break;
+                       }
+               }
        } else {
                ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true;
                if (!ack) {
@@ -3915,13 +4075,17 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
        wpa_ie_fixed_t *wpa_ie;
        bcm_tlv_t *wpa2_ie;
        wifi_p2p_ie_t *p2p_ie;
+#ifdef WLWFDIE
        wifi_wfd_ie_t *wfd_ie;
+#endif /* WLWFDIE */
        bool is_bssup = false;
        bool update_bss = false;
        bool pbc = false;
        u16 wpsie_len = 0;
        u16 p2pie_len = 0;
+#ifdef WLWFDIE
        u32 wfdie_len = 0;
+#endif /* WLWFDIE */
        u8 beacon_ie[IE_MAX_LEN];
        s32 ie_offset = 0;
        s32 bssidx = 0;
@@ -3979,24 +4143,30 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
                } else {
                        WL_ERR(("No P2PIE in beacon \n"));
                }
+#ifdef WLWFDIE
                /* find the WFD IEs */
                if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)info->tail, info->tail_len)) != NULL) {
-               /* Total length of P2P Information Element */
-               wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
-               if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) {
-                       memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len);
-               } else {
+                       /* Total length of P2P Information Element */
+                       wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+                       if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) {
+                               memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len);
+                       } else {
                                WL_ERR(("Found WFD IE but there is no space, (%d)(%d)(%d)\n",
-                               wpsie_len, p2pie_len, wfdie_len));
+                                       wpsie_len, p2pie_len, wfdie_len));
                                wfdie_len = 0;
                        }
                } else {
                        WL_ERR(("No WFDIE in beacon \n"));
                }
+#endif /* WLWFDIE */
                /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
                wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
                wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
+#ifdef WLWFDIE
                        beacon_ie, wpsie_len + p2pie_len + wfdie_len);
+#else
+                       beacon_ie, wpsie_len + p2pie_len);
+#endif /* WLWFDIE */
 
                /* find the RSN_IE */
                if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
@@ -4268,7 +4438,7 @@ exit:
 #ifdef WL_SCHED_SCAN
 #define PNO_TIME       30
 #define PNO_REPEAT     4
-#define PNO_FREQ_EXPO_MAX      3
+#define PNO_FREQ_EXPO_MAX      2
 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
                              struct net_device *dev,
                              struct cfg80211_sched_scan_request *request)
@@ -4615,8 +4785,13 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
                        kfree(notif_bss_info);
                        return err;
                }
+               else if( wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO) == NULL)
+               {
+                       WL_DBG(("Couldn't find P2P_SEID_DEV_INFO in probe response/beacon\n"));
+                       kfree(notif_bss_info);
+                       return err;
+               }
        }
-
        if (!mgmt->u.probe_resp.timestamp) {
                struct timeval tv;
 
@@ -4639,6 +4814,114 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
        return err;
 }
 
+static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid)
+{
+       struct net_device *ndev = wl_to_prmry_ndev(wl);
+       struct wiphy *wiphy = wl_to_wiphy(wl);
+       struct wl_bss_info *bi = NULL;
+       struct ieee80211_channel *notify_channel;
+       struct ieee80211_supported_band *band;
+       struct cfg80211_bss *bss;
+       s32 err = 0;
+       u16 channel;
+       u32 freq;
+       u32 wsec = 0;
+       u16 notify_capability;
+       u16 notify_interval;
+       u8 *notify_ie;
+       size_t notify_ielen;
+       s32 notify_signal;
+
+       WL_TRACE(("Enter\n"));
+
+       if (wl->scan_request) {
+               wl_notify_escan_complete(wl, ndev, true, true);
+       }
+
+       mutex_lock(&wl->usr_sync);
+
+       *(u32 *)wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+       err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, wl->extra_buf,
+                                       WL_EXTRA_BUF_MAX, false);
+       if (err) {
+               WL_ERR(("Failed to get bss info for IBSS\n"));
+               err = -EIO;
+               goto CleanUp;
+       }
+       bi = (struct wl_bss_info *)(wl->extra_buf + 4);
+
+       if (memcmp(bssid, &bi->BSSID, ETHER_ADDR_LEN)) {
+               WL_ERR(("BSSID mismatch: Inform %02x:%02x:%02x:%02x:%02x:%02x,"
+                                       "%02x:%02x:%02x:%02x:%02x:%02x\n",
+                                       bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5],
+                                       bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+                                       bi->BSSID.octet[3], bi->BSSID.octet[4],
+                                       bi->BSSID.octet[5]));
+               err = -EINVAL;
+               goto CleanUp;
+       }
+
+       err = wldev_iovar_getint(ndev, "wsec", &wsec);
+       if (err) {
+               WL_ERR(("wsec failed: %d\n", err));
+               err = -EIO;
+               goto CleanUp;
+       }
+
+       channel = bi->ctl_ch ? bi->ctl_ch :
+                               CHSPEC_CHANNEL(dtohchanspec(bi->chanspec));
+       if (channel <= CH_MAX_2G_CHANNEL)
+               band = wiphy->bands[IEEE80211_BAND_2GHZ];
+       else
+               band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
+       freq = ieee80211_channel_to_frequency(channel);
+       (void)band->band;
+#else
+       freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+       notify_channel = ieee80211_get_channel(wiphy, freq);
+
+       notify_capability = dtoh16(bi->capability);
+       notify_interval = dtoh16(bi->beacon_period);
+       notify_ie = (u8 *)bi + dtoh16(bi->ie_offset);
+       notify_ielen = dtoh32(bi->ie_length);
+       notify_signal = (int16)dtoh16(bi->RSSI) * 100;
+
+       if (wl->p2p_supported) {
+               notify_capability |= DOT11_CAP_IBSS;
+               if (wsec)
+                       notify_capability |= DOT11_CAP_PRIVACY;
+       }
+
+       WL_DBG(("BSSID %02x:%02x:%02x:%02x:%02x:%02x",
+                       bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]));
+       WL_INFO(("channel: %d(%d)\n", channel, freq));
+       WL_INFO(("capability: %X\n", notify_capability));
+       WL_INFO(("beacon interval: %d ms\n", notify_interval));
+       WL_INFO(("signal: %d dBm\n", notify_signal));
+       WL_INFO(("ie_len: %d\n", notify_ielen));
+       bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, 0,
+                               notify_capability, notify_interval,
+                               notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
+       if (!bss) {
+               WL_ERR(("cfg80211_inform_bss() Failed\n"));
+               err = -ENOMEM;
+               goto CleanUp;
+       }
+
+       cfg80211_put_bss(bss);
+       err = 0;
+
+CleanUp:
+
+       mutex_unlock(&wl->usr_sync);
+
+       WL_TRACE(("Exit\n"));
+       return err;
+}
+
 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
 {
        u32 event = ntoh32(e->event_type);
@@ -4648,12 +4931,12 @@ static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net
        WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
        if (event == WLC_E_SET_SSID) {
                if (status == WLC_E_STATUS_SUCCESS) {
-                       if (!wl_is_ibssmode(wl, ndev))
-                               return true;
+                       return true;
                }
        } else if (event == WLC_E_LINK) {
                if (flags & WLC_EVENT_MSG_LINK)
-                       return true;
+                       if (!wl_is_ibssmode(wl, ndev))
+                               return true;
        }
 
        WL_DBG(("wl_is_linkup false\n"));
@@ -4834,7 +5117,9 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
                if((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DISASSOC_IND)) {
                        reason = ntoh32(e->reason);
                        wl->deauth_reason = reason;
-                       WL_ERR(("Received %s event with reason code: %d\n", (event == WLC_E_DEAUTH_IND)? "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason));
+                       WL_ERR(("Received %s event with reason code: %d\n",
+                       (event == WLC_E_DEAUTH_IND)?
+                       "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason));
                }
                if (wl_is_linkup(wl, e, ndev)) {
                        wl_link_up(wl);
@@ -4843,10 +5128,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
                        wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
                        wl->deauth_reason = 0;
                        if (wl_is_ibssmode(wl, ndev)) {
-                               printk("cfg80211_ibss_joined\n");
-                               cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
-                                       GFP_KERNEL);
-                               WL_DBG(("joined in IBSS network\n"));
+                               wl_ibss_join_done(wl, ndev, e, data, true);
+                               WL_DBG(("wl_ibss_join_done succeeded\n"));
                        } else {
                                if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
                                        printk("wl_bss_connect_done succeeded\n");
@@ -4856,7 +5139,6 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
                                         wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
                                }
                        }
-
                } else if (wl_is_linkdown(wl, e)) {
                        if (wl->scan_request) {
                                if (wl->escan_on) {
@@ -4880,15 +5162,21 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
                                        scbval.val = htod32(scbval.val);
                                        wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
                                                sizeof(scb_val_t), true);
-                                       WL_ERR(("link down, calling cfg80211_disconnected with deauth_reason:%d\n", wl->deauth_reason));
-                                       cfg80211_disconnected(ndev, wl->deauth_reason , NULL, 0, GFP_KERNEL);
+                                       WL_ERR(("link down, calling cfg80211_disconnected"
+                                       " with deauth_reason:%d\n", wl->deauth_reason));
+                                       if (!wl_is_ibssmode(wl, ndev))
+                                               cfg80211_disconnected(ndev, wl->deauth_reason,
+                                                       NULL, 0, GFP_KERNEL);
                                        wl_link_down(wl);
                                        wl_init_prof(wl, ndev);
                                }
                        }
                        else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
                                printk("link down, during connecting\n");
-                               wl_bss_connect_done(wl, ndev, e, data, false);
+                               if (wl_is_ibssmode(wl, ndev))
+                                       wl_ibss_join_done(wl, ndev, e, data, false);
+                               else
+                                       wl_bss_connect_done(wl, ndev, e, data, false);
                        }
                        wl_clr_drv_status(wl, DISCONNECTING, ndev);
 
@@ -5184,6 +5472,35 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
 }
 
 static s32
+wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev,
+       const wl_event_msg_t *e, void *data, bool completed)
+{
+       s32 err = 0;
+
+       WL_TRACE(("Enter\n"));
+
+       if (wl->scan_request) {
+               wl_notify_escan_complete(wl, ndev, true, true);
+       }
+       if (wl_get_drv_status(wl, CONNECTING, ndev)) {
+               wl_clr_drv_status(wl, CONNECTING, ndev);
+               if (completed) {
+                       err = wl_inform_ibss(wl, (u8 *)&e->addr);
+                       if (err) {
+                               WL_ERR(("wl_inform_ibss() failed: %d\n", err));
+                       }
+                       wl_set_drv_status(wl, CONNECTED, ndev);
+
+                       cfg80211_ibss_joined(ndev, (u8 *)&e->addr, GFP_KERNEL);
+                       WL_DBG(("cfg80211_ibss_joined() called with valid BSSID\n"));
+               }
+       }
+
+       WL_TRACE(("Exit\n"));
+       return err;
+}
+
+static s32
 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
        const wl_event_msg_t *e, void *data)
 {
@@ -5365,6 +5682,13 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
                WL_ERR(("No valid band"));
                return -EINVAL;
        }
+
+       if ((event == WLC_E_P2P_PROBREQ_MSG) &&
+               wl->p2p && wl_get_p2p_status(wl, GO_NEG_PHASE)) {
+               WL_DBG(("Filtering P2P probe_req while being in GO-Neg state\n"));
+               goto exit;
+       }
+
 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
        freq = ieee80211_channel_to_frequency(channel);
 #else
@@ -5409,6 +5733,11 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
                        (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
                        wldev_iovar_setint(dev, "mpc", 1);
                }
+
+               if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
+                       WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
+                       wl_clr_p2p_status(wl, GO_NEG_PHASE);
+               }
        } else {
                mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
        }
@@ -6044,7 +6373,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
        wl_scan_results_t *list;
        u32 bi_length;
        u32 i;
-
+       u8 *p2p_dev_addr = NULL;
        WL_DBG((" enter event type : %d, status : %d \n",
                ntoh32(e->event_type), ntoh32(e->status)));
        /* P2P SCAN is coming from primary interface */
@@ -6086,16 +6415,18 @@ static s32 wl_escan_handler(struct wl_priv *wl,
 
                if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
                        if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
-                               WL_ERR(("Ignoring IBSS result\n"));
+                               WL_DBG(("Ignoring IBSS result\n"));
                                goto exit;
                        }
                }
 
                if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
-                       if (!memcmp(bi->BSSID.octet,
+                       p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
+                       if (p2p_dev_addr && !memcmp(p2p_dev_addr,
                                wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) {
                                s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec));
-                               WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel));
+                               WL_DBG(("ACTION FRAME SCAN : Peer " MACSTR " found, channel : %d\n",
+                                       MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), channel));
                                wl_clr_p2p_status(wl, SCANNING);
                                wl->afx_hdl->peer_chan = channel;
                                complete(&wl->act_frm_scan);
@@ -6721,20 +7052,148 @@ eventmsg_out:
 
 }
 
+static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
+{
+       struct net_device *dev = wl_to_prmry_ndev(wl);
+       struct ieee80211_channel *band_chan_arr = NULL;
+       wl_uint32_list_t *list;
+       u32 i, j, index, n_2g, n_5g, band, channel, array_size;
+       u32 *n_cnt = NULL;
+       chanspec_t c = 0;
+       s32 err = BCME_OK;
+       bool update;
+       bool ht40_allowed;
+       u8 *pbuf = NULL;
+
+#define LOCAL_BUF_LEN 1024
+       pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
+       if (pbuf == NULL) {
+               WL_ERR(("failed to allocate local buf\n"));
+               return -ENOMEM;
+       }
+
+       list = (wl_uint32_list_t *)(void *)pbuf;
+       list->count = htod32(WL_NUMCHANSPECS);
+
+       err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
+               0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
+       if (err != 0) {
+               WL_ERR(("get chanspecs failed with %d\n", err));
+               kfree(pbuf);
+               return err;
+       }
+#undef LOCAL_BUF_LEN
+
+       band = array_size = n_2g = n_5g = 0;
+       for (i = 0; i < dtoh32(list->count); i++) {
+               index = 0;
+               update = FALSE;
+               ht40_allowed = FALSE;
+               c = (chanspec_t)dtoh32(list->element[i]);
+               channel = CHSPEC_CHANNEL(c);
+               if (CHSPEC_IS40(c)) {
+                       if (CHSPEC_SB_UPPER(c))
+                               channel += CH_10MHZ_APART;
+                       else
+                               channel -= CH_10MHZ_APART;
+               }
+
+               if (CHSPEC_IS2G(c) && channel <= CH_MAX_2G_CHANNEL) {
+                       band_chan_arr = __wl_2ghz_channels;
+                       array_size = ARRAYSIZE(__wl_2ghz_channels);
+                       n_cnt = &n_2g;
+                       band = IEEE80211_BAND_2GHZ;
+                       ht40_allowed = (bw_cap == WLC_N_BW_40ALL) ? TRUE : FALSE;
+               } else if (CHSPEC_IS5G(c) && channel > CH_MAX_2G_CHANNEL) {
+                       band_chan_arr = __wl_5ghz_a_channels;
+                       array_size = ARRAYSIZE(__wl_5ghz_a_channels);
+                       n_cnt = &n_5g;
+                       band = IEEE80211_BAND_5GHZ;
+                       ht40_allowed = (bw_cap == WLC_N_BW_20ALL) ? FALSE : TRUE;
+               }
+
+               for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
+                       if (band_chan_arr[j].hw_value == channel) {
+                               update = TRUE;
+                               break;
+                       }
+               }
+
+               if (update)
+                       index = j;
+               else
+                       index = *n_cnt;
+
+               if (index <  array_size) {
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
+                       band_chan_arr[index].center_freq =
+                               ieee80211_channel_to_frequency(channel);
+#else
+                       band_chan_arr[index].center_freq =
+                               ieee80211_channel_to_frequency(channel, band);
+#endif
+                       band_chan_arr[index].hw_value = channel;
+
+                       if (CHSPEC_IS40(c) && ht40_allowed) {
+                               u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
+                               if (CHSPEC_SB_UPPER(c)) {
+                                       if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+                                               band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
+                                       band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
+                               } else {
+                                       band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
+                                       if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+                                               band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40MINUS;
+                               }
+                       } else {
+                               band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
+                               if (band == IEEE80211_BAND_2GHZ)
+                                       channel |= WL_CHANSPEC_BAND_2G;
+                               else
+                                       channel |= WL_CHANSPEC_BAND_5G;
+                                       err = wldev_iovar_getint(dev, "per_chan_info", &channel);
+                               if (!err) {
+                                       if (channel & WL_CHAN_RADAR) {
+                                               band_chan_arr[index].flags |= IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS;
+                                       }
+                                       if (channel & WL_CHAN_PASSIVE) {
+                                               band_chan_arr[index].flags |= IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS;
+                                       }
+                               }
+                       }
+
+                       if (!update)
+                               (*n_cnt)++;
+               }
+       }
+
+       __wl_band_2ghz.n_channels = n_2g;
+       __wl_band_5ghz_a.n_channels = n_5g;
+
+       kfree(pbuf);
+       return err;
+}
+
 s32 wl_update_wiphybands(struct wl_priv *wl)
 {
        struct wiphy *wiphy;
+       struct net_device *dev;
        u32 bandlist[3];
        u32 nband = 0;
        u32 i = 0;
        s32 err = 0;
        int nmode = 0;
-       int bw_40 = 0;
+       int bw_cap = 0;
        int index = 0;
 
        WL_DBG(("Entry"));
+
+       if (wl == NULL)
+               wl = wlcfg_drv_priv;
+       dev = wl_to_prmry_ndev(wl);
+
        memset(bandlist, 0, sizeof(bandlist));
-       err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist,
+       err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
                sizeof(bandlist), false);
        if (unlikely(err)) {
                WL_ERR(("error read bandlist (%d)\n", err));
@@ -6745,41 +7204,44 @@ s32 wl_update_wiphybands(struct wl_priv *wl)
        wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
        wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
 
-       err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "nmode", &nmode);
+       err = wldev_iovar_getint(dev, "nmode", &nmode);
        if (unlikely(err)) {
                WL_ERR(("error reading nmode (%d)\n", err));
-       }
-       else {
+       } else {
                /* For nmodeonly  check bw cap */
-               err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "mimo_bw_cap", &bw_40);
+               err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
                if (unlikely(err)) {
                        WL_ERR(("error get mimo_bw_cap (%d)\n", err));
                }
        }
 
+       err = wl_construct_reginfo(wl, bw_cap);
+       if (err) {
+               WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
+               return err;
+       }
        for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) {
                index = -1;
-               if (bandlist[i] == WLC_BAND_5G) {
+               if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
                        wiphy->bands[IEEE80211_BAND_5GHZ] =
                                &__wl_band_5ghz_a;
-                               index = IEEE80211_BAND_5GHZ;
-               } else if (bandlist[i] == WLC_BAND_2G) {
+                       index = IEEE80211_BAND_5GHZ;
+                       if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
+                               wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+               } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
                        wiphy->bands[IEEE80211_BAND_2GHZ] =
                                &__wl_band_2ghz;
-                               index = IEEE80211_BAND_2GHZ;
+                       index = IEEE80211_BAND_2GHZ;
+                       if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL)
+                               wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
                }
                if ((index >= 0) && nmode) {
-                       wiphy->bands[index]->ht_cap.cap =
-                               IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 |
-                               IEEE80211_HT_CAP_MAX_AMSDU;
+                       wiphy->bands[index]->ht_cap.cap |=
+                               IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40;
                        wiphy->bands[index]->ht_cap.ht_supported = TRUE;
                        wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
                        wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
                }
-
-               if ((index >= 0) && bw_40) {
-                       wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-               }
        }
 
        wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
@@ -7106,8 +7568,7 @@ static void wl_init_eq_lock(struct wl_priv *wl)
 
 static void wl_delay(u32 ms)
 {
-       if (ms < 1000 / HZ) {
-               cond_resched();
+       if (in_atomic() || ms < 1000 / HZ) {
                mdelay(ms);
        } else {
                msleep(ms);
@@ -7162,17 +7623,44 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
 {
        struct wl_priv *wl;
        struct net_device *ndev = NULL;
+       struct ether_addr primary_mac;
        s32 ret = 0;
        s32 bssidx = 0;
        s32 pktflag = 0;
        wl = wlcfg_drv_priv;
-       if (wl->p2p && wl->p2p->vif_created) {
-               ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
-               bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
-       } else if (wl_get_drv_status(wl, AP_CREATING, net) ||
+
+       if (wl_get_drv_status(wl, AP_CREATING, net) ||
                wl_get_drv_status(wl, AP_CREATED, net)) {
                ndev = net;
                bssidx = 0;
+       } else if (wl->p2p) {
+          if (net == wl->p2p_net) {
+                       net = wl_to_prmry_ndev(wl);
+               }
+
+               if (!wl->p2p->on) {
+                       get_primary_mac(wl, &primary_mac);
+                       wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
+                               &wl->p2p->int_addr);
+                       /* In case of p2p_listen command, supplicant send remain_on_channel
+                       * without turning on P2P
+                       */
+                       p2p_on(wl) = true;
+                       ret = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
+
+                       if (unlikely(ret)) {
+                               goto exit;
+                       }
+               }
+               if (net  != wl_to_prmry_ndev(wl)) {
+                       if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
+                               ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
+                               bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
+                       }
+               } else {
+                               ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
+                               bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
+               }
        }
        if (ndev != NULL) {
                switch (type) {
@@ -7189,7 +7677,7 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
                if (pktflag)
                        ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
        }
-
+exit:
        return ret;
 }
 
index fba8531..37c8e58 100644 (file)
@@ -136,6 +136,12 @@ do {                                                                       \
 
 #define WL_INVALID             -1
 
+
+/* Bring down SCB Timeout to 20secs from 60secs default */
+#ifndef WL_SCB_TIMEOUT
+#define WL_SCB_TIMEOUT 20
+#endif
+
 /* driver status */
 enum wl_status {
        WL_STATUS_READY = 0,
@@ -662,5 +668,6 @@ extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
 extern s32 wl_mode_to_nl80211_iftype(s32 mode);
 int wl_cfg80211_do_driver_init(struct net_device *net);
 void wl_cfg80211_enable_trace(int level);
+extern s32 wl_update_wiphybands(struct wl_priv *wl);
 extern s32 wl_cfg80211_if_is_group_owner(void);
 #endif                         /* _wl_cfg80211_h_ */
index a34c4ad..318e122 100644 (file)
@@ -59,6 +59,8 @@ static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
 static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
 static int wl_cfgp2p_if_open(struct net_device *net);
 static int wl_cfgp2p_if_stop(struct net_device *net);
+static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev,
+       bool notify);
 
 static const struct net_device_ops wl_cfgp2p_if_ops = {
        .ndo_open               = wl_cfgp2p_if_open,
@@ -338,6 +340,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
        wl_p2p_if_t ifreq;
        s32 err;
        struct net_device *ndev = wl_to_prmry_ndev(wl);
+       u32 scb_timeout = WL_SCB_TIMEOUT;
 
        ifreq.type = if_type;
        ifreq.chspec = chspec;
@@ -351,6 +354,15 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
 
        err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
                wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
+
+       if (unlikely(err < 0)) {
+               printk("'wl p2p_ifadd' error %d\n", err);
+       } else if (if_type == WL_P2P_IF_GO) {
+               err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
+               if (unlikely(err < 0))
+                       printk("'wl scb_timeout' error %d\n", err);
+       }
+
        return err;
 }
 
@@ -387,6 +399,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
 {
        wl_p2p_if_t ifreq;
        s32 err;
+       u32 scb_timeout = WL_SCB_TIMEOUT;
        struct net_device *netdev =  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
 
        ifreq.type = if_type;
@@ -404,6 +417,10 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
 
        if (unlikely(err < 0)) {
                printk("'wl p2p_ifupd' error %d\n", err);
+       } else if (if_type == WL_P2P_IF_GO) {
+               err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
+               if (unlikely(err < 0))
+                       printk("'wl scb_timeout' error %d\n", err);
        }
        return err;
 }
@@ -829,10 +846,12 @@ exit:
 /* Check whether the given IE looks like WFA P2P IE. */
 #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)     wl_cfgp2p_has_ie(ie, tlvs, len, \
                (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
-/* Check whether the given IE looks like WFA WFDisplay IE. */
-#define WFA_OUI_TYPE_WFD       0x0a    /* WiFi Display OUI TYPE */
-#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)     wl_cfgp2p_has_ie(ie, tlvs, len, \
-               (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
+#ifdef WLWFDIE
+ /* Check whether the given IE looks like WFA WFDisplay IE. */
+#define WFA_OUI_TYPE_WFD                0x0a    /* WiFi Display OUI TYPE */
+#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)      wl_cfgp2p_has_ie(ie, tlvs, len, \
+                (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
+#endif /* WLWFDIE */
 /* Delete and Set a management vndr ie to firmware
  * Parameters:
  * @wl       : wl_private data
@@ -957,8 +976,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
                                ie_len = ie_buf[pos++];
                                if ((ie_id == DOT11_MNG_VS_ID) &&
                                   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
+#ifdef WLWFDIE
                                        wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
                                        wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
+#else
+                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+#endif /* WLWFDIE */
                                        CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :"
                                                "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
                                                ie_buf[pos+1], ie_buf[pos+2]));
@@ -984,8 +1007,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
                                ie_len = ie_buf[pos++];
                                if ((ie_id == DOT11_MNG_VS_ID) &&
                                   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
+#ifdef WLWFDIE
                                        wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
                                        wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
+#else
+                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+#endif /* WLWFDIE */
                                        CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :"
                                                "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
                                                ie_buf[pos+1], ie_buf[pos+2]));
@@ -1095,18 +1122,21 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
        }
        return NULL;
 }
+
+#ifdef WLWFDIE
 wifi_wfd_ie_t *
 wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
 {
        bcm_tlv_t *ie;
 
        while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
-       if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
+               if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
                        return (wifi_wfd_ie_t *)ie;
                }
        }
        return NULL;
 }
+#endif /* WLWFDIE */
 
 static s32
 wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
@@ -1230,6 +1260,7 @@ wl_cfgp2p_listen_expired(unsigned long data)
        struct wl_priv *wl = (struct wl_priv *) data;
 
        CFGP2P_DBG((" Enter\n"));
+       memset(&msg, 0, sizeof(wl_event_msg_t));
        msg.event_type =  hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
        wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
 }
@@ -1237,7 +1268,7 @@ wl_cfgp2p_listen_expired(unsigned long data)
 /*
  *  Routine for cancelling the P2P LISTEN
  */
-s32
+static s32
 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev,
                          bool notify)
 {
@@ -1402,13 +1433,12 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
                wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
 
        if (ret < 0) {
-
                CFGP2P_ERR((" sending action frame is failed\n"));
                goto exit;
        }
        timeout = wait_event_interruptible_timeout(wl->netif_change_event,
-       (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 668198d..40d9e54 100644 (file)
 
 struct wl_priv;
 extern u32 wl_dbg_level;
+
+#ifdef WLWFDIE
 typedef struct wifi_p2p_ie wifi_wfd_ie_t;
+#endif /* WLWFDIE */
+
 /* Enumeration of the usages of the BSSCFGs used by the P2P Library.  Do not
  * confuse this with a bsscfg index.  This value is an index into the
  * saved_ie[] array of structures which in turn contains a bsscfg index field.
@@ -42,7 +46,7 @@ typedef enum {
        P2PAPI_BSSCFG_MAX
 } p2p_bsscfg_type_t;
 
-#define IE_MAX_LEN 300
+#define IE_MAX_LEN 512
 /* Structure to hold all saved P2P and WPS IEs for a BSSCFG */
 struct p2p_saved_ie {
        u8  p2p_probe_req_ie[IE_MAX_LEN];
@@ -91,7 +95,8 @@ enum wl_cfgp2p_status {
        WLP2P_STATUS_LISTEN_EXPIRED,
        WLP2P_STATUS_ACTION_TX_COMPLETED,
        WLP2P_STATUS_ACTION_TX_NOACK,
-       WLP2P_STATUS_SCANNING
+       WLP2P_STATUS_SCANNING,
+       WLP2P_STATUS_GO_NEG_PHASE
 };
 
 
@@ -191,8 +196,10 @@ wl_cfgp2p_find_wpsie(u8 *parse, u32 len);
 extern wifi_p2p_ie_t *
 wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
 
+#ifdef WLWFDIE
 extern wifi_wfd_ie_t *
 wl_cfgp2p_find_wfdie(u8 *parse, u32 len);
+#endif /* WLWFDIE */
 
 extern s32
 wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
index 0599293..6bb0765 100644 (file)
@@ -6341,6 +6341,7 @@ wl_iw_set_cscan(
                        else {
                                WL_ERROR(("%s Ignoring CSCAN : First Scan is not done yet %d\n",
                                        __FUNCTION__, g_first_counter_scans));
+                               res = -EBUSY;
                                goto exit_proc;
                        }
                }