net: wireless: bcmdhd: Update to Version 5.90.125.87
authorDmitry Shmidt <dimitrysh@google.com>
Wed, 21 Sep 2011 20:09:58 +0000 (13:09 -0700)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 20:24:21 +0000 (12:24 -0800)
- Improve discovery of FW hanging
- Add WFD noa and power-safe related functions

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcmdhd/dhd.h
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_android.c
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 5d9e678..ac374af 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,v 1.60.4.17 2011-01-09 08:11:56 Exp $
+ * $Id: dhd.h 285209 2011-09-21 01:21:24Z $
  */
 
 /****************
@@ -80,6 +80,9 @@ enum dhd_bus_state {
 #define WFD_MASK                       0x0004
 #define SOFTAP_FW_MASK                 0x0008
 
+/* max sequential rxcntl timeouts to set HANG event */
+#define MAX_CNTL_TIMEOUT  2
+
 enum dhd_bus_wake_state {
        WAKE_LOCK_OFF,
        WAKE_LOCK_PRIV,
@@ -96,6 +99,7 @@ enum dhd_bus_wake_state {
        WAKE_LOCK_SOFTAP_THREAD,
        WAKE_LOCK_MAX
 };
+
 enum dhd_prealloc_index {
        DHD_PREALLOC_PROT = 0,
        DHD_PREALLOC_RXBUF,
@@ -121,6 +125,7 @@ void dhd_os_prefree(void *osh, void *addr, uint size);
 #ifndef DHD_SDALIGN
 #define DHD_SDALIGN    32
 #endif
+
 /* Common structure for module and instance linkage */
 typedef struct dhd_pub {
        /* Linkage ponters */
@@ -203,6 +208,8 @@ typedef struct dhd_pub {
 #endif
        bool    dongle_isolation;
        int   hang_was_sent;
+       int   rxcnt_timeout;            /* counter rxcnt timeout to send HANG */
+       int   txcnt_timeout;            /* counter txcnt timeout to send HANG */
 #ifdef WLMEDIA_HTSF
        uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */
 #endif
@@ -296,6 +303,7 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
 #define DHD_OS_WAKE_UNLOCK(pub)                dhd_os_wake_unlock(pub)
 #define DHD_OS_WAKE_LOCK_TIMEOUT(pub)          dhd_os_wake_lock_timeout(pub)
 #define DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(pub, val)      dhd_os_wake_lock_timeout_enable(pub, val)
+
 #define DHD_PACKET_TIMEOUT     1
 #define DHD_EVENT_TIMEOUT      2
 
@@ -468,6 +476,7 @@ 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 */
@@ -707,4 +716,5 @@ void dhd_aoe_arp_clr(dhd_pub_t *dhd);
 int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen);
 void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr);
 #endif /* ARP_OFFLOAD_SUPPORT */
+
 #endif /* _dhd_h_ */
index 146b7a7..8496f17 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,v 1.57.2.22 2011-02-01 18:38:37 Exp $
+ * $Id: dhd_common.c 284903 2011-09-20 02:36:51Z $
  */
 #include <typedefs.h>
 #include <osl.h>
@@ -484,7 +484,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
 #endif /* PROP_TXSTATUS */
 
        case IOV_GVAL(IOV_BUS_TYPE):
-       /* The dhd application query the driver to check if its usb or sdio.  */
+               /* The dhd application queries the driver to check if its usb or sdio.  */
 #ifdef BCMDHDUSB
                int_val = BUS_TYPE_USB;
 #endif
@@ -1004,27 +1004,27 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
 
        case WLC_E_IF:
                {
-               dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data;
+                       dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data;
 #ifdef PROP_TXSTATUS
-{
-               uint8* ea = pvt_data->eth.ether_dhost;
-               WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, "
-                             "[%02x:%02x:%02x:%02x:%02x:%02x]\n",
-                             ifevent->ifidx,
-                             ((ifevent->action == WLC_E_IF_ADD) ? "ADD":"DEL"),
-                             ((ifevent->is_AP == 0) ? "STA":"AP "),
-                             ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]));
-               (void)ea;
-
-               dhd_wlfc_interface_event(dhd_pub->info,
-                                        ((ifevent->action == WLC_E_IF_ADD) ?
-                                         eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL),
-                                        ifevent->ifidx, ifevent->is_AP, ea);
-
-               /* dhd already has created an interface by default, for 0 */
-               if (ifevent->ifidx == 0)
-                       break;
-}
+                       {
+                               uint8* ea = pvt_data->eth.ether_dhost;
+                               WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, "
+                                               "[%02x:%02x:%02x:%02x:%02x:%02x]\n",
+                                               ifevent->ifidx,
+                                               ((ifevent->action == WLC_E_IF_ADD) ? "ADD":"DEL"),
+                                               ((ifevent->is_AP == 0) ? "STA":"AP "),
+                                               ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]));
+                               (void)ea;
+
+                               dhd_wlfc_interface_event(dhd_pub->info,
+                                       ((ifevent->action == WLC_E_IF_ADD) ?
+                                       eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL),
+                                       ifevent->ifidx, ifevent->is_AP, ea);
+
+                               /* dhd already has created an interface by default, for 0 */
+                               if (ifevent->ifidx == 0)
+                                       break;
+                       }
 #endif /* PROP_TXSTATUS */
 
 #ifdef WL_CFG80211
