summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2011-09-21 13:09:58 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:39:07 -0800
commitc3c5c90e1c07da1e8433bbf042e8f55ef40d4ce6 (patch)
tree41de6d7b5109129c4da42a55ce386c1871d64333
parent13a64b2007ea68795d06d869f55d4087b9acf0d6 (diff)
net: wireless: bcmdhd: Update to Version 5.90.125.87
- Improve discovery of FW hanging - Add WFD noa and power-safe related functions Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h12
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c59
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c26
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c34
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h10
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c85
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c95
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h10
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c137
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h11
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c26
11 files changed, 393 insertions, 112 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index 5d9e678e7db6..ac374af3ca50 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -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_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index 146b7a7f1796..8496f17bb059 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -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);
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 6a69b2bff76a..02331899b025 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -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;
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index 37ab6805d6d9..b79ef4417121 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -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 */
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 60f842c6d968..63db714ae883 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -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 $
*
*/
@@ -33,17 +33,17 @@
#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
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 8bc6b361e868..8c0e3ae7a261 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -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))
@@ -51,25 +53,31 @@
* 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");
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 0c3854d17e4c..7153a4ed5999 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -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)
{
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 9fae79ed83dc..066103ebe10e 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -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);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index dd5f5facd728..653fbcdf7e65 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -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;
+}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index 5aff46831f85..a7fdf7662e9f 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -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
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index ef77cdc9bda8..f71f29a242fb 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -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