mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
net: wireless: bcmdhd: Update to Version 5.90.195.35
- Add SoftAP auto-channel support - P2P fixes Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
@@ -8,7 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \
|
||||
-DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \
|
||||
-DKEEP_ALIVE -DCSCAN -DGET_CUSTOM_MAC_ENABLE -DPKT_FILTER_SUPPORT \
|
||||
-DEMBEDDED_PLATFORM -DENABLE_INSMOD_NO_FW_LOAD -DPNO_SUPPORT \
|
||||
-DSET_RANDOM_MAC_SOFTAP -DENABLE_P2P_INTERFACE -DDHD_USE_EARLYSUSPEND \
|
||||
-DSET_RANDOM_MAC_SOFTAP -DWL_ENABLE_P2P_IF -DDHD_USE_EARLYSUSPEND \
|
||||
-Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
|
||||
|
||||
DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \
|
||||
|
||||
@@ -212,7 +212,6 @@ typedef struct dhd_pub {
|
||||
* For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework
|
||||
* see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile
|
||||
*/
|
||||
/* #define ENABLE_P2P_INTERFACE 1 */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
|
||||
struct wake_lock wakelock[WAKE_LOCK_MAX];
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: dhd_common.c 316272 2012-02-21 22:35:51Z $
|
||||
* $Id: dhd_common.c 319098 2012-03-07 01:05:20Z $
|
||||
*/
|
||||
#include <typedefs.h>
|
||||
#include <osl.h>
|
||||
@@ -1814,11 +1814,14 @@ exit:
|
||||
bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd)
|
||||
{
|
||||
#ifdef WL_CFG80211
|
||||
#ifndef ENABLE_P2P_INTERFACE
|
||||
/* To be back compatble with ICS MR1 release where p2p interface disable but wlan0 used for p2p */
|
||||
#ifndef WL_ENABLE_P2P_IF
|
||||
/* To be back compatble with ICS MR1 release where p2p interface
|
||||
* disable but wlan0 used for p2p
|
||||
*/
|
||||
if (((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) ||
|
||||
((dhd->op_mode & WFD_MASK) == WFD_MASK))
|
||||
((dhd->op_mode & WFD_MASK) == WFD_MASK)) {
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
#else
|
||||
/* concurent mode with p2p interface for wfd and wlan0 for sta */
|
||||
@@ -1828,7 +1831,7 @@ bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd)
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif /* WL_ENABLE_P2P_IF */
|
||||
#endif /* WL_CFG80211 */
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1880,10 +1883,12 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
|
||||
|
||||
memset(iovbuf, 0, sizeof(iovbuf));
|
||||
|
||||
#ifndef WL_SCHED_SCAN
|
||||
if ((pfn_enabled) && (dhd_is_associated(dhd, NULL) == TRUE)) {
|
||||
DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enable/disable PNO */
|
||||
if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
|
||||
|
||||
@@ -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 316856 2012-02-23 21:44:34Z $
|
||||
* $Id: dhd_linux.c 319136 2012-03-07 03:10:36Z $
|
||||
*/
|
||||
|
||||
#include <typedefs.h>
|
||||
@@ -426,7 +426,7 @@ static void dhd_net_if_lock_local(dhd_info_t *dhd);
|
||||
static void dhd_net_if_unlock_local(dhd_info_t *dhd);
|
||||
static void dhd_suspend_lock(dhd_pub_t *dhdp);
|
||||
static void dhd_suspend_unlock(dhd_pub_t *dhdp);
|
||||
#if !defined(AP) && defined(WLP2P)
|
||||
#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
static u32 dhd_concurrent_fw(dhd_pub_t *dhd);
|
||||
#endif
|
||||
|
||||
@@ -588,8 +588,9 @@ static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force)
|
||||
/* Set flag when early suspend was called */
|
||||
dhdp->in_suspend = val;
|
||||
if ((force || !dhdp->suspend_disable_flag) &&
|
||||
(dhd_check_ap_wfd_mode_set(dhdp) == FALSE))
|
||||
(dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) {
|
||||
ret = dhd_set_suspend(val, dhdp);
|
||||
}
|
||||
DHD_OS_WAKE_UNLOCK(dhdp);
|
||||
return ret;
|
||||
}
|
||||
@@ -1284,11 +1285,13 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n",
|
||||
__FUNCTION__, dhd->pub.up, dhd->pub.busstate));
|
||||
netif_stop_queue(net);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
/* Send Event when bus down detected during data session */
|
||||
if (dhd->pub.busstate == DHD_BUS_DOWN) {
|
||||
DHD_ERROR(("%s: Event HANG sent up\n", __FUNCTION__));
|
||||
net_os_send_hang_message(net);
|
||||
}
|
||||
#endif
|
||||
DHD_OS_WAKE_UNLOCK(&dhd->pub);
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -2010,6 +2013,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr)
|
||||
|
||||
static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
if (!dhdp)
|
||||
return FALSE;
|
||||
if ((error == -ETIMEDOUT) || ((dhdp->busstate == DHD_BUS_DOWN) &&
|
||||
@@ -2019,6 +2023,7 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
|
||||
net_os_send_hang_message(net);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -2888,7 +2893,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(AP) && defined(WLP2P)
|
||||
#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
/* For Android ICS MR2 release, the concurrent mode is enabled by default and the firmware
|
||||
* name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA
|
||||
* firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware
|
||||
@@ -2950,7 +2955,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
||||
#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211))
|
||||
uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
|
||||
#endif
|
||||
#if defined(AP) || defined(WLP2P)
|
||||
#if defined(AP) || (defined(WLP2P) && defined(WL_ENABLE_P2P_IF))
|
||||
uint32 apsta = 1; /* Enable APSTA mode */
|
||||
#endif /* defined(AP) || defined(WLP2P) */
|
||||
#ifdef GET_CUSTOM_MAC_ENABLE
|
||||
@@ -3008,7 +3013,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
||||
#endif /* SET_RANDOM_MAC_SOFTAP */
|
||||
|
||||
DHD_TRACE(("Firmware = %s\n", fw_path));
|
||||
#if !defined(AP) && defined(WLP2P)
|
||||
#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
/* Check if firmware with WFD support used */
|
||||
if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || (op_mode == 0x04) ||
|
||||
(dhd_concurrent_fw(dhd))) {
|
||||
@@ -3029,6 +3034,26 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
||||
#if !defined(AP) && defined(WL_CFG80211)
|
||||
/* Check if firmware with HostAPD support used */
|
||||
if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == 0x02)) {
|
||||
/* Turn off wme if we are having only g ONLY firmware */
|
||||
bcm_mkiovar("nmode", 0, 0, buf, sizeof(buf));
|
||||
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
|
||||
FALSE, 0)) < 0) {
|
||||
DHD_ERROR(("%s:get nmode failed error (%d)\n", __FUNCTION__, ret));
|
||||
}
|
||||
else {
|
||||
DHD_TRACE(("%s:get nmode returned %d\n", __FUNCTION__,buf[0]));
|
||||
}
|
||||
if (buf[0] == 0) {
|
||||
int wme = 0;
|
||||
bcm_mkiovar("wme", (char *)&wme, 4, iovbuf, sizeof(iovbuf));
|
||||
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
|
||||
sizeof(iovbuf), TRUE, 0)) < 0) {
|
||||
DHD_ERROR(("%s set wme for HostAPD failed %d\n", __FUNCTION__, ret));
|
||||
}
|
||||
else {
|
||||
DHD_TRACE(("%s set wme succeeded for g ONLY firmware\n", __FUNCTION__));
|
||||
}
|
||||
}
|
||||
/* Turn off MPC in AP mode */
|
||||
bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
|
||||
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
|
||||
@@ -3764,10 +3789,10 @@ dhd_module_init(void)
|
||||
#endif /* defined(WL_CFG80211) */
|
||||
|
||||
return error;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
fail_2:
|
||||
dhd_bus_unregister();
|
||||
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
|
||||
#endif
|
||||
fail_1:
|
||||
#if defined(CONFIG_WIFI_CONTROL_FUNC)
|
||||
wl_android_wifictrl_func_del();
|
||||
@@ -4388,6 +4413,7 @@ dhd_dev_get_pno_status(struct net_device *dev)
|
||||
|
||||
#endif /* PNO_SUPPORT */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
int net_os_send_hang_message(struct net_device *dev)
|
||||
{
|
||||
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
|
||||
@@ -4414,6 +4440,7 @@ int net_os_send_hang_message(struct net_device *dev)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec)
|
||||
{
|
||||
|
||||
@@ -33,17 +33,17 @@
|
||||
|
||||
#define EPI_RC_NUMBER 195
|
||||
|
||||
#define EPI_INCREMENTAL_NUMBER 30
|
||||
#define EPI_INCREMENTAL_NUMBER 35
|
||||
|
||||
#define EPI_BUILD_NUMBER 0
|
||||
|
||||
#define EPI_VERSION 5, 90, 195, 30
|
||||
#define EPI_VERSION 5, 90, 195, 35
|
||||
|
||||
#define EPI_VERSION_NUM 0x055ac31e
|
||||
#define EPI_VERSION_NUM 0x055ac323
|
||||
|
||||
#define EPI_VERSION_DEV 5.90.195
|
||||
|
||||
|
||||
#define EPI_VERSION_STR "5.90.195.30"
|
||||
#define EPI_VERSION_STR "5.90.195.35"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,6 +71,7 @@ u32 wl_dbg_level = WL_DBG_ERR;
|
||||
#define MAX_WAIT_TIME 1500
|
||||
#define WL_SCAN_ACTIVE_TIME 40
|
||||
#define WL_SCAN_PASSIVE_TIME 130
|
||||
#define WL_FRAME_LEN 300
|
||||
|
||||
#define DNGL_FUNC(func, parameters) func parameters;
|
||||
#define COEX_DHCP
|
||||
@@ -94,13 +95,12 @@ static const struct ieee80211_regdomain brcm_regdom = {
|
||||
REG_RULE(2467-10, 2472+10, 20, 6, 20,
|
||||
NL80211_RRF_PASSIVE_SCAN |
|
||||
NL80211_RRF_NO_IBSS),
|
||||
/* IEEE 802.11 channel 14 - Only JP enables
|
||||
* this and for 802.11b only
|
||||
/*
|
||||
* IEEE 802.11 channel 14 - is for JP only,
|
||||
* we need cfg80211 to allow it (reg_flags = 0); so that
|
||||
* hostapd could request auto channel by sending down ch 14
|
||||
*/
|
||||
REG_RULE(2484-10, 2484+10, 20, 6, 20,
|
||||
NL80211_RRF_PASSIVE_SCAN |
|
||||
NL80211_RRF_NO_IBSS |
|
||||
NL80211_RRF_NO_OFDM),
|
||||
REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
|
||||
/* IEEE 802.11a, channel 36..64 */
|
||||
REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
|
||||
/* IEEE 802.11a, channel 100..165 */
|
||||
@@ -510,22 +510,7 @@ static struct ieee80211_supported_band __wl_band_2ghz = {
|
||||
.channels = __wl_2ghz_channels,
|
||||
.n_channels = ARRAY_SIZE(__wl_2ghz_channels),
|
||||
.bitrates = wl_g_rates,
|
||||
.n_bitrates = wl_g_rates_size,
|
||||
#if defined(ENABLE_P2P_INTERFACE)
|
||||
/* wpa_supplicant sets wmm_enabled based on whether ht_cap
|
||||
* is present or not. The wmm_enabled is inturn used to
|
||||
* set the replay counters in the RSN IE. Without this
|
||||
* the 4way handshake will fail complaining that IE in beacon
|
||||
* doesn't match with the IE present in the 3/4 EAPOL msg.
|
||||
*/
|
||||
.ht_cap = {
|
||||
IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU,
|
||||
.ht_supported = TRUE,
|
||||
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16
|
||||
}
|
||||
#endif
|
||||
.n_bitrates = wl_g_rates_size
|
||||
};
|
||||
|
||||
static struct ieee80211_supported_band __wl_band_5ghz_a = {
|
||||
@@ -533,22 +518,7 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
|
||||
.channels = __wl_5ghz_a_channels,
|
||||
.n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
|
||||
.bitrates = wl_a_rates,
|
||||
.n_bitrates = wl_a_rates_size,
|
||||
#if defined(ENABLE_P2P_INTERFACE)
|
||||
/* wpa_supplicant sets wmm_enabled based on whether ht_cap
|
||||
* is present or not. The wmm_enabled is inturn used to
|
||||
* set the replay counters in the RSN IE. Without this
|
||||
* the 4way handshake will fail complaining that IE in beacon
|
||||
* doesn't match with the IE present in the 3/4 EAPOL msg.
|
||||
*/
|
||||
.ht_cap = {
|
||||
IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU,
|
||||
.ht_supported = TRUE,
|
||||
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16
|
||||
}
|
||||
#endif
|
||||
.n_bitrates = wl_a_rates_size
|
||||
};
|
||||
|
||||
static const u32 __wl_cipher_suites[] = {
|
||||
@@ -901,6 +871,12 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
|
||||
else if (type == NL80211_IFTYPE_P2P_GO)
|
||||
dhd_mode = P2P_GO_ENABLED;
|
||||
DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode));
|
||||
/* Start the P2P I/F with PM disabled. Enable PM from
|
||||
* the framework
|
||||
*/
|
||||
if ((type == NL80211_IFTYPE_P2P_CLIENT) || (
|
||||
type == NL80211_IFTYPE_P2P_GO))
|
||||
vwdev->ps = NL80211_PS_DISABLED;
|
||||
} else {
|
||||
/* put back the rtnl_lock again */
|
||||
if (rollback_lock)
|
||||
@@ -1234,7 +1210,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req
|
||||
params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK;
|
||||
params->channel_list[i] |= chanspec;
|
||||
WL_SCAN(("Chan : %d, Channel spec: %x \n",
|
||||
channel, params->channel_list[i]));
|
||||
channel, params->channel_list[i]));
|
||||
params->channel_list[i] = htod16(params->channel_list[i]);
|
||||
}
|
||||
} else {
|
||||
@@ -2913,18 +2889,13 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
CHECK_SYS_UP(wl);
|
||||
|
||||
WL_DBG(("Enter : power save %s\n", (enabled ? "enable" : "disable")));
|
||||
if (wl->p2p_net == dev) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pm = enabled ? PM_FAST : PM_OFF;
|
||||
/* Do not enable the power save after assoc if it is p2p interface */
|
||||
if (wl->p2p && wl->p2p->vif_created) {
|
||||
WL_DBG(("Do not enable the power save for p2p interfaces even after assoc\n"));
|
||||
pm = PM_OFF;
|
||||
}
|
||||
pm = htod32(pm);
|
||||
WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
|
||||
err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
|
||||
if (unlikely(err)) {
|
||||
if (err == -ENODEV)
|
||||
@@ -2933,6 +2904,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
WL_ERR(("error (%d)\n", err));
|
||||
return err;
|
||||
}
|
||||
WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3429,7 +3401,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
|
||||
wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
|
||||
sizeof(scb_val_t), true);
|
||||
WL_DBG(("Disconnect STA : %s scb_val.val %d\n",
|
||||
bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val));
|
||||
bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
|
||||
scb_val.val));
|
||||
cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
|
||||
goto exit;
|
||||
|
||||
@@ -3626,6 +3599,14 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
|
||||
dev = wl_to_prmry_ndev(wl);
|
||||
}
|
||||
channel = ieee80211_frequency_to_channel(chan->center_freq);
|
||||
|
||||
if (wl_get_drv_status(wl, AP_CREATING, dev) && channel == 14) {
|
||||
WL_TRACE(("<0> %s: as!!! in AP creating mode, save chan num:%d\n",
|
||||
__FUNCTION__, channel));
|
||||
wl->hostapd_chan = channel;
|
||||
return err;
|
||||
}
|
||||
|
||||
WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
|
||||
dev->ifindex, channel_type, channel));
|
||||
err = wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), true);
|
||||
@@ -4012,6 +3993,26 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
|
||||
WL_ERR(("setting AP mode failed %d \n", err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* if requested, do softap ch autoselect */
|
||||
if (wl->hostapd_chan == 14) {
|
||||
int auto_chan;
|
||||
if ((err = wldev_get_auto_channel(dev, &auto_chan)) != 0) {
|
||||
WL_ERR(("softap: auto chan select failed,"
|
||||
" will use ch 6\n"));
|
||||
auto_chan = 6;
|
||||
} else {
|
||||
printf("<0>softap: got auto ch:%d\n", auto_chan);
|
||||
}
|
||||
err = wldev_ioctl(dev, WLC_SET_CHANNEL,
|
||||
&auto_chan, sizeof(auto_chan), true);
|
||||
if (err < 0) {
|
||||
WL_ERR(("softap: WLC_SET_CHANNEL error %d chip"
|
||||
" may not be supporting this channel\n", err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the RSN_IE */
|
||||
if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
|
||||
DOT11_MNG_RSN_ID)) != NULL) {
|
||||
@@ -4529,7 +4530,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
|
||||
|
||||
signal = notif_bss_info->rssi * 100;
|
||||
|
||||
#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE)
|
||||
#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
if (wl->p2p_net && wl->scan_request &&
|
||||
wl->scan_request->dev == wl->p2p_net) {
|
||||
#else
|
||||
@@ -4613,11 +4614,9 @@ static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
|
||||
|
||||
/* The mainline kernel >= 3.2.0 has support for indicating new/del station
|
||||
* to AP/P2P GO via events. If this change is backported to kernel for which
|
||||
* this driver is being built, set CFG80211_STA_EVENT_AVAILABLE to 1. You
|
||||
* should use this new/del sta event mechanism for BRCM supplicant from BRANCH
|
||||
* HOSTAP_BRANCH_0_15 (ver >= 15_1).
|
||||
* this driver is being built, then define WL_CFG80211_STA_EVENT. You
|
||||
* should use this new/del sta event mechanism for BRCM supplicant >= 22.
|
||||
*/
|
||||
#define CFG80211_STA_EVENT_AVAILABLE 0
|
||||
static s32
|
||||
wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
|
||||
const wl_event_msg_t *e, void *data)
|
||||
@@ -4627,13 +4626,13 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
|
||||
u32 reason = ntoh32(e->reason);
|
||||
u32 len = ntoh32(e->datalen);
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
|
||||
bool isfree = false;
|
||||
u8 *mgmt_frame;
|
||||
u8 bsscfgidx = e->bsscfgidx;
|
||||
s32 freq;
|
||||
s32 channel;
|
||||
u8 body[200];
|
||||
u8 body[WL_FRAME_LEN];
|
||||
u16 fc = 0;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ether_addr da;
|
||||
@@ -4642,16 +4641,21 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
|
||||
channel_info_t ci;
|
||||
#else
|
||||
struct station_info sinfo;
|
||||
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE */
|
||||
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !WL_CFG80211_STA_EVENT */
|
||||
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
|
||||
memset(body, 0, sizeof(body));
|
||||
memset(&bssid, 0, ETHER_ADDR_LEN);
|
||||
WL_DBG(("Enter event %d ndev %p\n", event, ndev));
|
||||
if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID)
|
||||
return WL_INVALID;
|
||||
|
||||
if (len > WL_FRAME_LEN) {
|
||||
WL_ERR(("Received frame length %d from dongle is greater than"
|
||||
" allocated body buffer len %d", len, WL_FRAME_LEN));
|
||||
goto exit;
|
||||
}
|
||||
memcpy(body, data, len);
|
||||
wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
|
||||
NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync);
|
||||
@@ -4710,7 +4714,7 @@ exit:
|
||||
if (isfree)
|
||||
kfree(mgmt_frame);
|
||||
return err;
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !CFG80211_STA_EVENT_AVAILABLE */
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */
|
||||
sinfo.filled = 0;
|
||||
if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
|
||||
reason == DOT11_SC_SUCCESS) {
|
||||
@@ -4727,7 +4731,7 @@ exit:
|
||||
} else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
|
||||
cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !CFG80211_STA_EVENT_AVAILABLE */
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -5329,10 +5333,10 @@ exit:
|
||||
}
|
||||
|
||||
#ifdef WL_SCHED_SCAN
|
||||
/* If target scan is not reliable, set the below define to "0" to do a
|
||||
/* If target scan is not reliable, set the below define to "1" to do a
|
||||
* full escan
|
||||
*/
|
||||
#define FULL_ESCAN_ON_PFN_NET_FOUND 1
|
||||
#define FULL_ESCAN_ON_PFN_NET_FOUND 0
|
||||
static s32
|
||||
wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
|
||||
const wl_event_msg_t *e, void *data)
|
||||
@@ -5421,9 +5425,9 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
|
||||
|
||||
wl_set_drv_status(wl, SCANNING, ndev);
|
||||
#if FULL_ESCAN_ON_PFN_NET_FOUND
|
||||
err = wl_do_escan(wl, wiphy, ndev, &request);
|
||||
#else
|
||||
err = wl_do_escan(wl, wiphy, ndev, NULL);
|
||||
#else
|
||||
err = wl_do_escan(wl, wiphy, ndev, &request);
|
||||
#endif
|
||||
if (err) {
|
||||
wl_clr_drv_status(wl, SCANNING, ndev);
|
||||
@@ -5845,9 +5849,22 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
return NOTIFY_DONE;
|
||||
switch (state) {
|
||||
case NETDEV_UNREGISTER:
|
||||
/* after calling list_del_rcu(&wdev->list) */
|
||||
wl_dealloc_netinfo(wl, ndev);
|
||||
break;
|
||||
/* after calling list_del_rcu(&wdev->list) */
|
||||
wl_dealloc_netinfo(wl, ndev);
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
/* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
|
||||
* In front of door, the function checks
|
||||
* whether current scan is working or not.
|
||||
* If the scanning is still working, wdev_cleanup_work call WARN_ON and
|
||||
* make the scan done forcibly.
|
||||
*/
|
||||
if (wl_get_drv_status(wl, SCANNING, dev)) {
|
||||
if (wl->escan_on) {
|
||||
wl_notify_escan_complete(wl, dev, true, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
@@ -6172,7 +6189,7 @@ static void wl_deinit_priv(struct wl_priv *wl)
|
||||
unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
|
||||
}
|
||||
|
||||
#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE)
|
||||
#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
static s32 wl_cfg80211_attach_p2p(void)
|
||||
{
|
||||
struct wl_priv *wl = wlcfg_drv_priv;
|
||||
@@ -6207,7 +6224,7 @@ static s32 wl_cfg80211_detach_p2p(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */
|
||||
#endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */
|
||||
|
||||
s32 wl_cfg80211_attach_post(struct net_device *ndev)
|
||||
{
|
||||
@@ -6222,7 +6239,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev)
|
||||
if (wl && !wl_get_drv_status(wl, READY, ndev)) {
|
||||
if (wl->wdev &&
|
||||
wl_cfgp2p_supported(wl, ndev)) {
|
||||
#if !defined(ENABLE_P2P_INTERFACE)
|
||||
#if !defined(WL_ENABLE_P2P_IF)
|
||||
wl->wdev->wiphy->interface_modes |=
|
||||
(BIT(NL80211_IFTYPE_P2P_CLIENT)|
|
||||
BIT(NL80211_IFTYPE_P2P_GO));
|
||||
@@ -6230,7 +6247,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev)
|
||||
if ((err = wl_cfgp2p_init_priv(wl)) != 0)
|
||||
goto fail;
|
||||
|
||||
#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE)
|
||||
#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
if (wl->p2p_net) {
|
||||
/* Update MAC addr for p2p0 interface here. */
|
||||
memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
|
||||
@@ -6242,7 +6259,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev)
|
||||
" Couldn't update the MAC Address for p2p0 \n"));
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */
|
||||
#endif /* defined(WLP2P) && (WL_ENABLE_P2P_IF) */
|
||||
|
||||
wl->p2p_supported = true;
|
||||
}
|
||||
@@ -6314,7 +6331,7 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
|
||||
|
||||
wlcfg_drv_priv = wl;
|
||||
|
||||
#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE)
|
||||
#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
err = wl_cfg80211_attach_p2p();
|
||||
if (err)
|
||||
goto cfg80211_attach_out;
|
||||
@@ -6340,7 +6357,7 @@ void wl_cfg80211_detach(void *para)
|
||||
wl_cfg80211_btcoex_deinit(wl);
|
||||
#endif
|
||||
|
||||
#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE)
|
||||
#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
|
||||
wl_cfg80211_detach_p2p();
|
||||
#endif
|
||||
wl_setup_rfkill(wl, FALSE);
|
||||
@@ -6620,6 +6637,10 @@ s32 wl_update_wiphybands(struct wl_priv *wl)
|
||||
u32 nband = 0;
|
||||
u32 i = 0;
|
||||
s32 err = 0;
|
||||
int nmode = 0;
|
||||
int bw_40 = 0;
|
||||
int index = 0;
|
||||
|
||||
WL_DBG(("Entry"));
|
||||
memset(bandlist, 0, sizeof(bandlist));
|
||||
err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist,
|
||||
@@ -6632,14 +6653,43 @@ s32 wl_update_wiphybands(struct wl_priv *wl)
|
||||
nband = bandlist[0];
|
||||
wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
|
||||
|
||||
err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "nmode", &nmode);
|
||||
if (unlikely(err)) {
|
||||
WL_ERR(("error (%d)\n", err));
|
||||
}
|
||||
|
||||
err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "mimo_bw_cap", &bw_40);
|
||||
if (unlikely(err)) {
|
||||
WL_ERR(("error (%d)\n", err));
|
||||
}
|
||||
|
||||
for (i = 1; i <= nband && i < sizeof(bandlist); i++) {
|
||||
if (bandlist[i] == WLC_BAND_5G)
|
||||
index = -1;
|
||||
if (bandlist[i] == WLC_BAND_5G) {
|
||||
wiphy->bands[IEEE80211_BAND_5GHZ] =
|
||||
&__wl_band_5ghz_a;
|
||||
else if (bandlist[i] == WLC_BAND_2G)
|
||||
index = IEEE80211_BAND_5GHZ;
|
||||
} else if (bandlist[i] == WLC_BAND_2G) {
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] =
|
||||
&__wl_band_2ghz;
|
||||
index = IEEE80211_BAND_2GHZ;
|
||||
}
|
||||
|
||||
if ((index >= 0) && nmode) {
|
||||
wiphy->bands[index]->ht_cap.cap =
|
||||
IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40
|
||||
| IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
wiphy->bands[index]->ht_cap.ht_supported = TRUE;
|
||||
wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
|
||||
}
|
||||
|
||||
if ((index >= 0) && bw_40) {
|
||||
wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
|
||||
}
|
||||
}
|
||||
|
||||
wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -446,6 +446,7 @@ struct wl_priv {
|
||||
struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */
|
||||
#endif /* WL_SCHED_SCAN */
|
||||
bool sched_scan_running; /* scheduled scan req status */
|
||||
u16 hostapd_chan; /* remember chan requested by framework for hostapd */
|
||||
};
|
||||
|
||||
static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
|
||||
|
||||
@@ -366,3 +366,53 @@ int wldev_set_country(
|
||||
__FUNCTION__, country_code, cspec.ccode, cspec.rev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* softap channel autoselect
|
||||
*/
|
||||
int wldev_get_auto_channel(struct net_device *dev, int *chan)
|
||||
{
|
||||
int chosen = 0;
|
||||
wl_uint32_list_t request;
|
||||
int retry = 0;
|
||||
int updown = 0;
|
||||
int ret = 0;
|
||||
wlc_ssid_t null_ssid;
|
||||
|
||||
memset(&null_ssid, 0, sizeof(wlc_ssid_t));
|
||||
ret |= wldev_ioctl(dev, WLC_UP, &updown, sizeof(updown), true);
|
||||
|
||||
ret |= wldev_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid), true);
|
||||
|
||||
request.count = htod32(0);
|
||||
ret = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request), true);
|
||||
if (ret < 0) {
|
||||
WLDEV_ERROR(("can't start auto channel scan:%d\n", ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (retry++ < 15) {
|
||||
|
||||
bcm_mdelay(350);
|
||||
|
||||
ret = wldev_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen), false);
|
||||
|
||||
if ((ret == 0) && (dtoh32(chosen) != 0)) {
|
||||
*chan = (uint16)chosen & 0x00FF; /* covert chanspec --> chan number */
|
||||
printf("%s: Got channel = %d, attempt:%d\n",
|
||||
__FUNCTION__, *chan, retry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = wldev_ioctl(dev, WLC_DOWN, &updown, sizeof(updown), true)) < 0) {
|
||||
WLDEV_ERROR(("%s fail to WLC_DOWN ioctl err =%d\n", __FUNCTION__, ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail :
|
||||
if (ret < 0) {
|
||||
WLDEV_ERROR(("%s: return value %d\n", __FUNCTION__, ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -107,4 +107,6 @@ int wldev_get_band(struct net_device *dev, uint *pband);
|
||||
|
||||
int wldev_set_band(struct net_device *dev, uint band);
|
||||
|
||||
int wldev_get_auto_channel(struct net_device *dev, int *chan);
|
||||
|
||||
#endif /* __WLDEV_COMMON_H__ */
|
||||
|
||||
Reference in New Issue
Block a user