@@ -1032,7 +1032,7 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
                                DHD_ERROR(("%s:  ifidx %d for %s action %d\n",
                                        __FUNCTION__, ifevent->ifidx,
                                        event->ifname, ifevent->action));
-                       if (ifevent->action == WLC_E_IF_ADD)
+                               if (ifevent->action == WLC_E_IF_ADD)
                                        wl_cfg80211_notify_ifchange();
                                return (BCME_OK);
                        }
@@ -1868,7 +1868,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
        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) {
@@ -1906,6 +1906,7 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
                DHD_ERROR(("%s error exit\n", __FUNCTION__));
                err = -1;
        }
+
        if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
                return (err);
 
@@ -2016,13 +2017,13 @@ dhd_pno_get_status(dhd_pub_t *dhd)
 #if defined(KEEP_ALIVE)
 int dhd_keep_alive_onoff(dhd_pub_t *dhd)
 {
-       char                    buf[256];
-       const char              *str;
+       char                            buf[256];
+       const char                      *str;
        wl_mkeep_alive_pkt_t    mkeep_alive_pkt;
        wl_mkeep_alive_pkt_t    *mkeep_alive_pktp;
-       int                     buf_len;
-       int                     str_len;
-       int res                 = -1;
+       int                                     buf_len;
+       int                                     str_len;
+       int res                                 = -1;
 
        if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
                return (res);
index 6a69b2b..0233189 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,v 1.131.2.55 2011-02-09 05:31:56 Exp $
+ * $Id: dhd_linux.c 285209 2011-09-21 01:21:24Z $
  */
 
 #include <typedefs.h>
@@ -1986,6 +1986,20 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr)
 }
 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
 
