From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:45:28 +0000 Subject: [PATCH] add boot partition size --- 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