aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEcco Park <eccopark@broadcom.com>2013-08-29 03:57:52 +0900
committerZiyan <jaraidaniel@gmail.com>2016-05-01 23:35:24 +0200
commit533cb9d9908bde24c4ef475767bb0b642bb12d13 (patch)
tree4d2d1f25da20b587f642989d3a7a7fd5b4c1b654 /drivers
parent10c3ec82c9ccc65fd266f45ceac395b1f5f1db2f (diff)
downloadkernel_samsung_tuna-533cb9d9908bde24c4ef475767bb0b642bb12d13.zip
kernel_samsung_tuna-533cb9d9908bde24c4ef475767bb0b642bb12d13.tar.gz
kernel_samsung_tuna-533cb9d9908bde24c4ef475767bb0b642bb12d13.tar.bz2
net: wireless: bcmdhd: Update to version 1.88.45
1. Remove WL_SUPPORT_AUTO_CHANNEL codes 2. add codes for WL_IFACE_COMB_NUM_CHANNELS and WL_CFG80211_P2P_DEV_IF to support concurent mode. (Google Bug : [9892309] support Wifi direct 5GHZ channels) but, remove the WL_IFACE_COM_NUM_CHANELS in Makefile 3. refactoring the codes for hidden ap roaming Signed-off-by: Ecco Park <eccopark@broadcom.com> Conflicts: drivers/net/wireless/bcmdhd/Makefile drivers/net/wireless/bcmdhd/wl_android.c drivers/net/wireless/bcmdhd/wl_cfg80211.c drivers/net/wireless/bcmdhd/wl_cfgp2p.c drivers/net/wireless/bcmdhd/wl_cfgp2p.h Change-Id: If8283f26714196aa971c186c57758c0e64ce87df
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c4
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pno.c2
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pno.h2
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c2
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h14
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c12
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c658
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h33
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c165
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h29
10 files changed, 479 insertions, 442 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 8559cca..98401b0 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c 419132 2013-08-19 21:33:05Z $
+ * $Id: dhd_linux.c 419821 2013-08-22 21:43:26Z $
*/
#include <typedefs.h>
@@ -3616,7 +3616,7 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd)
ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE;
if (mchan_supported)
ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE;
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
/* For customer_hw4, although ICS,
* we still support concurrent mode
*/
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c
index 5b86a1a..3a5d27d 100644
--- a/drivers/net/wireless/bcmdhd/dhd_pno.c
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_pno.c 419138 2013-08-19 22:11:30Z $
+ * $Id: dhd_pno.c 420056 2013-08-24 00:53:12Z $
*/
#include <typedefs.h>
#include <osl.h>
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h
index 25f54a5..1e02db1 100644
--- a/drivers/net/wireless/bcmdhd/dhd_pno.h
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_pno.h 419666 2013-08-22 03:35:55Z eccopark $
+ * $Id: dhd_pno.h 419969 2013-08-23 18:54:36Z $
*/
#ifndef __DHD_PNO_H__
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index 43af7c0..33bfb45 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_sdio.c 418699 2013-08-16 10:37:13Z $
+ * $Id: dhd_sdio.c 419981 2013-08-23 19:49:45Z $
*/
#include <typedefs.h>
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 883a373..21184c5 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -30,26 +30,26 @@
#define EPI_MINOR_VERSION 88
-#define EPI_RC_NUMBER 42
+#define EPI_RC_NUMBER 45
#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 1, 88, 42, 0
+#define EPI_VERSION 1, 88, 45, 0
-#define EPI_VERSION_NUM 0x01582a00
+#define EPI_VERSION_NUM 0x01582d00
-#define EPI_VERSION_DEV 1.88.42
+#define EPI_VERSION_DEV 1.88.45
/* Driver Version String, ASCII, 32 chars max */
#ifdef BCMINTERNAL
-#define EPI_VERSION_STR "1.88.42 (r BCMINT)"
+#define EPI_VERSION_STR "1.88.45 (r BCMINT)"
#else
#ifdef WLTEST
-#define EPI_VERSION_STR "1.88.42 (r WLTEST)"
+#define EPI_VERSION_STR "1.88.45 (r WLTEST)"
#else
-#define EPI_VERSION_STR "1.88.42 (r)"
+#define EPI_VERSION_STR "1.88.45 (r)"
#endif
#endif /* BCMINTERNAL */
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 9bd822f..c848a05 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_android.c 419132 2013-08-19 21:33:05Z $
+ * $Id: wl_android.c 420671 2013-08-28 11:37:19Z $
*/
#include <linux/module.h>
@@ -88,9 +88,6 @@
#define CMD_SETROAMMODE "SETROAMMODE"
#define CMD_MIRACAST "MIRACAST"
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
-#define CMD_GET_BEST_CHANNELS "GET_BEST_CHANNELS"
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
/* CCX Private Commands */
@@ -1002,13 +999,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len);
else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0)
bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len);
-#if defined(WL_SUPPORT_AUTO_CHANNEL)
- else if (strnicmp(command, CMD_GET_BEST_CHANNELS,
- strlen(CMD_GET_BEST_CHANNELS)) == 0) {
- bytes_written = wl_cfg80211_get_best_channels(net, command,
- priv_cmd.total_len);
- }
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0)
bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len);
else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index a09136c..9f99c81 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_cfg80211.c 419132 2013-08-19 21:33:05Z $
+ * $Id: wl_cfg80211.c 419844 2013-08-23 00:07:03Z $
*/
#include <typedefs.h>
#include <linuxver.h>
@@ -137,6 +137,69 @@ static const struct ieee80211_regdomain brcm_regdom = {
REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
};
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
+ (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
+/*
+ * Possible interface combinations supported by driver
+ *
+ * ADHOC Mode - #ADHOC <= 1 on channels = 1
+ * SoftAP Mode - #AP <= 1 on channels = 1
+ * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1
+ * on channels = 2
+ */
+static const struct ieee80211_iface_limit softap_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP),
+ },
+};
+
+static const struct ieee80211_iface_limit sta_p2p_limits[] = {
+ /*
+ * During P2P-GO removal, P2P-GO is first changed to STA and later only
+ * removed. So setting maximum possible number of STA interfaces as 2 to
+ * accommodate the above behaviour.
+ */
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
+ },
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+ },
+#endif /* WL_CFG80211_P2P_DEV_IF */
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_ADHOC),
+ },
+};
+
+static const struct ieee80211_iface_combination
+softap_iface_combinations[] = {
+ {
+ .num_different_channels = 1,
+ .max_interfaces = 1,
+ .limits = softap_limits,
+ .n_limits = ARRAY_SIZE(softap_limits),
+ },
+};
+
+static const struct ieee80211_iface_combination
+sta_p2p_iface_combinations[] = {
+ {
+ .num_different_channels = 2,
+ .max_interfaces = 3,
+ .limits = sta_p2p_limits,
+ .n_limits = ARRAY_SIZE(sta_p2p_limits),
+ },
+};
+#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
/* Data Element Definitions */
#define WPS_ID_CONFIG_METHODS 0x1008
@@ -196,9 +259,14 @@ static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request,
struct cfg80211_ssid *this_ssid);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
+#else
static s32
wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request);
+#endif /* WL_CFG80211_P2P_DEV_IF */
static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params);
@@ -214,10 +282,21 @@ static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme);
static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
u16 reason_code);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 mbm);
+#else
static s32
wl_cfg80211_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type, s32 dbm);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev, s32 *dbm);
+#else
static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
+#endif /* WL_CFG80211_P2P_DEV_IF */
static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx, bool unicast, bool multicast);
@@ -349,6 +428,7 @@ static void wl_ch_to_chanspec(int ch,
*/
static void wl_rst_ie(struct wl_priv *wl);
static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
+static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size);
static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
static u32 wl_get_ielen(struct wl_priv *wl);
@@ -362,8 +442,8 @@ wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request
#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
static s32 wl_inform_bss(struct wl_priv *wl);
-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done);
-static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done);
+static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
+static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
s32 wl_cfg80211_channel_to_freq(u32 channel);
@@ -825,6 +905,13 @@ wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
BIT(IEEE80211_STYPE_DEAUTH >> 4) |
BIT(IEEE80211_STYPE_ACTION >> 4)
},
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ [NL80211_IFTYPE_P2P_DEVICE] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+#endif /* WL_CFG80211_P2P_DEV_IF */
};
static void swap_key_from_BE(struct wl_wsec_key *key)
@@ -972,7 +1059,7 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
static bcm_struct_cfgdev *
wl_cfg80211_add_monitor_if(char *name)
{
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
WL_INFO(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
return ERR_PTR(-EOPNOTSUPP);
#else
@@ -981,12 +1068,16 @@ wl_cfg80211_add_monitor_if(char *name)
dhd_add_monitor(name, &ndev);
WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
return ndev_to_cfgdev(ndev);
-#endif
+#endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
}
static bcm_struct_cfgdev *
wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ const char *name,
+#else
char *name,
+#endif /* WL_CFG80211_P2P_DEV_IF */
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
@@ -1029,6 +1120,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
return NULL;
case NL80211_IFTYPE_MONITOR:
return wl_cfg80211_add_monitor_if(name);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ case NL80211_IFTYPE_P2P_DEVICE:
+ return wl_cfgp2p_add_p2p_disc_if();
+#endif /* WL_CFG80211_P2P_DEV_IF */
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
wlif_type = WL_P2P_IF_CLIENT;
@@ -1227,6 +1322,11 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
s32 index = -1;
WL_DBG(("Enter\n"));
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+ return wl_cfgp2p_del_p2p_disc_if(cfgdev);
+ }
+#endif /* WL_CFG80211_P2P_DEV_IF */
dev = cfgdev_to_wlc_ndev(cfgdev, wl);
if (wl_cfgp2p_find_idx(wl, dev, &index) != BCME_OK) {
@@ -2262,12 +2362,20 @@ scan_out:
return err;
}
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+#else
static s32
wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request)
+#endif /* WL_CFG80211_P2P_DEV_IF */
{
s32 err = 0;
struct wl_priv *wl = wiphy_priv(wiphy);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ struct net_device *ndev = wl_to_prmry_ndev(wl);
+#endif /* WL_CFG80211_P2P_DEV_IF */
WL_DBG(("Enter \n"));
RETURN_EIO_IF_NOT_UP(wl);
@@ -2484,6 +2592,8 @@ wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
/* change the command from "add" to "del" */
strncpy(wl->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
+ wl->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
ret = wldev_iovar_setbuf(dev, "ie",
wl->ibss_vsie, wl->ibss_vsie_len,
ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
@@ -3287,9 +3397,15 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
return err;
}
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 mbm)
+#else
static s32
wl_cfg80211_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type, s32 dbm)
+#endif /* WL_CFG80211_P2P_DEV_IF */
{
struct wl_priv *wl = wiphy_priv(wiphy);
@@ -3298,9 +3414,11 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
s32 err = 0;
s32 disable = 0;
s32 txpwrqdbm;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS)
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ s32 dbm = MBM_TO_DBM(mbm);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
dbm = MBM_TO_DBM(dbm);
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF */
RETURN_EIO_IF_NOT_UP(wl);
switch (type) {
@@ -3334,7 +3452,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
txpwrmw = (u16) dbm;
txpwrqdbm = (s32)bcm_mw_to_qdbm(txpwrmw);
#ifdef SUPPORT_WL_TXPOWER
- if (dbm == -1)
+ if (type == NL80211_TX_POWER_AUTOMATIC)
txpwrqdbm = 127;
txpwrqdbm |= WL_TXPWR_OVERRIDE;
#endif /* SUPPORT_WL_TXPOWER */
@@ -3348,7 +3466,12 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
return err;
}
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
+ struct wireless_dev *wdev, s32 *dbm)
+#else
static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+#endif /* WL_CFG80211_P2P_DEV_IF */
{
struct wl_priv *wl = wiphy_priv(wiphy);
struct net_device *ndev = wl_to_prmry_ndev(wl);
@@ -4166,11 +4289,17 @@ wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
return params;
}
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
+#else
static s32
wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
struct ieee80211_channel * channel,
enum nl80211_channel_type channel_type,
unsigned int duration, u64 *cookie)
+#endif /* WL_CFG80211_P2P_DEV_IF */
{
s32 target_channel;
u32 id;
@@ -4280,8 +4409,13 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
exit:
if (err == BCME_OK) {
WL_INFO(("Success\n"));
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ cfg80211_ready_on_channel(cfgdev, *cookie, channel,
+ duration, GFP_KERNEL);
+#else
cfg80211_ready_on_channel(cfgdev, *cookie, channel,
channel_type, duration, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
} else {
WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
}
@@ -4294,7 +4428,13 @@ wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
{
s32 err = 0;
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+ WL_DBG((" enter ) on P2P dedicated discover interface\n"));
+ }
+#else
WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
+#endif /* WL_CFG80211_P2P_DEV_IF */
return err;
}
@@ -4731,6 +4871,13 @@ exit:
}
#define MAX_NUM_OF_ASSOCIATED_DEV 64
+#if defined(WL_CFG80211_P2P_DEV_IF)
+static s32
+wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
+ struct ieee80211_channel *channel, bool offchan,
+ unsigned int wait, const u8* buf, size_t len, bool no_cck,
+ bool dont_wait_for_ack, u64 *cookie)
+#else
static s32
wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
struct ieee80211_channel *channel, bool offchan,
@@ -4744,6 +4891,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
bool dont_wait_for_ack,
#endif
u64 *cookie)
+#endif /* WL_CFG80211_P2P_DEV_IF */
{
wl_action_frame_t *action_frame;
wl_af_params_t *af_params;
@@ -5601,6 +5749,9 @@ wl_cfg80211_parse_ap_ies(
goto fail;
}
+ vndr = (u8 *)info->proberesp_ies;
+ vndr_ie_len = info->proberesp_ies_len;
+
if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
/* SoftAP mode */
struct ieee80211_mgmt *mgmt;
@@ -5610,10 +5761,6 @@ wl_cfg80211_parse_ap_ies(
vndr_ie_len = info->probe_resp_len -
offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
}
- } else {
- /* Other mode */
- vndr = (u8 *)info->proberesp_ies;
- vndr_ie_len = info->proberesp_ies_len;
}
/* Parse Probe Response IEs */
@@ -5648,6 +5795,9 @@ wl_cfg80211_set_ies(
WL_DBG(("Applied Vndr IEs for Beacon \n"));
}
+ vndr = (u8 *)info->proberesp_ies;
+ vndr_ie_len = info->proberesp_ies_len;
+
if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
/* SoftAP mode */
struct ieee80211_mgmt *mgmt;
@@ -5657,10 +5807,6 @@ wl_cfg80211_set_ies(
vndr_ie_len = info->probe_resp_len -
offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
}
- } else {
- /* Other mode */
- vndr = (u8 *)info->proberesp_ies;
- vndr_ie_len = info->proberesp_ies_len;
}
/* Set Probe Response IEs to FW */
@@ -5840,14 +5986,14 @@ wl_cfg80211_start_ap(
if (!check_dev_role_integrity(wl, dev_role))
goto fail;
-#if 0 || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+#if defined(WL_CFG80211_P2P_DEV_IF) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
if ((err = wl_cfg80211_set_channel(wiphy, dev,
dev->ieee80211_ptr->preset_chandef.chan,
NL80211_CHAN_HT20) < 0)) {
WL_ERR(("Set channel failed \n"));
goto fail;
}
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 6, 0)) */
if ((err = wl_cfg80211_bcn_set_params(info, dev,
dev_role, bssidx)) < 0) {
@@ -6242,6 +6388,10 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = wl_cfg80211_add_virtual_iface,
.del_virtual_intf = wl_cfg80211_del_virtual_iface,
.change_virtual_intf = wl_cfg80211_change_virtual_iface,
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ .start_p2p_device = wl_cfgp2p_start_p2p_device,
+ .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
+#endif /* WL_CFG80211_P2P_DEV_IF */
.scan = wl_cfg80211_scan,
.set_wiphy_params = wl_cfg80211_set_wiphy_params,
.join_ibss = wl_cfg80211_join_ibss,
@@ -6267,10 +6417,10 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.mgmt_tx = wl_cfg80211_mgmt_tx,
.mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
.change_bss = wl_cfg80211_change_bss,
-#if !0 && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+#if !defined(WL_CFG80211_P2P_DEV_IF) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
.set_channel = wl_cfg80211_set_channel,
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
+#endif /* !WL_CFG80211_P2P_DEV_IF && (LINUX_VERSION < VERSION(3, 6, 0)) */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
.set_beacon = wl_cfg80211_add_set_beacon,
.add_beacon = wl_cfg80211_add_set_beacon,
#else
@@ -6354,6 +6504,10 @@ wl_cfg80211_reg_notifier(
static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data)
{
s32 err = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
+ (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
+ dhd_pub_t *dhd = (dhd_pub_t *)data;
+#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
wdev->wiphy =
wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
@@ -6379,8 +6533,30 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
#if !defined(WL_ENABLE_P2P_IF)
| BIT(NL80211_IFTYPE_MONITOR)
#endif /* !WL_ENABLE_P2P_IF */
+#if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
+ | BIT(NL80211_IFTYPE_P2P_CLIENT)
+ | BIT(NL80211_IFTYPE_P2P_GO)
+#endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ | BIT(NL80211_IFTYPE_P2P_DEVICE)
+#endif /* WL_CFG80211_P2P_DEV_IF */
| BIT(NL80211_IFTYPE_AP);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
+ (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
+ if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
+ WL_DBG(("Setting interface combinations for SoftAP mode\n"));
+ wdev->wiphy->iface_combinations = softap_iface_combinations;
+ wdev->wiphy->n_iface_combinations =
+ ARRAY_SIZE(softap_iface_combinations);
+ } else {
+ WL_DBG(("Setting interface combinations for STA+P2P mode\n"));
+ wdev->wiphy->iface_combinations = sta_p2p_iface_combinations;
+ wdev->wiphy->n_iface_combinations =
+ ARRAY_SIZE(sta_p2p_iface_combinations);
+ }
+#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
+
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
@@ -6438,6 +6614,12 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
WL_ERR(("Couldn not register wiphy device (%d)\n", err));
wiphy_free(wdev->wiphy);
}
+
+#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
+ wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
+#endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */
+
return err;
}
@@ -6471,14 +6653,14 @@ static s32 wl_inform_bss(struct wl_priv *wl)
WL_DBG(("scanned AP count (%d)\n", bss_list->count));
bi = next_bss(bss_list, bi);
for_each_bss(bss_list, bi, i) {
- err = wl_inform_single_bss(wl, bi, 0);
+ err = wl_inform_single_bss(wl, bi);
if (unlikely(err))
break;
}
return err;
}
-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done)
+static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
{
struct wiphy *wiphy = wl_to_wiphy(wl);
struct ieee80211_mgmt *mgmt;
@@ -6493,7 +6675,6 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 i
u32 freq;
s32 err = 0;
gfp_t aflags;
- u8 *ie_offset = NULL;
if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
WL_DBG(("Beacon is larger than buffer. Discarding\n"));
@@ -6533,37 +6714,8 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 i
beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
wl_rst_ie(wl);
-
- ie_offset = ((u8 *) bi) + bi->ie_offset;
-
- if (is_roam_done && ((int)(*(ie_offset)) == WLAN_EID_SSID &&
- ((int)(*(ie_offset+1)) == 0 || (int)(*(ie_offset+2)) == 0))) {
- u8 *ie_new_offset = NULL;
- uint8 ie_new_length;
-
- WL_ERR(("WAR trace: Changing the SSID Info, from beacon %d\n",
- bi->flags & WL_BSS_FLAGS_FROM_BEACON));
-
- ie_new_offset = (u8 *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
- if (ie_new_offset) {
- *(ie_new_offset) = WLAN_EID_SSID;
- *(ie_new_offset+1) = bi->SSID_len;
- memcpy(ie_new_offset+2, bi->SSID, bi->SSID_len);
- ie_new_length = bi->ie_length - *(ie_offset+1) + bi->SSID_len;
-
- /* Copy the remaining IE apart from SSID IE from bi */
- memcpy(ie_new_offset+2 + bi->SSID_len,
- ie_offset+2 + *(ie_offset+1),
- bi->ie_length - 2 - *(ie_offset+1));
- wl_mrg_ie(wl, ie_new_offset, ie_new_length);
- kfree(ie_new_offset);
- } else {
- wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
- }
- } else {
- wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
- }
-
+ wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length);
+ wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
offsetof(struct wl_cfg80211_bss_info, frame_buf));
notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
@@ -6898,7 +7050,7 @@ wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
wl_get_assoc_ies(wl, ndev);
wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
- wl_update_bss_info(wl, ndev, 1);
+ wl_update_bss_info(wl, ndev);
cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
}
else {
@@ -6907,7 +7059,7 @@ wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
wl_link_up(wl);
wl_get_assoc_ies(wl, ndev);
wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
- wl_update_bss_info(wl, ndev, 1);
+ wl_update_bss_info(wl, ndev);
cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
wl_set_drv_status(wl, CONNECTED, ndev);
active = true;
@@ -7178,7 +7330,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
}
}
-static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done)
+static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
{
struct cfg80211_bss *bss;
struct wl_bss_info *bi;
@@ -7188,7 +7340,6 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is
s32 dtim_period;
size_t ie_len;
u8 *ie;
- u8 *ssidie;
u8 *curbssid;
s32 err = 0;
struct wiphy *wiphy;
@@ -7213,17 +7364,11 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is
}
bi = (struct wl_bss_info *)(wl->extra_buf + 4);
if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
+ WL_ERR(("Bssid doesn't match\n"));
err = -EIO;
goto update_bss_info_out;
}
-
- ie = ((u8 *)bi) + bi->ie_offset;
- ie_len = bi->ie_length;
- ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie, ie_len);
- if (ssidie && ssidie[1] == bi->SSID_len && !ssidie[2] && bi->SSID[0])
- memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
-
- err = wl_inform_single_bss(wl, bi, is_roam_done);
+ err = wl_inform_single_bss(wl, bi);
if (unlikely(err))
goto update_bss_info_out;
@@ -7232,8 +7377,13 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is
beacon_interval = cpu_to_le16(bi->beacon_period);
} else {
WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ ie = (u8 *)bss->ies->data;
+ ie_len = bss->ies->len;
+#else
ie = bss->information_elements;
ie_len = bss->len_information_elements;
+#endif /* WL_CFG80211_P2P_DEV_IF */
beacon_interval = bss->beacon_interval;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
cfg80211_put_bss(wiphy, bss);
@@ -7263,6 +7413,9 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is
wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
update_bss_info_out:
+ if (unlikely(err)) {
+ WL_ERR(("Failed with error %d\n", err));
+ }
mutex_unlock(&wl->usr_sync);
return err;
}
@@ -7287,7 +7440,7 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
wl_get_assoc_ies(wl, ndev);
wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
- wl_update_bss_info(wl, ndev, 1);
+ wl_update_bss_info(wl, ndev);
wl_update_pmklist(ndev, wl->pmk_list, err);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
@@ -7370,7 +7523,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
wl_get_assoc_ies(wl, ndev);
wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
- wl_update_bss_info(wl, ndev, 0);
+ wl_update_bss_info(wl, ndev);
wl_update_pmklist(ndev, wl->pmk_list, err);
wl_set_drv_status(wl, CONNECTED, ndev);
if (ndev != wl_to_prmry_ndev(wl)) {
@@ -9248,9 +9401,11 @@ void wl_cfg80211_detach(void *para)
wl_cfgp2p_deinit_priv(wl);
}
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev);
+#elif defined(WL_ENABLE_P2P_IF)
wl_cfg80211_detach_p2p();
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF */
wl_cfg80211_ibss_vsie_free(wl);
wl_deinit_priv(wl);
@@ -9270,7 +9425,7 @@ static void wl_wakeup_event(struct wl_priv *wl)
}
}
-#if defined(WL_ENABLE_P2P_IF)
+#if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF))
static int wl_is_p2p_event(struct wl_event_q *e)
{
switch (e->etype) {
@@ -9306,7 +9461,7 @@ static int wl_is_p2p_event(struct wl_event_q *e)
return FALSE;
}
}
-#endif
+#endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */
static s32 wl_event_handler(void *data)
{
@@ -9329,19 +9484,28 @@ static s32 wl_event_handler(void *data)
* there is no corresponding bsscfg for P2P interface. Map it to p2p0
* interface.
*/
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) {
+ cfgdev = wl_to_p2p_wdev(wl);
+ } else {
+ cfgdev = ndev_to_wdev(dhd_idx2net((struct dhd_pub *)(wl->pub),
+ e->emsg.ifidx));
+ }
+#elif defined(WL_ENABLE_P2P_IF)
if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
cfgdev = wl->p2p_net;
} else {
cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub),
e->emsg.ifidx);
}
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF */
if (!cfgdev) {
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ cfgdev = wl_to_prmry_wdev(wl);
+#elif defined(WL_ENABLE_P2P_IF)
cfgdev = wl_to_prmry_ndev(wl);
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF */
}
if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata);
@@ -10160,6 +10324,29 @@ static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
return err;
}
+static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size)
+{
+ u8 *ssidie;
+ ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
+ if (!ssidie)
+ return;
+ if (ssidie[1] != bi->SSID_len) {
+ if (ssidie[1]) {
+ WL_ERR(("%s: Wrong SSID len: %d != %d\n",
+ __FUNCTION__, ssidie[1], bi->SSID_len));
+ return;
+ }
+ memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream));
+ memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
+ *ie_size = *ie_size + bi->SSID_len;
+ ssidie[1] = bi->SSID_len;
+ return;
+ }
+ if (*(ssidie + 2) == '\0')
+ memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
+ return;
+}
+
static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
{
struct wl_ie *ie = wl_to_ie(wl);
@@ -10436,323 +10623,6 @@ exit:
return ret;
}
-#ifdef WL_SUPPORT_AUTO_CHANNEL
-static s32
-wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
-{
- u32 val = 0;
- s32 ret = BCME_ERROR;
- struct wl_priv *wl = wlcfg_drv_priv;
-
- /* Disable mpc, to avoid automatic interface down. */
- val = 0;
-
- ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
- sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
- &wl->ioctl_buf_sync);
- if (ret < 0) {
- WL_ERR(("set 'mpc' failed, error = %d\n", ret));
- goto done;
- }
-
- /* Set interface up, explicitly. */
- val = 1;
-
- ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
- if (ret < 0) {
- WL_ERR(("set interface up failed, error = %d\n", ret));
- goto done;
- }
-
- /* Stop all scan explicitly, till auto channel selection complete. */
- wl_set_drv_status(wl, SCANNING, ndev);
- ret = wl_notify_escan_complete(wl, ndev, true, true);
- if (ret < 0) {
- WL_ERR(("set scan abort failed, error = %d\n", ret));
- goto done;
- }
-
-done:
- return ret;
-}
-
-static bool
-wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
-{
- bool valid = false;
-
- /* channel 1 to 14 */
- if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
- valid = true;
- }
- /* channel 36 to 48 */
- else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
- valid = true;
- }
- /* channel 149 to 161 */
- else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
- valid = true;
- }
- else {
- valid = false;
- WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
- CHSPEC_CHANNEL(chanspec), chanspec));
- }
-
- return valid;
-}
-
-static s32
-wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
-{
- s32 ret = BCME_ERROR;
- struct wl_priv *wl = NULL;
- wl_uint32_list_t *list = NULL;
- chanspec_t chanspec = 0;
-
- memset(buf, 0, buflen);
-
- wl = wlcfg_drv_priv;
- list = (wl_uint32_list_t *)buf;
- list->count = htod32(WL_NUMCHANSPECS);
-
- /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
- chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
- WL_CHANSPEC_CTL_SB_NONE);
- chanspec = wl_chspec_host_to_driver(chanspec);
-
- ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
- sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
- if (ret < 0) {
- WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
- }
-
- return ret;
-}
-
-static s32
-wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
-{
- u32 channel = 0;
- s32 ret = BCME_ERROR;
- s32 i = 0;
- s32 j = 0;
- struct wl_priv *wl = NULL;
- wl_uint32_list_t *list = NULL;
- chanspec_t chanspec = 0;
-
- memset(buf, 0, buflen);
-
- wl = wlcfg_drv_priv;
- list = (wl_uint32_list_t *)buf;
- list->count = htod32(WL_NUMCHANSPECS);
-
- /* Restrict channels to 5GHz, 20MHz BW, no SB. */
- chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
- WL_CHANSPEC_CTL_SB_NONE);
- chanspec = wl_chspec_host_to_driver(chanspec);
-
- ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
- sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
- if (ret < 0) {
- WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
- goto done;
- }
-
- /* Skip DFS and inavlid P2P channel. */
- for (i = 0, j = 0; i < dtoh32(list->count); i++) {
- chanspec = (chanspec_t) dtoh32(list->element[i]);
- channel = CHSPEC_CHANNEL(chanspec);
-
- ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
- if (ret < 0) {
- WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
- goto done;
- }
-
- if (CHANNEL_IS_RADAR(channel) ||
- !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
- continue;
- } else {
- list->element[j] = list->element[i];
- }
-
- j++;
- }
-
- list->count = j;
-
-done:
- return ret;
-}
-
-static s32
-wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
- int *channel)
-{
- s32 ret = BCME_ERROR;
- int chosen = 0;
- int retry = 0;
-
- /* Start auto channel selection scan. */
- ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
- if (ret < 0) {
- WL_ERR(("can't start auto channel scan, error = %d\n", ret));
- *channel = 0;
- goto done;
- }
-
- /* Wait for auto channel selection, worst case possible delay is 5250ms. */
- retry = CHAN_SEL_RETRY_COUNT;
-
- while (retry--) {
- OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
-
- ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
- false);
- if ((ret == 0) && (dtoh32(chosen) != 0)) {
- *channel = (u16)(chosen & 0x00FF);
- WL_INFO(("selected channel = %d\n", *channel));
- break;
- }
- WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
- (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
- }
-
- if (retry <= 0) {
- WL_ERR(("failure, auto channel selection timed out\n"));
- *channel = 0;
- ret = BCME_ERROR;
- }
-
-done:
- return ret;
-}
-
-static s32
-wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
-{
- u32 val = 0;
- s32 ret = BCME_ERROR;
- struct wl_priv *wl = wlcfg_drv_priv;
-
- /* Clear scan stop driver status. */
- wl_clr_drv_status(wl, SCANNING, ndev);
-
- /* Enable mpc back to 1, irrespective of initial state. */
- val = 1;
-
- ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
- sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
- &wl->ioctl_buf_sync);
- if (ret < 0) {
- WL_ERR(("set 'mpc' failed, error = %d\n", ret));
- }
-
- return ret;
-}
-
-s32
-wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
-{
- int channel = 0;
- s32 ret = BCME_ERROR;
- u8 *buf = NULL;
- char *pos = cmd;
- struct wl_priv *wl = NULL;
- struct net_device *ndev = NULL;
-
- memset(cmd, 0, total_len);
-
- buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
- if (buf == NULL) {
- WL_ERR(("failed to allocate chanspec buffer\n"));
- return -ENOMEM;
- }
-
- /*
- * Always use primary interface, irrespective of interface on which
- * command came.
- */
- wl = wlcfg_drv_priv;
- ndev = wl_to_prmry_ndev(wl);
-
- /*
- * Make sure that FW and driver are in right state to do auto channel
- * selection scan.
- */
- ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
- if (ret < 0) {
- WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
- goto done;
- }
-
- /* Best channel selection in 2.4GHz band. */
- ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
- if (ret < 0) {
- WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
- goto done;
- }
-
- ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
- &channel);
- if (ret < 0) {
- WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
- goto done;
- }
-
- if (CHANNEL_IS_2G(channel)) {
- channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
- } else {
- WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
- channel = 0;
- }
-
- sprintf(pos, "%04d ", channel);
- pos += 5;
-
- /* Best channel selection in 5GHz band. */
- ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
- if (ret < 0) {
- WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
- goto done;
- }
-
- ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
- &channel);
- if (ret < 0) {
- WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
- goto done;
- }
-
- if (CHANNEL_IS_5G(channel)) {
- channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
- } else {
- WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
- channel = 0;
- }
-
- sprintf(pos, "%04d ", channel);
- pos += 5;
-
- /* Set overall best channel same as 5GHz best channel. */
- sprintf(pos, "%04d ", channel);
- pos += 5;
-
-done:
- if (NULL != buf) {
- kfree(buf);
- }
-
- /* Restore FW and driver back to normal state. */
- ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
- if (ret < 0) {
- WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
- }
-
- return (pos - cmd);
-}
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
static const struct rfkill_ops wl_rfkill_ops = {
.set_block = wl_rfkill_set
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 5d9d950..f414623 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -788,21 +788,33 @@ wl_get_netinfo_by_netdev(struct wl_priv *wl, struct net_device *ndev)
#define ndev_to_wlc_ndev(ndev, wl) (ndev)
#endif /* WL_ENABLE_P2P_IF */
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define wdev_to_wlc_ndev(wdev, wl) \
+ ((wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) ? \
+ wl_to_prmry_ndev(wl) : wdev_to_ndev(wdev))
+#define cfgdev_to_wlc_ndev(cfgdev, wl) wdev_to_wlc_ndev(cfgdev, wl)
+#elif defined(WL_ENABLE_P2P_IF)
#define cfgdev_to_wlc_ndev(cfgdev, wl) ndev_to_wlc_ndev(cfgdev, wl)
#else
#define cfgdev_to_wlc_ndev(cfgdev, wl) (cfgdev)
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF */
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define ndev_to_cfgdev(ndev) ndev_to_wdev(ndev)
+#else
#define ndev_to_cfgdev(ndev) (ndev)
+#endif /* WL_CFG80211_P2P_DEV_IF */
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define scan_req_match(wl) (((wl) && (wl->scan_request) && \
+ (wl->scan_request->wdev == wl->p2p_wdev)) ? true : false)
+#elif defined(WL_ENABLE_P2P_IF)
#define scan_req_match(wl) (((wl) && (wl->scan_request) && \
(wl->scan_request->dev == wl->p2p_net)) ? true : false)
#else
#define scan_req_match(wl) (((wl) && p2p_is_on(wl) && p2p_scan(wl)) ? \
true : false)
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF */
#define wl_to_sr(w) (w->scan_req_int)
#if defined(STATIC_WL_PRIV_STRUCT)
@@ -868,19 +880,6 @@ extern s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len);
extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
enum wl_management_type type);
extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len);
-#ifdef WL_SUPPORT_AUTO_CHANNEL
-#define CHANSPEC_BUF_SIZE 1024
-#define CHAN_SEL_IOCTL_DELAY 300
-#define CHAN_SEL_RETRY_COUNT 15
-#define CHANNEL_IS_RADAR(channel) (((channel & WL_CHAN_RADAR) || \
- (channel & WL_CHAN_PASSIVE)) ? true : false)
-#define CHANNEL_IS_2G(channel) (((channel >= 1) && (channel <= 14)) ? \
- true : false)
-#define CHANNEL_IS_5G(channel) (((channel >= 36) && (channel <= 165)) ? \
- true : false)
-extern s32 wl_cfg80211_get_best_channels(struct net_device *dev, char* command,
- int total_len);
-#endif /* WL_SUPPORT_AUTO_CHANNEL */
extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
extern s32 wl_mode_to_nl80211_iftype(s32 mode);
int wl_cfg80211_do_driver_init(struct net_device *net);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index ee72863..1816e60 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_cfgp2p.c 417759 2013-08-12 12:29:43Z $
+ * $Id: wl_cfgp2p.c 419821 2013-08-22 21:43:26Z $
*
*/
#include <typedefs.h>
@@ -1559,8 +1559,13 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
wl_clr_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
if (ndev && (ndev->ieee80211_ptr != NULL)) {
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ cfg80211_remain_on_channel_expired(cfgdev, wl->last_roc_id,
+ &wl->remain_on_chan, GFP_KERNEL);
+#else
cfg80211_remain_on_channel_expired(cfgdev, wl->last_roc_id,
&wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
}
}
if (wl_add_remove_eventmsg(wl_to_prmry_ndev(wl),
@@ -1610,8 +1615,13 @@ wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev,
del_timer_sync(&wl->p2p->listen_timer);
if (notify)
if (ndev && ndev->ieee80211_ptr) {
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ cfg80211_remain_on_channel_expired(wdev, wl->last_roc_id,
+ &wl->remain_on_chan, GFP_KERNEL);
+#else
cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id,
&wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
}
}
return 0;
@@ -1982,10 +1992,13 @@ wl_cfgp2p_down(struct wl_priv *wl)
struct wireless_dev *wdev = NULL;
s32 i = 0, index = -1;
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ ndev = wl_to_prmry_ndev(wl);
+ wdev = wl_to_p2p_wdev(wl);
+#elif defined(WL_ENABLE_P2P_IF)
ndev = wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl);
wdev = ndev_to_wdev(ndev);
-#endif
+#endif /* WL_CFG80211_P2P_DEV_IF */
wl_cfgp2p_cancel_listen(wl, ndev, wdev, TRUE);
for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
@@ -1993,6 +2006,9 @@ wl_cfgp2p_down(struct wl_priv *wl)
if (index != WL_INVALID)
wl_cfgp2p_clear_management_ie(wl, index);
}
+#if defined(WL_CFG80211_P2P_DEV_IF)
+ wl_cfgp2p_del_p2p_disc_if(wdev);
+#endif /* WL_CFG80211_P2P_DEV_IF */
wl_cfgp2p_deinit_priv(wl);
return 0;
}
@@ -2432,6 +2448,7 @@ static int wl_cfgp2p_if_open(struct net_device *net)
if (!wdev || !wl || !wl->p2p)
return -EINVAL;
WL_TRACE(("Enter\n"));
+#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
/* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now,
* do it here. This will make sure that in concurrent mode, supplicant
* is not dependent on a particular order of interface initialization.
@@ -2440,6 +2457,7 @@ static int wl_cfgp2p_if_open(struct net_device *net)
*/
wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)
| BIT(NL80211_IFTYPE_P2P_GO));
+#endif /* !WL_IFACE_COMB_NUM_CHANNELS */
wl_cfg80211_do_driver_init(net);
return 0;
@@ -2468,9 +2486,11 @@ static int wl_cfgp2p_if_stop(struct net_device *net)
spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
if (clear_flag)
wl_clr_drv_status(wl, SCANNING, net);
+#if !defined(WL_IFACE_COMB_NUM_CHANNELS)
wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
& (~(BIT(NL80211_IFTYPE_P2P_CLIENT)|
BIT(NL80211_IFTYPE_P2P_GO)));
+#endif /* !WL_IFACE_COMB_NUM_CHANNELS */
return 0;
}
@@ -2479,3 +2499,142 @@ bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops)
return (if_ops == &wl_cfgp2p_if_ops);
}
#endif /* WL_ENABLE_P2P_IF */
+
+#if defined(WL_CFG80211_P2P_DEV_IF)
+struct wireless_dev *
+wl_cfgp2p_add_p2p_disc_if(void)
+{
+ extern struct wl_priv *wlcfg_drv_priv;
+ struct wl_priv *wl = wlcfg_drv_priv;
+ struct wireless_dev *wdev = NULL;
+ struct ether_addr primary_mac;
+
+ if (!wl)
+ return NULL;
+
+ WL_TRACE(("Enter\n"));
+
+ if (wl->p2p_wdev) {
+ CFGP2P_ERR(("p2p_wdev defined already.\n"));
+ return NULL;
+ }
+
+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ if (unlikely(!wdev)) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ return NULL;
+ }
+
+ memset(&primary_mac, 0, sizeof(primary_mac));
+ get_primary_mac(wl, &primary_mac);
+ wl_cfgp2p_generate_bss_mac(&primary_mac,
+ &wl->p2p->dev_addr, &wl->p2p->int_addr);
+
+ wdev->wiphy = wl->wdev->wiphy;
+ wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
+ memcpy(wdev->address, &wl->p2p->dev_addr, ETHER_ADDR_LEN);
+
+ /* store p2p wdev ptr for further reference. */
+ wl->p2p_wdev = wdev;
+
+ CFGP2P_ERR(("P2P interface registered\n"));
+
+ return wdev;
+}
+
+int
+wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+ int ret = 0;
+ extern struct wl_priv *wlcfg_drv_priv;
+ struct wl_priv *wl = wlcfg_drv_priv;
+
+ if (!wl)
+ return -EINVAL;
+
+ WL_TRACE(("Enter\n"));
+
+ ret = wl_cfgp2p_set_firm_p2p(wl);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("Set P2P in firmware failed, ret=%d\n", ret));
+ goto exit;
+ }
+
+ ret = wl_cfgp2p_enable_discovery(wl, wl_to_prmry_ndev(wl), NULL, 0);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("P2P enable discovery failed, ret=%d\n", ret));
+ goto exit;
+ }
+
+ p2p_on(wl) = true;
+
+ CFGP2P_DBG(("P2P interface started\n"));
+
+exit:
+ return ret;
+}
+
+void
+wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+ int ret = 0;
+ int clear_flag = 0;
+ unsigned long flags = 0;
+ struct net_device *ndev = NULL;
+ extern struct wl_priv *wlcfg_drv_priv;
+ struct wl_priv *wl = wlcfg_drv_priv;
+
+ if (!wl || !wdev)
+ return;
+
+ WL_TRACE(("Enter\n"));
+
+ ndev = wdev_to_wlc_ndev(wdev, wl);
+
+ spin_lock_irqsave(&wl->cfgdrv_lock, flags);
+ if (wl->scan_request && wl->scan_request->wdev == wdev) {
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ clear_flag = 1;
+ }
+ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
+
+ if (clear_flag)
+ wl_clr_drv_status(wl, SCANNING, ndev);
+
+ ret = wl_cfgp2p_disable_discovery(wl);
+ if (unlikely(ret < 0)) {
+ CFGP2P_ERR(("P2P disable discovery failed, ret=%d\n", ret));
+ goto exit;
+ }
+
+ p2p_on(wl) = false;
+
+ CFGP2P_DBG(("P2P interface stopped\n"));
+
+exit:
+ return;
+}
+
+int
+wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev)
+{
+ extern struct wl_priv *wlcfg_drv_priv;
+ struct wl_priv *wl = wlcfg_drv_priv;
+
+ if (!wdev)
+ return -EINVAL;
+
+ WL_TRACE(("Enter\n"));
+
+ cfg80211_unregister_wdev(wdev);
+
+ kfree(wdev);
+
+ wl->p2p_wdev = NULL;
+
+ CFGP2P_ERR(("P2P interface unregistered\n"));
+
+ return 0;
+}
+#endif /* WL_CFG80211_P2P_DEV_IF */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index e121f4e..a2da8fd 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -188,20 +188,25 @@ enum wl_cfgp2p_status {
add_timer(timer); \
} while (0);
-#if !0 && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#if !defined(WL_CFG80211_P2P_DEV_IF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
#define WL_CFG80211_P2P_DEV_IF
-#endif
+#endif /* !WL_CFG80211_P2P_DEV_IF && (LINUX_VERSION >= VERSION(3, 8, 0)) */
-#if defined(WL_ENABLE_P2P_IF) && (0 || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)))
+#if defined(WL_ENABLE_P2P_IF) && (defined(WL_CFG80211_P2P_DEV_IF) || \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)))
#error Disable 'WL_ENABLE_P2P_IF', if 'WL_CFG80211_P2P_DEV_IF' is enabled \
or kernel version is 3.8.0 or above
-#endif
+#endif /* WL_ENABLE_P2P_IF && (WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 8, 0))) */
-#if !defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
+#if !defined(WLP2P) && (defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF))
#error WLP2P not defined
#endif
+#if defined(WL_CFG80211_P2P_DEV_IF)
+#define bcm_struct_cfgdev struct wireless_dev
+#else
#define bcm_struct_cfgdev struct net_device
+#endif /* WL_CFG80211_P2P_DEV_IF */
extern void
wl_cfgp2p_listen_expired(unsigned long data);
@@ -341,6 +346,20 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl);
extern bool
wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops);
+#if defined(WL_CFG80211_P2P_DEV_IF)
+extern struct wireless_dev *
+wl_cfgp2p_add_p2p_disc_if(void);
+
+extern int
+wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+
+extern void
+wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+
+extern int
+wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+
/* WiFi Direct */
#define SOCIAL_CHAN_1 1
#define SOCIAL_CHAN_2 6