+static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
+{
+       dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
+
+       if ((error == -ETIMEDOUT) || ((dhd->pub.busstate == DHD_BUS_DOWN) &&
+               (!dhd->pub.dongle_reset))) {
+               DHD_ERROR(("%s: Event HANG send up due to  re=%d te=%d e=%d s=%d\n", __FUNCTION__,
+                       dhd->pub.rxcnt_timeout, dhd->pub.txcnt_timeout, error, dhd->pub.busstate));
+               net_os_send_hang_message(net);
+               return TRUE;
+       }
+       return FALSE;
+}
+
 static int
 dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
 {
@@ -2036,6 +2050,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
 
        if (cmd == SIOCDEVPRIVATE+1) {
                ret = wl_android_priv_cmd(net, ifr, cmd);
+               dhd_check_hang(net, &dhd->pub, ret);
                DHD_OS_WAKE_UNLOCK(&dhd->pub);
                return ret;
        }
@@ -2173,11 +2188,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
        bcmerror = dhd_wl_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
 
 done:
-       if ((bcmerror == -ETIMEDOUT) || ((dhd->pub.busstate == DHD_BUS_DOWN) &&
-               (!dhd->pub.dongle_reset))) {
-               DHD_ERROR(("%s: Event HANG send up\n", __FUNCTION__));
-               net_os_send_hang_message(net);
-       }
+       dhd_check_hang(net, &dhd->pub, bcmerror);
 
        if (!bcmerror && buf && ioc.buf) {
                if (copy_to_user(ioc.buf, buf, buflen))
@@ -2270,6 +2281,8 @@ dhd_stop(struct net_device *net)
                wl_android_wifi_off(net);
 #endif
        dhd->pub.hang_was_sent = 0;
+       dhd->pub.rxcnt_timeout = 0;
+       dhd->pub.txcnt_timeout = 0;
        OLD_MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -4504,6 +4517,7 @@ int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd)
 
        DHD_OS_WAKE_LOCK(&dhd->pub);
        ret = dhd_wl_ioctl(&dhd->pub, ifidx, ioc, ioc->buf, ioc->len);
+       dhd_check_hang(net, &dhd->pub, ret);
        DHD_OS_WAKE_UNLOCK(&dhd->pub);
 
        return ret;
index 37ab680..b79ef44 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_sdio.c,v 1.274.2.40 2011-02-09 22:42:44 Exp $
+ * $Id: dhd_sdio.c 285209 2011-09-21 01:21:24Z $
  */
 
 #include <typedefs.h>
@@ -422,6 +422,11 @@ do { \
        } \
 } while (0)
 
+#define BUS_WAKE(bus) \
+       do { \
+               if ((bus)->sleeping) \
+                       dhdsdio_bussleep((bus), FALSE); \
+       } while (0);
 
 /*
  * pktavail interrupts from dongle to host can be managed in 3 different ways
@@ -920,13 +925,6 @@ dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
 }
 #endif /* defined(OOB_INTR_ONLY) */
 
-#define BUS_WAKE(bus) \
-       do { \
-               if ((bus)->sleeping) \
-                       dhdsdio_bussleep((bus), FALSE); \
-       } while (0);
-
-
 /* Writes a HW/SW header into the packet and sends it. */
 /* Assumes: (a) header space already there, (b) caller holds lock */
 static int
@@ -1375,14 +1373,18 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
                        DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
                        ret = 0;
                } else {
+                       bus->dhd->txcnt_timeout++;
                        if (!bus->dhd->hang_was_sent)
-                               DHD_ERROR(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
+                               DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
+                                       __FUNCTION__, bus->dhd->txcnt_timeout));
                        ret = -1;
                        bus->ctrl_frame_stat = FALSE;
                        goto done;
                }
        }
 
+       bus->dhd->txcnt_timeout = 0;
+
        if (ret == -1) {
 #ifdef DHD_DEBUG
                if (DHD_BYTES_ON() && DHD_CTL_ON()) {
@@ -1440,6 +1442,9 @@ done:
        else
                bus->dhd->tx_ctlpkts++;
 
+       if (bus->dhd->txcnt_timeout >= MAX_CNTL_TIMEOUT)
+               return -ETIMEDOUT;
+
        return ret ? -EIO : 0;
 }
 
@@ -1485,13 +1490,22 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
                dhd_os_sdunlock(bus->dhd);
 #endif /* DHD_DEBUG */
        }
+       if (timeleft == 0) {
+               bus->dhd->rxcnt_timeout++;
+               DHD_ERROR(("%s: rxcnt_timeout=%d\n", __FUNCTION__, bus->dhd->rxcnt_timeout));
+       }
+       else
+               bus->dhd->rxcnt_timeout = 0;
 
        if (rxlen)
                bus->dhd->rx_ctlpkts++;
        else
                bus->dhd->rx_ctlerrs++;
 
-       return rxlen ? (int)rxlen : -ETIMEDOUT;
+       if (bus->dhd->rxcnt_timeout >= MAX_CNTL_TIMEOUT)
+               return -ETIMEDOUT;
+
+       return rxlen ? (int)rxlen : -EIO;
 }
 
 /* IOVar table */
