From 297b60346df8beafee954a0fd7c2d64f33f3b9bc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 11 May 2024 01:44:05 +0000
Subject: [PATCH] rtl8211F_led_control
---
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c | 891 +++++++++++++++++++++++++++++++++++++----------------------
1 files changed, 555 insertions(+), 336 deletions(-)
diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c
index b5aac14..7b5c8b8 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c
@@ -1,15 +1,16 @@
-/* SPDX-License-Identifier: GPL-2.0 */
/*
* Linux cfgp2p driver
*
- * Copyright (C) 1999-2019, Broadcom Corporation
- *
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
+ *
+ * Copyright (C) 1999-2017, Broadcom Corporation
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -17,7 +18,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -25,7 +26,7 @@
*
* <<Broadcom-WL-IPTag/Open:>>
*
- * $Id: wl_cfgp2p.c 709309 2019-01-17 09:04:00Z $
+ * $Id: wl_cfgp2p.c 815562 2019-04-18 02:33:27Z $
*
*/
#include <typedefs.h>
@@ -39,28 +40,33 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/if_arp.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
#include <bcmutils.h>
+#include <bcmstdlib_s.h>
#include <bcmendian.h>
-#include <proto/ethernet.h>
-#include <proto/802.11.h>
+#include <ethernet.h>
+#include <802.11.h>
#include <net/rtnetlink.h>
#include <wl_cfg80211.h>
#include <wl_cfgp2p.h>
+#include <wl_cfgscan.h>
#include <wldev_common.h>
+#ifdef OEM_ANDROID
#include <wl_android.h>
+#endif // endif
#include <dngl_stats.h>
#include <dhd.h>
#include <dhd_linux.h>
#include <dhdioctl.h>
#include <wlioctl.h>
#include <dhd_cfg80211.h>
+#include <dhd_bus.h>
static s8 scanparambuf[WLC_IOCTL_SMLEN];
-static bool
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
+static bool wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
+ const u8 *oui, u32 oui_len, u8 type);
static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
struct wireless_dev *wdev, bool notify);
@@ -79,6 +85,22 @@
};
#endif /* WL_ENABLE_P2P_IF */
+#if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
+static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
+
+static int wl_cfgp2p_if_dummy(struct net_device *net)
+{
+ return 0;
+}
+
+static const struct net_device_ops wl_cfgp2p_if_ops = {
+ .ndo_open = wl_cfgp2p_if_dummy,
+ .ndo_stop = wl_cfgp2p_if_dummy,
+ .ndo_do_ioctl = wl_cfgp2p_do_ioctl,
+ .ndo_start_xmit = wl_cfgp2p_start_xmit,
+};
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
{
@@ -126,17 +148,17 @@
bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len)
{
- bcm_tlv_t *ie = (bcm_tlv_t *)data;
- u8 *frame = NULL;
+ const bcm_tlv_t *ie = (bcm_tlv_t *)data;
+ const u8 *frame = NULL;
u16 id, flen;
/* Skipped first ANQP Element, if frame has anqp elemnt */
- ie = bcm_parse_tlvs(ie, (int)len, DOT11_MNG_ADVERTISEMENT_ID);
+ ie = bcm_parse_tlvs(ie, len, DOT11_MNG_ADVERTISEMENT_ID);
if (ie == NULL)
return false;
- frame = (uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
+ frame = (const uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
id = ((u16) (((frame)[1] << 8) | (frame)[0]));
flen = ((u16) (((frame)[3] << 8) | (frame)[2]));
@@ -314,7 +336,6 @@
" channel=%d\n", (tx)? "TX" : "RX", channel));
}
-
}
}
@@ -325,7 +346,8 @@
s32
wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
{
- if (!(cfg->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
+ cfg->p2p = MALLOCZ(cfg->osh, sizeof(struct p2p_info));
+ if (cfg->p2p == NULL) {
CFGP2P_ERR(("struct p2p_info allocation failed\n"));
return -ENOMEM;
}
@@ -338,9 +360,6 @@
wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) = -1;
wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2) = NULL;
wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) = -1;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
- cfg->p2p->cfg = cfg;
-#endif
return BCME_OK;
}
@@ -351,9 +370,9 @@
void
wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg)
{
- CFGP2P_ERR(("In\n"));
+ CFGP2P_INFO(("In\n"));
if (cfg->p2p) {
- kfree(cfg->p2p);
+ MFREE(cfg->osh, cfg->p2p, sizeof(struct p2p_info));
cfg->p2p = NULL;
}
cfg->p2p_supported = 0;
@@ -376,7 +395,7 @@
}
if (val == 0) {
val = 1;
- ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
+ ret = wldev_ioctl_set(ndev, WLC_DOWN, &val, sizeof(s32));
if (ret < 0) {
CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
return ret;
@@ -389,7 +408,7 @@
return ret;
}
- ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
+ ret = wldev_ioctl_set(ndev, WLC_UP, &val, sizeof(s32));
if (ret < 0) {
CFGP2P_ERR(("WLC_UP error %d\n", ret));
return ret;
@@ -435,27 +454,22 @@
{
wl_p2p_if_t ifreq;
s32 err;
- u32 scb_timeout = WL_SCB_TIMEOUT;
struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
ifreq.type = if_type;
ifreq.chspec = chspec;
memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
- CFGP2P_DBG(("---cfg p2p_ifadd "MACDBG" %s %u\n",
+ CFGP2P_ERR(("---cfg p2p_ifadd "MACDBG" %s %u\n",
MAC2STRDBG(ifreq.addr.octet),
(if_type == WL_P2P_IF_GO) ? "go" : "client",
(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
- if (unlikely(err < 0))
+ if (unlikely(err < 0)) {
printk("'cfg p2p_ifadd' error %d\n", err);
- else if (if_type == WL_P2P_IF_GO) {
- err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
- if (unlikely(err < 0))
- printk("'cfg scb_timeout' error %d\n", err);
+ return err;
}
return err;
@@ -472,8 +486,8 @@
s32 ret;
struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
- CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdis "MACDBG"\n",
- netdev->ifindex, MAC2STRDBG(mac->octet)));
+ CFGP2P_INFO(("------ cfg p2p_ifdis "MACDBG" dev->ifindex:%d \n",
+ MAC2STRDBG(mac->octet), netdev->ifindex));
ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (unlikely(ret < 0)) {
@@ -491,15 +505,31 @@
wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
{
s32 ret;
+#ifdef WL_DISABLE_HE_P2P
+ s32 bssidx = 0;
+#endif /* WL_DISABLE_HE_P2P */
struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
- CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdel "MACDBG"\n",
- netdev->ifindex, MAC2STRDBG(mac->octet)));
+ CFGP2P_ERR(("------ cfg p2p_ifdel "MACDBG" dev->ifindex:%d\n",
+ MAC2STRDBG(mac->octet), netdev->ifindex));
ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (unlikely(ret < 0)) {
printk("'cfg p2p_ifdel' error %d\n", ret);
}
+#ifdef WL_DISABLE_HE_P2P
+ if ((bssidx = wl_get_bssidx_by_wdev(cfg, netdev->ieee80211_ptr)) < 0) {
+ WL_ERR(("Find index failed\n"));
+ ret = BCME_ERROR;
+ return ret;
+ }
+ WL_DBG(("Enabling back HE for P2P\n"));
+ wl_cfg80211_set_he_mode(netdev, cfg, bssidx, WL_IF_TYPE_P2P_DISC, TRUE);
+ if (ret < 0) {
+ WL_ERR(("failed to set he features, error=%d\n", ret));
+ }
+#endif /* WL_DISABLE_HE_P2P */
+
return ret;
}
@@ -514,7 +544,6 @@
{
wl_p2p_if_t ifreq;
s32 err;
- u32 scb_timeout = WL_SCB_TIMEOUT;
struct net_device *netdev = wl_to_p2p_bss_ndev(cfg, conn_idx);
@@ -530,18 +559,13 @@
err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
if (unlikely(err < 0)) {
printk("'cfg p2p_ifupd' error %d\n", err);
} else if (if_type == WL_P2P_IF_GO) {
cfg->p2p->p2p_go_count++;
- err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
- if (unlikely(err < 0))
- printk("'cfg scb_timeout' error %d\n", err);
}
return err;
}
-
/* Get the index of a created P2P BSS.
* Parameters:
@@ -563,7 +587,7 @@
if (ret == 0) {
memcpy(index, getbuf, sizeof(s32));
- CFGP2P_INFO(("---cfg p2p_if ==> %d\n", *index));
+ CFGP2P_DBG(("---cfg p2p_if ==> %d\n", *index));
}
return ret;
@@ -635,7 +659,7 @@
/* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */
discovery_mode.state = mode;
- discovery_mode.chspec = wl_ch_host_to_driver(bssidx, channel);
+ discovery_mode.chspec = wl_ch_host_to_driver(channel);
discovery_mode.dwell = listen_ms;
ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
@@ -675,7 +699,7 @@
CFGP2P_ERR(("Multi p2p not supported"));
return BCME_ERROR;
}
- if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 1) {
+ if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 2) {
CFGP2P_ERR(("Failed to create second p2p interface"
"Already one connection exists"));
return BCME_ERROR;
@@ -693,33 +717,42 @@
s32 bssidx = 0;
s32 ret = BCME_OK;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ BCM_REFERENCE(ndev);
CFGP2P_DBG(("enter\n"));
if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0) {
CFGP2P_ERR(("do nothing, already initialized\n"));
- return ret;
+ goto exit;
}
ret = wl_cfgp2p_set_discovery(cfg, 1);
if (ret < 0) {
CFGP2P_ERR(("set discover error\n"));
- return ret;
+ goto exit;
}
/* Enable P2P Discovery in the WL Driver */
ret = wl_cfgp2p_get_disc_idx(cfg, &bssidx);
-
if (ret < 0) {
- return ret;
+ goto exit;
}
+
/* In case of CFG80211 case, check if p2p_discovery interface has allocated p2p_wdev */
if (!cfg->p2p_wdev) {
CFGP2P_ERR(("p2p_wdev is NULL.\n"));
- return BCME_NODEVICE;
+ ret = -ENODEV;
+ goto exit;
}
- /* Make an entry in the netinfo */
- wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_MODE_BSS, 0, bssidx);
+ /* Once p2p also starts using interface_create iovar, the ifidx may change.
+ * so that time, the ifidx returned in WLC_E_IF should be used for populating
+ * the netinfo
+ */
+ ret = wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_IF_TYPE_STA, 0, bssidx, 0);
+ if (unlikely(ret)) {
+ goto exit;
+ }
wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) =
wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = bssidx;
@@ -733,7 +766,15 @@
wl_cfgp2p_set_discovery(cfg, 0);
wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
- return 0;
+ ret = 0;
+ goto exit;
+ }
+
+ /* Clear our saved WPS and P2P IEs for the discovery BSS */
+ wl_cfg80211_clear_p2p_disc_ies(cfg);
+exit:
+ if (ret) {
+ wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
}
return ret;
}
@@ -757,7 +798,7 @@
}
/* Clear our saved WPS and P2P IEs for the discovery BSS */
- wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
+ wl_cfg80211_clear_p2p_disc_ies(cfg);
/* Set the discovery state to SCAN */
wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
@@ -787,10 +828,19 @@
{
s32 ret = BCME_OK;
s32 bssidx;
+ bcm_struct_cfgdev *cfgdev;
CFGP2P_DBG(("enter\n"));
+ mutex_lock(&cfg->if_sync);
+#ifdef WL_IFACE_MGMT
+ if ((ret = wl_cfg80211_handle_if_role_conflict(cfg, WL_IF_TYPE_P2P_DISC)) != BCME_OK) {
+ WL_ERR(("secondary iface is active, p2p enable discovery is not supported\n"));
+ goto exit;
+ }
+#endif /* WL_IFACE_MGMT */
+
if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
- CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n"));
+ CFGP2P_DBG((" DISCOVERY is already initialized, we have nothing to do\n"));
goto set_ie;
}
@@ -817,19 +867,29 @@
bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
} else if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfg->p2p_wdev)) < 0) {
WL_ERR(("Find p2p index from wdev(%p) failed\n", cfg->p2p_wdev));
- return BCME_ERROR;
+ ret = BCME_ERROR;
+ goto exit;
}
- ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev),
- bssidx,
- VNDR_IE_PRBREQ_FLAG, ie, ie_len);
-
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ /* For 3.8+ kernels, pass p2p discovery wdev */
+ cfgdev = cfg->p2p_wdev;
+#else
+ /* Prior to 3.8 kernel, there is no netless p2p, so pass p2p0 ndev */
+ cfgdev = ndev_to_cfgdev(dev);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, cfgdev,
+ bssidx, VNDR_IE_PRBREQ_FLAG, ie, ie_len);
if (unlikely(ret < 0)) {
CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
goto exit;
}
}
exit:
+ if (ret) {
+ wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
+ }
+ mutex_unlock(&cfg->if_sync);
return ret;
}
@@ -843,24 +903,21 @@
{
s32 ret = BCME_OK;
s32 bssidx;
+
CFGP2P_DBG((" enter\n"));
wl_clr_p2p_status(cfg, DISCOVERY_ON);
-
#ifdef DHD_IFDEBUG
- WL_ERR(("%s: (cfg)->p2p->bss[type].bssidx: %d\n",
+ WL_ERR(("%s: bssidx: %d\n",
__FUNCTION__, (cfg)->p2p->bss[P2PAPI_BSSCFG_DEVICE].bssidx));
-#endif
+#endif // endif
bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
if (bssidx <= 0) {
CFGP2P_ERR((" do nothing, not initialized\n"));
return 0;
}
- ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
- bssidx);
-
+ ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
if (unlikely(ret < 0)) {
-
CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
}
/* Do a scan abort to stop the driver's scan engine in case it is still
@@ -871,8 +928,15 @@
return ret;
}
+/* Scan parameters */
+#define P2PAPI_SCAN_NPROBES 1
+#define P2PAPI_SCAN_DWELL_TIME_MS 80
+#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
+#define P2PAPI_SCAN_HOME_TIME_MS 60
+#define P2PAPI_SCAN_NPROBS_TIME_MS 30
+#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
s32
-wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active,
+wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active_scan,
u32 num_chans, u16 *channels,
s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
p2p_scan_purpose_t p2p_scan_purpose)
@@ -884,20 +948,26 @@
s8 *memblk;
wl_p2p_scan_t *p2p_params;
wl_escan_params_t *eparams;
+ wl_escan_params_v2_t *eparams_v2;
wlc_ssid_t ssid;
- /* Scan parameters */
-#define P2PAPI_SCAN_NPROBES 1
-#define P2PAPI_SCAN_DWELL_TIME_MS 80
-#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
-#define P2PAPI_SCAN_HOME_TIME_MS 60
-#define P2PAPI_SCAN_NPROBS_TIME_MS 30
-#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
+ u32 sync_id = 0;
+ s32 nprobes = 0;
+ s32 active_time = 0;
+ const struct ether_addr *mac_addr = NULL;
+ u32 scan_type = 0;
+ struct net_device *pri_dev = NULL;
- struct net_device *pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
+ pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
/* Allocate scan params which need space for 3 channels and 0 ssids */
- eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
- OFFSETOF(wl_escan_params_t, params)) +
- num_chans * sizeof(eparams->params.channel_list[0]);
+ if (cfg->scan_params_v2) {
+ eparams_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
+ OFFSETOF(wl_escan_params_v2_t, params)) +
+ num_chans * sizeof(eparams->params.channel_list[0]);
+ } else {
+ eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
+ OFFSETOF(wl_escan_params_t, params)) +
+ num_chans * sizeof(eparams->params.channel_list[0]);
+ }
memsize = sizeof(wl_p2p_scan_t) + eparams_size;
memblk = scanparambuf;
@@ -906,8 +976,8 @@
memsize, sizeof(scanparambuf)));
return -1;
}
- memset(memblk, 0, memsize);
- memset(cfg->ioctl_buf, 0, WLC_IOCTL_MAXLEN);
+ bzero(memblk, memsize);
+ bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
if (search_state == WL_P2P_DISC_ST_SEARCH) {
/*
* If we in SEARCH STATE, we don't need to set SSID explictly
@@ -916,7 +986,7 @@
wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx);
/* use null ssid */
ssid.SSID_len = 0;
- memset(&ssid.SSID, 0, sizeof(ssid.SSID));
+ bzero(&ssid.SSID, sizeof(ssid.SSID));
} else if (search_state == WL_P2P_DISC_ST_SCAN) {
/* SCAN STATE 802.11 SCAN
* WFD Supplicant has p2p_find command with (type=progressive, type= full)
@@ -927,91 +997,122 @@
wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
/* use wild card ssid */
ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN;
- memset(&ssid.SSID, 0, sizeof(ssid.SSID));
+ bzero(&ssid.SSID, sizeof(ssid.SSID));
memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN);
} else {
CFGP2P_ERR((" invalid search state %d\n", search_state));
return -1;
}
-
/* Fill in the P2P scan structure at the start of the iovar param block */
p2p_params = (wl_p2p_scan_t*) memblk;
p2p_params->type = 'E';
- /* Fill in the Scan structure that follows the P2P scan structure */
- eparams = (wl_escan_params_t*) (p2p_params + 1);
- eparams->params.bss_type = DOT11_BSSTYPE_ANY;
- if (active)
- eparams->params.scan_type = DOT11_SCANTYPE_ACTIVE;
- else
- eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE;
- if (tx_dst_addr == NULL)
- memcpy(&eparams->params.bssid, ðer_bcast, ETHER_ADDR_LEN);
- else
- memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN);
+ if (!active_scan) {
+ scan_type = WL_SCANFLAGS_PASSIVE;
+ }
- if (ssid.SSID_len)
- memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t));
-
- eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
+ if (tx_dst_addr == NULL) {
+ mac_addr = ðer_bcast;
+ } else {
+ mac_addr = tx_dst_addr;
+ }
switch (p2p_scan_purpose) {
case P2P_SCAN_SOCIAL_CHANNEL:
- eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
+ active_time = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
break;
case P2P_SCAN_AFX_PEER_NORMAL:
case P2P_SCAN_AFX_PEER_REDUCED:
- eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS);
+ active_time = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
break;
case P2P_SCAN_CONNECT_TRY:
- eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
+ active_time = WL_SCAN_CONNECT_DWELL_TIME_MS;
break;
- default :
- if (wl_get_drv_status_all(cfg, CONNECTED))
- eparams->params.active_time = -1;
- else
- eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
+ default:
+ active_time = wl_get_drv_status_all(cfg, CONNECTED) ?
+ -1 : P2PAPI_SCAN_DWELL_TIME_MS;
break;
}
- if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY)
- eparams->params.nprobes = htod32(eparams->params.active_time /
- WL_SCAN_JOIN_PROBE_INTERVAL_MS);
- else
- eparams->params.nprobes = htod32((eparams->params.active_time /
- P2PAPI_SCAN_NPROBS_TIME_MS));
-
-
- if (eparams->params.nprobes <= 0)
- eparams->params.nprobes = 1;
- CFGP2P_DBG(("nprobes # %d, active_time %d\n",
- eparams->params.nprobes, eparams->params.active_time));
- eparams->params.passive_time = htod32(-1);
- eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
- (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
-
- for (i = 0; i < num_chans; i++) {
- eparams->params.channel_list[i] = wl_ch_host_to_driver(bssidx, channels[i]);
+ if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY) {
+ nprobes = active_time /
+ WL_SCAN_JOIN_PROBE_INTERVAL_MS;
+ } else {
+ nprobes = active_time /
+ P2PAPI_SCAN_NPROBS_TIME_MS;
}
- eparams->version = htod32(ESCAN_REQ_VERSION);
- eparams->action = htod16(action);
- wl_escan_set_sync_id(eparams->sync_id, cfg);
+
+ if (nprobes <= 0) {
+ nprobes = 1;
+ }
+
+ wl_escan_set_sync_id(sync_id, cfg);
+ /* Fill in the Scan structure that follows the P2P scan structure */
+ if (cfg->scan_params_v2) {
+ eparams_v2 = (wl_escan_params_v2_t*) (p2p_params + 1);
+ eparams_v2->version = htod16(ESCAN_REQ_VERSION_V2);
+ eparams_v2->action = htod16(action);
+ eparams_v2->params.version = htod16(WL_SCAN_PARAMS_VERSION_V2);
+ eparams_v2->params.length = htod16(sizeof(wl_scan_params_v2_t));
+ eparams_v2->params.bss_type = DOT11_BSSTYPE_ANY;
+ eparams_v2->params.scan_type = htod32(scan_type);
+ (void)memcpy_s(&eparams_v2->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
+ eparams_v2->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
+ eparams_v2->params.active_time = htod32(active_time);
+ eparams_v2->params.nprobes = htod32(nprobes);
+ eparams_v2->params.passive_time = htod32(-1);
+ eparams_v2->sync_id = sync_id;
+ for (i = 0; i < num_chans; i++) {
+ eparams_v2->params.channel_list[i] =
+ wl_ch_host_to_driver(channels[i]);
+ }
+ eparams_v2->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
+ (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
+ if (ssid.SSID_len)
+ (void)memcpy_s(&eparams_v2->params.ssid,
+ sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
+ sync_id = eparams_v2->sync_id;
+ } else {
+ eparams = (wl_escan_params_t*) (p2p_params + 1);
+ eparams->version = htod32(ESCAN_REQ_VERSION);
+ eparams->action = htod16(action);
+ eparams->params.bss_type = DOT11_BSSTYPE_ANY;
+ eparams->params.scan_type = htod32(scan_type);
+ (void)memcpy_s(&eparams->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
+ eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
+ eparams->params.active_time = htod32(active_time);
+ eparams->params.nprobes = htod32(nprobes);
+ eparams->params.passive_time = htod32(-1);
+ eparams->sync_id = sync_id;
+ for (i = 0; i < num_chans; i++) {
+ eparams->params.channel_list[i] =
+ wl_ch_host_to_driver(channels[i]);
+ }
+ eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
+ (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
+ if (ssid.SSID_len)
+ (void)memcpy_s(&eparams->params.ssid,
+ sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
+ sync_id = eparams->sync_id;
+ }
+
wl_escan_set_type(cfg, WL_SCANTYPE_P2P);
- CFGP2P_INFO(("SCAN CHANNELS : "));
- for (i = 0; i < num_chans; i++) {
- if (i == 0) CFGP2P_INFO(("%d", channels[i]));
- else CFGP2P_INFO((",%d", channels[i]));
+ CFGP2P_DBG(("nprobes:%d active_time:%d\n", nprobes, active_time));
+ CFGP2P_DBG(("SCAN CHANNELS : "));
+ CFGP2P_DBG(("%d", channels[0]));
+ for (i = 1; i < num_chans; i++) {
+ CFGP2P_DBG((",%d", channels[i]));
}
-
- CFGP2P_INFO(("\n"));
+ CFGP2P_DBG(("\n"));
ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
- WL_ERR(("P2P_SEARCH sync ID: %d, bssidx: %d\n", eparams->sync_id, bssidx));
- if (ret == BCME_OK)
+ WL_INFORM(("P2P_SEARCH sync ID: %d, bssidx: %d\n", sync_id, bssidx));
+ if (ret == BCME_OK) {
wl_set_p2p_status(cfg, SCANNING);
+ }
return ret;
}
@@ -1039,7 +1140,17 @@
chan_cnt = AF_PEER_SEARCH_CNT;
else
chan_cnt = SOCIAL_CHAN_CNT;
- default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL);
+
+ if (cfg->afx_hdl->pending_tx_act_frm && cfg->afx_hdl->is_active) {
+ wl_action_frame_t *action_frame;
+ action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
+ if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
+ chan_cnt = 1;
+ p2p_scan_purpose = P2P_SCAN_AFX_PEER_REDUCED;
+ }
+ }
+
+ default_chan_list = (u16 *)MALLOCZ(cfg->osh, chan_cnt * sizeof(*default_chan_list));
if (default_chan_list == NULL) {
CFGP2P_ERR(("channel list allocation failed \n"));
ret = -ENOMEM;
@@ -1059,7 +1170,7 @@
ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt,
default_chan_list, WL_P2P_DISC_ST_SEARCH,
WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose);
- kfree(default_chan_list);
+ MFREE(cfg->osh, default_chan_list, chan_cnt * sizeof(*default_chan_list));
exit:
return ret;
}
@@ -1076,90 +1187,87 @@
/* Check whether the given IE looks like WFA WFDisplay IE. */
#ifndef WFA_OUI_TYPE_WFD
#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
-#endif
+#endif // endif
#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
-
/* Is any of the tlvs the expected entry? If
* not update the tlvs buffer pointer/length.
*/
static bool
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
+wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
+ const u8 *oui, u32 oui_len, u8 type)
{
/* If the contents match the OUI and the type */
- if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
- !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
- type == ie[TLV_BODY_OFF + oui_len]) {
+ if (ie->len >= oui_len + 1 &&
+ !bcmp(ie->data, oui, oui_len) &&
+ type == ie->data[oui_len]) {
return TRUE;
}
- if (tlvs == NULL)
- return FALSE;
/* point to the next ie */
- ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
- /* calculate the length of the rest of the buffer */
- *tlvs_len -= (int)(ie - *tlvs);
- /* update the pointer to the start of the buffer */
- *tlvs = ie;
+ if (tlvs != NULL) {
+ bcm_tlv_buffer_advance_past(ie, tlvs, tlvs_len);
+ }
return FALSE;
}
-wpa_ie_fixed_t *
-wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
+const wpa_ie_fixed_t *
+wl_cfgp2p_find_wpaie(const u8 *parse, u32 len)
{
- bcm_tlv_t *ie;
+ const bcm_tlv_t *ie;
- while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
- if (wl_cfgp2p_is_wpa_ie((u8*)ie, &parse, &len)) {
- return (wpa_ie_fixed_t *)ie;
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_wpa_ie(ie, &parse, &len)) {
+ return (const wpa_ie_fixed_t *)ie;
}
}
return NULL;
}
-wpa_ie_fixed_t *
-wl_cfgp2p_find_wpsie(u8 *parse, u32 len)
+const wpa_ie_fixed_t *
+wl_cfgp2p_find_wpsie(const u8 *parse, u32 len)
{
- bcm_tlv_t *ie;
+ const bcm_tlv_t *ie;
- while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
- if (wl_cfgp2p_is_wps_ie((u8*)ie, &parse, &len)) {
- return (wpa_ie_fixed_t *)ie;
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_wps_ie(ie, &parse, &len)) {
+ return (const wpa_ie_fixed_t *)ie;
}
}
return NULL;
}
wifi_p2p_ie_t *
-wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
+wl_cfgp2p_find_p2pie(const u8 *parse, u32 len)
{
bcm_tlv_t *ie;
- while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
- if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len)) {
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_p2p_ie(ie, &parse, &len)) {
return (wifi_p2p_ie_t *)ie;
}
}
return NULL;
}
-wifi_wfd_ie_t *
-wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
+const wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(const u8 *parse, u32 len)
{
- bcm_tlv_t *ie;
+ const bcm_tlv_t *ie;
- while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
- if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
- return (wifi_wfd_ie_t *)ie;
+ while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_wfd_ie(ie, &parse, &len)) {
+ return (const wifi_wfd_ie_t *)ie;
}
}
return NULL;
}
+
u32
wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
- s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd)
+ s8 *oui, s32 ie_id, const s8 *data, s32 datalen, const s8* add_del_cmd)
{
vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */
s32 iecount;
@@ -1168,18 +1276,23 @@
/* Validate the pktflag parameter */
if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
- VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG))) {
+ VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG |
+ VNDR_IE_DISASSOC_FLAG))) {
CFGP2P_ERR(("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag));
return -1;
}
/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
- strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
- hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+ strlcpy(hdr.cmd, add_del_cmd, sizeof(hdr.cmd));
/* Set the IE count - the buffer contains only 1 IE */
iecount = htod32(1);
memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+ /* For vendor ID DOT11_MNG_ID_EXT_ID, need to set pkt flag to VNDR_IE_CUSTOM_FLAG */
+ if (ie_id == DOT11_MNG_ID_EXT_ID) {
+ pktflag = pktflag | VNDR_IE_CUSTOM_FLAG;
+ }
/* Copy packet flags that indicate which packets will contain this IE */
pktflag = htod32(pktflag);
@@ -1249,7 +1362,10 @@
CFGP2P_ERR((" argument is invalid\n"));
goto exit;
}
-
+ if (!cfg->p2p) {
+ CFGP2P_ERR(("p2p if does not exist\n"));
+ goto exit;
+ }
for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
*type = i;
@@ -1276,10 +1392,31 @@
CFGP2P_DBG((" Enter\n"));
#ifdef DHD_IFDEBUG
- WL_ERR(("%s: cfg: %p, cfgdev: %p, cfg->wdev: %p, cfg->p2p_wdev: %p\n",
- __FUNCTION__, cfg, cfgdev, cfg->wdev, cfg->p2p_wdev));
-#endif
+ PRINT_WDEV_INFO(cfgdev);
+#endif /* DHD_IFDEBUG */
+
ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+#ifdef P2P_LISTEN_OFFLOADING
+ if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
+ wl_clr_p2p_status(cfg, DISC_IN_PROGRESS);
+ CFGP2P_ERR(("DISC_IN_PROGRESS cleared\n"));
+ if (ndev && (ndev->ieee80211_ptr != NULL)) {
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
+ cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
+ &cfg->remain_on_chan, GFP_KERNEL);
+ } else {
+ CFGP2P_ERR(("Invalid cfgdev. Dropping the"
+ "remain_on_channel_expired event.\n"));
+ }
+#else
+ cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
+ &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ }
+ }
+#endif /* P2P_LISTEN_OFFLOADING */
if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) {
wl_set_p2p_status(cfg, LISTEN_EXPIRED);
@@ -1318,20 +1455,36 @@
#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
if (ndev && (ndev->ieee80211_ptr != NULL)) {
#if defined(WL_CFG80211_P2P_DEV_IF)
- if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
+ if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy &&
+ bcmcfg_to_p2p_wdev(cfg)) {
/*
* To prevent kernel panic,
* if cfgdev->wiphy may be invalid, adding explicit check
*/
- cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
- &cfg->remain_on_chan, GFP_KERNEL);
- } else {
+ struct wireless_dev *wdev_dpp_listen = NULL;
+ wdev_dpp_listen = wl_get_wdev_by_dpp_listen(cfg);
+ /*
+ * check if dpp listen was trigerred
+ * if so, clear dpp disten flag and route the event for listen
+ * complete on the interface on which listen was reqeusted.
+ */
+ if (wdev_dpp_listen) {
+ wl_set_dpp_listen_by_netdev(cfg, wdev_dpp_listen->netdev, 0);
+ cfg80211_remain_on_channel_expired(wdev_dpp_listen,
+ cfg->last_roc_id, &cfg->remain_on_chan, GFP_KERNEL);
+ } else {
+ cfg80211_remain_on_channel_expired(bcmcfg_to_p2p_wdev(cfg),
+ cfg->last_roc_id, &cfg->remain_on_chan, GFP_KERNEL);
+ }
+
+ } else
CFGP2P_ERR(("Invalid cfgdev. Dropping the"
"remain_on_channel_expired event.\n"));
- }
#else
- cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
- &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
+ if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy)
+ cfg80211_remain_on_channel_expired(cfgdev,
+ cfg->last_roc_id, &cfg->remain_on_chan,
+ cfg->remain_on_chan_type, GFP_KERNEL);
#endif /* WL_CFG80211_P2P_DEV_IF */
}
}
@@ -1351,30 +1504,32 @@
* We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
* so lets do it from thread context.
*/
-
void
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
-wl_cfgp2p_listen_expired(struct timer_list *t)
-{
- struct p2p_info *p2p = from_timer(p2p, t, listen_timer);
- struct bcm_cfg80211 *cfg = p2p->cfg;
-#else
wl_cfgp2p_listen_expired(unsigned long data)
{
- struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
-#endif
wl_event_msg_t msg;
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
+ struct net_device *ndev;
CFGP2P_DBG((" Enter\n"));
+
+ if (!cfg) {
+ CFGP2P_ERR((" No cfg\n"));
+ return;
+ }
bzero(&msg, sizeof(wl_event_msg_t));
msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
msg.bsscfgidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
#if defined(WL_ENABLE_P2P_IF)
- wl_cfg80211_event(cfg->p2p_net ? cfg->p2p_net :
- wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
+ ndev = cfg->p2p_net ? cfg->p2p_net :
+ wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
#else
- wl_cfg80211_event(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg,
- NULL);
+ ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
#endif /* WL_ENABLE_P2P_IF */
+ if (!ndev) {
+ CFGP2P_ERR((" No ndev\n"));
+ return;
+ }
+ wl_cfg80211_event(ndev, &msg, NULL);
}
/*
* Routine for cancelling the P2P LISTEN
@@ -1391,7 +1546,7 @@
del_timer_sync(&cfg->p2p->listen_timer);
if (notify) {
#if defined(WL_CFG80211_P2P_DEV_IF)
- if (wdev)
+ if (bcmcfg_to_p2p_wdev(cfg))
cfg80211_remain_on_channel_expired(wdev, cfg->last_roc_id,
&cfg->remain_on_chan, GFP_KERNEL);
#else
@@ -1419,7 +1574,7 @@
{
#define EXTRA_DELAY_TIME 100
s32 ret = BCME_OK;
- struct timer_list *_timer;
+ timer_list_compat_t *_timer;
s32 extra_delay;
struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
@@ -1469,7 +1624,6 @@
return ret;
}
-
s32
wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable)
{
@@ -1509,6 +1663,8 @@
u32 event_type = ntoh32(e->event_type);
u32 status = ntoh32(e->status);
struct net_device *ndev = NULL;
+ u8 bsscfgidx = e->bsscfgidx;
+
CFGP2P_DBG((" Enter\n"));
ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
@@ -1516,22 +1672,26 @@
if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
- CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
+ CFGP2P_DBG((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
if (status == WLC_E_STATUS_SUCCESS) {
wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
- CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n"));
+ CFGP2P_ACTION(("TX actfrm : ACK\n"));
if (!cfg->need_wait_afrx && cfg->af_sent_channel) {
CFGP2P_DBG(("no need to wait next AF.\n"));
- wl_stop_wait_next_action_frame(cfg, ndev);
+ wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
}
}
else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
wl_set_p2p_status(cfg, ACTION_TX_NOACK);
- CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
- wl_stop_wait_next_action_frame(cfg, ndev);
+ if (status == WLC_E_STATUS_SUPPRESS) {
+ CFGP2P_ACTION(("TX actfrm : SUPPRES\n"));
+ } else {
+ CFGP2P_ACTION(("TX actfrm : NO ACK\n"));
+ }
+ wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
}
} else {
- CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
+ CFGP2P_DBG((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
"status : %d\n", status));
if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
@@ -1557,9 +1717,8 @@
s32 timeout = 0;
wl_eventmsg_buf_t buf;
-
- CFGP2P_INFO(("\n"));
- CFGP2P_INFO(("channel : %u , dwell time : %u\n",
+ CFGP2P_DBG(("\n"));
+ CFGP2P_DBG(("channel : %u , dwell time : %u\n",
af_params->channel, af_params->dwell_time));
wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
@@ -1580,7 +1739,7 @@
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
if (ret < 0) {
- CFGP2P_ERR((" sending action frame is failed\n"));
+ CFGP2P_ACTION(("TX actfrm : ERROR\n"));
goto exit;
}
@@ -1588,21 +1747,21 @@
msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX));
if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
- CFGP2P_INFO(("tx action frame operation is completed\n"));
+ CFGP2P_DBG(("tx action frame operation is completed\n"));
ret = BCME_OK;
} else if (ETHER_ISBCAST(&cfg->afx_hdl->tx_dst_addr)) {
- CFGP2P_INFO(("bcast tx action frame operation is completed\n"));
+ CFGP2P_DBG(("bcast tx action frame operation is completed\n"));
ret = BCME_OK;
} else {
ret = BCME_ERROR;
- CFGP2P_INFO(("tx action frame operation is failed\n"));
+ CFGP2P_DBG(("tx action frame operation is failed\n"));
}
/* clear status bit for action tx */
wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
exit:
- CFGP2P_INFO((" via act frame iovar : status = %d\n", ret));
+ CFGP2P_DBG((" via act frame iovar : status = %d\n", ret));
bzero(&buf, sizeof(wl_eventmsg_buf_t));
wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false);
@@ -1688,64 +1847,7 @@
subel += subelt_len;
}
}
-/*
- * Check if a BSS is up.
- * This is a common implementation called by most OSL implementations of
- * p2posl_bss_isup(). DO NOT call this function directly from the
- * common code -- call p2posl_bss_isup() instead to allow the OSL to
- * override the common implementation if necessary.
- */
-bool
-wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
-{
- s32 result, val;
- bool isup = false;
- s8 getbuf[64];
- /* Check if the BSS is up */
- *(int*)getbuf = -1;
- result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
- sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
- if (result != 0) {
- CFGP2P_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
- CFGP2P_ERR(("NOTE: this ioctl error is normal "
- "when the BSS has not been created yet.\n"));
- } else {
- val = *(int*)getbuf;
- val = dtoh32(val);
- CFGP2P_INFO(("---cfg bss -C %d ==> %d\n", bsscfg_idx, val));
- isup = (val ? TRUE : FALSE);
- }
- return isup;
-}
-
-
-/* Bring up or down a BSS */
-s32
-wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 is_up)
-{
- s32 ret = BCME_OK;
- s32 val = is_up ? 1 : 0;
-
- struct {
- s32 cfg;
- s32 val;
- } bss_setbuf;
-
- bss_setbuf.cfg = htod32(bsscfg_idx);
- bss_setbuf.val = htod32(val);
- CFGP2P_INFO(("---cfg bss -C %d %s\n", bsscfg_idx, is_up ? "up" : "down"));
- ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
- cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
- if (ret != 0) {
- CFGP2P_ERR(("'bss %d' failed with %d\n", is_up, ret));
- }
-
- return ret;
-}
-
-/* Check if 'p2p' is supported in the driver */
s32
wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev)
{
@@ -1776,7 +1878,6 @@
{
struct net_device *ndev = NULL;
struct wireless_dev *wdev = NULL;
- s32 i = 0, index = -1;
#if defined(WL_CFG80211_P2P_DEV_IF)
ndev = bcmcfg_to_prmry_ndev(cfg);
@@ -1788,18 +1889,21 @@
wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE);
wl_cfgp2p_disable_discovery(cfg);
-#if defined(WL_CFG80211_P2P_DEV_IF)
+
+#if defined(WL_CFG80211_P2P_DEV_IF) && !defined(KEEP_WIFION_OPTION)
+/*
+ * In CUSTOMER_HW4 implementation "ifconfig wlan0 down" can get
+ * called during phone suspend and customer requires the p2p
+ * discovery interface to be left untouched so that the user
+ * space can resume without any problem.
+ */
if (cfg->p2p_wdev) {
/* If p2p wdev is left out, clean it up */
WL_ERR(("Clean up the p2p discovery IF\n"));
wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
}
-#endif /* WL_CFG80211_P2P_DEV_IF */
- for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
- index = wl_to_p2p_bss_bssidx(cfg, i);
- if (index != WL_INVALID)
- wl_cfg80211_clear_per_bss_ies(cfg, index);
- }
+#endif /* WL_CFG80211_P2P_DEV_IF !defined(KEEP_WIFION_OPTION) */
+
wl_cfgp2p_deinit_priv(cfg);
return 0;
}
@@ -1821,9 +1925,10 @@
int count, start, duration;
wl_p2p_sched_t dongle_noa;
s32 bssidx, type;
+ int iovar_len = sizeof(dongle_noa);
CFGP2P_DBG((" Enter\n"));
- memset(&dongle_noa, 0, sizeof(dongle_noa));
+ bzero(&dongle_noa, sizeof(dongle_noa));
if (wl_cfgp2p_vif_created(cfg)) {
cfg->p2p->noa.desc[0].start = 0;
@@ -1882,8 +1987,12 @@
if (wl_cfgp2p_find_type(cfg, bssidx, &type) != BCME_OK)
return BCME_ERROR;
+ if (dongle_noa.action == WL_P2P_SCHED_ACTION_RESET) {
+ iovar_len -= sizeof(wl_p2p_sched_desc_t);
+ }
+
ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, type),
- "p2p_noa", &dongle_noa, sizeof(dongle_noa), cfg->ioctl_buf,
+ "p2p_noa", &dongle_noa, iovar_len, cfg->ioctl_buf,
WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (ret < 0) {
@@ -1972,8 +2081,8 @@
}
if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) {
- ret = wldev_ioctl(dev,
- WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true);
+ ret = wldev_ioctl_set(dev,
+ WLC_SET_PM, &legacy_ps, sizeof(legacy_ps));
if (unlikely(ret))
CFGP2P_ERR(("error (%d)\n", ret));
wl_cfg80211_update_power_mode(dev);
@@ -2015,11 +2124,12 @@
return BCME_ERROR;
}
+ memset_s(&csa_arg, sizeof(csa_arg), 0, sizeof(csa_arg));
csa_arg.mode = DOT11_CSA_MODE_ADVISORY;
csa_arg.count = P2P_ECSA_CNT;
csa_arg.reg = 0;
- sprintf(buf, "%d/%d", ch, bw);
+ snprintf(buf, len, "%d/%d", ch, bw);
chnsp = wf_chspec_aton(buf);
if (chnsp == 0) {
CFGP2P_ERR(("%s:chsp is not correct\n", __FUNCTION__));
@@ -2041,12 +2151,46 @@
return BCME_OK;
}
-u8 *
-wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
+s32
+wl_cfgp2p_increase_p2p_bw(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
{
- wifi_p2p_ie_t *ie = NULL;
+ int algo;
+ int bw;
+ int ret = BCME_OK;
+
+ sscanf(buf, "%3d", &bw);
+ if (bw == 0) {
+ algo = 0;
+ ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
+ WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
+ return BCME_ERROR;
+ }
+ } else {
+ algo = 1;
+ ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
+ WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
+ return BCME_ERROR;
+ }
+ ret = wldev_iovar_setbuf(ndev, "mchan_bw", &bw, sizeof(algo), cfg->ioctl_buf,
+ WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+ if (ret < 0) {
+ CFGP2P_ERR(("fw set mchan_bw failed %d\n", ret));
+ return BCME_ERROR;
+ }
+ }
+ return BCME_OK;
+}
+
+const u8 *
+wl_cfgp2p_retreive_p2pattrib(const void *buf, u8 element_id)
+{
+ const wifi_p2p_ie_t *ie = NULL;
u16 len = 0;
- u8 *subel;
+ const u8 *subel;
u8 subelt_id;
u16 subelt_len;
@@ -2055,7 +2199,7 @@
return 0;
}
- ie = (wifi_p2p_ie_t*) buf;
+ ie = (const wifi_p2p_ie_t*) buf;
len = ie->len;
/* Point subel to the P2P IE's subelt field.
@@ -2094,43 +2238,50 @@
#define P2P_GROUP_CAPAB_GO_BIT 0x01
-u8*
-wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib)
+const u8*
+wl_cfgp2p_find_attrib_in_all_p2p_Ies(const u8 *parse, u32 len, u32 attrib)
{
bcm_tlv_t *ie;
- u8* pAttrib;
+ const u8* pAttrib;
+ uint ie_len;
- CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
- while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
- if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) {
+ CFGP2P_DBG(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
+ ie_len = len;
+ while ((ie = bcm_parse_tlvs(parse, ie_len, DOT11_MNG_VS_ID))) {
+ if (wl_cfgp2p_is_p2p_ie(ie, &parse, &ie_len) == TRUE) {
/* Have the P2p ie. Now check for attribute */
- if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) {
- CFGP2P_INFO(("P2P attribute %d was found at parse %p",
+ if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(ie, attrib)) != NULL) {
+ CFGP2P_DBG(("P2P attribute %d was found at parse %p",
attrib, parse));
return pAttrib;
}
else {
- parse += (ie->len + TLV_HDR_LEN);
- len -= (ie->len + TLV_HDR_LEN);
+ /* move to next IE */
+ bcm_tlv_buffer_advance_past(ie, &parse, &ie_len);
+
CFGP2P_INFO(("P2P Attribute %d not found Moving parse"
- " to %p len to %d", attrib, parse, len));
+ " to %p len to %d", attrib, parse, ie_len));
}
}
else {
/* It was not p2p IE. parse will get updated automatically to next TLV */
- CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len));
+ CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, ie_len));
}
}
CFGP2P_ERR(("P2P attribute %d was NOT found", attrib));
return NULL;
}
-u8 *
+const u8 *
wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
{
- u8 *capability = NULL;
+ const u8 *capability = NULL;
bool p2p_go = 0;
- u8 *ptr = NULL;
+ const u8 *ptr = NULL;
+
+ if (bi->length != bi->ie_offset + bi->ie_length) {
+ return NULL;
+ }
if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) {
@@ -2173,13 +2324,15 @@
};
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT)
s32
wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
{
int ret = 0;
struct net_device* net = NULL;
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
struct wireless_dev *wdev = NULL;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 };
if (cfg->p2p_net) {
@@ -2193,15 +2346,16 @@
return -ENODEV;
}
- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
+ wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
if (unlikely(!wdev)) {
WL_ERR(("Could not allocate wireless device\n"));
free_netdev(net);
return -ENOMEM;
}
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
- strncpy(net->name, "p2p%d", sizeof(net->name) - 1);
- net->name[IFNAMSIZ - 1] = '\0';
+ strlcpy(net->name, "p2p%d", sizeof(net->name));
/* Copy the reference to bcm_cfg80211 */
memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *));
@@ -2215,38 +2369,50 @@
#else
ASSERT(!net->netdev_ops);
net->netdev_ops = &wl_cfgp2p_if_ops;
-#endif
+#endif // endif
/* Register with a dummy MAC addr */
memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
wdev->wiphy = cfg->wdev->wiphy;
wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
net->ieee80211_ptr = wdev;
+#else
+ net->ieee80211_ptr = NULL;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
net->ethtool_ops = &cfgp2p_ethtool_ops;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy));
/* Associate p2p0 network interface with new wdev */
wdev->netdev = net;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
ret = register_netdev(net);
if (ret) {
CFGP2P_ERR((" register_netdevice failed (%d)\n", ret));
free_netdev(net);
- kfree(wdev);
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
+ MFREE(cfg->osh, wdev, sizeof(*wdev));
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
return -ENODEV;
}
/* store p2p net ptr for further reference. Note that iflist won't have this
* entry as there corresponding firmware interface is a "Hidden" interface.
*/
+#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
cfg->p2p_wdev = wdev;
+#else
+ cfg->p2p_wdev = NULL;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
cfg->p2p_net = net;
printk("%s: P2P Interface Registered\n", net->name);
@@ -2292,7 +2458,11 @@
* For Android PRIV CMD handling map it to primary I/F
*/
if (cmd == SIOCDEVPRIVATE+1) {
- ret = wl_android_priv_cmd(ndev, ifr, cmd);
+#if defined(OEM_ANDROID)
+ ret = wl_android_priv_cmd(ndev, ifr);
+#else
+ (void)ndev;
+#endif // endif
} else {
CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n",
@@ -2302,14 +2472,14 @@
return ret;
}
-#endif
+#endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT */
#if defined(WL_ENABLE_P2P_IF)
static int wl_cfgp2p_if_open(struct net_device *net)
{
struct wireless_dev *wdev = net->ieee80211_ptr;
- if (!wdev || !wl_cfg80211_is_p2p_active())
+ if (!wdev || !wl_cfg80211_is_p2p_active(net))
return -EINVAL;
WL_TRACE(("Enter\n"));
#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
@@ -2330,11 +2500,12 @@
static int wl_cfgp2p_if_stop(struct net_device *net)
{
struct wireless_dev *wdev = net->ieee80211_ptr;
+ struct bcm_cfg80211 *cfg = wl_get_cfg(net);
if (!wdev)
return -EINVAL;
- wl_cfg80211_scan_stop(net);
+ wl_cfg80211_scan_stop(cfg, net);
#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
@@ -2363,27 +2534,54 @@
WL_TRACE(("Enter\n"));
if (cfg->p2p_wdev) {
- /*
- * This is not expected. This can happen due to
- * supplicant crash/unclean de-initialization which
- * didn't free the p2p discovery interface. Indicate
- * driver hang to user space so that the framework
- * can rei-init the Wi-Fi.
- */
+#ifndef EXPLICIT_DISCIF_CLEANUP
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* EXPLICIT_DISCIF_CLEANUP */
+ /*
+ * This is not expected. This can happen due to
+ * supplicant crash/unclean de-initialization which
+ * didn't free the p2p discovery interface. Indicate
+ * driver hang to user space so that the framework
+ * can rei-init the Wi-Fi.
+ */
CFGP2P_ERR(("p2p_wdev defined already.\n"));
wl_probe_wdev_all(cfg);
-
+#ifdef EXPLICIT_DISCIF_CLEANUP
+ /*
+ * CUSTOMER_HW4 design doesn't delete the p2p discovery
+ * interface on ifconfig wlan0 down context which comes
+ * without a preceeding NL80211_CMD_DEL_INTERFACE for p2p
+ * discovery. But during supplicant crash the DEL_IFACE
+ * command will not happen and will cause a left over iface
+ * even after ifconfig wlan0 down. So delete the iface
+ * first and then indicate the HANG event
+ */
+ wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
+#else
+ dhd->hang_reason = HANG_REASON_IFACE_DEL_FAILURE;
+#ifdef OEM_ANDROID
+#if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
+ if (dhd->memdump_enabled) {
+ /* Load the dongle side dump to host
+ * memory and then BUG_ON()
+ */
+ dhd->memdump_type = DUMP_TYPE_IFACE_OP_FAILURE;
+ dhd_bus_mem_dump(dhd);
+ }
+#endif /* BCMPCIE && DHD_FW_COREDUMP */
net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
+#endif /* OEM_ANDROID */
return ERR_PTR(-ENODEV);
+#endif /* EXPLICIT_DISCIF_CLEANUP */
}
- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
if (unlikely(!wdev)) {
WL_ERR(("Could not allocate wireless device\n"));
return ERR_PTR(-ENOMEM);
}
- memset(&primary_mac, 0, sizeof(primary_mac));
+ bzero(&primary_mac, sizeof(primary_mac));
get_primary_mac(cfg, &primary_mac);
wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
@@ -2391,12 +2589,16 @@
wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
memcpy(wdev->address, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE), ETHER_ADDR_LEN);
+#if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
+ if (cfg->p2p_net)
+ memcpy(cfg->p2p_net->dev_addr, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE),
+ ETHER_ADDR_LEN);
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
/* store p2p wdev ptr for further reference. */
cfg->p2p_wdev = wdev;
CFGP2P_ERR(("P2P interface registered\n"));
-
return wdev;
}
@@ -2426,7 +2628,7 @@
p2p_on(cfg) = true;
#if defined(P2P_IE_MISSING_FIX)
cfg->p2p_prb_noti = false;
-#endif
+#endif // endif
CFGP2P_DBG(("P2P interface started\n"));
@@ -2438,6 +2640,7 @@
wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
{
int ret = 0;
+ struct net_device *ndev = NULL;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
if (!cfg)
@@ -2445,13 +2648,28 @@
CFGP2P_DBG(("Enter\n"));
- ret = wl_cfg80211_scan_stop(wdev);
+ /* Check if cfg80211 interface is already down */
+ ndev = bcmcfg_to_prmry_ndev(cfg);
+ if (!wl_get_drv_status(cfg, READY, ndev)) {
+ WL_DBG(("cfg80211 interface is already down\n"));
+ return; /* it is even not ready */
+ }
+
+ ret = wl_cfg80211_scan_stop(cfg, wdev);
if (unlikely(ret < 0)) {
CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
}
- if (!cfg->p2p)
+ if (!p2p_is_on(cfg)) {
return;
+ }
+
+#ifdef P2P_LISTEN_OFFLOADING
+ wl_cfg80211_p2plo_deinit(cfg);
+#endif /* P2P_LISTEN_OFFLOADING */
+
+ /* Cancel any on-going listen */
+ wl_cfgp2p_cancel_listen(cfg, bcmcfg_to_prmry_ndev(cfg), wdev, TRUE);
ret = wl_cfgp2p_disable_discovery(cfg);
if (unlikely(ret < 0)) {
@@ -2470,10 +2688,12 @@
{
bool rollback_lock = false;
- if (!wdev)
+ if (!wdev || !cfg) {
+ WL_ERR(("null ptr. wdev:%p cfg:%p\n", wdev, cfg));
return -EINVAL;
+ }
- WL_TRACE(("Enter\n"));
+ WL_INFORM(("Enter\n"));
if (!rtnl_is_locked()) {
rtnl_lock();
@@ -2487,10 +2707,9 @@
synchronize_rcu();
- kfree(wdev);
+ MFREE(cfg->osh, wdev, sizeof(*wdev));
- if (cfg)
- cfg->p2p_wdev = NULL;
+ cfg->p2p_wdev = NULL;
CFGP2P_ERR(("P2P interface unregistered\n"));
--
Gitblit v1.6.2