summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2012-05-01 11:00:21 -0700
committerOm Prakash Singh <omp@nvidia.com>2012-06-15 14:15:17 +0530
commit020878af9bb7aa0a7e71b41c4aed4b184e26bd29 (patch)
tree2798c365f572120a78eb3f30da421978f726fba0 /drivers
parent9b5e33e67e8dd7cd664003c5a6bd805104ed82b7 (diff)
net: wireless: bcmdhd: Update to Version 5.90.195.61
- Deauth frame from p2p GO to client doesn't go from firmware if we do del_virtual_iface immediately. Putting a delay after sending deauth frame to allowed FW to send out deauth frame. - IF_DEL operation was timing out due to wrong status check. Fixed it and added few debug prints. - Sending Provision Discovery directly to GO instead of doing an internal scan. Also put the internal scan count to 3 to have better timings for GO-NEG. - Increase beacon timeout only for concurrent mode. For STA only operation, use the default beacon timeout value (4). - If scan abort is due to timeout, aborting the scan in FW is not required. Moreover, as this scan_timeout call is coming in timer interrupt context, all blocking calls such as fw scan abort will result in kernel panic : don’t call abort in Firmware. - Add p2p_cancel_listen routine. Fix p2p_listen_complete related kernel crash seen while turning off WiFi. Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h10
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cfg80211.c25
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c8
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c6
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c5
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h8
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c91
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h5
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c49
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h7
10 files changed, 154 insertions, 60 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index d1648b7d99cd..3911f336b16f 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -24,11 +24,12 @@
* 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 325862 2012-04-04 22:59:48Z $
+ * $Id: dhd.h 328934 2012-04-23 05:15:42Z $
*/
-
-
+/****************
+ * Common types *
+ */
#ifndef _dhd_h_
#define _dhd_h_
@@ -90,6 +91,9 @@ enum dhd_bus_state {
#define DHD_SCAN_ACTIVE_TIME 40 /* ms : Embedded default Active setting from DHD Driver */
#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD Driver */
+#define DHD_BEACON_TIMEOUT_NORMAL 4
+#define DHD_BEACON_TIMEOUT_HIGH 10
+
enum dhd_bus_wake_state {
WAKE_LOCK_OFF,
WAKE_LOCK_PRIV,
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
index 2503f51ec574..183891df160a 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
@@ -41,7 +41,9 @@ static int dhd_dongle_up = FALSE;
static s32 wl_dongle_up(struct net_device *ndev, u32 up);
-
+/**
+ * Function implementations
+ */
s32 dhd_cfg80211_init(struct wl_priv *wl)
{
@@ -70,13 +72,22 @@ s32 dhd_cfg80211_down(struct wl_priv *wl)
s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
{
dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
+ int bcn_timeout = DHD_BEACON_TIMEOUT_HIGH;
+ char iovbuf[30];
+
dhd->op_mode |= val;
WL_ERR(("Set : op_mode=%d\n", dhd->op_mode));
#ifdef ARP_OFFLOAD_SUPPORT
+ /* IF P2P is enabled, disable arpoe */
dhd_arp_offload_set(dhd, 0);
dhd_arp_offload_enable(dhd, false);
-#endif
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+ /* Setup timeout if Beacons are lost and roam is off to report link down */
+ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
return 0;
}
@@ -84,13 +95,21 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
{
dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
+ int bcn_timeout = DHD_BEACON_TIMEOUT_NORMAL;
+ char iovbuf[30];
+
dhd->op_mode &= ~CONCURENT_MASK;
WL_ERR(("Clean : op_mode=%d\n", dhd->op_mode));
#ifdef ARP_OFFLOAD_SUPPORT
+ /* IF P2P is disabled, enable arpoe back for STA mode. */
dhd_arp_offload_set(dhd, dhd_arp_mode);
dhd_arp_offload_enable(dhd, true);
-#endif
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+ /* Setup timeout if Beacons are lost and roam is off to report link down */
+ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
return 0;
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index 1e7a0679121d..d9810ace1cb4 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 319098 2012-03-07 01:05:20Z $
+ * $Id: dhd_common.c 329682 2012-04-26 09:20:38Z $
*/
#include <typedefs.h>
#include <osl.h>
@@ -1001,6 +1001,9 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
datalen = ntoh32_ua((void *)&event->datalen);
evlen = datalen + sizeof(bcm_event_t);
+ DHD_TRACE(("RX: event_type:%d flags:%d status:%d reason:%d \n",
+ type, flags, status, reason));
+
switch (type) {
#ifdef PROP_TXSTATUS
case WLC_E_FIFO_CREDIT_MAP:
@@ -1728,6 +1731,7 @@ fail:
/*
* returns = TRUE if associated, FALSE if not associated
+ * third paramter retval can return error from error
*/
bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval)
{
@@ -1896,7 +1900,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
return ret;
}
-#endif
+#endif /* !WL_SCHED_SCAN */
/* Enable/disable PNO */
if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 98738970afad..320ce5975bf0 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 325862 2012-04-04 22:59:48Z $
+ * $Id: dhd_linux.c 329682 2012-04-26 09:20:38Z $
*/
#include <typedefs.h>
@@ -1473,6 +1473,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
*/
((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++;
PKTFREE(dhdp->osh, pktbuf, TRUE);
+ DHD_TRACE(("RX: wlfc header \n"));
continue;
}
#endif
@@ -2964,7 +2965,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint power_mode = PM_FAST;
uint32 dongle_align = DHD_SDALIGN;
uint32 glom = 0;
- uint bcn_timeout = 10;
+ uint bcn_timeout = DHD_BEACON_TIMEOUT_NORMAL;
+
uint retry_max = 3;
#if defined(ARP_OFFLOAD_SUPPORT)
int arpoe = 1;
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index 3086bb3cb68c..954d8296fd6a 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 325395 2012-04-03 03:57:43Z $
+ * $Id: dhd_sdio.c 326662 2012-04-10 06:38:08Z $
*/
#include <typedefs.h>
@@ -4616,8 +4616,7 @@ clkwait:
int ret, i;
uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN;
- if (((bus->sih->chip == BCM4329_CHIP_ID) || /* limit to 4329 & 4330 for now */
- (bus->sih->chip == BCM4330_CHIP_ID)) && (*frame_seq != bus->tx_seq)) {
+ if (*frame_seq != bus->tx_seq) {
DHD_INFO(("%s IOCTL frame seq lag detected!"
" frm_seq:%d != bus->tx_seq:%d, corrected\n",
__FUNCTION__, *frame_seq, bus->tx_seq));
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index b3560bd9203f..3bff73e2a6bc 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -32,17 +32,17 @@
#define EPI_RC_NUMBER 195
-#define EPI_INCREMENTAL_NUMBER 53
+#define EPI_INCREMENTAL_NUMBER 61
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 5, 90, 195, 53
+#define EPI_VERSION 5, 90, 195, 61
-#define EPI_VERSION_NUM 0x055ac335
+#define EPI_VERSION_NUM 0x055ac33d
#define EPI_VERSION_DEV 5.90.195
-#define EPI_VERSION_STR "5.90.195.53"
+#define EPI_VERSION_STR "5.90.195.61"
#endif
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index f717f8f1a07a..98e498d785cd 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -100,7 +100,10 @@ static const struct ieee80211_regdomain brcm_regdom = {
* we need cfg80211 to allow it (reg_flags = 0); so that
* hostapd could request auto channel by sending down ch 14
*/
- REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
+ REG_RULE(2484-10, 2484+10, 20, 6, 20,
+ NL80211_RRF_PASSIVE_SCAN |
+ NL80211_RRF_NO_IBSS |
+ NL80211_RRF_NO_OFDM),
/* IEEE 802.11a, channel 36..64 */
REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
/* IEEE 802.11a, channel 100..165 */
@@ -735,7 +738,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
s32 mode = 0;
#if defined(WL_ENABLE_P2P_IF)
s32 dhd_mode = 0;
-#endif
+#endif /* (WL_ENABLE_P2P_IF) */
chanspec_t chspec;
struct wl_priv *wl = wiphy_priv(wiphy);
struct net_device *_ndev;
@@ -807,7 +810,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
return ERR_PTR(-EAGAIN);
}
}
- if (!p2p_is_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
+ if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
p2p_on(wl) = true;
wl_cfgp2p_set_firm_p2p(wl);
wl_cfgp2p_init_discovery(wl);
@@ -819,7 +822,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
-
+ wldev_iovar_setint(_ndev, "mpc", 0);
+ wl_notify_escan_complete(wl, _ndev, true, true);
/* In concurrency case, STA may be already associated in a particular channel.
* so retrieve the current channel of primary interface and then start the virtual
* interface on that.
@@ -874,8 +878,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
else if (type == NL80211_IFTYPE_P2P_GO)
dhd_mode = P2P_GO_ENABLED;
DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode));
-#endif
-
+#endif /* (WL_ENABLE_P2P_IF) */
+ /* Start the P2P I/F with PM disabled. Enable PM from
+ * the framework
+ */
if ((type == NL80211_IFTYPE_P2P_CLIENT) || (
type == NL80211_IFTYPE_P2P_GO))
vwdev->ps = NL80211_PS_DISABLED;
@@ -920,7 +926,7 @@ 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);
if (wl->p2p->vif_created) {
- if (wl->scan_request) {
+ if (wl_get_drv_status(wl, SCANNING, dev)) {
wl_notify_escan_complete(wl, dev, true, true);
}
wldev_iovar_setint(dev, "mpc", 1);
@@ -948,7 +954,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
WL_DBG(("IFDEL operation done\n"));
#if defined(WL_ENABLE_P2P_IF)
DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl));
-#endif
+#endif /* (WL_ENABLE_P2P_IF)) */
} else {
WL_ERR(("IFDEL didn't complete properly\n"));
}
@@ -972,7 +978,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
chanspec_t chspec;
struct wl_priv *wl = wiphy_priv(wiphy);
- WL_DBG(("Enter \n"));
+ WL_DBG(("Enter type %d\n", type));
switch (type) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_WDS:
@@ -1003,8 +1009,10 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
wl_set_mode_by_netdev(wl, ndev, mode);
if (wl->p2p_supported && wl->p2p->vif_created) {
WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created,
- p2p_on(wl)));
+ p2p_on(wl)));
wldev_iovar_setint(ndev, "mpc", 0);
+ wl_notify_escan_complete(wl, ndev, true, true);
+
/* In concurrency case, STA may be already associated in a particular
* channel. so retrieve the current channel of primary interface and
* then start the virtual interface on that.
@@ -1121,6 +1129,7 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev)
WL_DBG(("index : %d\n", index));
}
+
/* Wake up any waiting thread */
wake_up_interruptible(&wl->netif_change_event);
@@ -2007,7 +2016,11 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
if (is_wps_conn(sme)) {
- err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
+ if (sme->privacy)
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
+ else
+ /* WPS-2.0 allowes no security */
+ err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
} else {
WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
err = wldev_iovar_setint_bsscfg(dev, "wsec",
@@ -2847,7 +2860,6 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
err = -ENODEV;
if (!wl_get_drv_status(wl, CONNECTED, dev) ||
(dhd_is_associated(dhd, NULL, &err) == FALSE)) {
-
WL_ERR(("NOT assoc: %d\n", err));
goto get_station_err;
}
@@ -3168,7 +3180,7 @@ wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
/* Our scan params have 1 channel and 0 ssids */
params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
- (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
+ (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
*out_params_size = params_size; /* rtn size to the caller */
return params;
@@ -3195,7 +3207,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
ndev = dev;
}
- if (wl->scan_request) {
+ if (wl_get_drv_status(wl, SCANNING, ndev)) {
wl_notify_escan_complete(wl, ndev, true, true);
}
target_channel = ieee80211_frequency_to_channel(channel->center_freq);
@@ -3207,7 +3219,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
*cookie = id;
cfg80211_ready_on_channel(dev, *cookie, channel,
channel_type, duration, GFP_KERNEL);
- if (!p2p_is_on(wl)) {
+ if (wl->p2p && !wl->p2p->on) {
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
@@ -3331,7 +3343,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
struct ieee80211_channel *channel, bool offchan,
enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait,
- const u8* buf, size_t len, u64 *cookie)
+ const u8* buf, size_t len,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ bool no_cck,
+#endif
+ u64 *cookie)
{
wl_action_frame_t *action_frame;
wl_af_params_t *af_params;
@@ -3418,6 +3434,10 @@ 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
+ */
+ wl_delay(400);
cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
goto exit;
@@ -3521,7 +3541,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
}
if (IS_P2P_SOCIAL(af_params->channel) &&
- (IS_P2P_PUB_ACT_REQ(act_frm, action_frame->len) ||
+ (IS_P2P_PUB_ACT_REQ(act_frm, &act_frm->elts[0], action_frame->len) ||
IS_GAS_REQ(sd_act_frm, action_frame->len)) &&
wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
/* channel offload require P2P IE for Probe request
@@ -3534,7 +3554,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
} else {
ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true;
if (!ack) {
- for (retry = 1; retry < WL_CHANNEL_SYNC_RETRY; retry++) {
+ for (retry = 1; retry < retry_cnt; retry++) {
ack = (wl_cfgp2p_tx_action_frame(wl, dev,
af_params, bssidx)) ? false : true;
if (ack)
@@ -4774,17 +4794,24 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
bool act;
s32 err = 0;
u32 event = ntoh32(e->event_type);
+ u32 reason;
if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
wl_notify_connect_status_ap(wl, ndev, e, data);
} else {
WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
ntoh32(e->event_type), ntoh32(e->status), 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));
+ }
if (wl_is_linkup(wl, e, ndev)) {
wl_link_up(wl);
act = true;
wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
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,
@@ -4812,7 +4839,6 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
if (wl_get_drv_status(wl, CONNECTED, ndev)) {
scb_val_t scbval;
u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
- printk("link down, call cfg80211_disconnected\n");
wl_clr_drv_status(wl, CONNECTED, ndev);
if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
/* To make sure disconnect, explictly send dissassoc
@@ -4824,7 +4850,8 @@ 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);
- cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
+ 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_link_down(wl);
wl_init_prof(wl, ndev);
}
@@ -5824,7 +5851,7 @@ static void wl_scan_timeout(unsigned long data)
if (wl->scan_request) {
WL_ERR(("timer expired\n"));
if (wl->escan_on)
- wl_notify_escan_complete(wl, wl->escan_info.ndev, false, true);
+ wl_notify_escan_complete(wl, wl->escan_info.ndev, true, false);
else
wl_notify_iscan_complete(wl_to_iscan(wl), true);
}
@@ -5880,7 +5907,7 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
struct wl_priv *wl = wlcfg_drv_priv;
WL_DBG(("Enter \n"));
- if (!wdev || dev == wl_to_prmry_ndev(wl))
+ if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
return NOTIFY_DONE;
switch (state) {
case NETDEV_UNREGISTER:
@@ -5945,7 +5972,7 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl,
}
}
}
- if (!in_atomic())
+ if (timer_pending(&wl->scan_timeout))
del_timer_sync(&wl->scan_timeout);
spin_lock_irqsave(&wl->cfgdrv_lock, flags);
@@ -5987,7 +6014,6 @@ 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)));
@@ -6036,8 +6062,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
}
if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
- p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
- if (p2p_dev_addr && !memcmp(p2p_dev_addr,
+ if (!memcmp(bi->BSSID.octet,
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));
@@ -6190,6 +6215,7 @@ static s32 wl_init_priv(struct wl_priv *wl)
wl->iscan_kickstart = false;
wl->active_scan = true;
wl->rf_blocked = false;
+ wl->deauth_reason = 0;
spin_lock_init(&wl->cfgdrv_lock);
mutex_init(&wl->ioctl_buf_sync);
init_waitqueue_head(&wl->netif_change_event);
@@ -6714,12 +6740,16 @@ s32 wl_update_wiphybands(struct wl_priv *wl)
}
if ((index >= 0) && nmode) {
wiphy->bands[index]->ht_cap.cap =
- IEEE80211_HT_CAP_DSSSCCK40
- | IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_RX_STBC;
+ IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 |
+ IEEE80211_HT_CAP_MAX_AMSDU;
wiphy->bands[index]->ht_cap.ht_supported = TRUE;
- wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K;
+ 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);
@@ -7046,7 +7076,8 @@ static void wl_init_eq_lock(struct wl_priv *wl)
static void wl_delay(u32 ms)
{
- if (in_atomic() || ms < 1000 / HZ) {
+ if (ms < 1000 / HZ) {
+ cond_resched();
mdelay(ms);
} else {
msleep(ms);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 818eff594115..fba853149c35 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -131,8 +131,8 @@ do { \
#define IFACE_MAX_CNT 2
#define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */
-#define WL_CHANNEL_SYNC_RETRY 1
-#define WL_ACT_FRAME_RETRY 5
+#define WL_CHANNEL_SYNC_RETRY 3
+#define WL_ACT_FRAME_RETRY 4
#define WL_INVALID -1
@@ -449,6 +449,7 @@ struct wl_priv {
#endif /* WL_SCHED_SCAN */
bool sched_scan_running; /* scheduled scan req status */
u16 hostapd_chan; /* remember chan requested by framework for hostapd */
+ u16 deauth_reason; /* Place holder to save deauth/disassoc reasons */
};
static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index 880123e067dc..cfa5ac3f5ec6 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -105,6 +105,7 @@ bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len)
return false;
}
+
bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len)
{
@@ -128,6 +129,7 @@ bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len)
return false;
}
+
void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len)
{
wifi_p2p_pub_act_frame_t *pact_frm;
@@ -271,7 +273,6 @@ wl_cfgp2p_init_priv(struct wl_priv *wl)
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0;
wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL;
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0;
- spin_lock_init(&wl->p2p->timer_lock);
return BCME_OK;
}
@@ -318,7 +319,7 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl)
ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr,
sizeof(null_eth_addr), wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync);
if (ret && ret != BCME_UNSUPPORTED) {
- CFGP2P_ERR(("failed to update device address\n"));
+ CFGP2P_ERR(("failed to update device address ret %d\n", ret));
}
return ret;
}
@@ -539,7 +540,7 @@ wl_cfgp2p_init_discovery(struct wl_priv *wl)
/* Set the initial discovery state to SCAN */
ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0,
- wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
+ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
if (unlikely(ret != 0)) {
CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
@@ -690,7 +691,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
#define P2PAPI_SCAN_NPROBES 1
#define P2PAPI_SCAN_DWELL_TIME_MS 50
#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
-#define P2PAPI_SCAN_HOME_TIME_MS 10
+#define P2PAPI_SCAN_HOME_TIME_MS 60
struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
wl_set_p2p_status(wl, SCANNING);
/* Allocate scan params which need space for 3 channels and 0 ssids */
@@ -1180,12 +1181,15 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev,
s32 ret = BCME_OK;
CFGP2P_DBG((" Enter\n"));
+
+ /* If p2p_info is de-initialized, do nothing */
+ if (!wl->p2p)
+ return ret;
+
if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) {
wl_set_p2p_status(wl, LISTEN_EXPIRED);
if (timer_pending(&wl->p2p->listen_timer)) {
- spin_lock_bh(&wl->p2p->timer_lock);
del_timer_sync(&wl->p2p->listen_timer);
- spin_unlock_bh(&wl->p2p->timer_lock);
}
cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, &wl->remain_on_chan,
wl->remain_on_chan_type, GFP_KERNEL);
@@ -1213,6 +1217,33 @@ wl_cfgp2p_listen_expired(unsigned long data)
}
/*
+ * Routine for cancelling the P2P LISTEN
+ */
+s32
+wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev,
+ bool notify)
+{
+ WL_DBG(("Enter \n"));
+
+ /* Irrespective of whether timer is running or not, reset
+ * the LISTEN state.
+ */
+ wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0,
+ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
+
+ if (timer_pending(&wl->p2p->listen_timer)) {
+ del_timer_sync(&wl->p2p->listen_timer);
+
+ if (notify)
+ cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id,
+ &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL);
+ }
+
+
+ return 0;
+}
+
+/*
* Do a P2P Listen on the given channel for the given duration.
* A listen consists of sitting idle and responding to P2P probe requests
* with a P2P probe response.
@@ -1531,8 +1562,10 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev)
s32
wl_cfgp2p_down(struct wl_priv *wl)
{
- if (timer_pending(&wl->p2p->listen_timer))
- del_timer_sync(&wl->p2p->listen_timer);
+
+ wl_cfgp2p_cancel_listen(wl,
+ wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl), TRUE);
+
wl_cfgp2p_deinit_priv(wl);
return 0;
}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index 1e5b1197e92d..be497c3e2426 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -77,7 +77,6 @@ struct p2p_info {
wl_p2p_sched_t noa;
wl_p2p_ops_t ops;
wlc_ssid_t ssid;
- spinlock_t timer_lock;
};
/* dongle status */
@@ -268,14 +267,16 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl);
#define WL_P2P_INTERFACE_PREFIX "p2p"
#define WL_P2P_TEMP_CHAN "11"
+/* If the provision discovery is for JOIN operations, then we need not do an internal scan to find GO */
+#define IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len) (wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL )
#define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \
((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \
(frame->action == P2PSD_ACTION_ID_GAS_CREQ)))
-#define IS_P2P_PUB_ACT_REQ(frame, len) (wl_cfgp2p_is_pub_action(frame, len) && \
+#define IS_P2P_PUB_ACT_REQ(frame, p2p_ie, len) (wl_cfgp2p_is_pub_action(frame, len) && \
((frame->subtype == P2P_PAF_GON_REQ) || \
(frame->subtype == P2P_PAF_INVITE_REQ) || \
- (frame->subtype == P2P_PAF_PROVDIS_REQ)))
+ ((frame->subtype == P2P_PAF_PROVDIS_REQ) && IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len))))
#define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3))
#define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0)
#endif /* _wl_cfgp2p_h_ */