index 60f842c..63db714 100644 (file)
@@ -19,7 +19,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: epivers.h.in,v 13.32.4.1 2010-09-17 00:39:18 Exp $
+ * $Id: epivers.h.in,v 13.32.4.1 2010-09-17 00:39:18 $
  *
 */
 
 
 #define        EPI_RC_NUMBER           125
 
-#define        EPI_INCREMENTAL_NUMBER  84
+#define        EPI_INCREMENTAL_NUMBER  87
 
 #define        EPI_BUILD_NUMBER        0
 
-#define        EPI_VERSION             5, 90, 125, 84
+#define        EPI_VERSION             5, 90, 125, 87
 
-#define        EPI_VERSION_NUM         0x055a7d54
+#define        EPI_VERSION_NUM         0x055a7d57
 
 #define EPI_VERSION_DEV                5.90.125
 
 
-#define        EPI_VERSION_STR         "5.90.125.84"
+#define        EPI_VERSION_STR         "5.90.125.87"
 
 #endif 
index 8bc6b36..8c0e3ae 100644 (file)
@@ -36,7 +36,9 @@
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <bcmsdbus.h>
-
+#ifdef WL_CFG80211
+#include <wl_cfg80211.h>
+#endif
 #if defined(CONFIG_WIFI_CONTROL_FUNC)
 #include <linux/platform_device.h>
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
  * so they can be updated easily in the future (if needed)
  */
 
-#define CMD_START              "START"
-#define CMD_STOP               "STOP"
-#define        CMD_SCAN_ACTIVE         "SCAN-ACTIVE"
-#define        CMD_SCAN_PASSIVE        "SCAN-PASSIVE"
-#define CMD_RSSI               "RSSI"
-#define CMD_LINKSPEED          "LINKSPEED"
-#define CMD_RXFILTER_START     "RXFILTER-START"
-#define CMD_RXFILTER_STOP      "RXFILTER-STOP"
-#define CMD_RXFILTER_ADD       "RXFILTER-ADD"
-#define CMD_RXFILTER_REMOVE    "RXFILTER-REMOVE"
+#define CMD_START                              "START"
+#define CMD_STOP                               "STOP"
+#define CMD_SCAN_ACTIVE                        "SCAN-ACTIVE"
+#define CMD_SCAN_PASSIVE               "SCAN-PASSIVE"
+#define CMD_RSSI                               "RSSI"
+#define CMD_LINKSPEED                  "LINKSPEED"
+#define CMD_RXFILTER_START             "RXFILTER-START"
+#define CMD_RXFILTER_STOP              "RXFILTER-STOP"
+#define CMD_RXFILTER_ADD               "RXFILTER-ADD"
+#define CMD_RXFILTER_REMOVE            "RXFILTER-REMOVE"
 #define CMD_BTCOEXSCAN_START   "BTCOEXSCAN-START"
-#define CMD_BTCOEXSCAN_STOP    "BTCOEXSCAN-STOP"
-#define CMD_BTCOEXMODE         "BTCOEXMODE"
-#define CMD_SETSUSPENDOPT      "SETSUSPENDOPT"
-#define CMD_P2P_DEV_ADDR       "P2P_DEV_ADDR"
-#define CMD_SETFWPATH          "SETFWPATH"
-#define CMD_SETBAND            "SETBAND"
-#define CMD_GETBAND            "GETBAND"
-#define CMD_COUNTRY            "COUNTRY"
+#define CMD_BTCOEXSCAN_STOP            "BTCOEXSCAN-STOP"
+#define CMD_BTCOEXMODE                 "BTCOEXMODE"
+#define CMD_SETSUSPENDOPT              "SETSUSPENDOPT"
+#define CMD_P2P_DEV_ADDR               "P2P_DEV_ADDR"
+#define CMD_SETFWPATH                  "SETFWPATH"
+#define CMD_SETBAND                            "SETBAND"
+#define CMD_GETBAND                            "GETBAND"
+#define CMD_COUNTRY                            "COUNTRY"
+#define CMD_P2P_SET_NOA                        "P2P_SET_NOA"
+#define CMD_P2P_GET_NOA                        "P2P_GET_NOA"
+#define CMD_P2P_SET_PS                 "P2P_SET_PS"
+#define CMD_SET_ASSOC_RESP_IE  "SET_ASSOC_RESP_IE"
+#define CMD_SET_PROBE_RESP_IE  "SET_PROBE_RESP_IE"
+#define CMD_SET_BEACON_IE              "SET_BEACON_IE"
 
 #ifdef PNO_SUPPORT
 #define CMD_PNOSSIDCLR_SET     "PNOSSIDCLR"
@@ -112,6 +120,12 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command);
 #else
 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
 { return 0; }
+int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
+{ return 0; }
+int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
+{ return 0; }
+int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
+{ return 0; }
 #endif
 
 extern bool ap_fw_loaded;
@@ -517,7 +531,38 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 #endif
        else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
                bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
-       } else {
+       }
+       else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
+               int skip = strlen(CMD_P2P_SET_NOA) + 1;
+               bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
+                       priv_cmd.total_len - skip);
+       }
+       else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
+               bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
+       }
+       else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
+               int skip = strlen(CMD_P2P_SET_PS) + 1;
+               bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
+                       priv_cmd.total_len - skip);
+       }
+#ifdef WL_CFG80211
+       else if (strnicmp(command, CMD_SET_ASSOC_RESP_IE, strlen(CMD_SET_ASSOC_RESP_IE)) == 0) {
+               int skip = strlen(CMD_SET_ASSOC_RESP_IE) + 1;
+               bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
+                       priv_cmd.total_len - skip, WL_ASSOC_RESP);
+       }
+       else if (strnicmp(command, CMD_SET_PROBE_RESP_IE, strlen(CMD_SET_PROBE_RESP_IE)) == 0) {
+               int skip = strlen(CMD_SET_PROBE_RESP_IE) + 1;
+               bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
+                       priv_cmd.total_len - skip, WL_PROBE_RESP);
+       }
+       else if (strnicmp(command, CMD_SET_BEACON_IE, strlen(CMD_SET_BEACON_IE)) == 0) {
+               int skip = strlen(CMD_SET_BEACON_IE) + 1;
+               bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
+                       priv_cmd.total_len - skip, WL_BEACON);
+       }
+#endif /* WL_CFG80211 */
+       else {
                DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
                snprintf(command, 3, "OK");
                bytes_written = strlen("OK");
index 0c3854d..7153a4e 100644 (file)
@@ -1402,8 +1402,10 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
                        err = -ENOMEM;
                        goto exit;
                }
-               wldev_iovar_setbuf(ndev, "escan", params, params_size,
+               err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
                        wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN);
+               if (unlikely(err))
+                       WL_ERR((" Escan set error (%d)\n", err));
                kfree(params);
        }
        else if (p2p_on(wl) && p2p_scan(wl)) {
@@ -2171,7 +2173,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) {
                /* we only allow to connect using virtual interface in case of P2P */
                if (p2p_on(wl) && is_wps_conn(sme)) {
-                       WL_DBG(("p2p index : %d\n", wl_cfgp2p_find_idx(wl, dev)));
+                       WL_DBG(("ASSOC1 p2p index : %d sme->ie_len %d\n",
+                               wl_cfgp2p_find_idx(wl, dev), sme->ie_len));
                        /* Have to apply WPS IE + P2P IE in assoc req frame */
                        wl_cfgp2p_set_management_ie(wl, dev,
                                wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG,
@@ -2187,6 +2190,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                         * the newly received IEs from Supplicant. This will remove the WPS IE from
                         * the Assoc Req.
                         */
+                       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_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
                }
@@ -2902,11 +2907,8 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
        wl_clr_drv_status(wl, SCANNING);
        wl_clr_drv_status(wl, SCAN_ABORTING);
        dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
-
        if (wl_get_drv_status(wl, CONNECTING)) {
                wl_bss_connect_done(wl, ndev, NULL, NULL, false);
-               wl_delay(500);
-               return -EAGAIN;
        }
 #endif
        return 0;
@@ -3286,6 +3288,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
        if (wl->p2p->vif_created) {
                wifi_p2p_pub_act_frame_t *act_frm =
                        (wifi_p2p_pub_act_frame_t *) (action_frame->data);
+               WL_DBG(("action_frame->len: %d chan %d category %d subtype %d\n",
+                       action_frame->len, af_params->channel,
+                       act_frm->category, act_frm->subtype));
                /*
                 * To make sure to send successfully action frame, we have to turn off mpc
                 */
@@ -3687,6 +3692,8 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
                } else {
                        WL_ERR(("No P2PIE in beacon \n"));
                }
+               /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
+               wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
                wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
                        beacon_ie, wpsie_len + p2pie_len);
 
@@ -4129,15 +4136,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
        beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
        beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
        wl_rst_ie(wl);
-       /*
-       * wl_add_ie is not necessary because it can only add duplicated
-       * SSID, rate information to frame_buf
-       */
-       /*
-       * wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
-       * wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count,
-       * bi->rateset.rates);
-       */
+
        wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
        wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
                offsetof(struct wl_cfg80211_bss_info, frame_buf));
@@ -4150,10 +4149,11 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 #endif
        channel = ieee80211_get_channel(wiphy, freq);
 
-       WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
-               bi->SSID,
-               notif_bss_info->rssi, notif_bss_info->channel,
-               mgmt->u.beacon.capab_info, &bi->BSSID));
+       WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
+                       "mgmt_type %d frame_len %d\n", bi->SSID,
+                               notif_bss_info->rssi, notif_bss_info->channel,
+                               mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
+                               notif_bss_info->frame_len));
 
        signal = notif_bss_info->rssi * 100;
 
@@ -5832,7 +5832,7 @@ static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, boo
        s32 err = 0;
 
        /* Setup event_msgs */
-       bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+       bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
                sizeof(iovbuf));
        err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
        if (unlikely(err)) {
@@ -6619,7 +6619,64 @@ s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pd
 
        return 0;
 }
+s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
+{
+       struct wl_priv *wl;
+       wl = wlcfg_drv_priv;
+
+       return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
+}
+
+s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
+{
+       struct wl_priv *wl;
+       wl = wlcfg_drv_priv;
+
+       return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
+}
 
+s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
+{
+       struct wl_priv *wl;
+       wl = wlcfg_drv_priv;
+
+       return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
+}
+
+s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
+       enum wl_management_type type)
+{
+       struct wl_priv *wl;
+       struct net_device *ndev = NULL;
+       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) ||
+               wl_get_drv_status(wl, AP_CREATED)) {
+               ndev = net;
+               bssidx = 0;
+       }
+       if (ndev != NULL) {
+               switch (type) {
+                       case WL_BEACON:
+                               pktflag = VNDR_IE_BEACON_FLAG;
+                               break;
+                       case WL_PROBE_RESP:
+                               pktflag = VNDR_IE_PRBRSP_FLAG;
+                               break;
+                       case WL_ASSOC_RESP:
+                               pktflag = VNDR_IE_ASSOCRSP_FLAG;
+                               break;
+               }
+               ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
+       }
+
+       return ret;
+}
 static __used void wl_dongle_poweron(struct wl_priv *wl)
 {
 
index 9fae79e..066103e 100644 (file)
@@ -182,6 +182,11 @@ enum wl_fw_status {
        WL_NVRAM_LOADING_DONE
 };
 
+enum wl_management_type {
+       WL_BEACON = 0x1,
+       WL_PROBE_RESP = 0x2,
+       WL_ASSOC_RESP = 0x4
+};
 /* beacon / probe_response */
 struct beacon_proberesp {
        __le64 timestamp;
@@ -538,6 +543,11 @@ extern void wl_cfg80211_release_fw(void);
 extern s8 *wl_cfg80211_get_fwname(void);
 extern s8 *wl_cfg80211_get_nvramname(void);
 extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
+extern s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len);
+extern s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len);
+extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
+       enum wl_management_type type);
+extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len);
 extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
 #ifdef CONFIG_SYSCTL
 extern s32 wl_cfg80211_sysctl_export_devaddr(void *data);
index dd5f5fa..653fbcd 100644 (file)
@@ -1305,6 +1305,7 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev)
        }
        return p2p_supported;
 }
+
 /* Cleanup P2P resources */
 s32
 wl_cfgp2p_down(struct wl_priv *wl)
@@ -1313,3 +1314,139 @@ wl_cfgp2p_down(struct wl_priv *wl)
                del_timer_sync(&wl->p2p->listen_timer);
        return 0;
 }
+
+s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
+{
+       s32 ret = -1;
+       int count, start, duration;
+       wl_p2p_sched_t dongle_noa;
+
+       CFGP2P_DBG((" Enter\n"));
+       memset(&dongle_noa, 0, sizeof(dongle_noa));
+
+       if (wl->p2p && wl->p2p->vif_created) {
+
+               wl->p2p->noa.desc[0].start = 0;
+
+               sscanf(buf, "%d %d %d", &count, &start, &duration);
+               CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n",
+                               count, start, duration));
+               if (count != -1)
+                       wl->p2p->noa.desc[0].count = count;
+
+               /* supplicant gives interval as start */
+               if (start != -1)
+                       wl->p2p->noa.desc[0].interval = start * 1000;
+
+               if (duration != -1)
+                       wl->p2p->noa.desc[0].duration = duration * 1000;
+
+               if (wl->p2p->noa.desc[0].count != 255) {
+                       wl->p2p->noa.desc[0].start = 200 * 1000;
+                       dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS;
+                       dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF;
+                       dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
+               }
+               else {
+                       /* Continuous NoA interval. */
+                       dongle_noa.action = WL_P2P_SCHED_ACTION_NONE;
+                       dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
+                       if ((wl->p2p->noa.desc[0].interval == 102000) ||
+                               (wl->p2p->noa.desc[0].interval == 100000)) {
+                               wl->p2p->noa.desc[0].start = 100 -
+                                       (wl->p2p->noa.desc[0].duration / 1000);
+                               wl->p2p->noa.desc[0].duration /= 1000;
+                               dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT;
+                       }
+                       else {
+                               dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
+                       }
+               }
+               /* Put the noa descriptor in dongle format for dongle */
+
+               dongle_noa.desc[0].count = htod32(wl->p2p->noa.desc[0].count);
+               dongle_noa.desc[0].start = htod32(wl->p2p->noa.desc[0].start);
+               dongle_noa.desc[0].interval = htod32(wl->p2p->noa.desc[0].interval);
+               dongle_noa.desc[0].duration = htod32(wl->p2p->noa.desc[0].duration);
+
+               ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION),
+                       "p2p_noa", &dongle_noa, sizeof(dongle_noa), ioctlbuf, sizeof(ioctlbuf));
+
+               if (ret < 0) {
+                       CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret));
+               }
+       }
+       else {
+               CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
+       }
+       return ret;
+}
+
+s32 wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
+{
+       wifi_p2p_noa_desc_t* noa_desc;
+       CFGP2P_DBG((" Enter\n"));
+       if (wl->p2p && wl->p2p->vif_created) {
+               if (wl->p2p->noa.desc[0].count) {
+#define P2P_ATTR_NOTICE_OF_ABSENCE_LEN 2
+                       buf[0] = 0; /* noa index */
+                       buf[1] = (wl->p2p->ops.ops ? 0x80: 0) |
+                               (wl->p2p->ops.ctw & 0x7f); /* ops + ctw */
+                       noa_desc = (wifi_p2p_noa_desc_t*)&buf[P2P_ATTR_NOTICE_OF_ABSENCE_LEN];
+                       noa_desc->cnt_type = wl->p2p->noa.desc[0].count;
+                       noa_desc->duration = wl->p2p->noa.desc[0].duration;
+                       noa_desc->interval = wl->p2p->noa.desc[0].interval;
+                       noa_desc->start = wl->p2p->noa.desc[0].start;
+                       /* wl_android.c is adding 1 to ret value for all returned bufs */
+                       return sizeof(wifi_p2p_noa_desc_t) +
+                               P2P_ATTR_NOTICE_OF_ABSENCE_LEN - 1;
+               }
+               else {
+                       /* NOA parameters are not set */
+                       return 0;
+               }
+       }
+       else {
+               CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
+               return -1;
+       }
+}
+
+s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
+{
+       int ps, ctw, legacy_ps;
+       int ret = -1;
+
+       CFGP2P_DBG((" Enter\n"));
+       if (wl->p2p && wl->p2p->vif_created) {
+               sscanf(buf, "%d %d %d", &legacy_ps, &ps, &ctw);
+               CFGP2P_DBG((" Enter ps %d ctw %d\n", ps, ctw));
+               if (ctw != -1) {
+                       wl->p2p->ops.ctw = ctw;
+                       ret = 0;
+               }
+               if (ps != -1) {
+                       wl->p2p->ops.ops = ps;
+                       ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION),
+                               "p2p_ops", &wl->p2p->ops, sizeof(wl->p2p->ops),
+                               ioctlbuf, sizeof(ioctlbuf));
+                       if (ret < 0) {
+                               CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret));
+                       }
+               }
+
+               if (legacy_ps != -1) {
+                       s32 pm = legacy_ps ? PM_FAST : PM_OFF;
+                       ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION),
+                               WLC_SET_PM, &pm, sizeof(pm), true);
+                       if (unlikely(ret)) {
+                               CFGP2P_ERR(("error (%d)\n", ret));
+                       }
+               }
+       }
+       else {
+               CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
+               ret = -1;
+       }
+       return ret;
+}
index 5aff468..a7fdf76 100644 (file)
@@ -74,6 +74,8 @@ struct p2p_info {
        struct ether_addr int_addr;
        struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
        struct timer_list listen_timer;
+       wl_p2p_sched_t noa;
+       wl_p2p_ops_t ops;
        wlc_ssid_t ssid;
        spinlock_t timer_lock;
 };
@@ -224,6 +226,15 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev);
 extern s32
 wl_cfgp2p_down(struct wl_priv *wl);
 
+extern s32
+wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len);
+
+extern s32
+wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len);
+
+extern s32
+wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len);
+
 /* WiFi Direct */
 #define SOCIAL_CHAN_1 1
 #define SOCIAL_CHAN_2 6
index ef77cdc..f71f29a 100644 (file)
@@ -8077,8 +8077,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
        uint32 datalen = ntoh32(e->datalen);
        uint32 status =  ntoh32(e->status);
        uint32 toto;
-       static  uint32 roam_no_success = 0;
-       static bool roam_no_success_send = FALSE;
        memset(&wrqu, 0, sizeof(wrqu));
        memset(extra, 0, sizeof(extra));
 
@@ -8146,26 +8144,12 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
                cmd = IWEVREGISTERED;
                break;
        case WLC_E_ROAM:
-               if (status != WLC_E_STATUS_SUCCESS) {
-                       roam_no_success++;
-                       if ((roam_no_success == 3) && (roam_no_success_send == FALSE)) {
-                               
-                               roam_no_success_send = TRUE;
-                               bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
-                               bzero(&extra, ETHER_ADDR_LEN);
-                               cmd = SIOCGIWAP;
-                               WL_ERROR(("%s  ROAMING did not succeeded , send Link Down\n",
-                                       __FUNCTION__));
-                       } else {
-                               WL_TRACE(("##### ROAMING did not succeeded %d\n", roam_no_success));
-                               goto wl_iw_event_end;
-                       }
-               } else {
-                       memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
-                       wrqu.addr.sa_family = ARPHRD_ETHER;
-                       cmd = SIOCGIWAP;
+               if (status == WLC_E_STATUS_SUCCESS) {
+                       WL_ASSOC((" WLC_E_ROAM : success \n"));
+                       return;
                }
        break;
+
        case WLC_E_DEAUTH_IND:
        case WLC_E_DISASSOC_IND:
 #if defined(SOFTAP)
@@ -8225,8 +8209,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
                                wl_iw_send_priv_event(priv_dev, "AP_UP");
                        } else {
                                WL_TRACE(("STA_LINK_UP\n"));
-                               roam_no_success_send = FALSE;
-                               roam_no_success = 0;
                        }
 #else
 #endif