#CONFIG_BCMDHD_STATIC_BUF_IN_DHD := y
CONFIG_BCMDHD_AUTO_SELECT := y
CONFIG_BCMDHD_DEBUG := y
+#CONFIG_BCMDHD_RECONNECT := y
#CONFIG_BCMDHD_TIMESTAMP := y
#CONFIG_BCMDHD_WAPI := y
#CONFIG_BCMDHD_RANDOM_MAC := y
-#CONFIG_BCMDHD_MULTIPLE_DRIVER := y
+CONFIG_BCMDHD_REQUEST_FW := y
+#CONFIG_BCMDHD_DWDS := y
CONFIG_BCMDHD_TPUT := y
+#CONFIG_BCMDHD_MULTIPLE_DRIVER := y
+#CONFIG_BCMDHD_ADAPTER_INDEX := 0
+
CONFIG_MACH_PLATFORM := y
#CONFIG_BCMDHD_DTS := y
DHDCFLAGS = -Wall -Wstrict-prototypes -Wno-date-time \
-Dlinux -DLINUX -DBCMDRIVER \
- -Wno-unknown-warning-option -Wno-unused-but-set-variable \
- -Wno-uninitialized -Wno-error -Wno-format-security \
- -Wno-implicit-fallthrough \
+ -Wno-unused-but-set-variable \
+ -Wno-maybe-uninitialized -Wno-error -Wno-format-security \
+ -Wno-unknown-warning-option -Wno-sometimes-uninitialized \
+ -Wno-parentheses-equality -Wno-implicit-fallthrough \
-DBCMDONGLEHOST -DBCMDMA32 -DBCMFILEIMAGE \
-DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DGET_OTP_MAC_ENABLE \
-DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \
+ -DPKTPRIO_OVERRIDE \
-DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DDHDTCPACK_SUPPRESS \
-DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DOEM_ANDROID \
-DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP -DDHD_8021X_DUMP \
-DPOWERUP_MAX_RETRY=1 -DIFACE_HANG_FORCE_DEV_CLOSE -DWAIT_DEQUEUE \
-DUSE_NEW_RSPEC_DEFS \
-DWL_EXT_IAPSTA -DWL_ESCAN -DCCODE_LIST -DSUSPEND_EVENT \
- -DEAPOL_RESEND -DEAPOL_DYNAMATIC_RESEND \
+ -DKEY_INSTALL_CHECK \
-DENABLE_INSMOD_NO_FW_LOAD
-DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \
+DHDOFILES = aiutils.o siutils.o sbutils.o \
+ bcmutils.o bcmwifi_channels.o bcmxtlv.o bcm_app_utils.o bcmstdlib_s.o \
dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o \
dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o \
bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \
dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o dhd_dbg_ring.o \
- hnd_pktq.o hnd_pktpool.o bcmxtlv.o linux_pkt.o bcmstdlib_s.o frag.o \
+ hnd_pktq.o hnd_pktpool.o linux_pkt.o frag.o \
dhd_linux_exportfs.o dhd_linux_pktdump.o dhd_mschdbg.o \
dhd_config.o dhd_ccode.o wl_event.o wl_android_ext.o \
- wl_iapsta.o wl_escan.o
+ wl_iapsta.o wl_escan.o wl_timer.o
ifneq ($(CONFIG_WIRELESS_EXT),)
DHDOFILES += wl_iw.o
ifneq ($(CONFIG_CFG80211),)
DHDOFILES += wl_cfg80211.o wl_cfgscan.o wl_cfgp2p.o
DHDOFILES += wl_linux_mon.o wl_cfg_btcoex.o wl_cfgvendor.o
- DHDOFILES += dhd_cfg80211.o wl_cfgvif.o
+ DHDOFILES += dhd_cfg80211.o wl_cfgvif.o wl_roam.o
DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT
DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10
DHDCFLAGS += -DESCAN_RESULT_PATCH -DESCAN_BUF_OVERFLOW_MGMT
DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8
- DHDCFLAGS += -DWL_VIRTUAL_APSTA
+ DHDCFLAGS += -DWL_VIRTUAL_APSTA -DSTA_MGMT
DHDCFLAGS += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP
DHDCFLAGS += -DDHD_USE_SCAN_WAKELOCK
DHDCFLAGS += -DSPECIFIC_MAC_GEN_SCHEME
DHDCFLAGS += -DWL_IFACE_MGMT
- DHDCFLAGS += -DWLFBT
- DHDCFLAGS += -DWL_EXT_RECONNECT
- DHDCFLAGS += -DDHD_LOSSLESS_ROAMING
+ DHDCFLAGS += -DWLFBT -DWL_GCMP_SUPPORT
+ DHDCFLAGS += -DROAM_CHANNEL_CACHE -DDHD_LOSSLESS_ROAMING -DWL_ROAM_WAR
DHDCFLAGS += -DGTK_OFFLOAD_SUPPORT
+ DHDCFLAGS += -DRESTART_AP_WAR
DHDCFLAGS += -DWL_STATIC_IF
DHDCFLAGS += -DWL_CLIENT_SAE -DWL_OWE
endif
#BCMDHD_SDIO
ifneq ($(CONFIG_BCMDHD_SDIO),)
-BUS_TYPE := "sdio"
+BUS_TYPE := sdio
DHDCFLAGS += -DBCMSDIO -DMMC_SDIO_ABORT -DMMC_SW_RESET -DBCMLXSDMMC \
-DUSE_SDIOFIFO_IOVAR -DSDTEST \
-DBDC -DDHD_USE_IDLECOUNT -DCUSTOM_SDIO_F2_BLKSIZE=256 \
- -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DRXFRAME_THREAD \
- -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS \
+ -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DBCMSDIOH_STATIC_COPY_BUF \
+ -DRXFRAME_THREAD -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS \
-DBCMSDIO_RXLIM_POST -DBCMSDIO_TXSEQ_SYNC -DCONSOLE_DPC \
-DBCMSDIO_INTSTATUS_WAR
ifeq ($(CONFIG_BCMDHD_OOB),y)
#BCMDHD_PCIE
ifneq ($(CONFIG_BCMDHD_PCIE),)
-BUS_TYPE := "pcie"
+BUS_TYPE := pcie
DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1 \
-DDONGLE_ENABLE_ISOLATION
DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_STATS -DDHD_LB_TXP
#BCMDHD_USB
ifneq ($(CONFIG_BCMDHD_USB),)
-BUS_TYPE := "usb"
+BUS_TYPE := usb
DHDCFLAGS += -DUSBOS_TX_THREAD -DBCMDBUS -DBCMTRXV2 -DDBUS_USB_LOOPBACK \
-DBDC
-DHDCFLAGS += -DBCM_REQUEST_FW -DEXTERNAL_FW_PATH
+DHDCFLAGS += -DINSMOD_FW_LOAD
+DHDCFLAGS += -DBCM_REQUEST_FW
+DHDCFLAGS += -DSHOW_LOGTRACE
+ifneq ($(CONFIG_BCMDHD_REQUEST_FW),y)
+ DHDCFLAGS += -DEXTERNAL_FW_PATH
+endif
CONFIG_BCMDHD_NO_POWER_OFF := y
ifneq ($(CONFIG_BCMDHD_CUSB),)
DHDCFLAGS += -DBCMUSBDEV_COMPOSITE
ifeq ($(CONFIG_BCMDHD_MULTIPLE_DRIVER),y)
DHDCFLAGS += -DBCMDHD_MDRIVER
+ifneq ($(CONFIG_BCMDHD_ADAPTER_INDEX),)
+ CONFIG_BCMDHD_STATIC_BUF_IN_DHD := y
+ MODULE_NAME := dhd$(BUS_TYPE)_$(CONFIG_BCMDHD_ADAPTER_INDEX)
+ DHDCFLAGS += -DADAPTER_IDX=$(CONFIG_BCMDHD_ADAPTER_INDEX)
+ DHDCFLAGS += -DBUS_TYPE=\"-$(BUS_TYPE)-$(CONFIG_BCMDHD_ADAPTER_INDEX)\"
+ DHDCFLAGS += -DDHD_LOG_PREFIX=\"[dhd-$(BUS_TYPE)-$(CONFIG_BCMDHD_ADAPTER_INDEX)]\"
+else
+ MODULE_NAME := dhd$(BUS_TYPE)
DHDCFLAGS += -DBUS_TYPE=\"-$(BUS_TYPE)\"
DHDCFLAGS += -DDHD_LOG_PREFIX=\"[dhd-$(BUS_TYPE)]\"
- MODULE_NAME := dhd$(BUS_TYPE)
+endif
else
DHDCFLAGS += -DBUS_TYPE=\"\"
endif
ifneq ($(CONFIG_BCMDHD_ANDROID_VERSION),)
DHDCFLAGS += -DANDROID_VERSION=$(CONFIG_BCMDHD_ANDROID_VERSION)
DHDCFLAGS += -DDHD_NOTIFY_MAC_CHANGED
+ DHDCFLAGS += -DANDROID_BKPORT
ifneq ($(CONFIG_CFG80211),)
DHDCFLAGS += -DGSCAN_SUPPORT -DRTT_SUPPORT -DLINKSTAT_SUPPORT
DHDCFLAGS += -DCUSTOM_COUNTRY_CODE -DDHD_GET_VALID_CHANNELS
DHDCFLAGS += -DDEBUGABILITY -DDBG_PKT_MON
DHDCFLAGS += -DDHD_LOG_DUMP -DDHD_FW_COREDUMP
DHDCFLAGS += -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT
- DHDCFLAGS += -DDHD_WAKE_STATUS
- DHDOFILES += dhd_rtt.o bcm_app_utils.o
+ DHDCFLAGS += -DDHD_WAKE_STATUS -DWL_LATENCY_MODE
+ DHDOFILES += dhd_rtt.o
endif
else
DHDCFLAGS += -DANDROID_VERSION=0
DHDCFLAGS :=$(filter-out -DWL_STATIC_IF,$(DHDCFLAGS))
endif
+# EasyMesh
ifeq ($(CONFIG_BCMDHD_EASYMESH),y)
DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS))
DHDCFLAGS :=$(filter-out -DDHD_LOG_DUMP,$(DHDCFLAGS))
- DHDCFLAGS += -DWLEASYMESH -DWL_STATIC_IF -DWLDWDS -DFOURADDR_AUTO_BRG
+ DHDCFLAGS += -DWLEASYMESH
+ CONFIG_BCMDHD_DWDS := y
endif
-#CSI_SUPPORT
+# DWDS
+ifeq ($(CONFIG_BCMDHD_DWDS),y)
+ifneq ($(CONFIG_CFG80211),)
+ DHDCFLAGS += -DWLDWDS -DFOURADDR_AUTO_BRG
+ifneq ($(CONFIG_BCMDHD_SDIO),)
+ DHDCFLAGS += -DRXF_DEQUEUE_ON_BUSY
+endif
+ DHDCFLAGS += -DWL_STATIC_IF
+endif
+endif
+
+# CSI_SUPPORT
ifeq ($(CONFIG_CSI_SUPPORT),y)
DHDCFLAGS += -DCSI_SUPPORT
DHDOFILES += dhd_csi.o
endif
+# For CONNECTION_IMPROVE
+ifeq ($(CONFIG_BCMDHD_RECONNECT),y)
+ DHDCFLAGS += -DEAPOL_RESEND -DEAPOL_RESEND_M4
+ifneq ($(CONFIG_CFG80211),)
+ DHDCFLAGS += -DWL_EXT_RECONNECT -DWL_REASSOC_BCAST
+ DHDCFLAGS += -DWL_EXT_DISCONNECT_RECONNECT
+endif
+endif
+
# For TPUT_IMPROVE
ifeq ($(CONFIG_BCMDHD_TPUT),y)
DHDCFLAGS += -DDHD_TPUT_PATCH
# For WAPI
ifeq ($(CONFIG_BCMDHD_WAPI),y)
DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI
+ifeq ($(CONFIG_BCMDHD_ANDROID_VERSION),11)
+ DHDCFLAGS += -DCFG80211_WAPI_BKPORT
+endif
endif
# For scan random mac
# For Module auto-selection
ifeq ($(CONFIG_BCMDHD_AUTO_SELECT),y)
DHDCFLAGS += -DUPDATE_MODULE_NAME
+ifeq ($(CONFIG_BCMDHD_REQUEST_FW),y)
+# DHDCFLAGS += -DFW_AMPAK_PATH="\"ampak\""
+ DHDCFLAGS += -DMODULE_PATH
+endif
ifneq ($(CONFIG_BCMDHD_SDIO),)
DHDCFLAGS += -DGET_OTP_MODULE_NAME -DCOMPAT_OLD_MODULE
endif
#
endif
+ifeq ($(CONFIG_BCMDHD_REQUEST_FW),y)
+ DHDCFLAGS += -DDHD_LINUX_STD_FW_API
+ DHDCFLAGS += -DDHD_FW_NAME="\"fw_bcmdhd.bin\""
+ DHDCFLAGS += -DDHD_NVRAM_NAME="\"nvram.txt\""
+ DHDCFLAGS += -DDHD_CLM_NAME="\"clm_bcmdhd.blob\""
+else
+ DHDCFLAGS += -DDHD_SUPPORT_VFS_CALL
+ifeq ($(CONFIG_BCMDHD_FW_PATH),)
+ DHDCFLAGS += -DCONFIG_BCMDHD_FW_PATH="\"/system/etc/firmware/fw_bcmdhd.bin\""
+ DHDCFLAGS += -DCONFIG_BCMDHD_NVRAM_PATH="\"/system/etc/firmware/nvram.txt\""
+ DHDCFLAGS += -DCONFIG_BCMDHD_CLM_PATH="\"/system/etc/firmware/clm_bcmdhd.blob\""
+endif
+endif
+
ifeq ($(CONFIG_BCMDHD_AG),y)
DHDCFLAGS += -DBAND_AG
endif
bcmdhd_usb:
$(warning "building BCMDHD_USB..........")
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules CONFIG_BCMDHD_USB=y
- mv dhd.ko dhd_usb.ko
clean:
$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(ARCH) clean
#include <typedefs.h>
#include <bcmdefs.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
#include <stdarg.h>
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) */
#ifdef BCMDRIVER
#include <osl.h>
BCMEVENT_NAME(WLC_E_AUTH_START),
#endif /* WL_CLIENT_SAE */
#ifdef WL_TWT
- BCMEVENT_NAME(WLC_E_TWT_SETUP),
- BCMEVENT_NAME(WLC_E_TWT_TEARDOWN),
- BCMEVENT_NAME(WLC_E_TWT_INFO_FRM)
+ BCMEVENT_NAME(WLC_E_TWT),
#endif /* WL_TWT */
};
bcmsdh_unregister_client_driver();
}
+void *bcmsdh_get_dev(bcmsdh_info_t *sdh)
+{
+ bcmsdh_os_info_t *bcmsdh_osinfo = sdh->os_cxt;
+ return bcmsdh_osinfo->dev;
+}
+
void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *bcmsdh)
{
#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
#define CUSTOM_SDIO_F1_BLKSIZE DEFAULT_SDIO_F1_BLKSIZE
#endif
+#define COPY_BUF_SIZE (SDPCM_MAXGLOM_SIZE * 1600)
+
#define MAX_IO_RW_EXTENDED_BLK 511
uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */
return NULL;
}
bzero((char *)sd, sizeof(sdioh_info_t));
+#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STATIC_COPY_BUF)
+ sd->copy_buf = MALLOC(osh, COPY_BUF_SIZE);
+ if (sd->copy_buf == NULL) {
+ sd_err(("%s: MALLOC of %d-byte copy_buf failed\n",
+ __FUNCTION__, COPY_BUF_SIZE));
+ goto fail;
+ }
+#endif
sd->osh = osh;
sd->fake_func0.num = 0;
sd->fake_func0.card = func->card;
return sd;
fail:
+#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STATIC_COPY_BUF)
+ MFREE(sd->osh, sd->copy_buf, COPY_BUF_SIZE);
+#endif
MFREE(sd->osh, sd, sizeof(sdioh_info_t));
return NULL;
}
sd->func[1] = NULL;
sd->func[2] = NULL;
+#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STATIC_COPY_BUF)
+ MFREE(sd->osh, sd->copy_buf, COPY_BUF_SIZE);
+#endif
MFREE(sd->osh, sd, sizeof(sdioh_info_t));
}
return SDIOH_API_RC_SUCCESS;
}
if (err_ret) {
- if ((regaddr == 0x1001F) && ((err_ret == -ETIMEDOUT) || (err_ret == -EILSEQ)
- || (err_ret == -EIO))) {
+ if (regaddr == 0x1001F) {
/* XXX: Read/Write to SBSDIO_FUNC1_SLEEPCSR could return -110(timeout)
* or -84(CRC) error in case the host tries to wake the device up.
* Skip error log message if err code is -110 or -84 when accessing
return SDIOH_API_RC_FAIL;
}
}
- } else if(sd->txglom_mode == SDPCM_TXGLOM_CPY) {
+ }
+ else if(sd->txglom_mode == SDPCM_TXGLOM_CPY) {
for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
ttl_len += PKTLEN(sd->osh, pnext);
}
for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext);
pkt_len = PKTLEN(sd->osh, pnext);
-
if (!localbuf) {
+#ifdef BCMSDIOH_STATIC_COPY_BUF
+ if (ttl_len <= COPY_BUF_SIZE)
+ localbuf = sd->copy_buf;
+#else
localbuf = (uint8 *)MALLOC(sd->osh, ttl_len);
+#endif
if (localbuf == NULL) {
- sd_err(("%s: %s TXGLOM: localbuf malloc FAILED\n",
- __FUNCTION__, (write) ? "TX" : "RX"));
+ sd_err(("%s: %s localbuf malloc FAILED ttl_len=%d\n",
+ __FUNCTION__, (write) ? "TX" : "RX", ttl_len));
+ ttl_len -= pkt_len;
goto txglomfail;
}
}
-
bcopy(buf, (localbuf + local_plen), pkt_len);
local_plen += pkt_len;
if (PKTNEXT(sd->osh, pnext))
return SDIOH_API_RC_FAIL;
}
+#ifndef BCMSDIOH_STATIC_COPY_BUF
if (localbuf)
MFREE(sd->osh, localbuf, ttl_len);
+#endif
#ifndef PKT_STATICS
if (sd_msglevel & SDH_COST_VAL)
adapter->bus_num = host_idx;
adapter->slot_num = rca;
adapter->sdio_func = func;
- } else
+ } else {
sd_err(("can't find adapter info for this chip\n"));
+#ifdef ADAPTER_IDX
+ goto fail;
+#endif
+ }
#ifdef WL_CFG80211
wl_cfg80211_set_parent_dev(&func->dev);
#include <typedefs.h>
#include <bcmdefs.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
#include <stdarg.h>
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) */
#ifdef BCMDRIVER
#include <osl.h>
#include <bcmutils.h>
return bitcount;
}
-void
+static void
dump_nvram(char *varbuf, int column, unsigned int n, unsigned int len)
{
unsigned int m;
#include <typedefs.h>
#include <bcmdefs.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
#include <stdarg.h>
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) */
#ifdef BCMDRIVER
#include <osl.h>
*/
+#include <linux/usb.h>
#include "osl.h"
#include "dbus.h"
#include <bcmutils.h>
#include <dhd_wlfc.h>
#endif
#include <dhd_config.h>
+#ifdef WL_CFG80211
+#include <wl_cfg80211.h>
+#include <wl_cfgp2p.h>
+#endif
+#include <bcmdevs_legacy.h>
#if defined(BCM_REQUEST_FW)
#include <bcmsrom_fmt.h>
#include <trxhdr.h>
bool txoverride; /* flow control related */
bool rxoff;
bool tx_timer_ticking;
-
+ uint ctl_completed;
dbus_irbq_t *rx_q;
dbus_irbq_t *tx_q;
#endif
char *fw_path; /* module_param: path to firmware image */
char *nv_path; /* module_param: path to nvram vars file */
+ uint64 last_suspend_end_time;
} dhd_bus_t;
struct exec_parms {
static struct dbus_irb *dbus_if_getirb(void *cbarg, bool send);
static void dbus_if_rxerr_indicate(void *handle, bool on);
-void * dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype,
- uint16 bus_no, uint16 slot, uint32 hdrlen);
-void dhd_dbus_disconnect_cb(void *arg);
-void dbus_detach(dhd_bus_t *pub);
+static int dbus_suspend(void *context);
+static int dbus_resume(void *context);
+static void * dhd_dbus_probe_cb(uint16 bus_no, uint16 slot, uint32 hdrlen);
+static void dhd_dbus_disconnect_cb(void *arg);
+static void dbus_detach(dhd_bus_t *pub);
/** functions in this file that are called by lower DBUS levels, e.g. dbus_usb.c */
static dbus_intf_callbacks_t dbus_intf_cbs = {
* can be called inside disconnect()
*/
static dbus_intf_t *g_busintf = NULL;
-static probe_cb_t probe_cb = NULL;
-static disconnect_cb_t disconnect_cb = NULL;
-static void *probe_arg = NULL;
-static void *disc_arg = NULL;
#if defined(BCM_REQUEST_FW)
int8 *nonfwnvram = NULL; /* stand-alone multi-nvram given with driver load */
static int dbus_irbq_deinit(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int size_irb);
static int dbus_rxirbs_fill(dhd_bus_t *dhd_bus);
static int dbus_send_irb(dbus_pub_t *pub, uint8 *buf, int len, void *pkt, void *info);
-static void dbus_disconnect(void *handle);
-static void *dbus_probe(void *arg, const char *desc, uint32 bustype,
- uint16 bus_no, uint16 slot, uint32 hdrlen);
#if defined(BCM_REQUEST_FW)
extern char * dngl_firmware;
#ifdef EXTERNAL_FW_PATH
static int
-dbus_get_fw_nvram(dhd_bus_t *dhd_bus, char *pfw_path, char *pnv_path)
+dbus_get_fw_nvram(dhd_bus_t *dhd_bus)
{
int bcmerror = -1, i;
uint len, total_len;
struct trx_header *hdr;
uint32 img_offset = 0;
int offset = 0;
+ char *pfw_path = dhd_bus->fw_path;
+ char *pnv_path = dhd_bus->nv_path;
/* For Get nvram */
file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
* the dongle
*/
static int
-dbus_do_download(dhd_bus_t *dhd_bus, char *pfw_path, char *pnv_path)
+dbus_do_download(dhd_bus_t *dhd_bus)
{
int err = DBUS_OK;
- err = dbus_get_fw_nvram(dhd_bus, pfw_path, pnv_path);
+ err = dbus_get_fw_nvram(dhd_bus);
if (err) {
DBUSERR(("dbus_do_download: fail to get nvram %d\n", err));
return err;
nvram_words_pad = 4 - dhd_bus->nvram_len % 4;
len = actual_fwlen + dhd_bus->nvram_len + nvram_words_pad;
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
+ dhd_bus->image = (uint8*)DHD_OS_PREALLOC(dhd_bus->dhd,
+ DHD_PREALLOC_MEMDUMP_RAM, len);
+#else
dhd_bus->image = MALLOC(dhd_bus->pub.osh, len);
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
dhd_bus->image_len = len;
if (dhd_bus->image == NULL) {
DBUSERR(("%s: malloc failed!\n", __FUNCTION__));
#if defined(BCM_REQUEST_FW)
dhd_bus->firmware = dbus_get_fw_nvfile(dhd_bus->pub.attrib.devid,
dhd_bus->pub.attrib.chiprev, &dhd_bus->fw, &dhd_bus->fwlen,
- DBUS_FIRMWARE, 0, 0);
+ DBUS_FIRMWARE, 0, 0, dhd_bus->fw_path);
if (!dhd_bus->firmware)
return DBUS_ERR;
#endif
nonfwnvramlen = 0;
dhd_bus->nvfile = dbus_get_fw_nvfile(dhd_bus->pub.attrib.devid,
dhd_bus->pub.attrib.chiprev, (void *)&temp_nvram, &temp_len,
- DBUS_NVFILE, boardtype, boardrev);
+ DBUS_NVFILE, boardtype, boardrev, dhd_bus->nv_path);
if (dhd_bus->nvfile) {
int8 *tmp = MALLOC(dhd_bus->pub.osh, temp_len);
if (tmp) {
err = DBUS_ERR;
if (dhd_bus->nvram) {
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
+ DHD_OS_PREFREE(dhd_bus->dhd, dhd_bus->image, dhd_bus->image_len);
+#else
MFREE(dhd_bus->pub.osh, dhd_bus->image, dhd_bus->image_len);
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
dhd_bus->image = dhd_bus->fw;
dhd_bus->image_len = (uint32)dhd_bus->fwlen;
}
#endif /* EXTERNAL_FW_PATH */
#endif
-/** required for DBUS deregistration */
-static void
-dbus_disconnect(void *handle)
-{
- DBUSTRACE(("%s\n", __FUNCTION__));
-
- if (disconnect_cb)
- disconnect_cb(disc_arg);
-}
-
/**
* This function is called when the sent irb times out without a tx response status.
* DBUS adds reliability by resending timed out IRBs DBUS_TX_RETRY_LIMIT times.
return irb;
}
-/**
- * Called as part of DBUS bus registration. Calls back into higher level (e.g. dhd_linux.c) probe
- * function.
+/* Register/Unregister functions are called by the main DHD entry
+ * point (e.g. module insertion) to link with the bus driver, in
+ * order to look for or await the device.
*/
-static void *
-dbus_probe(void *arg, const char *desc, uint32 bustype, uint16 bus_no,
- uint16 slot, uint32 hdrlen)
-{
- DBUSTRACE(("%s\n", __FUNCTION__));
- if (probe_cb) {
- disc_arg = probe_cb(probe_arg, desc, bustype, bus_no, slot, hdrlen);
- return disc_arg;
- }
- return (void *)DBUS_ERR;
-}
+static dbus_driver_t dhd_dbus = {
+ dhd_dbus_probe_cb,
+ dhd_dbus_disconnect_cb,
+ dbus_suspend,
+ dbus_resume
+};
/**
* As part of initialization, higher level (e.g. dhd_linux.c) requests DBUS to prepare for
DBUSTRACE(("%s: Enter\n", __FUNCTION__));
- probe_cb = dhd_dbus_probe_cb;
- disconnect_cb = dhd_dbus_disconnect_cb;
- probe_arg = NULL;
-
- err = dbus_bus_register(0xa5c, 0x48f, dbus_probe, /* call lower DBUS level register function */
- dbus_disconnect, NULL, &g_busintf, NULL, NULL);
+ err = dbus_bus_register(&dhd_dbus, &g_busintf);
/* Device not detected */
if (err == DBUS_ERR_NODEVICE)
}
dhd_pub_t *g_pub = NULL;
+bool net_attached = FALSE;
void
dhd_bus_unregister(void)
{
- int ret;
-
DBUSTRACE(("%s\n", __FUNCTION__));
DHD_MUTEX_LOCK();
dhd_dbus_disconnect_cb(g_pub->bus);
}
}
- probe_cb = NULL;
DHD_MUTEX_UNLOCK();
- ret = dbus_bus_deregister();
- disconnect_cb = NULL;
- probe_arg = NULL;
+ dbus_bus_deregister();
}
/** As part of initialization, data structures have to be allocated and initialized */
}
#if defined(BCM_REQUEST_FW)
-int dbus_download_firmware(dhd_bus_t *pub, char *pfw_path, char *pnv_path)
+int dbus_download_firmware(dhd_bus_t *pub)
{
dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_OK;
DBUSTRACE(("%s: state %d\n", __FUNCTION__, dhd_bus->pub.busstate));
dhd_bus->pub.busstate = DBUS_STATE_DL_PENDING;
-#ifdef EXTERNAL_FW_PATH
- err = dbus_do_download(dhd_bus, pfw_path, pnv_path);
-#else
err = dbus_do_download(dhd_bus);
-#endif /* EXTERNAL_FW_PATH */
if (err == DBUS_OK) {
dhd_bus->pub.busstate = DBUS_STATE_DL_DONE;
} else {
return DBUS_ERR;
}
-int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf)
-{
- return dbus_send_pkt(dbus, pktbuf, pktbuf /* pktinfo */);
-}
-
int
dbus_send_buf(dbus_pub_t *pub, uint8 *buf, int len, void *info)
{
return dbus_send_irb(pub, buf, len, NULL, info);
}
-int
+static int
dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info)
{
return dbus_send_irb(pub, NULL, 0, pkt, info);
}
-int
+static int
dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len)
{
dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
return DBUS_ERR;
}
-int
+static int
dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len)
{
dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
if (dhd_bus->drvintf && dhd_bus->drvintf->recv_ctl)
return dhd_bus->drvintf->recv_ctl(dhd_bus->bus_info, buf, len);
+ } else {
+ DBUSERR(("%s: bustate=%d\n", __FUNCTION__, dhd_bus->pub.busstate));
}
return DBUS_ERR;
return DBUS_ERR;
}
+#ifdef INTR_EP_ENABLE
/** only called by dhd_cdc.c (Dec 2012) */
-int
+static int
dbus_poll_intr(dbus_pub_t *pub)
{
dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
}
return status;
}
+#endif /* INTR_EP_ENABLE */
/** called by nobody (Dec 2012) */
void *
dhd->tx_ctlerrs++;
}
- dhd_prot_ctl_complete(dhd);
+ dhd->bus->ctl_completed = TRUE;
+ dhd_os_ioctl_resp_wake(dhd);
}
static void
{
dhd_pub_t *dhd = (dhd_pub_t *)handle;
unsigned long flags;
+ wifi_adapter_info_t *adapter;
if (dhd == NULL) {
DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
return;
}
+ adapter = (wifi_adapter_info_t *)dhd->adapter;
+ if (dhd->busstate == DHD_BUS_SUSPEND && state == DBUS_STATE_DOWN) {
+ DBUSERR(("%s: switch state %d to %d\n", __FUNCTION__, state, DBUS_STATE_SLEEP));
+ state = DBUS_STATE_SLEEP;
+ }
switch (state) {
-
case DBUS_STATE_DL_NEEDED:
DBUSERR(("%s: firmware request cannot be handled\n", __FUNCTION__));
break;
case DBUS_STATE_DOWN:
- DBUSTRACE(("%s: DBUS is down\n", __FUNCTION__));
DHD_LINUX_GENERAL_LOCK(dhd, flags);
dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);
+ DBUSTRACE(("%s: DBUS is down\n", __FUNCTION__));
dhd->busstate = DHD_BUS_DOWN;
DHD_LINUX_GENERAL_UNLOCK(dhd, flags);
break;
dhd->busstate = DHD_BUS_DATA;
DHD_LINUX_GENERAL_UNLOCK(dhd, flags);
break;
- case DBUS_STATE_SLEEP:
- DBUSTRACE(("%s: DBUS is suspend\n", __FUNCTION__));
- DHD_LINUX_GENERAL_LOCK(dhd, flags);
- dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);
- dhd->busstate = DHD_BUS_SUSPEND;
- DHD_LINUX_GENERAL_UNLOCK(dhd, flags);
- break;
default:
break;
}
return bus->pub.attrib.chiprev;
}
+struct device *
+dhd_bus_to_dev(struct dhd_bus *bus)
+{
+ return dbus_get_dev();
+}
+
void
dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
{
DBUSTRACE(("txoff\n"));
return BCME_EPERM;
}
- return dbus_send_txdata(&bus->pub, pktbuf);
+ return dbus_send_pkt(&bus->pub, pktbuf, pktbuf);
+}
+
+int
+dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
+{
+ int timeleft = 0;
+ int ret = -1;
+
+ DBUSTRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd->dongle_reset)
+ return -EIO;
+
+ bus->ctl_completed = FALSE;
+ ret = dbus_send_ctl(bus, (void *)msg, msglen);
+ if (ret) {
+ DBUSERR(("%s: dbus_send_ctl error %d\n", __FUNCTION__, ret));
+ return ret;
+ }
+
+ timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->ctl_completed);
+ if ((!timeleft) || (!bus->ctl_completed)) {
+ DBUSERR(("%s: Txctl timeleft %d ctl_completed %d\n",
+ __FUNCTION__, timeleft, bus->ctl_completed));
+ ret = -1;
+ }
+
+#ifdef INTR_EP_ENABLE
+ /* If the ctl write is successfully completed, wait for an acknowledgement
+ * that indicates that it is now ok to do ctl read from the dongle
+ */
+ if (ret != -1) {
+ bus->ctl_completed = FALSE;
+ if (dbus_poll_intr(bus->pub)) {
+ DBUSERR(("%s: dbus_poll_intr not submitted\n", __FUNCTION__));
+ } else {
+ /* interrupt polling is sucessfully submitted. Wait for dongle to send
+ * interrupt
+ */
+ timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->ctl_completed);
+ if (!timeleft) {
+ DBUSERR(("%s: intr poll wait timed out\n", __FUNCTION__));
+ }
+ }
+ }
+#endif /* INTR_EP_ENABLE */
+
+ return ret;
+}
+
+int
+dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
+{
+ int timeleft;
+ int ret = -1;
+
+ DBUSTRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (bus->dhd->dongle_reset)
+ return -EIO;
+
+ bus->ctl_completed = FALSE;
+ ret = dbus_recv_ctl(bus, (uchar*)msg, msglen);
+ if (ret) {
+ DBUSERR(("%s: dbus_recv_ctl error %d\n", __FUNCTION__, ret));
+ goto done;
+ }
+
+ timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->ctl_completed);
+ if ((!timeleft) || (!bus->ctl_completed)) {
+ DBUSERR(("%s: Rxctl timeleft %d ctl_completed %d\n", __FUNCTION__,
+ timeleft, bus->ctl_completed));
+ ret = -ETIMEDOUT;
+ goto done;
+ }
+
+ /* XXX FIX: Must return cdc_len, not len, because after query_ioctl()
+ * it subtracts sizeof(cdc_ioctl_t); The other approach is
+ * to have dbus_recv_ctl() return actual len.
+ */
+ ret = msglen;
+
+done:
+ return ret;
}
static void
int timeleft;
DHD_LINUX_GENERAL_LOCK(dhdp, flags);
- dhdp->busstate = DHD_BUS_REMOVE;
+ if (dhdp->busstate != DHD_BUS_SUSPEND)
+ dhdp->busstate = DHD_BUS_REMOVE;
DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
}
+static int
+dhd_dbus_sync_dongle(dhd_pub_t *pub, int dlneeded)
+{
+ int ret = 0;
+
+ if (dlneeded == 0) {
+ ret = dbus_up(pub->bus);
+ if (ret) {
+ DBUSERR(("%s: dbus_up failed!!\n", __FUNCTION__));
+ goto exit;
+ }
+ ret = dhd_sync_with_dongle(pub);
+ if (ret < 0) {
+ DBUSERR(("%s: failed with code ret=%d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+ }
+
+exit:
+ return ret;
+}
+
+static int
+dbus_suspend(void *context)
+{
+ int ret = 0;
+
+#if defined(LINUX)
+ dhd_bus_t *bus = (dhd_bus_t*)context;
+ unsigned long flags;
+
+ DBUSERR(("%s Enter\n", __FUNCTION__));
+ if (bus->dhd == NULL) {
+ DBUSERR(("bus not inited\n"));
+ return BCME_ERROR;
+ }
+ if (bus->dhd->prot == NULL) {
+ DBUSERR(("prot is not inited\n"));
+ return BCME_ERROR;
+ }
+
+ if (bus->dhd->up == FALSE) {
+ return BCME_OK;
+ }
+
+ DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
+ if (bus->dhd->busstate != DHD_BUS_DATA && bus->dhd->busstate != DHD_BUS_SUSPEND) {
+ DBUSERR(("not in a readystate to LPBK is not inited\n"));
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
+ return BCME_ERROR;
+ }
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
+ if (bus->dhd->dongle_reset) {
+ DBUSERR(("Dongle is in reset state.\n"));
+ return -EIO;
+ }
+
+ DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
+ /* stop all interface network queue. */
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
+ bus->dhd->busstate = DHD_BUS_SUSPEND;
+#if defined(LINUX) || defined(linux)
+ if (DHD_BUS_BUSY_CHECK_IN_TX(bus->dhd)) {
+ DBUSERR(("Tx Request is not ended\n"));
+ bus->dhd->busstate = DHD_BUS_DATA;
+ /* resume all interface network queue. */
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
+ return -EBUSY;
+ }
+#endif /* LINUX || linux */
+ DHD_BUS_BUSY_SET_SUSPEND_IN_PROGRESS(bus->dhd);
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
+
+ ret = dhd_os_check_wakelock_all(bus->dhd);
+
+ DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
+ if (ret) {
+ bus->dhd->busstate = DHD_BUS_DATA;
+ /* resume all interface network queue. */
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
+ } else {
+ bus->last_suspend_end_time = OSL_LOCALTIME_NS();
+ }
+ bus->dhd->hostsleep = 2;
+ DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd);
+ dhd_os_busbusy_wake(bus->dhd);
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
+
+#endif /* LINUX */
+ DBUSERR(("%s Exit ret=%d\n", __FUNCTION__, ret));
+ return ret;
+}
+
+static int
+dbus_resume(void *context)
+{
+ dhd_bus_t *bus = (dhd_bus_t*)context;
+ ulong flags;
+ int dlneeded = 0;
+ int ret = 0;
+
+ DBUSERR(("%s Enter\n", __FUNCTION__));
+
+ if (bus->dhd->up == FALSE) {
+ return BCME_OK;
+ }
+
+ dlneeded = dbus_dlneeded(bus);
+ if (dlneeded == 0) {
+ ret = dbus_up(bus);
+ if (ret) {
+ DBUSERR(("%s: dbus_up failed!!\n", __FUNCTION__));
+ }
+ }
+
+ DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
+ DHD_BUS_BUSY_SET_RESUME_IN_PROGRESS(bus->dhd);
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
+
+ DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
+ DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd);
+ bus->dhd->hostsleep = 0;
+ bus->dhd->busstate = DHD_BUS_DATA;
+ dhd_os_busbusy_wake(bus->dhd);
+ /* resume all interface network queue. */
+ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
+ DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
+// dhd_conf_set_suspend_resume(bus->dhd, 0);
+
+ return 0;
+}
+
/*
* hdrlen is space to reserve in pkt headroom for DBUS
*/
-void *
-dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype,
- uint16 bus_no, uint16 slot, uint32 hdrlen)
+static void *
+dhd_dbus_probe_cb(uint16 bus_no, uint16 slot, uint32 hdrlen)
{
osl_t *osh = NULL;
dhd_bus_t *bus = NULL;
dhd_pub_t *pub = NULL;
uint rxsz;
- int dlneeded = 0;
+ int dlneeded = 0, ret = DBUS_OK;
wifi_adapter_info_t *adapter = NULL;
+ bool net_attach_now = TRUE;
DBUSTRACE(("%s: Enter\n", __FUNCTION__));
- adapter = dhd_wifi_platform_get_adapter(bustype, bus_no, slot);
+ adapter = dhd_wifi_platform_get_adapter(USB_BUS, bus_no, slot);
if (!g_pub) {
/* Ask the OS interface part for an OSL handle */
- if (!(osh = osl_attach(NULL, bustype, TRUE))) {
+ if (!(osh = osl_attach(NULL, USB_BUS, TRUE))) {
DBUSERR(("%s: OSL attach failed\n", __FUNCTION__));
goto fail;
}
bus->dhd = pub;
dlneeded = dbus_dlneeded(bus);
- if (dlneeded >= 0) {
- if (!g_pub) {
- dhd_conf_reset(pub);
- dhd_conf_set_chiprev(pub, bus->pub.attrib.devid, bus->pub.attrib.chiprev);
- dhd_conf_preinit(pub);
- }
+ if (dlneeded >= 0 && !g_pub) {
+ dhd_conf_reset(pub);
+ dhd_conf_set_chiprev(pub, bus->pub.attrib.devid, bus->pub.attrib.chiprev);
+ dhd_conf_preinit(pub);
}
- if (g_pub || dhd_download_fw_on_driverload) {
- if (dlneeded == 0) {
+#if defined(BCMDHD_MODULAR) && defined(INSMOD_FW_LOAD)
+ if (1)
+#else
+ if (g_pub || dhd_download_fw_on_driverload)
+#endif
+ {
+ if (dlneeded == 0)
wifi_set_adapter_status(adapter, WIFI_STATUS_FW_READY);
#ifdef BCM_REQUEST_FW
- } else if (dlneeded > 0) {
+ else if (dlneeded > 0) {
+ struct dhd_conf *conf = pub->conf;
+ unsigned long flags;
+ bool suspended;
wifi_clr_adapter_status(adapter, WIFI_STATUS_FW_READY);
+ suspended = conf->suspended;
dhd_set_path(bus->dhd);
- if (dbus_download_firmware(bus, bus->fw_path, bus->nv_path) != DBUS_OK)
+ conf->suspended = suspended;
+ if (dbus_download_firmware(bus) != DBUS_OK)
goto fail;
- bus->dhd->busstate = DHD_BUS_LOAD;
+ DHD_LINUX_GENERAL_LOCK(pub, flags);
+ if (bus->dhd->busstate != DHD_BUS_SUSPEND)
+ bus->dhd->busstate = DHD_BUS_LOAD;
+ DHD_LINUX_GENERAL_UNLOCK(pub, flags);
+ }
#endif
- } else {
+ else {
goto fail;
}
}
- } else {
+ }
+ else {
DBUSERR(("%s: dbus_attach failed\n", __FUNCTION__));
+ goto fail;
}
- if (!g_pub) {
- /* Ok, have the per-port tell the stack we're open for business */
- if (dhd_attach_net(bus->dhd, TRUE) != 0)
- {
+#if defined(BCMDHD_MODULAR) && defined(INSMOD_FW_LOAD)
+ if (dlneeded > 0)
+ net_attach_now = FALSE;
+#endif
+
+ if (!net_attached && (net_attach_now || (dlneeded == 0))) {
+ if (dhd_dbus_sync_dongle(pub, dlneeded)) {
+ goto fail;
+ }
+ if (dhd_attach_net(bus->dhd, TRUE) != 0) {
DBUSERR(("%s: Net attach failed!!\n", __FUNCTION__));
goto fail;
}
#if defined(MULTIPLE_SUPPLICANT)
wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
#endif
+ net_attached = TRUE;
+ }
+ else if (net_attached && (pub->up == 1) && (dlneeded == 0)) {
+ // kernel resume case
+ pub->hostsleep = 0;
+ ret = dhd_dbus_sync_dongle(pub, dlneeded);
+#ifdef WL_CFG80211
+ __wl_cfg80211_up_resume(pub);
+ wl_cfgp2p_start_p2p_device_resume(pub);
+#endif
+ dhd_conf_set_suspend_resume(pub, 0);
+ if (ret != DBUS_OK)
+ goto fail;
+ }
+
+ if (!g_pub) {
g_pub = pub;
}
DBUSTRACE(("%s: Exit\n", __FUNCTION__));
- wifi_clr_adapter_status(adapter, WIFI_STATUS_DETTACH);
- wifi_set_adapter_status(adapter, WIFI_STATUS_ATTACH);
- wake_up_interruptible(&adapter->status_event);
- /* This is passed to dhd_dbus_disconnect_cb */
+ if (net_attached) {
+ wifi_set_adapter_status(adapter, WIFI_STATUS_NET_ATTACHED);
+ wake_up_interruptible(&adapter->status_event);
+ /* This is passed to dhd_dbus_disconnect_cb */
+ }
return bus;
fail:
return NULL;
}
-void
+static void
dhd_dbus_disconnect_cb(void *arg)
{
dhd_bus_t *bus = (dhd_bus_t *)arg;
dhd_dbus_advertise_bus_remove(bus->dhd);
dbus_detach(pub->bus);
pub->bus = NULL;
- wifi_clr_adapter_status(adapter, WIFI_STATUS_ATTACH);
- wifi_set_adapter_status(adapter, WIFI_STATUS_DETTACH);
wake_up_interruptible(&adapter->status_event);
} else {
osh = pub->osh;
}
dhd_free(pub);
g_pub = NULL;
+ net_attached = FALSE;
+ wifi_clr_adapter_status(adapter, WIFI_STATUS_NET_ATTACHED);
if (MALLOCED(osh)) {
DBUSERR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh)));
}
}
EXPORT_SYMBOL(dbus_pnp_sleep);
+EXPORT_SYMBOL(dhd_bus_register);
EXPORT_SYMBOL(dbus_get_devinfo);
EXPORT_SYMBOL(dbus_detach);
EXPORT_SYMBOL(dbus_get_attrib);
EXPORT_SYMBOL(dbus_send_pkt);
EXPORT_SYMBOL(dbus_recv_ctl);
EXPORT_SYMBOL(dbus_attach);
+EXPORT_SYMBOL(dhd_bus_unregister);
MODULE_LICENSE("GPL");
#define USB_DLGO_SPINWAIT 100 /* wait after DL_GO (ms) */
#define TEST_CHIP 0x4328
+/* driver info, initialized when bcmsdh_register is called */
+static dbus_driver_t drvinfo = {NULL, NULL, NULL, NULL};
+
typedef struct {
dbus_pub_t *pub;
* attach() is not called at probe and detach()
* can be called inside disconnect()
*/
-static probe_cb_t probe_cb = NULL;
-static disconnect_cb_t disconnect_cb = NULL;
-static void *probe_arg = NULL;
-static void *disc_arg = NULL;
static dbus_intf_t *g_dbusintf = NULL;
static dbus_intf_t dbus_usb_intf; /** functions called by higher layer DBUS into lower layer */
*/
static void *dbus_usb_attach(dbus_pub_t *pub, void *cbarg, dbus_intf_callbacks_t *cbs);
static void dbus_usb_detach(dbus_pub_t *pub, void *info);
-static void * dbus_usb_probe(void *arg, const char *desc, uint32 bustype,
- uint16 bus_no, uint16 slot, uint32 hdrlen);
+static void * dbus_usb_probe(uint16 bus_no, uint16 slot, uint32 hdrlen);
/* functions */
* lower level DBUS functions to call (in both dbus_usb.c and dbus_usb_os.c).
*/
static void *
-dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint16 bus_no,
- uint16 slot, uint32 hdrlen)
+dbus_usb_probe(uint16 bus_no, uint16 slot, uint32 hdrlen)
{
DBUSTRACE(("%s(): \n", __FUNCTION__));
- if (probe_cb) {
-
+ if (drvinfo.probe) {
if (g_dbusintf != NULL) {
/* First, initialize all lower-level functions as default
* so that dbus.c simply calls directly to dbus_usb_os.c.
dbus_usb_intf.dlrun = dbus_usb_dlrun;
}
- disc_arg = probe_cb(probe_arg, "DBUS USB", USB_BUS, bus_no, slot, hdrlen);
- return disc_arg;
+ return drvinfo.probe(bus_no, slot, hdrlen);
}
return NULL;
}
+static int
+dbus_usb_suspend(void *handle)
+{
+ DBUSTRACE(("%s(): \n", __FUNCTION__));
+
+ if (drvinfo.suspend)
+ return drvinfo.suspend(handle);
+
+ return BCME_OK;
+}
+
+static int
+dbus_usb_resume(void *handle)
+{
+ DBUSTRACE(("%s(): \n", __FUNCTION__));
+
+ if (drvinfo.resume)
+ drvinfo.resume(handle);
+
+ return 0;
+}
+
+static dbus_driver_t dhd_usb_dbus = {
+ dbus_usb_probe,
+ dbus_usb_disconnect,
+ dbus_usb_suspend,
+ dbus_usb_resume
+};
+
/**
* On return, *intf contains this or lower-level DBUS functions to be called by higher
* level (dbus.c)
*/
int
-dbus_bus_register(int vid, int pid, probe_cb_t prcb,
- disconnect_cb_t discb, void *prarg, dbus_intf_t **intf, void *param1, void *param2)
+dbus_bus_register(dbus_driver_t *driver, dbus_intf_t **intf)
{
int err;
DBUSTRACE(("%s(): \n", __FUNCTION__));
- probe_cb = prcb;
- disconnect_cb = discb;
- probe_arg = prarg;
-
+ drvinfo = *driver;
*intf = &dbus_usb_intf;
- err = dbus_bus_osl_register(vid, pid, dbus_usb_probe,
- dbus_usb_disconnect, NULL, &g_dbusintf, param1, param2);
+ err = dbus_bus_osl_register(&dhd_usb_dbus, &g_dbusintf);
ASSERT(g_dbusintf);
return err;
dbus_usb_disconnect(void *handle)
{
DBUSTRACE(("%s(): \n", __FUNCTION__));
- if (disconnect_cb)
- disconnect_cb(disc_arg);
+ if (drvinfo.remove)
+ drvinfo.remove(handle);
}
/**
struct usb_interface *intf;
} probe_info_t;
+/* driver info, initialized when bcmsdh_register is called */
+static dbus_driver_t drvinfo = {NULL, NULL, NULL, NULL};
+
/*
* USB Linux dbus_intf_t
*/
};
static probe_info_t g_probe_info;
-static probe_cb_t probe_cb = NULL;
-static disconnect_cb_t disconnect_cb = NULL;
-static void *probe_arg = NULL;
static void *disc_arg = NULL;
dbus_usbos_suspend(struct usb_interface *intf,
pm_message_t message)
{
- DBUSERR(("%s suspend state: %d\n", __FUNCTION__, g_probe_info.suspend_state));
+ usbos_info_t *usbos_info = (usbos_info_t *) g_probe_info.usbos_info;
+ int err = 0;
+
+ printf("%s Enter\n", __FUNCTION__);
+
/* DHD for full dongle model */
g_probe_info.suspend_state = USBOS_SUSPEND_STATE_SUSPEND_PENDING;
- dbus_usbos_state_change((usbos_info_t*)g_probe_info.usbos_info, DBUS_STATE_SLEEP);
+ if (drvinfo.suspend && disc_arg)
+ err = drvinfo.suspend(disc_arg);
+ if (err) {
+ printf("%s: err=%d\n", __FUNCTION__, err);
+// g_probe_info.suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
+// return err;
+ }
+ usbos_info->pub->busstate = DBUS_STATE_SLEEP;
+
dbus_usbos_cancel_all_urbs((usbos_info_t*)g_probe_info.usbos_info);
g_probe_info.suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
- return 0;
+ printf("%s Exit err=%d\n", __FUNCTION__, err);
+ return err;
}
/**
* The resume method is called to tell the driver that the device has been resumed and the driver
* can return to normal operation. URBs may once more be submitted.
*/
-static int dbus_usbos_resume(struct usb_interface *intf)
+static int
+dbus_usbos_resume(struct usb_interface *intf)
{
- DBUSERR(("%s Device resumed\n", __FUNCTION__));
+ usbos_info_t *usbos_info = (usbos_info_t *) g_probe_info.usbos_info;
+
+ printf("%s Enter\n", __FUNCTION__);
- dbus_usbos_state_change((usbos_info_t*)g_probe_info.usbos_info, DBUS_STATE_UP);
g_probe_info.suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
+ if (drvinfo.resume && disc_arg)
+ drvinfo.resume(disc_arg);
+ usbos_info->pub->busstate = DBUS_STATE_UP;
+
+ printf("%s Exit\n", __FUNCTION__);
return 0;
}
* This function is directly called by the Linux kernel, when the suspended device has been reset
* instead of being resumed
*/
-static int dbus_usbos_reset_resume(struct usb_interface *intf)
+static int
+dbus_usbos_reset_resume(struct usb_interface *intf)
{
- DBUSERR(("%s Device reset resumed\n", __FUNCTION__));
+ printf("%s Enter\n", __FUNCTION__);
- /* The device may have lost power, so a firmware download may be required */
- dbus_usbos_state_change((usbos_info_t*)g_probe_info.usbos_info, DBUS_STATE_DL_NEEDED);
g_probe_info.suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
+ if (drvinfo.resume && disc_arg)
+ drvinfo.resume(disc_arg);
+
+ printf("%s Exit\n", __FUNCTION__);
return 0;
}
g_probe_info.device_speed = FULL_SPEED;
DBUSERR(("full speed device detected\n"));
}
- if (g_probe_info.dereged == FALSE && probe_cb) {
- disc_arg = probe_cb(probe_arg, "", USB_BUS, usb->bus->busnum, usb->portnum, 0);
+ if (g_probe_info.dereged == FALSE && drvinfo.probe) {
+ disc_arg = drvinfo.probe(usb->bus->busnum, usb->portnum, 0);
}
g_probe_info.disc_cb_done = FALSE;
if (probe_usb_init_data) {
usbos_info = (usbos_info_t *) probe_usb_init_data->usbos_info;
if (usbos_info) {
- if ((probe_usb_init_data->dereged == FALSE) && disconnect_cb && disc_arg) {
- disconnect_cb(disc_arg);
+ if ((probe_usb_init_data->dereged == FALSE) && drvinfo.remove && disc_arg) {
+ drvinfo.remove(disc_arg);
disc_arg = NULL;
probe_usb_init_data->disc_cb_done = TRUE;
}
}
int
-dbus_bus_osl_register(int vid, int pid, probe_cb_t prcb,
- disconnect_cb_t discb, void *prarg, dbus_intf_t **intf, void *param1, void *param2)
+dbus_bus_osl_register(dbus_driver_t *driver, dbus_intf_t **intf)
{
bzero(&g_probe_info, sizeof(probe_info_t));
- probe_cb = prcb;
- disconnect_cb = discb;
- probe_arg = prarg;
-
- devid_table[0].idVendor = vid;
- devid_table[0].idProduct = pid;
-
+ drvinfo = *driver;
*intf = &dbus_usbos_intf;
USB_REGISTER();
g_probe_info.dereged = TRUE;
DHD_MUTEX_LOCK();
- if (disconnect_cb && disc_arg && (g_probe_info.disc_cb_done == FALSE)) {
- disconnect_cb(disc_arg);
+ if (drvinfo.remove && disc_arg && (g_probe_info.disc_cb_done == FALSE)) {
+ drvinfo.remove(disc_arg);
disc_arg = NULL;
}
DHD_MUTEX_UNLOCK();
return *firmware != NULL ? 0 : -ENOENT;
}
+#ifndef DHD_LINUX_STD_FW_API
static void *
-dbus_get_fwfile(int devid, int chiprev, uint8 **fw, int *fwlen, uint16 boardtype, uint16 boardrev)
+dbus_get_fwfile(int devid, int chiprev, uint8 **fw, int *fwlen,
+ uint16 boardtype, uint16 boardrev, char *path)
{
const struct firmware *firmware = NULL;
#ifndef OEM_ANDROID
snprintf(file_name, sizeof(file_name), "%s", CONFIG_ANDROID_BCMDHD_FW_PATH);
#endif /* OEM_ANDROID */
- ret = dbus_request_firmware(file_name, &firmware);
+ ret = dbus_request_firmware(path, &firmware);
if (ret) {
- DBUSERR(("fail to request firmware %s\n", file_name));
+ DBUSERR(("fail to request firmware %s\n", path));
return NULL;
- }
+ } else
+ DBUSERR(("%s: %s (%zu bytes) open success\n", __FUNCTION__, path, firmware->size));
*fwlen = firmware->size;
*fw = (uint8 *)firmware->data;
}
static void *
-dbus_get_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen, uint16 boardtype, uint16 boardrev)
+dbus_get_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen,
+ uint16 boardtype, uint16 boardrev, char *path)
{
const struct firmware *firmware = NULL;
#ifndef OEM_ANDROID
snprintf(file_name, sizeof(file_name), "%s", CONFIG_ANDROID_BCMDHD_NVRAM_PATH);
#endif /* OEM_ANDROID */
- ret = dbus_request_firmware(file_name, &firmware);
+ ret = dbus_request_firmware(path, &firmware);
if (ret) {
- DBUSERR(("fail to request nvram %s\n", file_name));
+ DBUSERR(("fail to request nvram %s\n", path));
#ifndef OEM_ANDROID
/* Load generic nvram file */
#endif /* OEM_ANDROID */
if (ret) {
- DBUSERR(("fail to request nvram %s\n", file_name));
+ DBUSERR(("fail to request nvram %s\n", path));
return NULL;
}
- }
+ } else
+ DBUSERR(("%s: %s (%zu bytes) open success\n", __FUNCTION__, path, firmware->size));
*fwlen = firmware->size;
*fw = (uint8 *)firmware->data;
void *
dbus_get_fw_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen, int type, uint16 boardtype,
- uint16 boardrev)
+ uint16 boardrev, char *path)
{
switch (type) {
case DBUS_FIRMWARE:
- return dbus_get_fwfile(devid, chiprev, fw, fwlen, boardtype, boardrev);
+ return dbus_get_fwfile(devid, chiprev, fw, fwlen, boardtype, boardrev, path);
case DBUS_NVFILE:
- return dbus_get_nvfile(devid, chiprev, fw, fwlen, boardtype, boardrev);
+ return dbus_get_nvfile(devid, chiprev, fw, fwlen, boardtype, boardrev, path);
default:
return NULL;
}
}
+#else
+void *
+dbus_get_fw_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen, int type, uint16 boardtype,
+ uint16 boardrev, char *path)
+{
+ const struct firmware *firmware = NULL;
+ int err = DBUS_OK;
+
+ err = dbus_request_firmware(path, &firmware);
+ if (err) {
+ DBUSERR(("fail to request firmware %s\n", path));
+ return NULL;
+ } else {
+ DBUSERR(("%s: %s (%zu bytes) open success\n",
+ __FUNCTION__, path, firmware->size));
+ }
+
+ *fwlen = firmware->size;
+ *fw = (uint8 *)firmware->data;
+ return (void *)firmware;
+}
+#endif
void
dbus_release_fw_nvfile(void *firmware)
return intf_wlan;
}
#endif /* BCMUSBDEV_COMPOSITE */
+
+#ifdef LINUX
+struct device * dbus_get_dev(void)
+{
+ return &g_probe_info.usb->dev;
+}
+#endif /* LINUX */
\ No newline at end of file
#define _dhd_h_
#if defined(LINUX)
+#include <linux/firmware.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
#include <uapi/linux/sched/types.h>
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
struct dhd_conf *conf; /* Bus module handle */
void *adapter; /* adapter information, interrupt, fw path etc. */
void *event_params;
+#ifdef WL_TIMER
+ void *timer_params;
+#endif /* WL_TIMER */
#ifdef BCMDBUS
bool dhd_remove;
#endif /* BCMDBUS */
#endif /* DHD_FW_COREDUMP */
#if defined(linux) || defined(LINUX)
+int dhd_os_get_img_fwreq(const struct firmware **fw, char *file_path);
+void dhd_os_close_img_fwreq(const struct firmware *fw);
#if defined(DHD_SSSR_DUMP)
void dhd_write_sssr_dump(dhd_pub_t *dhdp, uint32 dump_mode);
#endif /* DHD_SSSR_DUMP */
#ifdef DBG_PKT_MON
/* Enable DHD PKT MON spin lock/unlock */
-#define DHD_PKT_MON_LOCK(lock, flags) (flags) = osl_spin_lock(lock)
-#define DHD_PKT_MON_UNLOCK(lock, flags) osl_spin_unlock(lock, (flags))
+#define DHD_PKT_MON_LOCK(lock, flags) (flags) = osl_mutex_lock(lock)
+#define DHD_PKT_MON_UNLOCK(lock, flags) osl_mutex_unlock(lock, (flags))
#endif /* DBG_PKT_MON */
#ifdef DHD_PKT_LOGGING
#error "DHD_DEBUGABILITY_LOG_DUMP_RING without DEBUGABILITY"
#endif /* DEBUGABILITY */
#endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
+
+#if defined(__linux__)
+#ifdef DHD_SUPPORT_VFS_CALL
+static INLINE struct file *dhd_filp_open(const char *filename, int flags, int mode)
+{
+ return filp_open(filename, flags, mode);
+}
+
+static INLINE int dhd_filp_close(void *image, void *id)
+{
+ return filp_close((struct file *)image, id);
+}
+
+static INLINE int dhd_i_size_read(const struct inode *inode)
+{
+ return i_size_read(inode);
+}
+
+static INLINE int dhd_kernel_read_compat(struct file *fp, loff_t pos, void *buf, size_t count)
+{
+ return kernel_read_compat(fp, pos, buf, count);
+}
+
+static INLINE int dhd_vfs_read(struct file *filep, char *buf, size_t size, loff_t *pos)
+{
+ return vfs_read(filep, buf, size, pos);
+}
+
+static INLINE int dhd_vfs_write(struct file *filep, char *buf, size_t size, loff_t *pos)
+{
+ return vfs_write(filep, buf, size, pos);
+}
+
+static INLINE int dhd_vfs_fsync(struct file *filep, int datasync)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+ return vfs_fsync(filep, datasync);
+#else
+ return vfs_fsync(filep, filep->f_path.dentry, 0);
+#endif
+}
+
+static INLINE int dhd_vfs_stat(char *buf, struct kstat *stat)
+{
+ return vfs_stat(buf, stat);
+}
+
+static INLINE int dhd_kern_path(char *name, int flags, struct path *file_path)
+{
+ return kern_path(name, flags, file_path);
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
+#define DHD_VFS_INODE(dir) (dir->d_inode)
+#else
+#define DHD_VFS_INODE(dir) d_inode(dir)
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
+#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b)
+#else
+#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b, c)
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
+
+#else
+#define DHD_VFS_UNLINK(dir, b, c) 0
+
+static INLINE struct file *dhd_filp_open(const char *filename, int flags, int mode)
+ { return NULL; }
+static INLINE int dhd_filp_close(void *image, void *id)
+ { return 0; }
+static INLINE int dhd_i_size_read(const struct inode *inode)
+ { return 0; }
+static INLINE int dhd_kernel_read_compat(struct file *fp, loff_t pos, void *buf, size_t count)
+ { return 0; }
+static INLINE int dhd_vfs_read(struct file *filep, char *buf, size_t size, loff_t *pos)
+ { return 0; }
+static INLINE int dhd_vfs_write(struct file *filep, char *buf, size_t size, loff_t *pos)
+ { return 0; }
+static INLINE int dhd_vfs_fsync(struct file *filep, int datasync)
+ { return 0; }
+static INLINE int dhd_vfs_stat(char *buf, struct kstat *stat)
+ { return 0; }
+static INLINE int dhd_kern_path(char *name, int flags, struct path *file_path)
+ { return 0; }
+#endif /* DHD_SUPPORT_VFS_CALL */
+#endif /* __linux__ */
+
#ifdef WL_MONITOR
void dhd_set_monitor(dhd_pub_t *pub, int ifidx, int val);
#endif /* WL_MONITOR */
extern int dbus_up(struct dhd_bus *pub);
extern int dbus_stop(struct dhd_bus *pub);
-extern int dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len);
-extern int dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len);
/*
* Exported from dhd bus module (dhd_usb, dhd_sdio)
*/
extern void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp);
extern void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable);
extern int dhd_bus_get_oob_irq_num(dhd_pub_t *dhdp);
+extern struct device * dhd_bus_to_dev(struct dhd_bus *bus);
extern void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub);
extern void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub);
extern bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub);
static INLINE void dhd_bus_aer_config(struct dhd_bus *bus) { }
#endif /* LINUX || linux */
-extern struct device * dhd_bus_to_dev(struct dhd_bus *bus);
-
extern int dhdpcie_cto_init(struct dhd_bus *bus, bool enable);
extern int dhdpcie_cto_cfg_init(struct dhd_bus *bus, bool enable);
static INLINE void dhd_bus_set_linkdown(dhd_pub_t *dhdp, bool val) { }
static INLINE int dhd_bus_get_linkdown(dhd_pub_t *dhdp) { return 0; }
static INLINE int dhd_bus_get_cto(dhd_pub_t *dhdp) { return 0; }
-extern INLINE int dhd_bus_checkdied(struct dhd_bus *bus, char *data, uint size) { return 0; }
+static INLINE int dhd_bus_checkdied(struct dhd_bus *bus, char *data, uint size) { return 0; }
#endif /* BCMPCIE */
#if defined(BCMPCIE) && defined(EWP_ETD_PRSRV_LOGS)
#define CCODE_4359C0
#endif
#if defined(BCMPCIE)
-#define CCODE_4375B4
+//#define CCODE_4375B4
#endif
#ifdef BCMDBUS
#define CCODE_4358U
{BCM4354_CHIP_ID, 2, ccode_4356a2, "XZ/11"},
{BCM4356_CHIP_ID, 2, ccode_4356a2, "XZ/11"},
{BCM4359_CHIP_ID, 9, ccode_4359c0, "XZ/11"},
- {BCM4375_CHIP_ID, 5, ccode_4375b4, "XZ/11"},
+ {BCM4375_CHIP_ID, 5, ccode_4375b4, ""},
#endif
#ifdef BCMDBUS
{BCM43569_CHIP_ID, 2, ccode_4358u, "XW/0"},
}
}
- if (bcmerror && ccode_ww && strlen(ccode_ww)>=4) {
- memcpy(cspec->ccode, ccode_ww, 2);
- cspec->rev = (int)simple_strtol(ccode_ww+3, NULL, 0);
+ if (dhd->op_mode != DHD_FLAG_MFG_MODE) {
+ if (bcmerror && ccode_ww && strlen(ccode_ww)>=4) {
+ memcpy(cspec->ccode, ccode_ww, 2);
+ cspec->rev = (int)simple_strtol(ccode_ww+3, NULL, 0);
+ }
}
return bcmerror;
uint16 reqid;
uint8 pending;
uint32 lastcmd;
-#ifdef BCMDBUS
- uint ctl_completed;
-#endif /* BCMDBUS */
uint8 bus_header[BUS_HEADER_LEN];
cdc_ioctl_t msg;
unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
static int
dhdcdc_msg(dhd_pub_t *dhd)
{
-#ifdef BCMDBUS
- int timeout = 0;
-#endif /* BCMDBUS */
int err = 0;
dhd_prot_t *prot = dhd->prot;
int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
len = CDC_MAX_MSG_SIZE;
/* Send request */
-#ifdef BCMDBUS
- prot->ctl_completed = FALSE;
- err = dbus_send_ctl(dhd->bus, (void *)&prot->msg, len);
- if (err) {
- DHD_ERROR(("dbus_send_ctl error=0x%x\n", err));
- DHD_OS_WAKE_UNLOCK(dhd);
- return err;
- }
-#else
err = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
-#endif /* BCMDBUS */
-#ifdef BCMDBUS
- timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed);
- if ((!timeout) || (!prot->ctl_completed)) {
- DHD_ERROR(("Txctl timeout %d ctl_completed %d\n",
- timeout, prot->ctl_completed));
- DHD_ERROR(("Txctl wait timed out\n"));
- err = -1;
- }
-#endif /* BCMDBUS */
-#if defined(BCMDBUS) && defined(INTR_EP_ENABLE)
- /* If the ctl write is successfully completed, wait for an acknowledgement
- * that indicates that it is now ok to do ctl read from the dongle
- */
- if (err != -1) {
- prot->ctl_completed = FALSE;
- if (dbus_poll_intr(dhd->dbus)) {
- DHD_ERROR(("dbus_poll_intr not submitted\n"));
- } else {
- /* interrupt polling is sucessfully submitted. Wait for dongle to send
- * interrupt
- */
- timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed);
- if (!timeout) {
- DHD_ERROR(("intr poll wait timed out\n"));
- }
- }
- }
-#endif /* defined(BCMDBUS) && defined(INTR_EP_ENABLE) */
DHD_OS_WAKE_UNLOCK(dhd);
return err;
}
static int
dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
{
-#ifdef BCMDBUS
- int timeout = 0;
-#endif /* BCMDBUS */
int ret;
int cdc_len = len + sizeof(cdc_ioctl_t);
dhd_prot_t *prot = dhd->prot;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
do {
-#ifdef BCMDBUS
- prot->ctl_completed = FALSE;
- ret = dbus_recv_ctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
- if (ret) {
- DHD_ERROR(("dbus_recv_ctl error=0x%x(%d)\n", ret, ret));
- goto done;
- }
- timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed);
- if ((!timeout) || (!prot->ctl_completed)) {
- DHD_ERROR(("Rxctl timeout %d ctl_completed %d\n",
- timeout, prot->ctl_completed));
- ret = -ETIMEDOUT;
- goto done;
- }
-
- /* XXX FIX: Must return cdc_len, not len, because after query_ioctl()
- * it subtracts sizeof(cdc_ioctl_t); The other approach is
- * to have dbus_recv_ctl() return actual len.
- */
- ret = cdc_len;
-#else
ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
-#endif /* BCMDBUS */
if (ret < 0)
break;
} while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id);
ret = len;
}
-#ifdef BCMDBUS
-done:
-#endif /* BCMDBUS */
return ret;
}
return ret;
}
-#ifdef BCMDBUS
-int
-dhd_prot_ctl_complete(dhd_pub_t *dhd)
-{
- dhd_prot_t *prot;
-
- if (dhd == NULL)
- return BCME_ERROR;
-
- prot = dhd->prot;
-
- ASSERT(prot);
- prot->ctl_completed = TRUE;
- dhd_os_ioctl_resp_wake(dhd);
- return 0;
-}
-#endif /* BCMDBUS */
-
/* XXX: due to overlays this should not be called directly; call dhd_wl_ioctl() instead */
int
dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
return 0;
}
+#ifdef DHD_LOSSLESS_ROAMING
+int dhd_update_sdio_data_prio_map(dhd_pub_t *dhdp)
+{
+ const uint8 prio2tid[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+ bcopy(prio2tid, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO);
+
+ return BCME_OK;
+}
+#endif // DHD_LOSSLESS_ROAMING
+
int
dhd_prot_attach(dhd_pub_t *dhd)
{
event_name, reason, bcn_mute_miti_evnt_data->uatbtt_count));
}
break;
-
- case WLC_E_TWT_SETUP:
- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
- break;
- case WLC_E_TWT_TEARDOWN:
- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
- break;
- case WLC_E_TWT_INFO_FRM:
- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+#ifdef WL_TWT
+ case WLC_E_TWT:
+ DHD_EVENT(("MACEVENT: %s, type:%d\n", event_name, reason));
break;
+#endif /* WL_TWT */
default:
DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
event_name, event_type, eabuf, (int)status, (int)reason,
}
#endif /* BCM_ROUTER_DHD */
+#ifdef DHD_LINUX_STD_FW_API
+int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t component,
+ char ** buffer, int *length)
+{
+ int ret = BCME_ERROR;
+ const struct firmware *fw = NULL;
+#ifdef SUPPORT_OTA_UPDATE
+ uint8 *buf = NULL;
+ int len = 0;
+ ota_update_info_t *ota_info = &dhd->ota_update_info;
+#endif /* SUPPORT_OTA_UPDATE */
+
+#ifdef SUPPORT_OTA_UPDATE
+ if (component == CLM_BLOB) {
+ if (ota_info->clm_len) {
+ DHD_ERROR(("Using OTA CLM_BLOB\n"));
+ buf = ota_info->clm_buf;
+ len = ota_info->clm_len;
+ }
+ }
+ else if (component == NVRAM) {
+ if (ota_info->nvram_len) {
+ DHD_ERROR(("Using OTA NVRAM.\n"));
+ buf = ota_info->nvram_buf;
+ len = ota_info->nvram_len;
+ }
+ }
+#endif /* SUPPORT_OTA_UPDATE */
+
+#ifdef SUPPORT_OTA_UPDATE
+ if (len) {
+ *buffer = (char *)buf;
+ *length = len;
+ }
+ else
+#endif /* SUPPORT_OTA_UPDATE */
+ {
+ if (file_path) {
+ ret = dhd_os_get_img_fwreq(&fw, file_path);
+ if (ret < 0) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ ret));
+ goto err;
+ } else {
+ if ((fw->size <= 0 || fw->size > *length)) {
+ DHD_ERROR(("fw->size = %zu, *length = %d\n", fw->size, *length));
+ *length = fw->size;
+ goto err;
+ }
+ *buffer = VMALLOCZ(dhd->osh, fw->size);
+ if (*buffer == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
+ __FUNCTION__, (int)fw->size));
+ ret = BCME_NOMEM;
+ goto err;
+ }
+ *length = fw->size;
+ ret = memcpy_s(*buffer, fw->size, fw->data, fw->size);
+ if (ret != BCME_OK) {
+ DHD_ERROR(("%s: memcpy_s failed, err : %d\n",
+ __FUNCTION__, ret));
+ goto err;
+ }
+ ret = BCME_OK;
+ }
+ }
+ }
+err:
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+ return ret;
+}
+
+#else
+
/* Given filename and download type, returns a buffer pointer and length
* for download to f/w. Type can be FW or NVRAM.
*
return ret;
}
+#endif /* DHD_LINUX_STD_FW_API */
int
dhd_download_2_dongle(dhd_pub_t *dhd, char *iovar, uint16 flag, uint16 dload_type,
{
int chunk_len;
-#if !defined(LINUX) && !defined(linux)
+#if (!defined(LINUX) && !defined(linux)) || defined(DHD_LINUX_STD_FW_API)
int cumulative_len = 0;
-#endif /* !LINUX && !linux */
+#endif /* !LINUX && !linux || DHD_LINUX_STD_FW_API */
int size2alloc;
unsigned char *new_buf;
int err = 0, data_offset;
if ((new_buf = (unsigned char *)MALLOCZ(dhd->osh, size2alloc)) != NULL) {
do {
-#if !defined(LINUX) && !defined(linux)
+#if (!defined(LINUX) && !defined(linux)) || defined(DHD_LINUX_STD_FW_API)
if (len >= MAX_CHUNK_LEN)
chunk_len = MAX_CHUNK_LEN;
else
err = BCME_ERROR;
goto exit;
}
-#endif /* !LINUX && !linux */
+#endif /* !LINUX && !linux || DHD_LINUX_STD_FW_API */
if (len - chunk_len == 0)
dl_flag |= DL_END;
len = len - chunk_len;
} while ((len > 0) && (err == 0));
-#if !defined(LINUX) && !defined(linux)
+#if (!defined(LINUX) && !defined(linux)) || defined(DHD_LINUX_STD_FW_API)
MFREE(dhd->osh, new_buf, size2alloc);
#endif /* !LINUX && !linux */
} else {
err = BCME_NOMEM;
}
-#if defined(LINUX) || defined(linux)
+#if (defined(LINUX) || defined(linux)) && !defined(DHD_LINUX_STD_FW_API)
exit:
if (new_buf) {
MFREE(dhd->osh, new_buf, size2alloc);
dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path)
{
char *clm_blob_path;
- int len;
+ int len = 0, memblock_len = 0;
char *memblock = NULL;
int err = BCME_OK;
char iovbuf[WLC_IOCTL_SMLEN];
clm_blob_path = clm_path;
DHD_TRACE(("clm path from module param:%s\n", clm_path));
} else {
+#ifdef DHD_LINUX_STD_FW_API
+ clm_blob_path = DHD_CLM_NAME;
+#else
clm_blob_path = VENDOR_PATH CONFIG_BCMDHD_CLM_PATH;
+#endif /* DHD_LINUX_STD_FW_API */
}
/* If CLM blob file is found on the filesystem, download the file.
* validate the country code before proceeding with the initialization.
* If country code is not valid, fail the initialization.
*/
-#if !defined(LINUX) && !defined(linux)
+#if (!defined(LINUX) && !defined(linux)) || defined(DHD_LINUX_STD_FW_API)
len = MAX_CLM_BUF_SIZE;
dhd_get_download_buffer(dhd, clm_blob_path, CLM_BLOB, &memblock, &len);
+#ifdef DHD_LINUX_STD_FW_API
+ memblock_len = len;
+#else
+ memblock_len = MAX_CLM_BUF_SIZE;
+#endif /* DHD_LINUX_STD_FW_API */
#else
memblock = dhd_os_open_image1(dhd, (char *)clm_blob_path);
+ len = dhd_os_get_image_size(memblock);
+ BCM_REFERENCE(memblock_len);
+#endif /* !LINUX && !linux || DHD_LINUX_STD_FW_API */
+
+#if defined(LINUX) || defined(linux)
if (memblock == NULL) {
printf("%s: Ignore clm file %s\n", __FUNCTION__, clm_path);
#if defined(DHD_BLOB_EXISTENCE_CHECK)
#endif /* DHD_BLOB_EXISTENCE_CHECK */
goto exit;
}
-
- len = dhd_os_get_image_size(memblock);
#endif /* !LINUX && !linux */
if ((len > 0) && (len < MAX_CLM_BUF_SIZE) && memblock) {
exit:
if (memblock) {
-#if defined(LINUX) || defined(linux)
+#if (defined(LINUX) || defined(linux)) && !defined(DHD_LINUX_STD_FW_API)
dhd_os_close_image1(dhd, memblock);
#else
- dhd_free_download_buffer(dhd, memblock, MAX_CLM_BUF_SIZE);
+ dhd_free_download_buffer(dhd, memblock, memblock_len);
#endif /* LINUX || linux */
}
#ifdef CACHE_FW_IMAGES
return;
#endif
+#if defined(DHD_LINUX_STD_FW_API)
+ VMFREE(dhd->osh, buffer, length);
+#else
MFREE(dhd->osh, buffer, length);
+#endif /* DHD_LINUX_STD_FW_API */
}
#ifdef REPORT_FATAL_TIMEOUTS
int32 i = 0;
uint8 *pfw_id = NULL;
uint32 fwid = 0;
+#ifdef DHD_LINUX_STD_FW_API
+ int err = 0;
+ const struct firmware *fw = NULL;
+#else
void *file = NULL;
int file_len = 0;
+#endif /* DHD_LINUX_STD_FW_API */
char fwid_str[FWID_STR_LEN];
uint32 hdr_logstrs_size = 0;
* both logstrs.bin and fw bin
*/
+#ifdef DHD_LINUX_STD_FW_API
+ err = dhd_os_get_img_fwreq(&fw, st_str_file_path);
+ if (err < 0) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ err));
+ goto error;
+ }
+ memset(fwid_str, 0, sizeof(fwid_str));
+ err = memcpy_s(fwid_str, (sizeof(fwid_str) - 1),
+ &(fw->data[fw->size - (sizeof(fwid_str) - 1)]),
+ (sizeof(fwid_str) - 1));
+ if (err) {
+ DHD_ERROR(("%s: failed to copy raw_fmts, err=%d\n",
+ __FUNCTION__, err));
+ goto error;
+ }
+#else
/* read the FWID from fw bin */
file = dhd_os_open_image1(NULL, st_str_file_path);
if (!file) {
DHD_ERROR(("%s: read fw file failed !\n", __FUNCTION__));
goto error;
}
+#endif /* DHD_LINUX_STD_FW_API */
pfw_id = (uint8 *)bcmstrnstr(fwid_str, sizeof(fwid_str) - 1,
FWID_STR_1, strlen(FWID_STR_1));
if (!pfw_id) {
hdr_logstrs_size = hdr->logstrs_size;
error:
+#ifdef DHD_LINUX_STD_FW_API
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+#else
if (file) {
dhd_os_close_image1(NULL, file);
}
+#endif /* DHD_LINUX_STD_FW_API */
if (match_fail) {
return BCME_DECERR;
}
return BCME_OK;
} /* dhd_parse_logstrs_file */
+#ifdef DHD_LINUX_STD_FW_API
+int dhd_parse_map_file(osl_t *osh, void *ptr, uint32 *ramstart, uint32 *rodata_start,
+ uint32 *rodata_end)
+{
+ char *raw_fmts = NULL, *raw_fmts_loc = NULL;
+ uint32 read_size = READ_NUM_BYTES, offset = 0;
+ int error = 0;
+ char * cptr = NULL;
+ char c;
+ uint8 count = 0;
+ uint32 size = 0;
+
+ *ramstart = 0;
+ *rodata_start = 0;
+ *rodata_end = 0;
+ size = (uint32)(((struct firmware *)ptr)->size);
+
+ /* Allocate 1 byte more than read_size to terminate it with NULL */
+ raw_fmts = MALLOCZ(osh, read_size + 1);
+ if (raw_fmts == NULL) {
+ DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__));
+ goto fail;
+ }
+
+ /* read ram start, rodata_start and rodata_end values from map file */
+ while (count != ALL_MAP_VAL)
+ {
+ /* Bound check for size before doing memcpy() */
+ if ((offset + read_size) > size) {
+ read_size = size - offset;
+ }
+
+ error = memcpy_s(raw_fmts, read_size,
+ (((char *)((struct firmware *)ptr)->data) + offset), read_size);
+ if (error) {
+ DHD_ERROR(("%s: failed to copy raw_fmts, err=%d\n",
+ __FUNCTION__, error));
+ goto fail;
+ }
+ /* End raw_fmts with NULL as strstr expects NULL terminated strings */
+ raw_fmts[read_size] = '\0';
+
+ /* Get ramstart address */
+ raw_fmts_loc = raw_fmts;
+ if (!(count & RAMSTART_BIT) &&
+ (cptr = bcmstrnstr(raw_fmts_loc, read_size, ramstart_str,
+ strlen(ramstart_str)))) {
+ cptr = cptr - BYTES_AHEAD_NUM;
+ sscanf(cptr, "%x %c text_start", ramstart, &c);
+ count |= RAMSTART_BIT;
+ }
+
+ /* Get ram rodata start address */
+ raw_fmts_loc = raw_fmts;
+ if (!(count & RDSTART_BIT) &&
+ (cptr = bcmstrnstr(raw_fmts_loc, read_size, rodata_start_str,
+ strlen(rodata_start_str)))) {
+ cptr = cptr - BYTES_AHEAD_NUM;
+ sscanf(cptr, "%x %c rodata_start", rodata_start, &c);
+ count |= RDSTART_BIT;
+ }
+
+ /* Get ram rodata end address */
+ raw_fmts_loc = raw_fmts;
+ if (!(count & RDEND_BIT) &&
+ (cptr = bcmstrnstr(raw_fmts_loc, read_size, rodata_end_str,
+ strlen(rodata_end_str)))) {
+ cptr = cptr - BYTES_AHEAD_NUM;
+ sscanf(cptr, "%x %c rodata_end", rodata_end, &c);
+ count |= RDEND_BIT;
+ }
+
+ if ((offset + read_size) >= size) {
+ break;
+ }
+
+ memset(raw_fmts, 0, read_size);
+ offset += (read_size - GO_BACK_FILE_POS_NUM_BYTES);
+ }
+
+fail:
+ if (raw_fmts) {
+ MFREE(osh, raw_fmts, read_size + 1);
+ raw_fmts = NULL;
+ }
+ if (count == ALL_MAP_VAL) {
+ return BCME_OK;
+ }
+ else {
+ DHD_ERROR(("%s: readmap error 0X%x \n", __FUNCTION__,
+ count));
+ return BCME_ERROR;
+ }
+} /* dhd_parse_map_file */
+#else
int dhd_parse_map_file(osl_t *osh, void *file, uint32 *ramstart, uint32 *rodata_start,
uint32 *rodata_end)
{
}
} /* dhd_parse_map_file */
+#endif /* DHD_LINUX_STD_FW_API */
#ifdef PCIE_FULL_DONGLE
int
#define MAXSZ_BUF 4096
#define MAXSZ_CONFIG 8192
+extern uint wl_reassoc_support;
+#ifdef BTC_WAR
+extern int btc_war;
+#endif /* BTC_WAR */
#if defined(BCMSDIO) && defined(DYNAMIC_MAX_HDR_READ)
extern uint firstread;
#endif
{BCM4375_CHIP_ID, 5, DONT_CARE, "bcm4375b4_pcie_ag", "ap6275hh3"},
#endif
#ifdef BCMDBUS
- {BCM43143_CHIP_ID, 2, DONT_CARE, "bcm43143b0", ""},
- {BCM43242_CHIP_ID, 1, DONT_CARE, "bcm43242a1_ag", ""},
- {BCM43569_CHIP_ID, 2, DONT_CARE, "bcm4358u_ag", "ap62x8"},
+ {BCM43143_CHIP_ID, 2, DONT_CARE, "bcm43143b0", ""},
+ {BCM43242_CHIP_ID, 1, DONT_CARE, "bcm43242a1_ag", ""},
+ {BCM43569_CHIP_ID, 2, DONT_CARE, "bcm4358u_ag", "ap62x8"},
#endif
};
extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx);
#endif
+#ifdef WL_CFG80211
+bool
+dhd_conf_legacy_chip_check(dhd_pub_t *dhd)
+{
+ uint chip = dhd->conf->chip;
+
+ if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
+ chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
+ chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
+ chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
+ chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
+ chip == BCM4371_CHIP_ID ||
+ chip == BCM43430_CHIP_ID ||
+ chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
+ chip == BCM4359_CHIP_ID ||
+ chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
+ chip == BCM43569_CHIP_ID) {
+ return true;
+ }
+
+ return false;
+}
+
+bool
+dhd_conf_new_chip_check(dhd_pub_t *dhd)
+{
+ uint chip = dhd->conf->chip;
+
+ if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
+ chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
+ chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
+ chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
+ chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
+ chip == BCM4371_CHIP_ID ||
+ chip == BCM43430_CHIP_ID ||
+ chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
+ chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
+ chip == BCM43569_CHIP_ID) {
+ return false;
+ }
+
+ return true;
+}
+
+bool
+dhd_conf_extsae_chip(dhd_pub_t *dhd)
+{
+ uint chip = dhd->conf->chip;
+
+ if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
+ chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
+ chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
+ chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
+ chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
+ chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
+ chip == BCM43569_CHIP_ID) {
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+#ifdef BCMSDIO
+bool
+dhd_conf_disable_slpauto(dhd_pub_t *dhd)
+{
+ uint chip = dhd->conf->chip;
+
+ if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
+ chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
+ chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
+ chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
+ chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
+ chip == BCM4371_CHIP_ID ||
+ chip == BCM43430_CHIP_ID ||
+ chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
+ chip == BCM4359_CHIP_ID) {
+ return false;
+ }
+
+ return true;
+}
+#endif
+
void
dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)
{
chiprev = dhd->conf->chiprev;
for (i=0; i<sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {
- const chip_name_map_t* row = &chip_name_map[i];
+ const chip_name_map_t *row = &chip_name_map[i];
if (row->chip == chip && row->chiprev == chiprev &&
(row->ag_type == ag_type ||
ag_type == DONT_CARE || row->ag_type == DONT_CARE)) {
#ifdef BCMSDIO
for (i=0; i<sizeof(module_name_map)/sizeof(module_name_map[0]); i++) {
- const module_name_map_t* row = &module_name_map[i];
+ const module_name_map_t *row = &module_name_map[i];
if (row->devid == devid && row->chip == chip && row->chiprev == chiprev &&
!strcmp(row->module_name, dhd->conf->module_name)) {
return row;
#ifdef BCMPCIE
for (i=0; i<sizeof(module_name_map)/sizeof(module_name_map[0]); i++) {
- const module_name_map_t* row = &module_name_map[i];
+ const module_name_map_t *row = &module_name_map[i];
if (row->devid == devid && row->chip == chip && row->chiprev == chiprev &&
row->svid == svid && row->ssid == ssid) {
return row;
}
#endif
-int
-dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
+char *
+dhd_conf_get_chip_name(dhd_pub_t *dhd, int ag_type, bool *chip_map_v2)
{
#ifdef UPDATE_MODULE_NAME
- const module_name_map_t* row_module = NULL;
+ const module_name_map_t *row_module = NULL;
+#endif
+ const chip_name_map_t *row_chip = NULL;
+ char *name = NULL;
+
+ *chip_map_v2 = FALSE;
+#ifdef UPDATE_MODULE_NAME
+ row_module = dhd_conf_match_module(dhd);
+ if (row_module && strlen(row_module->chip_name)) {
+ name = row_module->chip_name;
+ } else
+#endif
+ {
+ row_chip = dhd_conf_match_chip(dhd, ag_type);
+ if (row_chip && strlen(row_chip->chip_name)) {
+ name = row_chip->chip_name;
+ }
+ }
+
+ return name;
+}
+
+char *
+dhd_conf_get_module_name(dhd_pub_t *dhd, int ag_type)
+{
+#if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME)
+ const module_name_map_t *row_module = NULL;
+#endif
+ const chip_name_map_t *row_chip = NULL;
+ char *name = NULL;
+
+#if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME)
+ row_module = dhd_conf_match_module(dhd);
+ if (row_module && strlen(row_module->module_name)) {
+ name = row_module->module_name;
+ } else
#endif
- const chip_name_map_t* row_chip = NULL;
+ {
+ row_chip = dhd_conf_match_chip(dhd, ag_type);
+ if (row_chip && strlen(row_chip->module_name)) {
+ name = row_chip->module_name;
+ }
+ }
+
+ return name;
+}
+
+int
+dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
+{
int fw_type, ag_type;
- uint chip, chiprev;
- char *name_ptr;
+ char *name_ptr, *chip_name = NULL;
+ bool chip_map_v2;
int i;
- chip = dhd->conf->chip;
- chiprev = dhd->conf->chiprev;
-
if (fw_path[0] == '\0') {
#ifdef CONFIG_BCMDHD_FW_PATH
bcm_strncpy_s(fw_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1);
fw_type = FW_TYPE_EZMESH;
#endif /* WLEASYMESH */
- row_chip = dhd_conf_match_chip(dhd, ag_type);
- if (row_chip && strlen(row_chip->chip_name)) {
- strcpy(name_ptr, "fw_");
- strcat(name_ptr, row_chip->chip_name);
-#ifdef BCMUSBDEV_COMPOSITE
- strcat(name_ptr, "_cusb");
-#endif
- if (fw_type == FW_TYPE_APSTA)
- strcat(name_ptr, "_apsta.bin");
- else if (fw_type == FW_TYPE_P2P)
- strcat(name_ptr, "_p2p.bin");
- else if (fw_type == FW_TYPE_MESH)
- strcat(name_ptr, "_mesh.bin");
- else if (fw_type == FW_TYPE_EZMESH)
- strcat(name_ptr, "_ezmesh.bin");
- else if (fw_type == FW_TYPE_ES)
- strcat(name_ptr, "_es.bin");
- else if (fw_type == FW_TYPE_MFG)
- strcat(name_ptr, "_mfg.bin");
- else if (fw_type == FW_TYPE_MINIME)
- strcat(name_ptr, "_minime.bin");
- else
- strcat(name_ptr, ".bin");
- }
-
-#ifdef UPDATE_MODULE_NAME
- row_module = dhd_conf_match_module(dhd);
- if (row_module && strlen(row_module->chip_name)) {
+ chip_name = dhd_conf_get_chip_name(dhd, ag_type, &chip_map_v2);
+ if (chip_name) {
strcpy(name_ptr, "fw_");
- strcat(name_ptr, row_module->chip_name);
+ strcat(name_ptr, chip_name);
#ifdef BCMUSBDEV_COMPOSITE
strcat(name_ptr, "_cusb");
#endif
else
strcat(name_ptr, ".bin");
}
-#endif
dhd->conf->fw_type = fw_type;
void
dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path, int ag_type)
{
-#ifdef UPDATE_MODULE_NAME
- const module_name_map_t* row_module = NULL;
-#endif
- const chip_name_map_t* row_chip = NULL;
- uint chip, chiprev;
- char *name_ptr;
+ char *name_ptr, *chip_name = NULL;
+ bool chip_map_v2;
int i;
- chip = dhd->conf->chip;
- chiprev = dhd->conf->chiprev;
-
if (clm_path[0] == '\0') {
CONFIG_MSG("clm path is null\n");
return;
}
name_ptr = &clm_path[i];
- row_chip = dhd_conf_match_chip(dhd, ag_type);
- if (row_chip && strlen(row_chip->chip_name)) {
+ chip_name = dhd_conf_get_chip_name(dhd, ag_type, &chip_map_v2);
+ if (chip_name) {
strcpy(name_ptr, "clm_");
- strcat(name_ptr, row_chip->chip_name);
+ strcat(name_ptr, chip_name);
strcat(name_ptr, ".blob");
}
-#ifdef UPDATE_MODULE_NAME
- row_module = dhd_conf_match_module(dhd);
- if (row_module && strlen(row_module->chip_name)) {
- strcpy(name_ptr, "clm_");
- strcat(name_ptr, row_module->chip_name);
- strcat(name_ptr, ".blob");
- }
-#endif
-
CONFIG_TRACE("clm_path=%s\n", clm_path);
}
void
dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path, int ag_type)
{
-#if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME)
- const module_name_map_t* row_module = NULL;
-#endif
- const chip_name_map_t* row_chip = NULL;
uint chip, chiprev;
- char *name_ptr, nv_name[32];
+ char *name_ptr, *module_name = NULL, nv_name[32];
int i;
chip = dhd->conf->chip;
}
name_ptr = &nv_path[i];
- row_chip = dhd_conf_match_chip(dhd, ag_type);
- if (row_chip && strlen(row_chip->module_name)) {
+ module_name = dhd_conf_get_module_name(dhd, ag_type);
+ if (module_name) {
strcpy(name_ptr, "nvram_");
- strcat(name_ptr, row_chip->module_name);
+ strcat(name_ptr, module_name);
#ifdef BCMUSBDEV_COMPOSITE
strcat(name_ptr, "_cusb");
#endif
if (dhd->conf->chip == BCM4359_CHIP_ID) {
struct file *fp;
// compatible for AP6398S and AP6398SA
- fp = filp_open(nv_path, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(nv_path, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
strcpy(name_ptr, nv_name);
} else {
- filp_close((struct file *)fp, NULL);
+ dhd_filp_close((struct file *)fp, NULL);
}
}
#endif
}
#endif
-#if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME)
- row_module = dhd_conf_match_module(dhd);
- if (row_module && strlen(row_module->module_name)) {
- strcpy(name_ptr, "nvram_");
- strcat(name_ptr, row_module->module_name);
- strcat(name_ptr, ".txt");
- }
-#endif
-
for (i=0; i<dhd->conf->nv_by_chip.count; i++) {
if (chip==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chip &&
chiprev==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chiprev) {
void
dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path)
{
-#ifdef UPDATE_MODULE_NAME
- const module_name_map_t* row_module = NULL;
-#endif
- const chip_name_map_t* row_chip = NULL;
- uint chip, chiprev;
- char *name_ptr;
+ char *name_ptr, *chip_name = NULL;
+ bool chip_map_v2;
int i;
- chip = dhd->conf->chip;
- chiprev = dhd->conf->chiprev;
-
if (conf_path[0] == '\0') {
CONFIG_MSG("config path is null\n");
return;
}
name_ptr = &conf_path[i];
- row_chip = dhd_conf_match_chip(dhd, DONT_CARE);
- if (row_chip && strlen(row_chip->chip_name)) {
- strcpy(name_ptr, "config_");
- strcat(name_ptr, row_chip->chip_name);
- strcat(name_ptr, ".txt");
- }
-
-#ifdef UPDATE_MODULE_NAME
- row_module = dhd_conf_match_module(dhd);
- if (row_module && strlen(row_module->chip_name)) {
+ chip_name = dhd_conf_get_chip_name(dhd, DONT_CARE, &chip_map_v2);
+ if (chip_name) {
strcpy(name_ptr, "config_");
- strcat(name_ptr, row_module->chip_name);
+ strcat(name_ptr, chip_name);
strcat(name_ptr, ".txt");
}
-#endif
CONFIG_TRACE("config_path=%s\n", conf_path);
}
if (conf->tput_patch) {
conf->mtu = 1500;
- conf->pktsetsum = TRUE;
+/* set pktsetsum false by default since this will cause to
+ * the checksum is wrong of downloaded file
+*/
+ conf->pktsetsum = FALSE;
#ifdef BCMSDIO
conf->dhd_dpc_prio = 98;
/* need to check if CPU can support multi-core first,
}
#endif /* DHD_TPUT_PATCH */
+#ifdef DHD_LINUX_STD_FW_API
+#define FIRMWARE_CLASS_PATH "/sys/module/firmware_class/parameters/path"
+static void
+dhd_conf_get_filename(char *pFilename)
+{
+ const char *pName = NULL;
+
+ if ((pFilename) && (*pFilename)) {
+ // back/reverse search the '/'
+ pName = strrchr(pFilename, '/');
+ if (NULL == pName) {
+ pName = pFilename;
+ } else {
+ if (pName[1]) {
+ pName++;
+ } else {
+ pName = NULL;
+ }
+ }
+ }
+
+ if (pName)
+ strcpy(pFilename, pName);
+
+ return;
+}
+
+static void
+dhd_conf_add_filepath(dhd_pub_t *dhd, char *pFilename)
+{
+ char path[WLC_IOCTL_SMLEN];
+ char *name_ptr, *module_name = NULL;
+
+ if (strlen(pFilename)) {
+ name_ptr = path;
+ strcpy(name_ptr, "");
+#ifdef FW_AMPAK_PATH
+ strcat(name_ptr, "/");
+ strcat(name_ptr, FW_AMPAK_PATH);
+#endif
+#ifdef MODULE_PATH
+#if defined(BCMSDIO) && defined(GET_OTP_MODULE_NAME)
+ if (strlen(dhd->conf->module_name))
+ module_name = dhd->conf->module_name;
+ else
+#endif
+ {
+ module_name = dhd_conf_get_module_name(dhd, DONT_CARE);
+ }
+#endif
+ if (module_name) {
+ strcat(name_ptr, "/");
+ strcat(name_ptr, module_name);
+ }
+ strcat(name_ptr, "/");
+ strcat(name_ptr, pFilename);
+ strcpy(pFilename, path);
+ }
+
+ return;
+}
+
+#endif /* DHD_LINUX_STD_FW_API */
+
void
dhd_conf_set_path_params(dhd_pub_t *dhd, char *fw_path, char *nv_path)
{
/* External conf takes precedence if specified */
dhd_conf_preinit(dhd);
+#ifdef DHD_LINUX_STD_FW_API
+ // preprocess the filename to only left 'name'
+ dhd_conf_get_filename(fw_path);
+ dhd_conf_get_filename(nv_path);
+ dhd_conf_get_filename(dhd->clm_path);
+ dhd_conf_get_filename(dhd->conf_path);
+#endif
+
if (dhd->conf_path[0] == '\0') {
dhd_conf_copy_path(dhd, "config.txt", dhd->conf_path, nv_path);
}
dhd_conf_set_conf_name_by_chip(dhd, dhd->conf_path);
#endif
- dhd_conf_read_config(dhd, dhd->conf_path);
-#ifdef DHD_TPUT_PATCH
- dhd_conf_dump_tput_patch(dhd);
-#endif
-
ag_type = dhd_conf_set_fw_name_by_chip(dhd, fw_path);
dhd_conf_set_nv_name_by_chip(dhd, nv_path, ag_type);
dhd_conf_set_clm_name_by_chip(dhd, dhd->clm_path, ag_type);
dhd_conf_set_nv_name_by_mac(dhd, nv_path);
#endif
+#ifdef DHD_LINUX_STD_FW_API
+ // preprocess the filename to only left 'name'
+ dhd_conf_add_filepath(dhd, fw_path);
+ dhd_conf_add_filepath(dhd, nv_path);
+ dhd_conf_add_filepath(dhd, dhd->clm_path);
+ dhd_conf_add_filepath(dhd, dhd->conf_path);
+#endif
+
CONFIG_MSG("Final fw_path=%s\n", fw_path);
CONFIG_MSG("Final nv_path=%s\n", nv_path);
CONFIG_MSG("Final clm_path=%s\n", dhd->clm_path);
CONFIG_MSG("Final conf_path=%s\n", dhd->conf_path);
+
+ dhd_conf_read_config(dhd, dhd->conf_path);
+#ifdef DHD_TPUT_PATCH
+ dhd_conf_dump_tput_patch(dhd);
+#endif
}
int
if (val >= def) {
if (down) {
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, ifidx)) < 0)
CONFIG_ERROR("WLC_DOWN setting failed %d\n", ret);
}
if (cmd == WLC_SET_VAR) {
CONFIG_TRACE("set %s %d\n", name, val);
bcm_mkiovar(name, (char *)&val, sizeof(val), iovbuf, sizeof(iovbuf));
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, ifidx)) < 0)
CONFIG_ERROR("%s setting failed %d\n", name, ret);
} else {
CONFIG_TRACE("set %s %d %d\n", name, cmd, val);
- if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, 0)) < 0)
+ if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, ifidx)) < 0)
CONFIG_ERROR("%s setting failed %d\n", name, ret);
}
}
} else {
CONFIG_ERROR("mkiovar %s failed\n", name);
}
- } else {
- ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, FALSE, 0);
- if (ret < 0)
- CONFIG_ERROR("get iovar %s failed %d\n", name, ret);
+ } else {
+ ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, FALSE, 0);
+ if (ret < 0)
+ CONFIG_ERROR("get iovar %s failed %d\n", name, ret);
+ }
+
+ return ret;
+}
+
+static int
+dhd_conf_get_ioctl_ver(dhd_pub_t *dhd)
+{
+ int ret = 0;
+ s32 val = 0;
+
+ dhd->conf->ioctl_ver = WLC_IOCTL_VERSION;
+ ret = dhd_conf_get_iovar(dhd, 0, WLC_GET_VERSION, "WLC_GET_VERSION",
+ (char *)&val, sizeof(val));
+ if (ret) {
+ return ret;
+ }
+ val = dtoh32(val);
+ if (val != WLC_IOCTL_VERSION && val != 1) {
+ CONFIG_ERROR("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
+ val, WLC_IOCTL_VERSION);
+ return BCME_VERSION;
+ }
+ dhd->conf->ioctl_ver = val;
+ CONFIG_TRACE("ioctl_ver=%d\n", dhd->conf->ioctl_ver);
+
+ return ret;
+}
+
+int
+dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)
+{
+ int bcmerror = -1;
+
+ memset(cspec, 0, sizeof(wl_country_t));
+ bcm_mkiovar("country", NULL, 0, (char*)cspec, sizeof(wl_country_t));
+ if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t),
+ FALSE, 0)) < 0)
+ CONFIG_ERROR("country code getting failed %d\n", bcmerror);
+
+ return bcmerror;
+}
+
+int
+dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)
+{
+ int bcmerror = -1;
+ struct dhd_conf *conf = dhd->conf;
+ country_list_t *country = conf->country_head;
+
+#ifdef CCODE_LIST
+ bcmerror = dhd_ccode_map_country_list(dhd, cspec);
+#endif
+ // **:XZ/11 => return XZ/11 if not found
+ // **:**/0 => return user specified ccode if not found, but set regrev 0
+ while (country != NULL) {
+ if (!strncmp("**", country->cspec.country_abbrev, 2)) {
+ if (!strncmp("**", country->cspec.ccode, 2)) {
+ cspec->rev = 0;
+ bcmerror = 0;
+ break;
+ }
+ memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);
+ cspec->rev = country->cspec.rev;
+ bcmerror = 0;
+ break;
+ } else if (!strncmp(cspec->country_abbrev,
+ country->cspec.country_abbrev, 2)) {
+ memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);
+ cspec->rev = country->cspec.rev;
+ bcmerror = 0;
+ break;
+ }
+ country = country->next;
+ }
+
+ if (!bcmerror)
+ CONFIG_MSG("%s/%d\n", cspec->ccode, cspec->rev);
+
+ return bcmerror;
+}
+
+int
+dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec)
+{
+ int bcmerror = -1;
+
+ memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));
+
+ CONFIG_MSG("set country %s, revision %d\n", cspec->ccode, cspec->rev);
+ bcmerror = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "country", (char *)cspec,
+ sizeof(wl_country_t), FALSE);
+ dhd_conf_get_country(dhd, cspec);
+ CONFIG_MSG("Country code: %s (%s/%d)\n",
+ cspec->country_abbrev, cspec->ccode, cspec->rev);
+
+ return bcmerror;
+}
+
+int
+dhd_conf_fix_country(dhd_pub_t *dhd)
+{
+ int bcmerror = -1;
+ int band;
+ wl_uint32_list_t *list;
+ u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+ wl_country_t cspec;
+
+ if (!(dhd && dhd->conf)) {
+ return bcmerror;
+ }
+
+ memset(valid_chan_list, 0, sizeof(valid_chan_list));
+ list = (wl_uint32_list_t *)(void *) valid_chan_list;
+ list->count = htod32(WL_NUMCHANNELS);
+ if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list,
+ sizeof(valid_chan_list), FALSE, 0)) < 0) {
+ CONFIG_ERROR("get channels failed with %d\n", bcmerror);
+ }
+
+ band = dhd_conf_get_band(dhd);
+
+ if (bcmerror || ((band==WLC_BAND_AUTO || band==WLC_BAND_2G || band==-1) &&
+ dtoh32(list->count)<11)) {
+ CONFIG_ERROR("bcmerror=%d, # of channels %d\n",
+ bcmerror, dtoh32(list->count));
+ dhd_conf_map_country_list(dhd, &dhd->conf->cspec);
+ if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) {
+ strcpy(cspec.country_abbrev, "US");
+ cspec.rev = 0;
+ strcpy(cspec.ccode, "US");
+ dhd_conf_map_country_list(dhd, &cspec);
+ dhd_conf_set_country(dhd, &cspec);
+ }
}
- return ret;
+ return bcmerror;
}
static int
}
#endif
+int
+dhd_conf_country(dhd_pub_t *dhd, char *cmd, char *buf)
+{
+ wl_country_t cspec = {{0}, 0, {0}};
+ wl_country_t cur_cspec = {{0}, 0, {0}};
+ int err = 0;
+
+ if (buf) {
+ dhd_conf_get_country(dhd, &cur_cspec);
+ strlcpy(cspec.country_abbrev, buf, WL_CCODE_LEN + 1);
+ strlcpy(cspec.ccode, buf, WL_CCODE_LEN + 1);
+ dhd_conf_map_country_list(dhd, &cspec);
+ if (!memcmp(&cspec.ccode, &cur_cspec.ccode, WL_CCODE_LEN + 1) &&
+ (cspec.rev == cur_cspec.rev)) {
+ CONFIG_MSG("country code = %s/%d is already configured\n",
+ cspec.ccode, cspec.rev);
+ return 0;
+ }
+ err = dhd_conf_set_country(dhd, &cspec);
+ if (!err) {
+ dhd_conf_fix_country(dhd);
+ }
+ dhd_conf_get_country(dhd, &dhd->dhd_cspec);
+ }
+
+ return err;
+}
+
typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *name, char *buf);
typedef struct iovar_tpl_t {
#ifndef SUPPORT_RANDOM_MAC_SCAN
{WLC_SET_VAR, "scanmac", dhd_conf_scan_mac},
#endif
+ {WLC_SET_VAR, "country", dhd_conf_country},
};
static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,
return band;
}
-int
-dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)
-{
- int bcmerror = -1;
-
- memset(cspec, 0, sizeof(wl_country_t));
- bcm_mkiovar("country", NULL, 0, (char*)cspec, sizeof(wl_country_t));
- if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t),
- FALSE, 0)) < 0)
- CONFIG_ERROR("country code getting failed %d\n", bcmerror);
-
- return bcmerror;
-}
-
-int
-dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)
-{
- int bcmerror = -1;
- struct dhd_conf *conf = dhd->conf;
- country_list_t *country = conf->country_head;
-
-#ifdef CCODE_LIST
- bcmerror = dhd_ccode_map_country_list(dhd, cspec);
-#endif
- // **:XZ/11 => return XZ/11 if not found
- // **:**/0 => return user specified ccode if not found, but set regrev 0
- while (country != NULL) {
- if (!strncmp("**", country->cspec.country_abbrev, 2)) {
- if (!strncmp("**", country->cspec.ccode, 2)) {
- cspec->rev = 0;
- bcmerror = 0;
- break;
- }
- memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);
- cspec->rev = country->cspec.rev;
- bcmerror = 0;
- break;
- } else if (!strncmp(cspec->country_abbrev,
- country->cspec.country_abbrev, 2)) {
- memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);
- cspec->rev = country->cspec.rev;
- bcmerror = 0;
- break;
- }
- country = country->next;
- }
-
- if (!bcmerror)
- CONFIG_MSG("%s/%d\n", cspec->ccode, cspec->rev);
-
- return bcmerror;
-}
-
-int
-dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec)
-{
- int bcmerror = -1;
-
- memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));
-
- CONFIG_MSG("set country %s, revision %d\n", cspec->ccode, cspec->rev);
- bcmerror = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "country", (char *)cspec,
- sizeof(wl_country_t), FALSE);
- dhd_conf_get_country(dhd, cspec);
- CONFIG_MSG("Country code: %s (%s/%d)\n",
- cspec->country_abbrev, cspec->ccode, cspec->rev);
-
- return bcmerror;
-}
-
-int
-dhd_conf_fix_country(dhd_pub_t *dhd)
-{
- int bcmerror = -1;
- int band;
- wl_uint32_list_t *list;
- u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
- wl_country_t cspec;
-
- if (!(dhd && dhd->conf)) {
- return bcmerror;
- }
-
- memset(valid_chan_list, 0, sizeof(valid_chan_list));
- list = (wl_uint32_list_t *)(void *) valid_chan_list;
- list->count = htod32(WL_NUMCHANNELS);
- if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list,
- sizeof(valid_chan_list), FALSE, 0)) < 0) {
- CONFIG_ERROR("get channels failed with %d\n", bcmerror);
- }
-
- band = dhd_conf_get_band(dhd);
-
- if (bcmerror || ((band==WLC_BAND_AUTO || band==WLC_BAND_2G || band==-1) &&
- dtoh32(list->count)<11)) {
- CONFIG_ERROR("bcmerror=%d, # of channels %d\n",
- bcmerror, dtoh32(list->count));
- dhd_conf_map_country_list(dhd, &dhd->conf->cspec);
- if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) {
- strcpy(cspec.country_abbrev, "US");
- cspec.rev = 0;
- strcpy(cspec.ccode, "US");
- dhd_conf_map_country_list(dhd, &cspec);
- dhd_conf_set_country(dhd, &cspec);
- }
- }
-
- return bcmerror;
-}
-
bool
dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel)
{
}
int
-dhd_conf_set_roam(dhd_pub_t *dhd)
+dhd_conf_set_roam(dhd_pub_t *dhd, int ifidx)
{
int bcmerror = -1;
struct dhd_conf *conf = dhd->conf;
uint wnm_bsstrans_resp = 0;
if (dhd->conf->chip == BCM4359_CHIP_ID) {
- dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "wnm_bsstrans_resp",
+ dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "wnm_bsstrans_resp",
(char *)&wnm_bsstrans_resp, sizeof(wnm_bsstrans_resp));
if (wnm_bsstrans_resp == WL_BSSTRANS_POLICY_PRODUCT) {
dhd->wbtext_policy = WL_BSSTRANS_POLICY_ROAM_ALWAYS;
- dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "wnm_bsstrans_resp",
+ dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "wnm_bsstrans_resp",
WL_BSSTRANS_POLICY_ROAM_ALWAYS, 0, FALSE);
}
}
dhd_roam_disable = conf->roam_off;
- dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "roam_off", dhd->conf->roam_off, 0, FALSE);
+ dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "roam_off", dhd->conf->roam_off, 0, FALSE);
if (!conf->roam_off || !conf->roam_off_suspend) {
CONFIG_MSG("set roam_trigger %d\n", conf->roam_trigger[0]);
- dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_TRIGGER, "WLC_SET_ROAM_TRIGGER",
+ dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_ROAM_TRIGGER, "WLC_SET_ROAM_TRIGGER",
(char *)conf->roam_trigger, sizeof(conf->roam_trigger), FALSE);
CONFIG_MSG("set roam_scan_period %d\n", conf->roam_scan_period[0]);
- dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_SCAN_PERIOD, "WLC_SET_ROAM_SCAN_PERIOD",
+ dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_ROAM_SCAN_PERIOD, "WLC_SET_ROAM_SCAN_PERIOD",
(char *)conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE);
CONFIG_MSG("set roam_delta %d\n", conf->roam_delta[0]);
- dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_DELTA, "WLC_SET_ROAM_DELTA",
+ dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_ROAM_DELTA, "WLC_SET_ROAM_DELTA",
(char *)conf->roam_delta, sizeof(conf->roam_delta), FALSE);
- dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "fullroamperiod",
+ dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "fullroamperiod",
dhd->conf->fullroamperiod, 1, FALSE);
}
* Case 3: magic pkt and event wake up
* 1) dhd_master_mode=1
* 2) pkt_filter_delete=100, 102, 103, 104, 105, 106, 107
- * 3) pkt_filter_add=141 0 0 0 0xFFFFFFFFFFFF 0x000000000000
- * 4) magic_pkt_filter_add=141 0 1 12
- * 5) rekey_offload=1
+ * 3) magic_pkt_filter_add=141 0 1 12
+ * 4) rekey_offload=1
*/
for(i=0; i<dhd->conf->pkt_filter_add.count; i++) {
dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[i];
dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period,
char *packet, bool bcast)
{
- wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
+ wl_mkeep_alive_pkt_v1_t *mkeep_alive_pktp;
int ret = 0, len_bytes=0, buf_len=0;
char *buf = NULL, *iovar_buf = NULL;
uint8 *pdata;
CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
goto exit;
}
- mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *)buf;
- mkeep_alive_pktp->version = htod16(WL_MKEEP_ALIVE_VERSION);
+ mkeep_alive_pktp = (wl_mkeep_alive_pkt_v1_t *)buf;
+ mkeep_alive_pktp->version = htod16(WL_MKEEP_ALIVE_VERSION_1);
mkeep_alive_pktp->length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
mkeep_alive_pktp->keep_alive_id = id;
buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
#endif
}
else {
- dhd_conf_get_iovar(dhd, 0, WLC_GET_PM, "WLC_GET_PM", (char *)&pm, sizeof(pm));
+ dhd_conf_get_iovar(dhd, ifidx, WLC_GET_PM, "WLC_GET_PM", (char *)&pm, sizeof(pm));
CONFIG_TRACE("PM in suspend = %d\n", pm);
if (conf->pm >= 0)
pm = conf->pm;
else if (!strncmp("fullroamperiod=", full_param, len_param)) {
conf->fullroamperiod = (int)simple_strtol(data, NULL, 10);
CONFIG_MSG("fullroamperiod = %d\n", conf->fullroamperiod);
- } else
+ }
+ else if (!strncmp("wl_reassoc_support=", full_param, len_param)) {
+ if (!strncmp(data, "0", 1))
+ wl_reassoc_support = FALSE;
+ else
+ wl_reassoc_support = TRUE;
+ CONFIG_MSG("wl_reassoc_support = %d\n", wl_reassoc_support);
+ }
+ else
return false;
return true;
dhd_doflow = TRUE;
CONFIG_MSG("dhd_doflow = %d\n", dhd_doflow);
}
- else if (!strncmp("dhd_slpauto=", full_param, len_param) ||
- !strncmp("kso_enable=", full_param, len_param)) {
+ else if (!strncmp("dhd_slpauto=", full_param, len_param)) {
if (!strncmp(data, "0", 1))
dhd_slpauto = FALSE;
- else
+ else if (dhd_conf_disable_slpauto(dhd))
dhd_slpauto = TRUE;
CONFIG_MSG("dhd_slpauto = %d\n", dhd_slpauto);
}
conf->d2h_intr_control = (int)simple_strtol(data, NULL, 10);
CONFIG_MSG("d2h_intr_control = %d\n", conf->d2h_intr_control);
}
+ else if (!strncmp("enq_hdr_pkt=", full_param, len_param)) {
+ conf->enq_hdr_pkt = (int)simple_strtol(data, NULL, 0);
+ CONFIG_MSG("enq_hdr_pkt = 0x%x\n", conf->enq_hdr_pkt);
+ }
else
return false;
conf->in4way = (int)simple_strtol(data, NULL, 0);
CONFIG_MSG("in4way = 0x%x\n", conf->in4way);
}
+#ifdef BTC_WAR
+ else if (!strncmp("btc_war=", full_param, len_param)) {
+ btc_war = (int)simple_strtol(data, NULL, 0);
+ CONFIG_MSG("btc_war = 0x%x\n", btc_war);
+ }
+#endif /* BTC_WAR */
else if (!strncmp("war=", full_param, len_param)) {
conf->war = (int)simple_strtol(data, NULL, 0);
CONFIG_MSG("war = 0x%x\n", conf->war);
dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
{
int bcmerror = -1, chip_match = -1;
- uint len = 0, start_pos=0, end_pos=0;
- void *image = NULL;
+ uint len = 0, memblock_len = 0, start_pos=0, end_pos=0;
char *memblock = NULL;
char *bufp, *pick = NULL, *pch;
bool conf_file_exists;
uint len_param;
+ len = MAXSZ_CONFIG;
+
conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));
if (!conf_file_exists) {
CONFIG_MSG("config path %s\n", conf_path);
return (0);
}
- if (conf_file_exists) {
- image = dhd_os_open_image1(dhd, conf_path);
- if (image == NULL) {
- CONFIG_MSG("Ignore config file %s\n", conf_path);
- goto err;
- }
- }
+ if (conf_file_exists)
+ bcmerror = dhd_get_download_buffer(dhd, conf_path, NVRAM, &memblock,
+ (int *)&len);
+ else
+ bcmerror = dhd_get_download_buffer(dhd, NULL, NVRAM, &memblock, (int *)&len);
- memblock = MALLOC(dhd->osh, MAXSZ_CONFIG);
- if (memblock == NULL) {
- CONFIG_ERROR("Failed to allocate memory %d bytes\n", MAXSZ_CONFIG);
+ if (bcmerror != BCME_OK) {
+ CONFIG_MSG("Ignore config file %s\n", conf_path);
goto err;
}
+#ifdef DHD_LINUX_STD_FW_API
+ memblock_len = len;
+#else
+ memblock_len = MAXSZ_CONFIG;
+#endif /* DHD_LINUX_STD_FW_API */
+
pick = MALLOC(dhd->osh, MAXSZ_BUF);
if (!pick) {
CONFIG_ERROR("Failed to allocate memory %d bytes\n", MAXSZ_BUF);
}
/* Read variables */
- if (conf_file_exists) {
- len = dhd_os_get_image_block(memblock, MAXSZ_CONFIG, image);
- }
if (len > 0 && len < MAXSZ_CONFIG) {
bufp = (char *)memblock;
bufp[len] = 0;
MFREE(dhd->osh, pick, MAXSZ_BUF);
if (memblock)
- MFREE(dhd->osh, memblock, MAXSZ_CONFIG);
-
- if (image)
- dhd_os_close_image1(dhd, image);
+ dhd_free_download_buffer(dhd, memblock, memblock_len);
return bcmerror;
}
int
dhd_conf_compat_func(dhd_pub_t *dhd)
{
- const module_name_map_t* row = NULL;
+ const module_name_map_t *row = NULL;
row = dhd_conf_match_module(dhd);
if (row && row->compat_func) {
}
#endif
+void
+dhd_conf_preinit_ioctls_sta(dhd_pub_t *dhd, int ifidx)
+{
+ struct dhd_conf *conf = dhd->conf;
+ int pm;
+
+ dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "bcn_timeout", conf->bcn_timeout, 0, FALSE);
+#ifdef NO_POWER_SAVE
+ pm = PM_OFF;
+#else
+ if (conf->pm >= 0)
+ pm = conf->pm;
+ else
+ pm = PM_FAST;
+#endif
+ dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);
+ dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "assoc_retry_max", 10, 0, FALSE);
+ dhd_conf_set_roam(dhd, ifidx);
+}
+
void
dhd_conf_postinit_ioctls(dhd_pub_t *dhd)
{
struct dhd_conf *conf = dhd->conf;
- char wl_preinit[] = "assoc_retry_max=10";
+ char wl_preinit[] = "";
#ifdef NO_POWER_SAVE
char wl_no_power_save[] = "mpc=0, 86=0";
dhd_conf_set_wl_cmd(dhd, wl_no_power_save, FALSE);
#endif
+ dhd_conf_get_ioctl_ver(dhd);
dhd_conf_set_intiovar(dhd, 0, WLC_UP, "WLC_UP", 0, 0, FALSE);
- dhd_conf_map_country_list(dhd, &conf->cspec);
- dhd_conf_set_country(dhd, &conf->cspec);
- dhd_conf_fix_country(dhd);
- dhd_conf_get_country(dhd, &dhd->dhd_cspec);
+ dhd_conf_country(dhd, "country", conf->cspec.country_abbrev);
dhd_conf_set_intiovar(dhd, 0, WLC_SET_BAND, "WLC_SET_BAND", conf->band, 0, FALSE);
- dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "bcn_timeout", conf->bcn_timeout, 0, FALSE);
- dhd_conf_set_intiovar(dhd, 0, WLC_SET_PM, "WLC_SET_PM", conf->pm, 0, FALSE);
dhd_conf_set_intiovar(dhd, 0, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, FALSE);
dhd_conf_set_intiovar(dhd, 0, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE);
dhd_conf_set_bw_cap(dhd);
- dhd_conf_set_roam(dhd);
+ dhd_conf_set_roam(dhd, 0);
#if defined(BCMPCIE)
dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "bus:deepsleep_disable",
dhd_conf_set_intiovar(dhd, 0, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG",
conf->frameburst, 0, FALSE);
+ dhd_conf_preinit_ioctls_sta(dhd, 0);
dhd_conf_set_wl_cmd(dhd, wl_preinit, TRUE);
#if defined(BCMSDIO)
- if (conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID ||
- conf->chip == BCM4375_CHIP_ID) {
+ if (conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID) {
char ampdu_mpdu[] = "ampdu_mpdu=32";
dhd_conf_set_wl_cmd(dhd, ampdu_mpdu, TRUE);
} else {
char txack_alive[] = "txack_alive=0";
dhd_conf_set_wl_cmd(dhd, txack_alive, TRUE);
}
+#ifdef WLDWDS
+ {
+ char dwds[] = "dwds=1";
+ dhd_conf_set_wl_cmd(dhd, dwds, TRUE);
+ }
+#endif /* WLDWDS */
#if defined(WLEASYMESH)
if (conf->fw_type == FW_TYPE_EZMESH) {
if (conf->chip == BCM4359_CHIP_ID) {
}
-int
-dhd_conf_preinit(dhd_pub_t *dhd)
+void
+dhd_conf_free_preinit(dhd_pub_t *dhd)
{
struct dhd_conf *conf = dhd->conf;
- CONFIG_TRACE("Enter\n");
-
#ifdef SET_FWNV_BY_MAC
dhd_conf_free_mac_list(&conf->fw_by_mac);
dhd_conf_free_mac_list(&conf->nv_by_mac);
kfree(conf->vndr_ie_assocreq);
conf->vndr_ie_assocreq = NULL;
}
+}
+
+int
+dhd_conf_preinit(dhd_pub_t *dhd)
+{
+ struct dhd_conf *conf = dhd->conf;
+
+ CONFIG_TRACE("Enter\n");
+
+ dhd_conf_free_preinit(dhd);
conf->band = -1;
memset(&conf->bw_cap, -1, sizeof(conf->bw_cap));
if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {
strcpy(conf->cspec.country_abbrev, "ALL");
strcpy(conf->cspec.ccode, "ALL");
conf->cspec.rev = 0;
- } else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||
+ }
+ else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||
conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||
conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||
conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||
strcpy(conf->cspec.country_abbrev, "CN");
strcpy(conf->cspec.ccode, "CN");
conf->cspec.rev = 38;
- } else {
+ }
+ else {
strcpy(conf->cspec.country_abbrev, "CN");
strcpy(conf->cspec.ccode, "CN");
conf->cspec.rev = 0;
}
memset(&conf->channels, 0, sizeof(wl_channel_list_t));
+ conf->ioctl_ver = WLC_IOCTL_VERSION;
conf->roam_off = 1;
conf->roam_off_suspend = 1;
conf->roam_trigger[0] = -65;
conf->flow_ring_queue_threshold = FLOW_RING_QUEUE_THRESHOLD;
conf->d2h_intr_method = -1;
conf->d2h_intr_control = -1;
+ conf->enq_hdr_pkt = 0;
#endif
conf->dpc_cpucore = -1;
conf->rxf_cpucore = -1;
init_waitqueue_head(&conf->event_complete);
#if defined(BCMSDIO) && defined(CUSTOMER_HW_AMLOGIC)
- if (conf->chip != BCM43752_CHIP_ID) {
- dhd_slpauto = FALSE;
- }
+ dhd_slpauto = dhd_conf_disable_slpauto(dhd);
conf->txglom_mode = SDPCM_TXGLOM_CPY;
conf->rekey_offload = TRUE;
#endif
{
struct dhd_conf *conf = dhd->conf;
-#ifdef SET_FWNV_BY_MAC
- dhd_conf_free_mac_list(&conf->fw_by_mac);
- dhd_conf_free_mac_list(&conf->nv_by_mac);
-#endif
- dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);
- dhd_conf_free_country_list(conf);
- dhd_conf_free_mchan_list(conf);
-#ifdef PKT_FILTER_SUPPORT
- if (conf->magic_pkt_filter_add) {
- kfree(conf->magic_pkt_filter_add);
- conf->magic_pkt_filter_add = NULL;
- }
-#endif
- if (conf->wl_preinit) {
- kfree(conf->wl_preinit);
- conf->wl_preinit = NULL;
- }
- if (conf->wl_suspend) {
- kfree(conf->wl_suspend);
- conf->wl_suspend = NULL;
- }
- if (conf->wl_resume) {
- kfree(conf->wl_resume);
- conf->wl_resume = NULL;
- }
- if (conf->vndr_ie_assocreq) {
- kfree(conf->vndr_ie_assocreq);
- conf->vndr_ie_assocreq = NULL;
- }
+ dhd_conf_free_preinit(dhd);
memset(conf, 0, sizeof(dhd_conf_t));
return 0;
}
CONFIG_TRACE("Enter\n");
if (dhd->conf) {
-#ifdef SET_FWNV_BY_MAC
- dhd_conf_free_mac_list(&conf->fw_by_mac);
- dhd_conf_free_mac_list(&conf->nv_by_mac);
-#endif
- dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);
- dhd_conf_free_country_list(conf);
- dhd_conf_free_mchan_list(conf);
-#ifdef PKT_FILTER_SUPPORT
- if (conf->magic_pkt_filter_add) {
- kfree(conf->magic_pkt_filter_add);
- conf->magic_pkt_filter_add = NULL;
- }
-#endif
- if (conf->wl_preinit) {
- kfree(conf->wl_preinit);
- conf->wl_preinit = NULL;
- }
- if (conf->wl_suspend) {
- kfree(conf->wl_suspend);
- conf->wl_suspend = NULL;
- }
- if (conf->wl_resume) {
- kfree(conf->wl_resume);
- conf->wl_resume = NULL;
- }
- if (conf->vndr_ie_assocreq) {
- kfree(conf->vndr_ie_assocreq);
- conf->vndr_ie_assocreq = NULL;
- }
+ dhd_conf_free_preinit(dhd);
MFREE(dhd->osh, conf, sizeof(dhd_conf_t));
}
dhd->conf = NULL;
#define FW_TYPE_AG 1
#define FW_PATH_AUTO_SELECT 1
+#ifdef BCMDHD_MDRIVER
#define CONFIG_PATH_AUTO_SELECT
+#else
+#define CONFIG_PATH_AUTO_SELECT
+#endif
extern char firmware_path[MOD_PARAM_PATHLEN];
#if defined(BCMSDIO) || defined(BCMPCIE)
extern uint dhd_rxbound;
struct wl_chip_nv_path *m_chip_nv_path_head;
} wl_chip_nv_path_list_ctrl_t;
+#define MAX_CTRL_CHANSPECS 256
typedef struct wl_channel_list {
uint32 count;
- uint32 channel[WL_NUMCHANNELS];
+ uint32 channel[MAX_CTRL_CHANSPECS];
} wl_channel_list_t;
typedef struct wmes_param {
CONN_STATE_4WAY_M2 = 19,
CONN_STATE_4WAY_M3 = 20,
CONN_STATE_4WAY_M4 = 21,
- CONN_STATE_CONNECTED = 22,
- CONN_STATE_GROUPKEY_M1 = 23,
- CONN_STATE_GROUPKEY_M2 = 24,
+ CONN_STATE_ADD_KEY = 22,
+ CONN_STATE_CONNECTED = 23,
+ CONN_STATE_GROUPKEY_M1 = 24,
+ CONN_STATE_GROUPKEY_M2 = 25,
+};
+
+enum enq_pkt_type {
+ ENQ_PKT_TYPE_EAPOL = (1 << (0)),
+ ENQ_PKT_TYPE_ARP = (1 << (1)),
+ ENQ_PKT_TYPE_DHCP = (1 << (2)),
+ ENQ_PKT_TYPE_ICMP = (1 << (3)),
};
typedef struct dhd_conf {
#endif
wl_chip_nv_path_list_ctrl_t nv_by_chip;
country_list_t *country_head;
+ int ioctl_ver;
int band;
int bw_cap[2];
wl_country_t cspec;
int flow_ring_queue_threshold;
int d2h_intr_method;
int d2h_intr_control;
+ int enq_hdr_pkt;
#endif
int dpc_cpucore;
int rxf_cpucore;
int dhd_conf_get_otp(dhd_pub_t *dhd, si_t *sih);
bool dhd_conf_legacy_msi_chip(dhd_pub_t *dhd);
#endif
+#ifdef WL_CFG80211
+bool dhd_conf_legacy_chip_check(dhd_pub_t *dhd);
+bool dhd_conf_new_chip_check(dhd_pub_t *dhd);
+bool dhd_conf_extsae_chip(dhd_pub_t *dhd);
+#endif
void dhd_conf_set_path_params(dhd_pub_t *dhd, char *fw_path, char *nv_path);
int dhd_conf_set_intiovar(dhd_pub_t *dhd, int ifidx, uint cmd, char *name,
int val, int def, bool down);
int dhd_conf_get_band(dhd_pub_t *dhd);
-int dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec);
+int dhd_conf_country(dhd_pub_t *dhd, char *cmd, char *buf);
int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec);
-int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec);
#ifdef CCODE_LIST
int dhd_ccode_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec);
#endif
-int dhd_conf_fix_country(dhd_pub_t *dhd);
bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel);
void dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, int mode);
void dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int go, int source);
uint dhd_conf_get_chip(void *context);
uint dhd_conf_get_chiprev(void *context);
int dhd_conf_get_pm(dhd_pub_t *dhd);
+int dhd_conf_reg2args(dhd_pub_t *dhd, char *cmd, bool set, uint32 index, uint32 *val);
int dhd_conf_check_hostsleep(dhd_pub_t *dhd, int cmd, void *buf, int len,
int *hostsleep_set, int *hostsleep_val, int *ret);
void dhd_conf_get_hostsleep(dhd_pub_t *dhd,
uint dhd_conf_get_insuspend(dhd_pub_t *dhd, uint mask);
int dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend);
void dhd_conf_postinit_ioctls(dhd_pub_t *dhd);
+#ifdef WL_STATIC_IF
+void dhd_conf_preinit_ioctls_sta(dhd_pub_t *dhd, int ifidx);
+#endif /* WL_STATIC_IF */
int dhd_conf_preinit(dhd_pub_t *dhd);
int dhd_conf_reset(dhd_pub_t *dhd);
int dhd_conf_attach(dhd_pub_t *dhd);
return ret;
}
+int BCMFASTPATH
+(dhd_flow_queue_enqueue_head)(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt)
+{
+ int ret = BCME_OK;
+
+ ASSERT(queue != NULL);
+
+ if (dhd_flow_queue_throttle(queue)) {
+ queue->failures++;
+ ret = (*queue->cb)(queue, pkt);
+ goto done;
+ }
+
+ if (queue->head) {
+ FLOW_QUEUE_PKT_SETNEXT(pkt, queue->head);
+ queue->head = pkt;
+
+ } else {
+ queue->head = pkt;
+ FLOW_QUEUE_PKT_SETNEXT(pkt, NULL);
+ queue->tail = pkt; /* at tail */
+ }
+
+ queue->len++;
+ /* increment parent's cummulative length */
+ DHD_CUMM_CTR_INCR(DHD_FLOW_QUEUE_CLEN_PTR(queue));
+ /* increment grandparent's cummulative length */
+ DHD_CUMM_CTR_INCR(DHD_FLOW_QUEUE_L2CLEN_PTR(queue));
+
+done:
+ return ret;
+}
+
/** Dequeue an 802.3 packet from a flow ring's queue, from head (FIFO) */
void *
BCMFASTPATH(dhd_flow_queue_dequeue)(dhd_pub_t *dhdp, flow_queue_t *queue)
extern void dhd_flow_queue_reinit(dhd_pub_t *dhdp, flow_queue_t *queue, int max);
extern void dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb);
extern int dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt);
+extern int dhd_flow_queue_enqueue_head(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt);
extern void * dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue);
extern void dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt);
/* close the file if valid */
if (!(IS_ERR_OR_NULL(dhdp->fwtrace_info->fw_trace_fp))) {
- (void) filp_close(dhdp->fwtrace_info->fw_trace_fp, 0);
+ (void) dhd_filp_close(dhdp->fwtrace_info->fw_trace_fp, 0);
}
mutex_destroy(&dhdp->fwtrace_info->fwtrace_lock);
// Get the file size
// if the size + buf_len > TRACE_FILE_SIZE, then write to a different file.
//
- error = vfs_stat(fwtrace_info->trace_file, &stat);
+ error = dhd_vfs_stat(fwtrace_info->trace_file, &stat);
if (error) {
DHD_ERROR(("vfs_stat has failed with error code = %d\n", error));
goto done;
pos = fwtrace_info->fw_trace_fp->f_pos;
/* Write buf to file */
- ret_val_1 = vfs_write(fwtrace_info->fw_trace_fp,
+ ret_val_1 = dhd_vfs_write(fwtrace_info->fw_trace_fp,
(char *) buf, (uint32) buf_len, &pos);
if (ret_val_1 < 0) {
DHD_ERROR(("write file error, err = %d\n", ret_val_1));
fwtrace_info->fw_trace_fp->f_pos = pos;
/* Sync file from filesystem to physical media */
- ret_val_1 = vfs_fsync(fwtrace_info->fw_trace_fp, 0);
+ ret_val_1 = dhd_vfs_fsync(fwtrace_info->fw_trace_fp, 0);
if (ret_val_1 < 0) {
DHD_ERROR(("sync file error, error = %d\n", ret_val_1));
ret_val = BCME_ERROR;
if (fw_trace_enabled) {
if (!(IS_ERR_OR_NULL(fwtrace_info->fw_trace_fp))) {
- (void) filp_close(fwtrace_info->fw_trace_fp, 0);
+ (void) dhd_filp_close(fwtrace_info->fw_trace_fp, 0);
}
DHD_INFO((" *** Creating the trace file \n"));
ts_str);
fwtrace_info->fw_trace_fp =
- filp_open(fwtrace_info->trace_file, file_mode, 0664);
+ dhd_filp_open(fwtrace_info->trace_file, file_mode, 0664);
- if (IS_ERR(fwtrace_info->fw_trace_fp)) {
+ if (IS_ERR(fwtrace_info->fw_trace_fp) || (fwtrace_info->fw_trace_fp == NULL)) {
DHD_ERROR(("Unable to create the fw trace file file: %s\n",
fwtrace_info->trace_file));
ret_val = BCME_ERROR;
int ret_val = BCME_OK;
if (!(IS_ERR_OR_NULL(dhdp->fwtrace_info->fw_trace_fp))) {
- (void) filp_close(dhdp->fwtrace_info->fw_trace_fp, 0);
+ (void) dhd_filp_close(dhdp->fwtrace_info->fw_trace_fp, 0);
}
dhdp->fwtrace_info->fw_trace_fp = NULL;
extern int dhd_static_buf_init(void);
extern void dhd_static_buf_exit(void);
#endif /* DHD_STATIC_IN_DRIVER */
-#ifdef BCMDHD_MDRIVER
+#if defined(BCMDHD_MDRIVER) && !defined(DHD_STATIC_IN_DRIVER)
extern void *bcmdhd_mem_prealloc(uint bus_type, int index,
int section, unsigned long size);
#else
}
#ifdef CUSTOMER_HW_AMLOGIC
#ifdef BCMSDIO
- extern_wifi_set_enable(0);
- mdelay(200);
+// extern_wifi_set_enable(0);
+// mdelay(200);
extern_wifi_set_enable(1);
mdelay(200);
// sdio_reinit();
return err;
}
-static int dhd_wlan_set_reset(int onoff)
+static int
+dhd_wlan_set_reset(int onoff)
{
return 0;
}
-static int dhd_wlan_set_carddetect(int present)
+static int
+dhd_wlan_set_carddetect(int present)
{
int err = 0;
err = sdhci_force_presence_change(&sdmmc_channel, 0);
#endif /* CUSTOMER_HW_PLATFORM */
#ifdef CUSTOMER_HW_AMLOGIC
- extern_wifi_set_enable(0);
- mdelay(200);
+// extern_wifi_set_enable(0);
+// mdelay(200);
#endif
#elif defined(BCMPCIE)
printf("======== Card detection to remove PCIE card! ========\n");
return err;
}
-static int dhd_wlan_get_mac_addr(unsigned char *buf, int ifidx)
+static int
+dhd_wlan_get_mac_addr(unsigned char *buf, int ifidx)
{
int err = 0;
.get_country_code = dhd_wlan_get_country_code,
};
-int dhd_wlan_init_gpio(wifi_adapter_info_t *adapter)
+static int
+dhd_wlan_init_gpio(wifi_adapter_info_t *adapter)
{
#ifdef BCMDHD_DTS
char wlan_node[32];
#ifdef CUSTOMER_HW_AMLOGIC
#if defined(BCMPCIE)
- printf("======== Card detection to detect PCIE card! ========\n");
+// printf("======== Card detection to detect PCIE card! ========\n");
// pci_remove_reinit(0x14e4, 0x43ec, 1);
#endif
#endif
if (gpio_wl_reg_on >= 0) {
err = gpio_request(gpio_wl_reg_on, "WL_REG_ON");
if (err < 0) {
- printf("%s: gpio_request(%d) for WL_REG_ON failed\n",
- __FUNCTION__, gpio_wl_reg_on);
+ printf("%s: gpio_request(%d) for WL_REG_ON failed %d\n",
+ __FUNCTION__, gpio_wl_reg_on, err);
gpio_wl_reg_on = -1;
}
}
if (gpio_wl_host_wake >= 0) {
err = gpio_request(gpio_wl_host_wake, "bcmdhd");
if (err < 0) {
- printf("%s: gpio_request(%d) for WL_HOST_WAKE failed\n",
- __FUNCTION__, gpio_wl_host_wake);
+ printf("%s: gpio_request(%d) for WL_HOST_WAKE failed %d\n",
+ __FUNCTION__, gpio_wl_host_wake, err);
return -1;
}
adapter->gpio_wl_host_wake = gpio_wl_host_wake;
err = gpio_direction_input(gpio_wl_host_wake);
if (err < 0) {
- printf("%s: gpio_direction_input(%d) for WL_HOST_WAKE failed\n",
- __FUNCTION__, gpio_wl_host_wake);
+ printf("%s: gpio_direction_input(%d) for WL_HOST_WAKE failed %d\n",
+ __FUNCTION__, gpio_wl_host_wake, err);
gpio_free(gpio_wl_host_wake);
return -1;
}
host_oob_irq = gpio_to_irq(gpio_wl_host_wake);
if (host_oob_irq < 0) {
- printf("%s: gpio_to_irq(%d) for WL_HOST_WAKE failed\n",
- __FUNCTION__, gpio_wl_host_wake);
+ printf("%s: gpio_to_irq(%d) for WL_HOST_WAKE failed %d\n",
+ __FUNCTION__, gpio_wl_host_wake, host_oob_irq);
gpio_free(gpio_wl_host_wake);
return -1;
}
return 0;
}
-static void dhd_wlan_deinit_gpio(wifi_adapter_info_t *adapter)
+static void
+dhd_wlan_deinit_gpio(wifi_adapter_info_t *adapter)
{
int gpio_wl_reg_on = adapter->gpio_wl_reg_on;
#ifdef CUSTOMER_OOB
#endif /* CUSTOMER_OOB */
}
-int dhd_wlan_init_plat_data(wifi_adapter_info_t *adapter)
+#if defined(BCMDHD_MDRIVER)
+static void
+dhd_wlan_init_adapter(wifi_adapter_info_t *adapter)
+{
+#ifdef ADAPTER_IDX
+ if (ADAPTER_IDX == 0) {
+ adapter->bus_num = 1;
+ adapter->slot_num = 1;
+ } else if (ADAPTER_IDX == 1) {
+ adapter->bus_num = 2;
+ adapter->slot_num = 1;
+ }
+ adapter->index = ADAPTER_IDX;
+#ifdef BCMSDIO
+ adapter->bus_type = SDIO_BUS;
+#elif defined(BCMPCIE)
+ adapter->bus_type = PCI_BUS;
+#elif defined(BCMDBUS)
+ adapter->bus_type = USB_BUS;
+#endif
+ printf("bus_type=%d, bus_num=%d, slot_num=%d\n",
+ adapter->bus_type, adapter->bus_num, adapter->slot_num);
+#endif /* ADAPTER_IDX */
+
+#ifdef DHD_STATIC_IN_DRIVER
+ adapter->index = 0;
+#elif !defined(ADAPTER_IDX)
+#ifdef BCMSDIO
+ adapter->index = 0;
+#elif defined(BCMPCIE)
+ adapter->index = 1;
+#elif defined(BCMDBUS)
+ adapter->index = 2;
+#endif
+#endif /* DHD_STATIC_IN_DRIVER */
+}
+#endif /* BCMDHD_MDRIVER */
+
+int
+dhd_wlan_init_plat_data(wifi_adapter_info_t *adapter)
{
int err = 0;
- printf("======== %s ========\n", __FUNCTION__);
- if (adapter->index == -1) {
- adapter->index = 0;
- }
+#ifdef BCMDHD_MDRIVER
+ dhd_wlan_init_adapter(adapter);
+#endif /* BCMDHD_MDRIVER */
+
err = dhd_wlan_init_gpio(adapter);
+ if (err)
+ goto exit;
#ifdef DHD_STATIC_IN_DRIVER
- dhd_static_buf_init();
+ err = dhd_static_buf_init();
#endif
+
+exit:
return err;
}
-void dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter)
+void
+dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter)
{
- printf("======== %s ========\n", __FUNCTION__);
#ifdef DHD_STATIC_IN_DRIVER
dhd_static_buf_exit();
#endif
static dhd_if_t * dhd_get_ifp_by_ndev(dhd_pub_t *dhdp, struct net_device *ndev);
#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
-static void dhd_bridge_dev_set(dhd_info_t * dhd, int ifidx, struct net_device * dev);
-#endif /* defiend(WLDWDS) && defined(FOURADDR_AUTO_BRG) */
+static void dhd_bridge_dev_set(dhd_info_t *dhd, int ifidx, struct net_device *sdev);
+#endif /* WLDWDS && FOURADDR_AUTO_BRG */
#if (defined(DHD_WET) || defined(DHD_MCAST_REGEN) || defined(DHD_L2_FILTER))
/* update rx_pkt_chainable state of dhd interface */
#endif /* FORCE_TPOWERON */
#ifdef SHOW_LOGTRACE
-#if defined(CUSTOMER_HW4_DEBUG)
-#define WIFI_PATH "/etc/wifi/"
-static char *logstrs_path = VENDOR_PATH WIFI_PATH"logstrs.bin";
-char *st_str_file_path = VENDOR_PATH WIFI_PATH"rtecdc.bin";
-static char *map_file_path = VENDOR_PATH WIFI_PATH"rtecdc.map";
-static char *rom_st_str_file_path = VENDOR_PATH WIFI_PATH"roml.bin";
-static char *rom_map_file_path = VENDOR_PATH WIFI_PATH"roml.map";
+#ifdef DHD_LINUX_STD_FW_API
+static char *logstrs_path = "logstrs.bin";
+char *st_str_file_path = "rtecdc.bin";
+static char *map_file_path = "rtecdc.map";
+static char *rom_st_str_file_path = "roml.bin";
+static char *rom_map_file_path = "roml.map";
#else
static char *logstrs_path = PLATFORM_PATH"logstrs.bin";
char *st_str_file_path = PLATFORM_PATH"rtecdc.bin";
static char *map_file_path = PLATFORM_PATH"rtecdc.map";
static char *rom_st_str_file_path = PLATFORM_PATH"roml.bin";
static char *rom_map_file_path = PLATFORM_PATH"roml.map";
-#endif /* CUSTOMER_HW4_DEBUG */
+#endif /* DHD_LINUX_STD_FW_API */
static char *ram_file_str = "rtecdc";
static char *rom_file_str = "roml";
dhd_conf_set_suspend_resume(dhd, suspend);
DHD_OS_WAKE_LOCK_RESTORE(dhd);
} else {
+#ifdef BCMDBUS
+ if (dhd->busstate == DHD_BUS_DATA) {
+#endif
if (suspend_mode == PM_NOTIFIER || suspend_mode == SUSPEND_MODE_2)
dhd_conf_set_suspend_resume(dhd, suspend);
#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS)
#endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */
if (suspend_mode == PM_NOTIFIER)
dhd_suspend_resume_helper(dhdinfo, suspend, 0);
+#ifdef BCMDBUS
+ } else {
+ printf("%s: skip resume since bus suspeneded\n", __FUNCTION__);
+ }
+#endif
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
dhd_ifname(&dhd->pub, ifidx), addr, ret));
goto exit;
} else {
- memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETHER_ADDR_LEN);
+ dev_addr_set(dhd->iflist[ifidx]->net, addr);
if (ifidx == 0)
memcpy(dhd->pub.mac.octet, addr, ETHER_ADDR_LEN);
WL_MSG(dhd_ifname(&dhd->pub, ifidx), "MACID %pM is overwritten\n", addr);
struct wl_if_event_info info;
#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
struct net_device *ndev = NULL;
-#endif
+#endif /* WLDWDS && FOURADDR_AUTO_BRG */
#else
struct net_device *ndev;
#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
mac_addr = NULL;
}
-#ifdef WLEASYMESH
+#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
if ((ndev = wl_cfg80211_post_ifcreate(dhd->pub.info->iflist[0]->net,
&info, mac_addr, if_event->name, true)) == NULL)
#else
if (wl_cfg80211_post_ifcreate(dhd->pub.info->iflist[0]->net,
&info, mac_addr, NULL, true) == NULL)
-#endif
+#endif /* WLDWDS && FOURADDR_AUTO_BRG */
{
/* Do the post interface create ops */
DHD_ERROR(("Post ifcreate ops failed. Returning \n"));
}
#endif /* PCIE_FULL_DONGLE */
+#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
+ dhd_bridge_dev_set(dhd, ifidx, ndev);
+#endif /* WLDWDS && FOURADDR_AUTO_BRG */
+
done:
#ifdef DHD_AWDL
if (ret != BCME_OK && is_awdl_iface) {
#endif /* DHD_AWDL */
MFREE(dhd->pub.osh, if_event, sizeof(dhd_if_event_t));
-#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
- if (dhd->pub.info->iflist[ifidx]) {
- dhd_bridge_dev_set(dhd, ifidx, ndev);
- }
-#endif /* defiend(WLDWDS) && defined(FOURADDR_AUTO_BRG) */
DHD_OS_WAKE_UNLOCK(&dhd->pub);
dhd_net_if_unlock_local(dhd);
ifidx = if_event->event.ifidx;
DHD_TRACE(("Removing interface with idx %d\n", ifidx));
-#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
- if (dhd->pub.info->iflist[ifidx]) {
- dhd_bridge_dev_set(dhd, ifidx, NULL);
- }
-#endif /* defiend(WLDWDS) && defined(FOURADDR_AUTO_BRG) */
if (!dhd->pub.info->iflist[ifidx]) {
/* No matching netdev found */
DHD_ERROR(("Netdev not found! Do nothing.\n"));
goto done;
}
+#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
+ dhd_bridge_dev_set(dhd, ifidx, NULL);
+#endif /* WLDWDS && FOURADDR_AUTO_BRG */
#if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
if (if_event->event.ifidx > 0) {
/* Do the post interface del ops */
(unsigned char)buf[3], (unsigned char)buf[4], (unsigned char)buf[5]));
memcpy(dhdinfo->iflist[ifp->idx]->mac_addr, buf, ETHER_ADDR_LEN);
if (dhdinfo->iflist[ifp->idx]->net) {
- memcpy(dhdinfo->iflist[ifp->idx]->net->dev_addr, buf, ETHER_ADDR_LEN);
+ dev_addr_set(dhdinfo->iflist[ifp->idx]->net, buf);
}
}
* available). Store the address and return. macaddr will be applied
* from interface create context.
*/
- (void)memcpy_s(dev->dev_addr, ETH_ALEN, dhdif->mac_addr, ETH_ALEN);
+ dev_addr_set(dev, dhdif->mac_addr);
#ifdef DHD_NOTIFY_MAC_CHANGED
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
dev_open(dev, NULL);
static void
__dhd_txflowcontrol(dhd_pub_t *dhdp, struct net_device *net, bool state)
{
+
+ if (net->reg_state != NETREG_REGISTERED) {
+ return;
+ }
+
if (state == ON) {
if (!netif_queue_stopped(net)) {
DHD_INFO(("%s: Stop Netif Queue\n", __FUNCTION__));
shinfo = skb_shinfo(skb);
if (shinfo->nr_frags) {
-#ifdef CONFIG_64BIT
+#ifdef BCMDMA64OSL
DHD_ERROR(("!!Invalid nr_frags: %u pa.loaddr: 0x%llx pa.hiaddr: 0x%llx "
"skb: 0x%llx skb_data: 0x%llx skb_head: 0x%llx skb_tail: 0x%llx "
"skb_end: 0x%llx skb_len: %u shinfo: 0x%llx pktid: %u\n",
{
struct file *fp;
const char *clm = VENDOR_PATH CONFIG_BCMDHD_CLM_PATH;
- fp = filp_open(clm, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(clm, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: filp_open(%s) failed(%d) schedule wl_accel_work\n",
__FUNCTION__, clm, (int)IS_ERR(fp)));
return FALSE;
}
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
return TRUE;
}
#endif
/* dhd_sync_with_dongle has been called in dhd_bus_start or wl_android_wifi_on */
- memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN);
+ dev_addr_set(net, dhd->pub.mac.octet);
#ifdef TOE
/* Get current TOE mode from dongle */
exit:
mutex_unlock(&dhd->pub.ndev_op_sync);
+ if (ret) {
+ dhd_stop(net);
+ } else {
#if defined(ENABLE_INSMOD_NO_FW_LOAD) && defined(NO_POWER_OFF_AFTER_OPEN)
- dhd_download_fw_on_driverload = TRUE;
- dhd_driver_init_done = TRUE;
+ dhd_download_fw_on_driverload = TRUE;
+ dhd_driver_init_done = TRUE;
#elif defined(ENABLE_INSMOD_NO_FW_LOAD) && defined(ENABLE_INSMOD_NO_POWER_OFF)
- dhd_download_fw_on_driverload = FALSE;
- dhd_driver_init_done = TRUE;
+ dhd_download_fw_on_driverload = FALSE;
+ dhd_driver_init_done = TRUE;
#endif
- if (ret) {
- dhd_stop(net);
}
DHD_OS_WAKE_UNLOCK(&dhd->pub);
unregister_netdev(ifp->net);
else
unregister_netdevice(ifp->net);
+#if defined(WLDWDS) && defined(WL_EXT_IAPSTA)
+ if (ifp->dwds) {
+ wl_ext_iapsta_dettach_dwds_netdev(ifp->net, ifidx, ifp->bssidx);
+ } else
+#endif /* WLDWDS && WL_EXT_IAPSTA */
+ {
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_dettach_netdev(ifp->net, ifidx);
+ wl_ext_iapsta_dettach_netdev(ifp->net, ifidx);
#endif /* WL_EXT_IAPSTA */
#ifdef WL_ESCAN
- wl_escan_event_dettach(ifp->net, ifidx);
+ wl_escan_event_dettach(ifp->net, ifidx);
#endif /* WL_ESCAN */
#ifdef WL_EVENT
- wl_ext_event_dettach_netdev(ifp->net, ifidx);
+ wl_ext_event_dettach_netdev(ifp->net, ifidx);
#endif /* WL_EVENT */
+ }
}
ifp->net = NULL;
DHD_GENERAL_LOCK(dhdpub, flags);
if (!fp || !buf || buflen == 0)
return -1;
- if (vfs_write((struct file *)fp, buf, buflen, &wr_posn) < 0)
+ if (dhd_vfs_write((struct file *)fp, buf, buflen, &wr_posn) < 0)
return -1;
*posn = wr_posn;
if (!file || !buf)
return -1;
- return vfs_read(filep, buf, size, &filep->f_pos);
+ return dhd_vfs_read(filep, buf, size, &filep->f_pos);
}
int
return 0;
}
+#ifdef DHD_COREDUMP
+#define PC_FOUND_BIT 0x01
+#define LR_FOUND_BIT 0x02
+#define ALL_ADDR_VAL (PC_FOUND_BIT | LR_FOUND_BIT)
+#define READ_NUM_BYTES 1000
+#define DHD_FUNC_STR_LEN 80
static int
-dhd_init_logstrs_array(osl_t *osh, dhd_event_log_t *temp)
+dhd_lookup_map(osl_t *osh, char *fname, uint32 pc, char *pc_fn,
+ uint32 lr, char *lr_fn)
{
+#ifdef DHD_LINUX_STD_FW_API
+ const struct firmware *fw = NULL;
+ uint32 size = 0, mem_offset = 0;
+#else
struct file *filep = NULL;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
- struct kstat stat;
mm_segment_t fs;
- int error = 0;
#endif
- char *raw_fmts = NULL;
- int logstrs_size = 0;
+#endif /* DHD_LINUX_STD_FW_API */
+ char *raw_fmts = NULL, *raw_fmts_loc = NULL, *cptr = NULL;
+ uint32 read_size = READ_NUM_BYTES;
+ int err = BCME_ERROR;
+ uint32 addr = 0, addr1 = 0, addr2 = 0;
+ char type = '?', type1 = '?', type2 = '?';
+ char func[DHD_FUNC_STR_LEN] = "\0";
+ char func1[DHD_FUNC_STR_LEN] = "\0";
+ char func2[DHD_FUNC_STR_LEN] = "\0";
+ uint8 count = 0;
+ int num, len = 0, offset;
- if (control_logtrace != LOGTRACE_PARSED_FMT) {
- DHD_ERROR_NO_HW4(("%s : turned off logstr parsing\n", __FUNCTION__));
+ DHD_TRACE(("%s: fname %s pc 0x%x lr 0x%x \n",
+ __FUNCTION__, fname, pc, lr));
+ if (fname == NULL) {
+ DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__));
+ return BCME_ERROR;
+ }
+
+ /* Allocate 1 byte more than read_size to terminate it with NULL */
+ raw_fmts = MALLOCZ(osh, read_size + 1);
+ if (raw_fmts == NULL) {
+ DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n",
+ __FUNCTION__));
return BCME_ERROR;
}
+#ifdef DHD_LINUX_STD_FW_API
+ err = dhd_os_get_img_fwreq(&fw, fname);
+ if (err < 0) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ err));
+ goto fail;
+ }
+ size = fw->size;
+#else
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
fs = get_fs();
set_fs(KERNEL_DS);
#endif
- filep = filp_open(logstrs_path, O_RDONLY, 0);
-
- if (IS_ERR(filep)) {
- DHD_ERROR_NO_HW4(("%s: Failed to open the file %s \n", __FUNCTION__, logstrs_path));
+ filep = dhd_filp_open(fname, O_RDONLY, 0);
+ if (IS_ERR(filep) || (filep == NULL)) {
+ DHD_ERROR(("%s: Failed to open %s \n", __FUNCTION__, fname));
goto fail;
}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
- error = vfs_stat(logstrs_path, &stat);
- if (error) {
- DHD_ERROR_NO_HW4(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path));
- goto fail;
+#endif /* DHD_LINUX_STD_FW_API */
+
+ if (pc_fn == NULL) {
+ count |= PC_FOUND_BIT;
}
- logstrs_size = (int) stat.size;
+ if (lr_fn == NULL) {
+ count |= LR_FOUND_BIT;
+ }
+ while (count != ALL_ADDR_VAL)
+ {
+#ifdef DHD_LINUX_STD_FW_API
+ /* Bound check for size before doing memcpy() */
+ if ((mem_offset + read_size) > size) {
+ read_size = size - mem_offset;
+ }
+
+ err = memcpy_s(raw_fmts, read_size,
+ ((char *)(fw->data) + mem_offset), read_size);
+ if (err) {
+ DHD_ERROR(("%s: failed to copy raw_fmts, err=%d\n",
+ __FUNCTION__, err));
+ goto fail;
+ }
#else
- logstrs_size = dhd_os_get_image_size(filep);
+ err = dhd_os_read_file(filep, raw_fmts, read_size);
+ if (err < 0) {
+ DHD_ERROR(("%s: map file read failed err:%d \n",
+ __FUNCTION__, err));
+ goto fail;
+ }
+
+#endif /* DHD_LINUX_STD_FW_API */
+ /* End raw_fmts with NULL as strstr expects NULL terminated
+ * strings
+ */
+ raw_fmts[read_size] = '\0';
+ raw_fmts_loc = raw_fmts;
+ offset = 0;
+
+ while ((count != ALL_ADDR_VAL) && (offset < read_size))
+ {
+ cptr = bcmstrtok(&raw_fmts_loc, "\n", 0);
+ if (cptr == NULL) {
+ DHD_TRACE(("%s: cptr is NULL, offset %d"
+ " raw_fmts_loc %s \n",
+ __FUNCTION__, offset, raw_fmts_loc));
+ break;
+ }
+ DHD_TRACE(("%s: %s \n", __FUNCTION__, cptr));
+ if ((type2 == 'A') ||
+ (type2 == 'T') ||
+ (type2 == 'W')) {
+ addr1 = addr2;
+ type1 = type2;
+ (void)memcpy_s(func1, DHD_FUNC_STR_LEN,
+ func2, DHD_FUNC_STR_LEN);
+ DHD_TRACE(("%s: %x %c %s \n",
+ __FUNCTION__, addr1, type1, func1));
+ }
+ len = strlen(cptr);
+ num = sscanf(cptr, "%x %c %79s", &addr, &type, func);
+ DHD_TRACE(("%s: num %d addr %x type %c func %s \n",
+ __FUNCTION__, num, addr, type, func));
+ if (num == 3) {
+ addr2 = addr;
+ type2 = type;
+ (void)memcpy_s(func2, DHD_FUNC_STR_LEN,
+ func, DHD_FUNC_STR_LEN);
+ }
+
+ if (!(count & PC_FOUND_BIT) &&
+ (pc >= addr1 && pc < addr2)) {
+ if ((cptr = strchr(func1, '$')) != NULL) {
+ (void)strncpy(func, cptr + 1,
+ DHD_FUNC_STR_LEN - 1);
+ } else {
+ (void)memcpy_s(func, DHD_FUNC_STR_LEN,
+ func1, DHD_FUNC_STR_LEN);
+ }
+ if ((cptr = strstr(func, "__bcmromfn"))
+ != NULL) {
+ *cptr = 0;
+ }
+ if (pc > addr1) {
+ sprintf(pc_fn, "%.68s+0x%x",
+ func, pc - addr1);
+ } else {
+ (void)memcpy_s(pc_fn, DHD_FUNC_STR_LEN,
+ func, DHD_FUNC_STR_LEN);
+ }
+ count |= PC_FOUND_BIT;
+ DHD_INFO(("%s: found addr1 %x pc %x"
+ " addr2 %x \n",
+ __FUNCTION__, addr1, pc, addr2));
+ }
+ if (!(count & LR_FOUND_BIT) &&
+ (lr >= addr1 && lr < addr2)) {
+ if ((cptr = strchr(func1, '$')) != NULL) {
+ (void)strncpy(func, cptr + 1,
+ DHD_FUNC_STR_LEN - 1);
+ } else {
+ (void)memcpy_s(func, DHD_FUNC_STR_LEN,
+ func1, DHD_FUNC_STR_LEN);
+ }
+ if ((cptr = strstr(func, "__bcmromfn"))
+ != NULL) {
+ *cptr = 0;
+ }
+ if (lr > addr1) {
+ sprintf(lr_fn, "%.68s+0x%x",
+ func, lr - addr1);
+ } else {
+ (void)memcpy_s(lr_fn, DHD_FUNC_STR_LEN,
+ func, DHD_FUNC_STR_LEN);
+ }
+ count |= LR_FOUND_BIT;
+ DHD_INFO(("%s: found addr1 %x lr %x"
+ " addr2 %x \n",
+ __FUNCTION__, addr1, lr, addr2));
+ }
+ offset += (len + 1);
+ }
+#ifdef DHD_LINUX_STD_FW_API
+ if ((mem_offset + read_size) >= size) {
+ break;
+ }
+
+ memset(raw_fmts, 0, read_size);
+ mem_offset += (read_size -(len + 1));
+#else
+ if (err < (int)read_size) {
+ /*
+ * since we reset file pos back to earlier pos by
+ * bytes of one line we won't reach EOF.
+ * The reason for this is if string is spreaded across
+ * bytes, the read function should not miss it.
+ * So if ret value is less than read_size, reached EOF
+ * don't read further
+ */
+ break;
+ }
+ memset(raw_fmts, 0, read_size);
+ /*
+ * go back to bytes of one line so that we won't miss
+ * the string and addr even if it comes as splited in next read.
+ */
+ dhd_os_seek_file(filep, -(len + 1));
+#endif /* DHD_LINUX_STD_FW_API */
+ DHD_TRACE(("%s: seek %d \n", __FUNCTION__, -(len + 1)));
+ }
+
+fail:
+#ifdef DHD_LINUX_STD_FW_API
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+#else
+ if (!IS_ERR(filep))
+ dhd_filp_close(filep, NULL);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
+ set_fs(fs);
#endif
- if (logstrs_size <= 0) {
- DHD_ERROR(("%s: get file size fails %d! \n", __FUNCTION__, logstrs_size));
+
+#endif /* DHD_LINUX_STD_FW_API */
+ if (!(count & PC_FOUND_BIT)) {
+ sprintf(pc_fn, "0x%08x", pc);
+ }
+ if (!(count & LR_FOUND_BIT)) {
+ sprintf(lr_fn, "0x%08x", lr);
+ }
+ return err;
+}
+#endif /* DHD_COREDUMP */
+
+#ifdef DHD_LINUX_STD_FW_API
+static int
+dhd_init_logstrs_array(osl_t *osh, dhd_event_log_t *temp)
+{
+ char *raw_fmts = NULL;
+ int logstrs_size = 0;
+ int error = 0;
+ const struct firmware *fw = NULL;
+
+ if (control_logtrace != LOGTRACE_PARSED_FMT) {
+ DHD_ERROR_NO_HW4(("%s : turned off logstr parsing\n", __FUNCTION__));
+ return BCME_ERROR;
+ }
+
+ error = dhd_os_get_img_fwreq(&fw, logstrs_path);
+ if (error < 0) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ error));
+ goto fail;
+ }
+
+ logstrs_size = (int)fw->size;
+ if (logstrs_size == 0) {
+ DHD_ERROR(("%s: return as logstrs_size is 0\n", __FUNCTION__));
goto fail;
}
goto fail;
}
}
-
- if (vfs_read(filep, raw_fmts, logstrs_size, &filep->f_pos) != logstrs_size) {
- DHD_ERROR_NO_HW4(("%s: Failed to read file %s\n", __FUNCTION__, logstrs_path));
+ error = memcpy_s(raw_fmts, logstrs_size, (char *)(fw->data), logstrs_size);
+ if (error) {
+ DHD_ERROR(("%s: failed to copy raw_fmts, err=%d\n",
+ __FUNCTION__, error));
goto fail;
}
-
- if (dhd_parse_logstrs_file(osh, raw_fmts, logstrs_size, temp)
- == BCME_OK) {
- filp_close(filep, NULL);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
- set_fs(fs);
-#endif
+ if (dhd_parse_logstrs_file(osh, raw_fmts, logstrs_size, temp) == BCME_OK) {
+ dhd_os_close_img_fwreq(fw);
+ DHD_ERROR(("%s: return ok\n", __FUNCTION__));
return BCME_OK;
}
fail:
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
if (raw_fmts) {
MFREE(osh, raw_fmts, logstrs_size);
}
MFREE(osh, temp->fmts, temp->num_fmts * sizeof(char *));
}
-fail1:
- if (!IS_ERR(filep))
- filp_close(filep, NULL);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
- set_fs(fs);
-#endif
temp->fmts = NULL;
temp->raw_fmts = NULL;
static int
dhd_read_map(osl_t *osh, char *fname, uint32 *ramstart, uint32 *rodata_start,
uint32 *rodata_end)
+{
+ int err = BCME_ERROR;
+ const struct firmware *fw = NULL;
+
+ if (fname == NULL) {
+ DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__));
+ return BCME_ERROR;
+ }
+
+ err = dhd_os_get_img_fwreq(&fw, fname);
+ if (err < 0) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ err));
+ goto fail;
+ }
+
+ if ((err = dhd_parse_map_file(osh, (struct firmware *)fw, ramstart,
+ rodata_start, rodata_end)) < 0) {
+ goto fail;
+ }
+
+fail:
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+
+ return err;
+}
+
+static int
+dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, char *map_file)
+{
+ char *raw_fmts = NULL;
+ uint32 logstrs_size = 0;
+ int error = 0;
+ uint32 ramstart = 0;
+ uint32 rodata_start = 0;
+ uint32 rodata_end = 0;
+ uint32 logfilebase = 0;
+ const struct firmware *fw = NULL;
+
+ error = dhd_read_map(osh, map_file, &ramstart, &rodata_start, &rodata_end);
+ if (error != BCME_OK) {
+ DHD_ERROR(("readmap Error!! \n"));
+ /* don't do event log parsing in actual case */
+ if (strstr(str_file, ram_file_str) != NULL) {
+ temp->raw_sstr = NULL;
+ } else if (strstr(str_file, rom_file_str) != NULL) {
+ temp->rom_raw_sstr = NULL;
+ }
+ return error;
+ }
+ DHD_ERROR(("ramstart: 0x%x, rodata_start: 0x%x, rodata_end:0x%x\n",
+ ramstart, rodata_start, rodata_end));
+
+ /* Full file size is huge. Just read required part */
+ logstrs_size = rodata_end - rodata_start;
+ logfilebase = rodata_start - ramstart;
+
+ if (logstrs_size == 0) {
+ DHD_ERROR(("%s: return as logstrs_size is 0\n", __FUNCTION__));
+ goto fail1;
+ }
+
+ if (strstr(str_file, ram_file_str) != NULL && temp->raw_sstr != NULL) {
+ raw_fmts = temp->raw_sstr; /* reuse already malloced raw_fmts */
+ } else if (strstr(str_file, rom_file_str) != NULL && temp->rom_raw_sstr != NULL) {
+ raw_fmts = temp->rom_raw_sstr; /* reuse already malloced raw_fmts */
+ } else {
+ raw_fmts = MALLOC(osh, logstrs_size);
+
+ if (raw_fmts == NULL) {
+ DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__));
+ goto fail;
+ }
+ }
+
+ error = dhd_os_get_img_fwreq(&fw, str_file);
+ if (error < 0 || (fw == NULL) || (fw->size < logfilebase)) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ error));
+ goto fail;
+ }
+
+ error = memcpy_s(raw_fmts, logstrs_size, (char *)((fw->data) + logfilebase),
+ logstrs_size);
+ if (error) {
+ DHD_ERROR(("%s: failed to copy raw_fmts, err=%d\n",
+ __FUNCTION__, error));
+ goto fail;
+ }
+
+ if (strstr(str_file, ram_file_str) != NULL) {
+ temp->raw_sstr = raw_fmts;
+ temp->raw_sstr_size = logstrs_size;
+ temp->rodata_start = rodata_start;
+ temp->rodata_end = rodata_end;
+ } else if (strstr(str_file, rom_file_str) != NULL) {
+ temp->rom_raw_sstr = raw_fmts;
+ temp->rom_raw_sstr_size = logstrs_size;
+ temp->rom_rodata_start = rodata_start;
+ temp->rom_rodata_end = rodata_end;
+ }
+
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+
+ return BCME_OK;
+
+fail:
+ if (raw_fmts) {
+ MFREE(osh, raw_fmts, logstrs_size);
+ }
+
+fail1:
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+
+ if (strstr(str_file, ram_file_str) != NULL) {
+ temp->raw_sstr = NULL;
+ } else if (strstr(str_file, rom_file_str) != NULL) {
+ temp->rom_raw_sstr = NULL;
+ }
+
+ return error;
+} /* dhd_init_static_strs_array */
+#else
+static int
+dhd_init_logstrs_array(osl_t *osh, dhd_event_log_t *temp)
{
struct file *filep = NULL;
+ struct kstat stat;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
mm_segment_t fs;
#endif
- int err = BCME_ERROR;
+ char *raw_fmts = NULL;
+ int logstrs_size = 0;
+ int error = 0;
- if (fname == NULL) {
- DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__));
+ if (control_logtrace != LOGTRACE_PARSED_FMT) {
+ DHD_ERROR_NO_HW4(("%s : turned off logstr parsing\n", __FUNCTION__));
return BCME_ERROR;
}
set_fs(KERNEL_DS);
#endif
- filep = filp_open(fname, O_RDONLY, 0);
- if (IS_ERR(filep)) {
- DHD_ERROR_NO_HW4(("%s: Failed to open %s \n", __FUNCTION__, fname));
+ filep = dhd_filp_open(logstrs_path, O_RDONLY, 0);
+
+ if (IS_ERR(filep) || (filep == NULL)) {
+ DHD_ERROR_NO_HW4(("%s: Failed to open the file %s \n",
+ __FUNCTION__, logstrs_path));
goto fail;
}
+ error = dhd_vfs_stat(logstrs_path, &stat);
+ if (error) {
+ DHD_ERROR_NO_HW4(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path));
+ goto fail;
+ }
+ logstrs_size = (int) stat.size;
- if ((err = dhd_parse_map_file(osh, filep, ramstart,
- rodata_start, rodata_end)) < 0)
+ if (logstrs_size == 0) {
+ DHD_ERROR(("%s: return as logstrs_size is 0\n", __FUNCTION__));
+ goto fail1;
+ }
+
+ if (temp->raw_fmts != NULL) {
+ raw_fmts = temp->raw_fmts; /* reuse already malloced raw_fmts */
+ } else {
+ raw_fmts = MALLOC(osh, logstrs_size);
+ if (raw_fmts == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory \n", __FUNCTION__));
+ goto fail;
+ }
+ }
+
+ if (dhd_vfs_read(filep, raw_fmts, logstrs_size, &filep->f_pos) != logstrs_size) {
+ DHD_ERROR_NO_HW4(("%s: Failed to read file %s\n", __FUNCTION__, logstrs_path));
goto fail;
+ }
-fail:
+ if (dhd_parse_logstrs_file(osh, raw_fmts, logstrs_size, temp)
+ == BCME_OK) {
+ dhd_filp_close(filep, NULL);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
+ set_fs(fs);
+#endif
+ return BCME_OK;
+ }
+
+ fail:
+ if (raw_fmts) {
+ MFREE(osh, raw_fmts, logstrs_size);
+ }
+ if (temp->fmts != NULL) {
+ MFREE(osh, temp->fmts, temp->num_fmts * sizeof(char *));
+ }
+
+ fail1:
if (!IS_ERR(filep))
- filp_close(filep, NULL);
+ dhd_filp_close(filep, NULL);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
set_fs(fs);
#endif
+ temp->fmts = NULL;
+ temp->raw_fmts = NULL;
- return err;
+ return BCME_ERROR;
}
-#ifdef DHD_COREDUMP
-#define PC_FOUND_BIT 0x01
-#define LR_FOUND_BIT 0x02
-#define ALL_ADDR_VAL (PC_FOUND_BIT | LR_FOUND_BIT)
-#define READ_NUM_BYTES 1000
-#define DHD_FUNC_STR_LEN 80
+
static int
-dhd_lookup_map(osl_t *osh, char *fname, uint32 pc, char *pc_fn,
- uint32 lr, char *lr_fn)
+dhd_read_map(osl_t *osh, char *fname, uint32 *ramstart, uint32 *rodata_start,
+ uint32 *rodata_end)
{
struct file *filep = NULL;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
mm_segment_t fs;
#endif
- char *raw_fmts = NULL, *raw_fmts_loc = NULL, *cptr = NULL;
- uint32 read_size = READ_NUM_BYTES;
int err = BCME_ERROR;
- uint32 addr = 0, addr1 = 0, addr2 = 0;
- char type = '?', type1 = '?', type2 = '?';
- char func[DHD_FUNC_STR_LEN] = "\0";
- char func1[DHD_FUNC_STR_LEN] = "\0";
- char func2[DHD_FUNC_STR_LEN] = "\0";
- uint8 count = 0;
- int num, len = 0, offset;
-
- DHD_TRACE(("%s: fname %s pc 0x%x lr 0x%x \n",
- __FUNCTION__, fname, pc, lr));
- if (fname == NULL) {
- DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__));
- return BCME_ERROR;
- }
- /* Allocate 1 byte more than read_size to terminate it with NULL */
- raw_fmts = MALLOCZ(osh, read_size + 1);
- if (raw_fmts == NULL) {
- DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n",
- __FUNCTION__));
+ if (fname == NULL) {
+ DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__));
return BCME_ERROR;
}
set_fs(KERNEL_DS);
#endif
- filep = filp_open(fname, O_RDONLY, 0);
- if (IS_ERR(filep)) {
- DHD_ERROR(("%s: Failed to open %s \n", __FUNCTION__, fname));
+ filep = dhd_filp_open(fname, O_RDONLY, 0);
+ if (IS_ERR(filep) || (filep == NULL)) {
+ DHD_ERROR_NO_HW4(("%s: Failed to open %s \n", __FUNCTION__, fname));
goto fail;
}
- if (pc_fn == NULL) {
- count |= PC_FOUND_BIT;
- }
- if (lr_fn == NULL) {
- count |= LR_FOUND_BIT;
- }
- while (count != ALL_ADDR_VAL)
- {
- err = dhd_os_read_file(filep, raw_fmts, read_size);
- if (err < 0) {
- DHD_ERROR(("%s: map file read failed err:%d \n",
- __FUNCTION__, err));
- goto fail;
- }
-
- /* End raw_fmts with NULL as strstr expects NULL terminated
- * strings
- */
- raw_fmts[read_size] = '\0';
- raw_fmts_loc = raw_fmts;
- offset = 0;
-
- while ((count != ALL_ADDR_VAL) && (offset < read_size))
- {
- cptr = bcmstrtok(&raw_fmts_loc, "\n", 0);
- if (cptr == NULL) {
- DHD_TRACE(("%s: cptr is NULL, offset %d"
- " raw_fmts_loc %s \n",
- __FUNCTION__, offset, raw_fmts_loc));
- break;
- }
- DHD_TRACE(("%s: %s \n", __FUNCTION__, cptr));
- if ((type2 == 'A') ||
- (type2 == 'T') ||
- (type2 == 'W')) {
- addr1 = addr2;
- type1 = type2;
- (void)memcpy_s(func1, DHD_FUNC_STR_LEN,
- func2, DHD_FUNC_STR_LEN);
- DHD_TRACE(("%s: %x %c %s \n",
- __FUNCTION__, addr1, type1, func1));
- }
- len = strlen(cptr);
- num = sscanf(cptr, "%x %c %79s", &addr, &type, func);
- DHD_TRACE(("%s: num %d addr %x type %c func %s \n",
- __FUNCTION__, num, addr, type, func));
- if (num == 3) {
- addr2 = addr;
- type2 = type;
- (void)memcpy_s(func2, DHD_FUNC_STR_LEN,
- func, DHD_FUNC_STR_LEN);
- }
-
- if (!(count & PC_FOUND_BIT) &&
- (pc >= addr1 && pc < addr2)) {
- if ((cptr = strchr(func1, '$')) != NULL) {
- (void)strncpy(func, cptr + 1,
- DHD_FUNC_STR_LEN - 1);
- } else {
- (void)memcpy_s(func, DHD_FUNC_STR_LEN,
- func1, DHD_FUNC_STR_LEN);
- }
- if ((cptr = strstr(func, "__bcmromfn"))
- != NULL) {
- *cptr = 0;
- }
- if (pc > addr1) {
- sprintf(pc_fn, "%.68s+0x%x",
- func, pc - addr1);
- } else {
- (void)memcpy_s(pc_fn, DHD_FUNC_STR_LEN,
- func, DHD_FUNC_STR_LEN);
- }
- count |= PC_FOUND_BIT;
- DHD_INFO(("%s: found addr1 %x pc %x"
- " addr2 %x \n",
- __FUNCTION__, addr1, pc, addr2));
- }
- if (!(count & LR_FOUND_BIT) &&
- (lr >= addr1 && lr < addr2)) {
- if ((cptr = strchr(func1, '$')) != NULL) {
- (void)strncpy(func, cptr + 1,
- DHD_FUNC_STR_LEN - 1);
- } else {
- (void)memcpy_s(func, DHD_FUNC_STR_LEN,
- func1, DHD_FUNC_STR_LEN);
- }
- if ((cptr = strstr(func, "__bcmromfn"))
- != NULL) {
- *cptr = 0;
- }
- if (lr > addr1) {
- sprintf(lr_fn, "%.68s+0x%x",
- func, lr - addr1);
- } else {
- (void)memcpy_s(lr_fn, DHD_FUNC_STR_LEN,
- func, DHD_FUNC_STR_LEN);
- }
- count |= LR_FOUND_BIT;
- DHD_INFO(("%s: found addr1 %x lr %x"
- " addr2 %x \n",
- __FUNCTION__, addr1, lr, addr2));
- }
- offset += (len + 1);
- }
-
- if (err < (int)read_size) {
- /*
- * since we reset file pos back to earlier pos by
- * bytes of one line we won't reach EOF.
- * The reason for this is if string is spreaded across
- * bytes, the read function should not miss it.
- * So if ret value is less than read_size, reached EOF
- * don't read further
- */
- break;
- }
- memset(raw_fmts, 0, read_size);
- /*
- * go back to bytes of one line so that we won't miss
- * the string and addr even if it comes as splited in next read.
- */
- dhd_os_seek_file(filep, -(len + 1));
- DHD_TRACE(("%s: seek %d \n", __FUNCTION__, -(len + 1)));
- }
+ if ((err = dhd_parse_map_file(osh, filep, ramstart,
+ rodata_start, rodata_end)) < 0)
+ goto fail;
fail:
if (!IS_ERR(filep))
- filp_close(filep, NULL);
+ dhd_filp_close(filep, NULL);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
set_fs(fs);
#endif
- if (!(count & PC_FOUND_BIT)) {
- sprintf(pc_fn, "0x%08x", pc);
- }
- if (!(count & LR_FOUND_BIT)) {
- sprintf(lr_fn, "0x%08x", lr);
- }
return err;
}
-#endif /* DHD_COREDUMP */
static int
dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, char *map_file)
set_fs(KERNEL_DS);
#endif
- filep = filp_open(str_file, O_RDONLY, 0);
- if (IS_ERR(filep)) {
+ filep = dhd_filp_open(str_file, O_RDONLY, 0);
+ if (IS_ERR(filep) || (filep == NULL)) {
DHD_ERROR(("%s: Failed to open the file %s \n", __FUNCTION__, str_file));
goto fail;
}
}
}
- error = vfs_read(filep, raw_fmts, logstrs_size, (&filep->f_pos));
+ error = dhd_vfs_read(filep, raw_fmts, logstrs_size, (&filep->f_pos));
if (error != logstrs_size) {
DHD_ERROR(("%s: %s read failed %d \n", __FUNCTION__, str_file, error));
goto fail;
temp->rom_rodata_end = rodata_end;
}
- filp_close(filep, NULL);
+ dhd_filp_close(filep, NULL);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
set_fs(fs);
#endif
fail1:
if (!IS_ERR(filep))
- filp_close(filep, NULL);
+ dhd_filp_close(filep, NULL);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
set_fs(fs);
return error;
} /* dhd_init_static_strs_array */
-
+#endif /* DHD_LINUX_STD_FW_API */
#endif /* SHOW_LOGTRACE */
#ifdef BT_OVER_PCIE
goto fail;
}
#endif /* WL_EVENT */
+#ifdef WL_TIMER
+ if (wl_timer_attach(net) != 0) {
+ DHD_ERROR(("wl_ext_timer_attach failed\n"));
+ goto fail;
+ }
+#endif /* WL_TIMER */
#ifdef WL_ESCAN
/* Attach and link in the escan */
if (wl_escan_attach(net) != 0) {
dhd_os_start_logging(&dhd->pub, BT_LOG_RING_NAME, 3, 0, 0, 0);
#endif /* !OEM_ANDROID && BTLOG */
#ifdef DBG_PKT_MON
- dhd->pub.dbg->pkt_mon_lock = osl_spin_lock_init(dhd->pub.osh);
+ dhd->pub.dbg->pkt_mon_lock = osl_mutex_lock_init(dhd->pub.osh);
+ if (!dhd->pub.dbg->pkt_mon_lock) {
+ DHD_ERROR(("%s: pkt_mon_lock init failed !\n", __FUNCTION__));
+ goto fail;
+ }
#ifdef DBG_PKT_MON_INIT_DEFAULT
dhd_os_dbg_attach_pkt_monitor(&dhd->pub);
#endif /* DBG_PKT_MON_INIT_DEFAULT */
}
#endif /* DHD_PCIE_RUNTIMEPM */
-#ifdef SHOW_LOGTRACE
- skb_queue_head_init(&dhd->evt_trace_queue);
-
- /* Create ring proc entries */
- dhd_dbg_ring_proc_create(&dhd->pub);
-#endif /* SHOW_LOGTRACE */
-
#ifdef BTLOG
skb_queue_head_init(&dhd->bt_log_queue);
#endif /* BTLOG */
}
#endif /* !BCMDBUS */
+#ifdef SHOW_LOGTRACE
+ skb_queue_head_init(&dhd->evt_trace_queue);
+
+ /* Create ring proc entries */
+ dhd_dbg_ring_proc_create(&dhd->pub);
+#endif /* SHOW_LOGTRACE */
+
dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED;
#if defined(CONFIG_PM_SLEEP)
/* set default firmware and nvram path for built-in type driver */
// if (!dhd_download_fw_on_driverload) {
+#ifdef DHD_LINUX_STD_FW_API
+ fw = DHD_FW_NAME;
+ nv = DHD_NVRAM_NAME;
+#else
#ifdef CONFIG_BCMDHD_FW_PATH
fw = VENDOR_PATH CONFIG_BCMDHD_FW_PATH;
#endif /* CONFIG_BCMDHD_FW_PATH */
#ifdef CONFIG_BCMDHD_NVRAM_PATH
nv = VENDOR_PATH CONFIG_BCMDHD_NVRAM_PATH;
#endif /* CONFIG_BCMDHD_NVRAM_PATH */
+#endif /* DHD_LINUX_STD_FW_API */
// }
/* check if we need to initialize the path */
old_fs = get_fs();
set_fs(get_ds());
- if ((ret = vfs_stat(config_path, &stat))) {
+ if ((ret = dhd_vfs_stat(config_path, &stat))) {
set_fs(old_fs);
printk(KERN_ERR "%s: Failed to get information (%d)\n",
config_path, ret);
else {
bcmstrtok(&ptr, "\n", 0);
/* Print fw version info */
- DHD_ERROR(("Firmware version = %s\n", buf));
strncpy(fw_version, buf, FW_VER_STR_LEN);
fw_version[FW_VER_STR_LEN-1] = '\0';
-#if defined(BCMSDIO) || defined(BCMPCIE)
- dhd_set_version_info(dhd, buf);
-#endif /* BCMSDIO || BCMPCIE */
}
/* query for 'wlc_ver' to get version info from firmware */
dhd->wlc_ver_major = wlc_ver.wlc_ver_major;
dhd->wlc_ver_minor = wlc_ver.wlc_ver_minor;
}
-#ifdef BOARD_HIKEY
/* Set op_mode as MFG_MODE if WLTEST is present in "wl ver" */
if (strstr(fw_version, "WLTEST") != NULL) {
DHD_ERROR(("%s: wl ver has WLTEST, setting op_mode as DHD_FLAG_MFG_MODE\n",
__FUNCTION__));
op_mode = DHD_FLAG_MFG_MODE;
}
-#endif /* BOARD_HIKEY */
/* get a capabilities from firmware */
ret = dhd_get_fw_capabilities(dhd);
DHD_ERROR(("Firmware up: op_mode=0x%04x, MAC="MACDBG"\n",
dhd->op_mode, MAC2STRDBG(dhd->mac.octet)));
+ dhd_set_version_info(dhd, fw_version);
#if defined(DHD_BLOB_EXISTENCE_CHECK)
if (!dhd->is_blob)
#endif /* DHD_BLOB_EXISTENCE_CHECK */
dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP);
#endif /* defined(BCMPCIE) && defined(EAPOL_PKT_PRIO) */
+#if defined(BCMSDIO) && defined(DHD_LOSSLESS_ROAMING)
+ dhd_update_sdio_data_prio_map(dhd);
+#endif /* BCMSDIO && DHD_LOSSLESS_ROAMING */
+
#ifdef ARP_OFFLOAD_SUPPORT
DHD_ERROR(("arp_enable:%d arp_ol:%d\n",
dhd->arpoe_enable, dhd->arpol_configured));
*/
#ifdef PKT_FILTER_SUPPORT
/* Setup default defintions for pktfilter , enable in suspend */
- dhd->pktfilter_count = 6;
- dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = NULL;
- if (!FW_SUPPORTED(dhd, pf6)) {
- dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL;
- dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL;
- } else {
- /* Immediately pkt filter TYPE 6 Discard IPv4/IPv6 Multicast Packet */
- dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = DISCARD_IPV4_MCAST;
- dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = DISCARD_IPV6_MCAST;
- }
- /* apply APP pktfilter */
- dhd->pktfilter[DHD_ARP_FILTER_NUM] = "105 0 0 12 0xFFFF 0x0806";
+ if (dhd_master_mode) {
+ dhd->pktfilter_count = 6;
+ dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = NULL;
+ if (!FW_SUPPORTED(dhd, pf6)) {
+ dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL;
+ dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL;
+ } else {
+ /* Immediately pkt filter TYPE 6 Discard IPv4/IPv6 Multicast Packet */
+ dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = DISCARD_IPV4_MCAST;
+ dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = DISCARD_IPV6_MCAST;
+ }
+ /* apply APP pktfilter */
+ dhd->pktfilter[DHD_ARP_FILTER_NUM] = "105 0 0 12 0xFFFF 0x0806";
#ifdef BLOCK_IPV6_PACKET
- /* Setup filter to allow only IPv4 unicast frames */
- dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 "
- HEX_PREF_STR UNI_FILTER_STR ZERO_ADDR_STR ETHER_TYPE_STR IPV6_FILTER_STR
- " "
- HEX_PREF_STR ZERO_ADDR_STR ZERO_ADDR_STR ETHER_TYPE_STR ZERO_TYPE_STR;
+ /* Setup filter to allow only IPv4 unicast frames */
+ dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 "
+ HEX_PREF_STR UNI_FILTER_STR ZERO_ADDR_STR ETHER_TYPE_STR IPV6_FILTER_STR
+ " "
+ HEX_PREF_STR ZERO_ADDR_STR ZERO_ADDR_STR ETHER_TYPE_STR ZERO_TYPE_STR;
#else
- /* Setup filter to allow only unicast */
- dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00";
+ /* Setup filter to allow only unicast */
+ dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00";
#endif /* BLOCK_IPV6_PACKET */
#ifdef PASS_IPV4_SUSPEND
- /* XXX customer want to get IPv4 multicast packets */
- dhd->pktfilter[DHD_MDNS_FILTER_NUM] = "104 0 0 0 0xFFFFFF 0x01005E";
+ /* XXX customer want to get IPv4 multicast packets */
+ dhd->pktfilter[DHD_MDNS_FILTER_NUM] = "104 0 0 0 0xFFFFFF 0x01005E";
#else
- /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */
- dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL;
+ /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */
+ dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL;
#endif /* PASS_IPV4_SUSPEND */
- if (FW_SUPPORTED(dhd, pf6)) {
- /* Immediately pkt filter TYPE 6 Dicard Broadcast IP packet */
- dhd->pktfilter[DHD_IP4BCAST_DROP_FILTER_NUM] = DISCARD_IPV4_BCAST;
- /* Immediately pkt filter TYPE 6 Dicard Cisco STP packet */
- dhd->pktfilter[DHD_LLC_STP_DROP_FILTER_NUM] = DISCARD_LLC_STP;
- /* Immediately pkt filter TYPE 6 Dicard Cisco XID protocol */
- dhd->pktfilter[DHD_LLC_XID_DROP_FILTER_NUM] = DISCARD_LLC_XID;
- /* Immediately pkt filter TYPE 6 Dicard NETBIOS packet(port 137) */
- dhd->pktfilter[DHD_UDPNETBIOS_DROP_FILTER_NUM] = DISCARD_UDPNETBIOS;
- dhd->pktfilter_count = 11;
- }
+ if (FW_SUPPORTED(dhd, pf6)) {
+ /* Immediately pkt filter TYPE 6 Dicard Broadcast IP packet */
+ dhd->pktfilter[DHD_IP4BCAST_DROP_FILTER_NUM] = DISCARD_IPV4_BCAST;
+ /* Immediately pkt filter TYPE 6 Dicard Cisco STP packet */
+ dhd->pktfilter[DHD_LLC_STP_DROP_FILTER_NUM] = DISCARD_LLC_STP;
+ /* Immediately pkt filter TYPE 6 Dicard Cisco XID protocol */
+ dhd->pktfilter[DHD_LLC_XID_DROP_FILTER_NUM] = DISCARD_LLC_XID;
+ /* Immediately pkt filter TYPE 6 Dicard NETBIOS packet(port 137) */
+ dhd->pktfilter[DHD_UDPNETBIOS_DROP_FILTER_NUM] = DISCARD_UDPNETBIOS;
+ dhd->pktfilter_count = 11;
+ }
#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER
- dhd->pktfilter_count = 4;
- /* Setup filter to block broadcast and NAT Keepalive packets */
- /* discard all broadcast packets */
- dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0xffffff 0xffffff";
- /* discard NAT Keepalive packets */
- dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "102 0 0 36 0xffffffff 0x11940009";
- /* discard NAT Keepalive packets */
- dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "104 0 0 38 0xffffffff 0x11940009";
- dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL;
+ dhd->pktfilter_count = 4;
+ /* Setup filter to block broadcast and NAT Keepalive packets */
+ /* discard all broadcast packets */
+ dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0xffffff 0xffffff";
+ /* discard NAT Keepalive packets */
+ dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "102 0 0 36 0xffffffff 0x11940009";
+ /* discard NAT Keepalive packets */
+ dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "104 0 0 38 0xffffffff 0x11940009";
+ dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL;
#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */
+ } else
+ dhd_conf_discard_pkt_filter(dhd);
+ dhd_conf_add_pkt_filter(dhd);
#if defined(SOFTAP)
if (ap_fw_loaded) {
dhd_set_bandlock(dhd);
done:
+ dhd_conf_postinit_ioctls(dhd);
if (iov_buf) {
MFREE(dhd->osh, iov_buf, WLC_IOCTL_SMLEN);
}
fw_version[FW_VER_STR_LEN-1] = '\0';
}
-#ifdef BOARD_HIKEY
/* Set op_mode as MFG_MODE if WLTEST is present in "wl ver" */
if (strstr(fw_version, "WLTEST") != NULL) {
DHD_ERROR(("%s: wl ver has WLTEST, setting op_mode as DHD_FLAG_MFG_MODE\n",
__FUNCTION__));
op_mode = DHD_FLAG_MFG_MODE;
}
-#endif /* BOARD_HIKEY */
if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) ||
(op_mode == DHD_FLAG_MFG_MODE)) {
}
#else /* OEM_ANDROID */
- if ((ret = dhd_apply_default_clm(dhd, clm_path)) < 0) {
+ if ((ret = dhd_apply_default_clm(dhd, dhd->clm_path)) < 0) {
DHD_ERROR(("%s: CLM set failed. Abort initialization.\n", __FUNCTION__));
goto done;
}
dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP);
#endif /* defined(BCMPCIE) && defined(EAPOL_PKT_PRIO) */
+#if defined(BCMSDIO) && defined(DHD_LOSSLESS_ROAMING)
+ dhd_update_sdio_data_prio_map(dhd);
+#endif /* BCMSDIO && DHD_LOSSLESS_ROAMING */
+
#ifdef RSSI_MONITOR_SUPPORT
setbit(mask, WLC_E_RSSI_LQM);
#endif /* RSSI_MONITOR_SUPPORT */
setbit(mask, WLC_E_ADDTS_IND);
setbit(mask, WLC_E_DELTS_IND);
#endif /* WL_BCNRECV */
-#ifdef CUSTOMER_HW6
setbit(mask, WLC_E_COUNTRY_CODE_CHANGED);
-#endif /* CUSTOMER_HW6 */
+#if defined(WL_TWT) || defined(WL_TWT_HAL_IF)
+ setbit(mask, WLC_E_TWT);
+#endif /* WL_TWT || WL_TWT_HAL_IF */
/* Write updated Event mask */
eventmask_msg->ver = EVENTMSGS_VER;
* XXX Linux 2.6.25 does not like a blank MAC address, so use a
* dummy address until the interface is brought up.
*/
- memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
+ dev_addr_set(net, temp_addr);
if (ifidx == 0)
printf("%s\n", dhd_version);
}
#endif /* BCM_ROUTER_DHD && HNDCTF */
+#if defined(WLDWDS) && defined(WL_EXT_IAPSTA)
+ if (ifp->dwds) {
+ wl_ext_iapsta_attach_dwds_netdev(net, ifidx, ifp->bssidx);
+ } else
+#endif /* WLDWDS && WL_EXT_IAPSTA */
+ {
#ifdef WL_EVENT
- wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
+ wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
#endif /* WL_EVENT */
#ifdef WL_ESCAN
- wl_escan_event_attach(net, ifidx);
+ wl_escan_event_attach(net, ifidx);
#endif /* WL_ESCAN */
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
- wl_ext_iapsta_attach_name(net, ifidx);
+ wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
+ wl_ext_iapsta_attach_name(net, ifidx);
#endif /* WL_EXT_IAPSTA */
+ }
#if defined(CONFIG_TIZEN)
net_stat_tizen_register(net);
#ifdef WL_ESCAN
wl_escan_detach(dev);
#endif /* WL_ESCAN */
+#ifdef WL_TIMER
+ wl_timer_dettach(dhdp);
+#endif /* WL_TIMER */
#ifdef WL_EVENT
wl_ext_event_dettach(dhdp);
#endif /* WL_EVENT */
if (dhdp->dbg) {
#ifdef DBG_PKT_MON
dhd_os_dbg_detach_pkt_monitor(dhdp);
- osl_spin_lock_deinit(dhd->pub.osh, dhd->pub.dbg->pkt_mon_lock);
+ osl_mutex_lock_deinit(dhd->pub.osh, dhd->pub.dbg->pkt_mon_lock);
#endif /* DBG_PKT_MON */
}
#endif /* DEBUGABILITY */
#endif /* DHD_PCIE_RUNTIMEPM */
+#ifdef DHD_LINUX_STD_FW_API
+int
+dhd_os_get_img_fwreq(const struct firmware **fw, char *file_path)
+{
+ int ret = BCME_ERROR;
+
+ ret = request_firmware(fw, file_path, dhd_bus_to_dev(g_dhd_pub->bus));
+ if (ret < 0) {
+ DHD_ERROR(("%s: request_firmware %s err: %d\n", __FUNCTION__, file_path, ret));
+ /* convert to BCME_NOTFOUND error for error handling */
+ ret = BCME_NOTFOUND;
+ } else
+ DHD_ERROR(("%s: %s (%zu bytes) open success\n", __FUNCTION__, file_path, (*fw)->size));
+
+ return ret;
+}
+
+void
+dhd_os_close_img_fwreq(const struct firmware *fw)
+{
+ release_firmware(fw);
+}
+#endif /* DHD_LINUX_STD_FW_API */
+
void *
dhd_os_open_image1(dhd_pub_t *pub, char *filename)
{
struct file *fp;
int size;
- fp = filp_open(filename, O_RDONLY, 0);
+ fp = dhd_filp_open(filename, O_RDONLY, 0);
/*
- * 2.6.11 (FC4) supports filp_open() but later revs don't?
+ * 2.6.11 (FC4) supports dhd_filp_open() but later revs don't?
* Alternative:
* fp = open_namei(AT_FDCWD, filename, O_RD, 0);
* ???
*/
- if (IS_ERR(fp)) {
+ if (IS_ERR(fp) || (fp == NULL)) {
fp = NULL;
goto err;
}
goto err;
}
- size = i_size_read(file_inode(fp));
+ size = dhd_i_size_read(file_inode(fp));
if (size <= 0) {
DHD_ERROR(("%s: %s file size invalid %d\n", __FUNCTION__, filename, size));
fp = NULL;
return 0;
}
- size = i_size_read(file_inode(fp));
- rdlen = kernel_read_compat(fp, fp->f_pos, buf, MIN(len, size));
+ size = dhd_i_size_read(file_inode(fp));
+ rdlen = dhd_kernel_read_compat(fp, fp->f_pos, buf, MIN(len, size));
if (len >= size && size != rdlen) {
return -EIO;
if (!image)
return 0;
- rd_len = kernel_read_compat(fp, fp->f_pos, str, len);
+ rd_len = dhd_kernel_read_compat(fp, fp->f_pos, str, len);
str_end = strnchr(str, len, '\n');
if (str_end == NULL) {
goto err;
return 0;
}
- size = i_size_read(file_inode(fp));
+ size = dhd_i_size_read(file_inode(fp));
return size;
}
dhd_os_close_image1(dhd_pub_t *pub, void *image)
{
if (image) {
- filp_close((struct file *)image, NULL);
+ dhd_filp_close((struct file *)image, NULL);
}
}
feature_set |= WIFI_FEATURE_LINKSTAT;
#endif /* LINKSTAT_SUPPORT */
-#ifdef CUSTOMER_HW_AMLOGIC
- feature_set |= WIFI_FEATURE_SET_LATENCY_MODE;
-#endif
-
#if defined(PNO_SUPPORT) && !defined(DISABLE_ANDROID_PNO)
if (dhd_is_pno_supported(dhd)) {
feature_set |= WIFI_FEATURE_PNO;
#endif
/* open file to write */
- fp = filp_open(file_name, flags, 0664);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(file_name, flags, 0664);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("open file error, err = %ld\n", PTR_ERR(fp)));
goto exit;
}
/* Write buf to file */
- ret = vfs_write(fp, buf, size, &pos);
+ ret = dhd_vfs_write(fp, buf, size, &pos);
if (ret < 0) {
DHD_ERROR(("write file error, err = %d\n", ret));
goto exit;
/* Sync file from filesystem to physical media */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
- ret = vfs_fsync(fp, 0);
+ ret = dhd_vfs_fsync(fp, 0);
#else
ret = vfs_fsync(fp, fp->f_path.dentry, 0);
#endif
exit:
/* close file before return */
if (!IS_ERR(fp))
- filp_close(fp, current->files);
+ dhd_filp_close(fp, current->files);
/* restore previous address limit */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
*/
file_mode = O_CREAT | O_WRONLY | O_SYNC;
{
- struct file *fp = filp_open(memdump_path, file_mode, 0664);
+ struct file *fp = dhd_filp_open(memdump_path, file_mode, 0664);
/* Check if it is live Brix image having /installmedia, else use /data */
- if (IS_ERR(fp)) {
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("open file %s, try /data/\n", memdump_path));
snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s",
"/data/", fname, memdump_type, dhd->debug_dump_time_str);
} else {
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
}
}
#else
return;
i = snprintf(&info_string[i], sizeof(info_string) - i,
- "\n Chip: %x Rev %x", dhd_conf_get_chip(dhdp),
+ "\n%s Chip: %x Rev %x", DHD_LOG_PREFIXS, dhd_conf_get_chip(dhdp),
dhd_conf_get_chiprev(dhdp));
}
loff_t pos = 0;
/* Read memdump info from the file */
- fp = filp_open(filepath, file_mode, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, file_mode, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
#if defined(CONFIG_X86) && defined(OEM_ANDROID)
/* Check if it is Live Brix Image */
/* Try if it is Installed Brix Image */
filepath = RNDINFO_INST".in";
DHD_ERROR(("%s: Try File [%s]\n", __FUNCTION__, filepath));
- fp = filp_open(filepath, file_mode, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, file_mode, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
goto err1;
}
set_fs(KERNEL_DS);
/* Handle success case */
- ret = vfs_read(fp, (char *)&dhd->rnd_len, sizeof(dhd->rnd_len), &pos);
+ ret = dhd_vfs_read(fp, (char *)&dhd->rnd_len, sizeof(dhd->rnd_len), &pos);
if (ret < 0) {
DHD_ERROR(("%s: rnd_len read error, ret=%d\n", __FUNCTION__, ret));
goto err2;
goto err2;
}
- ret = vfs_read(fp, (char *)dhd->rnd_buf, dhd->rnd_len, &pos);
+ ret = dhd_vfs_read(fp, (char *)dhd->rnd_buf, dhd->rnd_len, &pos);
if (ret < 0) {
DHD_ERROR(("%s: rnd_buf read error, ret=%d\n", __FUNCTION__, ret));
goto err3;
}
set_fs(old_fs);
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
DHD_ERROR(("%s: RND read from %s\n", __FUNCTION__, filepath));
return BCME_OK;
dhd->rnd_buf = NULL;
err2:
set_fs(old_fs);
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
err1:
return BCME_ERROR;
}
loff_t pos = 0;
/* Read memdump info from the file */
- fp = filp_open(filepath, file_mode, 0664);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, file_mode, 0664);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
#if defined(CONFIG_X86) && defined(OEM_ANDROID)
/* Check if it is Live Brix Image */
/* Try if it is Installed Brix Image */
filepath = RNDINFO_INST".out";
DHD_ERROR(("%s: Try File [%s]\n", __FUNCTION__, filepath));
- fp = filp_open(filepath, file_mode, 0664);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, file_mode, 0664);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
goto err1;
}
set_fs(KERNEL_DS);
/* Handle success case */
- ret = vfs_write(fp, (char *)&rnd_len, sizeof(rnd_len), &pos);
+ ret = dhd_vfs_write(fp, (char *)&rnd_len, sizeof(rnd_len), &pos);
if (ret < 0) {
DHD_ERROR(("%s: rnd_len write error, ret=%d\n", __FUNCTION__, ret));
goto err2;
}
- ret = vfs_write(fp, (char *)rnd_buf, rnd_len, &pos);
+ ret = dhd_vfs_write(fp, (char *)rnd_buf, rnd_len, &pos);
if (ret < 0) {
DHD_ERROR(("%s: rnd_buf write error, ret=%d\n", __FUNCTION__, ret));
goto err2;
}
set_fs(old_fs);
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
DHD_ERROR(("%s: RND written to %s\n", __FUNCTION__, filepath));
return BCME_OK;
err2:
set_fs(old_fs);
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
err1:
return BCME_ERROR;
else
file_mode = O_CREAT | O_RDWR | O_SYNC;
- fp = filp_open(dump_path, file_mode, 0664);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(dump_path, file_mode, 0664);
+ if (IS_ERR(fp) || (fp == NULL)) {
/* If android installed image, try '/data' directory */
#if defined(CONFIG_X86) && defined(OEM_ANDROID)
DHD_ERROR(("%s: File open error on Installed android image, trying /data...\n",
sizeof(dump_path) - strlen(dump_path),
"_%s", dhdp->debug_dump_time_str);
}
- fp = filp_open(dump_path, file_mode, 0664);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(dump_path, file_mode, 0664);
+ if (IS_ERR(fp) || (fp == NULL)) {
ret = PTR_ERR(fp);
DHD_ERROR(("open file error, err = %d\n", ret));
goto exit2;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
- ret = vfs_stat(dump_path, &stat);
+ ret = dhd_vfs_stat(dump_path, &stat);
if (ret < 0) {
DHD_ERROR(("file stat error, err = %d\n", ret));
goto exit2;
exit2:
if (!IS_ERR(fp) && fp != NULL) {
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
DHD_ERROR(("%s: Finished writing log dump to file - '%s' \n",
__FUNCTION__, dump_path));
}
int ret = BCME_OK;
if (fp) {
- ret = vfs_write(fp, mem_buf, buf_len, (loff_t *)pos);
+ ret = dhd_vfs_write(fp, mem_buf, buf_len, (loff_t *)pos);
if (ret < 0) {
DHD_ERROR(("write file error, err = %d\n", ret));
goto exit;
struct file *fp;
char *filepath = VENDOR_PATH CONFIG_BCMDHD_CLM_PATH;
- fp = filp_open(filepath, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: ----- blob file doesn't exist (%s) -----\n", __FUNCTION__,
filepath));
dhdp->is_blob = FALSE;
#else
BCM_REFERENCE(fw_path);
#endif /* SKIP_CONCATE_BLOB */
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
}
}
#endif /* DHD_BLOB_EXISTENCE_CHECK */
#endif
/* File is always created. */
- fp = filp_open(filepath, O_RDWR | O_CREAT, 0664);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, O_RDWR | O_CREAT, 0664);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: Couldn't open file '%s' err %ld\n",
__FUNCTION__, filepath, PTR_ERR(fp)));
ret = BCME_ERROR;
} else {
if (fp->f_mode & FMODE_WRITE) {
- ret = vfs_write(fp, buf, buf_len, &fp->f_pos);
+ ret = dhd_vfs_write(fp, buf, buf_len, &fp->f_pos);
if (ret < 0) {
DHD_ERROR(("%s: Couldn't write file '%s'\n",
__FUNCTION__, filepath));
ret = BCME_OK;
}
}
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
}
/* restore previous address limit */
set_fs(KERNEL_DS);
#endif
- fp = filp_open(filepath, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
set_fs(old_fs);
#endif
return BCME_ERROR;
}
- ret = kernel_read_compat(fp, 0, buf, buf_len);
- filp_close(fp, NULL);
+ ret = dhd_kernel_read_compat(fp, 0, buf, buf_len);
+ dhd_filp_close(fp, NULL);
/* restore previous address limit */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
char tmp_buf[KIRQ_PRINT_BUF_LEN];
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0))
+ desc = irq_data_to_desc(irq_get_irq_data(irq_num));
+#else
desc = irq_to_desc(irq_num);
+#endif // (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
if (!desc) {
DHD_ERROR(("%s : irqdesc is not found \n", __FUNCTION__));
return;
}
/* END of DHD RING */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
-#define DHD_VFS_INODE(dir) (dir->d_inode)
-#else
-#define DHD_VFS_INODE(dir) d_inode(dir)
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
-#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b)
-#else
-#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b, c)
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
-
#if ((defined DHD_DUMP_MNGR) || (defined DNGL_AXI_ERROR_LOGGING))
int
dhd_file_delete(char *path)
{
- struct path file_path;
+ struct path file_path = {.dentry = 0};
int err;
struct dentry *dir;
- err = kern_path(path, 0, &file_path);
+ err = dhd_kern_path(path, 0, &file_path);
if (err < 0) {
DHD_ERROR(("Failed to get kern-path delete file: %s error: %d\n", path, err));
#if defined(WLDWDS) && defined(FOURADDR_AUTO_BRG)
/* This function is to automatically add/del interface to the bridged dev that priamy dev is in */
-static void dhd_bridge_dev_set(dhd_info_t *dhd, int ifidx, struct net_device *dev)
+static void
+dhd_bridge_dev_set(dhd_info_t *dhd, int ifidx, struct net_device *sdev)
{
- struct net_device *primary_ndev = NULL, *br_dev = NULL;
- int cmd;
- struct ifreq ifr;
+ struct net_device *pdev = NULL, *br_dev = NULL;
+ int i, err = 0;
- /* add new interface to bridge dev */
- if (dev) {
- int found = 0, i;
- DHD_ERROR(("bssidx %d\n", dhd->pub.info->iflist[ifidx]->bssidx));
- for (i = 0 ; i < ifidx; i++) {
- DHD_ERROR(("bssidx %d %d\n", i, dhd->pub.info->iflist[i]->bssidx));
- /* search the primary interface */
- if (dhd->pub.info->iflist[i]->bssidx == dhd->pub.info->iflist[ifidx]->bssidx) {
- primary_ndev = dhd->pub.info->iflist[i]->net;
- DHD_ERROR(("%dst is primary dev %s\n", i, primary_ndev->name));
- found = 1;
+ if (sdev) {
+ /* search the primary interface wlan1(wl0.1) with same bssidx */
+ for (i = 0; i < ifidx; i++) {
+ if (dhd->iflist[i]->bssidx == dhd->iflist[ifidx]->bssidx) {
+ pdev = dhd->pub.info->iflist[i]->net;
+ WL_MSG(sdev->name, "found primary dev %s\n", pdev->name);
break;
}
}
- if (found == 0) {
- DHD_ERROR(("Can not find primary dev %s\n", dev->name));
+ if (!pdev) {
+ WL_MSG(sdev->name, "can not find primary dev\n");
return;
}
- cmd = SIOCBRADDIF;
- ifr.ifr_ifindex = dev->ifindex;
- } else { /* del interface from bridge dev */
- primary_ndev = dhd->pub.info->iflist[ifidx]->net;
- cmd = SIOCBRDELIF;
- ifr.ifr_ifindex = primary_ndev->ifindex;
+ } else {
+ pdev = dhd->iflist[ifidx]->net;
}
+
/* if primary net device is bridged */
- if (primary_ndev->priv_flags & IFF_BRIDGE_PORT) {
+ if (pdev->priv_flags & IFF_BRIDGE_PORT) {
rtnl_lock();
/* get bridge device */
- br_dev = netdev_master_upper_dev_get(primary_ndev);
+ br_dev = netdev_master_upper_dev_get(pdev);
if (br_dev) {
const struct net_device_ops *ops = br_dev->netdev_ops;
- DHD_ERROR(("br %s pri %s\n", br_dev->name, primary_ndev->name));
if (ops) {
- if (cmd == SIOCBRADDIF) {
- DHD_ERROR(("br call ndo_add_slave\n"));
- ops->ndo_add_slave(br_dev, dev);
+ if (sdev) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
+ err = ops->ndo_add_slave(br_dev, sdev, NULL);
+#else
+ err = ops->ndo_add_slave(br_dev, sdev);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) */
+ if (err)
+ WL_MSG(sdev->name, "add to %s failed %d\n", br_dev->name, err);
+ else
+ WL_MSG(sdev->name, "slave added to %s\n", br_dev->name);
/* Also bring wds0.x interface up automatically */
- dev_change_flags(dev, dev->flags | IFF_UP);
- }
- else {
- DHD_ERROR(("br call ndo_del_slave\n"));
- ops->ndo_del_slave(br_dev, primary_ndev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
+ dev_change_flags(sdev, sdev->flags | IFF_UP, NULL);
+#else
+ dev_change_flags(sdev, sdev->flags | IFF_UP);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) */
+ } else {
+ err = ops->ndo_del_slave(br_dev, pdev);
+ if (err)
+ WL_MSG(pdev->name, "del from %s failed %d\n", br_dev->name, err);
+ else
+ WL_MSG(pdev->name, "slave deleted from %s\n", br_dev->name);
}
}
}
else {
- DHD_ERROR(("no br dev\n"));
+ WL_MSG(pdev->name, "not bridged\n");
}
rtnl_unlock();
}
else {
- DHD_ERROR(("device %s is not bridged\n", primary_ndev->name));
+ WL_MSG(pdev->name, "not bridged\n");
}
}
-#endif /* defiend(WLDWDS) && defined(FOURADDR_AUTO_BRG) */
+#endif /* WLDWDS && FOURADDR_AUTO_BRG */
/* dongle status */
enum wifi_adapter_status {
WIFI_STATUS_POWER_ON = 0,
- WIFI_STATUS_ATTACH,
WIFI_STATUS_FW_READY,
- WIFI_STATUS_DETTACH
+ WIFI_STATUS_NET_ATTACHED
};
#define wifi_chk_adapter_status(adapter, stat) (test_bit(stat, &(adapter)->status))
#define wifi_get_adapter_status(adapter, stat) (test_bit(stat, &(adapter)->status))
bool recv_reassoc_evt;
bool post_roam_evt;
#endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */
+#ifdef WLDWDS
+ bool dwds; /* DWDS interface */
+#endif /* WLDWDS */
#ifdef WLEASYMESH
uint8 _1905_al_ucast[ETHER_ADDR_LEN];
uint8 _1905_al_mcast[ETHER_ADDR_LEN];
* -----------------------------------------------------------------------------
*/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
#if defined(DHD_TRACE_WAKE_LOCK)
extern atomic_t trace_wklock_onoff;
return ret;
}
#endif /* PWRSTATS_SYSFS */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
/*
* Generic Attribute Structure for DHD.
ssize_t(*store)(struct dhd_info *, const char *, size_t count);
};
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
#if defined(DHD_TRACE_WAKE_LOCK)
static struct dhd_attr dhd_attr_wklock =
__ATTR(wklock_trace, 0660, show_wklock_trace, wklock_trace_onoff);
static struct dhd_attr dhd_attr_pwrstats_path =
__ATTR(power_stats, 0660, show_pwrstats_path, NULL);
#endif /* PWRSTATS_SYSFS */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
#define to_dhd(k) container_of(k, struct dhd_info, dhd_kobj)
#define to_attr(a) container_of(a, struct dhd_attr, attr)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
#ifdef DHD_MAC_ADDR_EXPORT
struct ether_addr sysfs_mac_addr;
static ssize_t
static struct dhd_attr dhd_attr_macaddr =
__ATTR(mac_addr, 0660, show_mac_addr, set_mac_addr);
#endif /* DHD_MAC_ADDR_EXPORT */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
#ifdef DHD_FW_COREDUMP
/*
int ret = 0;
/* Read memdump info from the file */
- fp = filp_open(filepath, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
#if defined(CONFIG_X86) && defined(OEM_ANDROID)
/* Check if it is Live Brix Image */
/* Try if it is Installed Brix Image */
filepath = MEMDUMPINFO_INST;
DHD_ERROR(("%s: Try File [%s]\n", __FUNCTION__, filepath));
- fp = filp_open(filepath, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
goto done;
}
}
/* Handle success case */
- ret = kernel_read_compat(fp, 0, (char *)&mem_val, sizeof(uint32));
+ ret = dhd_kernel_read_compat(fp, 0, (char *)&mem_val, sizeof(uint32));
if (ret < 0) {
DHD_ERROR(("%s: File read error, ret=%d\n", __FUNCTION__, ret));
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
goto done;
}
p_mem_val[sizeof(uint32) - 1] = '\0';
mem_val = bcm_atoi(p_mem_val);
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
done:
return mem_val;
DHD_ERROR(("%s: MEMDUMP ENABLED = %u\n", __FUNCTION__, dhd->memdump_enabled));
}
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
#ifdef DHD_EXPORT_CNTL_FILE
static ssize_t
show_memdump_info(struct dhd_info *dev, char *buf)
static struct dhd_attr dhd_attr_memdump =
__ATTR(memdump, 0660, show_memdump_info, set_memdump_info);
#endif /* DHD_EXPORT_CNTL_FILE */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
#endif /* DHD_FW_COREDUMP */
#ifdef BCMASSERT_LOG
* 2: Trigger Kernel crash by BUG()
* File doesn't exist: Keep default value (1).
*/
- fp = filp_open(filepath, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(filepath, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath));
} else {
- int ret = kernel_read_compat(fp, 0, (char *)&mem_val, sizeof(uint32));
+ int ret = dhd_kernel_read_compat(fp, 0, (char *)&mem_val, sizeof(uint32));
if (ret < 0) {
DHD_ERROR(("%s: File read error, ret=%d\n", __FUNCTION__, ret));
} else {
mem_val = bcm_atoi(p_mem_val);
DHD_ERROR(("%s: ASSERT ENABLED = %d\n", __FUNCTION__, mem_val));
}
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
}
#ifdef CUSTOMER_HW4_DEBUG
#endif /* !DHD_EXPORT_CNTL_FILE */
}
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
#ifdef DHD_EXPORT_CNTL_FILE
static ssize_t
show_assert_info(struct dhd_info *dev, char *buf)
static struct dhd_attr dhd_attr_assert =
__ATTR(assert, 0660, show_assert_info, set_assert_info);
#endif /* DHD_EXPORT_CNTL_FILE */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
#endif /* BCMASSERT_LOG */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
#ifdef DHD_EXPORT_CNTL_FILE
#if defined(WRITE_WLANINFO)
static ssize_t
static struct dhd_attr dhd_attr_adps_bam =
__ATTR(bad_ap_list, 0660, show_adps_bam_list, store_adps_bam_list);
#endif /* DHD_ADPS_BAM_EXPORT && WL_BAM */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
-#ifdef DHD_SEND_HANG_PRIVCMD_ERRORS
uint32 report_hang_privcmd_err = 1;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
+#ifdef DHD_SEND_HANG_PRIVCMD_ERRORS
static ssize_t
show_hang_privcmd_err(struct dhd_info *dev, char *buf)
{
#endif /* AGG_H2D_DB */
NULL
};
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
/*
* wifi kobject show function, the "attr" attribute specifices to which
static struct kobj_type dhd_ktype = {
.sysfs_ops = &dhd_sysfs_ops,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
.default_attrs = default_file_attrs,
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
};
#ifdef CSI_SUPPORT
* sysfs for dhd_lb
*/
#ifdef DHD_LB
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
#if defined(DHD_LB_TXP)
static ssize_t
show_lbtxp(struct dhd_info *dev, char *buf)
&dhd_tx_cpu.attr,
NULL
};
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
#define to_dhd_lb(k) container_of(k, struct dhd_info, dhd_lb_kobj)
static struct kobj_type dhd_lb_ktype = {
.sysfs_ops = &dhd_sysfs_lb_ops,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
.default_attrs = debug_lb_attrs,
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
};
#endif /* DHD_LB */
return TRUE;
}
-#ifdef DHD_DHCP_DUMP
#define BOOTP_CHADDR_LEN 16
#define BOOTP_SNAME_LEN 64
#define BOOTP_FILE_LEN 128
#define BOOTP_MIN_DHCP_OPT_LEN 312
#define BOOTP_MAGIC_COOKIE_LEN 4
+typedef struct bootp_fmt {
+ struct ipv4_hdr iph;
+ struct bcmudp_hdr udph;
+ uint8 op;
+ uint8 htype;
+ uint8 hlen;
+ uint8 hops;
+ uint32 transaction_id;
+ uint16 secs;
+ uint16 flags;
+ uint32 client_ip;
+ uint32 assigned_ip;
+ uint32 server_ip;
+ uint32 relay_ip;
+ uint8 hw_address[BOOTP_CHADDR_LEN];
+ uint8 server_name[BOOTP_SNAME_LEN];
+ uint8 file_name[BOOTP_FILE_LEN];
+ uint8 options[BOOTP_MIN_DHCP_OPT_LEN];
+} PACKED_STRUCT bootp_fmt_t;
+static const uint8 bootp_magic_cookie[4] = { 99, 130, 83, 99 };
+
+#ifdef DHD_DHCP_DUMP
#define DHCP_MSGTYPE_DISCOVER 1
#define DHCP_MSGTYPE_OFFER 2
#define DHCP_MSGTYPE_REQUEST 3
} \
} while (0)
-typedef struct bootp_fmt {
- struct ipv4_hdr iph;
- struct bcmudp_hdr udph;
- uint8 op;
- uint8 htype;
- uint8 hlen;
- uint8 hops;
- uint32 transaction_id;
- uint16 secs;
- uint16 flags;
- uint32 client_ip;
- uint32 assigned_ip;
- uint32 server_ip;
- uint32 relay_ip;
- uint8 hw_address[BOOTP_CHADDR_LEN];
- uint8 server_name[BOOTP_SNAME_LEN];
- uint8 file_name[BOOTP_FILE_LEN];
- uint8 options[BOOTP_MIN_DHCP_OPT_LEN];
-} PACKED_STRUCT bootp_fmt_t;
-
-static const uint8 bootp_magic_cookie[4] = { 99, 130, 83, 99 };
static char dhcp_ops[][10] = {
"NA", "REQUEST", "REPLY"
};
}
}
#endif /* DHD_RX_DUMP */
+
+#ifdef BCMPCIE
+static bool
+dhd_is_eapol_pkt(dhd_pub_t *dhd, uint8 *pktdata, uint32 pktlen)
+{
+ eapol_header_t *eapol_hdr = (eapol_header_t *)pktdata;
+
+ eapol_hdr = (eapol_header_t *)pktdata;
+
+ if (eapol_hdr->type == EAP_PACKET) {
+ return TRUE;
+ } else if (eapol_hdr->type == EAPOL_START) {
+ return TRUE;
+ } else if (eapol_hdr->type == EAPOL_KEY) {
+ return TRUE;
+ } else {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool
+dhd_is_arp_pkt(dhd_pub_t *dhdp, uint8 *pktdata)
+{
+ uint8 *pkt = (uint8 *)&pktdata[ETHER_HDR_LEN];
+ struct bcmarp *arph = (struct bcmarp *)pkt;
+ uint16 opcode;
+
+ /* validation check */
+ if (arph->htype != hton16(HTYPE_ETHERNET) ||
+ arph->hlen != ETHER_ADDR_LEN ||
+ arph->plen != 4) {
+ return FALSE;
+ }
+
+ opcode = ntoh16(arph->oper);
+ if (opcode == ARP_OPC_REQUEST) {
+ return TRUE;
+ } else if (opcode == ARP_OPC_REPLY) {
+ return TRUE;
+ } else {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool
+dhd_is_dhcp_pkt(dhd_pub_t *dhdp, uint8 *pktdata)
+{
+ bootp_fmt_t *b = (bootp_fmt_t *)&pktdata[ETHER_HDR_LEN];
+ struct ipv4_hdr *iph = &b->iph;
+ uint8 *ptr, *opt, *end = (uint8 *) b + ntohs(b->iph.tot_len);
+ int len, opt_len;
+
+ /* check IP header */
+ if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
+ IP_VER(iph) != IP_VER_4 ||
+ IPV4_PROT(iph) != IP_PROT_UDP) {
+ return FALSE;
+ }
+
+ /* check UDP port for bootp (67, 68) */
+ if (b->udph.src_port != htons(DHCP_PORT_SERVER) &&
+ b->udph.src_port != htons(DHCP_PORT_CLIENT) &&
+ b->udph.dst_port != htons(DHCP_PORT_SERVER) &&
+ b->udph.dst_port != htons(DHCP_PORT_CLIENT)) {
+ return FALSE;
+ }
+
+ /* check header length */
+ if (ntohs(iph->tot_len) < ntohs(b->udph.len) + sizeof(struct bcmudp_hdr)) {
+ return FALSE;
+ }
+
+ len = ntohs(b->udph.len) - sizeof(struct bcmudp_hdr);
+ opt_len = len - (sizeof(*b) - sizeof(struct ipv4_hdr) -
+ sizeof(struct bcmudp_hdr) - sizeof(b->options));
+
+ /* parse bootp options */
+ if (opt_len >= BOOTP_MAGIC_COOKIE_LEN &&
+ !memcmp(b->options, bootp_magic_cookie, BOOTP_MAGIC_COOKIE_LEN)) {
+ ptr = &b->options[BOOTP_MAGIC_COOKIE_LEN];
+ while (ptr < end && *ptr != 0xff) {
+ opt = ptr++;
+ if (*opt == 0) {
+ continue;
+ }
+ ptr += *ptr + 1;
+ if (ptr >= end) {
+ break;
+ }
+ if (*opt == DHCP_OPT_MSGTYPE) {
+ if (opt[1]) {
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static bool
+dhd_is_icmp_pkt(dhd_pub_t *dhd, uint8 *pktdata, uint32 pktlen)
+{
+ uint8 *pkt;
+ struct ipv4_hdr *iph;
+
+ pkt = (uint8 *)&pktdata[ETHER_HDR_LEN];
+ iph = (struct ipv4_hdr *)pkt;
+
+ /* check IP header */
+ if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
+ IP_VER(iph) != IP_VER_4 ||
+ IPV4_PROT(iph) != IP_PROT_ICMP) {
+ return FALSE;
+ }
+
+ /* check header length */
+ if (ntohs(iph->tot_len) - IPV4_HLEN(iph) < sizeof(struct bcmicmp_hdr)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+bool
+dhd_match_pkt_type(dhd_pub_t *dhd, uint8 *pktdata, uint32 pktlen)
+{
+ struct ether_header *eh;
+ uint16 ether_type;
+ bool match = FALSE;
+
+ if (!pktdata || pktlen < ETHER_HDR_LEN) {
+ return match;
+ }
+
+ eh = (struct ether_header *)pktdata;
+ ether_type = ntoh16(eh->ether_type);
+ if ((dhd->conf->enq_hdr_pkt & ENQ_PKT_TYPE_EAPOL) &&
+ ether_type == ETHER_TYPE_802_1X) {
+ match = dhd_is_eapol_pkt(dhd, pktdata, pktlen);
+ }
+ else if ((dhd->conf->enq_hdr_pkt & ENQ_PKT_TYPE_ARP) &&
+ ntoh16(eh->ether_type) == ETHER_TYPE_ARP) {
+ match = dhd_is_arp_pkt(dhd, pktdata);
+ }
+ else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
+ if (dhd->conf->enq_hdr_pkt & ENQ_PKT_TYPE_ICMP)
+ match = dhd_is_icmp_pkt(dhd, pktdata, pktlen);
+ if (!match && dhd->conf->enq_hdr_pkt & ENQ_PKT_TYPE_DHCP)
+ match = dhd_is_dhcp_pkt(dhd, pktdata);
+ }
+
+ return match;
+}
+#endif /* BCMPCIE */
extern msg_eapol_t dhd_is_4way_msg(uint8 *pktdata);
extern void dhd_dump_pkt(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
uint32 pktlen, bool tx, uint32 *pkthash, uint16 *pktfate);
+#ifdef BCMPCIE
+extern bool dhd_match_pkt_type(dhd_pub_t *dhd, uint8 *pktdata, uint32 pktlen);
+#endif /* BCMPCIE */
#ifdef DHD_PKTDUMP_ROAM
extern void dhd_dump_mod_pkt_timer(dhd_pub_t *dhdp, uint16 rsn);
extern void dhd_dump_pkt_init(dhd_pub_t *dhdp);
#else
#include <dhd_plat.h>
#endif /* CONFIG_WIFI_CONTROL_FUNC */
-#ifdef BCMDBUS
-#include <dbus.h>
-#endif
#ifdef CONFIG_DTS
#include<linux/regulator/consumer.h>
#include<linux/of_gpio.h>
return NULL;
plat_data = adapter->wifi_plat_data;
if (plat_data->mem_prealloc) {
-#ifdef BCMDHD_MDRIVER
+#if defined(BCMDHD_MDRIVER) && !defined(DHD_STATIC_IN_DRIVER)
alloc_ptr = plat_data->mem_prealloc(adapter->bus_type, adapter->index, section, size);
#else
alloc_ptr = plat_data->mem_prealloc(section, size);
return -ENOMEM;
}
adapter->name = "DHD generic adapter";
- adapter->index = -1;
-#ifdef BCMDHD_MDRIVER
-#ifdef BCMSDIO
adapter->index = 0;
-#elif defined(BCMPCIE)
- adapter->index = 1;
-#elif defined(BCMDBUS)
- adapter->index = 2;
-#endif
-#endif
adapter->bus_type = -1;
adapter->bus_num = -1;
adapter->slot_num = -1;
err = dhd_bus_register();
} else {
#ifdef DHD_SUPPORT_HDM
- if (dhd_download_fw_on_driverload || hdm_trigger_init) {
+ if (dhd_download_fw_on_driverload || hdm_trigger_init)
#else
- if (dhd_download_fw_on_driverload) {
+ if (dhd_download_fw_on_driverload)
#endif /* DHD_SUPPORT_HDM */
+ {
/* power up all adapters */
for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
int retry = POWERUP_MAX_RETRY;
for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
bool chip_up = FALSE;
int retry = POWERUP_MAX_RETRY;
+#ifndef DHD_INSMOD_NOWAIT
struct semaphore dhd_chipup_sem;
+#endif
adapter = &dhd_wifi_platdata->adapters[i];
adapter->bus_type, adapter->bus_num, adapter->slot_num));
do {
+#ifdef DHD_INSMOD_NOWAIT
+ err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);
+ if (err) {
+ DHD_ERROR(("%s: wifi pwr on error ! \n", __FUNCTION__));
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ continue;
+ } else {
+ wifi_platform_bus_enumerate(adapter, TRUE);
+ chip_up = TRUE;
+ break;
+ }
+#else
#ifndef CUSTOMER_HW_AMLOGIC
sema_init(&dhd_chipup_sem, 0);
err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem);
dhd_bus_unreg_sdio_notify();
wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
wifi_platform_bus_enumerate(adapter, FALSE);
+#endif
} while (retry--);
if (!chip_up) {
goto fail;
}
+#ifndef DHD_INSMOD_NOWAIT
/*
* Wait till MMC sdio_register_driver callback called and made driver attach.
* It's needed to make sync up exit from dhd insmod and
dhd_bus_unregister();
goto fail;
}
+#endif
return err;
wifi_adapter_info_t *adapter;
s32 timeout = -1;
int i;
- enum wifi_adapter_status wait_status;
#endif
#if !defined(DHD_PRELOAD)
adapter = &dhd_wifi_platdata->adapters[i];
wifi_platform_set_power(adapter, FALSE, 0);
if (err) {
- DHD_ERROR(("failed to wifi_platform_set_power on %s\n", adapter->name));
+ DHD_ERROR(("failed to wifi_platform_set_power off %s\n", adapter->name));
goto exit;
}
}
DHD_ERROR(("failed to wifi_platform_set_power on %s\n", adapter->name));
goto fail;
}
- if (dhd_download_fw_on_driverload)
- wait_status = WIFI_STATUS_ATTACH;
- else
- wait_status = WIFI_STATUS_DETTACH;
timeout = wait_event_interruptible_timeout(adapter->status_event,
- wifi_get_adapter_status(adapter, wait_status),
+ wifi_get_adapter_status(adapter, WIFI_STATUS_NET_ATTACHED),
msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));
if (timeout <= 0) {
err = -1;
#include "dhdioctl.h"
#include <sdiovar.h>
-#ifdef BCMDBUS
-#include <dbus.h>
-#define BUS_IOVAR_OP(a, b, c, d, e, f, g) dbus_iovar_op(a->dbus, b, c, d, e, f, g)
-#else
#include <dhd_bus.h>
#define BUS_IOVAR_OP dhd_bus_iovar_op
-#endif
typedef struct _macdbg_info_t {
dhd_pub_t *dhdp;
#include <dhd.h>
#include <dhd_proto.h>
-#ifdef BCMDBUS
-#include <dbus.h>
-#else
#include <dhd_bus.h>
-#endif /* BCMDBUS */
#include <dhd_dbg.h>
#include <siutils.h>
#if defined(DHD_CONTROL_PCIE_CPUCORE_WIFI_TURNON)
#include <dhd_linux_priv.h>
#endif /* DHD_CONTROL_PCIE_CPUCORE_WIFI_TURNON */
+#include <dhd_linux_pktdump.h>
#define EXTENDED_PCIE_DEBUG_DUMP 1 /* Enable Extended pcie registers dump */
}
#endif /* BCMINTERNAL */
+#ifdef DHD_LINUX_STD_FW_API
+static int
+dhdpcie_download_code_file(struct dhd_bus *bus, char *pfw_path)
+{
+ int bcmerror = BCME_ERROR;
+ int offset = 0;
+ int len = 0;
+ bool store_reset;
+ int offset_end = bus->ramsize;
+ const struct firmware *fw = NULL;
+ int buf_offset = 0, residual_len = 0;
+#ifdef CHECK_DOWNLOAD_FW
+ uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct
+#endif
+
+#if defined(DHD_FW_MEM_CORRUPTION)
+ if (dhd_bus_get_fw_mode(bus->dhd) == DHD_FLAG_MFG_MODE) {
+ dhd_tcm_test_enable = TRUE;
+ } else {
+ dhd_tcm_test_enable = FALSE;
+ }
+#endif /* DHD_FW_MEM_CORRUPTION */
+ DHD_ERROR(("%s: dhd_tcm_test_enable %u\n", __FUNCTION__, dhd_tcm_test_enable));
+ /* TCM check */
+ if (dhd_tcm_test_enable && !dhd_bus_tcm_test(bus)) {
+ DHD_ERROR(("dhd_bus_tcm_test failed\n"));
+ bcmerror = BCME_ERROR;
+ goto err;
+ }
+
+ DHD_ERROR(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
+
+ /* check if CR4/CA7 */
+ store_reset = (si_setcore(bus->sih, ARMCR4_CORE_ID, 0) ||
+ si_setcore(bus->sih, ARMCA7_CORE_ID, 0));
+
+ bcmerror = dhd_os_get_img_fwreq(&fw, bus->fw_path);
+ if (bcmerror < 0) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ bcmerror));
+ goto err;
+ }
+#ifdef CHECK_DOWNLOAD_FW
+ if (bus->dhd->conf->fwchk) {
+ memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
+ if (memptr_tmp == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
+ goto err;
+ }
+ }
+#endif
+ residual_len = fw->size;
+ while (residual_len) {
+ len = MIN(residual_len, MEMBLOCK);
+
+ /* if address is 0, store the reset instruction to be written in 0 */
+ if (store_reset) {
+ ASSERT(offset == 0);
+ bus->resetinstr = *(((uint32*)fw->data + buf_offset));
+ /* Add start of RAM address to the address given by user */
+ offset += bus->dongle_ram_base;
+ offset_end += offset;
+ store_reset = FALSE;
+ }
+
+ bcmerror = dhdpcie_bus_membytes(bus, TRUE, offset,
+ (uint8 *)fw->data + buf_offset, len);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, MEMBLOCK, offset));
+ goto err;
+ }
+#ifdef CHECK_DOWNLOAD_FW
+ if (bus->dhd->conf->fwchk) {
+ bcmerror = dhdpcie_bus_membytes(bus, FALSE, offset, memptr_tmp, len);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, MEMBLOCK, offset));
+ goto err;
+ }
+ if (memcmp(memptr_tmp, (uint8 *)fw->data + buf_offset, len)) {
+ DHD_ERROR(("%s: Downloaded image is corrupted at 0x%08x\n", __FUNCTION__, offset));
+ bcmerror = BCME_ERROR;
+ goto err;
+ } else
+ DHD_INFO(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__));
+ }
+#endif
+ offset += MEMBLOCK;
+
+ if (offset >= offset_end) {
+ DHD_ERROR(("%s: invalid address access to %x (offset end: %x)\n",
+ __FUNCTION__, offset, offset_end));
+ bcmerror = BCME_ERROR;
+ goto err;
+ }
+ residual_len -= len;
+ buf_offset += len;
+ }
+err:
+#ifdef CHECK_DOWNLOAD_FW
+ if (memptr_tmp)
+ MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN);
+#endif
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+ return bcmerror;
+} /* dhdpcie_download_code_file */
+
+#else
+
/**
* Downloads a file containing firmware into dongle memory. In case of a .bea file, the DHD
* is updated with the event logging partitions within that file as well.
return bcmerror;
} /* dhdpcie_download_code_file */
+#endif /* DHD_LINUX_STD_FW_API */
#ifdef CUSTOMER_HW4_DEBUG
#define MIN_NVRAMVARS_SIZE 128
dhdpcie_download_nvram(struct dhd_bus *bus)
{
int bcmerror = BCME_ERROR;
- uint len;
+ uint len, memblock_len = 0;
char * memblock = NULL;
char *bufp;
char *pnv_path;
} else {
nvram_uefi_exists = TRUE;
}
+#ifdef DHD_LINUX_STD_FW_API
+ memblock_len = len;
+#else
+ memblock_len = MAX_NVRAMBUF_SIZE;
+#endif /* DHD_LINUX_STD_FW_API */
DHD_ERROR(("%s: dhd_get_download_buffer len %d\n", __FUNCTION__, len));
if (local_alloc) {
MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
} else {
- dhd_free_download_buffer(bus->dhd, memblock, MAX_NVRAMBUF_SIZE);
+ dhd_free_download_buffer(bus->dhd, memblock, memblock_len);
}
}
void *ntxp = NULL;
uint8 prio = PKTPRIO(txp);
#endif
+ uint8 *pktdata = (uint8 *)PKTDATA(bus->dhd->osh, txp);
if (!bus->dhd->flowid_allocator) {
DHD_ERROR(("%s: Flow ring not intited yet \n", __FUNCTION__));
}
}
#else /* !(defined(BCM_ROUTER_DHD) && defined(HNDCTF)) */
+ if (dhd_match_pkt_type(bus->dhd, pktdata, (uint32)PKTLEN(bus->dhd->osh, txp))) {
+ if ((ret = dhd_flow_queue_enqueue_head(bus->dhd, queue, txp)) != BCME_OK)
+ txp_pend = txp;
+ } else
if ((ret = dhd_flow_queue_enqueue(bus->dhd, queue, txp)) != BCME_OK)
txp_pend = txp;
#endif /* defined(BCM_ROUTER_DHD) && defined(HNDCTF */
}
}
#else /* !(defined(BCM_ROUTER_DHD) && defined(HNDCTF)) */
+ if (dhd_match_pkt_type(bus->dhd, pktdata, (uint32)PKTLEN(bus->dhd->osh, txp))) {
+ if ((ret = dhd_flow_queue_enqueue_head(bus->dhd, queue, txp_pend)) != BCME_OK) {
+ DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
+ txp = txp_pend;
+ goto toss;
+ }
+ } else
if ((ret = dhd_flow_queue_enqueue(bus->dhd, queue, txp_pend)) != BCME_OK) {
DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags);
txp = txp_pend;
/* Got D3 Ack. Suspend the bus */
#ifdef OEM_ANDROID
if (active) {
- DHD_ERROR(("%s():Suspend failed because of wakelock"
+ DHD_ERROR(("%s():Suspend failed because of wakelock "
"restoring Dongle to D0\n", __FUNCTION__));
if (bus->dhd->dhd_watchdog_ms_backup) {
static struct pci_driver dhdpcie_driver = {
node: {&dhdpcie_driver.node, &dhdpcie_driver.node},
- name: "pcieh",
+ name: "pcieh"BUS_TYPE,
id_table: dhdpcie_pci_devid,
probe: dhdpcie_pci_probe,
remove: dhdpcie_pci_remove,
{
dhd_bus_t *bus = dhdpcie_info->bus;
struct pci_dev *pdev = dhdpcie_info->bus->dev;
- int host_irq_disabled;
+ int host_irq_disabled, err = 0;
if (!bus->irq_registered) {
snprintf(dhdpcie_info->pciname, sizeof(dhdpcie_info->pciname),
}
if (bus->d2h_intr_method == PCIE_MSI)
- printf("%s: MSI enabled\n", __FUNCTION__);
+ printf("%s: MSI enabled, irq=%d\n", __FUNCTION__, pdev->irq);
else
- printf("%s: INTx enabled\n", __FUNCTION__);
+ printf("%s: INTx enabled, irq=%d\n", __FUNCTION__, pdev->irq);
- if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED,
- dhdpcie_info->pciname, bus) < 0) {
- DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
+ err = request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED,
+ dhdpcie_info->pciname, bus);
+ if (err < 0) {
+ DHD_ERROR(("%s: request_irq() failed with %d\n", __FUNCTION__, err));
if (bus->d2h_intr_method == PCIE_MSI) {
dhdpcie_disable_msi(pdev);
}
adapter->bus_num = pdev->bus->number;
adapter->slot_num = PCI_SLOT(pdev->devfn);
adapter->pci_dev = pdev;
- } else
+ } else {
DHD_ERROR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
+#ifdef ADAPTER_IDX
+ break;
+#endif
+ }
osl_static_mem_init(osh, adapter);
/* allocate linux spcific pcie structure here */
if (dhdpcie_info)
dhdpcie_detach(dhdpcie_info);
- pci_disable_device(pdev);
+ if (adapter)
+ pci_disable_device(pdev);
if (osh)
osl_detach(osh);
if (adapter != NULL) {
int
dhdpcie_irq_disabled(dhd_bus_t *bus)
{
- struct irq_desc *desc = irq_to_desc(bus->dev->irq);
+ struct irq_desc *desc = NULL;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0))
+ desc = irq_data_to_desc(irq_get_irq_data(bus->dev->irq));
+#else
+ desc = irq_to_desc(bus->dev->irq);
+#endif // (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
/* depth will be zero, if enabled */
return desc->depth;
}
dhd_bus_mem_dump(g_dhd_bus->dhd);
return 0;
}
+#ifndef BCMDHD_MDRIVER
EXPORT_SYMBOL(dhd_dongle_mem_dump);
+#endif
#endif /* DHD_FW_COREDUMP */
#ifdef CONFIG_ARCH_MSM
return isup;
}
+#ifndef BCMDHD_MDRIVER
EXPORT_SYMBOL(dhd_bus_check_driver_up);
+#endif
set_fs(KERNEL_DS);
file_mode = O_CREAT | O_WRONLY;
- w_pcap_fp = filp_open(pktlogdump_path, file_mode, 0664);
- if (IS_ERR(w_pcap_fp)) {
+ w_pcap_fp = dhd_filp_open(pktlogdump_path, file_mode, 0664);
+ if (IS_ERR(w_pcap_fp) || (w_pcap_fp == NULL)) {
DHD_ERROR(("%s: Couldn't open file '%s' err %ld\n",
__FUNCTION__, pktlogdump_path, PTR_ERR(w_pcap_fp)));
ret = BCME_ERROR;
}
/* Sync file from filesystem to physical media */
- ret = vfs_fsync(w_pcap_fp, 0);
+ ret = dhd_vfs_fsync(w_pcap_fp, 0);
if (ret < 0) {
DHD_ERROR(("%s(): sync pcap file error, err = %d\n", __FUNCTION__, ret));
goto fail;
}
fail:
if (!IS_ERR(w_pcap_fp)) {
- filp_close(w_pcap_fp, NULL);
+ dhd_filp_close(w_pcap_fp, NULL);
}
set_fs(old_fs);
#ifdef DHD_COREDUMP
int (*set_coredump)(const char *buf, int buf_len, const char *info);
#endif /* DHD_COREDUMP */
-#ifdef BCMDHD_MDRIVER
+#if defined(BCMDHD_MDRIVER) && !defined(DHD_STATIC_IN_DRIVER)
void *(*mem_prealloc)(uint bus_type, int index, int section, unsigned long size);
#else
void *(*mem_prealloc)(int section, unsigned long size);
/* Remove any protocol-specific data header. */
extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, void *rxp, uchar *buf, uint *len);
+#ifdef DHD_LOSSLESS_ROAMING
+extern int dhd_update_sdio_data_prio_map(dhd_pub_t *dhdp);
+#endif // DHD_LOSSLESS_ROAMING
+
/* Use protocol to issue ioctl to dongle */
extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len);
#include <dhd_dbg.h>
#include <dhdioctl.h>
#include <sdiovar.h>
+#include <wl_android.h>
#include <dhd_config.h>
#ifdef DHD_PKTDUMP_TOFW
#include <dhd_linux_pktdump.h>
int err = 0;
int try_cnt = 0, try_max = CUSTOM_MAX_KSO_ATTEMPTS;
struct dhd_conf *conf = bus->dhd->conf;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)) && !defined(ANDROID13_KERNEL515_BKPORT)
wifi_adapter_info_t *adapter = NULL;
uint32 bus_type = -1, bus_num = -1, slot_num = -1;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)) && !defined(ANDROID13_KERNEL515_BKPORT)
dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num);
adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
sdio_retune_crc_disable(adapter->sdio_func);
#endif /* !defined(NDIS) */
exit:
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)) && !defined(ANDROID13_KERNEL515_BKPORT)
if (on)
sdio_retune_release(adapter->sdio_func);
sdio_retune_crc_enable(adapter->sdio_func);
#if defined(BCMSDIOH_STD)
uint32 sd3_tuning_disable = FALSE;
#endif /* BCMSDIOH_STD */
+#if defined(WL_EXT_IAPSTA) && defined(DHD_LOSSLESS_ROAMING)
+ int state;
+#endif /* WL_EXT_IAPSTA && DHD_LOSSLESS_ROAMING */
DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
(sleep ? "SLEEP" : "WAKE"),
if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq))
#endif /* DHD_USE_IDLECOUNT */
return BCME_BUSY;
+#if defined(WL_EXT_IAPSTA) && defined(DHD_LOSSLESS_ROAMING)
+ state = wl_ext_any_sta_handshaking(bus->dhd);
+ if (state) {
+ DHD_ERROR(("handshaking %d\n", state));
+ return BCME_BUSY;
+ }
+#endif /* WL_EXT_IAPSTA && DHD_LOSSLESS_ROAMING */
#ifdef BT_OVER_SDIO
/*
/* restore pkt buffer pointer, but keeps the header pushed by dhd_prot_hdrpush */
frame = (uint8*)PKTDATA(osh, pkt);
- DHD_INFO(("%s PKTLEN before postprocess %d",
+ DHD_INFO(("%s PKTLEN before postprocess %d\n",
__FUNCTION__, PKTLEN(osh, pkt)));
/* PKTLEN still includes tail_padding, so exclude it.
return bcmerror;
}
+#if defined(BCMSDIO_RXLIM_POST) || defined(BCMSDIO_TXSEQ_SYNC)
+static void
+dhdsdio_txseq_sync(dhd_bus_t *bus, sdpcm_shared_t *sh)
+{
+ struct dhd_conf *conf = bus->dhd->conf;
+
+ if (sh->flags & SDPCM_SHARED_RXLIM_POST) {
+#ifdef BCMSDIO_RXLIM_POST
+ if (conf->rxlim_en) {
+ if (sh->msgtrace_addr) {
+ bus->rxlim_en = TRUE;
+ bus->rxlim_addr = sh->msgtrace_addr;
+ DHD_INFO(("%s: RXLIM_POST enabled with rxlim_addr=0x%x\n",
+ __FUNCTION__, bus->rxlim_addr));
+ } else {
+ DHD_INFO(("%s: RXLIM_POST not enabled in fw\n", __FUNCTION__));
+ }
+ } else
+#endif /* BCMSDIO_RXLIM_POST */
+#ifdef BCMSDIO_TXSEQ_SYNC
+ if (conf->txseq_sync) {
+ uint8 val = 0;
+ sh->txseq_sync_addr = ltoh32(sh->txseq_sync_addr);
+ DHD_INFO(("%s: TXSEQ_SYNC enabled\n", __FUNCTION__));
+ if (0 == dhdsdio_membytes(bus, FALSE, sh->txseq_sync_addr, (uint8 *)&val, 1)) {
+ if (bus->tx_seq != val) {
+ DHD_INFO(("%s: Sync tx_seq from %d to %d\n",
+ __FUNCTION__, bus->tx_seq, val));
+ bus->tx_seq = val;
+ bus->tx_max = bus->tx_seq + 4;
+ }
+ }
+ } else
+#endif /* BCMSDIO_TXSEQ_SYNC */
+ {
+ DHD_INFO(("%s: rxlim_en and txseq_sync not enabled in config.txt\n", __FUNCTION__));
+ }
+ sh->flags &= ~SDPCM_SHARED_RXLIM_POST;
+ }
+ else {
+#ifdef BCMSDIO_RXLIM_POST
+ bus->rxlim_en = 0;
+#endif /* BCMSDIO_RXLIM_POST */
+#ifdef BCMSDIO_TXSEQ_SYNC
+ conf->txseq_sync = FALSE;
+#endif /* BCMSDIO_TXSEQ_SYNC */
+ DHD_INFO(("%s: TXSEQ_SYNC and RXLIM_POST not supported in fw\n", __FUNCTION__));
+ }
+}
+#endif /* BCMSDIO_RXLIM_POST || BCMSDIO_TXSEQ_SYNC */
+
static int
dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
{
sh->console_addr = ltoh32(sh->console_addr);
sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
-#ifdef BCMSDIO_RXLIM_POST
- if (sh->flags & SDPCM_SHARED_RXLIM_POST) {
- if (bus->dhd->conf->rxlim_en)
- bus->rxlim_en = !!sh->msgtrace_addr;
- bus->rxlim_addr = sh->msgtrace_addr;
- DHD_INFO(("%s: rxlim_en=%d, rxlim enable=%d, rxlim_addr=%d\n",
- __FUNCTION__,
- bus->dhd->conf->rxlim_en, bus->rxlim_en, bus->rxlim_addr));
- sh->flags &= ~SDPCM_SHARED_RXLIM_POST;
- } else {
- bus->rxlim_en = 0;
- DHD_INFO(("%s: FW has no rx limit post support\n", __FUNCTION__));
- }
-#endif /* BCMSDIO_RXLIM_POST */
-
-#ifdef BCMSDIO_TXSEQ_SYNC
- if (bus->dhd->conf->txseq_sync) {
- sh->txseq_sync_addr = ltoh32(sh->txseq_sync_addr);
- if (sh->flags & SDPCM_SHARED_TXSEQ_SYNC) {
- uint8 val = 0;
- DHD_INFO(("%s: TXSEQ_SYNC enabled in fw\n", __FUNCTION__));
- if (0 == dhdsdio_membytes(bus, FALSE, sh->txseq_sync_addr, (uint8 *)&val, 1)) {
- if (bus->tx_seq != val) {
- DHD_INFO(("%s: Sync tx_seq from %d to %d\n",
- __FUNCTION__, bus->tx_seq, val));
- bus->tx_seq = val;
- bus->tx_max = bus->tx_seq + 4;
- }
- }
- sh->flags &= ~SDPCM_SHARED_TXSEQ_SYNC;
- } else {
- bus->dhd->conf->txseq_sync = FALSE;
- }
- }
-#endif /* BCMSDIO_TXSEQ_SYNC */
+#if defined(BCMSDIO_RXLIM_POST) || defined(BCMSDIO_TXSEQ_SYNC)
+ dhdsdio_txseq_sync(bus, sh);
+#endif
/*
* XXX - Allow a sdpcm_shared_t version mismatch between dhd structure
} else if (bus->clkstate == CLK_PENDING) {
/* Awaiting I_CHIPACTIVE; don't resched */
} else if (bus->intstatus || bus->ipend ||
- (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
+ (!bus->fcstate && (pktq_mlen(&bus->txq, ((~bus->flowcontrol)
+#ifdef DHD_LOSSLESS_ROAMING
+ & bus->dhd->dequeue_prec_map
+#endif /* DHD_LOSSLESS_ROAMING */
+ ))) && DATAOK(bus)) ||
PKT_AVAILABLE(bus, bus->intstatus)) { /* Read multiple frames */
resched = TRUE;
}
return irq_num;
}
+#ifdef LINUX
+struct device *dhd_bus_to_dev(struct dhd_bus *bus)
+{
+ return (struct device *)bcmsdh_get_dev(bus->sdh);
+}
+#endif /* LINUX */
+
void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
{
#ifdef LINUX
/* resume all interface network queue. */
dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
}
+ bus->dhd->hostsleep = 2;
DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd);
dhd_os_busbusy_wake(bus->dhd);
DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd);
+ bus->dhd->hostsleep = 0;
bus->dhd->busstate = DHD_BUS_DATA;
dhd_os_busbusy_wake(bus->dhd);
/* resume all interface network queue. */
}
#endif /* BCMEMBEDIMAGE */
+#ifdef DHD_LINUX_STD_FW_API
+static int
+dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
+{
+ int bcmerror = -1;
+ int offset = 0;
+ int len;
+ uint8 *memblock = NULL, *memptr;
+#ifdef CHECK_DOWNLOAD_FW
+ uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct
+#endif
+ uint memblock_size = MEMBLOCK;
+#ifdef DHD_DEBUG_DOWNLOADTIME
+ unsigned long initial_jiffies = 0;
+ uint firmware_sz = 0;
+#endif
+ int offset_end = bus->ramsize;
+ const struct firmware *fw = NULL;
+ int buf_offset = 0, residual_len = 0;
+
+ DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
+
+ /* XXX: Should succeed in opening image if it is actually given through registry
+ * entry or in module param.
+ */
+ bcmerror = dhd_os_get_img_fwreq(&fw, bus->fw_path);
+ if (bcmerror < 0) {
+ DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
+ bcmerror));
+ goto err;
+ }
+ residual_len = fw->size;
+
+ /* Update the dongle image download block size depending on the F1 block size */
+#ifndef NDIS
+ if (sd_f1_blocksize == 512)
+ memblock_size = MAX_MEMBLOCK;
+#endif /* !NDIS */
+
+ memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
+ if (memblock == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
+ memblock_size));
+ goto err;
+ }
+ if ((uint32)(uintptr)memblock % DHD_SDALIGN)
+ memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
+
+#ifdef CHECK_DOWNLOAD_FW
+ if (bus->dhd->conf->fwchk) {
+ memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
+ if (memptr_tmp == NULL) {
+ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
+ goto err;
+ }
+ }
+#endif
+
+#ifdef DHD_DEBUG_DOWNLOADTIME
+ initial_jiffies = jiffies;
+#endif
+
+ /* Download image */
+ while (residual_len) {
+ len = MIN(residual_len, memblock_size);
+ bcopy((uint8 *)fw->data + buf_offset, (uint8 *)memptr, len);
+ /* check if CR4 */
+ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
+ /* if address is 0, store the reset instruction to be written in 0 */
+
+ if (offset == 0) {
+ bus->resetinstr = *(((uint32*)memptr));
+ /* Add start of RAM address to the address given by user */
+ offset += bus->dongle_ram_base;
+ offset_end += offset;
+ }
+ }
+
+ bcmerror = dhdsdio_membytes(bus, TRUE, offset, (uint8 *)memptr, len);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, memblock_size, offset));
+ goto err;
+ }
+
+#ifdef CHECK_DOWNLOAD_FW
+ if (bus->dhd->conf->fwchk) {
+ bcmerror = dhdsdio_membytes(bus, FALSE, offset, memptr_tmp, len);
+ if (bcmerror) {
+ DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
+ __FUNCTION__, bcmerror, MEMBLOCK, offset));
+ goto err;
+ }
+ if (memcmp(memptr_tmp, memptr, len)) {
+ DHD_ERROR(("%s: Downloaded image is corrupted at 0x%08x\n", __FUNCTION__, offset));
+ bcmerror = BCME_ERROR;
+ goto err;
+ } else
+ DHD_INFO(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__));
+ }
+#endif
+
+ offset += memblock_size;
+#ifdef DHD_DEBUG_DOWNLOADTIME
+ firmware_sz += len;
+#endif
+ if (offset >= offset_end) {
+ DHD_ERROR(("%s: invalid address access to %x (offset end: %x)\n",
+ __FUNCTION__, offset, offset_end));
+ bcmerror = BCME_ERROR;
+ goto err;
+ }
+ residual_len -= len;
+ buf_offset += len;
+ }
+
+#ifdef DHD_DEBUG_DOWNLOADTIME
+ DHD_ERROR(("Firmware download time for %u bytes: %u ms\n",
+ firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
+#endif
+
+err:
+ if (memblock)
+ MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
+#ifdef CHECK_DOWNLOAD_FW
+ if (bus->dhd->conf->fwchk) {
+ if (memptr_tmp)
+ MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN);
+ }
+#endif
+
+ if (fw) {
+ dhd_os_close_img_fwreq(fw);
+ }
+
+ return bcmerror;
+}
+#else
static int
dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
{
memblock_size));
goto err;
}
+ if ((uint32)(uintptr)memblock % DHD_SDALIGN)
+ memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
+
#ifdef CHECK_DOWNLOAD_FW
if (bus->dhd->conf->fwchk) {
memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
}
}
#endif
- if ((uint32)(uintptr)memblock % DHD_SDALIGN)
- memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
#ifdef DHD_DEBUG_DOWNLOADTIME
initial_jiffies = jiffies;
return bcmerror;
}
+#endif /* DHD_LINUX_STD_FW_API */
#ifdef DHD_UCODE_DOWNLOAD
/* Currently supported only for the chips in which ucode RAM is AXI addressable */
dhdsdio_download_nvram(struct dhd_bus *bus)
{
int bcmerror = -1;
- uint len;
- void * image = NULL;
+ uint len, memblock_len = 0;
char * memblock = NULL;
char *bufp;
char *pnv_path;
nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
- /* For Get nvram from UEFI */
- if (nvram_file_exists) {
- image = dhd_os_open_image1(bus->dhd, pnv_path);
- if (image == NULL) {
- printf("%s: Open nvram file failed %s\n", __FUNCTION__, pnv_path);
- goto err;
- }
- }
+ len = MAX_NVRAMBUF_SIZE;
+ if (nvram_file_exists)
+ bcmerror = dhd_get_download_buffer(bus->dhd, pnv_path, NVRAM, &memblock,
+ (int *)&len);
+ else
+ bcmerror = dhd_get_download_buffer(bus->dhd, NULL, NVRAM, &memblock, (int *)&len);
- memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE);
- if (memblock == NULL) {
- DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
- __FUNCTION__, MAX_NVRAMBUF_SIZE));
+ if (bcmerror != BCME_OK)
goto err;
- }
- /* For Get nvram from image or UEFI (when image == NULL ) */
- len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image);
+#ifdef DHD_LINUX_STD_FW_API
+ memblock_len = len;
+#else
+ memblock_len = MAX_NVRAMBUF_SIZE;
+#endif /* DHD_LINUX_STD_FW_API */
if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
bufp = (char *)memblock;
err:
if (memblock)
- MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
-
- if (image)
- dhd_os_close_image1(bus->dhd, image);
+ dhd_free_download_buffer(bus->dhd, memblock, memblock_len);
return bcmerror;
}
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
- * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * drivers/amlogic/wifi/dhd_static_buf.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
*/
+#define pr_fmt(fmt) "Wifi: %s: " fmt, __func__
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/skbuff.h>
-#include <linux/amlogic/wlan_plat.h>
+#include <linux/wlan_plat.h>
#include <linux/amlogic/dhd_buf.h>
-#define DHD_STATIC_VERSION_STR "101.10.361.16 (wlan=r892223-20220401-1)"
+#define DHD_STATIC_VERSION_STR "101.10.361.18 (wlan=r892223-20220519-1)"
#define STATIC_ERROR_LEVEL (1 << 0)
#define STATIC_TRACE_LEVEL (1 << 1)
#define STATIC_MSG_LEVEL (1 << 0)
void *wlan_static_nan_event_ring_buf[MAX_NUM_ADAPTERS] = {NULL};
#if defined(BCMDHD_SDIO) || defined(BCMDHD_PCIE)
-static struct sk_buff *wlan_static_skb[MAX_NUM_ADAPTERS][WLAN_SKB_BUF_NUM];
+static struct sk_buff *wlan_static_skb[MAX_NUM_ADAPTERS][WLAN_SKB_BUF_NUM] = {NULL};
#endif /* BCMDHD_SDIO | BCMDHD_PCIE */
void *
bcmdhd_mem_prealloc(
-#ifdef BCMDHD_MDRIVER
+#if defined(BCMDHD_MDRIVER) && !defined(DHD_STATIC_IN_DRIVER)
uint bus_type, int index,
#endif
int section, unsigned long size)
{
-#ifndef BCMDHD_MDRIVER
+#if !defined(BCMDHD_MDRIVER) || defined(DHD_STATIC_IN_DRIVER)
int index = 0;
#endif
-#ifdef BCMDHD_MDRIVER
+#if defined(BCMDHD_MDRIVER) && !defined(DHD_STATIC_IN_DRIVER)
DHD_STATIC_MSG("bus_type %d, index %d, sectoin %d, size %ld\n",
bus_type, index, section, size);
#else
return NULL;
}
+#ifndef DHD_STATIC_IN_DRIVER
EXPORT_SYMBOL(bcmdhd_mem_prealloc);
+#endif
static void
dhd_deinit_wlan_mem(int index)
#ifdef DHD_STATIC_IN_DRIVER
int
#else
-static int __init
+int
#endif
-bcmdhd_init_wlan_mem(unsigned int all_buf))
+bcmdhd_init_wlan_mem(unsigned int all_buf)
{
int i, ret = 0;
dhd_deinit_wlan_mem(i);
}
- return 0;
+ return ret;
}
#ifdef DHD_STATIC_IN_DRIVER
dhdp = (dhd_pub_t *)ctx->dhdp;
ASSERT(dhdp);
+ if (if_id >= WLFC_MAX_IFNUM)
+ return;
+
if (dhdp->skip_fc && dhdp->skip_fc((void *)dhdp, if_id))
return;
#ifndef _bcmdefs_h_
#define _bcmdefs_h_
+#ifndef BCM_FLEX_ARRAY
+#define BCM_FLEX_ARRAY (1)
+#endif /* BCM_FLEX_ARRAY */
+
/*
* One doesn't need to include this file explicitly, gets included automatically if
* typedefs.h is included.
#define WLC_E_AP_BCN_DRIFT 192 /* Beacon Drift event */
#define WLC_E_PFN_SCAN_ALLGONE_EXT 193 /* last found PFN network gets lost. */
#define WLC_E_AUTH_START 194 /* notify upper layer to start auth */
-#define WLC_E_TWT_TEARDOWN 195 /* TWT Teardown Complete Event */
-#define WLC_E_TWT_INFO_FRM 196 /* TWT Info Event Notification */
-#define WLC_E_LAST 197 /* highest val + 1 for range checking */
-#if (WLC_E_LAST > 197)
-#error "WLC_E_LAST: Invalid value for last event; must be <= 197."
+#define WLC_E_TWT 195 /* TWT event */
+#define WLC_E_LAST 196 /* highest val + 1 for range checking */
+#if (WLC_E_LAST > 196)
+#error "WLC_E_LAST: Invalid value for last event; must be <= 196."
#endif /* WLC_E_LAST */
/* define an API for getting the string name of an event */
uint8 data[]; /* type specific data; could be empty */
} wl_event_fbt_t;
+/* TWT Setup Completion is designed to notify the user of TWT Setup process
+ * status. When 'status' field is value of BCME_OK, the user must check the
+ * 'setup_cmd' field value in 'wl_twt_sdesc_t' structure that at the end of
+ * the event data to see the response from the TWT Responding STA; when
+ * 'status' field is value of BCME_ERROR or non BCME_OK, user must not use
+ * anything from 'wl_twt_sdesc_t' structure as it is the TWT Requesting STA's
+ * own TWT parameter.
+ */
+
+#define WL_TWT_EVENT_HDR_LEN (SIZE_OF(wl_twt_event_t, version) + SIZE_OF(wl_twt_event_t, length))
+#define WL_TWT_EVENT_BASE_LEN sizeof(wl_twt_event_t)
+typedef enum wl_twt_event_type {
+ WL_TWT_EVENT_SETUP = 1,
+ WL_TWT_EVENT_TEARDOWN = 2,
+ WL_TWT_EVENT_INFOFRM = 3,
+ WL_TWT_EVENT_NOTIFY = 4
+} wl_twt_event_type_t;
+
+#define WL_TWT_EVENT_VER 0u
+
+/* WLC_E_TWT event Main-event */
+typedef struct wl_twt_event {
+ uint16 version;
+ uint16 length; /* the byte count of fields from 'event_type' onwards */
+ uint8 event_type; /* See sub event types in wl_twt_event_type_t */
+ uint8 PAD[3];
+ uint8 event_info[];
+} wl_twt_event_t;
+
/* TWT Setup Completion is designed to notify the user of TWT Setup process
* status. When 'status' field is value of BCME_OK, the user must check the
* 'setup_cmd' field value in 'wl_twt_sdesc_t' structure that at the end of
/* TWT Setup Reason code */
typedef enum wl_twt_setup_rc {
- WL_TWT_SETUP_RC_ACCEPT = 0, /* TWT Setup Accepted */
- WL_TWT_SETUP_RC_REJECT = 1, /* TWT Setup Rejected */
- WL_TWT_SETUP_RC_TIMEOUT = 2, /* TWT Setup Time-out */
- WL_TWT_SETUP_RC_IE = 3, /* TWT Setup IE Validation failed */
- WL_TWT_SETUP_RC_PARAMS = 4, /* TWT Setup IE Params invalid */
- WL_TWT_SETUP_RC_ERROR = 5, /* Generic Error cases */
+ WL_TWT_SETUP_RC_ACCEPT = 0u, /* TWT Setup Accepted */
+ WL_TWT_SETUP_RC_REJECT = 1u, /* TWT Setup Rejected */
+ WL_TWT_SETUP_RC_TIMEOUT = 2u, /* TWT Setup Time-out */
+ WL_TWT_SETUP_RC_IE = 3u, /* TWT Setup IE Validation failed */
+ WL_TWT_SETUP_RC_PARAMS = 4u, /* TWT Setup IE Params invalid */
+ /* Any new reason code add before this */
+ WL_TWT_SETUP_RC_ERROR = 255u, /* Generic Error cases */
} wl_twt_setup_rc_t;
/* TWT Setup Completion event data */
uint16 length; /* the byte count of fields from 'dialog' onwards */
uint8 dialog; /* Setup frame dialog token */
uint8 reason_code; /* see WL_TWT_SETUP_RC_XXXX */
- uint8 pad[2];
+ uint8 configID; /* TWT Configuration ID */
+ uint8 pad[1];
int32 status;
/* wl_twt_sdesc_t desc; - defined in wlioctl.h */
} wl_twt_setup_cplt_t;
/* TWT teardown Reason code */
typedef enum wl_twt_td_rc {
- WL_TWT_TD_RC_SUCCESS = 0, /* Teardown complete Successful */
- WL_TWT_TD_RC_HOST = 1, /* Teardown triggered by Host */
- WL_TWT_TD_RC_PEER = 2, /* Peer initiated teardown */
- WL_TWT_TD_RC_MCHAN = 3, /* Teardown due to MCHAN Active */
- WL_TWT_TD_RC_MCNX = 4, /* Teardown due to MultiConnection */
- WL_TWT_TD_RC_SETUP_FAIL = 5, /* Setup fail midway. Teardown all connections */
- WL_TWT_TD_RC_SCHED = 6, /* Teardown by TWT Scheduler */
- WL_TWT_TD_RC_CSA = 7, /* Teardown due to CSA */
- WL_TWT_TD_RC_BTCX = 8, /* Teardown due to BTCX */
- WL_TWT_TD_RC_ERROR = 9, /* Generic Error cases */
+ WL_TWT_TD_RC_HOST = 0u, /* Teardown triggered by Host */
+ WL_TWT_TD_RC_PEER = 1u, /* Peer initiated teardown */
+ WL_TWT_TD_RC_MCHAN = 2u, /* Teardown due to MCHAN Active */
+ WL_TWT_TD_RC_MCNX = 3u, /* Teardown due to MultiConnection */
+ WL_TWT_TD_RC_CSA = 4u, /* Teardown due to CSA */
+ WL_TWT_TD_RC_BTCX = 5u, /* Teardown due to BTCX */
+ WL_TWT_TD_RC_SETUP_FAIL = 6u, /* Setup fail midway. Teardown all connections */
+ WL_TWT_TD_RC_SCHED = 7u, /* Teardown by TWT Scheduler */
+ /* Any new reason code add before this */
+ WL_TWT_TD_RC_ERROR = 255u, /* Generic Error cases */
} wl_twt_td_rc_t;
/* TWT Teardown complete event data */
typedef struct wl_twt_teardown_cplt {
uint16 version;
- uint16 length; /* the byte count of fields from 'reason_code' onwards */
+ uint16 length; /* the byte count of fields from 'reason_code' onwards */
uint8 reason_code; /* WL_TWT_TD_RC_XXXX */
- uint8 pad[3];
+ uint8 configID; /* TWT Configuration ID */
+ uint8 pad[2];
int32 status;
/* wl_twt_teardesc_t; - defined in wlioctl.h */
} wl_twt_teardown_cplt_t;
/* TWT Info Reason code */
typedef enum wl_twt_info_rc {
- WL_TWT_INFO_RC_HOST = 0, /* Host initiated Info complete */
- WL_TWT_INFO_RC_PEER = 1, /* Peer initiated TWT Info */
- WL_TWT_INFO_RC_ERROR = 2, /* generic error conditions */
+ WL_TWT_INFO_RC_HOST = 0u, /* Host initiated Info complete */
+ WL_TWT_INFO_RC_PEER = 1u, /* Peer initiated TWT Info */
+ /* Any new reason code add before this */
+ WL_TWT_INFO_RC_ERROR = 255u, /* generic error conditions */
} wl_twt_info_rc_t;
/* TWT Info complete event data */
typedef struct wl_twt_info_cplt {
uint16 version;
uint16 length; /* the byte count of fields from 'reason_code' onwards */
- uint8 reason_code; /* WL_TWT_INFO_RC_XXXX */
- uint8 pad[3];
+ uint8 reason_code; /* WL_TWT_INFO_RC_XXXX */
+ uint8 configID; /* TWT Configuration ID */
+ uint8 pad[2];
int32 status;
/* wl_twt_infodesc_t; - defined in wlioctl.h */
} wl_twt_info_cplt_t;
+#define WL_TWT_NOTIFY_VER 0u
+#define WL_TWT_NOTIFY_LEN sizeof(wl_twt_notify_t)
+#define WL_TWT_NOTIFY_HDR_LEN (SIZE_OF(wl_twt_notify_t, version) + SIZE_OF(wl_twt_notify_t, length))
+
+typedef enum wl_twt_notification {
+ WL_TWT_NOTIF_ALLOW_TWT = 1, /* Dongle indication of allowing TWT setup */
+} wl_twt_notification_t;
+
+/* TWT notification event */
+typedef struct wl_twt_notify {
+ uint16 version;
+ uint16 length; /* the byte count of fields from 'reason_code' onwards */
+ uint8 notification;
+ uint8 PAD[3];
+} wl_twt_notify_t;
+
#define WL_INVALID_IE_EVENT_VERSION 0
/* Invalid IE Event data */
extern void bcmsdh_oob_intr_set(bcmsdh_info_t *sdh, bool enable);
extern int bcmsdh_get_oob_intr_num(bcmsdh_info_t *bcmsdh);
#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
+extern void *bcmsdh_get_dev(bcmsdh_info_t *sdh);
extern void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *sdh);
extern void bcmsdh_dev_relax(bcmsdh_info_t *sdh);
extern bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *sdh);
#ifndef __BCMSDH_SDMMC_H__
#define __BCMSDH_SDMMC_H__
-#ifdef BCMDBG
#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0)
#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0)
#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0)
#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0)
#define sd_cost(x) do { if (sd_msglevel & SDH_COST_VAL) printf x; } while (0)
-#else
-#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#define sd_cost(x) do { if (sd_msglevel & SDH_COST_VAL) printf x; } while (0)
-#endif
#define sd_sync_dma(sd, read, nbytes)
#define sd_init_dma(sd)
struct sdio_func *func[SDIOD_MAX_IOFUNCS];
uint sd_clk_rate;
uint txglom_mode; /* Txglom mode: 0 - copy, 1 - multi-descriptor */
+#if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STATIC_COPY_BUF)
+ uint8 *copy_buf;
+#endif
#ifdef PKT_STATICS
uint32 sdio_spent_time_us;
#endif
((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
-#ifdef WL_BAND6G
+#ifdef WL_6G_BAND
#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS2G(chspec) ? WLC_BAND_2G : CHSPEC_IS5G(chspec) ? \
WLC_BAND_5G : WLC_BAND_6G)
#else
DBUS_ERR_RXZLP
};
+#define BCM_OTP_SIZE_43236 84 /* number of 16 bit values */
+#define BCM_OTP_SW_RGN_43236 24 /* start offset of SW config region */
+#define BCM_OTP_ADDR_43236 0x18000800 /* address of otp base */
+
#define ERR_CBMASK_TXFAIL 0x00000001
#define ERR_CBMASK_RXFAIL 0x00000002
#define ERR_CBMASK_ALL 0xFFFFFFFF
* For NDIS60, param2 is WdfDevice
* Under Linux, param1 and param2 are NULL;
*/
-extern int dbus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg,
- void *param1, void *param2);
-extern int dbus_deregister(void);
+//extern int dbus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg,
+// void *param1, void *param2);
+//extern int dbus_deregister(void);
//extern int dbus_download_firmware(dbus_pub_t *pub);
//extern int dbus_up(struct dhd_bus *pub);
extern int dbus_shutdown(dbus_pub_t *pub);
extern void dbus_flowctrl_rx(dbus_pub_t *pub, bool on);
-extern int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf);
+//extern int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf);
extern int dbus_send_buf(dbus_pub_t *pub, uint8 *buf, int len, void *info);
-extern int dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info);
+//extern int dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info);
//extern int dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len);
//extern int dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len);
-extern int dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx);
-extern int dbus_poll_intr(dbus_pub_t *pub);
+//extern int dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx);
+//extern int dbus_poll_intr(dbus_pub_t *pub);
extern int dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats);
extern int dbus_get_device_speed(dbus_pub_t *pub);
extern int dbus_set_config(dbus_pub_t *pub, dbus_config_t *config);
void (*rxerr_indicate)(void *cbarg, bool on);
} dbus_intf_callbacks_t;
+/* callback functions */
+typedef struct {
+ /* probe the device */
+ void *(*probe)(uint16 bus, uint16 slot, uint32 hdrlen);
+ /* remove the device */
+ void (*remove)(void *context);
+ /* can we suspend now */
+ int (*suspend)(void *context);
+ /* resume from suspend */
+ int (*resume)(void *context);
+} dbus_driver_t;
+
/*
* Porting: To support new bus, port these functions below
*/
* Bus specific Interface
* Implemented by dbus_usb.c/dbus_sdio.c
*/
-extern int dbus_bus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg,
- dbus_intf_t **intf, void *param1, void *param2);
+extern int dbus_bus_register(dbus_driver_t *driver, dbus_intf_t **intf);
extern int dbus_bus_deregister(void);
extern void dbus_bus_fw_get(void *bus, uint8 **fw, int *fwlen, int *decomp);
* Bus-specific and OS-specific Interface
* Implemented by dbus_usb_[linux/ndis].c/dbus_sdio_[linux/ndis].c
*/
-extern int dbus_bus_osl_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb,
- void *prarg, dbus_intf_t **intf, void *param1, void *param2);
+extern int dbus_bus_osl_register(dbus_driver_t *driver, dbus_intf_t **intf);
extern int dbus_bus_osl_deregister(void);
/*
extern uint usbdev_bulkin_eps(void);
#if defined(BCM_REQUEST_FW)
extern void *dbus_get_fw_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen, int type,
- uint16 boardtype, uint16 boardrev);
+ uint16 boardtype, uint16 boardrev, char *path);
extern void dbus_release_fw_nvfile(void *firmware);
#endif /* #if defined(BCM_REQUEST_FW) */
#endif /* EHCI_FASTPATH_TX || EHCI_FASTPATH_RX */
void dbus_flowctrl_tx(void *dbi, bool on);
+#ifdef LINUX
+struct device * dbus_get_dev(void);
+#endif /* LINUX */
#endif /* __DBUS_H__ */
#elif (defined (BCMDBG_ASSERT) && !defined (BCMDBG_ASSERT_DISABLED))
#define EPI_VERSION_STR "101.10.361 (wlan=r892223 ASSRT)"
#else
-#define EPI_VERSION_STR "101.10.361.17 (wlan=r892223-20220415-1)(20220705-1)"
+#define EPI_VERSION_STR "101.10.361.24 (wlan=r892223-20220913-1)"
#endif /* BCMINTERNAL */
#endif /* _epivers_h_ */
#define DECLSPEC_ALIGN(x) __attribute__ ((aligned(x)))
/* Linux Kernel: File Operations: start */
-extern void * osl_os_open_image(char * filename);
-extern int osl_os_get_image_block(char * buf, int len, void * image);
-extern void osl_os_close_image(void * image);
-extern int osl_os_image_size(void *image);
+static INLINE void * osl_os_open_image(char * filename)
+ { return NULL; }
+static INLINE void osl_os_close_image(void * image)
+ { return; }
+static INLINE int osl_os_get_image_block(char * buf, int len, void * image)
+ { return 0; }
+static INLINE int osl_os_image_size(void *image)
+ { return 0; }
/* Linux Kernel: File Operations: end */
#ifdef BCMDRIVER
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
#define netdev_tx_t int
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
+#define complete_and_exit(a, b) kthread_complete_and_exit(a, b)
+#else
+#define dev_addr_set(net, addr) memcpy(net->dev_addr, addr, ETHER_ADDR_LEN)
+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(5, 17, 0) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0))
+#define netif_rx_ni(skb) netif_rx(skb)
+#define pci_free_consistent(a, b, c, d) dma_free_coherent(&((struct pci_dev *)a)->dev, b, c, d)
+#define pci_map_single(a, b, c, d) dma_map_single(&((struct pci_dev *)a)->dev, b, c, d)
+#define pci_unmap_single(a, b, c, d) dma_unmap_single(&((struct pci_dev *)a)->dev, b, c, d)
+#define pci_dma_mapping_error(a, b) dma_mapping_error(&((struct pci_dev *)a)->dev, b)
+#ifndef PCI_DMA_TODEVICE
+#define PCI_DMA_TODEVICE 1
+#define PCI_DMA_FROMDEVICE 2
+#endif
+#endif
+
+#ifdef ANDROID_BKPORT
+#if (ANDROID_VERSION >= 13) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 41))
+#define ANDROID13_KERNEL515_BKPORT
+#define CFG80211_BKPORT_MLO
+#endif /* ANDROID_VERSION >= 13 && KERNEL >= 5.15.41 */
+#endif /* ANDROID_BKPORT */
#endif /* _linuxver_h_ */
#define WL_SCAN_PARAMS_SSID_MAX 10
-struct wl_scan_params {
+typedef struct wl_scan_params_v1 {
wlc_ssid_t ssid; /**< default: {0, ""} */
struct ether_addr bssid; /**< default: bcast */
int8 bss_type; /**< default: any,
* parameter portion is assumed, otherwise ssid in
* the fixed portion is ignored
*/
- uint16 channel_list[1]; /**< list of chanspecs */
-};
+ uint16 channel_list[BCM_FLEX_ARRAY];
+} wl_scan_params_v1_t;
+
+/** size of wl_scan_params_v1 not including variable length array */
+#define WL_SCAN_PARAMS_V1_FIXED_SIZE (OFFSETOF(wl_scan_params_v1_t, channel_list))
+#define WL_MAX_ROAMSCAN_V1_DATSZ \
+ (WL_SCAN_PARAMS_V1_FIXED_SIZE + (WL_NUMCHANNELS * sizeof(uint16)))
/* changes in wl_scan_params_v2 as comapred to wl_scan_params (v1)
* unit8 scantype to uint32
#define WL_MAX_ROAMSCAN_V3_DATSZ \
(WL_SCAN_PARAMS_V3_FIXED_SIZE + (WL_NUMCHANNELS * sizeof(uint16)))
-#define ISCAN_REQ_VERSION 1
+#define ISCAN_REQ_VERSION_V1 1
#define ISCAN_REQ_VERSION_V2 2
/** incremental scan struct */
-struct wl_iscan_params {
+typedef struct wl_iscan_params_v1 {
uint32 version;
uint16 action;
uint16 scan_duration;
- struct wl_scan_params params;
-};
+ struct wl_scan_params_v1 params;
+} wl_iscan_params_v1_t;
/** incremental scan struct */
typedef struct wl_iscan_params_v2 {
uint32 buflen;
uint32 version;
uint32 count;
- wl_bss_info_v109_t bss_info[1];
+ wl_bss_info_v109_t bss_info[BCM_FLEX_ARRAY];
} wl_scan_results_v109_t;
+#define WL_SCAN_RESULTS_V109_FIXED_SIZE (OFFSETOF(wl_scan_results_v109_t, bss_info))
typedef struct wl_scan_results_v2 {
uint32 buflen;
} iscan_buf_t;
#endif /* SIMPLE_ISCAN */
#define ESCAN_REQ_VERSION 1
+#define ESCAN_REQ_VERSION_V1 1
#define ESCAN_REQ_VERSION_V2 2
-/** event scan reduces amount of SOC memory needed to store scan results */
-struct wl_escan_params {
+typedef struct wl_escan_params_v1 {
uint32 version;
uint16 action;
uint16 sync_id;
- struct wl_scan_params params;
-};
+ struct wl_scan_params_v1 params;
+} wl_escan_params_v1_t;
typedef struct wl_escan_params_v2 {
uint32 version;
wl_scan_params_v3_t params;
} wl_escan_params_v3_t;
-#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t))
+#define WL_ESCAN_PARAMS_V1_FIXED_SIZE (OFFSETOF(wl_escan_params_v1_t, params) + sizeof(wlc_ssid_t))
#define WL_ESCAN_PARAMS_V2_FIXED_SIZE (OFFSETOF(wl_escan_params_v2_t, params) + sizeof(wlc_ssid_t))
#define WL_ESCAN_PARAMS_V3_FIXED_SIZE (OFFSETOF(wl_escan_params_v3_t, params) + sizeof(wlc_ssid_t))
/* New scan version is defined then change old version of scan to
typedef struct wl_iscan_params_v2 wl_iscan_params_t;
#define WL_SCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_scan_params_t, channel_list))
#else
-typedef struct wl_scan_params wl_scan_params_t;
-typedef struct wl_escan_params wl_escan_params_t;
-typedef struct wl_iscan_params wl_iscan_params_t;
+typedef struct wl_scan_params_v1 wl_scan_params_t;
+typedef struct wl_escan_params_v1 wl_escan_params_t;
+typedef struct wl_iscan_params_v1 wl_iscan_params_t;
#define WL_SCAN_PARAMS_FIXED_SIZE 64
#endif /* WL_SCAN_PARAMS_V3 */
uint32 version;
uint16 sync_id;
uint16 bss_count;
- wl_bss_info_v109_t bss_info[1];
+ wl_bss_info_v109_t bss_info[BCM_FLEX_ARRAY];
} wl_escan_result_v109_t;
+#define WL_ESCAN_RESULTS_V109_FIXED_SIZE (OFFSETOF(wl_escan_result_v109_t, bss_info))
/** event scan reduces amount of SOC memory needed to store scan results */
typedef struct wl_escan_result_v2 {
#define WL_STA_VER_4 4
#define WL_STA_VER_5 5
+#define WL_STA_VER_6 6u
/* FIXME: the user/branch should make the selection! */
#define WL_STA_VER WL_STA_VER_4
#define WL_ICMP_CFG_IPV6_LEN(count) (WL_ICMP_CFG_IPV6_FIXED_LEN + \
((count) * sizeof(struct ipv6_addr)))
+typedef struct wl_mkeep_alive_pkt_v1 {
+ uint16 version; /* Version for mkeep_alive */
+ uint16 length; /* length of fixed parameters in the structure */
+ uint32 period_msec; /* high bit on means immediate send */
+ uint16 len_bytes;
+ uint8 keep_alive_id; /* 0 - 3 for N = 4 */
+ uint8 data[BCM_FLEX_ARRAY];
+} wl_mkeep_alive_pkt_v1_t;
+
typedef struct wl_mkeep_alive_pkt {
uint16 version; /* Version for mkeep_alive */
uint16 length; /* length of fixed parameters in the structure */
uint8 data[1];
} wl_mkeep_alive_pkt_t;
+#define WL_MKEEP_ALIVE_VERSION_1 1u
#define WL_MKEEP_ALIVE_VERSION 1
#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data)
/* 1/2 second precision since idle time is a seconds counter anyway */
*/
/* TWT Setup descriptor */
+
+/* Any change to wl_twt_sdesc is not possible without affecting this ROMed structure
+ * in various current branches. Hence to use new updated structure wl_twt_sdesc_v1
+ * typecast it to wl_twt_sdesc_t and define WL_TWT_SDESC_TYPEDEF_HAS_ALIAS
+ * in required branches
+ */
+#ifndef WL_TWT_SDESC_TYPEDEF_HAS_ALIAS
typedef struct wl_twt_sdesc {
/* Setup Command. */
uint8 setup_cmd; /* See TWT_SETUP_CMD_XXXX in 802.11ah.h */
/* deprecated - to be removed */
uint16 li;
} wl_twt_sdesc_t;
+#endif /* WL_TWT_SDESC_TYPEDEF_HAS_ALIAS */
#define WL_TWT_SETUP_DESC_VER 1u
uint16 version; /* structure version */
uint16 length; /* data length (starting after this field) */
uint8 negotiation_type; /* Negotiation Type: See macros TWT_NEGO_TYPE_X */
- uint8 PAD[3];
+ uint8 configID; /* TWT Configuration ID */
+ uint8 flow_flags; /* Flow Flags Configuration. See WL_TWT_FLOW_FLAG_XXXX */
+ uint8 PAD;
uint32 wake_time_h; /* target wake time - BSS TSF (us) */
uint32 wake_time_l;
uint32 wake_dur; /* target wake duration in unit of microseconds */
uint32 wake_dur_min; /* Min. wake duration allowed for TWT Setup */
uint32 wake_dur_max; /* Max. wake duration allowed for TWT Setup */
uint32 avg_pkt_num; /* Average Number of Packets per interval */
+ uint32 avg_pkt_size; /* Average packet size for TWT SP */
} wl_twt_cdesc_t;
/* Flow flags */
#define WL_TWT_INV_BCAST_ID 0xFFu
#define WL_TWT_INV_FLOW_ID 0xFFu
+#define WL_TWT_INV_CONFIG_ID 0xFFu
+#define WL_TWT_ALL_TWT_CONFIG_ID 0u /* ConfigID 0 corresponds to All TWT */
+
+#define WL_TWT_INV_WAKE_DUR 0xFFFFFFFFu
+#define WL_TWT_INV_WAKE_INT 0xFFFFFFFFu
+#define WL_TWT_INV_PKT_NUM 0xFFFFFFFFu
+#define WL_TWT_INV_PKT_SIZE 0xFFFFFFFFu
+#define WL_TWT_INV_WAKE_TIME 0xFFFFFFFFu
/* auto flow_id */
#define WL_TWT_SETUP_FLOW_ID_AUTO 0xFFu
#define WL_TWT_STATS_MAX_BTWT WL_TWT_MAX_BTWT
#define WL_TWT_STATS_MAX_ITWT WL_TWT_MAX_ITWT
+/* TWT States */
#define WL_TWT_INACTIVE 0u /* Resource is not allotted */
-#define WL_TWT_RESERVED 1u /* Resource is allotted but HEB is not yet programmed */
-#define WL_TWT_ACTIVE 2u /* Resource is allotted and HEB is programmed */
-#define WL_TWT_SUSPEND 3u /* Resource is suspended and HEB released */
+#define WL_TWT_ACTIVE 1u /* Resource is allotted and HEB is programmed */
+#define WL_TWT_SUSPEND 2u /* Resource is suspended and HEB released */
+#define WL_TWT_RESERVED 3u /* Resource is allotted but HEB is not yet programmed */
/* Wake type */
/* TODO: not yet finalized */
uint16 length; /* data length (starting after this field) */
struct ether_addr peer; /* Peer address - leave it all 0s' for AP */
uint8 pad[2];
+#ifndef WL_TWT_SDESC_TYPEDEF_HAS_ALIAS /* Use either legacy structure or
+ * the new versioned structure
+ */
wl_twt_sdesc_t desc; /* Setup Descriptor */
+#else
+ struct wl_twt_sdesc_v1 desc;
+#endif /* WL_TWT_SDESC_TYPEDEF_HAS_ALIAS */
uint16 dialog; /* Deprecated - to be removed */
uint8 pad1[2];
} wl_twt_setup_t;
struct ether_addr peer; /* leave it all 0s' for AP */
wl_twt_teardesc_t teardesc; /* Teardown descriptor */
- /* deprecated - to be removed */
+ /* deprecated - to be removed - Start here */
uint8 flow_flags;
uint8 flow_id;
uint8 bid;
- uint8 pad;
+ /* deprecated - to be removed - End here */
+
+ uint8 configID; /* TWT Configuration ID */
} wl_twt_teardown_t;
/* twt information descriptor */
uint16 length; /* data length (starting after this field) */
/* peer address */
struct ether_addr peer; /* leave it all 0s' for AP */
- uint8 pad[2];
+ uint8 configID; /* TWT Configuration ID */
+ uint8 pad[1];
wl_twt_infodesc_t infodesc; /* information descriptor */
/* deprecated - to be removed */
wl_twt_idesc_t desc;
typedef struct wl_twt_status {
uint8 state; /* TWT State */
uint8 heb_id; /* HEB ID */
- uint8 PAD[2];
+ uint8 configID; /* TWT Configuration ID */
+ uint8 PAD[1];
struct ether_addr peer;
uint8 PAD[2];
- wl_twt_sdesc_t desc; /* TWT Descriptor */
+ uint32 avg_pkt_num; /* Average Packet number per TWT SP Interval */
+ uint32 avg_pkt_size; /* Average Packet size for TWT SP */
+#ifndef WL_TWT_SDESC_TYPEDEF_HAS_ALIAS /* Use either legacy structure or
+ * the new versioned structure
+ */
+ wl_twt_sdesc_t desc; /* Setup Descriptor */
+#else
+ struct wl_twt_sdesc_v1 desc;
+#endif /* WL_TWT_SDESC_TYPEDEF_HAS_ALIAS */
} wl_twt_status_t;
/* wl twt status output */
uint16 version;
uint16 length;
struct ether_addr peer;
- uint8 PAD[2];
+ uint8 configID;
+ uint8 PAD;
} wl_twt_status_cmd_v1_t;
#define WL_TWT_PEER_STATS_VERSION_1 1u
wl_twt_peer_stats_v1_t peer_stats_list[];
} wl_twt_stats_v1_t;
+#define WL_TWT_PEER_STATS_VERSION_2 2u
+typedef struct wl_twt_peer_stats_v2 {
+ uint16 version;
+ uint16 length;
+ struct ether_addr peer;
+ uint8 id; /* TWT session ID */
+ uint8 flow_flags;
+ uint8 configID; /* TWT Configuration ID */
+ uint8 PAD[3];
+ uint32 sp_seq; /* sequence number of the service period */
+ uint32 tx_ucast_pkts; /* Number of unicast Tx packets in TWT SPs */
+ uint32 tx_pkts_min; /* Minimum number of Tx packets in a TWT SP */
+ uint32 tx_pkts_max; /* Maximum number of Tx packets in a TWT SP */
+ uint32 tx_pkts_avg; /* Average number of Tx packets in each TWT SP */
+ uint32 tx_failures; /* Tx packets failure count */
+ uint32 rx_ucast_pkts; /* Number of unicast Rx packets in TWT SPs */
+ uint32 rx_pkts_min; /* Minimum number of Rx packets in a TWT SP */
+ uint32 rx_pkts_max; /* Maximum number of Rx packets in a TWT SP */
+ uint32 rx_pkts_avg; /* Average number of Rx packets in each TWT SP */
+ uint32 rx_pkts_retried; /* retried Rx packets count */
+ uint32 tx_pkt_sz_avg; /* Average Tx packet size in TWT SPs */
+ uint32 rx_pkt_sz_avg; /* Average Rx Packet size in TWT SPs */
+ uint32 eosp_dur_avg; /* Average Wake duration in SPs ended due to EOSP */
+ uint32 eosp_count; /* Count of TWT SPs ended due to EOSP */
+} wl_twt_peer_stats_v2_t;
+
+#define WL_TWT_STATS_VERSION_2 2u
+typedef struct wl_twt_stats_v2 {
+ uint16 version;
+ uint16 length;
+ uint32 num_stats; /* number of peer stats in the peer_stats_list */
+ wl_twt_peer_stats_v2_t peer_stats_list[];
+} wl_twt_stats_v2_t;
+
#define WL_TWT_STATS_CMD_VERSION_1 1
#define WL_TWT_STATS_CMD_FLAGS_RESET (1u << 0u)
/* HE TWT stats command */
uint16 version;
uint16 length;
struct ether_addr peer;
- uint8 PAD[2];
+ uint8 configID; /* TWT Configuration ID */
+ uint8 PAD;
uint16 flags; /* see WL_TWT_STATS_CMD_FLAGS */
uint8 num_fid;
uint8 num_bid;
/* Array bounds covered by ASSERT in osl_attach */
return linuxbcmerrormap[-bcmerror];
}
-#ifdef SHARED_OSL_CMN
-osl_t *
-osl_attach(void *pdev, uint bustype, bool pkttag, void **osl_cmn)
-{
-#else
+
osl_t *
-osl_attach(void *pdev, uint bustype, bool pkttag)
+osl_attach(void *pdev, uint bustype, bool pkttag
+#ifdef SHARED_OSL_CMN
+ , void **osl_cmn
+#endif /* SHARED_OSL_CMN */
+)
{
+#ifndef SHARED_OSL_CMN
void **osl_cmn = NULL;
#endif /* SHARED_OSL_CMN */
osl_t *osh;
return rand;
}
-/* Linux Kernel: File Operations: start */
-void *
-osl_os_open_image(char *filename)
-{
- struct file *fp;
-
- fp = filp_open(filename, O_RDONLY, 0);
- /*
- * 2.6.11 (FC4) supports filp_open() but later revs don't?
- * Alternative:
- * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
- * ???
- */
- if (IS_ERR(fp)) {
- printf("ERROR %ld: Unable to open file %s\n", PTR_ERR(fp), filename);
- fp = NULL;
- }
-
- return fp;
-}
-
-int
-osl_os_get_image_block(char *buf, int len, void *image)
-{
- struct file *fp = (struct file *)image;
- int rdlen;
-
- if (fp == NULL) {
- return 0;
- }
-
- rdlen = kernel_read_compat(fp, fp->f_pos, buf, len);
- if (rdlen > 0) {
- fp->f_pos += rdlen;
- }
-
- return rdlen;
-}
-
-void
-osl_os_close_image(void *image)
-{
- struct file *fp = (struct file *)image;
-
- if (fp != NULL) {
- filp_close(fp, NULL);
- }
-}
-
-int
-osl_os_image_size(void *image)
-{
- int len = 0, curroffset;
-
- if (image) {
- /* store the current offset */
- curroffset = generic_file_llseek(image, 0, 1);
- /* goto end of file to get length */
- len = generic_file_llseek(image, 0, 2);
- /* restore back the offset */
- generic_file_llseek(image, curroffset, 0);
- }
- return len;
-}
-
/* Linux Kernel: File Operations: end */
#if defined(AXI_TIMEOUTS_NIC)
int
kernel_read_compat(struct file *file, loff_t offset, char *addr, unsigned long count)
{
+#ifdef DHD_SUPPORT_VFS_CALL
return (int)kernel_read(file, addr, (size_t)count, &offset);
+#else
+ return 0;
+#endif /* DHD_SUPPORT_VFS_CALL */
}
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) */
#define WL_BSSIDX_MAX 16
#endif /* WL_STATIC_IF */
-uint android_msg_level = ANDROID_ERROR_LEVEL | ANDROID_MSG_LEVEL;
-
#define ANDROID_ERROR_MSG(x, args...) \
do { \
if (android_msg_level & ANDROID_ERROR_LEVEL) { \
#define CMD_TWT_SETUP "TWT_SETUP"
#define CMD_TWT_TEARDOWN "TWT_TEARDOWN"
#define CMD_TWT_INFO "TWT_INFO_FRM"
-#define CMD_TWT_STATUS_QUERY "TWT_STATUS"
-#define CMD_TWT_CAPABILITY "TWT_CAP"
+#define CMD_TWT_STATUS_QUERY "GET_TWT_STATUS"
+#define CMD_TWT_CAPABILITY "GET_TWT_CAP"
+#define CMD_TWT_GET_STATS "GET_TWT_STATISTICS"
+#define CMD_TWT_CLR_STATS "CLEAR_TWT_STATISTICS"
+#define WL_TWT_CMD_INVAL 255
+
+/* setup command name to value conversion */
+static struct {
+ const char *name;
+ uint8 val;
+} setup_cmd_val[] = {
+ {"request", TWT_SETUP_CMD_REQUEST_TWT},
+ {"suggest", TWT_SETUP_CMD_SUGGEST_TWT},
+ {"demand", TWT_SETUP_CMD_DEMAND_TWT},
+ {"accept", TWT_SETUP_CMD_ACCEPT_TWT},
+ {"alternate", TWT_SETUP_CMD_ALTER_TWT},
+ {"reject", TWT_SETUP_CMD_REJECT_TWT}
+};
#endif /* WL_TWT */
/* drv command info structure */
char *command, int total_len);
static int wlc_wbtext_get_roam_prof(struct net_device *ndev, wl_roamprof_band_t *rp,
uint8 band, uint8 *roam_prof_ver, uint8 *roam_prof_size);
+#ifdef WES_SUPPORT
static int wl_android_wbtext_enable(struct net_device *dev, int mode);
+#endif // WES_SUPPORT
#endif /* WBTEXT */
#ifdef WES_SUPPORT
/* wl_roam.c */
#ifdef CUSTOMER_HW4_PRIVATE_CMD
#ifdef ROAM_API
-#ifdef WBTEXT
-static bool wl_android_check_wbtext_support(struct net_device *dev)
-{
- dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
- return dhdp->wbtext_support;
-}
-#endif /* WBTEXT */
-
static bool
wl_android_check_wbtext_policy(struct net_device *dev)
{
return error;
}
+#ifdef WES_SUPPORT
+static bool wl_android_check_wbtext_support(struct net_device *dev)
+{
+ dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(dev);
+ return dhdp->wbtext_support;
+}
+
static int
wl_android_wbtext_enable(struct net_device *dev, int mode)
{
return error;
}
+#endif /* WES_SUPPORT */
static int wl_cfg80211_wbtext_btm_timer_threshold(struct net_device *dev,
char *command, int total_len)
dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY);
#ifdef BCMSDIO
ret = dhd_net_bus_resume(dev, 0);
+ if (ret)
+ goto retry_power;
#endif /* BCMSDIO */
-#ifdef BCMPCIE
ret = dhd_net_bus_devreset(dev, FALSE);
-#endif /* BCMPCIE */
#ifdef WBRC
if (dhdp->dhd_induce_bh_error == DHD_INDUCE_BH_ON_FAIL_ONCE) {
ANDROID_ERROR(("%s: dhd_induce_bh_error = %d\n",
ret = BCME_ERROR;
}
#endif /* WBRC */
+ if (ret)
+ goto retry_power;
+#if defined(BCMSDIO) || defined(BCMDBUS)
+#ifdef BCMSDIO
+ dhd_net_bus_resume(dev, 1);
+#endif /* BCMSDIO */
+ ret = dhd_dev_init_ioctl(dev);
+ if (ret < 0) {
+ goto retry_bus;
+ }
+#endif /* BCMSDIO || BCMDBUS */
if (ret == 0) {
break;
}
+#if defined(BCMSDIO) || defined(BCMDBUS)
+retry_bus:
+#ifdef BCMSDIO
+ dhd_net_bus_suspend(dev);
+#endif /* BCMSDIO */
+#endif /* BCMSDIO || BCMDBUS */
+retry_power:
ANDROID_ERROR(("failed to power up wifi chip, retry again (%d left) **\n\n",
retry));
-#ifdef BCMPCIE
dhd_net_bus_devreset(dev, TRUE);
-#endif /* BCMPCIE */
dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
#ifdef WBRC
/* Inform BT reset which will internally wait till BT reset is done */
#endif /* BCM_DETECT_TURN_ON_FAILURE */
goto exit;
}
-#if defined(BCMSDIO) || defined(BCMDBUS)
- ret = dhd_net_bus_devreset(dev, FALSE);
- if (ret)
- goto err;
-#ifdef BCMSDIO
- dhd_net_bus_resume(dev, 1);
-#endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMDBUS */
-#if defined(BCMSDIO) || defined(BCMDBUS)
- if (!ret) {
- if (dhd_dev_init_ioctl(dev) < 0) {
- ret = -EFAULT;
- goto err;
- }
- }
-#endif /* BCMSDIO || BCMDBUS */
g_wifi_on = TRUE;
}
exit:
- WL_MSG(dev->name, "Success\n");
- dhd_net_if_unlock(dev);
- return ret;
-
-#if defined(BCMSDIO) || defined(BCMDBUS)
-err:
- dhd_net_bus_devreset(dev, TRUE);
-#ifdef BCMSDIO
- dhd_net_bus_suspend(dev);
-#endif /* BCMSDIO */
- dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
- WL_MSG(dev->name, "Failed\n");
+ if (ret)
+ WL_MSG(dev->name, "Failed %d\n", ret);
+ else
+ WL_MSG(dev->name, "Success\n");
dhd_net_if_unlock(dev);
return ret;
-#endif /* BCMSDIO || BCMDBUS */
}
int wl_android_wifi_off(struct net_device *dev, bool on_failure)
exit:
#ifdef DHD_SEND_HANG_PRIVCMD_ERRORS
if (ret) {
- /* Avoid incrementing priv_cmd_errors in case of unsupported feature */
- if (ret != BCME_UNSUPPORTED) {
+ /* Avoid incrementing priv_cmd_errors in case of unsupported feature
+ * or BUSY state specific to TWT commands
+ */
+ if (
+#ifdef WL_TWT
+ ((ret != BCME_BUSY) &&
+ ((strnicmp(command, CMD_TWT_SETUP, strlen(CMD_TWT_SETUP)) == 0) ||
+ (strnicmp(command, CMD_TWT_TEARDOWN, strlen(CMD_TWT_TEARDOWN)) == 0) ||
+ (strnicmp(command, CMD_TWT_INFO, strlen(CMD_TWT_INFO)) == 0))) ||
+#endif /* WL_TWT */
+ (ret != BCME_UNSUPPORTED)) {
wl_android_check_priv_cmd_errors(net);
}
} else {
#ifdef WL_TWT
+static uint8
+wl_twt_cmd2val(const char *name)
+{
+ uint i;
+
+ for (i = 0; i < ARRAYSIZE(setup_cmd_val); i ++) {
+ if (strcmp(name, setup_cmd_val[i].name) == 0) {
+ return setup_cmd_val[i].val;
+ }
+ }
+
+ return WL_TWT_CMD_INVAL;
+}
+
static int
wl_android_twt_setup(struct net_device *ndev, char *command, int total_len)
{
- wl_twt_config_t val;
- s32 bw;
+ wl_twt_setup_t val;
+ s32 bw = 0;
char *token, *pos;
u8 mybuf[WLC_IOCTL_SMLEN] = {0};
u8 resp_buf[WLC_IOCTL_SMLEN] = {0};
- u64 twt;
uint8 *rem = mybuf;
uint16 rem_len = sizeof(mybuf);
- int32 val32;
+ uint8 tmp;
WL_DBG_MEM(("Enter. cmd:%s\n", command));
val.version = WL_TWT_SETUP_VER;
val.length = sizeof(val.version) + sizeof(val.length);
- /* Default values, Overide Below */
- val.desc.wake_time_h = 0xFFFFFFFF;
- val.desc.wake_time_l = 0xFFFFFFFF;
- val.desc.wake_int_min = 0xFFFFFFFF;
- val.desc.wake_int_max = 0xFFFFFFFF;
- val.desc.wake_dur_min = 0xFFFFFFFF;
- val.desc.wake_dur_max = 0xFFFFFFFF;
- val.desc.avg_pkt_num = 0xFFFFFFFF;
+ val.desc.bid = WL_TWT_INV_BCAST_ID;
+ val.desc.flow_id = WL_TWT_INV_FLOW_ID;
+ val.desc.btwt_persistence = WL_TWT_INFINITE_BTWT_PERSIST;
+ val.desc.wake_type = WL_TWT_TIME_TYPE_AUTO;
pos = command + sizeof(CMD_TWT_SETUP);
- /* negotiation_type */
+ /* setup_cmd */
token = strsep((char**)&pos, " ");
if (!token) {
- ANDROID_ERROR(("Mandatory param negotiation type not present\n"));
+ ANDROID_ERROR(("Mandaory param setup_cmd not present\n"));
bw = -EINVAL;
goto exit;
}
- val.desc.negotiation_type = htod32((u32)bcm_atoi(token));
- /* Wake Duration */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("Mandatory param wake Duration not present\n"));
- bw = -EINVAL;
- goto exit;
+ val.desc.setup_cmd = wl_twt_cmd2val(token);
+ if (val.desc.setup_cmd == WL_TWT_CMD_INVAL) {
+ ANDROID_ERROR(("Unrecognized TWT Setup command '%s'\n", token));
}
- val.desc.wake_dur = htod32((u32)bcm_atoi(token));
+ ANDROID_INFO(("TWT_SETUP val.desc.setup_cmd %s\n", token));
- /* Wake interval */
+ /* negotiation_type */
token = strsep((char**)&pos, " ");
if (!token) {
- ANDROID_ERROR(("Mandaory param Wake Interval not present\n"));
+ ANDROID_ERROR(("Mandatory param negotiation type not present\n"));
bw = -EINVAL;
goto exit;
}
- val.desc.wake_int = htod32((u32)bcm_atoi(token));
-
- /* Wake Time parameter */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("No Wake Time parameter provided, using default\n"));
- } else {
- twt = (u64)bcm_atoi(token);
- val32 = htod32((u32)(twt >> 32));
- if ((val32 != -1) && ((int32)(htod32((u32)twt)) != -1)) {
- val.desc.wake_time_h = htod32((u32)(twt >> 32));
- val.desc.wake_time_l = htod32((u32)twt);
- }
- }
+ val.desc.negotiation_type = htod32((u32)bcm_atoi(token));
+ ANDROID_INFO(("TWT_SETUP val.desc.negotiation_type %d\n", val.desc.negotiation_type));
- /* Minimum allowed Wake interval */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("No Minimum allowed Wake interval provided, using default\n"));
- } else {
- val32 = htod32((u32)bcm_atoi(token));
- if (val32 != -1) {
- val.desc.wake_int_min = htod32((u32)bcm_atoi(token));
- }
- }
-
- /* Max Allowed Wake interval */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("Maximum allowed Wake interval not provided, using default\n"));
- } else {
- val32 = htod32((u32)bcm_atoi(token));
- if (val32 != -1) {
- val.desc.wake_int_max = htod32((u32)bcm_atoi(token));
- }
- }
-
- /* Minimum allowed Wake duration */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("Maximum allowed Wake duration not provided, using default\n"));
- } else {
- val32 = htod32((u32)bcm_atoi(token));
- if (val32 != -1) {
- val.desc.wake_dur_min = htod32((u32)bcm_atoi(token));
- }
- }
-
- /* Maximum allowed Wake duration */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("Maximum allowed Wake duration not provided, using default\n"));
- } else {
- val32 = htod32((u32)bcm_atoi(token));
- if (val32 != -1) {
- val.desc.wake_dur_max = htod32((u32)bcm_atoi(token));
- }
- }
+ if (pos != NULL) {
+ ANDROID_INFO(("TWT_SETUP string %s\n", pos));
+ while ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ ANDROID_INFO(("TWT_SETUP token is %s\n", token));
- /* Average number of packets */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("Average number of packets not provided, using default\n"));
- } else {
- val32 = htod32((u32)bcm_atoi(token));
- if (val32 != -1) {
- val.desc.avg_pkt_num = htod32((u32)bcm_atoi(token));
- }
- }
-
- /* a peer_address */
- token = strsep((char**)&pos, " ");
- if (!token) {
- ANDROID_ERROR(("Average number of packets not provided, using default\n"));
- } else {
- /* get peer mac */
- if (!bcm_ether_atoe(token, &val.peer)) {
- ANDROID_ERROR(("%s : Malformed peer addr\n", __FUNCTION__));
- bw = BCME_ERROR;
- goto exit;
+ if (!strnicmp(token, "u", 1)) {
+ val.desc.flow_flags |= WL_TWT_FLOW_FLAG_UNANNOUNCED;
+ }
+ else if (!strnicmp(token, "t", 1)) {
+ val.desc.flow_flags |= WL_TWT_FLOW_FLAG_TRIGGER;
+ }
+ else if (!strnicmp(token, "n", 1)) {
+ val.desc.flow_flags |= WL_TWT_FLOW_FLAG_UNSOLICITED;
+ }
+ else if (!strnicmp(token, "p", 1)) {
+ token++;
+ val.desc.btwt_persistence = (int)simple_strtol(token, NULL, 0);
+ ANDROID_INFO(("TWT_SETUP broadcast persistence %d\n",
+ val.desc.btwt_persistence));
+ }
+ /* Wake Duration */
+ else if (!strnicmp(token, "-d", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ val.desc.wake_dur = (int)simple_strtol(token, NULL, 0);
+ ANDROID_INFO(("TWT_SETUP val.desc.wake_dur %d\n",
+ val.desc.wake_dur));
+ }
+ }
+ /* Wake Interval */
+ else if (!strnicmp(token, "-i", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ val.desc.wake_int = (int)simple_strtol(token, NULL, 0);
+ ANDROID_INFO(("TWT_SETUP val.desc.wake_int %d\n",
+ val.desc.wake_int));
+ }
+ }
+ /* flow id */
+ else if (!strnicmp(token, "-f", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ val.desc.flow_id = (int)simple_strtol(token, NULL, 0);
+ ANDROID_INFO(("TWT_SETUP val.desc.flow_id %d\n",
+ val.desc.flow_id));
+ }
+ }
+ else if (!strnicmp(token, "-b", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ val.desc.bid = (int)simple_strtol(token, NULL, 0);
+ ANDROID_INFO(("TWT_SETUP val.desc.bid %d\n", val.desc.bid));
+ }
+ }
+ else if (!strnicmp(token, "-r", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ tmp = (int)simple_strtol(token, NULL, 0);
+ if (tmp > TWT_BCAST_FRAME_RECOMM_3) {
+ bw = -EINVAL;
+ goto exit;
+ }
+ val.desc.bid = tmp;
+ ANDROID_INFO(("TWT_SETUP frame recommendation %d\n",
+ val.desc.frame_recomm));
+ }
+ }
+ else if (!strnicmp(token, "-s", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ val.desc.duty_cycle_min =
+ (int)simple_strtol(token, NULL, 0);
+ ANDROID_INFO(("TWT_SETUP duty_cycle_min %d\n",
+ val.desc.duty_cycle_min));
+ }
+ }
+ else if (!strnicmp(token, "-v", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ val.desc.wake_int_max = (int)simple_strtol(token, NULL, 0);
+ ANDROID_INFO(("TWT_SETUP wake_int_max %d\n",
+ val.desc.wake_int_max));
+ }
+ }
+ /* a peer_address */
+ else if (!strnicmp(token, "-a", 2)) {
+ if ((token = bcmstrtok(&pos, " ", 0)) != NULL) {
+ if (!bcm_ether_atoe(token, &val.peer)) {
+ ANDROID_ERROR(("%s : Malformed peer addr\n",
+ __FUNCTION__));
+ bw = -EINVAL;
+ goto exit;
+ }
+ }
+ }
}
}
- bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_CONFIG,
+ bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_SETUP,
sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
if (bw != BCME_OK) {
goto exit;
bw = wldev_iovar_setbuf(ndev, "twt",
mybuf, sizeof(mybuf) - rem_len, resp_buf, WLC_IOCTL_SMLEN, NULL);
if (bw < 0) {
- ANDROID_ERROR(("twt config set failed. ret:%d\n", bw));
+ ANDROID_ERROR(("twt setup failed. ret:%d\n", bw));
}
exit:
return bw;
exit:
return bw;
}
+
+/* wl twt stats result display version 2 */
+static int
+wl_android_twt_stats_display_v2(wl_twt_stats_v2_t *stats, char *command, int total_len)
+{
+ u32 i;
+ wl_twt_peer_stats_v2_t *peer_stats;
+ int rem_len = 0, bytes_written = 0;
+
+ rem_len = total_len;
+ for (i = 0; i < stats->num_stats; i++) {
+ peer_stats = &stats->peer_stats_list[i];
+
+ bytes_written = scnprintf(command, rem_len,
+ "%u %u %u %u %u",
+ peer_stats->eosp_dur_avg, peer_stats->tx_pkts_avg, peer_stats->rx_pkts_avg,
+ peer_stats->tx_pkt_sz_avg, peer_stats->rx_pkt_sz_avg);
+ CHECK_SCNPRINTF_RET_VAL(bytes_written);
+ command += bytes_written;
+ rem_len -= bytes_written;
+ }
+
+ if ((total_len - rem_len) > 0) {
+ return (total_len - rem_len);
+ } else {
+ return BCME_ERROR;
+ }
+}
+
+static int
+wl_android_twt_stats(struct net_device *ndev, char *command, int total_len)
+{
+ wl_twt_stats_cmd_v1_t query;
+ wl_twt_stats_v2_t stats_v2;
+ int ret = BCME_OK;
+ char iovbuf[WLC_IOCTL_SMLEN] = {0, };
+ uint8 *pxtlv = NULL;
+ uint8 *iovresp = NULL;
+ char *token, *pos;
+ uint16 buflen = 0, bufstart = 0;
+ struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
+
+ WL_DBG_MEM(("Enter. cmd:%s\n", command));
+
+ bzero(&query, sizeof(query));
+ query.version = WL_TWT_STATS_CMD_VERSION_1;
+ query.length = sizeof(query) - OFFSETOF(wl_twt_stats_cmd_v1_t, peer);
+
+ /* Default values, Overide Below */
+ query.num_bid = 0xFF;
+ query.num_fid = 0xFF;
+
+ if (!(strnicmp(command, CMD_TWT_CLR_STATS, strlen(CMD_TWT_CLR_STATS)))) {
+ query.flags |= WL_TWT_STATS_CMD_FLAGS_RESET;
+ pos = command + sizeof(CMD_TWT_CLR_STATS);
+ } else if (!(strnicmp(command, CMD_TWT_GET_STATS, strlen(CMD_TWT_GET_STATS)))) {
+ pos = command + sizeof(CMD_TWT_GET_STATS);
+ }
+
+ /* Config ID */
+ token = strsep((char**)&pos, " ");
+ if (!token) {
+ ANDROID_ERROR(("Mandatory param config ID not present\n"));
+ ret = -EINVAL;
+ goto exit;
+ }
+ query.configID = (u8)bcm_atoi(token);
+
+ iovresp = (uint8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
+ if (iovresp == NULL) {
+ ANDROID_ERROR(("%s: iov resp memory alloc exited\n", __FUNCTION__));
+ goto exit;
+ }
+
+ buflen = bufstart = WLC_IOCTL_SMLEN;
+ pxtlv = (uint8 *)iovbuf;
+ ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_TWT_CMD_STATS,
+ sizeof(query), (uint8 *)&query, BCM_XTLV_OPTION_ALIGN32);
+ if (ret != BCME_OK) {
+ ANDROID_ERROR(("%s : Error return during pack xtlv :%d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+
+ if ((ret = wldev_iovar_getbuf(ndev, "twt", iovbuf, bufstart-buflen,
+ iovresp, WLC_IOCTL_MEDLEN, NULL))) {
+ ANDROID_ERROR(("twt status failed with err=%d \n", ret));
+ goto exit;
+ }
+
+ (void)memcpy_s(&stats_v2, sizeof(stats_v2), iovresp, sizeof(stats_v2));
+
+ if (dtoh16(stats_v2.version) == WL_TWT_STATS_VERSION_2) {
+ if (!(strnicmp(command, CMD_TWT_GET_STATS, strlen(CMD_TWT_GET_STATS)))) {
+ ANDROID_ERROR(("stats query ver %d, \n", dtoh16(stats_v2.version)));
+ ret = wl_android_twt_stats_display_v2((wl_twt_stats_v2_t*)iovresp,
+ command, total_len);
+ }
+ } else {
+ ret = BCME_UNSUPPORTED;
+ ANDROID_ERROR(("Version 1 unsupported. ver %d, \n", dtoh16(stats_v2.version)));
+ goto exit;
+ }
+
+exit:
+ if (iovresp) {
+ MFREE(cfg->osh, iovresp, WLC_IOCTL_MEDLEN);
+ }
+
+ return ret;
+}
#endif /* WL_TWT */
int
else if (strnicmp(command, CMD_TWT_CAPABILITY, strlen(CMD_TWT_CAPABILITY)) == 0) {
bytes_written = wl_android_twt_cap(net, command, priv_cmd.total_len);
}
+ else if ((strnicmp(command, CMD_TWT_GET_STATS, strlen(CMD_TWT_GET_STATS)) == 0) ||
+ (strnicmp(command, CMD_TWT_CLR_STATS, strlen(CMD_TWT_CLR_STATS)) == 0)) {
+ bytes_written = wl_android_twt_stats(net, command, priv_cmd.total_len);
+ }
#endif /* WL_TWT */
#ifdef WL_P2P_6G
else if (strnicmp(command, CMD_ENABLE_6G_P2P, strlen(CMD_ENABLE_6G_P2P)) == 0) {
if (cfg->static_ndev_state[static_ifidx] != NDEV_STATE_FW_IF_CREATED) {
#ifdef CUSTOM_MULTI_MAC
if (!wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, static_ifidx+1))
- memcpy(net->dev_addr, hw_ether, ETHER_ADDR_LEN);
+ dev_addr_set(net, hw_ether);
#endif
wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, net->dev_addr);
if (!wdev) {
wdev = new_ndev->ieee80211_ptr;
ASSERT(wdev);
wdev->iftype = iface_type;
- (void)memcpy_s(new_ndev->dev_addr, ETH_ALEN, addr, ETH_ALEN);
+ dev_addr_set(new_ndev, addr);
}
cfg->static_ndev_state[static_ifidx] = NDEV_STATE_FW_IF_CREATED;
#include <wldev_common.h>
#include <dngl_stats.h>
#include <dhd.h>
+#include <wl_android_ext.h>
#ifdef WL_EXT_IAPSTA
-#ifdef WL_ESCAN
-#include <wl_escan.h>
-#endif /* WL_ESCAN */
#include <wl_iapsta.h>
#endif /* WL_IAPSTA */
#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) || \
#endif
#include <wl_event.h>
#endif
-#include <wl_android_ext.h>
+#include <wl_timer.h>
/* If any feature uses the Generic Netlink Interface, put it here to enable WL_GENL
* automatically
#define ANDROID_SCAN_LEVEL (1 << 3)
#define ANDROID_DBG_LEVEL (1 << 4)
#define ANDROID_TPUT_LEVEL (1 << 8)
+#define ANDROID_AMPDU_LEVEL (1 << 9)
+#define ANDROID_TVPM_LEVEL (1 << 10)
+#define ANDROID_BTC_LEVEL (1 << 11)
#define ANDROID_MSG_LEVEL (1 << 0)
#define WL_MSG(name, arg1, args...) \
#define WLC_ACS_BAND_INVALID 0xffffu
#endif /* WL_SUPPORT_AUTO_CHANNEL */
#define WL_PRIV_CMD_LEN 64
+#define CHECK_SCNPRINTF_RET_VAL(ret) \
+ { \
+ if (ret < 0) { \
+ WL_ERR(("scnprintf failed %d\n", ret)); \
+ return BCME_ERROR; \
+ } \
+ }
#endif /* _wl_android_ */
#include <wl_escan.h>
#endif /* WL_ESCAN */
+uint android_msg_level = ANDROID_ERROR_LEVEL | ANDROID_MSG_LEVEL;
+
#define AEXT_ERROR(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_ERROR_LEVEL) { \
#define CMD_ROAM_TRIGGER "ROAM_TRIGGER"
#define CMD_PM "PM"
#define CMD_MONITOR "MONITOR"
+#ifdef BTC_WAR
+#define CMD_BTC_WAR "BTC_WAR"
+#endif /* BTC_WAR */
#define CMD_SET_SUSPEND_BCN_LI_DTIM "SET_SUSPEND_BCN_LI_DTIM"
#define CMD_WLMSGLEVEL "WLMSGLEVEL"
#ifdef WL_EXT_IAPSTA
{WL_AUTH_SAE_KEY, WPA3_AUTH_SAE_PSK|WPA2_AUTH_PSK_SHA256|WPA2_AUTH_PSK, "wpa3sae/psk/sha256"},
{WL_AUTH_OPEN_SYSTEM, 0x20|WPA2_AUTH_PSK_SHA256|WPA2_AUTH_PSK, "wpa3/psk/sha256"},
{WL_AUTH_SAE_KEY, 0x20|WPA2_AUTH_PSK_SHA256|WPA2_AUTH_PSK, "wpa3sae/psk/sha256"},
- {WL_AUTH_OPEN_SYSTEM, WPA3_AUTH_OWE, "wpa3/owe"},
+ {WL_AUTH_OPEN_SYSTEM, WPA3_AUTH_OWE, "owe"},
};
typedef struct wsec_name_map_t {
}
chanspec_t
-wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec)
+wl_ext_chspec_host_to_driver(struct dhd_pub *dhd, chanspec_t chanspec)
{
- if (ioctl_ver == 1) {
+ if (dhd->conf->ioctl_ver == 1) {
chanspec = wl_ext_chspec_to_legacy(chanspec);
if (chanspec == INVCHANSPEC) {
return chanspec;
}
static void
-wl_ext_ch_to_chanspec(int ioctl_ver, int ch,
+wl_ext_ch_to_chanspec(struct dhd_pub *dhd, int ch,
struct wl_join_params *join_params, size_t *join_params_size)
{
chanspec_t chanspec = 0;
join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
join_params->params.chanspec_list[0] |= chanspec;
join_params->params.chanspec_list[0] =
- wl_ext_chspec_host_to_driver(ioctl_ver,
+ wl_ext_chspec_host_to_driver(dhd,
join_params->params.chanspec_list[0]);
join_params->params.chanspec_num =
}
chanspec_t
-wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
+wl_ext_chspec_driver_to_host(struct dhd_pub *dhd, chanspec_t chanspec)
{
chanspec = dtohchanspec(chanspec);
- if (ioctl_ver == 1) {
+ if (dhd->conf->ioctl_ver == 1) {
chanspec = wl_ext_chspec_from_legacy(chanspec);
}
}
#endif /* WL_EXT_IAPSTA || WL_CFG80211 || WL_ESCAN */
+chanspec_band_t
+wl_ext_wlcband_to_chanspec_band(int band)
+{
+ chanspec_band_t chanspec_band = INVCHANSPEC;
+
+ switch (band) {
+#ifdef WL_6G_BAND
+ case WLC_BAND_6G:
+ chanspec_band = WL_CHANSPEC_BAND_6G;
+ break;
+#endif /* WL_6G_BAND */
+ case WLC_BAND_5G:
+ chanspec_band = WL_CHANSPEC_BAND_5G;
+ break;
+ case WLC_BAND_2G:
+ chanspec_band = WL_CHANSPEC_BAND_2G;
+ break;
+ default:
+ AEXT_ERROR("wlan", "Invalid Frequency Band\n");
+ break;
+ }
+ return chanspec_band;
+}
+
bool
wl_ext_check_scan(struct net_device *dev, dhd_pub_t *dhdp)
{
}
}
-int
-wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
-{
- int ret = 0;
- s32 val = 0;
-
- val = 1;
- ret = wl_ext_ioctl(dev, WLC_GET_VERSION, &val, sizeof(val), 0);
- if (ret) {
- return ret;
- }
- val = dtoh32(val);
- if (val != WLC_IOCTL_VERSION && val != 1) {
- AEXT_ERROR(dev->name, "Version mismatch, please upgrade. Got %d, expected %d or 1\n",
- val, WLC_IOCTL_VERSION);
- return BCME_VERSION;
- }
- *ioctl_ver = val;
-
- return ret;
-}
-
void
wl_ext_bss_iovar_war(struct net_device *ndev, s32 *val)
{
}
int
-wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver,
- uint16 channel, chanspec_t *ret_chspec)
+wl_ext_set_chanspec(struct net_device *dev, struct wl_chan_info *chan_info,
+ chanspec_t *ret_chspec)
{
- s32 _chan = channel;
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ s32 _chan = chan_info->chan;
chanspec_t chspec = 0;
chanspec_t fw_chspec = 0;
u32 bw = WL_CHANSPEC_BW_20;
u32 band;
u32 bw_cap;
} param = {0, 0};
- uint band;
+ chanspec_band_t chanspec_band = 0;
- if (_chan <= CH_MAX_2G_CHANNEL)
- band = IEEE80211_BAND_2GHZ;
- else
- band = IEEE80211_BAND_5GHZ;
+ if ((chan_info->band != WLC_BAND_2G) && (chan_info->band != WLC_BAND_5G) &&
+ (chan_info->band != WLC_BAND_6G)) {
+ AEXT_ERROR(dev->name, "bad band %d\n", chan_info->band);
+ return BCME_BADBAND;
+ }
- if (band == IEEE80211_BAND_5GHZ) {
- param.band = WLC_BAND_5G;
- err = wl_ext_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
- iovar_buf, WLC_IOCTL_SMLEN, NULL);
- if (err) {
- if (err != BCME_UNSUPPORTED) {
- AEXT_ERROR(dev->name, "bw_cap failed, %d\n", err);
- return err;
- } else {
- err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
- if (bw_cap != WLC_N_BW_20ALL)
- bw = WL_CHANSPEC_BW_40;
- }
+ param.band = chan_info->band;
+ err = wl_ext_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ if (err) {
+ if (err != BCME_UNSUPPORTED) {
+ AEXT_ERROR(dev->name, "bw_cap failed, %d\n", err);
+ return err;
} else {
- if (WL_BW_CAP_80MHZ(iovar_buf[0]))
- bw = WL_CHANSPEC_BW_80;
- else if (WL_BW_CAP_40MHZ(iovar_buf[0]))
+ err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+ if (bw_cap != WLC_N_BW_20ALL)
bw = WL_CHANSPEC_BW_40;
- else
- bw = WL_CHANSPEC_BW_20;
-
}
+ } else {
+ if (WL_BW_CAP_80MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_80;
+ else if (WL_BW_CAP_40MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_40;
+ else
+ bw = WL_CHANSPEC_BW_20;
}
- else if (band == IEEE80211_BAND_2GHZ)
- bw = WL_CHANSPEC_BW_20;
set_channel:
- chspec = wf_channel2chspec(_chan, bw);
+ chanspec_band = wl_ext_wlcband_to_chanspec_band(chan_info->band);
+ chspec = wf_create_chspec_from_primary(chan_info->chan, bw, chanspec_band);
if (wf_chspec_valid(chspec)) {
- fw_chspec = wl_ext_chspec_host_to_driver(ioctl_ver, chspec);
+ fw_chspec = wl_ext_chspec_host_to_driver(dhd, chspec);
if (fw_chspec != INVCHANSPEC) {
if ((err = wl_ext_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) {
if (bw == WL_CHANSPEC_BW_80)
goto change_bw;
err = wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
- WL_MSG(dev->name, "channel %d\n", _chan);
+ WL_MSG(dev->name, "channel %s-%d\n", CHSPEC2BANDSTR(chspec), _chan);
} else if (err) {
AEXT_ERROR(dev->name, "failed to set chanspec error %d\n", err);
} else
- WL_MSG(dev->name, "channel %d, 0x%x\n", channel, chspec);
+ WL_MSG(dev->name, "channel %s-%d(0x%x %sMHz)\n",
+ CHSPEC2BANDSTR(chspec), chan_info->chan, chspec,
+ CHSPEC_IS20(chspec)?"20":
+ CHSPEC_IS40(chspec)?"40":
+ CHSPEC_IS80(chspec)?"80":"160");
} else {
AEXT_ERROR(dev->name, "failed to convert host chanspec to fw chanspec\n");
err = BCME_ERROR;
static int
wl_ext_channel(struct net_device *dev, char* command, int total_len)
{
+ struct wl_chan_info chan_info;
int ret;
- int channel=0;
+ char band[16]="";
+ int channel = 0;
channel_info_t ci;
int bytes_written = 0;
chanspec_t fw_chspec;
- int ioctl_ver = 0;
AEXT_TRACE(dev->name, "cmd %s", command);
- sscanf(command, "%*s %d", &channel);
+ sscanf(command, "%*s %d %s", &channel, band);
+ if (strnicmp(band, "band=auto", strlen("band=auto")) == 0) {
+ chan_info.band = WLC_BAND_AUTO;
+ }
+#ifdef WL_6G_BAND
+ else if (strnicmp(band, "band=6g", strlen("band=6g")) == 0) {
+ chan_info.band = WLC_BAND_6G;
+ }
+#endif /* WL_6G_BAND */
+ else if (strnicmp(band, "band=5g", strlen("band=5g")) == 0) {
+ chan_info.band = WLC_BAND_5G;
+ }
+ else if (strnicmp(band, "band=2g", strlen("band=2g")) == 0) {
+ chan_info.band = WLC_BAND_2G;
+ }
+ else if (channel <= CH_MAX_2G_CHANNEL)
+ chan_info.band = WLC_BAND_2G;
+ else
+ chan_info.band = WLC_BAND_5G;
if (channel > 0) {
- wl_ext_get_ioctl_ver(dev, &ioctl_ver);
- ret = wl_ext_set_chanspec(dev, ioctl_ver, channel, &fw_chspec);
+ chan_info.chan = channel;
+ ret = wl_ext_set_chanspec(dev, &chan_info, &fw_chspec);
} else {
if (!(ret = wl_ext_ioctl(dev, WLC_GET_CHANNEL, &ci,
sizeof(channel_info_t), FALSE))) {
return ret;
}
+#ifdef BTC_WAR
+extern int btc_war;
+static int
+wl_ext_btc_war(struct net_device *dev, char *command, int total_len)
+{
+ int user_btc_war = 0;
+ bool enable = FALSE;
+
+ sscanf(command, "%*s %d", &user_btc_war);
+
+ AEXT_TRACE(dev->name, "btc_war=%d, user_btc_war=%d\n",
+ btc_war, user_btc_war);
+
+ if (btc_war >= 0) {
+ btc_war = user_btc_war;
+ if (btc_war > 0)
+ enable = TRUE;
+ wl_ext_btc_config(dev, enable);
+ }
+
+ return 0;
+}
+#endif /* BTC_WAR */
+
s32
wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info)
{
s32 err = 0;
u32 chan_cnt = 0;
s8 *iovar_buf = NULL;
- int ioctl_ver = 0;
char sec[64];
- wl_ext_get_ioctl_ver(dev, &ioctl_ver);
-
if (dhd->conf->chip == BCM43362_CHIP_ID)
goto set_ssid;
ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
ext_join_params->assoc.chanspec_list[0] |= chspec;
ext_join_params->assoc.chanspec_list[0] =
- wl_ext_chspec_host_to_driver(ioctl_ver,
+ wl_ext_chspec_host_to_driver(dhd,
ext_join_params->assoc.chanspec_list[0]);
}
ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
else
memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN);
- wl_ext_ch_to_chanspec(ioctl_ver, conn_info->channel, &join_params, &join_params_size);
+ wl_ext_ch_to_chanspec(dhd, conn_info->channel, &join_params, &join_params_size);
AEXT_TRACE(dev->name, "join_param_size %zu\n", join_params_size);
if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
}
bool
-wl_ext_dfs_chan(uint16 chan)
+wl_ext_dfs_chan(struct wl_chan_info *chan_info)
{
- if (chan >= 52 && chan <= 144)
+ if (chan_info->band == WLC_BAND_5G && chan_info->chan >= 52 && chan_info->chan <= 144)
return TRUE;
return FALSE;
}
+bool
+wl_ext_passive_chan(struct net_device *dev, struct wl_chan_info *chan_info)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ u32 chanspec;
+ s32 ret = BCME_OK;
+
+ chanspec = wf_create_chspec_from_primary(chan_info->chan,
+ WL_CHANSPEC_BW_20, wl_ext_wlcband_to_chanspec_band(chan_info->band));
+
+ chanspec = wl_ext_chspec_host_to_driver(dhd, chanspec);
+
+ ret = wldev_iovar_getint(dev, "per_chan_info", &chanspec);
+ if (!ret) {
+ if (chanspec & WL_CHAN_PASSIVE)
+ return TRUE;
+ } else {
+ if (chan_info->band == WLC_BAND_5G && chan_info->chan >= 52 && chan_info->chan <= 144)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
uint16
wl_ext_get_default_chan(struct net_device *dev,
uint16 *chan_2g, uint16 *chan_5g, bool nodfs)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_chan_info chan_info;
uint16 chan_tmp = 0, chan = 0;
wl_uint32_list_t *list;
u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
if (chan_tmp <= 13 && !*chan_2g) {
*chan_2g = chan_tmp;
} else if (chan_tmp >= 36 && chan_tmp <= 161 && !*chan_5g) {
- if (wl_ext_dfs_chan(chan_tmp) && nodfs)
+ chan_info.band = WLC_BAND_5G;
+ chan_info.chan = chan_tmp;
+ if (wl_ext_dfs_chan(&chan_info) && nodfs)
+ continue;
+ else if (wl_ext_passive_chan(dev, &chan_info))
continue;
else
*chan_5g = chan_tmp;
return ret;
}
-#ifdef WL_CFG80211
-bool
-wl_legacy_chip_check(struct net_device *net)
-{
- struct dhd_pub *dhd = dhd_get_pub(net);
- uint chip;
-
- chip = dhd_conf_get_chip(dhd);
-
- if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
- chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
- chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
- chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
- chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
- chip == BCM4371_CHIP_ID ||
- chip == BCM43430_CHIP_ID ||
- chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
- chip == BCM4359_CHIP_ID ||
- chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
- chip == BCM43569_CHIP_ID) {
- return true;
- }
-
- return false;
-}
-
-bool
-wl_new_chip_check(struct net_device *net)
-{
- struct dhd_pub *dhd = dhd_get_pub(net);
- uint chip;
-
- chip = dhd_conf_get_chip(dhd);
-
- if (chip == BCM4359_CHIP_ID || chip == BCM43012_CHIP_ID ||
- chip == BCM43751_CHIP_ID || chip == BCM43752_CHIP_ID) {
- return true;
- }
-
- return false;
-}
-
-bool
-wl_extsae_chip(struct dhd_pub *dhd)
-{
- uint chip;
-
- chip = dhd_conf_get_chip(dhd);
-
- if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
- chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
- chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
- chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
- chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
- chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
- chip == BCM43569_CHIP_ID) {
- return false;
- }
-
- return true;
-}
-#endif
-
#ifdef WLEASYMESH
#define CMD_EASYMESH "EASYMESH"
//Set map 4 and dwds 1 on wlan0 interface
int total_len)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
- wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
+ wl_mkeep_alive_pkt_v1_t *mkeep_alive_pktp;
int ret = -1, i, ifidx, id, period=-1;
char *packet = NULL, *buf = NULL;
int bytes_written = 0;
ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf,
total_len, NULL);
if (!ret) {
- mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf;
+ mkeep_alive_pktp = (wl_mkeep_alive_pkt_v1_t *) buf;
bytes_written += snprintf(command+bytes_written, total_len,
"Id :%d\n"
"Period (msec) :%d\n"
wl_ext_recal(struct net_device *dev, char *data, char *command,
int total_len)
{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
int ret = 0, i, nchan, nssid = 0;
- int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
- wl_scan_params_t *params = NULL;
- int ioctl_ver;
+ int params_size = WL_SCAN_PARAMS_V1_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+ wl_scan_params_v1_t *params = NULL;
char *p;
AEXT_TRACE(dev->name, "Enter\n");
if (data) {
params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
- params = (wl_scan_params_t *) kzalloc(params_size, GFP_KERNEL);
+ params = (wl_scan_params_v1_t *) kzalloc(params_size, GFP_KERNEL);
if (params == NULL) {
ret = -ENOMEM;
goto exit;
}
memset(params, 0, params_size);
- wl_ext_get_ioctl_ver(dev, &ioctl_ver);
-
memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
params->bss_type = DOT11_BSSTYPE_ANY;
params->scan_type = 0;
params->home_time = htod32(params->home_time);
for (i = 0; i < nchan; i++) {
- wl_ext_chspec_host_to_driver(ioctl_ver, params->channel_list[i]);
+ wl_ext_chspec_host_to_driver(dhd, params->channel_list[i]);
}
p = (char*)params->channel_list + nchan * sizeof(uint16);
csi_config_t configs[1];
} csi_list_t;
-static int
-wl_ether_atoe(const char *a, struct ether_addr *n)
-{
- char *c = NULL;
- int i = 0;
-
- memset(n, 0, ETHER_ADDR_LEN);
- for (;;) {
- n->octet[i++] = (uint8)strtoul(a, &c, 16);
- if (!*c++ || i == ETHER_ADDR_LEN)
- break;
- a = c;
- }
- return (i == ETHER_ADDR_LEN);
-}
-
static int
wl_ext_csi(struct net_device *dev, char *data, char *command, int total_len)
{
if (data) {
sscanf(data, "%s %d", mac, &period);
- ret = wl_ether_atoe(mac, &ea);
+ ret = bcm_ether_atoe(mac, &ea);
if (!ret) {
AEXT_ERROR(dev->name, "rejecting mac=%s, ret=%d\n", mac, ret);
goto exit;
return bytes_written;
}
+static int
+wl_ext_disable_5g_band(struct net_device *dev, char *data, char *command,
+ int total_len)
+{
+#ifdef WL_CFG80211
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif
+ int ret = -1;
+ int val;
+
+ if (data) {
+ val = (int)simple_strtol(data, NULL, 0);
+ ret = wl_ext_iovar_setint(dev, "disable_5g_band", val);
+#ifdef WL_CFG80211
+ if (!ret)
+ wl_update_wiphybands(cfg, true);
+#endif
+ } else {
+ ret = wl_ext_iovar_getint(dev, "disable_5g_band", &val);
+ if (!ret) {
+ ret = snprintf(command, total_len, "%d", val);
+ AEXT_TRACE(dev->name, "command result is %s\n", command);
+ }
+ }
+
+ return ret;
+}
+
typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command,
int total_len);
{WLC_GET_VAR, WLC_SET_VAR, "csi", wl_ext_csi},
#endif /* CSI_SUPPORT */
{WLC_GET_VAR, WLC_SET_VAR, "country", wl_ext_get_country},
+ {WLC_GET_VAR, WLC_SET_VAR, "disable_5g_band", wl_ext_disable_5g_band},
};
/*
else if (strnicmp(command, CMD_MONITOR, strlen(CMD_MONITOR)) == 0) {
*bytes_written = wl_ext_monitor(net, command, total_len);
}
+#ifdef BTC_WAR
+ else if (strnicmp(command, CMD_BTC_WAR, strlen(CMD_BTC_WAR)) == 0) {
+ *bytes_written = wl_ext_btc_war(net, command, total_len);
+ }
+#endif /* BTC_WAR */
else if (strnicmp(command, CMD_SET_SUSPEND_BCN_LI_DTIM, strlen(CMD_SET_SUSPEND_BCN_LI_DTIM)) == 0) {
int bcn_li_dtim;
bcn_li_dtim = (int)simple_strtol((command + strlen(CMD_SET_SUSPEND_BCN_LI_DTIM) + 1), NULL, 10);
return ret;
}
+#define CH_MIN_5G_CHANNEL 34
+int
+wl_construct_ctl_chanspec_list(struct net_device *dev, wl_uint32_list_t *chan_list)
+{
+ void *list;
+ u32 i, channel;
+ chanspec_t chspec = 0;
+ s32 err = BCME_OK;
+ bool legacy_chan_info = FALSE;
+ u16 list_count;
+
+#define LOCAL_BUF_LEN 4096
+ list = kmalloc(LOCAL_BUF_LEN, GFP_KERNEL);
+ if (list == NULL) {
+ WL_ERR(("failed to allocate local buf\n"));
+ return -ENOMEM;
+ }
+
+ err = wldev_iovar_getbuf(dev, "chan_info_list", NULL,
+ 0, list, LOCAL_BUF_LEN, NULL);
+ if (err == BCME_UNSUPPORTED) {
+ err = wl_ext_iovar_getbuf(dev, "chanspecs", NULL,
+ 0, list, LOCAL_BUF_LEN, NULL);
+ if (err != BCME_OK) {
+ WL_ERR(("get chanspecs err(%d)\n", err));
+ kfree(list);
+ return err;
+ }
+ /* Update indicating legacy chan info usage */
+ legacy_chan_info = TRUE;
+ } else if (err != BCME_OK) {
+ WL_ERR(("get chan_info_list err(%d)\n", err));
+ kfree(list);
+ return err;
+ }
+
+ list_count = legacy_chan_info ? ((wl_uint32_list_t *)list)->count :
+ ((wl_chanspec_list_v1_t *)list)->count;
+ for (i = 0; i < dtoh32(list_count); i++) {
+ if (legacy_chan_info) {
+ chspec = (chanspec_t)dtoh32(((wl_uint32_list_t *)list)->element[i]);
+ } else {
+ chspec = (chanspec_t)dtoh32
+ (((wl_chanspec_list_v1_t *)list)->chspecs[i].chanspec);
+ }
+ chspec = wl_chspec_driver_to_host(chspec);
+ channel = wf_chspec_ctlchan(chspec);
+
+ if (!CHSPEC_IS20(chspec)) {
+ continue;
+ }
+ if (CHSPEC_IS2G(chspec) && (channel >= CH_MIN_2G_CHANNEL) &&
+ (channel <= CH_MAX_2G_CHANNEL)) {
+ chan_list->element[chan_list->count] = chspec;
+ chan_list->count++;
+ }
+#ifdef WL_6G_BAND
+ else if (CHSPEC_IS6G(chspec) && (channel >= CH_MIN_6G_CHANNEL) &&
+ (channel <= CH_MAX_6G_CHANNEL)) {
+ if (channel == 2)
+ continue;
+ chan_list->element[chan_list->count] = chspec;
+ chan_list->count++;
+ }
+#endif /* WL_6G_BAND */
+ else if (CHSPEC_IS5G(chspec) && (channel >= CH_MIN_5G_CHANNEL) &&
+ (channel <= 165)) {
+ chan_list->element[chan_list->count] = chspec;
+ chan_list->count++;
+ } else {
+ continue;
+ }
+ }
+
+ kfree(list);
+#undef LOCAL_BUF_LEN
+ return err;
+}
+
#if defined(WL_CFG80211) || defined(WL_ESCAN)
int
wl_ext_get_distance(struct net_device *net, u32 band)
#if defined(BSSCACHE)
wl_bss_cache_ctrl_t *bss_cache_ctrl,
#else
- wl_scan_results_t *bss_list,
+ wl_scan_results_v109_t *bss_list,
#endif /* BSSCACHE */
- int ioctl_ver, int *best_2g_ch, int *best_5g_ch
-)
+ int *best_2g_ch, int *best_5g_ch, int *best_6g_ch)
{
+ struct dhd_pub *dhd = dhd_get_pub(net);
struct wl_bss_info *bi = NULL; /* must be initialized */
+ struct wl_chan_info chan_info;
s32 i, j;
#if defined(BSSCACHE)
wl_bss_cache_t *node;
#endif /* BSSCACHE */
int b_band[CH_MAX_2G_CHANNEL]={0}, a_band1[4]={0}, a_band4[5]={0};
- s32 cen_ch, distance, distance_2g, distance_5g, ch, min_ap=999;
- u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+#ifdef WL_6G_BAND
+ int six_g_band5[24]={0}, six_g_band6[5]={0}, six_g_band7[18]={0}, six_g_band8[13]={0};
+ s32 distance_6g;
+#endif /* WL_6G_BAND */
+ s32 cen_ch, distance, distance_2g, distance_5g, chanspec, min_ap=999;
+ u8 valid_chan_list[sizeof(u32)*(MAX_CTRL_CHANSPECS + 1)];
wl_uint32_list_t *list;
int ret;
- chanspec_t chanspec;
- struct dhd_pub *dhd = dhd_get_pub(net);
+ chanspec_t chspec;
+ u32 channel;
memset(b_band, -1, sizeof(b_band));
memset(a_band1, -1, sizeof(a_band1));
memset(a_band4, -1, sizeof(a_band4));
+#ifdef WL_6G_BAND
+ memset(six_g_band5, -1, sizeof(six_g_band5));
+ memset(six_g_band6, -1, sizeof(six_g_band6));
+ memset(six_g_band7, -1, sizeof(six_g_band7));
+ memset(six_g_band8, -1, sizeof(six_g_band8));
+#endif /* WL_6G_BAND */
memset(valid_chan_list, 0, sizeof(valid_chan_list));
list = (wl_uint32_list_t *)(void *) valid_chan_list;
- list->count = htod32(WL_NUMCHANNELS);
- ret = wl_ext_ioctl(net, WLC_GET_VALID_CHANNELS, &valid_chan_list,
- sizeof(valid_chan_list), 0);
- if (ret<0) {
+
+ ret = wl_construct_ctl_chanspec_list(net, list);
+ if (ret < 0) {
AEXT_ERROR(net->name, "get channels failed with %d\n", ret);
return 0;
} else {
- for (i = 0; i < dtoh32(list->count); i++) {
- ch = dtoh32(list->element[i]);
- if (!dhd_conf_match_channel(dhd, ch))
+ for (i = 0; i < list->count; i++) {
+ chspec = list->element[i];
+ channel = wf_chspec_ctlchan(chspec);
+ chan_info.band = CHSPEC2WLC_BAND(chspec);
+ chan_info.chan = channel;
+ if (wl_ext_passive_chan(net, &chan_info)) {
continue;
- if (ch < CH_MAX_2G_CHANNEL)
- b_band[ch-1] = 0;
- else if (ch <= 48)
- a_band1[(ch-36)/4] = 0;
- else if (ch >= 149 && ch <= 161)
- a_band4[(ch-149)/4] = 0;
+ }
+ if (CHSPEC_IS2G(chspec) && (channel >= CH_MIN_2G_CHANNEL) &&
+ (channel <= CH_MAX_2G_CHANNEL)) {
+ b_band[channel-1] = 0;
+ }
+#ifdef WL_6G_BAND
+ else if (CHSPEC_IS6G(chspec) && (channel >= CH_MIN_6G_CHANNEL) &&
+ (channel <= CH_MAX_6G_CHANNEL)) {
+ if (channel <= 93)
+ six_g_band5[(channel-1)/4] = 0;
+ else if (channel >= 97 && channel <= 109)
+ six_g_band6[(channel-97)/4] = 0;
+ else if (channel >= 117 && channel <= 181)
+ six_g_band7[(channel-117)/4] = 0;
+ else if (channel >= 189 && channel <= 221)
+ six_g_band8[(channel-189)/4] = 0;
+ }
+#endif /* WL_6G_BAND */
+ else if (CHSPEC_IS5G(chspec) && channel >= CH_MIN_5G_CHANNEL) {
+ if (channel <= 48)
+ a_band1[(channel-36)/4] = 0;
+ else if (channel >= 149 && channel <= 161)
+ a_band4[(channel-149)/4] = 0;
+ }
}
}
distance_2g = wl_ext_get_distance(net, WLC_BAND_2G);
distance_5g = wl_ext_get_distance(net, WLC_BAND_5G);
+#ifdef WL_6G_BAND
+ distance_6g = wl_ext_get_distance(net, WLC_BAND_6G);
+#endif /* WL_6G_BAND */
#if defined(BSSCACHE)
node = bss_cache_ctrl->m_cache_head;
#if defined(BSSCACHE)
bi = node->results.bss_info;
#else
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : bss_list->bss_info;
+ bi = bi ? (wl_bss_info_v109_t *)((uintptr)bi + dtoh32(bi->length)) : bss_list->bss_info;
#endif /* BSSCACHE */
- chanspec = wl_ext_chspec_driver_to_host(ioctl_ver, bi->chanspec);
+ chanspec = wl_ext_chspec_driver_to_host(dhd, bi->chanspec);
cen_ch = CHSPEC_CHANNEL(bi->chanspec);
distance = 0;
if (CHSPEC_IS20(chanspec))
if (b_band[j] >= 0 && abs(cen_ch-(1+j)) <= distance)
b_band[j] += 1;
}
- } else {
+ }
+#ifdef WL_6G_BAND
+ else if (CHSPEC_IS6G(chanspec)) {
+ distance += distance_6g;
+ if (cen_ch <= 93) {
+ for (j=0; j<ARRAYSIZE(six_g_band5); j++) {
+ if (six_g_band5[j] >= 0 && abs(cen_ch-(93+j*4)) <= distance)
+ six_g_band5[j] += 1;
+ }
+ }
+ else if (channel >= 97 && channel <= 109) {
+ for (j=0; j<ARRAYSIZE(six_g_band6); j++) {
+ if (six_g_band6[j] >= 0 && abs(cen_ch-(97+j*4)) <= distance)
+ six_g_band6[j] += 1;
+ }
+ }
+ else if (channel >= 117 && channel <= 181) {
+ for (j=0; j<ARRAYSIZE(six_g_band7); j++) {
+ if (six_g_band7[j] >= 0 && abs(cen_ch-(117+j*4)) <= distance)
+ six_g_band7[j] += 1;
+ }
+ }
+ else if (channel >= 189 && channel <= 221) {
+ for (j=0; j<ARRAYSIZE(six_g_band8); j++) {
+ if (six_g_band8[j] >= 0 && abs(cen_ch-(189+j*4)) <= distance)
+ six_g_band8[j] += 1;
+ }
+ }
+ }
+#endif /* WL_6G_BAND */
+ else {
distance += distance_5g;
if (cen_ch <= 48) {
for (j=0; j<ARRAYSIZE(a_band1); j++) {
if (a_band1[j] >= 0 && abs(cen_ch-(36+j*4)) <= distance)
a_band1[j] += 1;
}
- } else if (cen_ch >= 149) {
+ }
+ else if (cen_ch >= 149) {
for (j=0; j<ARRAYSIZE(a_band4); j++) {
if (a_band4[j] >= 0 && abs(cen_ch-(149+j*4)) <= distance)
a_band4[j] += 1;
*best_5g_ch = i*4 + 149;
}
}
+#ifdef WL_6G_BAND
+ *best_6g_ch = 0;
+ min_ap = 999;
+ for (i=0; i<ARRAYSIZE(six_g_band5); i++) {
+ if(six_g_band5[i] < min_ap && six_g_band5[i] >= 0) {
+ min_ap = six_g_band5[i];
+ *best_6g_ch = i*4 + 1;
+ }
+ }
+ for (i=0; i<ARRAYSIZE(six_g_band6); i++) {
+ if(six_g_band6[i] < min_ap && six_g_band6[i] >= 0) {
+ min_ap = six_g_band6[i];
+ *best_6g_ch = i*4 + 97;
+ }
+ }
+ for (i=0; i<ARRAYSIZE(six_g_band7); i++) {
+ if(six_g_band7[i] < min_ap && six_g_band7[i] >= 0) {
+ min_ap = six_g_band7[i];
+ *best_6g_ch = i*4 + 117;
+ }
+ }
+ for (i=0; i<ARRAYSIZE(six_g_band8); i++) {
+ if(six_g_band8[i] < min_ap && six_g_band8[i] >= 0) {
+ min_ap = six_g_band8[i];
+ *best_6g_ch = i*4 + 189;
+ }
+ }
+#endif /* WL_6G_BAND */
if (android_msg_level & ANDROID_INFO_LEVEL) {
struct bcmstrbuf strbuf;
char *tmp_buf = NULL;
- tmp_buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
+ tmp_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
if (tmp_buf == NULL) {
AEXT_ERROR(net->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
goto exit;
}
- bcm_binit(&strbuf, tmp_buf, WLC_IOCTL_SMLEN);
+ bcm_binit(&strbuf, tmp_buf, WLC_IOCTL_MEDLEN);
+ bcm_bprintf(&strbuf, "2g: ");
for (j=0; j<ARRAYSIZE(b_band); j++)
bcm_bprintf(&strbuf, "%d/%d, ", b_band[j], 1+j);
bcm_bprintf(&strbuf, "\n");
+ bcm_bprintf(&strbuf, "5g band 1: ");
for (j=0; j<ARRAYSIZE(a_band1); j++)
bcm_bprintf(&strbuf, "%d/%d, ", a_band1[j], 36+j*4);
bcm_bprintf(&strbuf, "\n");
+ bcm_bprintf(&strbuf, "5g band 4: ");
for (j=0; j<ARRAYSIZE(a_band4); j++)
bcm_bprintf(&strbuf, "%d/%d, ", a_band4[j], 149+j*4);
bcm_bprintf(&strbuf, "\n");
- bcm_bprintf(&strbuf, "best_2g_ch=%d, best_5g_ch=%d\n",
+#ifdef WL_6G_BAND
+ bcm_bprintf(&strbuf, "6g band 5: ");
+ for (j=0; j<ARRAYSIZE(six_g_band5); j++)
+ bcm_bprintf(&strbuf, "%d/%d, ", six_g_band5[j], 1+j*4);
+ bcm_bprintf(&strbuf, "\n");
+ bcm_bprintf(&strbuf, "6g band 6: ");
+ for (j=0; j<ARRAYSIZE(six_g_band6); j++)
+ bcm_bprintf(&strbuf, "%d/%d, ", six_g_band6[j], 97+j*4);
+ bcm_bprintf(&strbuf, "\n");
+ bcm_bprintf(&strbuf, "6g band 7: ");
+ for (j=0; j<ARRAYSIZE(six_g_band7); j++)
+ bcm_bprintf(&strbuf, "%d/%d, ", six_g_band7[j], 117+j*4);
+ bcm_bprintf(&strbuf, "\n");
+ bcm_bprintf(&strbuf, "6g band 8: ");
+ for (j=0; j<ARRAYSIZE(six_g_band8); j++)
+ bcm_bprintf(&strbuf, "%d/%d, ", six_g_band8[j], 189+j*4);
+ bcm_bprintf(&strbuf, "\n");
+#endif /* WL_6G_BAND */
+ bcm_bprintf(&strbuf, "best_2g_ch=%d, best_5g_ch=%d",
*best_2g_ch, *best_5g_ch);
+#ifdef WL_6G_BAND
+ bcm_bprintf(&strbuf, ", best_6g_ch=%d", *best_6g_ch);
+#endif /* WL_6G_BAND */
+ bcm_bprintf(&strbuf, "\n");
AEXT_INFO(net->name, "\n%s", strbuf.origbuf);
if (tmp_buf) {
kfree(tmp_buf);
int channel = 0, chosen = 0, retry = 0, ret = 0, spect = 0;
u8 *reqbuf = NULL;
uint32 buf_size;
+ chanspec_band_t acs_band = WLC_BAND_INVALID;
ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
if (ret) {
}
memset(reqbuf, 0, CHANSPEC_BUF_SIZE);
- if (band == WLC_BAND_AUTO) {
- AEXT_INFO(dev->name, "ACS full channel scan \n");
- reqbuf[0] = htod32(0);
- } else if (band == WLC_BAND_5G) {
- AEXT_INFO(dev->name, "ACS 5G band scan \n");
- ret = wl_android_get_band_chanspecs(dev, (void *)reqbuf, CHANSPEC_BUF_SIZE,
- WL_CHANSPEC_BAND_5G, false);
- if (ret < 0) {
- AEXT_ERROR(dev->name, "ACS 5g chanspec retreival failed! \n");
- goto done;
- }
- } else if (band == WLC_BAND_2G) {
- /*
- * If channel argument is not provided/ argument 20 is provided,
- * Restrict channel to 2GHz, 20MHz BW, No SB
- */
- AEXT_INFO(dev->name, "ACS 2G band scan \n");
- ret = wl_android_get_band_chanspecs(dev, (void *)reqbuf, CHANSPEC_BUF_SIZE,
- WL_CHANSPEC_BAND_2G, false);
- if (ret < 0) {
- AEXT_ERROR(dev->name, "ACS 2g chanspec retreival failed! \n");
- goto done;
- }
- } else {
- AEXT_ERROR(dev->name, "ACS: No band chosen\n");
+ acs_band = wl_ext_wlcband_to_chanspec_band(band);
+ if (acs_band == INVCHANSPEC) {
+ acs_band = WL_CHANSPEC_BAND_2G;
+ }
+
+ if ((ret = wl_android_get_band_chanspecs(dev, reqbuf, CHANSPEC_BUF_SIZE,
+ acs_band, true)) < 0) {
+ WL_ERR(("ACS chanspec retrieval failed!\n"));
goto done;
}
- buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
+ AEXT_INFO(dev->name, "ACS chanspec band 0x%x\n", acs_band);
+
+ buf_size = CHANSPEC_BUF_SIZE;
ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
buf_size);
if (ret < 0) {
}
/* Wait for auto channel selection, max 3000 ms */
- if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G)) {
+ if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G) || (band == WLC_BAND_6G)) {
OSL_SLEEP(500);
} else {
/*
chosen = dtoh32(chosen);
}
- if (chosen) {
- int chosen_band;
- int apcs_band;
-#ifdef D11AC_IOTYPES
- if (wl_cfg80211_get_ioctl_version() == 1) {
- channel = LCHSPEC_CHANNEL((chanspec_t)chosen);
- } else {
- channel = CHSPEC_CHANNEL((chanspec_t)chosen);
- }
-#else
- channel = CHSPEC_CHANNEL((chanspec_t)chosen);
-#endif /* D11AC_IOTYPES */
- apcs_band = (band == WLC_BAND_AUTO) ? WLC_BAND_2G : band;
- chosen_band = (channel <= CH_MAX_2G_CHANNEL) ? WLC_BAND_2G : WLC_BAND_5G;
- if (apcs_band == chosen_band) {
- WL_MSG(dev->name, "selected channel = %d\n", channel);
- break;
- }
+ if (wf_chspec_valid((chanspec_t)chosen)) {
+ channel = wf_chspec_ctlchan((chanspec_t)chosen);
+ acs_band = CHSPEC_BAND((chanspec_t)chosen);
+ WL_MSG(dev->name, "selected channel = %d(band %d)\n",
+ channel, CHSPEC2WLC_BAND((chanspec_t)chosen));
+ break;
}
AEXT_INFO(dev->name, "%d tried, ret = %d, chosen = 0x%x\n",
(APCS_MAX_RETRY - retry), ret, chosen);
}
memset(&scan_info, 0, sizeof(wl_scan_info_t));
if (band == WLC_BAND_2G || band == WLC_BAND_AUTO) {
- for (i=0; i<13; i++)
- scan_info.channels.channel[i] = i + 1;
+ for (i=0; i<13; i++) {
+ scan_info.channels.channel[i+cnt] = wf_create_chspec_from_primary(i+1,
+ WL_CHANSPEC_BW_20, WL_CHANSPEC_BAND_2G);
+ }
cnt += 13;
}
if (band == WLC_BAND_5G || band == WLC_BAND_AUTO) {
- for (i=0; i<4; i++)
- scan_info.channels.channel[i+cnt] = 36 + i*4;
+ for (i=0; i<4; i++) {
+ scan_info.channels.channel[i+cnt] = wf_create_chspec_from_primary(36+i*4,
+ WL_CHANSPEC_BW_20, WL_CHANSPEC_BAND_5G);
+ }
cnt += 4;
- for (i=0; i<4; i++)
- scan_info.channels.channel[i+cnt] = 149 + i*4;
+ for (i=0; i<4; i++) {
+ scan_info.channels.channel[i+cnt] = wf_create_chspec_from_primary(149+i*4,
+ WL_CHANSPEC_BW_20, WL_CHANSPEC_BAND_5G);
+ }
cnt += 4;
}
+#ifdef WL_6G_BAND
+ if (band == WLC_BAND_6G || band == WLC_BAND_AUTO) {
+ for (i=0; i<59; i++) {
+ scan_info.channels.channel[i+cnt] = wf_create_chspec_from_primary(1+i*4,
+ WL_CHANSPEC_BW_20, WL_CHANSPEC_BAND_6G);
+ }
+ cnt += 59;
+ }
+#endif /* WL_6G_BAND */
+ if (band == WLC_BAND_2G)
+ fast_scan = FALSE;
scan_info.channels.count = cnt;
if (fast_scan)
scan_info.scan_time = 40;
if (escan->escan_state == ESCAN_STATE_IDLE) {
if (band == WLC_BAND_5G)
channel = escan->best_5g_ch;
+#ifdef WL_6G_BAND
+ else if (band == WLC_BAND_6G)
+ channel = escan->best_6g_ch;
+#endif /* WL_6G_BAND */
else
channel = escan->best_2g_ch;
WL_MSG(dev->name, "selected channel = %d\n", channel);
void
wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
- wl_scan_results_t *ss_list)
+ wl_scan_results_v109_t *ss_list)
{
wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
- wl_bss_info_t *bi = NULL;
+ wl_bss_info_v109_t *bi = NULL;
int i, j, k;
struct osl_timespec now, timeout;
node = *rssi_head;
prev = NULL;
k = 0;
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
+ bi = bi ? (wl_bss_info_v109_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
for (;node;) {
if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
AEXT_INFO("wlan", "Update %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
#if defined(RSSIAVG)
wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
#endif /* RSSIAVG */
- wl_scan_results_t *ss_list)
+ wl_scan_results_v109_t *ss_list)
{
wl_bss_cache_t *node, *node_target = NULL, *prev, *leaf, **bss_head;
wl_bss_cache_t *node_rssi_prev = NULL, *node_rssi = NULL;
- wl_bss_info_t *bi = NULL;
+ wl_bss_info_v109_t *bi = NULL;
int i, k=0, bss_num = 0;
struct osl_timespec now, timeout;
int16 rssi_min;
prev = NULL;
node_target = NULL;
node_rssi_prev = NULL;
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
+ bi = bi ? (wl_bss_info_v109_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
// find the bss with same BSSID
for (;node;) {
#ifndef _wl_android_ext_
#define _wl_android_ext_
+
+typedef struct wl_chan_info {
+ uint band;
+ uint16 chan;
+} wl_chan_info_t;
+
typedef struct bcol_gtk_para {
int enable;
int ptk_len;
#define ACS_FW_BIT (1<<0)
#define ACS_DRV_BIT (1<<1)
int wl_ext_autochannel(struct net_device *dev, uint acs, uint32 band);
+chanspec_band_t wl_ext_wlcband_to_chanspec_band(int band);
int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len,
int *bytes_written);
void wl_ext_get_sec(struct net_device *dev, int ifmode, char *sec, int total_len, bool dump);
void wl_ext_wait_event_complete(struct dhd_pub *dhd, int ifidx);
int wl_ext_add_del_ie(struct net_device *dev, uint pktflag, char *ie_data, const char* add_del_cmd);
#ifdef WL_ESCAN
+int wl_construct_ctl_chanspec_list(struct net_device *dev, wl_uint32_list_t *chan_list);
int wl_ext_drv_scan(struct net_device *dev, uint band, bool fast_scan);
#endif
#ifdef WL_EXT_GENL
int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx,
struct mutex* buf_sync);
-chanspec_t wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec);
-chanspec_t wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec);
-bool wl_ext_dfs_chan(uint16 chan);
+chanspec_t wl_ext_chspec_driver_to_host(struct dhd_pub *dhd, chanspec_t chanspec);
+chanspec_t wl_ext_chspec_host_to_driver(struct dhd_pub *dhd, chanspec_t chanspec);
+bool wl_ext_dfs_chan(struct wl_chan_info *chan_info);
+bool wl_ext_passive_chan(struct net_device *dev, struct wl_chan_info *chan_info);
uint16 wl_ext_get_default_chan(struct net_device *dev,
uint16 *chan_2g, uint16 *chan_5g, bool nodfs);
-int wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver,
- uint16 channel, chanspec_t *ret_chspec);
+int wl_ext_set_chanspec(struct net_device *dev, struct wl_chan_info *chan_info,
+ chanspec_t *ret_chspec);
int wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver);
#endif
#if defined(WL_CFG80211) || defined(WL_ESCAN)
void wl_ext_user_sync(struct dhd_pub *dhd, int ifidx, bool lock);
#endif
-#if defined(WL_CFG80211)
-bool wl_legacy_chip_check(struct net_device *net);
-bool wl_new_chip_check(struct net_device *net);
-bool wl_extsae_chip(struct dhd_pub *dhd);
-#endif
#if defined(WL_EXT_IAPSTA) || defined(WL_CFG80211)
void wl_ext_bss_iovar_war(struct net_device *dev, s32 *val);
#endif /* WL_EXT_IAPSTA ||WL_CFG80211 */
void wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl);
void wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, u8 *bssid);
void wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl);
-void wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list);
+void wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_v109_t *ss_list);
int wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg);
int16 wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr);
#endif
struct wl_bss_cache *next;
int dirty;
struct osl_timespec tv;
- wl_scan_results_t results;
+ wl_scan_results_v109_t results;
} wl_bss_cache_t;
typedef struct wl_bss_cache_ctrl {
#if defined(RSSIAVG)
wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
#endif
- wl_scan_results_t *ss_list);
+ wl_scan_results_v109_t *ss_list);
void wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl);
#endif
int wl_ext_get_best_channel(struct net_device *net,
#if defined(BSSCACHE)
wl_bss_cache_ctrl_t *bss_cache_ctrl,
#else
- wl_scan_results_t *bss_list,
+ wl_scan_results_v109_t *bss_list,
#endif
- int ioctl_ver, int *best_2g_ch, int *best_5g_ch
+ int *best_2g_ch, int *best_5g_ch, int *best_6g_ch
);
+
+#ifdef WL_6G_BAND
+#define CHSPEC2BANDSTR(chspec) ((chspec && CHSPEC_IS2G(chspec)) ? "2g" : CHSPEC_IS5G(chspec) ? \
+ "5g" : CHSPEC_IS6G(chspec) ? "6g" : "0g")
+#define WLCBAND2STR(band) ((band == WLC_BAND_2G) ? "2g" : (band == WLC_BAND_5G) ? \
+ "5g" : (band == WLC_BAND_6G) ? "6g" : "0g")
+#else
+#define CHSPEC2BANDSTR(chspec) ((chspec && CHSPEC_IS2G(chspec)) ? "2g" : CHSPEC_IS5G(chspec) ? \
+ "5g" : "0g")
+#define WLCBAND2STR(band) ((band == WLC_BAND_2G) ? "2g" : (band == WLC_BAND_5G) ? \
+ "5g" : "0g")
+#endif /* WL_6G_BAND */
#endif
return BCME_NOMEM;
}
- ret = vfs_read(fp, buf, WL_BAD_AP_MAX_BUF_SIZE, &fp->f_pos);
+ ret = dhd_vfs_read(fp, buf, WL_BAD_AP_MAX_BUF_SIZE, &fp->f_pos);
if (ret < 0) {
WL_ERR(("%s: file read failed (%d)\n", __FUNCTION__, ret));
goto fail;
fs = get_fs();
set_fs(KERNEL_DS);
- fp = filp_open(fname, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(fname, O_RDONLY, 0);
+ if (IS_ERR(fp) || (fp == NULL)) {
fp = NULL;
WL_ERR(("%s: file open failed(%d)\n", __FUNCTION__, ret));
goto fail;
}
fail:
if (fp) {
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
}
set_fs(fs);
fs = get_fs();
set_fs(KERNEL_DS);
- fp = filp_open(fname, O_CREAT | O_RDWR | O_TRUNC, 0666);
- if (IS_ERR(fp)) {
+ fp = dhd_filp_open(fname, O_CREAT | O_RDWR | O_TRUNC, 0666);
+ if (IS_ERR(fp) || (fp == NULL)) {
ret = PTR_ERR(fp);
WL_ERR(("%s: file open failed(%d)\n", __FUNCTION__, ret));
fp = NULL;
#pragma GCC diagnostic pop
#endif
- ret = vfs_write(fp, tmp, len, &fp->f_pos);
+ ret = dhd_vfs_write(fp, tmp, len, &fp->f_pos);
if (ret < 0) {
WL_ERR(("%s: file write failed(%d)\n", __FUNCTION__, ret));
goto fail;
}
/* Sync file from filesystem to physical media */
- ret = vfs_fsync(fp, 0);
+ ret = dhd_vfs_fsync(fp, 0);
if (ret < 0) {
WL_ERR(("%s: sync file failed(%d)\n", __FUNCTION__, ret));
goto fail;
ret = BCME_OK;
fail:
if (fp) {
- filp_close(fp, NULL);
+ dhd_filp_close(fp, NULL);
}
set_fs(fs);
mutex_unlock(&cfg->bad_ap_mngr.fs_lock);
#endif /* WL_CFG80211_P2P_DEV_IF */
static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool unicast, bool multicast);
static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params);
static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool pairwise, const u8 *mac_addr);
static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool pairwise, const u8 *mac_addr,
void *cookie, void (*callback) (void *cookie,
struct key_params *params));
static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
- struct net_device *dev, u8 key_idx);
+ struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
+ u8 key_idx);
#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
bcm_struct_cfgdev *cfgdev, u64 cookie);
bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
const wl_event_msg_t *e, void *data, bool completed);
-#ifdef DHD_LOSSLESS_ROAMING
static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
const wl_event_msg_t *e, void *data);
-#endif /* DHD_LOSSLESS_ROAMING */
static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
const wl_event_msg_t *e, void *data);
#ifdef BT_WIFI_HANDOVER
WL_ERR(("%s: starts to read %s. Axi error \n", __FUNCTION__, filename));
- fp = filp_open(filename, O_RDONLY, 0);
+ fp = dhd_filp_open(filename, O_RDONLY, 0);
if (IS_ERR(fp) || (fp == NULL)) {
WL_ERR(("%s: Couldn't read the file, err %ld,File [%s] No previous axi error \n",
return ret;
}
- kernel_read_compat(fp, fp->f_pos, (char *)dhd->axi_err_dump, sizeof(dhd_axi_error_dump_t));
- filp_close(fp, NULL);
+ dhd_kernel_read_compat(fp, fp->f_pos, (char *)dhd->axi_err_dump, sizeof(dhd_axi_error_dump_t));
+ dhd_filp_close(fp, NULL);
/* Delete axi error info file */
if (dhd_file_delete(filename) < 0) {
if (addr) {
ifflags |= WL_INTERFACE_MAC_USE;
- if (wl_legacy_chip_check(ndev)) {
+ if (dhd_conf_legacy_chip_check(cfg->pub)) {
iface.flags = ifflags;
memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
}
#endif /* WLEASYMESH */
/* Pass ver = 0 for fetching the interface_create iovar version */
- if (wl_legacy_chip_check(ndev)) {
+ if (dhd_conf_legacy_chip_check(cfg->pub)) {
bzero(&iface_v0, sizeof(iface_v0));
iface_v0.ver = WL_INTERFACE_CREATE_VER_0;
iface_v0.flags = iftype | ifflags;
#ifdef WLDWDS
/* set wds0.x to 4addr interface here */
if (event->role == WLC_E_IF_ROLE_WDS) {
- WL_MSG(ndev->name, "set vwdev 4addr to %s\n", event->name);
+ struct dhd_if *ifp = dhd_get_ifp(cfg->pub, event->ifidx);
+ ifp->dwds = TRUE;
+ WL_MSG(event->name, "set to 4addr\n");
wdev->use_4addr = true;
}
#endif /* WLDWDS */
SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
- memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
+ dev_addr_set(new_ndev, addr);
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_ifadding(new_ndev, event->ifidx);
+ if (event->role != WLC_E_IF_ROLE_WDS) {
+ wl_ext_iapsta_ifadding(new_ndev, event->ifidx);
+ }
#endif /* WL_EXT_IAPSTA */
if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd)
!= BCME_OK) {
chan = params->channel;
#endif /* WL_CFG80211_P2P_DEV_IF */
if (chan) {
- u16 center_freq = chan->center_freq;
#ifdef WL_EXT_IAPSTA
- enum nl80211_band band;
- s32 _chan;
- _chan = ieee80211_frequency_to_channel(center_freq);
+ chanspec = wl_freq_to_chanspec(chan->center_freq);
wl_ext_iapsta_update_iftype(dev, WL_IF_TYPE_IBSS);
- _chan = wl_ext_iapsta_update_channel(dev, _chan);
- if (CHANNEL_IS_5G(_chan))
- band = NL80211_BAND_5GHZ;
- else
- band = NL80211_BAND_2GHZ;
- center_freq = ieee80211_channel_to_frequency(_chan, band);
+ chanspec = wl_ext_iapsta_update_channel(dev, chanspec);
#endif /* WL_EXT_IAPSTA */
- cfg->channel = wl_freq_to_chanspec(center_freq);
+ cfg->channel = chanspec;
}
if (wl_get_drv_status(cfg, CONNECTED, dev)) {
struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
if (!err)
cur_rssi = dtoh32(scb_val.val);
WL_MSG(dev->name, "Reconnecting with " MACDBG " ssid \"%s\", len (%d), "
- "channel=%d(chan_cnt=%d), sec=%s, rssi=%d => %d\n",
+ "channel=%s-%d(chan_cnt=%d), sec=%s, rssi=%d => %d\n",
MAC2STRDBG((u8*)(&info->bssid)), info->ssid, info->ssid_len,
- wf_chspec_ctlchan(chanspec), chan_cnt, sec_info, cur_rssi, target_rssi);
+ CHSPEC2BANDSTR(chanspec), wf_chspec_ctlchan(chanspec), chan_cnt,
+ sec_info, cur_rssi, target_rssi);
} else {
WL_MSG(dev->name, "Connecting with " MACDBG " ssid \"%s\", len (%d), "
- "channel=%d(chan_cnt=%d), sec=%s, rssi=%d\n",
+ "channel=%s-%d(chan_cnt=%d), sec=%s, rssi=%d\n",
MAC2STRDBG((u8*)(&info->bssid)), info->ssid, info->ssid_len,
- wf_chspec_ctlchan(chanspec), chan_cnt, sec_info, target_rssi);
+ CHSPEC2BANDSTR(chanspec), wf_chspec_ctlchan(chanspec), chan_cnt,
+ sec_info, target_rssi);
}
if (wl_dbg_level & WL_DBG_DBG) {
WL_MSG(dev->name, "akm:0x%x auth:0x%x wpaver:0x%x pwise:0x%x gwise:0x%x\n",
}
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_update_channel(dev, wf_chspec_ctlchan(assoc_info->chanspecs[0]));
+ wl_ext_iapsta_update_channel(dev, assoc_info->chanspecs[0]);
#endif
/* print relevant info for debug purpose */
wl_conn_debug_info(cfg, dev, assoc_info);
reassoc_params->chanspec_num = htod32(chan_cnt);
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_update_channel(dev, wf_chspec_ctlchan(chanspec));
+ wl_ext_iapsta_update_channel(dev, chanspec);
#endif
/* print relevant info for debug purpose */
wl_conn_debug_info(cfg, dev, info);
if (assoc_info.reassoc) {
/* Handle roam to same ESS */
+#ifdef DHD_LOSSLESS_ROAMING
+ wl_ext_send_event_msg(dev, WLC_E_ROAM_PREP, WLC_E_STATUS_SUCCESS, WLC_E_REASON_LOW_RSSI);
+#endif
if ((err = wl_handle_reassoc(cfg, dev, &assoc_info)) != BCME_OK) {
goto fail;
}
WL_TRACE_HW4(("Aborting the scan! \n"));
wl_cfgscan_cancel_scan(cfg);
}
- if (conn_in_progress || connected || wdev->ssid_len) {
+ if (conn_in_progress || connected ||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ wdev->u.client.ssid_len
+#else
+ wdev->ssid_len
+#endif
+ ) {
+#ifdef WL_EXT_IAPSTA
+ wl_ext_in4way_sync(dev, 0, WL_EXT_STATUS_PRE_DISCONNECTING, NULL);
+#endif
scbval.val = reason_code;
memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
scbval.val = htod32(scbval.val);
* and issue disconnect indication if required.
*/
- if (wdev->current_bss || wdev->ssid_len) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ // terence 20220911: fix me
+ if (wdev->links[0].client.current_bss || wdev->u.client.ssid_len)
+#else
+ if (wdev->current_bss || wdev->ssid_len)
+#endif
+ {
WL_INFORM_MEM(("report disconnect event\n"));
CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
}
static s32
wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool unicast, bool multicast)
{
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
s32 bssidx;
s32 mode = wl_get_mode_by_netdev(cfg, dev);
- WL_MSG(dev->name, "key index (%d)\n", key_idx);
+ WL_MSG(dev->name, "key index (%d) for %pM\n", key_idx, mac_addr);
if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
return BCME_ERROR;
static s32
wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
static s32
wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool pairwise, const u8 *mac_addr)
{
struct wl_wsec_key key;
/* NOTE : this function cannot work as is and is never called */
static s32
wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
void (*callback) (void *cookie, struct key_params * params))
{
static s32
wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
- struct net_device *dev, u8 key_idx)
+ struct net_device *dev,
+#if defined(CFG80211_BKPORT_MLO)
+ int link_id,
+#endif
+ u8 key_idx)
{
#ifdef MFP
/* Firmware seems to use hard coded index for Group Mgmt Key.
}
#endif /* WL_SUPPORT_ACS */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+static int
+wl_cfg80211_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ unsigned int link_id,
+#endif
+ struct cfg80211_chan_def *chandef)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ u32 chanspec = 0;
+ int ret = 0;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ if (NULL == wdev->netdev) {
+ /* the P2P interface may temporary use wdev without ndev */
+ return -EINVAL;
+ }
+
+ if ((ret = wldev_iovar_getint(wdev->netdev, "chanspec", (s32 *)&chanspec) != BCME_OK)) {
+ return ret;
+ }
+ if (!chandef || (wl_chspec_chandef(chanspec, chandef, wiphy) != BCME_OK)) {
+ return BCME_ERROR;
+ }
+ return 0;
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0) */
+
static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = wl_cfg80211_add_virtual_iface,
.del_virtual_intf = wl_cfg80211_del_virtual_iface,
.update_ft_ies = wl_cfg80211_update_ft_ies,
#endif /* WLFBT */
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0)
+ .get_channel = wl_cfg80211_get_channel,
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0) */
};
s32 wl_mode_to_nl80211_iftype(s32 mode)
return err;
}
+static bool
+wl_is_ccode_change_allowed(struct net_device *net)
+{
+ struct wireless_dev *wdev = ndev_to_wdev(net);
+ struct wiphy *wiphy = wdev->wiphy;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ struct net_info *iter, *next;
+
+ /* Country code isn't allowed change on AP/GO, NDP established */
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
+ for_each_ndev(cfg, iter, next) {
+ GCC_DIAGNOSTIC_POP();
+ if (iter->ndev) {
+ if (wl_get_drv_status(cfg, AP_CREATED, iter->ndev)) {
+ WL_ERR(("AP active. skip coutry ccode change\n"));
+ return false;
+ }
+ }
+ }
+
+#ifdef WL_NAN
+ if (wl_cfgnan_is_enabled(cfg) && wl_cfgnan_is_dp_active(net)) {
+ WL_ERR(("NDP established. skip coutry ccode change\n"));
+ return false;
+ }
+#endif /* WL_NAN */
+ return true;
+}
+
static bool
wl_is_ccode_change_required(struct net_device *net,
char *country_code, int revinfo)
#endif /* WL_NAN */
}
+static int wl_copy_regd(const struct ieee80211_regdomain *regd_orig,
+ struct ieee80211_regdomain *regd_copy)
+{
+ int i;
+
+ if (memcpy_s(regd_copy, sizeof(*regd_copy), regd_orig, sizeof(*regd_orig))) {
+ return BCME_ERROR;
+ }
+ for (i = 0; i < regd_orig->n_reg_rules; i++) {
+ if (memcpy_s(®d_copy->reg_rules[i], sizeof(regd_copy->reg_rules[i]),
+ ®d_orig->reg_rules[i], sizeof(regd_orig->reg_rules[i]))) {
+ return BCME_ERROR;
+ }
+ }
+ return BCME_OK;
+}
+
+static void wl_notify_regd(struct wiphy *wiphy, char *country_code)
+{
+ struct ieee80211_regdomain *regd_copy = NULL;
+ int regd_len;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+
+ regd_len = sizeof(brcm_regdom) + (brcm_regdom.n_reg_rules *
+ sizeof(struct ieee80211_reg_rule));
+
+ regd_copy = (struct ieee80211_regdomain *)MALLOCZ(cfg->osh, regd_len);
+ if (!regd_copy) {
+ WL_ERR(("failed to alloc regd_copy\n"));
+ return;
+ }
+
+ /* the upper layer function below requires non-const type */
+ if (wl_copy_regd(&brcm_regdom, regd_copy)) {
+ WL_ERR(("failed to copy new regd\n"));
+ goto exit;
+ }
+
+ if (country_code) {
+ if (memcpy_s(regd_copy->alpha2, sizeof(regd_copy->alpha2),
+ country_code, WL_CCODE_LEN)) {
+ WL_ERR(("failed to copy new ccode:%s\n", country_code));
+ goto exit;
+ }
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+ if (rtnl_is_locked()) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
+ wiphy_lock(wiphy);
+ regulatory_set_wiphy_regd_sync(wiphy, regd_copy);
+ wiphy_unlock(wiphy);
+#else
+ regulatory_set_wiphy_regd_sync_rtnl(wiphy, regd_copy);
+#endif /* LINUX_VERSION > 5.12.0 */
+ } else {
+ regulatory_set_wiphy_regd(wiphy, regd_copy);
+ }
+#else
+ wiphy_apply_custom_regulatory(wiphy, regd_copy);
+#endif /* LINUX_VERSION > 4.0.0 */
+
+exit:
+ MFREE(cfg->osh, regd_copy, regd_len);
+ return;
+}
+
s32
wl_cfg80211_set_country_code(struct net_device *net, char *country_code,
bool notify, bool user_enforced, int revinfo)
goto exit;
}
+ if (wl_is_ccode_change_allowed(net) == false) {
+ WL_ERR(("country code change isn't allowed during AP role/NAN connected\n"));
+ ret = BCME_EPERM;
+ goto exit;
+ }
+
wl_cfg80211_cleanup_connection(net, user_enforced);
+ /* Store before applying - so that if event comes earlier that is handled properly */
+ if (strlcpy(cfg->country, country_code, WL_CCODE_LEN) >= WLC_CNTRY_BUF_SZ) {
+ WL_ERR(("country code copy failed :%d\n", ret));
+ goto exit;
+ }
+
ret = wldev_set_country(net, country_code,
notify, revinfo);
if (ret < 0) {
WL_ERR(("set country Failed :%d\n", ret));
+ bzero(cfg->country, sizeof(cfg->country));
goto exit;
}
*/
if (!IS_REGDOM_SELF_MANAGED(wiphy)) {
regulatory_hint(wiphy, country_code);
+ } else {
+ wl_notify_regd(wiphy, country_code);
}
exit:
- return ret;
+ return OSL_ERROR(ret);
}
#ifdef CONFIG_CFG80211_INTERNAL_REGDB
void wl_config_custom_regulatory(struct wiphy *wiphy)
{
-#if defined(WL_SELF_MANAGED_REGDOM) && \
- (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+#if defined(WL_SELF_MANAGED_REGDOM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
/* Use self managed regulatory domain */
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED |
REGULATORY_IGNORE_STALE_KICKOFF;
- wiphy->regd = &brcm_regdom;
WL_DBG(("Self managed regdom\n"));
return;
#else /* WL_SELF_MANAGED_REGDOM && KERNEL >= 4.0 */
#else /* KERNEL VER >= 3.14 */
wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
- wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
+ wl_notify_regd(wiphy, NULL);
WL_DBG(("apply custom regulatory\n"));
#endif /* WL_SELF_MANAGED_REGDOM && KERNEL >= 4.0 */
}
wdev->wiphy->max_num_csa_counters = WL_MAX_NUM_CSA_COUNTERS;
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 12, 0) */
- /* Now we can register wiphy with cfg80211 module */
- err = wiphy_register(wdev->wiphy);
- if (unlikely(err < 0)) {
- 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)
/* Workaround for a cfg80211 bug */
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(SUPPORT_RANDOM_MAC_SCAN) */
#if defined(WL_SAE) || defined(WL_CLIENT_SAE)
- if (wl_extsae_chip(dhd))
+ if (dhd_conf_extsae_chip(dhd))
wdev->wiphy->features |= NL80211_FEATURE_SAE;
#endif /* WL_SAE || WL_CLIENT_SAE */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)) && defined(BCMSUP_4WAY_HANDSHAKE)
wdev->wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN;
#endif /* WL_SCAN_TYPE */
+ /* Now we can register wiphy with cfg80211 module */
+ err = wiphy_register(wdev->wiphy);
+ if (unlikely(err < 0)) {
+ WL_ERR(("Couldn not register wiphy device (%d)\n", err));
+ wiphy_free(wdev->wiphy);
+ return err;
+ }
+
+ /* set wiphy->regd through reg_process_self_managed_hints
+ * need to call it after wiphy_register
+ * since wiphy_register adds rdev to cfg80211_rdev_list
+ */
+ if (IS_REGDOM_SELF_MANAGED(wdev->wiphy)) {
+ rtnl_lock();
+ wl_notify_regd(wdev->wiphy, NULL);
+ rtnl_unlock();
+ }
return err;
}
wdev->wiphy->wowlan = NULL;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
#endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
-#if defined(WL_SELF_MANAGED_REGDOM) && \
- (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+#if defined(WL_SELF_MANAGED_REGDOM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
/* Making regd ptr NULL, to avoid reference/freeing by regulatory unregister */
wiphy->regd = NULL;
#endif /* WL_SELF_MANAGED_REGDOM && KERNEL >= 4.0 */
memcpy(&emsg, as->event_msg, sizeof(wl_event_msg_t));
ret = wl_ext_in4way_sync(ndev, STA_REASSOC_RETRY,
WL_EXT_STATUS_RECONNECT, &emsg);
- if (ret)
+ if (ret == BCME_ERROR)
return 0;
}
wl_ext_iapsta_enable_master_if(ndev, FALSE);
memcpy(&emsg, as->event_msg, sizeof(wl_event_msg_t));
ret = wl_ext_in4way_sync(ndev, STA_REASSOC_RETRY,
WL_EXT_STATUS_RECONNECT, &emsg);
- if (ret)
+ if (ret == BCME_BADADDR) {
+ u8 *curbssid = NULL;
+ curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
+ if (curbssid)
+ (void)memcpy_s(as->addr, ETH_ALEN, curbssid, ETH_ALEN);
+ }
+ else if (ret == BCME_ERROR)
return 0;
}
#endif
goto exit;
}
+#ifdef WL_ROAM_WAR
+ if (event_type == WLC_E_JOIN)
+ bzero((u8*)&cfg->roaming_bssid, ETHER_ADDR_LEN);
+ else if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
+ if (event_type == WLC_E_AUTH && ntoh32(e->status) == WLC_E_STATUS_SUCCESS)
+ bcopy(&e->addr, &cfg->roaming_bssid, ETHER_ADDR_LEN);
+ else if (event_type == WLC_E_DEAUTH &&
+ !ETHER_ISNULLADDR(&cfg->roaming_bssid.octet) &&
+ memcmp(&e->addr, &cfg->roaming_bssid, ETHER_ADDR_LEN)) {
+ WL_MSG(ndev->name, "skip WLC_E_DEAUTH(%pM), roaming_bssid %pM\n",
+ &e->addr, &cfg->roaming_bssid);
+ goto exit;
+ }
+ }
+#endif /* WL_ROAM_WAR */
+
if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
assoc_state = WL_STATE_ASSOCIATING;
} else if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
return err;
}
-#ifdef DHD_LOSSLESS_ROAMING
static s32
wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
const wl_event_msg_t *e, void *data)
struct wl_connect_info *conn_info = wl_to_conn(cfg);
s32 err = 0;
u8 *curbssid;
- chanspec_t *chanspec;
+ chanspec_t *chanspec, cur_chanspec;
scb_val_t scbval;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || \
defined(WL_COMPAT_WIRELESS)
struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
struct ieee80211_channel *notify_channel = NULL;
u32 freq;
- u32 cur_channel, cur_chanspec, orig_channel;
+ u32 cur_channel, orig_channel;
#endif /* LINUX_VERSION > 2.6.39 || WL_COMPAT_WIRELESS */
#if (defined(CONFIG_ARCH_MSM) && defined(CFG80211_ROAMED_API_UNIFIED)) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) || \
cur_channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(cur_chanspec));
orig_channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(*chanspec));
if (dhdp->conf->chip != BCM43569_CHIP_ID) {
- if ((orig_channel == cur_channel) &&
+ if (((orig_channel == cur_channel) && memcmp(ðer_null, &cfg->last_roamed_addr, ETHER_ADDR_LEN)) &&
((memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) ||
(memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0))) {
- WL_DBG(("BSS already present, Skipping roamed event to upper layer\n"));
+ WL_INFORM_MEM(("BSS already present, Skipping roamed event to upper layer\n"));
+ WL_INFORM_MEM(("orig_chan/cur_chan=%d/%d, addr/curbssid/last_roamed_addr=%pM/%pM/%pM\n",
+ orig_channel, cur_channel,
+ (const u8*)(&e->addr), curbssid, (const u8*)(&cfg->last_roamed_addr)));
goto fail;
}
}
}
rssi = dtoh32(scbval.val);
- WL_MSG(ndev->name, "%pM(ch:%3d/%sMHz) => %pM(ch:%3d/%sMHz, rssi: %3d)\n",
- curbssid, orig_channel,
+ WL_MSG(ndev->name, "%pM(chan=%s-%d/%sMHz) => %pM(chan=%s-%d/%sMHz, rssi: %3d)\n",
+ curbssid,
+ CHSPEC2BANDSTR(*chanspec), wf_chspec_ctlchan(*chanspec),
CHSPEC_IS20(*chanspec)?"20":
CHSPEC_IS40(*chanspec)?"40":
CHSPEC_IS80(*chanspec)?"80":
CHSPEC_IS160(*chanspec)?"160":"??",
- (const u8*)(&e->addr), cur_channel,
+ (const u8*)(&e->addr),
+ CHSPEC2BANDSTR(cur_chanspec), wf_chspec_ctlchan(cur_chanspec),
CHSPEC_IS20(cur_chanspec)?"20":
CHSPEC_IS40(cur_chanspec)?"40":
CHSPEC_IS80(cur_chanspec)?"80":
DHD_STATLOG_CTRL(dhdp, ST(REASSOC_INFORM),
dhd_net2idx(dhdp->info, ndev), 0);
#ifdef WL_EXT_IAPSTA
- wl_ext_in4way_sync(ndev, 0, WL_EXT_STATUS_CONNECTED, NULL);
+ wl_ext_in4way_sync(ndev, 0, WL_EXT_STATUS_ROAMED, NULL);
#endif
#if (defined(CONFIG_ARCH_MSM) && defined(CFG80211_ROAMED_API_UNIFIED)) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) || \
defined(WL_FILS_ROAM_OFFLD) || defined(CFG80211_ROAM_API_GE_4_12)
memset(&roam_info, 0, sizeof(struct cfg80211_roam_info));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ roam_info.links[0].channel = notify_channel;
+ roam_info.links[0].bssid = curbssid;
+#else
roam_info.channel = notify_channel;
roam_info.bssid = curbssid;
+#endif
roam_info.req_ie = conn_info->req_ie;
roam_info.req_ie_len = conn_info->req_ie_len;
roam_info.resp_ie = conn_info->resp_ie;
return err;
fail:
+#ifdef WL_EXT_IAPSTA
+ if (err)
+ wl_ext_in4way_sync(ndev, STA_NO_BTC_IN4WAY, WL_EXT_STATUS_DISCONNECTED, NULL);
+#endif
#ifdef DHD_LOSSLESS_ROAMING
wl_del_roam_timeout(cfg);
#endif /* DHD_LOSSLESS_ROAMING */
return err;
}
-#endif /* DHD_LOSSLESS_ROAMING */
static bool
wl_cfg80211_verify_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
resp_params = (struct cfg80211_connect_resp_params *)params;
resp_params->status = status;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ resp_params->links[0].bssid = curbssid;
+ resp_params->links[0].bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
+ ssid->SSID, ssid->SSID_len);
+#else
resp_params->bssid = curbssid;
resp_params->bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
ssid->SSID, ssid->SSID_len);
- if (!resp_params->bss) {
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ if (!resp_params->links[0].bss)
+#else
+ if (!resp_params->bss)
+#endif
+ {
WL_ERR(("null bss\n"));
return BCME_ERROR;
}
completed = false;
sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
}
- if (!ndev->ieee80211_ptr->ssid_len) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ if (!ndev->ieee80211_ptr->u.client.ssid_len)
+#else
+ if (!ndev->ieee80211_ptr->ssid_len)
+#endif
+ {
/* In certain cases, the delayed cfg80211 work from
* disconnect context will induce race conditions in
* which the ssid_len will be cleared, but dhd is in
if (completed) {
WL_MSG(ndev->name, "Report connect result - connection succeeded\n");
-#ifdef WL_EXT_IAPSTA
- wl_ext_in4way_sync(ndev, 0, WL_EXT_STATUS_CONNECTED, NULL);
- wl_ext_iapsta_enable_master_if(ndev, TRUE);
-#endif
} else {
WL_MSG(ndev->name, "Report connect result - connection failed\n");
#ifdef WL_EXT_IAPSTA
#endif /* WAPI */
}
+#ifdef WL_EXT_IAPSTA
+ if (completed) {
+ wl_ext_in4way_sync(ndev, 0, WL_EXT_STATUS_CONNECTED, NULL);
+ wl_ext_iapsta_enable_master_if(ndev, TRUE);
+ }
+#endif
+
exit:
CLR_TS(cfg, conn_start);
return err;
return err;
}
-#ifdef CUSTOMER_HW6
+static void
+wl_map_brcm_specifc_country_code(char *country_code)
+{
+ /* If country code is default locale, change the domain to world domain
+ * Default locale formats: AA, ZZ, XA-XZ, QM-QZ
+ */
+ if (!strcmp("AA", country_code) || !strcmp("ZZ", country_code) ||
+ ((country_code[0] == 'X') && (country_code[1] >= 'A') &&
+ (country_code[1] <= 'Z')) || ((country_code[0] == 'Q') &&
+ (country_code[1] >= 'M') && (country_code[1] <= 'Z'))) {
+ WL_DBG(("locale mapped to world domain\n"));
+ country_code[0] = '0';
+ country_code[1] = '0';
+ }
+}
+
static s32
wl_cfg80211_ccode_evt_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
const wl_event_msg_t *event, void *data)
{
+ dhd_pub_t *dhd = cfg->pub;
s32 err = 0;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ char country_str[WLC_CNTRY_BUF_SZ] = { 0 };
+ struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
+
+ if (strlcpy(country_str, data, WL_CCODE_LEN + 1) >= WLC_CNTRY_BUF_SZ) {
+ return -EINVAL;
+ }
+
+ if (strncmp(cfg->country, country_str, WL_CCODE_LEN) == 0) {
+ /* If country code is updated from command context, skip wiphy update */
+ WL_MSG(dev->name, "No change in country (%s)\n", country_str);
+ return BCME_OK;
+ }
+
+ WL_MSG(dev->name, "Updating new country %s\n", country_str);
+ dhd_conf_country(dhd, "country", country_str);
+
/* Indicate to upper layer for regdom change */
- WL_INFORM_MEM(("Received country code change event\n"));
err = wl_update_wiphybands(cfg, true);
+ if (err != BCME_OK) {
+ WL_ERR(("update wiphy bands failed\n"));
+ return err;
+ }
+
+ wl_map_brcm_specifc_country_code(country_str);
+
+ if (!IS_REGDOM_SELF_MANAGED(wiphy)) {
+ err = regulatory_hint(wiphy, country_str);
+ if (err) {
+ WL_ERR(("update country change failed\n"));
+ return err;
+ }
+ WL_DBG_MEM(("regulatory hint notified for ccode change\n"));
+ }
return err;
}
-#endif /* CUSTOMER_HW6 */
static void wl_init_conf(struct wl_conf *conf)
{
cfg->evt_handler[WLC_E_ADPS] = wl_adps_event_handler;
#endif /* WL_BAM */
cfg->evt_handler[WLC_E_PSK_SUP] = wl_cfg80211_sup_event_handler;
-#ifdef CUSTOMER_HW6
cfg->evt_handler[WLC_E_COUNTRY_CODE_CHANGED] = wl_cfg80211_ccode_evt_handler;
-#endif /* CUSTOMER_HW6 */
#ifdef WL_BCNRECV
cfg->evt_handler[WLC_E_BCNRECV_ABORTED] = wl_bcnrecv_aborted_event_handler;
#endif /* WL_BCNRECV */
cfg->evt_handler[WLC_E_BSS_LOAD] = wl_cfg80211_bssload_report_event_handler;
#endif /* WL_CHAN_UTIL */
#ifdef WL_TWT
- cfg->evt_handler[WLC_E_TWT_SETUP] = wl_notify_twt_event;
- cfg->evt_handler[WLC_E_TWT_TEARDOWN] = wl_notify_twt_event;
- cfg->evt_handler[WLC_E_TWT_INFO_FRM] = wl_notify_twt_event;
+ cfg->evt_handler[WLC_E_TWT] = wl_notify_twt_event;
+#else
+#ifdef WL_TWT_HAL_IF
+ cfg->evt_handler[WLC_E_TWT] = wl_cfgvendor_notify_twt_event;
+#endif /* WL_TWT_HAL_IF */
#endif /* WL_TWT */
#ifdef WL_CLIENT_SAE
cfg->evt_handler[WLC_E_JOIN_START] = wl_notify_start_auth;
wdev = ndev_to_wdev(dev);
if (!wdev) {
- WL_ERR(("wdev null. Do nothing\n"));
+ WL_DBG(("wdev(%s) null. Do nothing\n", dev->name));
return NOTIFY_DONE;
}
}
#ifdef WL_STATIC_IF
/* Register dummy n/w iface. FW init will happen only from dev_open */
-#ifdef WLEASYMESH
+#ifdef WLDWDS
ntype = NL80211_IFTYPE_AP;
#else
ntype = NL80211_IFTYPE_STATION;
#ifdef OEM_ANDROID
if (cfg->event_workq == NULL) {
- WL_ERR(("Event handler is not created\n"));
+ WL_ERR(("Event handler is not created (%s)\n", bcmevent_get_name(event_type)));
return;
}
#endif /* OEM_ANDROID */
if (notify) {
if (!IS_REGDOM_SELF_MANAGED(wiphy)) {
WL_UPDATE_CUSTOM_REGULATORY(wiphy);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
- rtnl_unlock();
-#endif
- wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
- rtnl_lock();
-#endif
+ wl_notify_regd(wiphy, NULL);
}
}
/* Start the event logging */
wl_add_remove_eventmsg(ndev, WLC_E_TRACE, TRUE);
#endif /* SHOW_LOGTRACE */
+#if defined(BCMDBUS)
+ if (!dhd->dhd_console_ms)
+ wl_add_remove_eventmsg(ndev, WLC_E_TRACE, FALSE);
+#endif
(void)memcpy_s(wdev->wiphy->perm_addr, ETHER_ADDR_LEN,
bcmcfg_to_prmry_ndev(cfg)->perm_addr, ETHER_ADDR_LEN);
return err;
}
+#ifdef BCMDBUS
+s32
+__wl_cfg80211_up_resume(dhd_pub_t *dhd)
+{
+ struct net_device *ndev = dhd_linux_get_primary_netdev(dhd);
+ struct bcm_cfg80211 *cfg;
+ struct wireless_dev *wdev;
+ s32 err = 0;
+#ifdef WL_HOST_BAND_MGMT
+ s32 ret = 0;
+#endif /* WL_HOST_BAND_MGMT */
+ u16 wl_iftype = 0;
+ u16 wl_mode = 0;
+
+ WL_DBG(("In\n"));
+
+ if (!ndev)
+ return -EINVAL;
+ cfg = wl_get_cfg(ndev);
+ wdev = ndev->ieee80211_ptr;
+ if (!cfg || !wdev)
+ return -EINVAL;
+
+#if defined(BCMDONGLEHOST)
+ err = dhd_config_dongle(cfg);
+ if (unlikely(err))
+ return err;
+#endif /* defined(BCMDONGLEHOST) */
+
+#ifdef SHOW_LOGTRACE
+ /* Start the event logging */
+ wl_add_remove_eventmsg(ndev, WLC_E_TRACE, TRUE);
+#endif /* SHOW_LOGTRACE */
+#if defined(BCMDBUS)
+ if (!dhd->dhd_console_ms)
+ wl_add_remove_eventmsg(ndev, WLC_E_TRACE, FALSE);
+#endif
+
+ if (cfg80211_to_wl_iftype(wdev->iftype, &wl_iftype, &wl_mode) < 0) {
+ return -EINVAL;
+ }
+ if (!dhd->fw_preinit) {
+ err = wl_config_infra(cfg, ndev, wl_iftype);
+ if (unlikely(err && err != -EINPROGRESS)) {
+ WL_ERR(("wl_config_infra failed\n"));
+ if (err == -1) {
+ WL_ERR(("return error %d\n", err));
+ return err;
+ }
+ }
+ }
+
+#ifdef WL_HOST_BAND_MGMT
+ /* By default the curr_band is initialized to BAND_AUTO */
+ if ((ret = wl_cfg80211_set_band(ndev, WLC_BAND_AUTO)) < 0) {
+ if (ret == BCME_UNSUPPORTED) {
+ /* Don't fail the initialization, lets just
+ * fall back to the original method
+ */
+ WL_ERR(("WL_HOST_BAND_MGMT defined, "
+ "but roam_band iovar not supported \n"));
+ } else {
+ WL_ERR(("roam_band failed. ret=%d", ret));
+ err = -1;
+ }
+ }
+#endif /* WL_HOST_BAND_MGMT */
+ return err;
+}
+#endif /* BCMDBUS */
+
static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
{
s32 err = 0;
struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
struct wireless_dev *wdev = ndev->ieee80211_ptr;
struct cfg80211_bss *bss = CFG80211_GET_BSS(wiphy, NULL, latest_bssid,
- wdev->ssid, wdev->ssid_len);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ wdev->u.client.ssid, wdev->u.client.ssid_len
+#else
+ wdev->ssid, wdev->ssid_len
+#endif
+ );
BCM_REFERENCE(bss);
if (init_roam_cache(cfg, ioctl_version) == 0) {
/* Enable support for Roam cache */
cfg->rcc_enabled = true;
- WL_ERR(("Roam channel cache enabled\n"));
+ WL_MSG(net->name, "Roam channel cache enabled\n");
} else {
WL_ERR(("Failed to enable RCC.\n"));
}
bssidx, &cfg->ioctl_buf_sync);
if (ret == BCME_OK) {
ies = (vndr_ie_buf_t *)cfg->ioctl_buf;
- WL_INFORM_MEM(("FW IE count:%d ", ies->iecount));
+ WL_INFORM_MEM(("FW IE count:%d\n", ies->iecount));
#ifdef GET_FW_IE_DATA
if (wl_dbg_level & WL_DBG_DBG) {
int i = 0;
ack = false;
} else {
err = wldev_iovar_setbuf(dev, "assoc_mgr_cmd", ambuf, param_len,
- cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+ cfg->ioctl_buf, WLC_IOCTL_MEDLEN, &cfg->ioctl_buf_sync);
if (unlikely(err)) {
WL_ERR(("Failed to send auth(%d)\n", err));
ack = false;
#endif /* SUPPORT_AP_RADIO_PWRSAVE */
#ifdef BCMWAPI_WPI
+#ifdef CFG80211_WAPI_BKPORT
+#define IS_WAPI_VER(version) (version == NL80211_WAPI_VERSION_1)
+#undef WLAN_AKM_SUITE_WAPI_PSK
+#define WLAN_AKM_SUITE_WAPI_PSK 0x000FAC13
+#undef WLAN_AKM_SUITE_WAPI_CERT
+#define WLAN_AKM_SUITE_WAPI_CERT 0x000FAC14
+#else
#ifdef OEM_ANDROID
#undef NL80211_WAPI_VERSION_1
#define NL80211_WAPI_VERSION_1 0
#define NL80211_WAPI_VERSION_1 1 << 2
#define IS_WAPI_VER(version) (version & NL80211_WAPI_VERSION_1)
#endif /* OEM_ANDROID */
+#endif /* CFG80211_WAPI_BKPORT */
#endif /* BCMWAPI_WPI */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
bool p2p_6g_enabled; /* P2P 6G support enabled */
#endif /* WL_P2P_6G */
u32 halpid;
+ u8 country[WLC_CNTRY_BUF_SZ];
+#ifdef BCMDBUS
+ bool bus_resuming;
+#endif /* BCMDBUS */
+#ifdef WL_ROAM_WAR
+ struct ether_addr roaming_bssid;
+#endif /* WL_ROAM_WAR */
#if defined(RSSIAVG)
wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
int autochannel;
int best_2g_ch;
int best_5g_ch;
+ int best_6g_ch;
};
/* Max auth timeout allowed in case of EAP is 70sec, additional 5 sec for
extern bool wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg,
struct net_device *ndev);
#endif /* CUSTOMER_HW6 */
+#if !defined(WL_TWT) && defined(WL_TWT_HAL_IF)
+extern s32 wl_cfgvendor_notify_twt_event(struct bcm_cfg80211 *cfg,
+ bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
+#endif /* !WL_TWT && WL_TWT_HAL_IF */
+#ifdef BCMDBUS
+s32
+__wl_cfg80211_up_resume(dhd_pub_t *dhd);
+#endif /* BCMDBUS */
void wl_wlfc_enable(struct bcm_cfg80211 *cfg, bool enable);
s32 wl_handle_join(struct bcm_cfg80211 *cfg, struct net_device *dev,
wlcfg_assoc_info_t *assoc_info);
#define NAN_RNG_GEOFENCE_MAX_RETRY_CNT 3u
+#define NAN_MAX_CHANNEL_INFO_SUPPORTED 4u
/*
* Discovery Beacon Interval config,
* Default value is 128 msec in 2G DW and 176 msec in 2G/5G DW.
uint8 *list;
} nan_mac_list_t;
+typedef struct nan_channel_info {
+ uint32 channel;
+ uint32 bandwidth;
+ uint32 nss;
+} nan_channel_info_t;
+
+typedef struct nan_ndl_sched_info {
+ uint32 num_channels;
+ nan_channel_info_t channel_info[NAN_MAX_CHANNEL_INFO_SUPPORTED];
+} nan_ndl_sched_info_t;
+
typedef struct wl_nan_sid_beacon_tune {
uint8 sid_enable; /* flag for sending service id in beacon */
uint8 sid_count; /* Limit for number of SIDs to be included in Beacons */
NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL = 224,
NAN_ATTRIBUTE_NSS = 225,
NAN_ATTRIBUTE_ENABLE_RANGING = 226,
- NAN_ATTRIBUTE_DW_EARLY_TERM = 227
+ NAN_ATTRIBUTE_DW_EARLY_TERM = 227,
+ NAN_ATTRIBUTE_CHANNEL_INFO = 228,
+ NAN_ATTRIBUTE_NUM_CHANNELS = 229,
+ NAN_ATTRIBUTE_INSTANT_MODE_ENABLE = 230,
+ NAN_ATTRIBUTE_INSTANT_COMM_CHAN = 231,
+ NAN_ATTRIBUTE_MAX = 232
} NAN_ATTRIBUTE;
enum geofence_suspend_reason {
BCM_REFERENCE(ndev);
CFGP2P_DBG(("enter\n"));
- if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0) {
+#ifdef BCMDBUS
+ if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0 && !cfg->bus_resuming)
+#else
+ if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0)
+#endif /* BCMDBUS */
+ {
CFGP2P_ERR(("do nothing, already initialized\n"));
goto exit;
}
* so that time, the ifidx returned in WLC_E_IF should be used for populating
* the netinfo
*/
+#ifdef BCMDBUS
+ if (!cfg->bus_resuming)
+#endif /* BCMDBUS */
ret = wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_IF_TYPE_STA, 0, bssidx, 0);
if (unlikely(ret)) {
goto exit;
}
#endif /* WL_IFACE_MGMT */
- if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
+#ifdef BCMDBUS
+ if (!cfg->bus_resuming && (wl_get_p2p_status(cfg, DISCOVERY_ON)))
+#else
+ if (wl_get_p2p_status(cfg, DISCOVERY_ON))
+#endif /* BCMDBUS */
+ {
CFGP2P_DBG((" DISCOVERY is already initialized, we have nothing to do\n"));
goto set_ie;
}
#endif
/* Register with a dummy MAC addr */
- memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
+ dev_addr_set(net, temp_addr);
#ifndef WL_NEWCFG_PRIVCMD_SUPPORT
wdev->wiphy = cfg->wdev->wiphy;
#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);
+ dev_addr_set(cfg->p2p_net, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE));
#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
/* store p2p wdev ptr for further reference. */
cfg->p2p_prb_noti = false;
#endif
- CFGP2P_DBG(("P2P interface started\n"));
+ printf("P2P interface started\n");
exit:
return ret;
p2p_on(cfg) = false;
- CFGP2P_DBG(("Exit. P2P interface stopped\n"));
+ printf("Exit. P2P interface stopped\n");
return;
}
}
return false;
}
+
+#ifdef BCMDBUS
+int
+wl_cfgp2p_start_p2p_device_resume(dhd_pub_t *dhd)
+{
+ int ret = 0;
+#ifdef WL_CFG80211_P2P_DEV_IF
+ struct net_device *primary_ndev = dhd_linux_get_primary_netdev(dhd);
+ struct bcm_cfg80211 *cfg;
+ struct wiphy *wiphy;
+
+ if (!primary_ndev)
+ return -EINVAL;
+ cfg = wl_get_cfg(primary_ndev);
+ if (!cfg)
+ return -EINVAL;
+
+ RETURN_EIO_IF_NOT_UP(cfg);
+ if (!p2p_on(cfg))
+ return -EINVAL;
+
+ rtnl_lock();
+ wiphy = bcmcfg_to_wiphy(cfg);
+ cfg->bus_resuming = TRUE;
+ ret = wl_cfgp2p_start_p2p_device(wiphy, cfg->wdev);
+ cfg->bus_resuming = FALSE;
+ printf("P2P interface resumed\n");
+ rtnl_unlock();
+#endif
+
+ return ret;
+}
+#endif /* BCMDBUS */
* instead of channel in actframe iovar.
*/
#define FW_MAJOR_VER_ACTFRAME_CHSPEC 14
+
+#ifdef BCMDBUS
+int
+wl_cfgp2p_start_p2p_device_resume(dhd_pub_t *dhd);
+#endif /* BCMDBUS */
#endif /* _wl_cfgp2p_h_ */
if (cfg->autochannel && ndev) {
#if defined(BSSCACHE)
- wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version,
- &cfg->best_2g_ch, &cfg->best_5g_ch);
+ wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl,
+ &cfg->best_2g_ch, &cfg->best_5g_ch, &cfg->best_6g_ch);
#else
- wl_ext_get_best_channel(ndev, bss_list, ioctl_version,
- &cfg->best_2g_ch, &cfg->best_5g_ch);
+ wl_ext_get_best_channel(ndev, bss_list,
+ &cfg->best_2g_ch, &cfg->best_5g_ch, &cfg->best_6g_ch);
#endif
}
static void
wl_cfgscan_populate_scan_channel(struct bcm_cfg80211 *cfg,
struct ieee80211_channel **channels, u32 n_channels,
- u16 *channel_list, u32 target_channel)
+ u16 *channel_list, struct wl_chan_info *chan_info)
{
- u32 i = 0;
- u32 chanspec = 0;
- u32 channel;
+ u32 i, chanspec = 0;
for (i=0; i<n_channels; i++) {
- channel = ieee80211_frequency_to_channel(channels[i]->center_freq);
- if (channel != target_channel)
- continue;
- if (!dhd_conf_match_channel(cfg->pub, channel))
- return;
-
chanspec = wl_freq_to_chanspec(channels[i]->center_freq);
if (chanspec == INVCHANSPEC) {
WL_ERR(("Invalid chanspec! Skipping channel\n"));
continue;
}
-
- channel_list[0] = chanspec;
- break;
+ if (chan_info->band == CHSPEC2WLC_BAND(chanspec) &&
+ chan_info->chan == wf_chspec_ctlchan(chanspec)) {
+ channel_list[0] = chanspec;
+ break;
+ }
}
- WL_SCAN(("chan: %d, chanspec: %x\n", target_channel, chanspec));
+ WL_SCAN(("chan: %s-%d, chanspec: %x\n",
+ WLCBAND2STR(chan_info->band), chan_info->chan, chanspec));
}
#endif
struct cfg80211_scan_request *request)
{
#ifdef SCAN_SUPPRESS
+ struct wl_chan_info chan_info;
u32 channel;
#endif
wl_scan_params_t *params = NULL;
cur_offset = channel_offset;
/* Copy channel array if applicable */
#ifdef SCAN_SUPPRESS
- channel = wl_ext_scan_suppress(ndev, scan_params, cfg->scan_params_v2);
+ channel = wl_ext_scan_suppress(ndev, scan_params, cfg->scan_params_v2, &chan_info);
if (channel) {
n_channels = 1;
if ((n_channels > 0) && chan_list) {
if (len >= (scan_param_size + (n_channels * sizeof(u16)))) {
wl_cfgscan_populate_scan_channel(cfg,
request->channels, request->n_channels,
- chan_list, channel);
+ chan_list, &chan_info);
cur_offset += (n_channels * (sizeof(u16)));
}
}
}
#ifdef WL_EXT_IAPSTA
- if (wl_ext_in4way_sync(ndev, STA_FAKE_SCAN_IN_CONNECT, WL_EXT_STATUS_SCANNING, NULL)) {
+ err = wl_ext_in4way_sync(ndev, STA_FAKE_SCAN_IN_CONNECT, WL_EXT_STATUS_SCANNING, NULL);
+ if (err) {
+ wl_event_msg_t msg;
mutex_lock(&cfg->scan_sync);
+ bzero(&msg, sizeof(wl_event_msg_t));
+ msg.event_type = hton32(WLC_E_ESCAN_RESULT);
+ msg.status = hton32(WLC_E_STATUS_SUCCESS);
+ wl_cfg80211_event(ndev, &msg, NULL);
goto scan_success;
}
#endif
}
#endif /* ESCAN_CHANNEL_CACHE */
- WL_DBG_MEM(("channel cnt:%d\n", info->chan_cnt));
+ WL_SCAN(("channel cnt:%d\n", info->chan_cnt));
return BCME_OK;
}
s32
wl_cfgscan_get_band_freq_list(struct bcm_cfg80211 *cfg, int band,
- uint16 *list, uint32 *num_channels)
+ uint32 *list, uint32 *num_channels)
{
s32 err = BCME_OK;
uint32 i, freq, list_count, count = 0;
list_count = ((wl_chanspec_list_v1_t *)list)->count;
for (i = 0; i < list_count; i++) {
chspec = dtoh32(((wl_chanspec_list_v1_t *)list)->chspecs[i].chanspec);
+ if (!CHSPEC_IS20(chspec)) {
+ continue;
+ }
chaninfo = dtoh32(((wl_chanspec_list_v1_t *)list)->chspecs[i].chaninfo);
freq = wl_channel_to_frequency(wf_chspec_ctlchan(chspec),
CHSPEC_BAND(chspec));
if (((band & WIFI_BAND_BG) && CHSPEC_IS2G(chspec)) ||
((band & WIFI_BAND_6GHZ) && CHSPEC_IS6G(chspec))) {
/* add 2g/6g channels */
- list[i] = freq;
+ list[count] = freq;
count++;
}
/* handle 5g separately */
continue;
}
- list[i] = freq;
+ list[count] = freq;
count++;
}
}
extern bool wl_cfgscan_is_dfs_set(wifi_band band);
extern s32 wl_cfgscan_get_band_freq_list(struct bcm_cfg80211 *cfg, int band,
- uint16 *list, uint32 *num_channels);
+ uint32 *list, uint32 *num_channels);
#endif /* DHD_GET_VALID_CHANNELS */
#endif /* _wl_cfgscan_h_ */
iter_cnt_to_send -= cnt;
cache->tot_consumed += cnt;
/* Push the data to the skb */
+#ifdef ANDROID13_KERNEL515_BKPORT
+ nla_put_nohdr(skb, cnt * sizeof(wifi_gscan_result_t), ptr);
+#else
nla_append(skb, cnt * sizeof(wifi_gscan_result_t), ptr);
+#endif
if (cache->tot_consumed == cache->tot_count) {
cache = cache->next;
}
{
int err = 0, type, band;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
- uint16 *reply = NULL;
+ uint32 *reply = NULL;
uint32 reply_len = 0, num_channels, mem_needed;
struct sk_buff *skb;
dhd_pub_t *dhdp;
ret = dhd_cfgvendor_priv_string_handler(cfg, wdev, nlioc, buf);
if (ret) {
- WL_ERR(("dhd_cfgvendor returned error %d", ret));
+ WL_ERR(("dhd_cfgvendor returned error %d\n", ret));
vfree(buf);
return ret;
}
dtoh32(cca_result->secs[0].congest_obss),
dtoh32(cca_result->secs[0].interference)));
} else {
- WL_TRACE(("cca_get_stats is unsupported \n"));
+ WL_INFORM(("cca_get_stats is unsupported \n"));
}
/* If cca_get_stats is unsupported, cca_busy_time has zero value as initial value */
#endif /* DBG_PKT_MON */
#ifdef KEEP_ALIVE
+/* max size of IP packet for keep alive */
+#define MKEEP_ALIVE_IP_PKT_MAX 256
+
static int wl_cfgvendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
- /* max size of IP packet for keep alive */
- const int MKEEP_ALIVE_IP_PKT_MAX = 256;
-
int ret = BCME_OK, rem, type;
uint8 mkeep_alive_id = 0;
uint8 *ip_pkt = NULL;
#endif /* KEEP_ALIVE */
#if defined(PKT_FILTER_SUPPORT) && defined(APF)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+const struct nla_policy apf_atrribute_policy[APF_ATTRIBUTE_MAX] = {
+ [APF_ATTRIBUTE_VERSION] = { .type = NLA_U32 },
+ [APF_ATTRIBUTE_MAX_LEN] = { .type = NLA_U32 },
+ [APF_ATTRIBUTE_PROGRAM] = { .type = NLA_BINARY },
+ [APF_ATTRIBUTE_PROGRAM_LEN] = { .type = NLA_U32 },
+};
+#endif /* LINUX_VERSION >= 5.3 */
+
static int
wl_cfgvendor_apf_get_capabilities(struct wiphy *wiphy,
struct wireless_dev *wdev, const void *data, int len)
}
#endif /* WL_SAR_TX_POWER */
-static struct wiphy_vendor_command wl_vendor_cmds [] = {
- {
- {
- .vendor_id = OUI_BRCM,
- .subcmd = BRCM_VENDOR_SCMD_PRIV_STR
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_priv_string_handler
- },
-#ifdef BCM_PRIV_CMD_SUPPORT
- {
- {
- .vendor_id = OUI_BRCM,
- .subcmd = BRCM_VENDOR_SCMD_BCM_STR
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_priv_bcm_handler
- },
-#endif /* BCM_PRIV_CMD_SUPPORT */
-#if defined(WL_SAE) || defined(WL_CLIENT_SAE)
- {
- {
- .vendor_id = OUI_BRCM,
- .subcmd = BRCM_VENDOR_SCMD_BCM_PSK
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_sae_password
- },
-#endif /* WL_SAE || WL_CLIENT_SAE */
- {
- {
- .vendor_id = OUI_BRCM,
- .subcmd = BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_connect_params_handler
- },
- {
- {
- .vendor_id = OUI_BRCM,
- .subcmd = BRCM_VENDOR_SCMD_SET_START_AP_PARAMS
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_start_ap_params_handler
- },
-#ifdef GSCAN_SUPPORT
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_gscan_get_capabilities
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_SET_CONFIG
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_scan_cfg
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_batch_scan_cfg
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_initiate_gscan
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_enable_full_scan_result
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_SET_HOTLIST
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_hotlist_cfg
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_gscan_get_batch_results
- },
-#endif /* GSCAN_SUPPORT */
-#if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_gscan_get_channel_list
- },
-#endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
-#ifdef RTT_SUPPORT
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = RTT_SUBCMD_SET_CONFIG
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_rtt_set_config
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = RTT_SUBCMD_CANCEL_CONFIG
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_rtt_cancel_config
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = RTT_SUBCMD_GETCAPABILITY
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_rtt_get_capability
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = RTT_SUBCMD_GETAVAILCHANNEL
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_rtt_get_responder_info
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = RTT_SUBCMD_SET_RESPONDER
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_rtt_set_responder
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = RTT_SUBCMD_CANCEL_RESPONDER
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_rtt_cancel_responder
- },
-#endif /* RTT_SUPPORT */
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_get_feature_set
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_get_feature_set_matrix
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = ANDR_WIFI_RANDOM_MAC_OUI
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_rand_mac_oui
- },
-#ifdef CUSTOM_FORCE_NODFS_FLAG
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = ANDR_WIFI_NODFS_CHANNELS
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_nodfs_flag
- },
-#endif /* CUSTOM_FORCE_NODFS_FLAG */
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = ANDR_WIFI_SET_COUNTRY
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_country
- },
-#ifdef LINKSTAT_SUPPORT
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = LSTATS_SUBCMD_GET_INFO
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_lstats_get_info
- },
-#endif /* LINKSTAT_SUPPORT */
+#if !defined(WL_TWT) && defined(WL_TWT_HAL_IF)
+static int
+wl_cfgvendor_twt_setup(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len)
+{
+ wl_twt_config_t val;
+ s32 bw;
+ s32 type, rem_attr;
+ u8 mybuf[WLC_IOCTL_SMLEN] = {0};
+ u8 resp_buf[WLC_IOCTL_SMLEN] = {0};
+ const struct nlattr *iter;
+ uint8 *rem = mybuf;
+ uint16 rem_len = sizeof(mybuf);
+
+ bzero(&val, sizeof(val));
+ val.version = WL_TWT_SETUP_VER;
+ val.length = sizeof(val.version) + sizeof(val.length);
+
+ /* Default values, Override Below */
+ val.desc.flow_flags = 0;
+ val.desc.wake_time_h = 0xFFFFFFFF;
+ val.desc.wake_time_l = 0xFFFFFFFF;
+ val.desc.wake_int_min = 0xFFFFFFFF;
+ val.desc.wake_int_max = 0xFFFFFFFF;
+ val.desc.wake_dur_min = 0xFFFFFFFF;
+ val.desc.wake_dur_max = 0xFFFFFFFF;
+ val.desc.avg_pkt_num = 0xFFFFFFFF;
+ val.desc.avg_pkt_size = 0xFFFFFFFF;
+
+ nla_for_each_attr(iter, data, len, rem_attr) {
+ type = nla_type(iter);
+ switch (type) {
+ case ANDR_TWT_ATTR_CONFIG_ID:
+ /* Config ID */
+ val.desc.configID = nla_get_u8(iter);
+ break;
+ case ANDR_TWT_ATTR_NEGOTIATION_TYPE:
+ /* negotiation_type */
+ val.desc.negotiation_type = nla_get_u8(iter);
+ break;
+ case ANDR_TWT_ATTR_TRIGGER_TYPE:
+ /* Trigger Type */
+ if (nla_get_u8(iter) == 1) {
+ val.desc.flow_flags |= WL_TWT_FLOW_FLAG_TRIGGER;
+ }
+ break;
+ case ANDR_TWT_ATTR_WAKE_DURATION:
+ /* Wake Duration */
+ val.desc.wake_dur = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_WAKE_INTERVAL:
+ /* Wake interval */
+ val.desc.wake_int = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_WAKETIME_OFFSET:
+ /* Wake Time parameter */
+ val.desc.wake_time_h = 0;
+ val.desc.wake_time_l = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_WAKE_INTERVAL_MIN:
+ /* Minimum allowed Wake interval */
+ val.desc.wake_int_min = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_WAKE_INTERVAL_MAX:
+ /* Max Allowed Wake interval */
+ val.desc.wake_int_max = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_WAKE_DURATION_MIN:
+ /* Minimum allowed Wake duration */
+ val.desc.wake_dur_min = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_WAKE_DURATION_MAX:
+ /* Maximum allowed Wake duration */
+ val.desc.wake_dur_max = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_AVG_PKT_NUM:
+ /* Average number of packets */
+ val.desc.avg_pkt_num = nla_get_u32(iter);
+ break;
+ case ANDR_TWT_ATTR_AVG_PKT_SIZE:
+ /* Average packets size */
+ val.desc.avg_pkt_size = nla_get_u32(iter);
+ break;
+ default:
+ WL_ERR(("Invalid setup attribute type %d\n", type));
+ break;
+ }
+ }
-#ifdef GSCAN_SUPPORT
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = GSCAN_SUBCMD_SET_EPNO_SSID
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_epno_cfg
+ bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_CONFIG,
+ sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
+ if (bw != BCME_OK) {
+ goto exit;
+ }
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_lazy_roam_cfg
+ bw = wldev_iovar_setbuf(wdev_to_ndev(wdev), "twt",
+ mybuf, sizeof(mybuf) - rem_len, resp_buf, WLC_IOCTL_SMLEN, NULL);
+ if (bw < 0) {
+ WL_ERR(("twt config set failed. ret:%d\n", bw));
+ } else {
+ WL_INFORM(("twt config setup succeeded, config ID %d "
+ "Negotiation type %d flow flags %d\n", val.desc.configID,
+ val.desc.negotiation_type, val.desc.flow_flags));
+ }
- },
- {
- {
- .vendor_id = OUI_GOOGLE,
- .subcmd = WIFI_SUBCMD_ENABLE_LAZY_ROAM
- },
- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+exit:
+ return bw;
+}
+
+static int
+wl_cfgvendor_twt_teardown(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len)
+{
+ wl_twt_teardown_t val;
+ s32 bw;
+ s32 type, rem_attr;
+ u8 mybuf[WLC_IOCTL_SMLEN] = {0};
+ u8 res_buf[WLC_IOCTL_SMLEN] = {0};
+ const struct nlattr *iter;
+ uint8 *rem = mybuf;
+ uint16 rem_len = sizeof(mybuf);
+
+ bzero(&val, sizeof(val));
+ val.version = WL_TWT_TEARDOWN_VER;
+ val.length = sizeof(val.version) + sizeof(val.length);
+
+ /* Default values, Override Below */
+ val.teardesc.flow_id = 0xFF;
+ val.teardesc.bid = 0xFF;
+
+ nla_for_each_attr(iter, data, len, rem_attr) {
+ type = nla_type(iter);
+ switch (type) {
+ case ANDR_TWT_ATTR_CONFIG_ID:
+ /* Config ID */
+ val.configID = nla_get_u8(iter);
+ break;
+ case ANDR_TWT_ATTR_NEGOTIATION_TYPE:
+ /* negotiation_type */
+ val.teardesc.negotiation_type = nla_get_u8(iter);
+ break;
+ case ANDR_TWT_ATTR_ALL_TWT:
+ /* all twt */
+ val.teardesc.alltwt = nla_get_u8(iter);
+ break;
+ default:
+ WL_ERR(("Invalid teardown attribute type %d\n", type));
+ break;
+ }
+ }
+
+ bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_TEARDOWN,
+ sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
+ if (bw != BCME_OK) {
+ goto exit;
+ }
+
+ bw = wldev_iovar_setbuf(wdev_to_ndev(wdev), "twt",
+ mybuf, sizeof(mybuf) - rem_len, res_buf, WLC_IOCTL_SMLEN, NULL);
+ if (bw < 0) {
+ WL_ERR(("twt teardown failed. ret:%d\n", bw));
+ } else {
+ WL_INFORM(("twt teardown succeeded, config ID %d "
+ "Negotiation type %d alltwt %d\n", val.configID,
+ val.teardesc.negotiation_type, val.teardesc.alltwt));
+ }
+
+exit:
+ return bw;
+}
+
+static int
+wl_cfgvendor_twt_info_frame(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len)
+{
+ wl_twt_info_t val;
+ int bw;
+ s32 type, rem_attr;
+ const struct nlattr *iter;
+ u8 mybuf[WLC_IOCTL_SMLEN] = {0};
+ u8 res_buf[WLC_IOCTL_SMLEN] = {0};
+ uint8 *rem = mybuf;
+ uint16 rem_len = sizeof(mybuf);
+ uint32 val32 = 0;
+
+ bzero(&val, sizeof(val));
+ val.version = WL_TWT_INFO_VER;
+ val.length = sizeof(val.version) + sizeof(val.length);
+
+ /* Default values, Override Below */
+ val.infodesc.flow_id = 0xFF;
+ val.desc.next_twt_h = 0xFFFFFFFF;
+ val.desc.next_twt_l = 0xFFFFFFFF;
+
+ nla_for_each_attr(iter, data, len, rem_attr) {
+ type = nla_type(iter);
+ if (type == ANDR_TWT_ATTR_CONFIG_ID) {
+ /* Config ID */
+ val.configID = nla_get_u8(iter);
+ } else if (type == ANDR_TWT_ATTR_RESUME_TIME) {
+ /* Resume offset */
+ val32 = nla_get_u32(iter);
+ if (!((val32 == 0) || (val32 == -1))) {
+ val.infodesc.next_twt_h = 0;
+ val.infodesc.next_twt_l = val32;
+ val.infodesc.flow_flags |= WL_TWT_INFO_FLAG_RESUME;
+ }
+ } else if (type == ANDR_TWT_ATTR_ALL_TWT) {
+ /* all twt */
+ val32 = (uint32)nla_get_u8(iter);
+ if (val32) {
+ val.infodesc.flow_flags |= WL_TWT_INFO_FLAG_ALL_TWT;
+ }
+ } else {
+ WL_ERR(("Invalid info frame attribute type %d\n", type));
+ }
+ }
+
+ bw = bcm_pack_xtlv_entry(&rem, &rem_len, WL_TWT_CMD_INFO,
+ sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
+ if (bw != BCME_OK) {
+ goto exit;
+ }
+
+ bw = wldev_iovar_setbuf(wdev_to_ndev(wdev), "twt",
+ mybuf, sizeof(mybuf) - rem_len, res_buf, WLC_IOCTL_SMLEN, NULL);
+ if (bw < 0) {
+ WL_ERR(("twt info frame failed. ret:%d\n", bw));
+ } else {
+ WL_INFORM(("twt info frame succeeded, config ID %d\n", val.configID));
+ }
+
+exit:
+ return bw;
+}
+
+static int
+wl_cfgvendor_twt_stats_update_v2(struct wiphy *wiphy, wl_twt_stats_v2_t *stats)
+{
+ u32 i;
+ wl_twt_peer_stats_v2_t *peer_stats;
+ struct sk_buff *skb;
+ int32 mem_needed;
+ int ret = BCME_OK;
+
+ mem_needed = BRCM_TWT_HAL_VENDOR_EVENT_BUF_LEN;
+
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
+ if (unlikely(!skb)) {
+ WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__, mem_needed));
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_NUM_PEER_STATS, stats->num_stats);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_NUM_PEER_STATS, ret:%d\n", ret));
+ goto fail;
+ }
+
+ for (i = 0; i < stats->num_stats; i++) {
+ peer_stats = &stats->peer_stats_list[i];
+
+ WL_INFORM_MEM(("%u %u %u %u %u",
+ peer_stats->eosp_dur_avg, peer_stats->tx_pkts_avg, peer_stats->rx_pkts_avg,
+ peer_stats->tx_pkt_sz_avg, peer_stats->rx_pkt_sz_avg));
+ ret = nla_put_u8(skb, ANDR_TWT_ATTR_CONFIG_ID, peer_stats->configID);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_CONFIG_ID, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_AVG_PKT_NUM_TX, peer_stats->tx_pkts_avg);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_AVG_PKT_NUM_TX, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_AVG_PKT_SIZE_TX, peer_stats->tx_pkt_sz_avg);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_AVG_PKT_SIZE_TX, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_AVG_PKT_NUM_RX, peer_stats->rx_pkts_avg);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_AVG_PKT_NUM_RX, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_AVG_PKT_SIZE_RX, peer_stats->rx_pkt_sz_avg);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_AVG_PKT_SIZE_RX, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_AVG_EOSP_DUR, peer_stats->eosp_dur_avg);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_AVG_EOSP_DUR, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_EOSP_CNT, peer_stats->eosp_count);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_EOSP_CNT, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_NUM_SP, peer_stats->sp_seq);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_NUM_SP, ret:%d\n", ret));
+ goto fail;
+ }
+ }
+
+ ret = cfg80211_vendor_cmd_reply(skb);
+ if (unlikely(ret)) {
+ WL_ERR(("vendor command reply failed, ret=%d\n", ret));
+ }
+ return ret;
+
+fail:
+ /* Free skb for failure cases */
+ if (skb) {
+ kfree_skb(skb);
+ }
+ return ret;
+}
+
+static int
+wl_cfgvendor_twt_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len, bool clear_stats)
+{
+ wl_twt_stats_cmd_v1_t query;
+ wl_twt_stats_v2_t stats_v2;
+ s32 type, rem_attr;
+ const struct nlattr *iter;
+ int ret = BCME_OK;
+ char iovbuf[WLC_IOCTL_SMLEN] = {0, };
+ uint8 *pxtlv = NULL;
+ uint8 *iovresp = NULL;
+ uint16 buflen = 0, bufstart = 0;
+ struct bcm_cfg80211 *cfg = wl_get_cfg(wdev_to_ndev(wdev));
+
+ bzero(&query, sizeof(query));
+ query.version = WL_TWT_STATS_CMD_VERSION_1;
+ query.length = sizeof(query) - OFFSETOF(wl_twt_stats_cmd_v1_t, peer);
+
+ /* Default values, Override Below */
+ query.num_bid = 0xFF;
+ query.num_fid = 0xFF;
+
+ if (clear_stats) {
+ query.flags |= WL_TWT_STATS_CMD_FLAGS_RESET;
+ }
+ nla_for_each_attr(iter, data, len, rem_attr) {
+ type = nla_type(iter);
+ if (type == ANDR_TWT_ATTR_CONFIG_ID) {
+ /* Config ID */
+ query.configID = nla_get_u8(iter);
+ } else {
+ WL_ERR(("Invalid TWT stats attribute type %d\n", type));
+ }
+ }
+
+ iovresp = (uint8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
+ if (iovresp == NULL) {
+ WL_ERR(("%s: iov resp memory alloc exited\n", __FUNCTION__));
+ goto exit;
+ }
+
+ buflen = bufstart = WLC_IOCTL_SMLEN;
+ pxtlv = (uint8 *)iovbuf;
+ ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_TWT_CMD_STATS,
+ sizeof(query), (uint8 *)&query, BCM_XTLV_OPTION_ALIGN32);
+ if (ret != BCME_OK) {
+ WL_ERR(("%s : Error return during pack xtlv :%d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+
+ if ((ret = wldev_iovar_getbuf(wdev_to_ndev(wdev), "twt", iovbuf, bufstart-buflen,
+ iovresp, WLC_IOCTL_MEDLEN, NULL))) {
+ WL_ERR(("twt status failed with err=%d \n", ret));
+ goto exit;
+ }
+
+ (void)memcpy_s(&stats_v2, sizeof(stats_v2), iovresp, sizeof(stats_v2));
+
+ if (dtoh16(stats_v2.version) == WL_TWT_STATS_VERSION_2) {
+ if (!clear_stats) {
+ WL_ERR(("stats query ver %d, \n", dtoh16(stats_v2.version)));
+ ret = wl_cfgvendor_twt_stats_update_v2(wiphy, (wl_twt_stats_v2_t*)iovresp);
+ }
+ } else {
+ ret = BCME_UNSUPPORTED;
+ WL_ERR(("Version 1 unsupported. ver %d, \n", dtoh16(stats_v2.version)));
+ goto exit;
+ }
+
+exit:
+ if (iovresp) {
+ MFREE(cfg->osh, iovresp, WLC_IOCTL_MEDLEN);
+ }
+
+ return ret;
+}
+
+static int
+wl_cfgvendor_twt_get_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len)
+{
+ return wl_cfgvendor_twt_stats(wiphy, wdev, data, len, false);
+}
+
+static int
+wl_cfgvendor_twt_clear_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len)
+{
+ return wl_cfgvendor_twt_stats(wiphy, wdev, data, len, true);
+}
+
+static int
+wl_cfgvendor_twt_update_cap(struct wiphy *wiphy, wl_twt_cap_t *result)
+{
+ struct sk_buff *skb;
+ int32 mem_needed;
+ int ret = BCME_OK;
+
+ WL_INFORM_MEM(("TWT Capabilites Device,Peer 0x%04x 0x%04x\n",
+ result->device_cap, result->peer_cap));
+
+ mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
+
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
+ if (unlikely(!skb)) {
+ WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__, mem_needed));
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_DEVICE_CAP, result->device_cap);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_DEVICE_CAP, ret:%d\n", ret));
+ goto fail;
+ }
+ ret = nla_put_u32(skb, ANDR_TWT_ATTR_PEER_CAP, result->peer_cap);
+ if (ret < 0) {
+ WL_ERR(("Failed to put ANDR_TWT_ATTR_PEER_CAP, ret:%d\n", ret));
+ goto fail;
+ }
+
+ ret = cfg80211_vendor_cmd_reply(skb);
+ if (unlikely(ret)) {
+ WL_ERR(("vendor command reply failed, ret=%d\n", ret));
+ }
+ return ret;
+
+fail:
+ /* Free skb for failure cases */
+ if (skb) {
+ kfree_skb(skb);
+ }
+ return ret;
+}
+
+static int
+wl_cfgvendor_twt_cap(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int len)
+{
+ int ret = BCME_OK;
+ char iovbuf[WLC_IOCTL_SMLEN] = {0, };
+ uint8 *pxtlv = NULL;
+ uint8 *iovresp = NULL;
+ wl_twt_cap_cmd_t cmd_cap;
+ wl_twt_cap_t result;
+
+ uint16 buflen = 0, bufstart = 0;
+ struct bcm_cfg80211 *cfg = wl_get_cfg(wdev_to_ndev(wdev));
+
+ bzero(&cmd_cap, sizeof(cmd_cap));
+
+ cmd_cap.version = WL_TWT_CAP_CMD_VERSION_1;
+ cmd_cap.length = sizeof(cmd_cap) - OFFSETOF(wl_twt_cap_cmd_t, peer);
+
+ iovresp = (uint8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
+ if (iovresp == NULL) {
+ WL_ERR(("%s: iov resp memory alloc exited\n", __FUNCTION__));
+ goto exit;
+ }
+
+ buflen = bufstart = WLC_IOCTL_SMLEN;
+ pxtlv = (uint8 *)iovbuf;
+
+ ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_TWT_CMD_CAP,
+ sizeof(cmd_cap), (uint8 *)&cmd_cap, BCM_XTLV_OPTION_ALIGN32);
+ if (ret != BCME_OK) {
+ WL_ERR(("%s : Error return during pack xtlv :%d\n", __FUNCTION__, ret));
+ goto exit;
+ }
+
+ if ((ret = wldev_iovar_getbuf(wdev_to_ndev(wdev), "twt", iovbuf, bufstart-buflen,
+ iovresp, WLC_IOCTL_MEDLEN, NULL))) {
+ WL_ERR(("Getting twt status failed with err=%d \n", ret));
+ goto exit;
+ }
+
+ (void)memcpy_s(&result, sizeof(result), iovresp, sizeof(result));
+
+ if (dtoh16(result.version) == WL_TWT_CAP_CMD_VERSION_1) {
+ WL_ERR(("capability ver %d, \n", dtoh16(result.version)));
+ ret = wl_cfgvendor_twt_update_cap(wiphy, &result);
+ return ret;
+ } else {
+ ret = BCME_UNSUPPORTED;
+ WL_ERR(("Version 1 unsupported. ver %d, \n", dtoh16(result.version)));
+ goto exit;
+ }
+
+exit:
+ if (iovresp) {
+ MFREE(cfg->osh, iovresp, WLC_IOCTL_MEDLEN);
+ }
+
+ return ret;
+}
+
+static int
+wl_cfgvendor_twt_update_setup_response(struct sk_buff *skb, void *event_data)
+{
+ s32 err = BCME_OK;
+ const wl_twt_setup_cplt_t *setup_cplt = (wl_twt_setup_cplt_t *)event_data;
+ const wl_twt_sdesc_t *sdesc = (const wl_twt_sdesc_t *)&setup_cplt[1];
+
+ WL_DBG(("TWT_SETUP: status %d, reason %d, configID %d, setup_cmd %d, flow_flags 0x%x,"
+ " flow_id %d, channel %d, negotiation_type %d, wake_time_h %u, wake_time_l %u,"
+ " wake_dur %u, wake_int %u\n",
+ (int)setup_cplt->status, (int)setup_cplt->reason_code, (int)setup_cplt->configID,
+ (int)sdesc->setup_cmd, sdesc->flow_flags, (int)sdesc->flow_id, (int)sdesc->channel,
+ (int)sdesc->negotiation_type, sdesc->wake_time_h, sdesc->wake_time_l,
+ sdesc->wake_dur, sdesc->wake_int));
+
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_SUB_EVENT, ANDR_TWT_EVENT_SETUP);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_SUB_EVENT failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_CONFIG_ID, setup_cplt->configID);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_CONFIG_ID failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_REASON_CODE, setup_cplt->reason_code);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_REASON_CODE failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_STATUS, !!(setup_cplt->status));
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_STATUS failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_NEGOTIATION_TYPE, sdesc->negotiation_type);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_NEGOTIATION_TYPE failed\n"));
+ goto fail;
+ }
+ err = nla_put_u32(skb, ANDR_TWT_ATTR_WAKE_DURATION, sdesc->wake_dur);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u32 WIFI_TWT_ATTR_WAKE_DURATION failed\n"));
+ goto fail;
+ }
+ err = nla_put_u32(skb, ANDR_TWT_ATTR_WAKE_INTERVAL, sdesc->wake_int);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u32 WIFI_TWT_ATTR_WAKE_INTERVAL failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_TRIGGER_TYPE,
+ !!(sdesc->flow_flags & WL_TWT_FLOW_FLAG_TRIGGER));
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_TRIGGER_TYPE failed\n"));
+ goto fail;
+ }
+
+fail:
+ return err;
+}
+
+static int
+wl_cfgvendor_twt_update_teardown_response(struct sk_buff *skb, void *event_data)
+{
+ s32 err = BCME_OK;
+ const wl_twt_teardown_cplt_t *td_cplt = (wl_twt_teardown_cplt_t *)event_data;
+ const wl_twt_teardesc_t *teardesc = (const wl_twt_teardesc_t *)&td_cplt[1];
+
+ WL_DBG(("TWT_TEARDOWN: status %d, reason %d, configID %d, flow_id %d, negotiation_type %d,"
+ " bid %d, alltwt %d\n", (int)td_cplt->status, (int)td_cplt->reason_code,
+ (int)td_cplt->configID, (int)teardesc->flow_id, (int)teardesc->negotiation_type,
+ (int)teardesc->bid, (int)teardesc->alltwt));
+
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_SUB_EVENT, ANDR_TWT_EVENT_TEARDOWN);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_SUB_EVENT failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_REASON_CODE, td_cplt->reason_code);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 ANDR_TWT_ATTR_REASON_CODE failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_STATUS, !!(td_cplt->status));
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 ANDR_TWT_ATTR_STATUS failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_CONFIG_ID, td_cplt->configID);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 ANDR_TWT_ATTR_CONFIG_ID failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_ALL_TWT, teardesc->alltwt);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 ANDR_TWT_ATTR_ALL_TWT failed\n"));
+ goto fail;
+ }
+
+fail:
+ return err;
+}
+
+static int
+wl_cfgvendor_twt_update_infoframe_response(struct sk_buff *skb, void *event_data)
+{
+ s32 err = BCME_OK;
+ const wl_twt_info_cplt_t *info_cplt = (wl_twt_info_cplt_t *)event_data;
+ const wl_twt_infodesc_t *infodesc = (const wl_twt_infodesc_t *)&info_cplt[1];
+
+ WL_DBG(("TWT_INFOFRM: status %d, reason %d, configID %d, flow_flags 0x%x, flow_id %d,"
+ " next_twt_h %u, next_twt_l %u\n", (int)info_cplt->status,
+ (int)info_cplt->reason_code, (int)info_cplt->configID, infodesc->flow_flags,
+ (int)infodesc->flow_id, infodesc->next_twt_h, infodesc->next_twt_l));
+
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_SUB_EVENT, ANDR_TWT_EVENT_INFO_FRM);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_SUB_EVENT failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_REASON_CODE, info_cplt->reason_code);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_REASON_CODE failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_STATUS, !!(info_cplt->status));
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_STATUS failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_CONFIG_ID, info_cplt->configID);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_CONFIG_ID failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_ALL_TWT,
+ !!(infodesc->flow_flags & WL_TWT_INFO_FLAG_ALL_TWT));
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 ANDR_TWT_ATTR_TWT_RESUMED failed\n"));
+ goto fail;
+ }
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_TWT_RESUMED,
+ !!(infodesc->flow_flags & WL_TWT_INFO_FLAG_RESUME));
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 ANDR_TWT_ATTR_TWT_RESUMED failed\n"));
+ goto fail;
+ }
+
+fail:
+ return err;
+}
+
+static int
+wl_cfgvendor_twt_update_notify_response(struct sk_buff *skb, void *event_data)
+{
+ s32 err = BCME_OK;
+ const wl_twt_notify_t *notif_cplt = (wl_twt_notify_t *)event_data;
+
+ WL_DBG(("TWT_NOTIFY: notification %d\n", (int)notif_cplt->notification));
+
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_SUB_EVENT, ANDR_TWT_EVENT_NOTIFY);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_SUB_EVENT failed\n"));
+ goto fail;
+ }
+
+ err = nla_put_u8(skb, ANDR_TWT_ATTR_TWT_NOTIFICATION, notif_cplt->notification);
+ if (unlikely(err)) {
+ WL_ERR(("nla_put_u8 WIFI_TWT_ATTR_NOTIFICATION failed\n"));
+ goto fail;
+ }
+
+fail:
+ return err;
+}
+
+s32
+wl_cfgvendor_notify_twt_event(struct bcm_cfg80211 *cfg,
+ bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data)
+{
+ struct sk_buff *skb = NULL;
+ gfp_t kflags;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ int err = BCME_OK;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+ const wl_twt_event_t *twt_event = (wl_twt_event_t *)data;
+
+ kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+ skb = CFG80211_VENDOR_EVENT_ALLOC(wiphy, ndev_to_wdev(ndev),
+ BRCM_TWT_HAL_VENDOR_EVENT_BUF_LEN, BRCM_VENDOR_EVENT_TWT, kflags);
+ if (!skb) {
+ WL_ERR(("skb alloc failed"));
+ err = BCME_NOMEM;
+ goto fail;
+ }
+
+ switch (twt_event->event_type) {
+ case WL_TWT_EVENT_SETUP:
+ err = wl_cfgvendor_twt_update_setup_response(skb,
+ (void*)twt_event->event_info);
+ break;
+ case WL_TWT_EVENT_TEARDOWN:
+ err = wl_cfgvendor_twt_update_teardown_response(skb,
+ (void*)twt_event->event_info);
+ break;
+ case WL_TWT_EVENT_INFOFRM:
+ err = wl_cfgvendor_twt_update_infoframe_response(skb,
+ (void*)twt_event->event_info);
+ break;
+ case WL_TWT_EVENT_NOTIFY:
+ err = wl_cfgvendor_twt_update_notify_response(skb,
+ (void*)twt_event->event_info);
+ break;
+ default:
+ WL_ERR(("Invalid TWT sub event type %d", twt_event->event_type));
+ err = BCME_UNSUPPORTED;
+ break;
+ }
+
+ if (err) {
+ goto fail;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ cfg80211_vendor_event(skb, kflags);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
+ WL_ERR(("Successfully sent TWT vendor event type %d\n", twt_event->event_type));
+ return BCME_OK;
+
+fail:
+ /* Free skb for failure cases */
+ if (skb) {
+ kfree_skb(skb);
+ }
+
+ return err;
+}
+#endif /* !WL_TWT && WL_TWT_HAL_IF */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+const struct nla_policy andr_wifi_attr_policy[ANDR_WIFI_ATTRIBUTE_MAX] = {
+ [ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET] = { .type = NLA_U32 },
+ [ANDR_WIFI_ATTRIBUTE_FEATURE_SET] = { .type = NLA_U32 },
+ [ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI] = { .type = NLA_NUL_STRING, .len = 3 },
+ [ANDR_WIFI_ATTRIBUTE_NODFS_SET] = { .type = NLA_U32 },
+ [ANDR_WIFI_ATTRIBUTE_COUNTRY] = { .type = NLA_NUL_STRING, .len = 3 },
+ [ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE] = { .type = NLA_U8 },
+ [ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE] = { .type = NLA_U32 },
+ [ANDR_WIFI_ATTRIBUTE_LATENCY_MODE] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [ANDR_WIFI_ATTRIBUTE_RANDOM_MAC] = { .type = NLA_U32 },
+ [ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO] = { .type = NLA_S8 },
+ [ANDR_WIFI_ATTRIBUTE_THERMAL_MITIGATION] = { .type = NLA_S8 },
+ [ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW] = { .type = NLA_U32 },
+ [ANDR_WIFI_ATTRIBUTE_VOIP_MODE] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER] = { .type = NLA_U32, .len = sizeof(uint32) },
+};
+
+const struct nla_policy dump_buf_policy[DUMP_BUF_ATTR_MAX] = {
+ [DUMP_BUF_ATTR_MEMDUMP] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_C0_D11_BEFORE] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_C0_D11_AFTER] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_C1_D11_BEFORE] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_C1_D11_AFTER] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_C2_D11_BEFORE] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_C2_D11_AFTER] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_DIG_BEFORE] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SSSR_DIG_AFTER] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_TIMESTAMP] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_GENERAL_LOG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_ECNTRS] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SPECIAL_LOG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_DHD_DUMP] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_EXT_TRAP] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_HEALTH_CHK] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_PRESERVE_LOG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_COOKIE] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_FLOWRING_DUMP] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_PKTLOG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_PKTLOG_DEBUG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_STATUS_LOG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_AXI_ERROR] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_RTT_LOG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_SDTC_ETB_DUMP] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_PKTID_MAP_LOG] = { .type = NLA_BINARY },
+ [DUMP_BUF_ATTR_PKTID_UNMAP_LOG] = { .type = NLA_BINARY },
+};
+
+const struct nla_policy brcm_drv_attr_policy[BRCM_ATTR_DRIVER_MAX] = {
+ [BRCM_ATTR_DRIVER_CMD] = { .type = NLA_NUL_STRING },
+ [BRCM_ATTR_DRIVER_KEY_PMK] = { .type = NLA_BINARY, .len = WSEC_MAX_PASSPHRASE_LEN },
+ [BRCM_ATTR_DRIVER_FEATURE_FLAGS] = { .type = NLA_BINARY, .len =
+ ((BRCM_WLAN_VENDOR_FEATURES_MAX / 8) + 1) },
+ [BRCM_ATTR_DRIVER_RAND_MAC] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [BRCM_ATTR_SAE_PWE] = { .type = NLA_U32 },
+};
+
+#ifdef RTT_SUPPORT
+const struct nla_policy rtt_attr_policy[RTT_ATTRIBUTE_MAX] = {
+ [RTT_ATTRIBUTE_TARGET_CNT] = { .type = NLA_U8 },
+ [RTT_ATTRIBUTE_TARGET_INFO] = { .type = NLA_NESTED },
+ [RTT_ATTRIBUTE_TARGET_MAC] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [RTT_ATTRIBUTE_TARGET_TYPE] = { .type = NLA_U8 },
+ [RTT_ATTRIBUTE_TARGET_PEER] = { .type = NLA_U8 },
+ [RTT_ATTRIBUTE_TARGET_CHAN] = { .type = NLA_BINARY },
+ [RTT_ATTRIBUTE_TARGET_PERIOD] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_TARGET_NUM_BURST] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_TARGET_LCI] = { .type = NLA_U8 },
+ [RTT_ATTRIBUTE_TARGET_LCR] = { .type = NLA_U8 },
+ [RTT_ATTRIBUTE_TARGET_BURST_DURATION] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_TARGET_PREAMBLE] = { .type = NLA_U8 },
+ [RTT_ATTRIBUTE_TARGET_BW] = { .type = NLA_U8 },
+ [RTT_ATTRIBUTE_RESULTS_COMPLETE] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_RESULTS_PER_TARGET] = { .type = NLA_NESTED },
+ [RTT_ATTRIBUTE_RESULT_CNT] = { .type = NLA_U32 },
+ [RTT_ATTRIBUTE_RESULT] = { .type = NLA_BINARY, .len = sizeof(rtt_result_t) },
+ [RTT_ATTRIBUTE_RESULT_DETAIL] = { .type = NLA_BINARY,
+ .len = sizeof(struct rtt_result_detail) },
+};
+#endif /* RTT_SUPPORT */
+
+#ifdef KEEP_ALIVE
+const struct nla_policy mkeep_alive_attr_policy[MKEEP_ALIVE_ATTRIBUTE_MAX] = {
+ [MKEEP_ALIVE_ATTRIBUTE_ID] = { .type = NLA_U8 },
+ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = { .type = NLA_BINARY, .len = MKEEP_ALIVE_IP_PKT_MAX },
+ [MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = { .type = NLA_U16 },
+ [MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = { .type = NLA_U32 },
+ [MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE] = { .type = NLA_U16 }
+};
+#endif /* KEEP_ALIVE */
+#ifdef WL_NAN
+const struct nla_policy nan_attr_policy[NAN_ATTRIBUTE_MAX] = {
+ [NAN_ATTRIBUTE_2G_SUPPORT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_5G_SUPPORT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_CLUSTER_LOW] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_CLUSTER_HIGH] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_SID_BEACON] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SUB_SID_BEACON] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SDF_2G_SUPPORT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SDF_5G_SUPPORT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_HOP_COUNT_LIMIT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RANDOM_TIME] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_MASTER_PREF] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_OUI] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_WARMUP_TIME] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_CHANNEL] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_24G_CHANNEL] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_5G_CHANNEL] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_CONF_CLUSTER_VAL] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_DWELL_TIME] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SCAN_PERIOD] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_DWELL_TIME_5G] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SCAN_PERIOD_5G] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_AVAIL_BIT_MAP] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_ENTRY_CONTROL] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSSI_CLOSE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSSI_MIDDLE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSSI_PROXIMITY] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSSI_CLOSE_5G] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSSI_MIDDLE_5G] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSSI_PROXIMITY_5G] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSSI_WINDOW_SIZE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_CIPHER_SUITE_TYPE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SCID_LEN] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_SCID] = { .type = NLA_BINARY, .len = MAX_SCID_LEN },
+ [NAN_ATTRIBUTE_2G_AWAKE_DW] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_5G_AWAKE_DW] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_DISC_IND_CFG] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_MAC_ADDR] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_CMD_USE_NDPE] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_ENABLE_MERGE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_NSS] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_ENABLE_RANGING] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_DW_EARLY_TERM] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_TRANSAC_ID] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_PUBLISH_ID] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO] = { .type = NLA_BINARY, .len =
+ NAN_MAX_SERVICE_SPECIFIC_INFO_LEN },
+ [NAN_ATTRIBUTE_SUBSCRIBE_ID] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_SUBSCRIBE_TYPE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_PUBLISH_COUNT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_PUBLISH_TYPE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_PERIOD] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_TTL] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_SERVICE_NAME_LEN] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_SERVICE_NAME] = { .type = NLA_BINARY, .len = WL_NAN_SVC_HASH_LEN },
+ [NAN_ATTRIBUTE_PEER_ID] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_INST_ID] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_SUBSCRIBE_COUNT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SUBSCRIBE_MATCH] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_PUBLISH_MATCH] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SERVICERESPONSEFILTER] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_USESERVICERESPONSEFILTER] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_RX_MATCH_FILTER] = { .type = NLA_BINARY, .len = MAX_MATCH_FILTER_LEN },
+ [NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_TX_MATCH_FILTER] = { .type = NLA_BINARY, .len = MAX_MATCH_FILTER_LEN },
+ [NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES] = { .type = NLA_U16, .len = sizeof(uint16) },
+ [NAN_ATTRIBUTE_MAC_ADDR_LIST] = { .type = NLA_BINARY, .len =
+ (NAN_SRF_MAX_MAC*ETHER_ADDR_LEN) },
+ [NAN_ATTRIBUTE_TX_TYPE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SDE_CONTROL_SECURITY] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RECV_IND_CFG] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_KEY_TYPE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_KEY_LEN] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_KEY_DATA] = { .type = NLA_BINARY, .len = NAN_MAX_PMK_LEN },
+ [NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN] = { .type = NLA_U16, .len =
+ sizeof(uint16) },
+ [NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO] = { .type = NLA_BINARY, .len =
+ MAX_SDEA_SVC_INFO_LEN },
+ [NAN_ATTRIBUTE_SECURITY] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RANGING_INTERVAL] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_RANGING_INDICATION] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_SVC_RESPONDER_POLICY] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_NDP_ID] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_IFACE] = { .type = NLA_BINARY, .len = IFNAMSIZ+1 },
+ [NAN_ATTRIBUTE_QOS] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_RSP_CODE] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_INST_COUNT] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [NAN_ATTRIBUTE_IF_ADDR] = { .type = NLA_BINARY, .len = ETHER_ADDR_LEN },
+ [NAN_ATTRIBUTE_NO_CONFIG_AVAIL] = { .type = NLA_U8, .len = sizeof(uint8) },
+ [NAN_ATTRIBUTE_CHANNEL_INFO] = { .type = NLA_BINARY, .len =
+ sizeof(nan_channel_info_t) * NAN_MAX_CHANNEL_INFO_SUPPORTED },
+ [NAN_ATTRIBUTE_NUM_CHANNELS] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_INSTANT_MODE_ENABLE] = { .type = NLA_U32, .len = sizeof(uint32) },
+ [NAN_ATTRIBUTE_INSTANT_COMM_CHAN] = { .type = NLA_U32, .len = sizeof(uint32) },
+};
+#endif /* WL_NAN */
+
+const struct nla_policy gscan_attr_policy[GSCAN_ATTRIBUTE_MAX] = {
+ [GSCAN_ATTRIBUTE_BAND] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_NUM_CHANNELS] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_CHANNEL_LIST] = { .type = NLA_BINARY },
+ [GSCAN_ATTRIBUTE_WHITELIST_SSID] = { .type = NLA_BINARY, .len = IEEE80211_MAX_SSID_LEN },
+ [GSCAN_ATTRIBUTE_NUM_WL_SSID] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_WL_SSID_LEN] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_WL_SSID_FLUSH] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM] = { .type = NLA_NESTED },
+ /* length is sizeof(wl_ssid_whitelist_t) * MAX_SSID_WHITELIST_NUM */
+ [GSCAN_ATTRIBUTE_NUM_BSSID] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_BSSID_PREF_LIST] = { .type = NLA_NESTED },
+ /* length is sizeof(wl_bssid_pref_list_t) * MAX_BSSID_PREF_LIST_NUM */
+ [GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_BSSID_PREF] = { .type = NLA_BINARY, .len = ETH_ALEN },
+ [GSCAN_ATTRIBUTE_RSSI_MODIFIER] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH] = { .type = NLA_U32 },
+ [GSCAN_ATTRIBUTE_BLACKLIST_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN },
+ [GSCAN_ATTRIBUTE_ROAM_STATE_SET] = { .type = NLA_U32 },
+};
+
+#ifdef DHD_WAKE_STATUS
+const struct nla_policy wake_stat_attr_policy[WAKE_STAT_ATTRIBUTE_MAX] = {
+ [WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT] = { .type = NLA_U32 },
+#ifdef CUSTOM_WAKE_REASON_STATS
+ [WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE] = { .type = NLA_BINARY,
+ .len = (MAX_WAKE_REASON_STATS * sizeof(int))},
+#else
+ [WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE] = { .type = NLA_BINARY,
+ .len = (WLC_E_LAST * sizeof(uint))},
+#endif /* CUSTOM_WAKE_REASON_STATS */
+ [WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT_USED] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT] = { .type = NLA_U32 },
+ [WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT] = { .type = NLA_U32 },
+};
+#endif /* DHD_WAKE_STATUS */
+
+#ifdef RSSI_MONITOR_SUPPORT
+const struct nla_policy rssi_monitor_attr_policy[RSSI_MONITOR_ATTRIBUTE_MAX] = {
+ [RSSI_MONITOR_ATTRIBUTE_MAX_RSSI] = { .type = NLA_U32 },
+ [RSSI_MONITOR_ATTRIBUTE_MIN_RSSI] = { .type = NLA_U32 },
+ [RSSI_MONITOR_ATTRIBUTE_START] = { .type = NLA_U32 }
+};
+#endif /* RSSI_MONITOR_SUPPORT */
+
+
+const struct nla_policy hal_start_attr_policy[SET_HAL_START_ATTRIBUTE_MAX] = {
+ [0] = { .strict_start_type = 0 },
+ [SET_HAL_START_ATTRIBUTE_DEINIT] = { .type = NLA_UNSPEC },
+ [SET_HAL_START_ATTRIBUTE_PRE_INIT] = { .type = NLA_NUL_STRING },
+ [SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID] = { .type = NLA_U32 },
+};
+
+const struct nla_policy andr_dbg_policy[DEBUG_ATTRIBUTE_MAX] = {
+ [DEBUG_ATTRIBUTE_GET_DRIVER] = { .type = NLA_BINARY },
+ [DEBUG_ATTRIBUTE_GET_FW] = { .type = NLA_BINARY },
+ [DEBUG_ATTRIBUTE_RING_ID] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_RING_NAME] = { .type = NLA_NUL_STRING },
+ [DEBUG_ATTRIBUTE_RING_FLAGS] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_LOG_LEVEL] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_LOG_TIME_INTVAL] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_FW_DUMP_LEN] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_FW_DUMP_DATA] = { .type = NLA_U64 },
+ [DEBUG_ATTRIBUTE_FW_ERR_CODE] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_RING_DATA] = { .type = NLA_BINARY },
+ [DEBUG_ATTRIBUTE_RING_STATUS] = { .type = NLA_BINARY },
+ [DEBUG_ATTRIBUTE_RING_NUM] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_DRIVER_DUMP_LEN] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_DRIVER_DUMP_DATA] = { .type = NLA_BINARY },
+ [DEBUG_ATTRIBUTE_PKT_FATE_NUM] = { .type = NLA_U32 },
+ [DEBUG_ATTRIBUTE_PKT_FATE_DATA] = { .type = NLA_U64 },
+ [DEBUG_ATTRIBUTE_HANG_REASON] = { .type = NLA_BINARY },
+};
+
+#if !defined(WL_TWT) && defined(WL_TWT_HAL_IF)
+const struct nla_policy andr_twt_attr_policy[ANDR_TWT_ATTR_MAX] = {
+ [ANDR_TWT_ATTR_NONE] = { .strict_start_type = 0 },
+ [ANDR_TWT_ATTR_CONFIG_ID] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_NEGOTIATION_TYPE] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_TRIGGER_TYPE] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_WAKE_DURATION] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_WAKE_INTERVAL] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_WAKE_INTERVAL_MIN] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_WAKE_INTERVAL_MAX] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_WAKE_DURATION_MIN] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_WAKE_DURATION_MAX] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_AVG_PKT_SIZE] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_AVG_PKT_NUM] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_WAKETIME_OFFSET] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_ALL_TWT] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_RESUME_TIME] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_AVG_EOSP_DUR] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_EOSP_CNT] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_NUM_SP] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_DEVICE_CAP] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_PEER_CAP] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_STATUS] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_REASON_CODE] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_TWT_RESUMED] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_TWT_NOTIFICATION] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_SUB_EVENT] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_NUM_PEER_STATS] = { .type = NLA_U8 },
+ [ANDR_TWT_ATTR_AVG_PKT_NUM_TX] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_AVG_PKT_SIZE_TX] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_AVG_PKT_NUM_RX] = { .type = NLA_U32 },
+ [ANDR_TWT_ATTR_AVG_PKT_SIZE_RX] = { .type = NLA_U32 },
+};
+#endif /* !WL_TWT && WL_TWT_HAL_IF */
+
+#endif /* LINUX_VERSION >= 5.3 */
+
+static struct wiphy_vendor_command wl_vendor_cmds [] = {
+ {
+ {
+ .vendor_id = OUI_BRCM,
+ .subcmd = BRCM_VENDOR_SCMD_PRIV_STR
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_priv_string_handler,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = brcm_drv_attr_policy,
+ .maxattr = BRCM_ATTR_DRIVER_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#ifdef BCM_PRIV_CMD_SUPPORT
+ {
+ {
+ .vendor_id = OUI_BRCM,
+ .subcmd = BRCM_VENDOR_SCMD_BCM_STR
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_priv_bcm_handler,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = brcm_drv_attr_policy,
+ .maxattr = BRCM_ATTR_DRIVER_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#endif /* BCM_PRIV_CMD_SUPPORT */
+#if defined(WL_SAE) || defined(WL_CLIENT_SAE)
+ {
+ {
+ .vendor_id = OUI_BRCM,
+ .subcmd = BRCM_VENDOR_SCMD_BCM_PSK
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_set_sae_password
+ },
+#endif /* WL_SAE || WL_CLIENT_SAE */
+ {
+ {
+ .vendor_id = OUI_BRCM,
+ .subcmd = BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_connect_params_handler,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = brcm_drv_attr_policy,
+ .maxattr = BRCM_ATTR_DRIVER_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_BRCM,
+ .subcmd = BRCM_VENDOR_SCMD_SET_START_AP_PARAMS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_start_ap_params_handler,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = brcm_drv_attr_policy,
+ .maxattr = BRCM_ATTR_DRIVER_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#ifdef GSCAN_SUPPORT
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_gscan_get_capabilities
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_SET_CONFIG
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_set_scan_cfg
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_set_batch_scan_cfg
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_initiate_gscan
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_enable_full_scan_result
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_SET_HOTLIST
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_hotlist_cfg
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_gscan_get_batch_results
+ },
+#endif /* GSCAN_SUPPORT */
+#if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_gscan_get_channel_list,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = gscan_attr_policy,
+ .maxattr = GSCAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
+#ifdef RTT_SUPPORT
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = RTT_SUBCMD_SET_CONFIG
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_rtt_set_config,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = rtt_attr_policy,
+ .maxattr = RTT_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = RTT_SUBCMD_CANCEL_CONFIG
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_rtt_cancel_config,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = rtt_attr_policy,
+ .maxattr = RTT_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = RTT_SUBCMD_GETCAPABILITY
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_rtt_get_capability,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = rtt_attr_policy,
+ .maxattr = RTT_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = RTT_SUBCMD_GETAVAILCHANNEL
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_rtt_get_responder_info,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = rtt_attr_policy,
+ .maxattr = RTT_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = RTT_SUBCMD_SET_RESPONDER
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_rtt_set_responder,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = rtt_attr_policy,
+ .maxattr = RTT_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = RTT_SUBCMD_CANCEL_RESPONDER
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_rtt_cancel_responder,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = rtt_attr_policy,
+ .maxattr = RTT_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#endif /* RTT_SUPPORT */
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_get_feature_set,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_get_feature_set_matrix,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_WIFI_RANDOM_MAC_OUI
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_set_rand_mac_oui,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#ifdef CUSTOM_FORCE_NODFS_FLAG
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_WIFI_NODFS_CHANNELS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_set_nodfs_flag,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#endif /* CUSTOM_FORCE_NODFS_FLAG */
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_WIFI_SET_COUNTRY
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_set_country,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#ifdef LINKSTAT_SUPPORT
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = LSTATS_SUBCMD_GET_INFO
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_lstats_get_info
+ },
+#endif /* LINKSTAT_SUPPORT */
+
+#ifdef GSCAN_SUPPORT
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = GSCAN_SUBCMD_SET_EPNO_SSID
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_epno_cfg
+
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_set_lazy_roam_cfg
+
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = WIFI_SUBCMD_ENABLE_LAZY_ROAM
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = wl_cfgvendor_enable_lazy_roam
},
.subcmd = WIFI_SUBCMD_SET_SSID_WHITELIST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_ssid_whitelist
+ .doit = wl_cfgvendor_set_ssid_whitelist,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = gscan_attr_policy,
+ .maxattr = GSCAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
.subcmd = WIFI_SUBCMD_SET_BSSID_BLACKLIST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_bssid_blacklist
+ .doit = wl_cfgvendor_set_bssid_blacklist,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = gscan_attr_policy,
+ .maxattr = GSCAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
#ifdef ROAMEXP_SUPPORT
.subcmd = WIFI_SUBCMD_FW_ROAM_POLICY
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_fw_roaming_state
+ .doit = wl_cfgvendor_set_fw_roaming_state,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = gscan_attr_policy,
+ .maxattr = GSCAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = DEBUG_GET_VER
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_get_version
+ .doit = wl_cfgvendor_dbg_get_version,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_dbg_policy,
+ .maxattr = DEBUG_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#ifdef DHD_LOG_DUMP
{
.subcmd = DEBUG_GET_FILE_DUMP_BUF
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_file_dump
+ .doit = wl_cfgvendor_dbg_file_dump,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = dump_buf_policy,
+ .maxattr = DUMP_BUF_ATTR_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* DHD_LOG_DUMP */
.subcmd = DEBUG_GET_MEM_DUMP
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_get_mem_dump
+ .doit = wl_cfgvendor_dbg_get_mem_dump,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_dbg_policy,
+ .maxattr = DEBUG_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = DEBUG_START_LOGGING
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_start_logging
+ .doit = wl_cfgvendor_dbg_start_logging,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_dbg_policy,
+ .maxattr = DEBUG_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = DEBUG_GET_RING_STATUS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_get_ring_status
+ .doit = wl_cfgvendor_dbg_get_ring_status,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_dbg_policy,
+ .maxattr = DEBUG_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = DEBUG_GET_RING_DATA
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_get_ring_data
+ .doit = wl_cfgvendor_dbg_get_ring_data,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_dbg_policy,
+ .maxattr = DEBUG_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* DEBUGABILITY */
{
.subcmd = DEBUG_GET_TX_PKT_FATES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_get_tx_pkt_fates
+ .doit = wl_cfgvendor_dbg_get_tx_pkt_fates,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_dbg_policy,
+ .maxattr = DEBUG_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = DEBUG_GET_RX_PKT_FATES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_dbg_get_rx_pkt_fates
+ .doit = wl_cfgvendor_dbg_get_rx_pkt_fates,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_dbg_policy,
+ .maxattr = DEBUG_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* DBG_PKT_MON */
#ifdef KEEP_ALIVE
.subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_start_mkeep_alive
+ .doit = wl_cfgvendor_start_mkeep_alive,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = mkeep_alive_attr_policy,
+ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_stop_mkeep_alive
+ .doit = wl_cfgvendor_stop_mkeep_alive,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = mkeep_alive_attr_policy,
+ .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* KEEP_ALIVE */
#ifdef WL_NAN
.subcmd = NAN_WIFI_SUBCMD_ENABLE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_start_handler
+ .doit = wl_cfgvendor_nan_start_handler,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_DISABLE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_stop_handler
+ .doit = wl_cfgvendor_nan_stop_handler,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_CONFIG
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_config_handler
+ .doit = wl_cfgvendor_nan_config_handler,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_REQUEST_PUBLISH
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_req_publish
+ .doit = wl_cfgvendor_nan_req_publish,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_req_subscribe
+ .doit = wl_cfgvendor_nan_req_subscribe,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_CANCEL_PUBLISH
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_cancel_publish
+ .doit = wl_cfgvendor_nan_cancel_publish,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_cancel_subscribe
+ .doit = wl_cfgvendor_nan_cancel_subscribe,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_TRANSMIT
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_transmit
+ .doit = wl_cfgvendor_nan_transmit,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_data_path_iface_create
+ .doit = wl_cfgvendor_nan_data_path_iface_create,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_data_path_iface_delete
+ .doit = wl_cfgvendor_nan_data_path_iface_delete,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_data_path_request
+ .doit = wl_cfgvendor_nan_data_path_request,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_data_path_response
+ .doit = wl_cfgvendor_nan_data_path_response,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_END
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_data_path_end
+ .doit = wl_cfgvendor_nan_data_path_end,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#ifdef WL_NAN_DISC_CACHE
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_data_path_sec_info
+ .doit = wl_cfgvendor_nan_data_path_sec_info,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* WL_NAN_DISC_CACHE */
{
.subcmd = NAN_WIFI_SUBCMD_ENABLE_MERGE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_nan_enable_merge
+ .doit = wl_cfgvendor_nan_enable_merge,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = nan_attr_policy,
+ .maxattr = NAN_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* WL_NAN */
#if defined(PKT_FILTER_SUPPORT) && defined(APF)
.subcmd = APF_SUBCMD_GET_CAPABILITIES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_apf_get_capabilities
+ .doit = wl_cfgvendor_apf_get_capabilities,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = apf_atrribute_policy,
+ .maxattr = APF_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
.subcmd = APF_SUBCMD_SET_FILTER
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_apf_set_filter
+ .doit = wl_cfgvendor_apf_set_filter,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = apf_atrribute_policy,
+ .maxattr = APF_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* PKT_FILTER_SUPPORT && APF */
#ifdef NDO_CONFIG_SUPPORT
.subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_configure_nd_offload
+ .doit = wl_cfgvendor_configure_nd_offload,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* NDO_CONFIG_SUPPORT */
#ifdef RSSI_MONITOR_SUPPORT
.subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_rssi_monitor
+ .doit = wl_cfgvendor_set_rssi_monitor,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = rssi_monitor_attr_policy,
+ .maxattr = RSSI_MONITOR_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* RSSI_MONITOR_SUPPORT */
#ifdef DHD_WAKE_STATUS
.subcmd = DEBUG_GET_WAKE_REASON_STATS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_get_wake_reason_stats
+ .doit = wl_cfgvendor_get_wake_reason_stats,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = wake_stat_attr_policy,
+ .maxattr = WAKE_STAT_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* DHD_WAKE_STATUS */
#ifdef DHDTCPACK_SUPPRESS
.subcmd = WIFI_SUBCMD_CONFIG_TCPACK_SUP
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_tcpack_sup_mode
+ .doit = wl_cfgvendor_set_tcpack_sup_mode,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* DHDTCPACK_SUPPRESS */
#if !defined(BCMSUP_4WAY_HANDSHAKE) || (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0))
.subcmd = BRCM_VENDOR_SCMD_SET_PMK
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_pmk
+ .doit = wl_cfgvendor_set_pmk,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = brcm_drv_attr_policy,
+ .maxattr = BRCM_ATTR_DRIVER_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* !BCMSUP_4WAY_HANDSHAKE || LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
{
.subcmd = BRCM_VENDOR_SCMD_GET_FEATURES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_get_driver_feature
+ .doit = wl_cfgvendor_get_driver_feature,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = brcm_drv_attr_policy,
+ .maxattr = BRCM_ATTR_DRIVER_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT)
{
.subcmd = DEBUG_SET_HAL_START
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_hal_started
+ .doit = wl_cfgvendor_set_hal_started,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = hal_start_attr_policy,
+ .maxattr = SET_HAL_START_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
{
{
.subcmd = DEBUG_SET_HAL_PID
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_hal_pid
+ .doit = wl_cfgvendor_set_hal_pid,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = hal_start_attr_policy,
+ .maxattr = SET_HAL_START_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* WL_CFG80211 */
#ifdef WL_LATENCY_MODE
.subcmd = WIFI_SUBCMD_SET_LATENCY_MODE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
- .doit = wl_cfgvendor_set_latency_mode
+ .doit = wl_cfgvendor_set_latency_mode,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* WL_LATENCY_MODE */
#ifdef WL_P2P_RAND
.subcmd = BRCM_VENDOR_SCMD_SET_MAC
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV,
- .doit = wl_cfgvendor_set_p2p_rand_mac
+ .doit = wl_cfgvendor_set_p2p_rand_mac,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = brcm_drv_attr_policy,
+ .maxattr = BRCM_ATTR_DRIVER_MAX
+#endif /* LINUX_VERSION >= 5.3 */
},
#endif /* WL_P2P_RAND */
#ifdef WL_SAR_TX_POWER
.subcmd = WIFI_SUBCMD_TX_POWER_SCENARIO
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV,
- .doit = wl_cfgvendor_tx_power_scenario
+ .doit = wl_cfgvendor_tx_power_scenario,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_wifi_attr_policy,
+ .maxattr = ANDR_WIFI_ATTRIBUTE_MAX
+#endif /* LINUX_VERSION >= 5.3 */
}
#endif /* WL_SAR_TX_POWER */
+#if !defined(WL_TWT) && defined(WL_TWT_HAL_IF)
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_TWT_SUBCMD_SETUP
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_twt_setup,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_twt_attr_policy,
+ .maxattr = ANDR_TWT_ATTR_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_TWT_SUBCMD_TEARDOWN
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_twt_teardown,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_twt_attr_policy,
+ .maxattr = ANDR_TWT_ATTR_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_TWT_SUBCMD_INFO_FRAME
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_twt_info_frame,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_twt_attr_policy,
+ .maxattr = ANDR_TWT_ATTR_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_TWT_SUBCMD_GET_CAP
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_twt_cap,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_twt_attr_policy,
+ .maxattr = ANDR_TWT_ATTR_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_TWT_SUBCMD_GET_STATS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_twt_get_stats,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_twt_attr_policy,
+ .maxattr = ANDR_TWT_ATTR_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+ {
+ {
+ .vendor_id = OUI_GOOGLE,
+ .subcmd = ANDR_TWT_SUBCMD_CLR_STATS
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wl_cfgvendor_twt_clear_stats,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = andr_twt_attr_policy,
+ .maxattr = ANDR_TWT_ATTR_MAX
+#endif /* LINUX_VERSION >= 5.3 */
+ },
+#endif /* !WL_TWT && WL_TWT_HAL_IF */
};
{ OUI_BRCM, BRCM_VENDOR_EVENT_CU},
{ OUI_BRCM, BRCM_VENDOR_EVENT_WIPS},
{ OUI_GOOGLE, NAN_ASYNC_RESPONSE_DISABLED},
- { OUI_BRCM, BRCM_VENDOR_EVENT_RCC_INFO}
+ { OUI_BRCM, BRCM_VENDOR_EVENT_RCC_INFO},
+ {OUI_BRCM, BRCM_VENDOR_EVENT_TWT}
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
WL_INFORM(("Apply CMD_RAW_DATA policy\n"));
for (i = 0; i < n_cmds; i++) {
- wl_vendor_cmds[i].policy = VENDOR_CMD_RAW_DATA;
+ if (wl_vendor_cmds[i].policy == NULL) {
+ wl_vendor_cmds[i].policy = VENDOR_CMD_RAW_DATA;
+ }
}
}
#endif /* LINUX VER >= 5.3 */
ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START = 0x1900,
ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_END = 0x19FF,
+ /* define all TWT related commands between 0x2140 and 0x214F */
+ ANDROID_NL80211_SUBCMD_TWT_START = 0x2140,
+ ANDROID_NL80211_SUBCMD_TWT_END = 0x214F,
+
/* This is reserved for future usage */
} ANDROID_VENDOR_SUB_COMMAND;
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
APF_SUBCMD_SET_FILTER,
WIFI_SUBCMD_TX_POWER_SCENARIO = ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START,
+
+ ANDR_TWT_SUBCMD_GET_CAP = ANDROID_NL80211_SUBCMD_TWT_START,
+ ANDR_TWT_SUBCMD_SETUP,
+ ANDR_TWT_SUBCMD_TEARDOWN,
+ ANDR_TWT_SUBCMD_INFO_FRAME,
+ ANDR_TWT_SUBCMD_GET_STATS,
+ ANDR_TWT_SUBCMD_CLR_STATS,
/* Add more sub commands here */
VENDOR_SUBCMD_MAX
};
RTT_ATTRIBUTE_TARGET_BURST_DURATION,
RTT_ATTRIBUTE_TARGET_PREAMBLE,
RTT_ATTRIBUTE_TARGET_BW,
- RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
+ RTT_ATTRIBUTE_RESULTS_COMPLETE,
RTT_ATTRIBUTE_RESULTS_PER_TARGET,
RTT_ATTRIBUTE_RESULT_CNT,
RTT_ATTRIBUTE_RESULT,
- RTT_ATTRIBUTE_RESULT_DETAIL
+ RTT_ATTRIBUTE_RESULT_DETAIL,
+ /* Add any new RTT_ATTRIBUTE prior to RTT_ATTRIBUTE_MAX */
+ RTT_ATTRIBUTE_MAX
};
enum wifi_rssi_monitor_attr {
#endif
RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
- RSSI_MONITOR_ATTRIBUTE_START
+ RSSI_MONITOR_ATTRIBUTE_START,
+ RSSI_MONITOR_ATTRIBUTE_MAX
};
enum wifi_sae_key_attr {
DEBUG_ATTRIBUTE_DRIVER_DUMP_DATA,
DEBUG_ATTRIBUTE_PKT_FATE_NUM,
DEBUG_ATTRIBUTE_PKT_FATE_DATA,
- DEBUG_ATTRIBUTE_HANG_REASON
+ DEBUG_ATTRIBUTE_HANG_REASON,
+ /* Please add new attributes from here to sync up old HAL */
+ DEBUG_ATTRIBUTE_MAX
};
typedef enum {
DUMP_BUF_ATTR_PKTLOG_DEBUG = 21,
DUMP_BUF_ATTR_STATUS_LOG = 22,
DUMP_BUF_ATTR_AXI_ERROR = 23,
- DUMP_BUF_ATTR_RTT_LOG = 24
+ DUMP_BUF_ATTR_RTT_LOG = 24,
+ DUMP_BUF_ATTR_SDTC_ETB_DUMP = 25,
+ DUMP_BUF_ATTR_PKTID_MAP_LOG = 26,
+ DUMP_BUF_ATTR_PKTID_UNMAP_LOG = 27,
/* Please add new attributes from here to sync up old HAL */
+ DUMP_BUF_ATTR_MAX
} EWP_DUMP_CMD_ATTRIBUTE;
enum mkeep_alive_attributes {
MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
- MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE
+ MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE,
+ MKEEP_ALIVE_ATTRIBUTE_MAX
};
typedef enum wl_vendor_event {
BRCM_VENDOR_EVENT_CU = 38,
BRCM_VENDOR_EVENT_WIPS = 39,
NAN_ASYNC_RESPONSE_DISABLED = 40,
- BRCM_VENDOR_EVENT_RCC_INFO = 41
+ BRCM_VENDOR_EVENT_RCC_INFO = 41,
+ BRCM_VENDOR_EVENT_TWT = 43,
+ WL_VENDOR_EVENT_LAST
} wl_vendor_event_t;
enum andr_wifi_attr {
ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE,
ANDR_WIFI_ATTRIBUTE_LATENCY_MODE,
ANDR_WIFI_ATTRIBUTE_RANDOM_MAC,
- ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO
+ ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO,
+ ANDR_WIFI_ATTRIBUTE_THERMAL_MITIGATION,
+ ANDR_WIFI_ATTRIBUTE_THERMAL_COMPLETION_WINDOW,
+ ANDR_WIFI_ATTRIBUTE_VOIP_MODE,
+ ANDR_WIFI_ATTRIBUTE_DTIM_MULTIPLIER,
+ /* Any new ANDR_WIFI attribute add prior to the ANDR_WIFI_ATTRIBUTE_MAX */
+ ANDR_WIFI_ATTRIBUTE_MAX
};
enum apf_attributes {
APF_ATTRIBUTE_VERSION,
APF_ATTRIBUTE_MAX_LEN,
APF_ATTRIBUTE_PROGRAM,
- APF_ATTRIBUTE_PROGRAM_LEN
+ APF_ATTRIBUTE_PROGRAM_LEN,
+ APF_ATTRIBUTE_MAX
};
typedef enum wl_vendor_gscan_attribute {
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
- WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT
+ WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT,
+ WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
+ /* Please add new attributes from here to sync up old HAL */
+ WAKE_STAT_ATTRIBUTE_MAX
};
typedef struct rx_data_cnt_details_t {
typedef enum {
SET_HAL_START_ATTRIBUTE_DEINIT = 0x0001,
SET_HAL_START_ATTRIBUTE_PRE_INIT = 0x0002,
- SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
+ SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003,
+ /* Add any new HAL_START attribute prior to SET_HAL_START_ATTRIBUTE_MAX */
+ SET_HAL_START_ATTRIBUTE_MAX
} SET_HAL_START_ATTRIBUTE;
+#ifdef WL_TWT
+typedef enum {
+ WIFI_TWT_EVENT_SETUP = 1,
+ WIFI_TWT_EVENT_TEARDOWN = 2,
+ WIFI_TWT_EVENT_INFO_FRM = 3,
+ WIFI_TWT_EVENT_NOTIFY = 4
+} wifi_twt_sub_event;
+
+typedef enum {
+ WIFI_TWT_ATTR_NONE = 0,
+ WIFI_TWT_ATTR_SUB_EVENT = 1,
+ WIFI_TWT_ATTR_REASON_CODE = 2,
+ WIFI_TWT_ATTR_STATUS = 3,
+ WIFI_TWT_ATTR_SETUP_CMD = 4,
+ WIFI_TWT_ATTR_FLOW_FLAGS = 5,
+ WIFI_TWT_ATTR_FLOW_ID = 6,
+ WIFI_TWT_ATTR_CHANNEL = 7,
+ WIFI_TWT_ATTR_NEGOTIATION_TYPE = 8,
+ WIFI_TWT_ATTR_WAKETIME_H = 9,
+ WIFI_TWT_ATTR_WAKETIME_L = 10,
+ WIFI_TWT_ATTR_WAKE_DURATION = 11,
+ WIFI_TWT_ATTR_WAKE_INTERVAL = 12,
+ WIFI_TWT_ATTR_BID = 13,
+ WIFI_TWT_ATTR_ALLTWT = 14,
+ WIFI_TWT_ATTR_NEXT_TWT_H = 15,
+ WIFI_TWT_ATTR_NEXT_TWT_L = 16,
+ WIFI_TWT_ATTR_CONFIG_ID = 17,
+ WIFI_TWT_ATTR_NOTIFICATION = 18,
+ WIFI_TWT_ATTR_FLOW_TYPE = 19,
+ WIFI_TWT_ATTR_TRIGGER_TYPE = 20,
+
+ WIFI_TWT_ATTR_MAX
+} wifi_twt_attribute;
+#endif /* WL_TWT */
+
+#ifdef WL_TWT_HAL_IF
+#define BRCM_TWT_HAL_VENDOR_EVENT_BUF_LEN 500
+
+typedef enum {
+ ANDR_TWT_ATTR_NONE = 0,
+ ANDR_TWT_ATTR_CONFIG_ID = 1,
+ ANDR_TWT_ATTR_NEGOTIATION_TYPE = 2,
+ ANDR_TWT_ATTR_TRIGGER_TYPE = 3,
+ ANDR_TWT_ATTR_WAKE_DURATION = 4,
+ ANDR_TWT_ATTR_WAKE_INTERVAL = 5,
+ ANDR_TWT_ATTR_WAKE_INTERVAL_MIN = 6,
+ ANDR_TWT_ATTR_WAKE_INTERVAL_MAX = 7,
+ ANDR_TWT_ATTR_WAKE_DURATION_MIN = 8,
+ ANDR_TWT_ATTR_WAKE_DURATION_MAX = 9,
+ ANDR_TWT_ATTR_AVG_PKT_SIZE = 10,
+ ANDR_TWT_ATTR_AVG_PKT_NUM = 11,
+ ANDR_TWT_ATTR_WAKETIME_OFFSET = 12,
+ ANDR_TWT_ATTR_ALL_TWT = 13,
+ ANDR_TWT_ATTR_RESUME_TIME = 14,
+ ANDR_TWT_ATTR_AVG_EOSP_DUR = 15,
+ ANDR_TWT_ATTR_EOSP_CNT = 16,
+ ANDR_TWT_ATTR_NUM_SP = 17,
+ ANDR_TWT_ATTR_DEVICE_CAP = 18,
+ ANDR_TWT_ATTR_PEER_CAP = 19,
+ ANDR_TWT_ATTR_STATUS = 20,
+ ANDR_TWT_ATTR_REASON_CODE = 21,
+ ANDR_TWT_ATTR_TWT_RESUMED = 22,
+ ANDR_TWT_ATTR_TWT_NOTIFICATION = 23,
+ ANDR_TWT_ATTR_SUB_EVENT = 24,
+ ANDR_TWT_ATTR_NUM_PEER_STATS = 25,
+ ANDR_TWT_ATTR_AVG_PKT_NUM_TX = 26,
+ ANDR_TWT_ATTR_AVG_PKT_SIZE_TX = 27,
+ ANDR_TWT_ATTR_AVG_PKT_NUM_RX = 28,
+ ANDR_TWT_ATTR_AVG_PKT_SIZE_RX = 29,
+ ANDR_TWT_ATTR_MAX
+} andr_twt_attribute;
+
+typedef enum {
+ ANDR_TWT_EVENT_SETUP = 1,
+ ANDR_TWT_EVENT_TEARDOWN = 2,
+ ANDR_TWT_EVENT_INFO_FRM = 3,
+ ANDR_TWT_EVENT_NOTIFY = 4
+} andr_twt_sub_event;
+#endif /* WL_TWT_HAL_IF */
+
/* Capture the BRCM_VENDOR_SUBCMD_PRIV_STRINGS* here */
#define BRCM_VENDOR_SCMD_CAPA "cap"
#define MEMDUMP_PATH_LEN 128
#if defined(CUSTOM_SET_CPUCORE) || defined(APSTA_RESTRICTED_CHANNEL)
dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
#endif /* CUSTOM_SET_CPUCORE || APSTA_RESTRICTED_CHANNEL */
-#ifdef WL_EXT_IAPSTA
- enum nl80211_band band;
- s32 _chan;
-#endif /* WL_EXT_IAPSTA */
u16 center_freq = chan->center_freq;
dev = ndev_to_wlc_ndev(dev, cfg);
#ifdef WL_EXT_IAPSTA
- _chan = ieee80211_frequency_to_channel(chan->center_freq);
if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
u16 wl_iftype = 0;
u16 wl_mode = 0;
+
+ chspec = wl_freq_to_chanspec(chan->center_freq);
if (cfg80211_to_wl_iftype(dev->ieee80211_ptr->iftype,
&wl_iftype, &wl_mode) < 0) {
WL_ERR(("Unknown interface type:0x%x\n", dev->ieee80211_ptr->iftype));
return -EINVAL;
}
wl_ext_iapsta_update_iftype(dev, wl_iftype);
- _chan = wl_ext_iapsta_update_channel(dev, _chan);
- }
- if (CHANNEL_IS_5G(_chan))
- band = NL80211_BAND_5GHZ;
- else
- band = NL80211_BAND_2GHZ;
- center_freq = ieee80211_channel_to_frequency(_chan, band);
+ chspec = wl_ext_iapsta_update_channel(dev, chspec);
+ center_freq = wl_channel_to_frequency(wf_chspec_primary20_chan(chspec),
+ CHSPEC_BAND(chspec));
+ } else
#endif
chspec = wl_freq_to_chanspec(center_freq);
- WL_MSG(dev->name, "netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
- dev->ifindex, channel_type, CHSPEC_CHANNEL(chspec));
+ WL_MSG(dev->name, "netdev_ifidx(%d) chan_type(%d) target channel(%s-%d %sMHz)\n",
+ dev->ifindex, channel_type, CHSPEC2BANDSTR(chspec),
+ CHSPEC_CHANNEL(chspec), wf_chspec_to_bw_str(chspec));
#ifdef WL_P2P_6G
if (!(cfg->p2p_6g_enabled)) {
dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
#endif /* WLEASYMESH */
- new_chip = wl_new_chip_check(dev);
+ new_chip = dhd_conf_new_chip_check(cfg->pub);
if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
}
#ifdef WLEASYMESH
else if (dhd->conf->fw_type == FW_TYPE_EZMESH) {
- WL_MSG(dev->name, "Getting AP mode ok, set map and dwds");
+ WL_MSG(dev->name, "Getting AP mode ok, set map and dwds\n");
err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
if (err < 0) {
WL_ERR(("WLC_DOWN error %d\n", err));
WL_ERR(("wl dwds 1 error %d\n", err));
return err;
}
- WL_MSG(dev->name, "Get AP %d", (int)ap);
+ WL_MSG(dev->name, "Get AP %d\n", (int)ap);
}
#endif /* WLEASYMESH*/
if (wl_get_drv_status_all(cfg, CONNECTED) > 0) {
#ifdef WLEASYMESH
if (dhd->conf->fw_type == FW_TYPE_EZMESH) {
- WL_MSG(dev->name, "do wl down");
+ WL_MSG(dev->name, "do wl down\n");
} else {
#endif /* WLEASYMESH */
- WL_ERR(("Concurrent i/f operational. can't do wl down"));
+ WL_ERR(("Concurrent i/f operational. can't do wl down\n"));
return BCME_ERROR;
#ifdef WLEASYMESH
}
#ifdef WLEASYMESH
//For FrontHaulAP
if (dhd->conf->fw_type == FW_TYPE_EZMESH) {
- WL_MSG(dev->name, "wl map 2");
+ WL_MSG(dev->name, "wl map 2\n");
err = wldev_iovar_setint(dev, "map", 2);
if (err < 0) {
WL_ERR(("wl map 2 error %d\n", err));
}
#endif /* SOFTAP_UAPSD_OFF */
+#ifdef WLDWDS
+ err = wldev_iovar_setint(dev, "dwds", 1);
+ if (err < 0) {
+ WL_ERR(("set dwds error %d\n", err));
+ goto exit;
+ }
+#endif /* WLDWDS */
+
err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
if (unlikely(err)) {
WL_ERR(("WLC_UP error (%d)\n", err));
}
if (dhd->conf->chip == BCM43430_CHIP_ID && bssidx > 0 &&
(wsec & (TKIP_ENABLED|AES_ENABLED))) {
+ struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
+ struct ether_addr bssid;
+ int ret = 0;
wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround
err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
if (err < 0) {
WL_ERR(("wsec error %d\n", err));
goto exit;
}
+ bzero(&bssid, sizeof(bssid));
+ ret = wldev_ioctl_get(primary_ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
+ if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
+ scb_val_t scbval;
+ bzero(&scbval, sizeof(scb_val_t));
+ scbval.val = WLAN_REASON_DEAUTH_LEAVING;
+ wldev_ioctl_set(primary_ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
+ }
}
if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
WL_DBG(("Applying buffered WEP KEY \n"));
* hardcoded values in 'wl_cfg80211_set_channel()'.
*/
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && !defined(WL_COMPAT_WIRELESS))
- if (!dev->ieee80211_ptr->preset_chandef.chan) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ if (!dev->ieee80211_ptr->u.ap.preset_chandef.chan)
+#else
+ if (!dev->ieee80211_ptr->preset_chandef.chan)
+#endif
+ {
WL_ERR(("chan is NULL\n"));
err = -EINVAL;
goto fail;
}
if ((err = wl_cfg80211_set_channel(wiphy, dev,
- dev->ieee80211_ptr->preset_chandef.chan,
- NL80211_CHAN_HT20) < 0)) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ dev->ieee80211_ptr->u.ap.preset_chandef.chan,
+#else
+ dev->ieee80211_ptr->preset_chandef.chan,
+#endif
+ NL80211_CHAN_HT20) < 0)) {
WL_ERR(("Set channel failed \n"));
goto fail;
}
}
}
#endif /* SUPPORT_AP_RADIO_PWRSAVE */
+#ifdef WL_EXT_IAPSTA
+ wl_ext_in4way_sync(dev, 0, WL_EXT_STATUS_AP_ENABLING, NULL);
+#endif
fail:
if (err) {
WL_ERR(("ADD/SET beacon failed\n"));
wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ wl_cfg80211_stop_ap(wiphy, dev, 0);
+#else
wl_cfg80211_stop_ap(wiphy, dev);
+#endif
if (dev_role == NL80211_IFTYPE_AP) {
#ifdef WL_EXT_IAPSTA
if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
s32
wl_cfg80211_stop_ap(
struct wiphy *wiphy,
- struct net_device *dev)
+ struct net_device *dev
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ , unsigned int link_id
+#endif
+ )
{
int err = 0;
u32 dev_role = 0;
err = -EINVAL;
goto exit;
}
+#ifdef WL_EXT_IAPSTA
+ wl_ext_in4way_sync(dev, 0, WL_EXT_STATUS_AP_DISABLING, NULL);
+#endif
/* Free up resources */
wl_cfg80211_cleanup_if(dev);
(reason == WLC_E_REASON_INITIAL_ASSOC) &&
(wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
+ char chan_str[64];
/* AP/GO brought up successfull in firmware */
- WL_MSG(ndev->name, "AP/GO Link up\n");
+ wl_ext_get_chan_str(ndev, chan_str, sizeof(chan_str));
+ WL_MSG(ndev->name, "AP/GO Link up (%s)\n", chan_str);
wl_set_drv_status(cfg, AP_CREATED, ndev);
if (delayed_work_pending(&cfg->ap_work)) {
cancel_delayed_work_sync(&cfg->ap_work);
wl_ext_in4way_sync(ndev, AP_WAIT_STA_RECONNECT,
WL_EXT_STATUS_STA_CONNECTED, (void *)&e->addr);
#endif
+#ifdef STA_MGMT
+ if (!wl_ext_add_sta_info(ndev, (u8 *)&e->addr)) {
+ return -EINVAL;
+ }
+#endif /* STA_MGMT */
cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
#ifdef WL_WPS_SYNC
wl_wps_session_update(ndev, WPS_STATE_LINKUP, e->addr.octet);
wl_ext_in4way_sync(ndev, AP_WAIT_STA_RECONNECT,
WL_EXT_STATUS_STA_DISCONNECTED, (void *)&e->addr);
#endif
+#ifdef STA_MGMT
+ if (!wl_ext_del_sta_info(ndev, (u8 *)&e->addr)) {
+ return -EINVAL;
+ }
+#endif /* STA_MGMT */
cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
#ifdef WL_WPS_SYNC
wl_wps_session_update(ndev, WPS_STATE_LINKDOWN, e->addr.octet);
}
#endif /* WL_CFG80211_ACL */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
int wl_chspec_chandef(chanspec_t chanspec,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
- struct cfg80211_chan_def *chandef,
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
- struct chan_info *chaninfo,
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
- struct wiphy *wiphy)
+ struct cfg80211_chan_def *chandef, struct wiphy *wiphy)
{
uint16 freq = 0;
- int chan_type = 0;
- int channel = 0;
struct ieee80211_channel *chan;
if (!chandef) {
return -1;
+ } else {
+ memset(chandef, 0, sizeof(*chandef));
}
- channel = CHSPEC_CHANNEL(chanspec);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
+ chandef->center_freq1 = wl_channel_to_frequency(CHSPEC_CHANNEL(chanspec), CHSPEC_BAND(chanspec));
+ freq = wl_channel_to_frequency(wf_chspec_primary20_chan(chanspec), CHSPEC_BAND(chanspec));
+ chandef->chan = ieee80211_get_channel(wiphy, freq);
+ chandef->center_freq2 = 0;
switch (CHSPEC_BW(chanspec)) {
case WL_CHANSPEC_BW_20:
- chan_type = NL80211_CHAN_HT20;
+ chandef->width = NL80211_CHAN_WIDTH_20;
break;
+
case WL_CHANSPEC_BW_40:
- {
- if (CHSPEC_SB_UPPER(chanspec)) {
- channel += CH_10MHZ_APART;
- } else {
- channel -= CH_10MHZ_APART;
- }
- }
- chan_type = NL80211_CHAN_HT40PLUS;
+ chandef->width = NL80211_CHAN_WIDTH_40;
break;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
case WL_CHANSPEC_BW_80:
+ chandef->width = NL80211_CHAN_WIDTH_80;
+ break;
+
case WL_CHANSPEC_BW_8080:
{
+ /* XXX Left as is but need proper calculation for center_freq2 is used */
+ int chan_type = 0;
+ int channel = 0;
uint16 sb = CHSPEC_CTL_SB(chanspec);
if (sb == WL_CHANSPEC_CTL_SB_LL) {
chan_type = NL80211_CHAN_HT40MINUS;
else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
chan_type = NL80211_CHAN_HT40PLUS;
- }
+ freq = wl_channel_to_frequency(channel, CHSPEC_BAND(chanspec));
+ chan = ieee80211_get_channel(wiphy, freq);
+ cfg80211_chandef_create(chandef, chan, chan_type);
+ return 0;
break;
+ }
+
case WL_CHANSPEC_BW_160:
- channel = wf_chspec_primary20_chan(chanspec);
- /* Using base chan_type as kernel does not define chan_type for 160 MHz */
- chan_type = NL80211_CHAN_HT20;
+ chandef->width = NL80211_CHAN_WIDTH_160;
break;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
default:
+ chandef->width = NL80211_CHAN_WIDTH_20;
+ break;
+ }
+
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && \
+ (LINUX_VERSION_CODE <= KERNEL_VERSION (3, 7, 0)))
+
+ int chan_type = 0;
+ int channel = 0;
+ channel = CHSPEC_CHANNEL(chanspec);
+ switch (CHSPEC_BW(chanspec)) {
+ case WL_CHANSPEC_BW_20:
chan_type = NL80211_CHAN_HT20;
break;
+ case WL_CHANSPEC_BW_40:
+ if (CHSPEC_SB_UPPER(chanspec)) {
+ channel += CH_10MHZ_APART;
+ } else {
+ channel -= CH_10MHZ_APART;
+ }
+ chan_type = NL80211_CHAN_HT40PLUS;
+ break;
+ default:
+ chan_type = NL80211_CHAN_HT20;
+ break;
}
+
freq = wl_channel_to_frequency(channel, CHSPEC_BAND(chanspec));
chan = ieee80211_get_channel(wiphy, freq);
WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
return -EINVAL;
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
- cfg80211_chandef_create(chandef, chan, chan_type);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
- chaninfo->freq = freq;
- chaninfo->chan_type = chan_type;
+ chandef->freq = freq;
+ chandef->chan_type = chan_type;
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
+
return 0;
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
void
wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
{
u32 freq;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
struct cfg80211_chan_def chandef;
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
- struct chan_info chaninfo;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
if (!wiphy) {
WL_ERR(("wiphy is null\n"));
}
#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION (3, 18, 0)) */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
- if (wl_chspec_chandef(chanspec, &chandef, wiphy))
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
- if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
- {
+ if (wl_chspec_chandef(chanspec, &chandef, wiphy)) {
WL_ERR(("chspec_chandef failed\n"));
return;
}
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+ cfg80211_ch_switch_notify(dev, &chandef, 0);
+#else
cfg80211_ch_switch_notify(dev, &chandef);
+#endif
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
- freq = chan_info.freq;
- cfg80211_ch_switch_notify(dev, freq, chan_info.chan_type);
+ freq = chandef.freq;
+ cfg80211_ch_switch_notify(dev, freq, chandef.chan_type);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
WL_MSG(dev->name, "Channel switch notification for freq: %d chanspec: 0x%x\n",
defined(WL_COMPAT_WIRELESS)
extern s32 wl_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ap_settings *info);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
+extern s32 wl_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
+ unsigned int link_id);
+#else
extern s32 wl_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev);
+#endif
extern s32 wl_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_beacon_data *info);
#else
#ifdef SUPPORT_AP_BWCTRL
extern void wl_restore_ap_bw(struct bcm_cfg80211 *cfg);
#endif /* SUPPORT_AP_BWCTRL */
+
+extern int wl_chspec_chandef(chanspec_t chanspec,
+ struct cfg80211_chan_def *chandef, struct wiphy *wiphy);
#endif /* _wl_cfgvif_h_ */
#define dtohchanspec(i) (i)
#define WL_EXTRA_BUF_MAX 2048
-#define wl_escan_get_buf(a) ((wl_scan_results_t *) (a)->escan_buf)
+#define wl_escan_get_buf(a) ((wl_scan_results_v109_t *) (a)->escan_buf)
#if defined(WL_WIRELESS_EXT)
extern int wl_iw_handle_scanresults_ies(char **event_p, char *end,
- struct iw_request_info *info, wl_bss_info_t *bi);
+ struct iw_request_info *info, wl_bss_info_v109_t *bi);
#define for_each_bss_wext(list, bss, __i) \
for (__i = 0; __i < list->count && __i < IW_MAX_AP; __i++, bss = next_bss(list, bss))
#endif
return wl_chspec_host_to_driver(ioctl_ver, chanspec);
}
-static inline struct wl_bss_info *next_bss(wl_scan_results_t *list,
+static inline struct wl_bss_info *next_bss(wl_scan_results_v109_t *list,
struct wl_bss_info *bss)
{
return bss = bss ?
#ifndef BSSCACHE
static void
wl_escan_dump_bss(struct net_device *dev, struct wl_escan_info *escan,
- wl_bss_info_t *bi)
+ wl_bss_info_v109_t *bi)
{
int16 rssi;
int channel;
static s32
wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan)
{
- wl_scan_results_t *bss_list;
+ wl_scan_results_v109_t *bss_list;
#ifndef BSSCACHE
- wl_bss_info_t *bi = NULL; /* must be initialized */
+ wl_bss_info_v109_t *bi = NULL; /* must be initialized */
s32 i;
#endif
s32 err = 0;
wl_reset_bss_cache(&escan->g_bss_cache_ctrl);
if (escan->autochannel)
wl_ext_get_best_channel(dev, &escan->g_bss_cache_ctrl,
- escan->ioctl_ver, &escan->best_2g_ch, &escan->best_5g_ch);
+ &escan->best_2g_ch, &escan->best_5g_ch, &escan->best_6g_ch);
#else
bi = next_bss(bss_list, bi);
for_each_bss(bss_list, bi, i) {
wl_escan_dump_bss(dev, escan, bi);
}
if (escan->autochannel)
- wl_ext_get_best_channel(dev, bss_list, escan->ioctl_ver,
- &escan->best_2g_ch, &escan->best_5g_ch);
+ wl_ext_get_best_channel(dev, bss_list,
+ &escan->best_2g_ch, &escan->best_5g_ch, &escan->best_6g_ch);
#endif
return err;
}
#endif /* ESCAN_RESULT_PATCH */
-static wl_scan_params_t *
+static wl_scan_params_v1_t *
wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan,
int channel, int nprobes, int *out_params_size)
{
- wl_scan_params_t *params;
+ wl_scan_params_v1_t *params;
int params_size;
int num_chans;
*out_params_size = 0;
/* Our scan params only need space for 1 channel and 0 ssids */
- params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
- params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
+ params_size = WL_SCAN_PARAMS_V1_FIXED_SIZE + 1 * sizeof(uint16);
+ params = (wl_scan_params_v1_t*) kzalloc(params_size, GFP_KERNEL);
if (params == NULL) {
ESCAN_ERROR(dev->name, "mem alloc failed (%d bytes)\n", params_size);
return params;
static void
wl_escan_abort(struct net_device *dev, struct wl_escan_info *escan)
{
- wl_scan_params_t *params = NULL;
+ wl_scan_params_v1_t *params = NULL;
s32 params_size = 0;
s32 err = BCME_OK;
if (!in_atomic()) {
#ifdef ESCAN_BUF_OVERFLOW_MGMT
static void
wl_escan_find_removal_candidate(struct wl_escan_info *escan,
- wl_bss_info_t *bss, removal_element_t *candidate)
+ wl_bss_info_v109_t *bss, removal_element_t *candidate)
{
int idx;
for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
static void
wl_escan_remove_lowRSSI_info(struct net_device *dev, struct wl_escan_info *escan,
- wl_scan_results_t *list, removal_element_t *candidate, wl_bss_info_t *bi)
+ wl_scan_results_v109_t *list, removal_element_t *candidate, wl_bss_info_v109_t *bi)
{
int idx1, idx2;
int total_delete_len = 0;
for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
- int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
- wl_bss_info_t *bss = NULL;
+ int cur_len = WL_SCAN_RESULTS_V109_FIXED_SIZE;
+ wl_bss_info_v109_t *bss = NULL;
if (candidate[idx1].RSSI >= bi->RSSI)
continue;
for (idx2 = 0; idx2 < list->count; idx2++) {
- bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
+ bss = bss ? (wl_bss_info_v109_t *)((uintptr)bss + dtoh32(bss->length)) :
list->bss_info;
if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
candidate[idx1].RSSI == bss->RSSI &&
{
struct wl_escan_info *escan = (struct wl_escan_info *)argu;
s32 status = ntoh32(e->status);
- wl_bss_info_t *bi;
- wl_escan_result_t *escan_result;
- wl_bss_info_t *bss = NULL;
- wl_scan_results_t *list;
+ wl_bss_info_v109_t *bi;
+ wl_escan_result_v109_t *escan_result;
+ wl_bss_info_v109_t *bss = NULL;
+ wl_scan_results_v109_t *list;
u32 bi_length;
u32 i;
u16 channel;
mutex_lock(&escan->usr_sync);
- escan_result = (wl_escan_result_t *)data;
+ escan_result = (wl_escan_result_v109_t *)data;
if (escan->escan_state != ESCAN_STATE_SCANING) {
ESCAN_DBG(dev->name, "Not my scan\n");
goto exit;
}
bi_length = dtoh32(bi->length);
- if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
+ if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_V109_FIXED_SIZE)) {
ESCAN_ERROR(dev->name, "Invalid bss_info length %d: ignoring\n",
bi_length);
goto exit;
/* ----- terence 20130524: skip invalid bss */
{
- int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
+ int cur_len = WL_SCAN_RESULTS_V109_FIXED_SIZE;
#ifdef ESCAN_BUF_OVERFLOW_MGMT
removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
int remove_lower_rssi = FALSE;
ESCAN_DBG(dev->name, "%s(%pM) RSSI %d flags 0x%x length %d\n",
bi->SSID, &bi->BSSID, bi->RSSI, bi->flags, bi->length);
for (i = 0; i < list->count; i++) {
- bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
+ bss = bss ? (wl_bss_info_v109_t *)((uintptr)bss + dtoh32(bss->length))
: list->bss_info;
#ifdef ESCAN_BUF_OVERFLOW_MGMT
ESCAN_DBG(dev->name,
wl_uint32_list_t *list, void *scan_params, wl_scan_info_t *scan_info)
{
int err = 0;
- wl_scan_results_t *results;
+ wl_scan_results_v109_t *results;
char *ptr;
int i = 0, j = 0;
wlc_ssid_t ssid_tmp;
u32 n_channels = 0;
- uint channel;
chanspec_t chanspec;
u32 n_ssids = 0;
- wl_scan_params_t *params = NULL;
+ wl_scan_params_v1_t *params = NULL;
wl_scan_params_v2_t *params_v2 = NULL;
- u32 scan_param_size = 0;
u32 channel_offset = 0;
u32 cur_offset;
uint16 *chan_list = NULL;
results = wl_escan_get_buf(escan);
results->version = 0;
results->count = 0;
- results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
+ results->buflen = WL_SCAN_RESULTS_V109_FIXED_SIZE;
escan->escan_state = ESCAN_STATE_SCANING;
/* Arm scan timeout timer */
if (escan->scan_params_v2) {
params_v2 = (wl_scan_params_v2_t *)scan_params;
- scan_param_size = sizeof(wl_scan_params_v2_t);
channel_offset = offsetof(wl_scan_params_v2_t, channel_list);
} else {
- params = (wl_scan_params_t *)scan_params;
- scan_param_size = sizeof(wl_scan_params_t);
- channel_offset = offsetof(wl_scan_params_t, channel_list);
+ params = (wl_scan_params_v1_t *)scan_params;
+ channel_offset = offsetof(wl_scan_params_v1_t, channel_list);
}
if (params_v2) {
params->scan_type = DOT11_SCANTYPE_ACTIVE;
params->nprobes = htod32(-1);
if (scan_info->scan_time)
- params_v2->active_time = htod32(scan_info->scan_time);
+ params->active_time = htod32(scan_info->scan_time);
else
params->active_time = htod32(-1);
params->passive_time = htod32(-1);
cur_offset = channel_offset;
- n_channels = dtoh32(list->count);
+ n_channels = list->count;
/* Copy channel array if applicable */
ESCAN_SCAN(dev->name, "### List of channelspecs to scan ###\n");
if (n_channels > 0) {
for (i = 0; i < n_channels; i++) {
- channel = dtoh32(list->element[i]);
- if (!dhd_conf_match_channel(escan->pub, channel))
- continue;
- chanspec = WL_CHANSPEC_BW_20;
+ chanspec = list->element[i];
if (chanspec == INVCHANSPEC) {
ESCAN_ERROR(dev->name, "Invalid chanspec! Skipping channel\n");
continue;
}
- if (channel <= CH_MAX_2G_CHANNEL) {
- chanspec |= WL_CHANSPEC_BAND_2G;
- } else {
- chanspec |= WL_CHANSPEC_BAND_5G;
- }
- chan_list[j] = channel;
- chan_list[j] &= WL_CHANSPEC_CHAN_MASK;
- chan_list[j] |= chanspec;
+ chan_list[j] = chanspec;
ESCAN_SCAN(dev->name, "Chan : %d, Channel spec: %x\n",
- channel, chan_list[j]);
+ CHSPEC_CHANNEL(chanspec), chanspec);
chan_list[j] = wl_chspec_host_to_driver(escan->ioctl_ver,
chan_list[j]);
j++;
{
wl_event_msg_t msg;
struct wl_escan_info *escan = (struct wl_escan_info *)data;
- wl_scan_results_t *bss_list;
+ wl_scan_results_v109_t *bss_list;
struct wl_bss_info *bi = NULL;
s32 i;
u32 channel;
struct dhd_pub *dhdp = dhd_get_pub(dev);
struct wl_escan_info *escan = dhdp->escan;
s32 err = BCME_OK;
- wl_escan_params_t *eparams = NULL;
+ wl_escan_params_v1_t *eparams = NULL;
wl_escan_params_v2_t *eparams_v2 = NULL;
- u8 *scan_params = NULL;
+ u8 *scan_params = NULL, *params = NULL;
s32 params_size;
- wl_escan_params_t *params = NULL;
u32 n_channels = 0;
wl_uint32_list_t *list;
- u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+ u8 valid_chan_list[sizeof(u32)*(MAX_CTRL_CHANSPECS + 1)];
mutex_lock(&escan->usr_sync);
if (escan->escan_state == ESCAN_STATE_DOWN) {
goto exit2;
}
- ESCAN_TRACE(dev->name, "Enter \n");
+ ESCAN_TRACE(dev->name, "Enter\n");
if (escan->scan_params_v2) {
params_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
OFFSETOF(wl_escan_params_v2_t, params));
} else {
- params_size = (WL_SCAN_PARAMS_FIXED_SIZE +
- OFFSETOF(wl_escan_params_t, params));
+ params_size = (WL_SCAN_PARAMS_V1_FIXED_SIZE +
+ OFFSETOF(wl_escan_params_v1_t, params));
}
/* if scan request is not empty parse scan request paramters */
if (scan_info->channels.count) {
memcpy(list, &scan_info->channels, sizeof(wl_channel_list_t));
} else {
- list->count = htod32(WL_NUMCHANNELS);
- err = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
- sizeof(valid_chan_list), false);
+ err = wl_construct_ctl_chanspec_list(dev, list);
if (err != 0) {
ESCAN_ERROR(dev->name, "get channels failed with %d\n", err);
goto exit;
}
}
- n_channels = dtoh32(list->count);
- /* Allocate space for populating ssids in wl_escan_params_t struct */
- if (dtoh32(list->count) % 2)
+ n_channels = list->count;
+ /* Allocate space for populating ssids in wl_escan_params_v1_t struct */
+ if (list->count % 2)
/* If n_channels is odd, add a padd of u16 */
params_size += sizeof(u16) * (n_channels + 1);
else
params_size += sizeof(struct wlc_ssid) * 2;
}
- params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
+ params = kzalloc(params_size, GFP_KERNEL);
if (params == NULL) {
ESCAN_ERROR(dev->name, "kzalloc failed\n");
err = -ENOMEM;
scan_params = (u8 *)&eparams_v2->params;
eparams_v2->version = htod32(ESCAN_REQ_VERSION_V2);
eparams_v2->action = htod16(WL_SCAN_ACTION_START);
+ wl_escan_set_sync_id(eparams_v2->sync_id);
} else {
- eparams = (wl_escan_params_t *)params;
+ eparams = (wl_escan_params_v1_t *)params;
scan_params = (u8 *)&eparams->params;
- eparams->version = htod32(ESCAN_REQ_VERSION);
+ eparams->version = htod32(ESCAN_REQ_VERSION_V1);
eparams->action = htod16(WL_SCAN_ACTION_START);
+ wl_escan_set_sync_id(eparams->sync_id);
}
- wl_escan_set_sync_id(params->sync_id);
wl_escan_prep(dev, escan, list, scan_params, scan_info);
static int
wl_escan_merge_scan_results(struct net_device *dev, struct wl_escan_info *escan,
- struct iw_request_info *info, char *extra, wl_bss_info_t *bi, int *len, int max_size)
+ struct iw_request_info *info, char *extra, wl_bss_info_v109_t *bi, int *len, int max_size)
{
s32 err = BCME_OK;
struct iw_event iwe;
s32 err = BCME_OK;
int i = 0, cnt = 0;
int len_prep = 0;
- wl_bss_info_t *bi = NULL;
- wl_scan_results_t *bss_list;
+ wl_bss_info_v109_t *bi = NULL;
+ wl_scan_results_v109_t *bss_list;
__u16 buflen_from_user = dwrq->length;
bss_list = escan->bss_list;
s32 err = BCME_OK;
int i = 0, cnt = 0;
int len_prep = 0;
- wl_bss_info_t *bi = NULL;
- wl_scan_results_t *bss_list;
+ wl_bss_info_v109_t *bi = NULL;
+ wl_scan_results_v109_t *bss_list;
__u16 buflen_from_user = dwrq->length;
wl_bss_cache_t *node;
int cache_cnt = 0;
#endif
int len_prep = 0, len_ret = 0;
- wl_bss_info_t *bi = NULL;
+ wl_bss_info_v109_t *bi = NULL;
__u16 buflen_from_user = dwrq->length;
char *buf = NULL;
struct ether_addr cur_bssid;
struct ether_addr *peer_bssid, struct wl_mesh_params *mesh_info)
{
int i = 0;
- wl_bss_info_t *bi = NULL;
- wl_scan_results_t *bss_list;
+ wl_bss_info_v109_t *bi = NULL;
+ wl_scan_results_v109_t *bss_list;
int16 bi_rssi, bi_chan;
wlc_ssid_t bi_meshid;
bool is_mesh_peer = FALSE, found = FALSE;
struct wl_mesh_params *mesh_info)
{
int i = 0;
- wl_bss_info_t *bi = NULL;
- wl_scan_results_t *bss_list;
+ wl_bss_info_v109_t *bi = NULL;
+ wl_scan_results_v109_t *bss_list;
int16 bi_rssi, bi_chan, max_rssi = -100;
uint min_hop_cnt = 255;
wlc_ssid_t bi_meshid;
#if defined(WL_WIRELESS_EXT)
#include <wl_iw.h>
#endif /* WL_WIRELESS_EXT */
-#include <wl_iapsta.h>
#include <wl_android_ext.h>
+#include <wl_iapsta.h>
#include <dhd_config.h>
#define ESCAN_BUF_SIZE (64 * 1024)
int escan_state;
int ioctl_ver;
u8 escan_buf[ESCAN_BUF_SIZE];
- wl_scan_results_t *bss_list;
+ wl_scan_results_v109_t *bss_list;
u8 *escan_ioctl_buf;
struct mutex usr_sync; /* maily for up/down synchronization */
int autochannel;
int best_2g_ch;
int best_5g_ch;
+ int best_6g_ch;
#if defined(RSSIAVG)
wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
uint16 master_channel;
uint hop_cnt;
struct ether_addr peer_bssid[MAX_HOP_LIST];
- uint16 scan_channel;
+ uint32 scan_channel;
} wl_mesh_params_t;
bool wl_escan_mesh_info(struct net_device *dev,
struct wl_escan_info *escan, struct ether_addr *peer_bssid,
#else
/* Allocate workqueue for event */
if (!event_params->event_workq) {
- event_params->event_workq = alloc_workqueue("ext_eventd", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+ event_params->event_workq = alloc_workqueue("ext_eventd",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);
}
if (!event_params->event_workq) {
mutex_unlock(&event_params->event_sync);
return -ENOMEM;
}
+ memset(leaf, 0, sizeof(event_handler_list_t));
leaf->next = NULL;
leaf->dev = dev;
leaf->etype = event;
#include <net/rtnetlink.h>
#include <bcmendian.h>
#include <dhd_linux.h>
+#include <wlioctl_utils.h>
#include <wl_android.h>
#include <dhd_config.h>
#ifdef WL_CFG80211
#include <wl_cfg80211.h>
+#include <wl_cfgscan.h>
#endif /* WL_CFG80211 */
#ifdef WL_ESCAN
#include <wl_escan.h>
#endif /* WL_ESCAN */
+#ifdef BTC_WAR
+/* btc_war:
+ * -1(don't apply btc)
+ * 0(disable btc war): btc_mode=1; txchain=3; rxchain=3
+ * 1(enable btc war): txchain=2; rxchain=2; btc_mode=5
+ */
+int btc_war = -1;
+module_param(btc_war, int, 0644);
+#endif /* BTC_WAR */
+
#define IAPSTA_ERROR(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_ERROR_LEVEL) { \
#define CSA_FW_BIT (1<<0)
#define CSA_DRV_BIT (1<<1)
+#define WL_DUMP_BUF_LEN (127 * 1024)
+
#define MAX_AP_LINK_WAIT_TIME 3000
#define MAX_STA_LINK_WAIT_TIME 15000
#define STA_LINKDOWN_TIMEOUT 10000
#define STA_CONNECT_TIMEOUT 10500
+#define STA_CONNECT_FULL_CHAN_TIMEOUT 3000
#define STA_CONNECT_RETRY_TIMEOUT 600
#define STA_RECONNECT_RETRY_TIMEOUT 300
+#define STA_DISCONNECT_RECONNECT_TIMEOUT 30000
+#define STA_DISCONNECT_RECONNECT_MAX 3
+#define STA_4WAY_TIMEOUT 1000
+#ifdef EAPOL_RESEND_M4
+#define STA_KEY_INSTALL_INTERVAL 50
+#define STA_KEY_INSTALL_MAX (STA_4WAY_TIMEOUT/STA_KEY_INSTALL_INTERVAL)
+#else
+#define STA_KEY_INSTALL_INTERVAL 50
+#define STA_KEY_INSTALL_MAX 3
+#endif
#define STA_EAPOL_TIMEOUT 100
#define STA_EMPTY_SCAN_MAX 6
+#define AP_RESTART_TIMEOUT 1000
+#define AP_TXBCNFRM_TIMEOUT 10000
+#ifdef RXF0OVFL_REINIT_WAR
+#define RXF0OVFL_POLLING_TIMEOUT 1000
+#define RXF0OVFL_THRESHOLD 100
+#endif /* RXF0OVFL_REINIT_WAR */
+
+#define MAX_DWDS_IF_NUM 4
enum wl_if_list {
IF_PIF,
ENC_TKIPAES
} encmode_t;
+#ifdef STA_MGMT
+typedef struct wl_sta_info {
+ int ifidx;
+ struct ether_addr bssid;
+ struct list_head list;
+} wl_sta_info_t;
+#endif /* STA_MGMT */
+
+#ifdef TPUT_MONITOR
+typedef struct wl_tput_info {
+ unsigned long last_tx;
+ unsigned long last_rx;
+ struct osl_timespec tput_ts;
+ int32 tput_tx;
+ int32 tput_rx;
+ int32 tput_tx_kb;
+ int32 tput_rx_kb;
+} wl_tput_info_t;
+#endif /* TPUT_MONITOR */
+
+#ifdef WLDWDS
+typedef struct wl_dwds_info {
+ struct net_device *dev;
+ int ifidx;
+ uint8 bssidx;
+#ifdef TPUT_MONITOR
+ struct wl_tput_info tput_info;
+#endif /* TPUT_MONITOR */
+} wl_dwds_info_t;
+#endif /* WLDWDS */
+
typedef struct wl_if_info {
struct net_device *dev;
ifmode_t ifmode;
bgnmode_t bgnmode;
int hidden;
int maxassoc;
- uint16 channel;
+ struct wl_chan_info chan_info;
authmode_t amode;
encmode_t emode;
bool vsdb;
uint conn_state;
uint16 prev_channel;
uint16 post_channel;
+ struct osl_timespec sta_disc_ts;
+ struct osl_timespec sta_conn_ts;
+ bool ap_recon_sta;
+ wait_queue_head_t ap_recon_sta_event;
+ struct ether_addr ap_disc_sta_bssid;
+ struct osl_timespec ap_disc_sta_ts;
#ifdef TPUT_MONITOR
- unsigned long last_tx;
- unsigned long last_rx;
- struct osl_timespec tput_ts;
- int32 tput_tx;
- int32 tput_rx;
- int32 tput_tx_kb;
- int32 tput_rx_kb;
+ struct wl_tput_info tput_info;
#endif /* TPUT_MONITOR */
timer_list_compat_t connect_timer;
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
int eapol_resend_intvl;
#endif /* EAPOL_DYNAMATIC_RESEND */
#endif /* EAPOL_RESEND */
+#ifdef KEY_INSTALL_CHECK
+ timer_list_compat_t key_install_timer;
+ int key_install_cnt;
+#endif /* KEY_INSTALL_CHECK */
int empty_scan;
+#ifdef RESTART_AP_WAR
+ timer_list_compat_t restart_ap_timer;
+#endif /* RESTART_AP_WAR */
+#ifdef RESET_AP_WAR
+ timer_list_compat_t reset_ap_timer;
+ uint32 txbcnfrm;
+#endif /* RESET_AP_WAR */
+#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
+#ifdef WL_EXT_DISCONNECT_RECONNECT
+ struct osl_timespec sta_disc_conn_ts;
+ int sta_disc_recon_cnt;
+#endif /* WL_EXT_DISCONNECT_RECONNECT */
+#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
} wl_if_info_t;
typedef struct wl_apsta_params {
struct wl_if_info if_info[MAX_IF_NUM];
- struct dhd_pub *dhd;
- int ioctl_ver;
+#ifdef WLDWDS
+ struct wl_dwds_info dwds_info[MAX_DWDS_IF_NUM];
+#endif /* WLDWDS */
+ u8 *ioctl_buf;
bool init;
int rsdb;
bool vsdb;
#endif /* WLMESH && WL_ESCAN */
struct mutex in4way_sync;
int sta_btc_mode;
- struct osl_timespec sta_disc_ts;
- struct osl_timespec sta_conn_ts;
- bool ap_recon_sta;
- wait_queue_head_t ap_recon_sta_event;
- struct ether_addr ap_disc_sta_bssid;
- struct osl_timespec ap_disc_sta_ts;
#ifdef TPUT_MONITOR
timer_list_compat_t monitor_timer;
int32 tput_sum;
#ifdef EAPOL_RESEND
spinlock_t eapol_lock;
#endif /* EAPOL_RESEND */
+#ifdef STA_MGMT
+ struct list_head sta_list;
+#endif /* STA_MGMT */
+#ifdef RXF0OVFL_REINIT_WAR
+ timer_list_compat_t rxf0ovfl_timer;
+ uint32 rxbeaconmbss;
+ uint32 rxf0ovfl;
+ int war_reason;
+#endif /* RXF0OVFL_REINIT_WAR */
} wl_apsta_params_t;
enum wifi_isam_status {
ISAM_RC_MESH_ACS = 1,
ISAM_RC_TPUT_MONITOR = 2,
ISAM_RC_AP_ACS = 3,
- ISAM_RC_EAPOL_RESEND = 4
+ ISAM_RC_AP_RESTART = 4,
+ ISAM_RC_AP_RESET = 5,
+ ISAM_RC_EAPOL_RESEND = 6,
+ ISAM_RC_KEY_INSTALL = 7,
+ ISAM_RC_RXF0OVFL_REINIT = 8
};
#define wl_get_isam_status(cur_if, stat) \
static int wl_ext_enable_iface(struct net_device *dev, char *ifname,
int wait_up, bool lock);
static int wl_ext_disable_iface(struct net_device *dev, char *ifname);
-#if defined(WLMESH) && defined(WL_ESCAN)
-static int wl_mesh_escan_attach(dhd_pub_t *dhd, struct wl_if_info *cur_if);
-#endif /* WLMESH && WL_ESCAN */
static struct wl_if_info *
wl_get_cur_if(struct net_device *dev)
}
static int
-wl_ext_set_emode(struct wl_apsta_params *apsta_params,
- struct wl_if_info *cur_if)
+wl_ext_set_emode(struct wl_if_info *cur_if)
{
struct net_device *dev = cur_if->dev;
- int wsec=0;
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct wl_wsec_key wsec_key;
wsec_pmk_t psk;
authmode_t amode = cur_if->amode;
encmode_t emode = cur_if->emode;
+ int wsec=0;
char *key = cur_if->key;
- struct dhd_pub *dhd = apsta_params->dhd;
memset(&wsec_key, 0, sizeof(wsec_key));
memset(&psk, 0, sizeof(psk));
return 0;
}
-static u32
-wl_ext_get_chanspec(struct wl_apsta_params *apsta_params,
- struct net_device *dev)
+static void
+wl_ext_set_chan_info(struct wl_if_info *cur_if, uint band, uint16 chan)
+{
+ cur_if->chan_info.band = band;
+ cur_if->chan_info.chan = chan;
+}
+
+static bool
+wl_ext_associated(struct net_device *dev)
{
- int ret = 0;
struct ether_addr bssid;
- u32 chanspec = 0;
+ int ret = 0;
ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static u32
+wl_ext_get_chanspec(struct net_device *dev, struct wl_chan_info *chan_info)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ u32 chanspec = 0;
+
+ if (wl_ext_associated(dev)) {
if (wl_ext_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
- chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
+ chanspec = wl_ext_chspec_driver_to_host(dhd, chanspec);
+ if (chan_info) {
+ chan_info->band = CHSPEC2WLC_BAND(chanspec);
+ chan_info->chan = wf_chspec_ctlchan(chanspec);
+ }
return chanspec;
}
}
}
static uint16
-wl_ext_get_chan(struct wl_apsta_params *apsta_params, struct net_device *dev)
+wl_ext_get_chan(struct net_device *dev, struct wl_chan_info *chan_info)
{
- int ret = 0;
uint16 chan = 0, ctl_chan;
- struct ether_addr bssid;
u32 chanspec = 0;
-
- ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
- if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
- if (wl_ext_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
- chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
- ctl_chan = wf_chspec_ctlchan(chanspec);
- chan = (u16)(ctl_chan & 0x00FF);
- return chan;
- }
+
+ chanspec = wl_ext_get_chanspec(dev, chan_info);
+ if (chanspec) {
+ ctl_chan = wf_chspec_ctlchan(chanspec);
+ chan = (u16)(ctl_chan & 0x00FF);
}
- return 0;
+ return chan;
+}
+
+void
+wl_ext_get_chan_str(struct net_device *dev, char *chan_str, int total_len)
+{
+ struct wl_chan_info chan_info;
+ int bytes_written=0;
+ u32 chanspec = 0;
+
+ memset(chan_str, 0, total_len);
+ chanspec = wl_ext_get_chanspec(dev, &chan_info);
+ if (chanspec) {
+ bytes_written += snprintf(chan_str+bytes_written, total_len, "%s-%d %sMHz",
+ WLCBAND2STR(chan_info.band), chan_info.chan,
+ wf_chspec_to_bw_str(chanspec));
+ }
}
static chanspec_t
-wl_ext_chan_to_chanspec(struct wl_apsta_params *apsta_params,
- struct net_device *dev, uint16 channel)
+wl_ext_chan_to_chanspec(struct net_device *dev, struct wl_chan_info *chan_info)
{
- s32 _chan = channel;
- chanspec_t chspec = 0;
- chanspec_t fw_chspec = 0;
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ chanspec_band_t chanspec_band;
+ chanspec_t chspec = 0, fw_chspec = 0;
u32 bw = WL_CHANSPEC_BW_20;
- s32 err = BCME_OK;
- s32 bw_cap = 0;
+ s32 err = BCME_OK, bw_cap = 0;
s8 iovar_buf[WLC_IOCTL_SMLEN];
struct {
u32 band;
u32 bw_cap;
} param = {0, 0};
- uint band;
- if (_chan <= CH_MAX_2G_CHANNEL)
- band = IEEE80211_BAND_2GHZ;
- else
- band = IEEE80211_BAND_5GHZ;
+ if ((chan_info->band != WLC_BAND_2G) && (chan_info->band != WLC_BAND_5G) &&
+ (chan_info->band != WLC_BAND_6G)) {
+ IAPSTA_ERROR(dev->name, "bad band %d\n", chan_info->band);
+ return BCME_BADBAND;
+ }
- if (band == IEEE80211_BAND_5GHZ) {
- param.band = WLC_BAND_5G;
- err = wl_ext_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
- iovar_buf, WLC_IOCTL_SMLEN, NULL);
- if (err) {
- if (err != BCME_UNSUPPORTED) {
- IAPSTA_ERROR(dev->name, "bw_cap failed, %d\n", err);
- return err;
- } else {
- err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
- if (bw_cap != WLC_N_BW_20ALL)
- bw = WL_CHANSPEC_BW_40;
- }
+ param.band = chan_info->band;
+ err = wl_ext_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ if (err) {
+ if (err != BCME_UNSUPPORTED) {
+ IAPSTA_ERROR(dev->name, "bw_cap failed, %d\n", err);
+ return err;
} else {
- if (WL_BW_CAP_80MHZ(iovar_buf[0]))
- bw = WL_CHANSPEC_BW_80;
- else if (WL_BW_CAP_40MHZ(iovar_buf[0]))
+ err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+ if (bw_cap != WLC_N_BW_20ALL)
bw = WL_CHANSPEC_BW_40;
- else
- bw = WL_CHANSPEC_BW_20;
}
+ } else {
+ if (WL_BW_CAP_80MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_80;
+ else if (WL_BW_CAP_40MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_40;
+ else
+ bw = WL_CHANSPEC_BW_20;
}
- else if (band == IEEE80211_BAND_2GHZ)
- bw = WL_CHANSPEC_BW_20;
set_channel:
- chspec = wf_channel2chspec(_chan, bw);
+ chanspec_band = wl_ext_wlcband_to_chanspec_band(chan_info->band);
+ chspec = wf_create_chspec_from_primary(chan_info->chan, bw, chanspec_band);
if (wf_chspec_valid(chspec)) {
- fw_chspec = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, chspec);
+ fw_chspec = wl_ext_chspec_host_to_driver(dhd, chspec);
if (fw_chspec == INVCHANSPEC) {
IAPSTA_ERROR(dev->name, "failed to convert host chanspec to fw chanspec\n");
fw_chspec = 0;
assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
ret = wl_ext_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf), 0);
if (ret)
- return -1;
+ return 0;
maxassoc = dtoh32(assoc_maclist->count);
- bytes_written += snprintf(command+bytes_written, total_len,
- "%2s: %12s",
- "no", "------addr------");
for (i=0; i<maxassoc; i++) {
bytes_written += snprintf(command+bytes_written, total_len,
- "\n%2d: %pM", i, &assoc_maclist->ea[i]);
+ "\n#%02d: %pM", i, &assoc_maclist->ea[i]);
}
return bytes_written;
}
-static void
-wl_ext_mod_timer(timer_list_compat_t *timer, uint sec, uint msec)
-{
- uint timeout = sec * 1000 + msec;
-
- IAPSTA_TRACE("wlan", "timeout=%d\n", timeout);
-
- if (timer_pending(timer))
- del_timer_sync(timer);
-
- if (timeout)
- mod_timer(timer, jiffies + msecs_to_jiffies(timeout));
-}
-
-static void
-wl_ext_send_event_msg(struct net_device *dev, int event, int status)
+void
+wl_ext_send_event_msg(struct net_device *dev, int event, int status,
+ int reason)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
struct wl_if_info *cur_if;
wl_event_msg_t msg;
- cur_if = wl_get_cur_if(dev);
- if (!cur_if)
- return;
-
- bzero(&msg, sizeof(wl_event_msg_t));
-
- msg.ifidx = hton32(dhd_net2idx(dhd->info, dev));
- msg.event_type = hton32(event);
- msg.status = hton32(status);
- memcpy(&msg.addr, &cur_if->bssid, ETHER_ADDR_LEN);
-
+ if (dhd && dhd->up) {
+ cur_if = wl_get_cur_if(dev);
+ if (!cur_if)
+ return;
+ bzero(&msg, sizeof(wl_event_msg_t));
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
+ msg.event_type = hton32(event);
+ msg.status = hton32(status);
+ msg.reason = hton32(reason);
+ memcpy(&msg.addr, &cur_if->bssid, ETHER_ADDR_LEN);
#ifdef WL_EVENT
- wl_ext_event_send(dhd->event_params, &msg, NULL);
-#endif
+ wl_ext_event_send(dhd->event_params, &msg, NULL);
+#endif /* WL_EVENT */
#ifdef WL_CFG80211
- if (dhd->up) {
wl_cfg80211_event(dev, &msg, NULL);
+#endif /* WL_CFG80211 */
+ }
+}
+
+#ifdef BTC_WAR
+bool
+wl_ext_iapsta_if_2g_enabled(struct net_device *net)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *tmp_if;
+ struct wl_chan_info chan_info;
+ bool enabled = FALSE;
+ uint16 cur_chan;
+ int i;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if && wl_get_isam_status(tmp_if, IF_READY)) {
+ cur_chan = wl_ext_get_chan(tmp_if->dev, &chan_info);
+ if (cur_chan && chan_info.band == WLC_BAND_2G) {
+ enabled = TRUE;
+ break;
+ }
+ }
+ }
+
+ return enabled;
+}
+
+void
+wl_ext_btc_config(struct net_device *dev, bool enable)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ bool enab = FALSE;
+
+ if (dhd->conf->chip == BCM4354_CHIP_ID || dhd->conf->chip == BCM4356_CHIP_ID ||
+ dhd->conf->chip == BCM43752_CHIP_ID) {
+ IAPSTA_INFO(dev->name, "btc_war=%d, enable=%d\n", btc_war, enable);
+ if (btc_war >= 0) {
+ if (enable && btc_war > 0) {
+ if (wl_ext_iapsta_if_2g_enabled(dev))
+ enab = TRUE;
+ }
+ if (enab) {
+ IAPSTA_INFO(dev->name, "enable\n");
+ wl_ext_iovar_setint(dev, "txchain", 2);
+ wl_ext_iovar_setint(dev, "rxchain", 2);
+ wl_ext_iovar_setint(dev, "btc_mode", 5);
+ } else {
+ IAPSTA_INFO(dev->name, "disable\n");
+ wl_ext_iovar_setint(dev, "btc_mode", 1);
+ wl_ext_iovar_setint(dev, "txchain", 3);
+ wl_ext_iovar_setint(dev, "rxchain", 3);
+ }
+ }
}
-#endif /* defined(WL_CFG80211) */
}
+#endif /* BTC_WAR */
static void
wl_ext_connect_timeout(unsigned long data)
cur_if->assoc_info.reassoc = 0;
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
IAPSTA_ERROR(dev->name, "timer expired\n");
- wl_ext_send_event_msg(dev, WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS);
+ wl_ext_send_event_msg(dev, WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WLC_E_STATUS_SUCCESS);
}
#if defined(WL_CFG80211) || (defined(WLMESH) && defined(WL_ESCAN))
tmp_if = &apsta_params->if_info[i];
if (tmp_if && tmp_if->ifmode == ifmode &&
wl_get_isam_status(tmp_if, IF_READY)) {
- if (wl_ext_get_chan(apsta_params, tmp_if->dev)) {
+ if (wl_ext_associated(tmp_if->dev)) {
target_if = tmp_if;
break;
}
}
#ifdef WL_ESCAN
-#define WL_MESH_DELAY_SCAN_TMO 3
+#define WL_MESH_DELAY_SCAN_TMO 3000
static void
wl_mesh_timer(unsigned long data)
{
bzero(&msg, sizeof(wl_event_msg_t));
IAPSTA_TRACE(dev->name, "timer expired\n");
- msg.ifidx = hton32(dhd_net2idx(dhd->info, dev));
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
msg.event_type = hton32(WLC_E_RESERVED);
msg.reason = hton32(ISAM_RC_MESH_ACS);
wl_ext_event_send(dhd->event_params, &msg, NULL);
}
static int
-wl_mesh_clear_mesh_info(struct wl_apsta_params *apsta_params,
- struct wl_if_info *mesh_if, bool scan)
+wl_mesh_clear_mesh_info(struct wl_if_info *mesh_if, bool scan)
{
+ struct dhd_pub *dhd = dhd_get_pub(mesh_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
uchar mesh_oui[]={0x00, 0x22, 0xf4};
int ret;
ret = wl_mesh_clear_vndr_ie(mesh_if->dev, mesh_oui);
memset(mesh_info, 0, sizeof(struct wl_mesh_params));
if (scan) {
- mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
- wl_ext_mod_timer(&mesh_if->delay_scan, 0, 100);
+ mesh_info->scan_channel = wl_ext_get_chan(mesh_if->dev,
+ &mesh_if->chan_info);
+ wl_timer_mod(dhd, &mesh_if->delay_scan, 100);
}
return ret;
if (sta_if) {
wldev_ioctl(mesh_if->dev, WLC_GET_BSSID, &mesh_info->master_bssid,
ETHER_ADDR_LEN, 0);
- mesh_info->master_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
+ mesh_info->master_channel = wl_ext_get_chan(mesh_if->dev, &mesh_if->chan_info);
mesh_info->hop_cnt = 0;
memset(mesh_info->peer_bssid, 0, MAX_HOP_LIST*ETHER_ADDR_LEN);
if (!wl_mesh_update_vndr_ie(apsta_params, mesh_if))
wl_ext_get_sec(mesh_if->dev, mesh_if->ifmode, sec, sizeof(sec), FALSE);
if (strnicmp(sec, "sae/sae", strlen("sae/sae")) == 0)
sae = TRUE;
- cur_chan = wl_ext_get_chan(apsta_params, mesh_if->dev);
+ cur_chan = wl_ext_get_chan(mesh_if->dev, &mesh_if->chan_info);
bss_found = wl_escan_mesh_peer(mesh_if->dev, mesh_if->escan, &cur_ssid, cur_chan,
sae, &peer_mesh_info);
}
static void
-wl_mesh_event_handler(struct wl_apsta_params *apsta_params,
- struct wl_if_info *mesh_if, const wl_event_msg_t *e, void *data)
+wl_mesh_event_handler(struct wl_if_info *cur_if,
+ const wl_event_msg_t *e, void *data)
{
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
uint32 event_type = ntoh32(e->event_type);
uint32 status = ntoh32(e->status);
uint32 reason = ntoh32(e->reason);
- int ret;
+ uint16 flags = ntoh16(e->flags);
+ struct wl_if_info *mesh_if = NULL, *tmp_if = NULL;
+ int ret, i;
- if (wl_get_isam_status(mesh_if, AP_CREATED) &&
- ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
- (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
- reason == WLC_E_REASON_INITIAL_ASSOC))) {
- if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
- mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
- wl_ext_mod_timer(&mesh_if->delay_scan, WL_MESH_DELAY_SCAN_TMO, 0);
- }
- }
- else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
- (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
- reason == WLC_E_REASON_DEAUTH)) {
- wl_mesh_clear_mesh_info(apsta_params, mesh_if, FALSE);
- }
- else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
- (event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
- reason == DOT11_SC_SUCCESS) {
- mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
- wl_ext_mod_timer(&mesh_if->delay_scan, 0, 100);
- }
- else if (event_type == WLC_E_DISASSOC_IND || event_type == WLC_E_DEAUTH_IND ||
- (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
- if (!memcmp(&mesh_info->peer_bssid, &e->addr, ETHER_ADDR_LEN))
- wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
- }
- else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
- event_type == WLC_E_RESERVED && reason == ISAM_RC_MESH_ACS) {
- if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
- wl_scan_info_t scan_info;
- memset(&scan_info, 0, sizeof(wl_scan_info_t));
- wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &scan_info.ssid, sizeof(wlc_ssid_t), 0);
- scan_info.channels.count = 1;
- scan_info.channels.channel[0] = mesh_info->scan_channel;
- ret = wl_escan_set_scan(mesh_if->dev, &scan_info);
- if (ret)
- wl_ext_mod_timer(&mesh_if->delay_scan, WL_MESH_DELAY_SCAN_TMO, 0);
+ if (cur_if->ifmode == IMESH_MODE)
+ mesh_if = cur_if;
+ else {
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->dev && tmp_if->ifmode == IMESH_MODE) {
+ mesh_if = tmp_if;
+ break;
+ }
+ }
+ }
+
+ if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) {
+ if (event_type == WLC_E_LINK) {
+ if (!(flags & WLC_EVENT_MSG_LINK)) {
+ if (mesh_if && apsta_params->macs)
+ wl_mesh_clear_mesh_info(mesh_if, TRUE);
+ } else {
+ if (mesh_if && apsta_params->macs)
+ wl_mesh_update_master_info(apsta_params, mesh_if);
+ }
+ }
+ else if (event_type == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) {
+ if (mesh_if && apsta_params->macs)
+ wl_mesh_clear_mesh_info(mesh_if, TRUE);
+ }
+ else if (event_type == WLC_E_DEAUTH || event_type == WLC_E_DEAUTH_IND ||
+ event_type == WLC_E_DISASSOC || event_type == WLC_E_DISASSOC_IND) {
+ if (mesh_if && apsta_params->macs)
+ wl_mesh_clear_mesh_info(mesh_if, TRUE);
}
}
- else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
- ((event_type == WLC_E_ESCAN_RESULT && status == WLC_E_STATUS_SUCCESS) ||
- (event_type == WLC_E_ESCAN_RESULT &&
- (status == WLC_E_STATUS_ABORT || status == WLC_E_STATUS_NEWSCAN ||
- status == WLC_E_STATUS_11HQUIET || status == WLC_E_STATUS_CS_ABORT ||
- status == WLC_E_STATUS_NEWASSOC || status == WLC_E_STATUS_TIMEOUT)))) {
- if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
- if (!wl_mesh_update_mesh_info(apsta_params, mesh_if)) {
- mesh_info->scan_channel = 0;
- wl_ext_mod_timer(&mesh_if->delay_scan, WL_MESH_DELAY_SCAN_TMO, 0);
+ else if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) {
+ if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+ ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
+ (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_INITIAL_ASSOC))) {
+ if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
+ mesh_info->scan_channel = wl_ext_get_chan(&mesh_if->dev,
+ mesh_if->chan_info);
+ wl_timer_mod(dhd, &mesh_if->delay_scan, WL_MESH_DELAY_SCAN_TMO);
+ }
+ }
+ else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
+ (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_DEAUTH)) {
+ wl_mesh_clear_mesh_info(mesh_if, FALSE);
+ }
+ else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+ (event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
+ reason == DOT11_SC_SUCCESS) {
+ mesh_info->scan_channel = wl_ext_get_chan(mesh_if->dev,
+ &mesh_if->chan_info);
+ wl_timer_mod(dhd, &mesh_if->delay_scan, 100);
+ }
+ else if (event_type == WLC_E_DISASSOC_IND || event_type == WLC_E_DEAUTH_IND ||
+ (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
+ if (!memcmp(&mesh_info->peer_bssid, &e->addr, ETHER_ADDR_LEN))
+ wl_mesh_clear_mesh_info(mesh_if, TRUE);
+ }
+ else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+ event_type == WLC_E_RESERVED && reason == ISAM_RC_MESH_ACS) {
+ if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
+ wl_scan_info_t scan_info;
+ memset(&scan_info, 0, sizeof(wl_scan_info_t));
+ wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &scan_info.ssid, sizeof(wlc_ssid_t), 0);
+ if (mesh_info->scan_channel) {
+ scan_info.channels.count = 1;
+ scan_info.channels.channel[0] = mesh_info->scan_channel;
+ }
+ ret = wl_escan_set_scan(mesh_if->dev, &scan_info);
+ if (ret)
+ wl_timer_mod(dhd, &mesh_if->delay_scan, WL_MESH_DELAY_SCAN_TMO);
+ }
+ }
+ else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+ ((event_type == WLC_E_ESCAN_RESULT && status == WLC_E_STATUS_SUCCESS) ||
+ (event_type == WLC_E_ESCAN_RESULT &&
+ (status == WLC_E_STATUS_ABORT || status == WLC_E_STATUS_NEWSCAN ||
+ status == WLC_E_STATUS_11HQUIET || status == WLC_E_STATUS_CS_ABORT ||
+ status == WLC_E_STATUS_NEWASSOC || status == WLC_E_STATUS_TIMEOUT)))) {
+ if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
+ if (!wl_mesh_update_mesh_info(apsta_params, mesh_if)) {
+ mesh_info->scan_channel = 0;
+ wl_timer_mod(dhd, &mesh_if->delay_scan, WL_MESH_DELAY_SCAN_TMO);
+ }
}
}
}
wl_mesh_escan_detach(dhd_pub_t *dhd, struct wl_if_info *mesh_if)
{
IAPSTA_TRACE(mesh_if->dev->name, "Enter\n");
-
- del_timer_sync(&mesh_if->delay_scan);
-
+ wl_timer_deregister(mesh_if->dev, &mesh_if->delay_scan);
if (mesh_if->escan) {
mesh_if->escan = NULL;
}
IAPSTA_TRACE(mesh_if->dev->name, "Enter\n");
mesh_if->escan = dhd->escan;
- init_timer_compat(&mesh_if->delay_scan, wl_mesh_timer, mesh_if->dev);
+ wl_timer_register(mesh_if->dev, &mesh_if->delay_scan, wl_mesh_timer);
return 0;
}
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
struct wl_if_info *tmp_if;
- uint16 chan = 0;
char *dump_buf = NULL;
int dump_len = WLC_IOCTL_MEDLEN;
int dump_written = 0;
for (i=0; i<MAX_IF_NUM; i++) {
tmp_if = &apsta_params->if_info[i];
if (tmp_if->dev && tmp_if->ifmode == IMESH_MODE && apsta_params->macs) {
- chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if (chan) {
+ if (wl_ext_associated(tmp_if->dev)) {
dump_written += snprintf(dump_buf+dump_written, dump_len,
DHD_LOG_PREFIXS "[%s-%c] mbssid=%pM, mchan=%d, hop=%d, pbssid=%pM",
tmp_if->ifname, tmp_if->prefix, &mesh_info->master_bssid,
wl_ext_if_up(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if,
bool force_enable, int wait_up)
{
+ struct wl_chan_info *chan_info = &cur_if->chan_info;
s8 iovar_buf[WLC_IOCTL_SMLEN];
struct {
s32 cfg;
chanspec_t fw_chspec;
u32 timeout;
wlc_ssid_t ssid = { 0, {0} };
- uint16 chan = 0;
+ uint32 chanspec = 0;
- if (cur_if->ifmode != IAP_MODE) {
+ if (cur_if->ifmode != IAP_MODE && cur_if->ifmode != IGO_MODE) {
IAPSTA_ERROR(cur_if->ifname, "Wrong ifmode\n");
return 0;
}
- if (wl_ext_dfs_chan(cur_if->channel) && !apsta_params->radar && !force_enable) {
+ if (wl_ext_dfs_chan(chan_info) && !apsta_params->radar && !force_enable) {
WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
- cur_if->prefix, cur_if->channel);
+ cur_if->prefix, chan_info->chan);
return 0;
- } else if (!cur_if->channel) {
+ } else if (wl_ext_passive_chan(cur_if->dev, chan_info)) {
+ WL_MSG(cur_if->ifname, "[%c] skip PASSIVE channel %d\n",
+ cur_if->prefix, chan_info->chan);
+ return 0;
+ } else if (!chan_info->chan) {
WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
return 0;
}
WL_MSG(cur_if->ifname, "[%c] Turning on...\n", cur_if->prefix);
- wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
- &fw_chspec);
+ wl_ext_set_chanspec(cur_if->dev, chan_info, &fw_chspec);
wl_clr_isam_status(cur_if, AP_CREATED);
wl_set_isam_status(cur_if, AP_CREATING);
}
wl_ext_ioctl(cur_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
- chan = wl_ext_get_chan(apsta_params, cur_if->dev);
- WL_MSG(cur_if->ifname, "[%c] enabled with SSID: \"%s\" on channel %d\n",
- cur_if->prefix, ssid.SSID, chan);
+ chanspec = wl_ext_get_chanspec(cur_if->dev, chan_info);
+ WL_MSG(cur_if->ifname, "[%c] enabled with SSID: \"%s\" on channel %s-%d(0x%x)\n",
+ cur_if->prefix, ssid.SSID, CHSPEC2BANDSTR(chanspec),
+ chan_info->chan, chanspec);
wl_clr_isam_status(cur_if, AP_CREATING);
}
static bool
-wl_ext_diff_band(uint16 chan1, uint16 chan2)
+wl_ext_same_chan(struct wl_chan_info *chan_info_1,
+ struct wl_chan_info *chan_info_2)
+{
+ if (chan_info_1->band == chan_info_2->band &&
+ chan_info_1->chan == chan_info_2->chan) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool
+wl_ext_rsdb_band(uint band_1, uint band_2)
{
- if ((chan1 <= CH_MAX_2G_CHANNEL && chan2 > CH_MAX_2G_CHANNEL) ||
- (chan1 > CH_MAX_2G_CHANNEL && chan2 <= CH_MAX_2G_CHANNEL)) {
+ if ((band_1 == WLC_BAND_2G && band_2 != WLC_BAND_2G) ||
+ (band_2 == WLC_BAND_2G && band_1 != WLC_BAND_2G)) {
return TRUE;
}
return FALSE;
}
static uint16
-wl_ext_same_band(struct wl_apsta_params *apsta_params,
+wl_ext_get_same_band_chan(struct wl_apsta_params *apsta_params,
struct wl_if_info *cur_if, bool nodfs)
{
struct wl_if_info *tmp_if;
- uint16 tmp_chan, target_chan = 0;
+ struct wl_chan_info chan_info;
wl_prio_t max_prio;
+ uint16 chan = 0;
int i;
// find the max prio
tmp_if = &apsta_params->if_info[i];
if (cur_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) &&
tmp_if->prio > max_prio) {
- tmp_chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if (wl_ext_dfs_chan(tmp_chan) && nodfs)
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(tmp_if->dev, &chan_info);
+ if (wl_ext_dfs_chan(&chan_info) && nodfs)
continue;
- if (tmp_chan && !wl_ext_diff_band(cur_if->channel, tmp_chan)) {
- target_chan = tmp_chan;
+ if (chan_info.chan && (cur_if->chan_info.band == chan_info.band)) {
+ chan = chan_info.chan;
max_prio = tmp_if->prio;
}
}
}
- return target_chan;
+ return chan;
}
static uint16
wl_ext_get_vsdb_chan(struct wl_apsta_params *apsta_params,
- struct wl_if_info *cur_if, struct wl_if_info *target_if)
+ const struct wl_if_info *cur_if, const struct wl_if_info *target_if)
{
- uint16 target_chan = 0, cur_chan = cur_if->channel;
+ struct wl_chan_info chan_info;
+ uint cur_band = cur_if->chan_info.band;
+ uint16 cur_chan = cur_if->chan_info.chan;
+ uint target_band;
+ uint16 target_chan;
if (cur_if->vsdb && target_if->vsdb)
return 0;
- target_chan = wl_ext_get_chan(apsta_params, target_if->dev);
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ target_chan = wl_ext_get_chan(target_if->dev, &chan_info);
if (target_chan) {
- IAPSTA_INFO(cur_if->ifname, "cur_chan=%d, target_chan=%d\n",
- cur_chan, target_chan);
- if (wl_ext_diff_band(cur_chan, target_chan)) {
+ target_band = chan_info.band;
+ IAPSTA_INFO(cur_if->ifname, "cur_chan=%s-%d, target_chan=%s-%d\n",
+ WLCBAND2STR(cur_band), cur_chan,
+ WLCBAND2STR(target_band), target_chan);
+ if (wl_ext_rsdb_band(cur_band, target_band)) {
if (!apsta_params->rsdb)
return target_chan;
} else {
struct wl_if_info *cur_if)
{
struct wl_if_info *tmp_if;
- uint16 cur_chan, tmp_chan;
+ struct wl_chan_info cur_chan_info, tmp_chan_info;
int i;
if (apsta_params->rsdb) {
- cur_chan = wl_ext_get_chan(apsta_params, cur_if->dev);
+ memset(&cur_chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(cur_if->dev, &cur_chan_info);
for (i=0; i<MAX_IF_NUM; i++) {
tmp_if = &apsta_params->if_info[i];
if (tmp_if != cur_if && wl_get_isam_status(tmp_if, IF_READY) &&
tmp_if->prio > cur_if->prio) {
- tmp_chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if (!tmp_chan)
+ memset(&tmp_chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(tmp_if->dev, &tmp_chan_info);
+ if (!tmp_chan_info.chan)
continue;
- if (wl_ext_diff_band(cur_chan, tmp_chan) &&
- wl_ext_diff_band(cur_chan, cur_if->channel))
+ if (wl_ext_rsdb_band(cur_chan_info.band, tmp_chan_info.band) &&
+ wl_ext_rsdb_band(cur_chan_info.band, cur_if->chan_info.chan))
return TRUE;
- else if (!wl_ext_diff_band(cur_chan, tmp_chan) &&
- wl_ext_diff_band(cur_chan, cur_if->channel))
+ else if (!wl_ext_rsdb_band(cur_chan_info.band, tmp_chan_info.band) &&
+ wl_ext_rsdb_band(cur_chan_info.band, cur_if->chan_info.chan))
return TRUE;
}
}
bool core_conflict = FALSE;
if (wl_ext_master_if(cur_if) && (apsta_params->csa & CSA_DRV_BIT)) {
- if (!cur_if->channel) {
+ if (!cur_if->chan_info.chan) {
WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
- } else if (wl_ext_dfs_chan(cur_if->channel) && !apsta_params->radar) {
+ } else if (wl_ext_dfs_chan(&cur_if->chan_info) && !apsta_params->radar) {
WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
- cur_if->prefix, cur_if->channel);
+ cur_if->prefix, cur_if->chan_info.chan);
wl_ext_if_down(apsta_params, cur_if);
} else {
wl_chan_switch_t csa_arg;
memset(&csa_arg, 0, sizeof(csa_arg));
csa_arg.mode = 1;
csa_arg.count = 3;
- csa_arg.chspec = wl_ext_chan_to_chanspec(apsta_params, cur_if->dev,
- cur_if->channel);
+ csa_arg.chspec = wl_ext_chan_to_chanspec(cur_if->dev, &cur_if->chan_info);
core_conflict = wl_ext_rsdb_core_conflict(apsta_params, cur_if);
if (core_conflict) {
WL_MSG(cur_if->ifname, "[%c] Skip CSA due to rsdb core conflict\n",
cur_if->prefix);
} else if (csa_arg.chspec) {
WL_MSG(cur_if->ifname, "[%c] Trigger CSA to channel %d(0x%x)\n",
- cur_if->prefix, cur_if->channel, csa_arg.chspec);
+ cur_if->prefix, cur_if->chan_info.chan, csa_arg.chspec);
wl_set_isam_status(cur_if, AP_CREATING);
wl_ext_iovar_setbuf(cur_if->dev, "csa", &csa_arg, sizeof(csa_arg),
iovar_buf, sizeof(iovar_buf), NULL);
wl_ext_move_cur_dfs_channel(struct wl_apsta_params *apsta_params,
struct wl_if_info *cur_if)
{
- uint16 other_chan = 0, cur_chan = cur_if->channel;
+ struct wl_chan_info *cur_chan_info = &cur_if->chan_info;
+ uint cur_band = cur_chan_info->band;
+ uint16 cur_chan = cur_chan_info->chan, auto_chan = 0;
uint16 chan_2g = 0, chan_5g = 0;
- uint32 auto_band = WLC_BAND_2G;
-
- if (wl_ext_master_if(cur_if) && wl_ext_dfs_chan(cur_if->channel) &&
- !apsta_params->radar) {
+ if (!apsta_params->radar && wl_ext_master_if(cur_if) &&
+ wl_ext_dfs_chan(cur_chan_info)) {
wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE);
if (!chan_2g && !chan_5g) {
- cur_if->channel = 0;
+ cur_chan_info->chan = 0;
WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
return;
}
-
if (apsta_params->vsdb) {
- if (chan_5g) {
- cur_if->channel = chan_5g;
- auto_band = WLC_BAND_5G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
- } else {
- cur_if->channel = chan_2g;
- auto_band = WLC_BAND_2G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
- }
- if (!other_chan) {
- other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
- auto_band);
+ if (chan_5g)
+ wl_ext_set_chan_info(cur_if, WLC_BAND_5G, chan_5g);
+ else
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, chan_2g);
+ auto_chan = wl_ext_get_same_band_chan(apsta_params, cur_if, TRUE);
+ if (!auto_chan) {
+ auto_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+ cur_chan_info->band);
}
- if (other_chan)
- cur_if->channel = other_chan;
- } else if (apsta_params->rsdb) {
+ if (auto_chan)
+ cur_chan_info->chan = auto_chan;
+ }
+ else if (apsta_params->rsdb) {
if (chan_5g) {
- cur_if->channel = chan_5g;
- auto_band = WLC_BAND_5G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, FALSE);
- if (wl_ext_dfs_chan(other_chan) && chan_2g) {
- cur_if->channel = chan_2g;
- auto_band = WLC_BAND_2G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+ wl_ext_set_chan_info(cur_if, WLC_BAND_5G, chan_5g);
+ auto_chan = wl_ext_get_same_band_chan(apsta_params, cur_if, FALSE);
+ if (auto_chan) {
+ if (wl_ext_dfs_chan(cur_chan_info) && chan_2g) {
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, chan_2g);
+ auto_chan = wl_ext_get_same_band_chan(apsta_params, cur_if, TRUE);
+ }
}
} else {
- cur_if->channel = chan_2g;
- auto_band = WLC_BAND_2G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, chan_2g);
+ auto_chan = wl_ext_get_same_band_chan(apsta_params, cur_if, TRUE);
}
- if (!other_chan) {
- other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
- auto_band);
+ if (!auto_chan) {
+ auto_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+ cur_chan_info->band);
}
- if (other_chan)
- cur_if->channel = other_chan;
- } else {
- cur_if->channel = chan_5g;
- other_chan = wl_ext_same_band(apsta_params, cur_if, FALSE);
- if (other_chan) {
- cur_if->channel = other_chan;
+ if (auto_chan) {
+ cur_chan_info->chan = auto_chan;
+ }
+ }
+ else {
+ wl_ext_set_chan_info(cur_if, WLC_BAND_5G, chan_5g);
+ auto_chan = wl_ext_get_same_band_chan(apsta_params, cur_if, FALSE);
+ if (auto_chan) {
+ cur_chan_info->chan = auto_chan;
} else {
- auto_band = WLC_BAND_5G;
- other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
- auto_band);
- if (other_chan)
- cur_if->channel = other_chan;
+ auto_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+ cur_chan_info->band);
+ if (auto_chan) {
+ cur_chan_info->chan = auto_chan;
+ }
}
}
- WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n",
- cur_if->prefix, cur_chan, cur_if->channel);
+ WL_MSG(cur_if->ifname, "[%c] move channel %s-%d => %s-%d\n",
+ cur_if->prefix, WLCBAND2STR(cur_band), cur_chan,
+ WLCBAND2STR(cur_chan_info->band), cur_chan_info->chan);
}
}
static void
wl_ext_move_other_dfs_channel(struct wl_apsta_params *apsta_params,
- struct wl_if_info *cur_if)
+ struct wl_if_info *tgt_if)
{
- uint16 other_chan = 0, cur_chan = cur_if->channel;
+ struct wl_chan_info *tgt_chan_info = &tgt_if->chan_info;
+ uint cur_band = tgt_chan_info->band;
+ uint16 cur_chan = tgt_chan_info->chan, auto_chan = 0;
uint16 chan_2g = 0, chan_5g = 0;
- uint32 auto_band = WLC_BAND_2G;
- if (wl_ext_master_if(cur_if) && wl_ext_dfs_chan(cur_if->channel) &&
- !apsta_params->radar) {
-
- wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE);
+ if (!apsta_params->radar && wl_ext_master_if(tgt_if) &&
+ wl_ext_dfs_chan(tgt_chan_info)) {
+ wl_ext_get_default_chan(tgt_if->dev, &chan_2g, &chan_5g, TRUE);
if (!chan_2g && !chan_5g) {
- cur_if->channel = 0;
- WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
+ tgt_chan_info->chan = 0;
+ WL_MSG(tgt_if->ifname, "[%c] no valid channel\n", tgt_if->prefix);
return;
}
if (apsta_params->vsdb) {
- if (chan_5g) {
- cur_if->channel = chan_5g;
- auto_band = WLC_BAND_5G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
- } else {
- cur_if->channel = chan_2g;
- auto_band = WLC_BAND_2G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+ if (chan_5g)
+ wl_ext_set_chan_info(tgt_if, WLC_BAND_5G, chan_5g);
+ else
+ wl_ext_set_chan_info(tgt_if, WLC_BAND_2G, chan_2g);
+ auto_chan = wl_ext_get_same_band_chan(apsta_params, tgt_if, TRUE);
+ if (!auto_chan) {
+ auto_chan = wl_ext_autochannel(tgt_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+ tgt_chan_info->band);
}
- if (!other_chan) {
- other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
- auto_band);
+ if (auto_chan) {
+ tgt_chan_info->chan = auto_chan;
}
- if (other_chan)
- cur_if->channel = other_chan;
- } else if (apsta_params->rsdb) {
+ }
+ else if (apsta_params->rsdb) {
if (chan_2g) {
- cur_if->channel = chan_2g;
- auto_band = WLC_BAND_2G;
- other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
- if (!other_chan) {
- other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
- auto_band);
+ wl_ext_set_chan_info(tgt_if, WLC_BAND_2G, chan_2g);
+ auto_chan = wl_ext_get_same_band_chan(apsta_params, tgt_if, TRUE);
+ if (!auto_chan) {
+ auto_chan = wl_ext_autochannel(tgt_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+ tgt_chan_info->band);
}
} else {
- cur_if->channel = 0;
+ tgt_chan_info->chan = 0;
+ }
+ if (auto_chan) {
+ tgt_chan_info->chan = auto_chan;
}
- if (other_chan)
- cur_if->channel = other_chan;
} else {
- cur_if->channel = 0;
+ tgt_chan_info->chan = 0;
}
- WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n",
- cur_if->prefix, cur_chan, cur_if->channel);
+ WL_MSG(tgt_if->ifname, "[%c] move channel %s-%d => %s-%d\n",
+ tgt_if->prefix, WLCBAND2STR(cur_band), cur_chan,
+ WLCBAND2STR(tgt_chan_info->band), tgt_chan_info->chan);
}
}
struct wl_if_info *cur_if)
{
struct wl_if_info *tmp_if, *target_if = NULL;
- uint16 tmp_chan, target_chan = 0;
+ struct wl_chan_info cur_chan_info, tgt_chan_info;
+ uint16 tmp_chan;
wl_prio_t max_prio;
int i;
if (apsta_params->vsdb) {
- target_chan = cur_if->channel;
goto exit;
}
tmp_chan = wl_ext_get_vsdb_chan(apsta_params, cur_if, tmp_if);
if (tmp_chan) {
target_if = tmp_if;
- target_chan = tmp_chan;
max_prio = tmp_if->prio;
}
}
}
- if (target_chan) {
- tmp_chan = wl_ext_get_chan(apsta_params, cur_if->dev);
- if (apsta_params->rsdb && tmp_chan &&
- wl_ext_diff_band(tmp_chan, target_chan)) {
- WL_MSG(cur_if->ifname, "[%c] keep on current channel %d\n",
- cur_if->prefix, tmp_chan);
- cur_if->channel = 0;
+ if (target_if) {
+ memset(&cur_chan_info, 0, sizeof(struct wl_chan_info));
+ memset(&tgt_chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(cur_if->dev, &cur_chan_info);
+ wl_ext_get_chan(target_if->dev, &tgt_chan_info);
+ if (apsta_params->rsdb && cur_chan_info.chan &&
+ wl_ext_rsdb_band(cur_chan_info.band, tgt_chan_info.band)) {
+ WL_MSG(cur_if->ifname, "[%c] keep on current channel %s-%d\n",
+ cur_if->prefix, WLCBAND2STR(cur_chan_info.band), cur_chan_info.chan);
+ cur_if->chan_info.chan = 0;
} else {
- WL_MSG(cur_if->ifname, "[%c] channel=%d => %s[%c] channel=%d\n",
- cur_if->prefix, cur_if->channel,
- target_if->ifname, target_if->prefix, target_chan);
- cur_if->channel = target_chan;
+ WL_MSG(cur_if->ifname, "[%c] channel=%s-%d => %s[%c] channel=%s-%d\n",
+ cur_if->prefix,
+ WLCBAND2STR(cur_if->chan_info.band), cur_if->chan_info.chan,
+ target_if->ifname, target_if->prefix,
+ WLCBAND2STR(tgt_chan_info.band), tgt_chan_info.chan);
+ wl_ext_set_chan_info(cur_if, tgt_chan_info.band, tgt_chan_info.chan);
}
}
exit:
wl_ext_move_cur_dfs_channel(apsta_params, cur_if);
- return cur_if->channel;
+ return cur_if->chan_info.chan;
}
static struct wl_if_info *
wl_prio_t max_prio = 0, cur_prio;
int i;
- if (apsta_params->vsdb || !cur_if->channel) {
+ if (apsta_params->vsdb || !cur_if->chan_info.chan) {
return NULL;
}
}
if (target_if) {
- WL_MSG(target_if->ifname, "channel=%d => %s channel=%d\n",
- target_chan, cur_if->ifname, cur_if->channel);
- target_if->channel = cur_if->channel;
+ WL_MSG(target_if->ifname, "channel=%s-%d => %s channel=%s-%d\n",
+ WLCBAND2STR(target_if->chan_info.band), target_chan,
+ cur_if->ifname, WLCBAND2STR(cur_if->chan_info.band), cur_if->chan_info.chan);
+ wl_ext_set_chan_info(target_if, cur_if->chan_info.band, cur_if->chan_info.chan);
wl_ext_move_other_dfs_channel(apsta_params, target_if);
if (apsta_params->csa == 0) {
wl_ext_if_down(apsta_params, target_if);
for (i=0; i<MAX_IF_NUM; i++) {
tmp_if = &apsta_params->if_info[i];
if (tmp_if && wl_get_isam_status(tmp_if, IF_READY)) {
- if (wl_ext_get_chan(apsta_params, tmp_if->dev)) {
+ if (wl_ext_associated(tmp_if->dev)) {
enabled = TRUE;
break;
}
return connecting;
}
-#ifdef PROPTX_MAXCOUNT
-int
-wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx)
+bool
+wl_ext_sta_handshaking(struct net_device *dev)
{
- struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- struct wl_if_info *tmp_if, *cur_if = NULL;
- int i, maxcount = WL_TXSTATUS_FREERUNCTR_MASK;
-
+ struct wl_if_info *cur_if = NULL;
+ bool connecting = FALSE;
+ int state;
+
+ cur_if = wl_get_cur_if(dev);
+ if (!cur_if)
+ return FALSE;
+
+ if (cur_if->ifmode != ISTA_MODE && cur_if->ifmode != IGC_MODE)
+ return FALSE;
+
+ state = cur_if->conn_state;
+ if (state >= CONN_STATE_4WAY_M1 && state < CONN_STATE_CONNECTED) {
+ connecting = TRUE;
+ IAPSTA_TRACE(dev->name, "conn_state %d\n", state);
+ }
+
+ return connecting;
+}
+
+#ifdef DHD_LOSSLESS_ROAMING
+int
+wl_ext_any_sta_handshaking(struct dhd_pub *dhd)
+{
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *cur_if;
+ int state = 0, i;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[i];
+ if (cur_if->dev && cur_if->ifmode == ISTA_MODE) {
+ state = cur_if->conn_state;
+ if (state >= CONN_STATE_4WAY_M1 && state < CONN_STATE_CONNECTED) {
+ return state;
+ }
+ }
+ }
+ return 0;
+}
+#endif /* DHD_LOSSLESS_ROAMING */
+
+#ifdef PROPTX_MAXCOUNT
+int
+wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx)
+{
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *tmp_if, *cur_if = NULL;
+ int i, maxcount = WL_TXSTATUS_FREERUNCTR_MASK;
+
if (!apsta_params->rsdb)
return maxcount;
{
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct wl_if_info *tmp_if;
+ struct wl_chan_info chan_info;
bool band_5g = FALSE;
- uint16 chan = 0;
int i, ret;
if (!apsta_params->rsdb)
for (i=0; i<MAX_IF_NUM; i++) {
tmp_if = &apsta_params->if_info[i];
if (tmp_if->dev) {
- chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if (chan > CH_MAX_2G_CHANNEL) {
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(tmp_if->dev, &chan_info);
+ if (chan_info.band == WLC_BAND_5G || chan_info.band == WLC_BAND_6G) {
tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_5g;
ret = dhd_wlfc_update_maxcount(dhd, tmp_if->ifidx,
tmp_if->transit_maxcount);
for (i=0; i<MAX_IF_NUM; i++) {
tmp_if = &apsta_params->if_info[i];
if (tmp_if->dev) {
- chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if ((chan == 0) || (chan <= CH_MAX_2G_CHANNEL && chan >= CH_MIN_2G_CHANNEL)) {
- if (chan == 0) {
+ wl_ext_get_chan(tmp_if->dev, &chan_info);
+ if ((chan_info.chan == 0) || (chan_info.band == WLC_BAND_2G)) {
+ if (chan_info.chan == 0) {
tmp_if->transit_maxcount = WL_TXSTATUS_FREERUNCTR_MASK;
} else if (band_5g) {
tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_2g;
wl_ext_get_dfs_master_if(struct wl_apsta_params *apsta_params)
{
struct wl_if_info *cur_if = NULL;
- uint16 chan = 0;
+ struct wl_chan_info chan_info;
int i;
for (i=0; i<MAX_IF_NUM; i++) {
cur_if = &apsta_params->if_info[i];
if (!cur_if->dev || !wl_ext_master_if(cur_if))
continue;
- chan = wl_ext_get_chan(apsta_params, cur_if->dev);
- if (wl_ext_dfs_chan(chan)) {
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(cur_if->dev, &chan_info);
+ if (chan_info.chan && wl_ext_dfs_chan(&chan_info)) {
return cur_if;
}
}
uint16 post_channel)
{
struct wl_if_info *cur_if = NULL;
- uint16 chan = 0;
+ struct wl_chan_info chan_info;
int i;
if (apsta_params->vsdb)
cur_if = &apsta_params->if_info[i];
if (!cur_if->dev || !wl_ext_master_if(cur_if))
continue;
- chan = wl_ext_get_chan(apsta_params, cur_if->dev);
- if (chan) {
- cur_if->prev_channel = chan;
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(cur_if->dev, &chan_info);
+ if (chan_info.chan) {
+ cur_if->prev_channel = chan_info.chan;
cur_if->post_channel = post_channel;
}
}
}
+void
+wl_ext_iapsta_enable_master_if(struct net_device *dev, bool post)
+{
+ dhd_pub_t *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *cur_if = NULL;
+ int i;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[i];
+ if (cur_if && cur_if->post_channel) {
+ if (post)
+ cur_if->chan_info.chan = cur_if->post_channel;
+ else
+ cur_if->chan_info.chan = cur_if->prev_channel;
+ if (wl_ext_associated(cur_if->dev))
+ wl_ext_if_down(apsta_params, cur_if);
+ wl_ext_if_up(apsta_params, cur_if, TRUE, 0);
+ cur_if->prev_channel = 0;
+ cur_if->post_channel = 0;
+ }
+ }
+}
+
+void
+wl_ext_iapsta_restart_master(struct net_device *dev)
+{
+ dhd_pub_t *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *ap_if = NULL;
+
+ if (apsta_params->radar)
+ return;
+
+ ap_if = wl_ext_get_dfs_master_if(apsta_params);
+ if (ap_if) {
+ uint16 chan_2g, chan_5g;
+ wl_ext_if_down(apsta_params, ap_if);
+ wl_ext_iapsta_restart_master(dev);
+ wl_ext_get_default_chan(ap_if->dev, &chan_2g, &chan_5g, TRUE);
+ if (chan_5g)
+ wl_ext_set_chan_info(ap_if, WLC_BAND_5G, chan_5g);
+ else if (chan_2g)
+ wl_ext_set_chan_info(ap_if, WLC_BAND_2G, chan_2g);
+ else
+ ap_if->chan_info.chan = 0;
+ if (ap_if->chan_info.chan) {
+ wl_ext_move_cur_channel(apsta_params, ap_if);
+ wl_ext_if_up(apsta_params, ap_if, FALSE, 0);
+ }
+ }
+}
+
static void
wl_ext_if_reenabled(struct wl_apsta_params *apsta_params, ifmode_t ifmode, u32 channel)
{
tmp_if = &apsta_params->if_info[i];
if (tmp_if && tmp_if->ifmode == ifmode &&
wl_get_isam_status(tmp_if, IF_READY)) {
- if (wl_ext_get_chan(apsta_params, tmp_if->dev) == channel) {
+ if (wl_ext_get_chan(tmp_if->dev, &tmp_if->chan_info) == channel) {
WL_MSG(tmp_if->ifname, "re-enable channel %d\n", channel);
if (ifmode == IAP_MODE) {
wl_ext_if_down(apsta_params, tmp_if);
}
u32
-wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel)
+wl_ext_iapsta_update_channel(struct net_device *dev, u32 chanspec)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
cur_if = wl_get_cur_if(dev);
if (cur_if) {
+ struct wl_chan_info *chan_info = &cur_if->chan_info;
mutex_lock(&apsta_params->usr_sync);
wl_ext_isam_status(cur_if->dev, NULL, 0);
- cur_if->channel = channel;
+ wl_ext_set_chan_info(cur_if, CHSPEC2WLC_BAND(chanspec),
+ wf_chspec_ctlchan(chanspec));
if (wl_ext_master_if(cur_if) && apsta_params->acs) {
- uint auto_band = WL_GET_BAND(channel);
- cur_if->channel = wl_ext_autochannel(cur_if->dev, apsta_params->acs,
- auto_band);
- }
- channel = wl_ext_move_cur_channel(apsta_params, cur_if);
- if (channel) {
- if (cur_if->ifmode == ISTA_MODE && wl_ext_dfs_chan(channel))
- wl_ext_save_master_channel(apsta_params, channel);
+ chan_info->chan = wl_ext_autochannel(cur_if->dev, apsta_params->acs,
+ chan_info->band);
+ }
+ chan_info->chan = wl_ext_move_cur_channel(apsta_params, cur_if);
+ if (chan_info->chan) {
+ if (cur_if->ifmode == ISTA_MODE && wl_ext_dfs_chan(chan_info))
+ wl_ext_save_master_channel(apsta_params, chan_info->chan);
target_if = wl_ext_move_other_channel(apsta_params, cur_if);
if (dhd->conf->chip == BCM4359_CHIP_ID &&
cur_if->ifmode == ISTA_MODE && !target_if) {
* step2: enable wlan2 on channel 36
* step3: enable wlan0 to connect channel 1 AP, then it will fw trap
*/
- wl_ext_if_reenabled(apsta_params, IAP_MODE, channel);
+ wl_ext_if_reenabled(apsta_params, IAP_MODE, chan_info->chan);
}
}
if (cur_if->ifmode == ISTA_MODE) {
- if (conf->war & SET_CHAN_INCONN) {
+ if (conf->war & SET_CHAN_INCONN && chan_info->chan) {
chanspec_t fw_chspec;
- IAPSTA_INFO(dev->name, "set channel %d\n", channel);
- wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, channel,
- &fw_chspec);
+ IAPSTA_INFO(dev->name, "set channel %d\n", chan_info->chan);
+ wl_ext_set_chanspec(cur_if->dev, chan_info, &fw_chspec);
}
wl_set_isam_status(cur_if, STA_CONNECTING);
}
+ chanspec = wf_create_chspec_from_primary(chan_info->chan,
+ CHSPEC_BW(chanspec), wl_ext_wlcband_to_chanspec_band(chan_info->band));
mutex_unlock(&apsta_params->usr_sync);
}
- return channel;
+ return chanspec;
}
static int
cur_if->prio = PRIO_STA;
cur_if->vsdb = TRUE;
cur_if->prefix = 'S';
+#ifdef WL_STATIC_IF
+ dhd_conf_preinit_ioctls_sta(dhd, ifidx);
+#endif /* WL_STATIC_IF */
} else if (wl_iftype == WL_IF_TYPE_AP && cur_if->ifmode != IMESH_MODE) {
cur_if->ifmode = IAP_MODE;
cur_if->prio = PRIO_AP;
return FALSE;
}
-void
-wl_ext_iapsta_enable_master_if(struct net_device *dev, bool post)
-{
- dhd_pub_t *dhd = dhd_get_pub(dev);
- struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- struct wl_if_info *cur_if = NULL;
- int i;
-
- for (i=0; i<MAX_IF_NUM; i++) {
- cur_if = &apsta_params->if_info[i];
- if (cur_if && cur_if->post_channel) {
- if (post)
- cur_if->channel = cur_if->post_channel;
- else
- cur_if->channel = cur_if->prev_channel;
- wl_ext_if_up(apsta_params, cur_if, TRUE, 0);
- cur_if->prev_channel = 0;
- cur_if->post_channel = 0;
- }
- }
-}
-
-void
-wl_ext_iapsta_restart_master(struct net_device *dev)
-{
- dhd_pub_t *dhd = dhd_get_pub(dev);
- struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- struct wl_if_info *ap_if = NULL;
-
- if (apsta_params->radar)
- return;
-
- ap_if = wl_ext_get_dfs_master_if(apsta_params);
- if (ap_if) {
- uint16 chan_2g, chan_5g;
- wl_ext_if_down(apsta_params, ap_if);
- wl_ext_iapsta_restart_master(dev);
- wl_ext_get_default_chan(ap_if->dev, &chan_2g, &chan_5g, TRUE);
- if (chan_5g)
- ap_if->channel = chan_5g;
- else if (chan_2g)
- ap_if->channel = chan_2g;
- else
- ap_if->channel = 0;
- if (ap_if->channel) {
- wl_ext_move_cur_channel(apsta_params, ap_if);
- wl_ext_if_up(apsta_params, ap_if, FALSE, 0);
- }
- }
-}
-
bool
wl_ext_iapsta_mesh_creating(struct net_device *net)
{
return;
}
IAPSTA_ERROR(dev->name, "timer expired\n");
- wl_ext_send_event_msg(dev, WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS);
+ wl_ext_send_event_msg(dev, WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WLC_E_STATUS_SUCCESS);
+}
+
+#ifdef WL_EXT_DISCONNECT_RECONNECT
+static bool
+wl_ext_disc_recon_retry(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
+{
+ int sta_disc_recon_cnt = cur_if->sta_disc_recon_cnt;
+ struct osl_timespec *sta_disc_conn_ts = &cur_if->sta_disc_conn_ts;
+ struct osl_timespec cur_ts;
+ uint32 diff_ms = 0;
+ bool retry = FALSE;
+
+ if (sta_disc_recon_cnt == 0)
+ osl_do_gettimeofday(sta_disc_conn_ts);
+
+ osl_do_gettimeofday(&cur_ts);
+ diff_ms = osl_do_gettimediff(&cur_ts, sta_disc_conn_ts)/1000;
+
+ IAPSTA_INFO(cur_if->ifname, "sta_disc_recon_cnt=%d, diff_ms = %dms\n",
+ sta_disc_recon_cnt, diff_ms);
+ if (sta_disc_recon_cnt >= STA_DISCONNECT_RECONNECT_MAX) {
+ if (diff_ms >= STA_DISCONNECT_RECONNECT_TIMEOUT) {
+ osl_do_gettimeofday(sta_disc_conn_ts);
+ cur_if->sta_disc_recon_cnt = 0;
+ retry = TRUE;
+ } else {
+ retry = FALSE;
+ }
+ } else {
+ retry = TRUE;
+ }
+
+ if (retry)
+ cur_if->sta_disc_recon_cnt++;
+
+ return retry;
+}
+#endif /* WL_EXT_DISCONNECT_RECONNECT */
+
+static void
+wl_ext_update_assoc_info(struct net_device *dev, bool reassoc)
+{
+#ifndef WL_REASSOC_BCAST
+ dhd_pub_t *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_chan_info chan_info;
+#endif
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+ wlcfg_assoc_info_t *assoc_info;
+ struct wl_if_info *cur_if;
+
+ cur_if = wl_get_cur_if(dev);
+ if (cur_if) {
+ assoc_info = &cur_if->assoc_info;
+ assoc_info->reassoc = reassoc;
+ assoc_info->bssid_hint = false;
+#ifdef WL_REASSOC_BCAST
+ assoc_info->chan_cnt = 0;
+ assoc_info->chanspecs[0] = 0;
+ memcpy(&assoc_info->bssid, ðer_bcast, ETHER_ADDR_LEN);
+#else
+ assoc_info->chanspecs[0] = wl_ext_get_chanspec(dev, &chan_info);
+ if (assoc_info->chanspecs[0] && reassoc) {
+ assoc_info->chan_cnt = 1;
+ wldev_ioctl(dev, WLC_GET_BSSID, &cur_if->bssid, ETHER_ADDR_LEN, 0);
+ memcpy(&assoc_info->bssid, &cur_if->bssid, ETHER_ADDR_LEN);
+ } else {
+ assoc_info->chan_cnt = 0;
+ memcpy(&assoc_info->bssid, ðer_bcast, ETHER_ADDR_LEN);
+ }
+#endif /* WL_REASSOC_BCAST */
+ if (!ETHER_ISBCAST(assoc_info->bssid))
+ assoc_info->targeted_join = true;
+ else
+ assoc_info->targeted_join = false;
+ wl_get_assoc_channels(cfg, dev, assoc_info);
+ }
}
static int
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct wl_if_info *cur_if;
struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
- struct osl_timespec cur_ts, *sta_conn_ts = &apsta_params->sta_conn_ts;
+ struct osl_timespec cur_ts, *sta_conn_ts;
+ wlcfg_assoc_info_t *assoc_info;
uint32 diff_ms = 0;
int max_wait_time = 0, ret = 0;
- bool connecting = FALSE;
+ bool connecting, handshaking, associated;
+ uint32 etype = ntoh32(e->event_type);
+ uint32 status = ntoh32(e->status);
+
+ if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
+ WL_MSG(dev->name, "skip connect retry due to disconnecting\n");
+ return BCME_BADADDR;
+ }
cur_if = wl_get_cur_if(dev);
if (!cur_if)
return ret;
+ sta_conn_ts = &cur_if->sta_conn_ts;
+ connecting = wl_ext_sta_connecting(dev);
+ handshaking = wl_ext_sta_handshaking(dev);
mutex_unlock(&apsta_params->in4way_sync);
mutex_lock(&cfg->connect_sync);
- connecting = wl_ext_sta_connecting(dev);
osl_do_gettimeofday(&cur_ts);
diff_ms = osl_do_gettimediff(&cur_ts, sta_conn_ts)/1000;
+ associated = wl_ext_associated(dev);
+ assoc_info = &cur_if->assoc_info;
if (connecting && diff_ms < STA_CONNECT_TIMEOUT &&
!wl_get_drv_status(cfg, DISCONNECTING, dev)) {
- uint32 etype = ntoh32(e->event_type);
- uint32 status = ntoh32(e->status);
if (etype == WLC_E_SET_SSID && (status == WLC_E_STATUS_NO_NETWORKS ||
status == WLC_E_STATUS_NO_ACK)) {
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
- if (cur_if->assoc_info.reassoc) {
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, 0);
+ if (assoc_info->reassoc && associated && !handshaking) {
+ /* There are two cases will come in to retry reassoc:
+ * 1) reconnect from wpa_supplicant
+ * 2) fw roam
+ */
+ if (associated)
+ bzero(&cfg->last_roamed_addr, ETHER_ADDR_LEN);
WL_MSG(dev->name, "retry reassoc\n");
- wl_handle_reassoc(cfg, dev, &cur_if->assoc_info);
- max_wait_time = STA_RECONNECT_RETRY_TIMEOUT;
- } else {
- if (!wl_ext_get_chan(apsta_params, dev)) {
- WL_MSG(dev->name, "retry join\n");
- wl_cfg80211_disassoc(dev, WLAN_REASON_DEAUTH_LEAVING);
- wl_handle_join(cfg, dev, &cur_if->assoc_info);
- max_wait_time = STA_CONNECT_RETRY_TIMEOUT;
+ if (wl_handle_reassoc(cfg, dev, assoc_info))
+ goto exit;
+ if (assoc_info->chan_cnt == 0)
+ max_wait_time = STA_CONNECT_FULL_CHAN_TIMEOUT;
+ else
+ max_wait_time = STA_RECONNECT_RETRY_TIMEOUT +
+ (WL_BCAST_SCAN_JOIN_ACTIVE_DWELL_TIME_MS * assoc_info->chan_cnt);
+ max_wait_time = min(max_wait_time, STA_CONNECT_FULL_CHAN_TIMEOUT);
+ }
+ else {
+ /* There is one case will come in to retry join:
+ * 1) connect from wpa_supplicant
+ */
+ WL_MSG(dev->name, "retry join\n");
+ if (associated) {
+ bzero(&cfg->last_roamed_addr, ETHER_ADDR_LEN);
+ wl_cfg80211_disassoc(dev, WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
+ }
+ if (wl_handle_join(cfg, dev, assoc_info))
+ goto exit;
+ if (assoc_info->chan_cnt == 0)
+ max_wait_time = STA_CONNECT_FULL_CHAN_TIMEOUT;
+ else
+ max_wait_time = STA_CONNECT_RETRY_TIMEOUT +
+ (WL_BCAST_SCAN_JOIN_ACTIVE_DWELL_TIME_MS * assoc_info->chan_cnt);
+ max_wait_time = min(max_wait_time, STA_CONNECT_FULL_CHAN_TIMEOUT);
+ }
+ IAPSTA_INFO(dev->name, "reconnect %dms later\n", max_wait_time);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, max_wait_time);
+ }
+ ret = BCME_ERROR;
+ }
+#ifdef WL_EXT_DISCONNECT_RECONNECT
+ else if (cur_if->conn_state >= CONN_STATE_CONNECTED &&
+ !wl_get_drv_status(cfg, DISCONNECTING, dev) &&
+ wl_get_drv_status(cfg, CONNECTED, dev)) {
+ if (etype == WLC_E_DISASSOC_IND || etype == WLC_E_DEAUTH_IND) {
+ /* There is one case will come in to retry join:
+ * 1) receive disconnect from AP after connected
+ */
+ if (wl_ext_disc_recon_retry(apsta_params, cur_if)) {
+ int wpa_auth = 0;
+ WL_MSG(dev->name, "retry join cnt %d\n", cur_if->sta_disc_recon_cnt);
+ bzero(&cfg->last_roamed_addr, ETHER_ADDR_LEN);
+ wl_ext_update_assoc_info(dev, FALSE);
+#ifdef DHD_LOSSLESS_ROAMING
+ wl_ext_send_event_msg(dev, WLC_E_ROAM_PREP, WLC_E_STATUS_SUCCESS, WLC_E_REASON_DEAUTH);
+#endif
+ if (wl_handle_join(cfg, dev, assoc_info))
+ goto exit;
+ wl_timer_mod(dhd, &cur_if->connect_timer, STA_CONNECT_TIMEOUT);
+ osl_do_gettimeofday(sta_conn_ts);
+ wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTING);
+ wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
+ if (!(wpa_auth & (WPA3_AUTH_SAE_PSK|0x20))) {
+ if (assoc_info->chan_cnt == 0)
+ max_wait_time = STA_CONNECT_FULL_CHAN_TIMEOUT;
+ else
+ max_wait_time = STA_CONNECT_RETRY_TIMEOUT +
+ (WL_BCAST_SCAN_JOIN_ACTIVE_DWELL_TIME_MS * assoc_info->chan_cnt);
+ max_wait_time = min(max_wait_time, STA_CONNECT_FULL_CHAN_TIMEOUT);
+ IAPSTA_INFO(dev->name, "reconnect %dms later\n", max_wait_time);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, max_wait_time);
}
+ ret = BCME_ERROR;
+ }
+ else {
+ WL_MSG(dev->name, "out of retry cnt %d within %dms\n",
+ cur_if->sta_disc_recon_cnt, STA_DISCONNECT_RECONNECT_TIMEOUT);
}
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, max_wait_time);
}
- ret = -EAGAIN;
}
+#endif /* WL_EXT_DISCONNECT_RECONNECT */
+
+exit:
mutex_unlock(&cfg->connect_sync);
mutex_lock(&apsta_params->in4way_sync);
static void
wl_ext_set_connect_retry(struct net_device *dev, void *context)
{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
wlcfg_assoc_info_t *assoc_info = (wlcfg_assoc_info_t *)context;
struct wl_if_info *cur_if;
int max_wait_time;
if (!cur_if)
return;
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, 0);
memset(&cur_if->assoc_info, 0, sizeof(wlcfg_assoc_info_t));
wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
if (!(wpa_auth & (WPA3_AUTH_SAE_PSK|0x20) && assoc_info)) {
memcpy(&cur_if->bssid, assoc_info->bssid, ETHER_ADDR_LEN);
memcpy(&cur_if->assoc_info, assoc_info, sizeof(wlcfg_assoc_info_t));
- if (assoc_info->reassoc)
+ if (assoc_info->chan_cnt == 0)
+ max_wait_time = STA_CONNECT_FULL_CHAN_TIMEOUT;
+ else if (assoc_info->reassoc)
max_wait_time = STA_RECONNECT_RETRY_TIMEOUT;
else
max_wait_time = STA_CONNECT_RETRY_TIMEOUT;
IAPSTA_INFO(dev->name, "reconnect %dms later\n", max_wait_time);
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, max_wait_time);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, max_wait_time);
}
}
#endif /* WL_EXT_RECONNECT */
+
+#ifdef STA_MGMT
+static void
+wl_ext_flush_sta_list(struct net_device *net, int ifidx)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ wl_sta_info_t *node, *next;
+
+ list_for_each_entry_safe(node, next, &apsta_params->sta_list, list) {
+ if (node->ifidx == ifidx || ifidx == 0xFF) {
+ IAPSTA_INFO(net->name, "Del BSSID %pM\n", &node->bssid);
+ list_del(&node->list);
+ kfree(node);
+ }
+ }
+}
+
+bool
+wl_ext_del_sta_info(struct net_device *net, u8 *bssid)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ int ifidx = dhd_net2idx(dhd->info, net);
+ wl_sta_info_t *node, *next;
+ bool in_list = FALSE;
+
+ list_for_each_entry_safe(node, next, &apsta_params->sta_list, list) {
+ if (node->ifidx == ifidx && !memcmp(&node->bssid, bssid, ETHER_ADDR_LEN)) {
+ IAPSTA_INFO(net->name, "Del BSSID %pM\n", &node->bssid);
+ in_list = TRUE;
+ list_del(&node->list);
+ kfree(node);
+ }
+ }
+ return in_list;
+}
+
+bool
+wl_ext_add_sta_info(struct net_device *net, u8 *bssid)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ int ifidx = dhd_net2idx(dhd->info, net);
+ wl_sta_info_t *node, *next, *leaf;
+
+ list_for_each_entry_safe(node, next, &apsta_params->sta_list, list) {
+ if (node->ifidx == ifidx && !memcmp(&node->bssid, bssid, ETHER_ADDR_LEN)) {
+ IAPSTA_INFO(net->name, "BSSID %pM already in list\n", bssid);
+ return FALSE;
+ }
+ }
+
+ leaf = kmalloc(sizeof(wl_sta_info_t), GFP_KERNEL);
+ if (!leaf) {
+ IAPSTA_ERROR(net->name, "Memory alloc failure %d\n",
+ (int)sizeof(wl_sta_info_t));
+ return FALSE;
+ }
+ IAPSTA_INFO(net->name, "Add BSSID %pM in the leaf\n", bssid);
+ leaf->ifidx = ifidx;
+ memcpy(&leaf->bssid, bssid, ETHER_ADDR_LEN);
+ list_add_tail(&leaf->list, &apsta_params->sta_list);
+
+ return TRUE;
+}
+#endif /* STA_MGMT */
#endif /* WL_CFG80211 */
#ifndef WL_STATIC_IF
conn_state >= CONN_STATE_CONNECTED ||
conn_state <= CONN_STATE_CONNECTING)
apsta_params->if_info[ifidx].conn_state = conn_state;
- else
+ else
IAPSTA_INFO(cur_if->dev->name, "skip update %d\n", conn_state);
} else {
apsta_params->if_info[ifidx].conn_state = conn_state;
#ifdef BCMDBUS
if (!rx)
#endif /* BCMDBUS */
- wl_ext_mod_timer(&cur_if->eapol_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->eapol_timer, 0);
if (cur_if->pend_eapol_pkt) {
PKTCFREE(dhd->osh, cur_if->pend_eapol_pkt, TRUE);
#else
interval = STA_EAPOL_TIMEOUT;
#endif /* EAPOL_DYNAMATIC_RESEND */
- wl_ext_mod_timer(&cur_if->eapol_timer, 0, interval);
+ wl_timer_mod(dhd, &cur_if->eapol_timer, interval);
IAPSTA_TRACE(cur_if->dev->name, "backup eapol pkt\n");
}
spin_unlock_irqrestore(&apsta_params->eapol_lock, flags);
cur_if->eapol_max_intvl, STA_EAPOL_TIMEOUT,
cur_if->eapol_cnt);
#else
- IAPSTA_INFO(dev->name, "resend eapol pkt %d\n", STA_EAPOL_TIMEOUT);
+ IAPSTA_INFO(dev->name, "resend eapol pkt %dms\n", STA_EAPOL_TIMEOUT);
#endif /* EAPOL_DYNAMATIC_RESEND */
pending = TRUE;
}
bzero(&msg, sizeof(wl_event_msg_t));
IAPSTA_TRACE(dev->name, "timer expired\n");
- msg.ifidx = hton32(dhd_net2idx(dhd->info, dev));
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
msg.event_type = hton32(WLC_E_RESERVED);
msg.reason = hton32(ISAM_RC_EAPOL_RESEND);
wl_ext_event_send(dhd->event_params, &msg, NULL);
}
#endif /* EAPOL_RESEND */
-#if defined(WL_CFG80211) && defined(SCAN_SUPPRESS)
+#ifdef KEY_INSTALL_CHECK
static void
-wl_ext_light_scan_prep(struct net_device *dev, void *scan_params, bool scan_v2)
+wl_ext_key_install_timeout(unsigned long data)
{
- wl_scan_params_t *params = NULL;
- wl_scan_params_v2_t *params_v2 = NULL;
+ struct net_device *dev = (struct net_device *)data;
+ struct dhd_pub *dhd;
+ wl_event_msg_t msg;
- if (!scan_params) {
- IAPSTA_ERROR(dev->name, "NULL scan_params\n");
+ if (!dev) {
+ IAPSTA_ERROR("wlan", "dev is not ready\n");
return;
}
- IAPSTA_INFO(dev->name, "Enter\n");
- if (scan_v2) {
- params_v2 = (wl_scan_params_v2_t *)scan_params;
- } else {
- params = (wl_scan_params_t *)scan_params;
- }
+ dhd = dhd_get_pub(dev);
- if (params_v2) {
- /* scan params ver2 */
- params_v2->nprobes = 1;
- params_v2->active_time = 20;
- params_v2->home_time = 150;
- } else {
- /* scan params ver 1 */
- if (!params) {
- ASSERT(0);
- return;
- }
- params->nprobes = 1;
- params->active_time = 20;
- params->home_time = 150;
+ bzero(&msg, sizeof(wl_event_msg_t));
+ IAPSTA_TRACE(dev->name, "timer expired\n");
+
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
+ msg.event_type = hton32(WLC_E_RESERVED);
+ msg.reason = hton32(ISAM_RC_KEY_INSTALL);
+ wl_ext_event_send(dhd->event_params, &msg, NULL);
+}
+
+static void
+wl_ext_key_install_handler(struct wl_if_info *cur_if,
+ const wl_event_msg_t *e, void *data)
+{
+ struct net_device *dev = cur_if->dev;
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+ uint32 etype = ntoh32(e->event_type);
+ uint32 reason = ntoh32(e->reason);
+ int err, key_installed = 0;
+
+ if (etype == WLC_E_RESERVED && reason == ISAM_RC_KEY_INSTALL) {
+ if (cur_if->conn_state >= CONN_STATE_4WAY_M4 &&
+ !wl_get_drv_status(cfg, DISCONNECTING, dev) &&
+ wl_get_drv_status(cfg, CONNECTED, dev)) {
+ err = wldev_iovar_getint(dev, "buf_key_b4_m4_installed", &key_installed);
+ if (!err && !key_installed) {
+ cur_if->key_install_cnt++;
+ if (cur_if->key_install_cnt > STA_KEY_INSTALL_MAX) {
+ IAPSTA_ERROR(dev->name, "key not installed, send disconnect\n");
+#ifdef EAPOL_RESEND
+ wl_ext_release_eapol_txpkt(dhd, cur_if->ifidx, FALSE);
+#endif /* EAPOL_RESEND */
+ wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTED);
+ wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
+ wl_timer_mod(dhd, &cur_if->key_install_timer, 0);
+ cur_if->key_install_cnt = 0;
+ } else {
+ IAPSTA_INFO(dev->name, "check key installed %dms later, cnt=%d\n",
+ STA_KEY_INSTALL_INTERVAL, cur_if->key_install_cnt);
+ wl_timer_mod(dhd, &cur_if->key_install_timer, STA_KEY_INSTALL_INTERVAL);
+ }
+ } else {
+#ifdef EAPOL_RESEND
+ wl_ext_release_eapol_txpkt(dhd, cur_if->ifidx, FALSE);
+#endif /* EAPOL_RESEND */
+ IAPSTA_INFO(dev->name, "key installed\n");
+ wl_timer_mod(dhd, &cur_if->connect_timer, 0);
+ wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTED);
+ cur_if->key_install_cnt = 0;
+ }
+ }
+ }
+ return;
+}
+
+static int
+wl_key_installed(struct wl_if_info *cur_if)
+{
+ struct net_device *dev = cur_if->dev;
+ dhd_pub_t *dhd = dhd_get_pub(dev);
+ int err, key_installed = 0;
+
+ err = wldev_iovar_getint(dev, "buf_key_b4_m4_installed", &key_installed);
+ if (err) {
+ IAPSTA_INFO(dev->name, "not supported %d\n", err);
+ key_installed = 1;
+ } else if (key_installed)
+ IAPSTA_INFO(dev->name, "key installed\n");
+
+ if (key_installed)
+ wl_timer_mod(dhd, &cur_if->key_install_timer, 0);
+ else {
+ IAPSTA_INFO(dev->name, "check key installed %dms later\n", STA_KEY_INSTALL_INTERVAL);
+ wl_timer_mod(dhd, &cur_if->key_install_timer, STA_KEY_INSTALL_INTERVAL);
+ }
+
+ return key_installed;
+}
+#endif /* KEY_INSTALL_CHECK */
+
+#if defined(WL_CFG80211) && defined(SCAN_SUPPRESS)
+static void
+wl_ext_light_scan_prep(struct net_device *dev, void *scan_params, bool scan_v2)
+{
+ wl_scan_params_v1_t *params = NULL;
+ wl_scan_params_v2_t *params_v2 = NULL;
+
+ if (!scan_params) {
+ IAPSTA_ERROR(dev->name, "NULL scan_params\n");
+ return;
+ }
+ IAPSTA_INFO(dev->name, "Enter\n");
+
+ if (scan_v2) {
+ params_v2 = (wl_scan_params_v2_t *)scan_params;
+ } else {
+ params = (wl_scan_params_v1_t *)scan_params;
+ }
+
+ if (params_v2) {
+ /* scan params ver2 */
+ params_v2->nprobes = 1;
+ params_v2->active_time = 20;
+ params_v2->home_time = 150;
+ } else {
+ /* scan params ver 1 */
+ if (!params) {
+ ASSERT(0);
+ return;
+ }
+ params->nprobes = 1;
+ params->active_time = 20;
+ params->home_time = 150;
}
return;
}
static uint16
-wl_ext_max_tput_chan(struct wl_apsta_params *apsta_params)
+wl_ext_max_tput_chan(struct wl_apsta_params *apsta_params,
+ struct wl_chan_info *chan_info)
{
struct wl_if_info *tmp_if, *max_tput_if = NULL;
- uint16 chan = 0, max_tput_chan = 0;
int32 tput_sum = 0;
int i;
for (i=0; i<MAX_IF_NUM; i++) {
tmp_if = &apsta_params->if_info[i];
- if (tmp_if->dev && (tmp_if->tput_tx + tmp_if->tput_rx) > tput_sum) {
- chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if (chan) {
+ if (tmp_if->dev && (tmp_if->tput_info.tput_tx + tmp_if->tput_info.tput_rx) > tput_sum) {
+ memset(chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(tmp_if->dev, chan_info);
+ if (chan_info->chan) {
max_tput_if = tmp_if;
- tput_sum = tmp_if->tput_tx + tmp_if->tput_rx;
- max_tput_chan = chan;
+ tput_sum = tmp_if->tput_info.tput_tx + tmp_if->tput_info.tput_rx;
break;
}
}
}
- if (max_tput_chan)
- IAPSTA_INFO(max_tput_if->dev->name, "chan=%d\n", max_tput_chan);
+ if (max_tput_if)
+ IAPSTA_INFO(max_tput_if->dev->name, "chan=%s-%d\n",
+ WLCBAND2STR(chan_info->band), chan_info->chan);
- return max_tput_chan;
+ return chan_info->chan;
}
uint16
-wl_ext_scan_suppress(struct net_device *dev, void *scan_params, bool scan_v2)
+wl_ext_scan_suppress(struct net_device *dev, void *scan_params, bool scan_v2,
+ struct wl_chan_info *chan_info)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct dhd_conf *conf = dhd->conf;
- uint16 chan = 0;
if (!(conf->scan_intput & (SCAN_CURCHAN_INTPUT|SCAN_LIGHT_INTPUT)))
return 0;
+ memset(chan_info, 0, sizeof(struct wl_chan_info));
if (apsta_params->tput_sum >= conf->scan_tput_thresh) {
IAPSTA_INFO(dev->name, "tput %dMbps >= %dMbps (busy cnt/thresh %d/%d)\n",
apsta_params->tput_sum, conf->scan_tput_thresh,
if (apsta_params->scan_busy_cnt >= conf->scan_busy_thresh) {
apsta_params->scan_busy_cnt = 0;
} else if (conf->scan_intput & SCAN_CURCHAN_INTPUT) {
- chan = wl_ext_max_tput_chan(apsta_params);
+ wl_ext_max_tput_chan(apsta_params, chan_info);
}
- if ((conf->scan_intput & SCAN_LIGHT_INTPUT) && !chan)
+ if ((conf->scan_intput & SCAN_LIGHT_INTPUT) && !chan_info->chan)
wl_ext_light_scan_prep(dev, scan_params, scan_v2);
apsta_params->scan_busy_cnt++;
}
apsta_params->scan_busy_cnt = 0;
}
- return chan;
+ return chan_info->chan;
}
static int
}
}
}
-
}
static void
enum wl_ext_status status)
{
struct net_device *dev = cur_if->dev;
- struct osl_timespec cur_ts, *sta_disc_ts = &apsta_params->sta_disc_ts;
+ struct osl_timespec cur_ts, *sta_disc_ts = &cur_if->sta_disc_ts;
int max_wait_time = 200, max_wait_cnt = 20;
int cur_conn_state = cur_if->conn_state;
uint32 diff_ms = 0;
if (suspend) {
if (insuspend & AP_DOWN_IN_SUSPEND) {
- cur_if->channel = wl_ext_get_chan(apsta_params, cur_if->dev);
- if (cur_if->channel)
+ cur_if->chan_info.chan = wl_ext_get_chan(cur_if->dev, &cur_if->chan_info);
+ if (cur_if->chan_info.chan)
wl_ext_if_down(apsta_params, cur_if);
}
} else {
if (insuspend & AP_DOWN_IN_SUSPEND) {
- if (cur_if->channel)
+ if (cur_if->chan_info.chan)
wl_ext_if_up(apsta_params, cur_if, FALSE, 0);
}
}
#ifdef TPUT_MONITOR
if (suspend)
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, 0);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, 0);
#endif /* TPUT_MONITOR */
for (i=0; i<MAX_IF_NUM; i++) {
#ifdef TPUT_MONITOR
if (!suspend)
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, dhd->conf->tput_monitor_ms);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, dhd->conf->tput_monitor_ms);
#endif /* TPUT_MONITOR */
return 0;
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct dhd_conf *conf = dhd->conf;
struct net_device *dev = cur_if->dev;
- struct osl_timespec cur_ts, *sta_disc_ts = &apsta_params->sta_disc_ts;
- struct osl_timespec *sta_conn_ts = &apsta_params->sta_conn_ts;
+ struct osl_timespec cur_ts, *sta_disc_ts = &cur_if->sta_disc_ts;
+ struct osl_timespec *sta_conn_ts = &cur_if->sta_conn_ts;
uint32 diff_ms = 0;
- int ret = 0, cur_conn_state;
- int suppressed = 0, wpa_auth = 0;
+ int ret = 0, suppressed = 0, wpa_auth = 0, max_wait_time = 0, key_installed = 1;
+ uint cur_conn_state, conn_state;
bool connecting = FALSE;
wl_event_msg_t *e = (wl_event_msg_t *)context;
#ifdef WL_CFG80211
osl_do_gettimeofday(&cur_ts);
diff_ms = osl_do_gettimediff(&cur_ts, sta_conn_ts)/1000;
if (connecting && diff_ms <= STA_CONNECT_TIMEOUT) {
- IAPSTA_ERROR(dev->name, "connecting... %d\n", cur_conn_state);
+ IAPSTA_ERROR(dev->name, "scan during connecting... %d\n",
+ cur_conn_state);
ret = -EBUSY;
break;
}
if (wl_get_drv_status(cfg, CONNECTING, dev) ||
(connecting && diff_ms <= STA_CONNECT_TIMEOUT) ||
(cur_if->empty_scan >= STA_EMPTY_SCAN_MAX)) {
- unsigned long flags = 0;
cur_if->empty_scan = 0;
- spin_lock_irqsave(&dhd->up_lock, flags);
- if (dhd->up) {
- wl_event_msg_t msg;
- bzero(&msg, sizeof(wl_event_msg_t));
- msg.event_type = hton32(WLC_E_ESCAN_RESULT);
- msg.status = hton32(WLC_E_STATUS_SUCCESS);
- WL_MSG(dev->name, "FAKE SCAN\n");
- wl_cfg80211_event(dev, &msg, NULL);
- ret = -EBUSY;
- }
- spin_unlock_irqrestore(&dhd->up_lock, flags);
+ WL_MSG(dev->name, "FAKE SCAN\n");
+ ret = -EBUSY;
}
}
break;
case WL_EXT_STATUS_SCAN_COMPLETE:
- if ((conf->war & FW_REINIT_EMPTY_SCAN) && cfg->bss_list->count == 0) {
- uint16 channel;
+ if ((conf->war & FW_REINIT_EMPTY_SCAN) &&
+ cfg->bss_list->count == 0 && !p2p_scan(cfg)) {
+ bool assoc;
osl_do_gettimeofday(&cur_ts);
diff_ms = osl_do_gettimediff(&cur_ts, sta_disc_ts)/1000;
- channel = wl_ext_get_chan(apsta_params, dev);
+ assoc = wl_ext_associated(dev);
cur_if->empty_scan++;
- if ((channel && cur_if->empty_scan >= STA_EMPTY_SCAN_MAX) ||
+ if ((assoc && cur_if->empty_scan >= STA_EMPTY_SCAN_MAX) ||
(diff_ms < STA_LINKDOWN_TIMEOUT &&
apsta_params->linkdown_reason == WLC_E_LINK_BCN_LOSS)) {
if (conf->chip == BCM43569_CHIP_ID) {
- if (channel) {
+ if (assoc) {
IAPSTA_INFO(dev->name, "wl disassoc for empty scan\n");
wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
}
}
break;
#endif /* WL_CFG80211 */
- case WL_EXT_STATUS_DISCONNECTING:
+ case WL_EXT_STATUS_PRE_DISCONNECTING:
#ifdef EAPOL_RESEND
wl_ext_release_eapol_txpkt(dhd, cur_if->ifidx, FALSE);
#endif /* EAPOL_RESEND */
- wl_ext_mod_timer(&cur_if->connect_timer, 0, 0);
+#ifdef KEY_INSTALL_CHECK
+ wl_timer_mod(dhd, &cur_if->key_install_timer, 0);
+#endif /* KEY_INSTALL_CHECK */
+ wl_timer_mod(dhd, &cur_if->connect_timer, 0);
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, 0);
memset(&cur_if->assoc_info, 0, sizeof(wlcfg_assoc_info_t));
+#ifdef WL_EXT_DISCONNECT_RECONNECT
+ cur_if->sta_disc_recon_cnt = 0;
+#endif /* WL_EXT_DISCONNECT_RECONNECT */
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
#ifdef SCAN_SUPPRESS
apsta_params->scan_busy_cnt = 0;
#endif /* SCAN_SUPPRESS */
+ break;
+ case WL_EXT_STATUS_DISCONNECTING:
if (connecting) {
IAPSTA_ERROR(dev->name, "connect failed at %d\n", cur_conn_state);
wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_IDLE);
if (action & STA_NO_BTC_IN4WAY) {
wl_set_btc_in4way(apsta_params, cur_if, status, FALSE);
}
+#ifdef BTC_WAR
+ wl_ext_btc_config(cur_if->dev, FALSE);
+#endif /* BTC_WAR */
if (action & STA_WAIT_DISCONNECTED) {
wl_wait_disconnect(apsta_params, cur_if, status);
wake_up_interruptible(&conf->event_complete);
if (action & STA_REASSOC_RETRY) {
wl_ext_set_connect_retry(dev, context);
}
+#ifdef WL_EXT_DISCONNECT_RECONNECT
+ cur_if->sta_disc_recon_cnt = 0;
+#endif /* WL_EXT_DISCONNECT_RECONNECT */
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
- wl_ext_mod_timer(&cur_if->connect_timer, 0, STA_CONNECT_TIMEOUT);
+ wl_timer_mod(dhd, &cur_if->connect_timer, STA_CONNECT_TIMEOUT);
osl_do_gettimeofday(sta_conn_ts);
wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTING);
if (action & STA_NO_BTC_IN4WAY) {
case WL_EXT_STATUS_CONNECTED:
wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
if ((wpa_auth < WPA_AUTH_UNSPECIFIED) || (wpa_auth & WPA2_AUTH_FT)) {
- wl_ext_mod_timer(&cur_if->connect_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->connect_timer, 0);
wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTED);
+#ifdef BTC_WAR
+ wl_ext_btc_config(cur_if->dev, TRUE);
+#endif /* BTC_WAR */
+ max_wait_time = 0;
+ } else {
+ max_wait_time = STA_4WAY_TIMEOUT;
}
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
- memset(&cur_if->assoc_info, 0, sizeof(wlcfg_assoc_info_t));
+ wl_ext_update_assoc_info(dev, TRUE);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, max_wait_time);
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
if (cur_if->ifmode == ISTA_MODE) {
dhd_conf_set_wme(dhd, cur_if->ifidx, 0);
dhd_conf_set_mchan_bw(dhd, WL_P2P_IF_CLIENT, -1);
}
break;
+ case WL_EXT_STATUS_ROAMED:
+ wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
+ if ((wpa_auth >= WPA_AUTH_UNSPECIFIED) && !(wpa_auth & WPA2_AUTH_FT)) {
+ wl_timer_mod(dhd, &cur_if->connect_timer, STA_CONNECT_TIMEOUT);
+ osl_do_gettimeofday(sta_conn_ts);
+ wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTING);
+#ifdef BTC_WAR
+ wl_ext_btc_config(cur_if->dev, TRUE);
+#endif /* BTC_WAR */
+ max_wait_time = STA_4WAY_TIMEOUT;
+ } else {
+ max_wait_time = 0;
+ }
+#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
+ wl_ext_update_assoc_info(dev, TRUE);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, max_wait_time);
+#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
+#ifdef KEY_INSTALL_CHECK
+ wl_timer_mod(dhd, &cur_if->key_install_timer, 0);
+#endif /* KEY_INSTALL_CHECK */
+ if (cur_if->ifmode == ISTA_MODE) {
+ dhd_conf_set_wme(dhd, cur_if->ifidx, 0);
+ wake_up_interruptible(&conf->event_complete);
+ }
+ break;
case WL_EXT_STATUS_RECONNECT:
#ifdef EAPOL_RESEND
wl_ext_release_eapol_txpkt(dhd, cur_if->ifidx, FALSE);
#ifdef EAPOL_RESEND
wl_ext_release_eapol_txpkt(dhd, cur_if->ifidx, FALSE);
#endif /* EAPOL_RESEND */
+#ifdef KEY_INSTALL_CHECK
+ wl_timer_mod(dhd, &cur_if->key_install_timer, 0);
+#endif /* KEY_INSTALL_CHECK */
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, 0);
memset(&cur_if->assoc_info, 0, sizeof(wlcfg_assoc_info_t));
+#ifdef WL_EXT_DISCONNECT_RECONNECT
+ cur_if->sta_disc_recon_cnt = 0;
+#endif /* WL_EXT_DISCONNECT_RECONNECT */
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
#ifdef SCAN_SUPPRESS
apsta_params->scan_busy_cnt = 0;
!(ntoh16(e->flags) & WLC_EVENT_MSG_LINK)) {
apsta_params->linkdown_reason = ntoh32(e->reason);
}
- wl_ext_mod_timer(&cur_if->connect_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->connect_timer, 0);
if (connecting) {
IAPSTA_ERROR(dev->name, "connect failed at %d\n", cur_conn_state);
}
if (action & STA_NO_BTC_IN4WAY) {
wl_set_btc_in4way(apsta_params, cur_if, status, FALSE);
}
+#ifdef BTC_WAR
+ wl_ext_btc_config(cur_if->dev, FALSE);
+#endif /* BTC_WAR */
osl_do_gettimeofday(sta_disc_ts);
wake_up_interruptible(&conf->event_complete);
break;
case WL_EXT_STATUS_ADD_KEY:
- wl_ext_mod_timer(&cur_if->connect_timer, 0, 0);
- wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTED);
-#ifdef EAPOL_RESEND
- wl_ext_release_eapol_txpkt(dhd, cur_if->ifidx, FALSE);
-#endif /* EAPOL_RESEND */
+ conn_state = CONN_STATE_ADD_KEY;
+ wl_timer_mod(dhd, &cur_if->connect_timer, 0);
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->reconnect_timer, 0);
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
+#ifdef KEY_INSTALL_CHECK
+ key_installed = wl_key_installed(cur_if);
+#endif /* KEY_INSTALL_CHECK */
+ if (key_installed)
+ conn_state = CONN_STATE_CONNECTED;
+ wl_ext_update_conn_state(dhd, cur_if->ifidx, conn_state);
+ IAPSTA_INFO(dev->name, "WPA 4-WAY complete %d => %d\n",
+ cur_conn_state, conn_state);
+#ifdef EAPOL_RESEND
+ if (key_installed)
+ wl_ext_release_eapol_txpkt(dhd, cur_if->ifidx, FALSE);
+#endif /* EAPOL_RESEND */
if (action & STA_NO_BTC_IN4WAY) {
wl_set_btc_in4way(apsta_params, cur_if, status, FALSE);
}
+#ifdef BTC_WAR
+ wl_ext_btc_config(cur_if->dev, TRUE);
+#endif /* BTC_WAR */
wake_up_interruptible(&conf->event_complete);
- IAPSTA_INFO(dev->name, "WPA 4-WAY complete %d\n", cur_conn_state);
break;
default:
IAPSTA_INFO(dev->name, "Unknown action=0x%x, status=%d\n", action, status);
{
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
struct net_device *dev = cur_if->dev;
- struct osl_timespec cur_ts, *ap_disc_sta_ts = &apsta_params->ap_disc_sta_ts;
- u8 *ap_disc_sta_bssid = (u8*)&apsta_params->ap_disc_sta_bssid;
+ struct osl_timespec cur_ts, *ap_disc_sta_ts = &cur_if->ap_disc_sta_ts;
+ u8 *ap_disc_sta_bssid = (u8*)&cur_if->ap_disc_sta_bssid;
uint32 diff_ms = 0, timeout, max_wait_time = 300;
int ret = 0, suppressed = 0;
u8* mac_addr = context;
break;
}
break;
+ case WL_EXT_STATUS_AP_ENABLING:
+#ifdef RESTART_AP_WAR
+ wl_timer_mod(dhd, &cur_if->restart_ap_timer, AP_RESTART_TIMEOUT);
+#endif /* RESTART_AP_WAR */
+ break;
case WL_EXT_STATUS_AP_ENABLED:
+#ifdef RESTART_AP_WAR
+ wl_timer_mod(dhd, &cur_if->restart_ap_timer, 0);
+#endif /* RESTART_AP_WAR */
if (cur_if->ifmode == IAP_MODE)
dhd_conf_set_wme(dhd, cur_if->ifidx, 1);
else if (cur_if->ifmode == IGO_MODE)
dhd_conf_set_mchan_bw(dhd, WL_P2P_IF_GO, -1);
break;
+ case WL_EXT_STATUS_AP_DISABLING:
+#ifdef RESTART_AP_WAR
+ wl_timer_mod(dhd, &cur_if->restart_ap_timer, 0);
+#endif /* RESTART_AP_WAR */
+ break;
case WL_EXT_STATUS_DELETE_STA:
if (action & AP_WAIT_STA_RECONNECT) {
osl_do_gettimeofday(&cur_ts);
}
if (wait) {
IAPSTA_INFO(dev->name, "status=%d, ap_recon_sta=%d, waiting %dms ...\n",
- status, apsta_params->ap_recon_sta, max_wait_time);
+ status, cur_if->ap_recon_sta, max_wait_time);
mutex_unlock(&apsta_params->in4way_sync);
- timeout = wait_event_interruptible_timeout(apsta_params->ap_recon_sta_event,
- apsta_params->ap_recon_sta, msecs_to_jiffies(max_wait_time));
+ timeout = wait_event_interruptible_timeout(cur_if->ap_recon_sta_event,
+ cur_if->ap_recon_sta, msecs_to_jiffies(max_wait_time));
mutex_lock(&apsta_params->in4way_sync);
IAPSTA_INFO(dev->name, "status=%d, ap_recon_sta=%d, timeout=%d\n",
- status, apsta_params->ap_recon_sta, timeout);
+ status, cur_if->ap_recon_sta, timeout);
if (timeout > 0) {
IAPSTA_INFO(dev->name, "skip delete STA %pM\n", mac_addr);
ret = -1;
}
} else {
IAPSTA_INFO(dev->name, "status=%d, ap_recon_sta=%d => 0\n",
- status, apsta_params->ap_recon_sta);
- apsta_params->ap_recon_sta = FALSE;
+ status, cur_if->ap_recon_sta);
+ cur_if->ap_recon_sta = FALSE;
if (cur_if->ifmode == IGO_MODE)
wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_IDLE);
}
case WL_EXT_STATUS_STA_DISCONNECTED:
if (action & AP_WAIT_STA_RECONNECT) {
IAPSTA_INFO(dev->name, "latest disc STA %pM ap_recon_sta=%d\n",
- ap_disc_sta_bssid, apsta_params->ap_recon_sta);
+ ap_disc_sta_bssid, cur_if->ap_recon_sta);
osl_do_gettimeofday(ap_disc_sta_ts);
memcpy(ap_disc_sta_bssid, mac_addr, ETHER_ADDR_LEN);
- apsta_params->ap_recon_sta = FALSE;
+ cur_if->ap_recon_sta = FALSE;
}
break;
case WL_EXT_STATUS_STA_CONNECTED:
if (diff_ms < max_wait_time &&
!memcmp(ap_disc_sta_bssid, mac_addr, ETHER_ADDR_LEN)) {
IAPSTA_INFO(dev->name, "status=%d, ap_recon_sta=%d => 1\n",
- status, apsta_params->ap_recon_sta);
- apsta_params->ap_recon_sta = TRUE;
- wake_up_interruptible(&apsta_params->ap_recon_sta_event);
+ status, cur_if->ap_recon_sta);
+ cur_if->ap_recon_sta = TRUE;
+ wake_up_interruptible(&cur_if->ap_recon_sta_event);
} else {
- apsta_params->ap_recon_sta = FALSE;
+ cur_if->ap_recon_sta = FALSE;
}
}
break;
#endif /* WL_WIRELESS_EXT */
#ifdef TPUT_MONITOR
+static void
+wl_tput_monitor_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct dhd_pub *dhd;
+ wl_event_msg_t msg;
+
+ if (!dev) {
+ IAPSTA_ERROR("wlan", "dev is not ready\n");
+ return;
+ }
+
+ dhd = dhd_get_pub(dev);
+
+ bzero(&msg, sizeof(wl_event_msg_t));
+ IAPSTA_TRACE(dev->name, "timer expired\n");
+
+ msg.ifidx = 0;
+ msg.event_type = hton32(WLC_E_RESERVED);
+ msg.reason = hton32(ISAM_RC_TPUT_MONITOR);
+ wl_ext_event_send(dhd->event_params, &msg, NULL);
+}
+
static int
wl_ext_assoclist_num(struct net_device *dev)
{
return maxassoc;
}
+static int
+dev_wlc_ioctl(struct net_device *dev, int cmd, void *arg, int len)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ dhd_ioctl_t ioc;
+ int8 index;
+ int ret;
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+
+ index = dhd_net2idx(dhd->info, dev);
+ if (index == DHD_BAD_IF) {
+ IAPSTA_ERROR(dev->name, "Bad ifidx from dev\n");
+ return -ENODEV;
+ }
+ ret = dhd_ioctl_process(dhd, index, &ioc, arg);
+
+ return ret;
+}
+
static void
-wl_tput_monitor_timer(unsigned long data)
+wl_ampdu_dump(struct net_device *dev)
{
- struct net_device *dev = (struct net_device *)data;
- struct dhd_pub *dhd;
- wl_event_msg_t msg;
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ char *ioctl_buf = apsta_params->ioctl_buf, *buf = NULL;
+ char *tx_pch_start, *tx_pch_end, *rx_pch_start, *rx_pch_end;
+ int ret = 0, max_len, tx_len, rx_len;
- if (!dev) {
- IAPSTA_ERROR("wlan", "dev is not ready\n");
+ if (!(android_msg_level & ANDROID_AMPDU_LEVEL))
+ return;
+
+ if (!ioctl_buf)
return;
+
+ memset(ioctl_buf, 0, WL_DUMP_BUF_LEN);
+ ret = bcm_mkiovar("dump", "ampdu", strlen("ampdu"), ioctl_buf, WL_DUMP_BUF_LEN);
+ if (ret == 0) {
+ goto exit;
+ }
+ ret = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctl_buf, WL_DUMP_BUF_LEN);
+ if (ret) {
+ goto exit;
}
- dhd = dhd_get_pub(dev);
+ buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (buf == NULL) {
+ IAPSTA_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_MEDLEN);
+ goto exit;
+ }
+ memset(buf, 0, WLC_IOCTL_MEDLEN);
+ ret = bcm_mkiovar("dump_clear", "ampdu", strlen("ampdu"), buf, WLC_IOCTL_MEDLEN);
+ if (ret == 0) {
+ goto exit;
+ }
+ ret = dev_wlc_ioctl(dev, WLC_SET_VAR, (void *)buf, WLC_IOCTL_MEDLEN);
+ if (ret) {
+ goto exit;
+ }
- bzero(&msg, sizeof(wl_event_msg_t));
- IAPSTA_TRACE(dev->name, "timer expired\n");
+ tx_pch_start = strstr(ioctl_buf, "TX MCS");
+ tx_pch_end = strstr(ioctl_buf, "HEMU");
+ rx_pch_start = strstr(ioctl_buf, "RX MCS");
+ rx_pch_end = strstr(ioctl_buf, "RX MCS SGI");
+ max_len = (tx_pch_end-tx_pch_start) + (rx_pch_end-rx_pch_start);
+ if (max_len > (WLC_IOCTL_MEDLEN-1))
+ goto exit;
- msg.ifidx = 0;
- msg.event_type = hton32(WLC_E_RESERVED);
- msg.reason = hton32(ISAM_RC_TPUT_MONITOR);
- wl_ext_event_send(dhd->event_params, &msg, NULL);
+ tx_len = tx_pch_end - tx_pch_start;
+ rx_len = rx_pch_end - rx_pch_start;
+
+ memset(buf, 0, WLC_IOCTL_MEDLEN);
+ memcpy(buf, tx_pch_start, tx_len);
+ memcpy(buf+tx_len, rx_pch_start, rx_len);
+ WL_MSG(dev->name,"\n%s\n", buf);
+
+exit:
+ if (buf)
+ kfree(buf);
}
static void
-wl_tput_dump(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
+wl_btc_dump(struct net_device *dev)
{
- struct dhd_pub *dhd = apsta_params->dhd;
- void *buf = NULL;
- sta_info_v4_t *sta = NULL;
- struct ether_addr bssid;
- wl_rssi_ant_t *rssi_ant_p;
- char rssi_buf[16];
- scb_val_t scb_val;
- int ret, bytes_written = 0, i;
- s32 rate = 0;
- dhd_if_t *ifp = NULL;
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ int ret, val;
- if (!(android_msg_level & ANDROID_TPUT_LEVEL))
+ if (!(android_msg_level & ANDROID_BTC_LEVEL))
return;
- ifp = dhd_get_ifp(dhd, cur_if->ifidx);
+ ret = dhd_conf_reg2args(dhd, "btc_params", FALSE, 15, &val);
+ if (!ret)
+ WL_MSG(dev->name,"btc_params15=%d\n", val);
+}
- buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
- if (buf == NULL) {
- IAPSTA_ERROR(cur_if->dev->name, "MALLOC failed\n");
+static void
+wl_tvpm_dump(struct net_device *dev)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ wl_tvpm_req_t* tvpm_req = NULL;
+ size_t reqlen = sizeof(wl_tvpm_req_t) + sizeof(wl_tvpm_status_t);
+ uint8 *outbuf = apsta_params->ioctl_buf;
+ size_t outlen = WLC_IOCTL_MEDLEN;
+ wl_tvpm_status_t* status;
+ int ret, phy_temp = 0;
+ bool tvpm = FALSE, sense = FALSE;
+
+ if (!(android_msg_level & ANDROID_TVPM_LEVEL))
+ return;
+
+ tvpm_req = kmalloc(reqlen, GFP_KERNEL);
+ if (tvpm_req == NULL) {
+ IAPSTA_ERROR(dev->name, "MALLOC failed\n");
goto exit;
}
+ memset(tvpm_req, 0, reqlen);
- wldev_ioctl_get(cur_if->dev, WLC_GET_RATE, &rate, sizeof(rate));
- rate = dtoh32(rate);
- memset(rssi_buf, 0, sizeof(rssi_buf));
- if (cur_if->ifmode == ISTA_MODE) {
- ret = wldev_iovar_getbuf(cur_if->dev, "phy_rssi_ant", NULL, 0,
- buf, WLC_IOCTL_MEDLEN, NULL);
- rssi_ant_p = (wl_rssi_ant_t *)buf;
- rssi_ant_p->version = dtoh32(rssi_ant_p->version);
- rssi_ant_p->count = dtoh32(rssi_ant_p->count);
- if (ret < 0 || rssi_ant_p->count == 0) {
- wldev_ioctl(cur_if->dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t), 0);
+ tvpm_req->version = TVPM_REQ_VERSION_1;
+ tvpm_req->length = reqlen;
+ tvpm_req->req_type = WL_TVPM_REQ_STATUS;
+ ret = wldev_iovar_getbuf(dev, "tvpm", tvpm_req, reqlen, outbuf, outlen, NULL);
+ status = (wl_tvpm_status_t*)outbuf;
+ if (!ret && status->enable) {
+ tvpm = TRUE;
+ } else {
+ ret = wldev_iovar_getbuf(dev, "phy_tempsense", &phy_temp, sizeof(phy_temp),
+ outbuf, outlen, NULL);
+ if (!ret) {
+ phy_temp = dtoh32(*(int*)outbuf);
+ sense = TRUE;
+ }
+ }
+
+ if (tvpm) {
+ WL_MSG(dev->name,"temp=%3d, duty=%3d, pwrbko=%d, chains=%d\n",
+ status->temp, status->tx_dutycycle, status->tx_power_backoff,
+ status->num_active_chains);
+ }
+ else if (sense) {
+ WL_MSG(dev->name,"phy_temp=%3d\n", phy_temp);
+ }
+
+exit:
+ if (tvpm_req)
+ kfree(tvpm_req);
+}
+
+static void
+wl_phy_rssi_ant(struct net_device *dev, struct ether_addr *mac,
+ char *rssi_buf, int len)
+{
+ struct wl_if_info *cur_if = NULL;
+ char buf[WLC_IOCTL_SMLEN];
+ wl_rssi_ant_t *rssi_ant_p;
+ int ret, bytes_written = 0, i;
+ scb_val_t scb_val;
+
+ cur_if = wl_get_cur_if(dev);
+ if (!cur_if)
+ return;
+
+ memset(buf, 0, sizeof(buf));
+ ret = wldev_iovar_getbuf(dev, "phy_rssi_ant",
+ mac, mac ? ETHER_ADDR_LEN : 0, buf, sizeof(buf), NULL);
+ rssi_ant_p = (wl_rssi_ant_t *)buf;
+ rssi_ant_p->version = dtoh32(rssi_ant_p->version);
+ rssi_ant_p->count = dtoh32(rssi_ant_p->count);
+ if (ret < 0 || rssi_ant_p->count == 0) {
+ if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) {
+ wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t), 0);
rssi_ant_p->count = 1;
rssi_ant_p->rssi_ant[0] = dtoh32(scb_val.val);
}
- for (i=0; i<rssi_ant_p->count && rssi_ant_p->rssi_ant[i]; i++) {
- bytes_written += snprintf(rssi_buf+bytes_written, sizeof(rssi_buf),
- "[%2d]", rssi_ant_p->rssi_ant[i]);
+ }
+ for (i=0; i<rssi_ant_p->count && rssi_ant_p->rssi_ant[i]; i++) {
+ bytes_written += snprintf(rssi_buf+bytes_written, len,
+ "[%2d]", rssi_ant_p->rssi_ant[i]);
+ }
+}
+
+static void
+wl_tput_dump(struct wl_apsta_params *apsta_params,
+ struct net_device *dev, wl_tput_info_t *tput_info)
+{
+ WL_MSG(dev->name,
+ "tx=%3d.%d%d%d Mbps, rx=%3d.%d%d%d Mbps, tput_sum=%3d.%d%d%d Mbps\n",
+ tput_info->tput_tx, (tput_info->tput_tx_kb/100)%10,
+ (tput_info->tput_tx_kb/10)%10, (tput_info->tput_tx_kb)%10,
+ tput_info->tput_rx, (tput_info->tput_rx_kb/100)%10,
+ (tput_info->tput_rx_kb/10)%10, (tput_info->tput_rx_kb)%10,
+ apsta_params->tput_sum, (apsta_params->tput_sum_kb/100)%10,
+ (apsta_params->tput_sum_kb/10)%10, (apsta_params->tput_sum_kb)%10);
+}
+
+static void
+wl_sta_info_dump(struct net_device *dev, struct ether_addr *mac)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ void *buf = apsta_params->ioctl_buf;
+ sta_info_v4_t *sta = NULL;
+ char rssi_buf[16];
+ int ret;
+ s32 rate = 0;
+
+ memset(rssi_buf, 0, sizeof(rssi_buf));
+ wl_phy_rssi_ant(dev, mac, rssi_buf, sizeof(rssi_buf));
+ ret = wldev_iovar_getbuf(dev, "sta_info", (const void*)mac,
+ ETHER_ADDR_LEN, buf, WLC_IOCTL_MEDLEN, NULL);
+ if (ret == 0) {
+ sta = (sta_info_v4_t *)buf;
+ }
+ if (sta == NULL || (sta->ver != WL_STA_VER_4 && sta->ver != WL_STA_VER_5 &&
+ sta->ver != WL_STA_VER_6)) {
+ wldev_ioctl_get(dev, WLC_GET_RATE, &rate, sizeof(rate));
+ rate = dtoh32(rate);
+ WL_MSG(dev->name,
+ "mac=%pM, rssi=%s, tx_rate:%4d%2s\n",
+ mac, rssi_buf, rate/2, (rate & 1) ? ".5" : "");
+ } else {
+ if (dtoh32(sta->rx_rate) != -1) {
+ WL_MSG(dev->name,
+ "mac=%pM, rssi=%s, tx_rate:%4d.%d, rx_rate:%4d.%d\n",
+ mac, rssi_buf,
+ dtoh32(sta->tx_rate)/1000, ((dtoh32(sta->tx_rate)/100)%10),
+ dtoh32(sta->rx_rate)/1000, ((dtoh32(sta->rx_rate)/100)%10));
+ } else {
+ WL_MSG(dev->name,
+ "mac=%pM, rssi=%s, tx_rate:%4d.%d, rx_rate:%4d\n",
+ mac, rssi_buf,
+ dtoh32(sta->tx_rate)/1000, ((dtoh32(sta->tx_rate)/100)%10),
+ dtoh32(sta->rx_rate));
}
+ }
+}
+
+static void
+wl_cur_if_tput_dump(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
+{
+#ifdef WLDWDS
+ struct wl_dwds_info *dwds_if;
+ int i;
+#endif /* WLDWDS */
+ struct ether_addr bssid;
+ int ret = 0;
+
+ if (!(android_msg_level & ANDROID_TPUT_LEVEL))
+ return;
+
+ wl_tput_dump(apsta_params, cur_if->dev, &cur_if->tput_info);
+
+ if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) {
wldev_ioctl(cur_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
- ret = wldev_iovar_getbuf(cur_if->dev, "sta_info", (const void*)&bssid,
- ETHER_ADDR_LEN, buf, WLC_IOCTL_MEDLEN, NULL);
- if (ret == 0) {
- sta = (sta_info_v4_t *)buf;
+ if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
+ wl_sta_info_dump(cur_if->dev, &bssid);
}
}
- else {
- bytes_written += snprintf(rssi_buf+bytes_written, sizeof(rssi_buf),
- "[ ][ ]");
- }
-
- if (sta == NULL || (sta->ver != WL_STA_VER_4 && sta->ver != WL_STA_VER_5)) {
- WL_MSG(cur_if->dev->name,
- "rssi=%s, tx=%3d.%d%d%d Mbps(rate:%4d%2s), rx=%3d.%d%d%d Mbps(rate: ), "\
- "tput_sum=%3d.%d%d%d Mbps\n",
- rssi_buf, cur_if->tput_tx, (cur_if->tput_tx_kb/100)%10,
- (cur_if->tput_tx_kb/10)%10, (cur_if->tput_tx_kb)%10,
- rate/2, (rate & 1) ? ".5" : "",
- cur_if->tput_rx, (cur_if->tput_rx_kb/100)%10,
- (cur_if->tput_rx_kb/10)%10, (cur_if->tput_rx_kb)%10,
- apsta_params->tput_sum, (apsta_params->tput_sum_kb/100)%10,
- (apsta_params->tput_sum_kb/10)%10, (apsta_params->tput_sum_kb)%10);
- } else {
- WL_MSG(cur_if->dev->name,
- "rssi=%s, tx=%3d.%d%d%d Mbps(rate:%4d%2s), rx=%3d.%d%d%d Mbps(rate:%4d.%d), "\
- "tput_sum=%3d.%d%d%d Mbps\n",
- rssi_buf, cur_if->tput_tx, (cur_if->tput_tx_kb/100)%10,
- (cur_if->tput_tx_kb/10)%10, (cur_if->tput_tx_kb)%10,
- rate/2, (rate & 1) ? ".5" : "",
- cur_if->tput_rx, (cur_if->tput_rx_kb/100)%10,
- (cur_if->tput_rx_kb/10)%10, (cur_if->tput_rx_kb)%10,
- dtoh32(sta->rx_rate)/1000, ((dtoh32(sta->rx_rate)/100)%10),
- apsta_params->tput_sum, (apsta_params->tput_sum_kb/100)%10,
- (apsta_params->tput_sum_kb/10)%10, (apsta_params->tput_sum_kb)%10);
+ else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IGO_MODE) {
+ int i, maxassoc = 0;
+ char mac_buf[MAX_NUM_OF_ASSOCLIST *
+ sizeof(struct ether_addr) + sizeof(uint)] = {0};
+ struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+
+ assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
+ ret = wl_ext_ioctl(cur_if->dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf), 0);
+ if (ret)
+ goto exit;
+ maxassoc = dtoh32(assoc_maclist->count);
+ for (i=0; i<maxassoc; i++) {
+ wl_sta_info_dump(cur_if->dev, &assoc_maclist->ea[i]);
+ }
+#ifdef WLDWDS
+ for (i=0; i<MAX_DWDS_IF_NUM; i++) {
+ dwds_if = &apsta_params->dwds_info[i];
+ if (dwds_if->dev && cur_if->bssidx == dwds_if->bssidx) {
+ wl_tput_dump(apsta_params, dwds_if->dev, &dwds_if->tput_info);
+ }
+ }
+#endif /* WLDWDS */
}
exit:
- if (buf) {
- kfree(buf);
- }
+ return;
}
static void
-wl_tput_monitor(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
+wl_tput_monitor(struct dhd_pub *dhd, int ifidx, struct wl_tput_info *tput_info)
{
- struct dhd_pub *dhd = apsta_params->dhd;
dhd_if_t *ifp = NULL;
- ifp = dhd_get_ifp(dhd, cur_if->ifidx);
+ ifp = dhd_get_ifp(dhd, ifidx);
+ if (!ifp)
+ return;
- if (cur_if->tput_ts.tv_sec == 0 && cur_if->tput_ts.tv_nsec == 0) {
- osl_do_gettimeofday(&cur_if->tput_ts);
- cur_if->last_tx = ifp->stats.tx_bytes;
- cur_if->last_rx = ifp->stats.rx_bytes;
+ if (tput_info->tput_ts.tv_sec == 0 && tput_info->tput_ts.tv_nsec == 0) {
+ osl_do_gettimeofday(&tput_info->tput_ts);
+ tput_info->last_tx = ifp->stats.tx_bytes;
+ tput_info->last_rx = ifp->stats.rx_bytes;
} else {
struct osl_timespec cur_ts;
uint32 diff_ms;
osl_do_gettimeofday(&cur_ts);
- diff_ms = osl_do_gettimediff(&cur_ts, &cur_if->tput_ts)/1000;
- memcpy(&cur_if->tput_ts, &cur_ts, sizeof(struct osl_timespec));
- cur_if->tput_tx = (int32)(((ifp->stats.tx_bytes-cur_if->last_tx)/1024/1024)*8)*1000/diff_ms;
- if (cur_if->tput_tx == 0) {
- cur_if->tput_tx = (int32)((ifp->stats.tx_bytes-cur_if->last_tx)*8*1000/1024/1024)/diff_ms;
- cur_if->tput_tx_kb = (int32)((ifp->stats.tx_bytes-cur_if->last_tx)*8*1000/1024)/diff_ms;
- cur_if->tput_tx_kb = cur_if->tput_tx_kb % 1000;
+ diff_ms = osl_do_gettimediff(&cur_ts, &tput_info->tput_ts)/1000;
+ memcpy(&tput_info->tput_ts, &cur_ts, sizeof(struct osl_timespec));
+ tput_info->tput_tx = (int32)(((ifp->stats.tx_bytes-tput_info->last_tx)/1024/1024)*8)*1000/diff_ms;
+ if (tput_info->tput_tx == 0) {
+ tput_info->tput_tx = (int32)((ifp->stats.tx_bytes-tput_info->last_tx)*8*1000/1024/1024)/diff_ms;
+ tput_info->tput_tx_kb = (int32)((ifp->stats.tx_bytes-tput_info->last_tx)*8*1000/1024)/diff_ms;
+ tput_info->tput_tx_kb = tput_info->tput_tx_kb % 1000;
} else
- cur_if->tput_tx_kb = 0;
- cur_if->tput_rx = (int32)(((ifp->stats.rx_bytes-cur_if->last_rx)/1024/1024)*8)*1000/diff_ms;
- if (cur_if->tput_rx == 0) {
- cur_if->tput_rx = (int32)((ifp->stats.rx_bytes-cur_if->last_rx)*8*1000/1024/1024)/diff_ms;
- cur_if->tput_rx_kb = (int32)((ifp->stats.rx_bytes-cur_if->last_rx)*8*1000/1024)/diff_ms;
- cur_if->tput_rx_kb = cur_if->tput_rx_kb % 1000;
+ tput_info->tput_tx_kb = 0;
+ tput_info->tput_rx = (int32)(((ifp->stats.rx_bytes-tput_info->last_rx)/1024/1024)*8)*1000/diff_ms;
+ if (tput_info->tput_rx == 0) {
+ tput_info->tput_rx = (int32)((ifp->stats.rx_bytes-tput_info->last_rx)*8*1000/1024/1024)/diff_ms;
+ tput_info->tput_rx_kb = (int32)((ifp->stats.rx_bytes-tput_info->last_rx)*8*1000/1024)/diff_ms;
+ tput_info->tput_rx_kb = tput_info->tput_rx_kb % 1000;
} else
- cur_if->tput_rx_kb = 0;
- cur_if->last_tx = ifp->stats.tx_bytes;
- cur_if->last_rx = ifp->stats.rx_bytes;
+ tput_info->tput_rx_kb = 0;
+ tput_info->last_tx = ifp->stats.tx_bytes;
+ tput_info->last_rx = ifp->stats.rx_bytes;
}
}
static void
-wl_tput_monitor_handler(struct wl_apsta_params *apsta_params,
- struct wl_if_info *cur_if, const wl_event_msg_t *e, void *data)
+wl_tput_monitor_handler(struct wl_if_info *cur_if,
+ const wl_event_msg_t *e, void *data)
{
- struct dhd_pub *dhd = apsta_params->dhd;
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ wl_tput_info_t *tput_info;
struct wl_if_info *tmp_if;
+#ifdef WLDWDS
+ struct wl_dwds_info *dwds_if;
+#endif /* WLDWDS */
uint32 etype = ntoh32(e->event_type);
uint32 status = ntoh32(e->status);
uint32 reason = ntoh32(e->reason);
uint16 flags = ntoh16(e->flags);
uint timeout = dhd->conf->tput_monitor_ms;
int32 tput_sum = 0, tput_sum_kb = 0;
- bool monitor_if[MAX_IF_NUM] = {FALSE};
+ bool monitor_if[MAX_IF_NUM] = {FALSE}, monitor = FALSE;
int i;
if (etype == WLC_E_RESERVED && reason == ISAM_RC_TPUT_MONITOR) {
tput_sum = 0;
for (i=0; i<MAX_IF_NUM; i++) {
tmp_if = &apsta_params->if_info[i];
- if (tmp_if->dev && tmp_if->ifmode == ISTA_MODE &&
- wl_ext_get_chan(apsta_params, tmp_if->dev)) {
- wl_tput_monitor(apsta_params, tmp_if);
+ if (tmp_if->dev &&
+ (tmp_if->ifmode == ISTA_MODE || tmp_if->ifmode == IGC_MODE) &&
+ wl_ext_associated(tmp_if->dev)) {
+ wl_tput_monitor(dhd, tmp_if->ifidx, &tmp_if->tput_info);
monitor_if[i] = TRUE;
}
- else if (tmp_if->dev && tmp_if->ifmode == IAP_MODE &&
+ else if (tmp_if->dev &&
+ (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IGO_MODE) &&
wl_ext_assoclist_num(tmp_if->dev)) {
- wl_tput_monitor(apsta_params, tmp_if);
+ wl_tput_monitor(dhd, tmp_if->ifidx, &tmp_if->tput_info);
monitor_if[i] = TRUE;
}
- tput_sum += (tmp_if->tput_tx + tmp_if->tput_rx);
- tput_sum_kb += (tmp_if->tput_tx_kb + tmp_if->tput_rx_kb);
+ if (monitor_if[i] == TRUE) {
+ tput_info = &tmp_if->tput_info;
+ tput_sum += (tput_info->tput_tx + tput_info->tput_rx);
+ tput_sum_kb += (tput_info->tput_tx_kb + tput_info->tput_rx_kb);
+ }
+ }
+#ifdef WLDWDS
+ for (i=0; i<MAX_DWDS_IF_NUM; i++) {
+ dwds_if = &apsta_params->dwds_info[i];
+ if (dwds_if->dev) {
+ wl_tput_monitor(dhd, dwds_if->ifidx, &dwds_if->tput_info);
+ tput_info = &dwds_if->tput_info;
+ tput_sum += (tput_info->tput_tx + tput_info->tput_rx);
+ tput_sum_kb += (tput_info->tput_tx_kb + tput_info->tput_rx_kb);
+ }
}
+#endif /* WLDWDS */
apsta_params->tput_sum = tput_sum + (tput_sum_kb/1000);
apsta_params->tput_sum_kb = tput_sum_kb % 1000;
for (i=0; i<MAX_IF_NUM; i++) {
if (monitor_if[i]) {
tmp_if = &apsta_params->if_info[i];
- wl_tput_dump(apsta_params, tmp_if);
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, timeout);
+ wl_cur_if_tput_dump(apsta_params, tmp_if);
+ monitor = TRUE;
}
}
+ if (monitor) {
+ wl_btc_dump(cur_if->dev);
+ wl_tvpm_dump(cur_if->dev);
+ wl_ampdu_dump(cur_if->dev);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, timeout);
+ }
#ifdef BCMSDIO
if (apsta_params->tput_sum >= dhd->conf->doflow_tput_thresh && dhd_doflow) {
dhd_doflow = FALSE;
}
#endif
}
- else if (cur_if->ifmode == ISTA_MODE) {
+ else if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) {
if (etype == WLC_E_LINK) {
if (flags & WLC_EVENT_MSG_LINK) {
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, timeout);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, timeout);
} else if (!wl_ext_iapsta_other_if_enabled(cur_if->dev)) {
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, 0);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, 0);
}
}
}
- else if (cur_if->ifmode == IAP_MODE) {
+ else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IGO_MODE) {
if ((etype == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
(etype == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
reason == WLC_E_REASON_INITIAL_ASSOC)) {
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, timeout);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, timeout);
} else if ((etype == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
(etype == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
reason == WLC_E_REASON_DEAUTH)) {
if (!wl_ext_iapsta_other_if_enabled(cur_if->dev)) {
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, 0);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, 0);
}
} else if ((etype == WLC_E_ASSOC_IND || etype == WLC_E_REASSOC_IND) &&
reason == DOT11_SC_SUCCESS) {
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, timeout);
+ wl_timer_mod(dhd, &apsta_params->monitor_timer, timeout);
}
}
}
#endif /* TPUT_MONITOR */
#ifdef ACS_MONITOR
-static void
-wl_ext_mod_timer_pending(timer_list_compat_t *timer, uint sec, uint msec)
-{
- uint timeout = sec * 1000 + msec;
-
- if (timeout && !timer_pending(timer)) {
- IAPSTA_TRACE("wlan", "timeout=%d\n", timeout);
- mod_timer(timer, jiffies + msecs_to_jiffies(timeout));
- }
-}
-
static bool
wl_ext_max_prio_if(struct wl_apsta_params *apsta_params,
struct wl_if_info *cur_if)
{
struct wl_if_info *tmp_if;
wl_prio_t max_prio;
- uint16 target_chan;
int i;
if (apsta_params->vsdb) {
- target_chan = cur_if->channel;
goto exit;
}
tmp_if = &apsta_params->if_info[i];
if (cur_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) &&
tmp_if->prio > max_prio) {
- target_chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if (target_chan) {
+ if (wl_ext_associated(tmp_if->dev)) {
return TRUE;
}
}
wl_ext_acs_scan(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
{
if (apsta_params->acs & ACS_DRV_BIT) {
- if (wl_ext_get_chan(apsta_params, cur_if->dev)) {
+ if (wl_ext_associated(cur_if->dev)) {
int ret, cur_scan_time;
cur_if->escan->autochannel = 1;
cur_scan_time = wl_ext_set_scan_time(cur_if->dev, 80,
static void
wl_ext_acs(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
{
- uint cur_band;
- uint16 cur_chan, acs_chan;
+ struct wl_chan_info chan_info;
if (apsta_params->acs & ACS_DRV_BIT) {
mutex_lock(&apsta_params->usr_sync);
- cur_chan = wl_ext_get_chan(apsta_params, cur_if->dev);
- if (cur_chan) {
- cur_band = WL_GET_BAND(cur_chan);
- if (cur_band == WLC_BAND_5G)
- cur_if->channel = cur_if->escan->best_5g_ch;
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(cur_if->dev, &chan_info);
+ if (chan_info.chan) {
+ if (chan_info.band == WLC_BAND_5G)
+ cur_if->chan_info.chan = cur_if->escan->best_5g_ch;
else
- cur_if->channel = cur_if->escan->best_2g_ch;
- acs_chan = wl_ext_move_cur_channel(apsta_params, cur_if);
- if (acs_chan != cur_chan) {
- WL_MSG(cur_if->dev->name, "move channel %d => %d\n",
- cur_chan, acs_chan);
+ cur_if->chan_info.chan = cur_if->escan->best_2g_ch;
+ wl_ext_move_cur_channel(apsta_params, cur_if);
+ if (!wl_ext_same_chan(&cur_if->chan_info, &chan_info)) {
+ WL_MSG(cur_if->dev->name, "move channel %s-%d => %s-%d\n",
+ WLCBAND2STR(chan_info.band), chan_info.chan,
+ WLCBAND2STR(cur_if->chan_info.band), cur_if->chan_info.chan);
wl_ext_if_down(apsta_params, cur_if);
wl_ext_move_other_channel(apsta_params, cur_if);
wl_ext_if_up(apsta_params, cur_if, FALSE, 500);
bzero(&msg, sizeof(wl_event_msg_t));
IAPSTA_TRACE(dev->name, "timer expired\n");
- msg.ifidx = hton32(dhd_net2idx(dhd->info, dev));
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
msg.event_type = hton32(WLC_E_RESERVED);
msg.reason = hton32(ISAM_RC_AP_ACS);
wl_ext_event_send(dhd->event_params, &msg, NULL);
(etype == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
reason == WLC_E_REASON_INITIAL_ASSOC)) {
// Link up
- wl_ext_mod_timer_pending(&cur_if->acs_timer, acs_tmo, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, acs_tmo*1000);
}
else if ((etype == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
(etype == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
reason == WLC_E_REASON_DEAUTH)) {
// Link down
- wl_ext_mod_timer(&cur_if->acs_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, 0);
cur_if->escan->autochannel = 0;
}
else if ((etype == WLC_E_ASSOC_IND || etype == WLC_E_REASSOC_IND) &&
reason == DOT11_SC_SUCCESS) {
// external STA connected
- wl_ext_mod_timer(&cur_if->acs_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, 0);
}
else if (etype == WLC_E_DISASSOC_IND ||
etype == WLC_E_DEAUTH_IND ||
(etype == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
// external STA disconnected
- wl_ext_mod_timer_pending(&cur_if->acs_timer, acs_tmo, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, acs_tmo*1000);
}
else if (etype == WLC_E_RESERVED && reason == ISAM_RC_AP_ACS) {
// acs_tmo expired
if (!wl_ext_assoclist_num(cur_if->dev) &&
!wl_ext_max_prio_if(apsta_params, cur_if)) {
wl_ext_acs_scan(apsta_params, cur_if);
- wl_ext_mod_timer(&cur_if->acs_timer, acs_tmo, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, acs_tmo*1000);
} else {
- wl_ext_mod_timer(&cur_if->acs_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, 0);
}
}
else if (((etype == WLC_E_ESCAN_RESULT && status == WLC_E_STATUS_SUCCESS) ||
!wl_ext_max_prio_if(apsta_params, cur_if)) {
wl_ext_acs(apsta_params, cur_if);
} else {
- wl_ext_mod_timer(&cur_if->acs_timer, 0, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, 0);
+ }
+ }
+ }
+}
+
+static void
+wl_acs_detach(struct wl_if_info *cur_if)
+{
+ IAPSTA_TRACE(cur_if->dev->name, "Enter\n");
+ wl_timer_deregister(cur_if->dev, &cur_if->acs_timer);
+ if (cur_if->escan) {
+ cur_if->escan = NULL;
+ }
+}
+
+static void
+wl_acs_attach(dhd_pub_t *dhd, struct wl_if_info *cur_if)
+{
+ IAPSTA_TRACE(cur_if->dev->name, "Enter\n");
+ cur_if->escan = dhd->escan;
+ wl_timer_register(cur_if->dev, &cur_if->acs_timer, wl_acs_timer);
+}
+#endif /* ACS_MONITOR */
+
+#ifdef RESTART_AP_WAR
+static void
+wl_ext_restart_ap_timeout(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct dhd_pub *dhd;
+ wl_event_msg_t msg;
+
+ if (!dev) {
+ IAPSTA_ERROR("wlan", "dev is not ready\n");
+ return;
+ }
+
+ dhd = dhd_get_pub(dev);
+
+ bzero(&msg, sizeof(wl_event_msg_t));
+ IAPSTA_TRACE(dev->name, "timer expired\n");
+
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
+ msg.event_type = hton32(WLC_E_RESERVED);
+ msg.reason = hton32(ISAM_RC_AP_RESTART);
+ wl_ext_event_send(dhd->event_params, &msg, NULL);
+}
+
+static void
+wl_ext_restart_ap_handler(struct wl_if_info *cur_if,
+ const wl_event_msg_t *e, void *data)
+{
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ uint32 etype = ntoh32(e->event_type);
+ uint32 reason = ntoh32(e->reason);
+
+ if (etype == WLC_E_RESERVED && reason == ISAM_RC_AP_RESTART) {
+ if (!wl_get_isam_status(cur_if, AP_CREATED)) {
+ if (!wl_ext_associated(cur_if->dev)) {
+ WL_MSG(cur_if->ifname, "restart AP\n");
+ wl_ext_if_down(apsta_params, cur_if);
+ wl_ext_if_up(apsta_params, cur_if, FALSE, 1);
+ wl_timer_mod(dhd, &cur_if->restart_ap_timer, AP_RESTART_TIMEOUT);
+ } else {
+ WL_MSG(cur_if->ifname, "skip restart AP\n");
}
}
}
+ return;
+}
+#endif /* RESTART_AP_WAR */
+
+#if defined(RESET_AP_WAR) || defined(RXF0OVFL_REINIT_WAR)
+static int
+wl_ext_counters_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+ struct wl_if_info *cur_if = ctx;
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ int res = BCME_OK;
+
+ switch (type) {
+ case WL_CNT_XTLV_CNTV_LE10_UCODE: {
+ wl_cnt_v_le10_mcst_t *cnt = (wl_cnt_v_le10_mcst_t *)data;
+ if (len != sizeof(wl_cnt_v_le10_mcst_t)) {
+ printf("type %d: cnt struct length mismatch! %d != %d\n",
+ type, len, (int)sizeof(wl_cnt_v_le10_mcst_t));
+ }
+#ifdef RESET_AP_WAR
+ if (apsta_params->war_reason == ISAM_RC_AP_RESET)
+ cur_if->txbcnfrm = dtoh32(cnt->txbcnfrm);
+#endif /* RESET_AP_WAR */
+#ifdef RXF0OVFL_REINIT_WAR
+ if (apsta_params->war_reason == ISAM_RC_RXF0OVFL_REINIT) {
+ apsta_params->rxbeaconmbss = dtoh32(cnt->rxbeaconmbss);
+ apsta_params->rxf0ovfl = dtoh32(cnt->rxf0ovfl);
+ }
+#endif /* RXF0OVFL_REINIT_WAR */
+ break;
+ }
+ case WL_CNT_XTLV_GE40_UCODE_V1:
+ {
+ wl_cnt_ge40mcst_v1_t *cnt = (wl_cnt_ge40mcst_v1_t *)data;
+ if (len != sizeof(wl_cnt_ge40mcst_v1_t)) {
+ IAPSTA_ERROR(cur_if->ifname,
+ "type 0x%x, cnt struct length mismatch! %d != %d\n",
+ type, len, (int)sizeof(wl_cnt_ge40mcst_v1_t));
+ }
+#ifdef RESET_AP_WAR
+ if (apsta_params->war_reason == ISAM_RC_AP_RESET)
+ cur_if->txbcnfrm = dtoh32(cnt->txbcnfrm);
+#endif /* RESET_AP_WAR */
+#ifdef RXF0OVFL_REINIT_WAR
+ if (apsta_params->war_reason == ISAM_RC_RXF0OVFL_REINIT) {
+ apsta_params->rxbeaconmbss = dtoh32(cnt->rxbeaconmbss);
+ apsta_params->rxf0ovfl = dtoh32(cnt->rxf0ovfl);
+ }
+#endif /* RXF0OVFL_REINIT_WAR */
+ break;
+ }
+ case WL_CNT_XTLV_GE80_UCODE_V1:
+ {
+ wl_cnt_ge80mcst_v1_t *cnt = (wl_cnt_ge80mcst_v1_t *)data;
+ if (len != sizeof(wl_cnt_ge80mcst_v1_t)) {
+ IAPSTA_ERROR(cur_if->ifname,
+ "type 0x%x, cnt struct length mismatch! %d != %d\n",
+ type, len, (int)sizeof(wl_cnt_ge80mcst_v1_t));
+ }
+#ifdef RESET_AP_WAR
+ if (apsta_params->war_reason == ISAM_RC_AP_RESET)
+ cur_if->txbcnfrm = dtoh32(cnt->txbcnfrm);
+#endif /* RESET_AP_WAR */
+#ifdef RXF0OVFL_REINIT_WAR
+ if (apsta_params->war_reason == ISAM_RC_RXF0OVFL_REINIT) {
+ apsta_params->rxbeaconmbss = dtoh32(cnt->rxbeaconmbss);
+ apsta_params->rxf0ovfl = dtoh32(cnt->rxf0ovfl);
+ }
+#endif /* RXF0OVFL_REINIT_WAR */
+ break;
+ }
+ default:
+ break;
+ }
+ return res;
+}
+
+static int
+wl_ext_counters_update(struct wl_if_info *cur_if, int war_reason)
+{
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ char *iovar_buf = apsta_params->ioctl_buf;
+ uint32 corerev = 0;
+ wl_cnt_info_t *cntinfo;
+ uint16 ver;
+ int ret = 0;
+
+ ret = wldev_iovar_getbuf(cur_if->dev, "counters", NULL, 0,
+ iovar_buf, WLC_IOCTL_MEDLEN, NULL);
+ if (unlikely(ret)) {
+ IAPSTA_ERROR(cur_if->ifname,
+ "counters error (%d) - size = %zu\n", ret, sizeof(wl_cnt_wlc_t));
+ goto exit;
+ }
+ cntinfo = (wl_cnt_info_t *)iovar_buf;
+ cntinfo->version = dtoh16(cntinfo->version);
+ cntinfo->datalen = dtoh16(cntinfo->datalen);
+ ver = cntinfo->version;
+ CHK_CNTBUF_DATALEN(iovar_buf, WLC_IOCTL_MEDLEN);
+ if (ver > WL_CNT_VERSION_XTLV) {
+ IAPSTA_ERROR(cur_if->ifname,
+ "Incorrect version of counters struct: expected %d; got %d\n",
+ WL_CNT_VERSION_XTLV, ver);
+ goto exit;
+ }
+
+ if (ver == WL_CNT_VERSION_11) {
+ wlc_rev_info_t revinfo;
+ memset(&revinfo, 0, sizeof(revinfo));
+ ret = wl_ext_ioctl(cur_if->dev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), 0);
+ if (ret) {
+ IAPSTA_ERROR(cur_if->ifname, "WLC_GET_REVINFO failed %d\n", ret);
+ goto exit;
+ }
+ corerev = dtoh32(revinfo.corerev);
+ }
+ ret = wl_cntbuf_to_xtlv_format(NULL, cntinfo, WLC_IOCTL_MEDLEN, corerev);
+ if (ret) {
+ IAPSTA_ERROR(cur_if->ifname, "wl_cntbuf_to_xtlv_format failed %d\n", ret);
+ goto exit;
+ }
+
+ apsta_params->war_reason = war_reason;
+ if ((ret = bcm_unpack_xtlv_buf(cur_if, cntinfo->data, cntinfo->datalen,
+ BCM_XTLV_OPTION_ALIGN32, wl_ext_counters_cbfn))) {
+ IAPSTA_ERROR(cur_if->ifname, "bcm_unpack_xtlv_buf failed %d\n", ret);
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+#endif /* RESET_AP_WAR | RXF0OVFL_REINIT_WAR */
+
+#ifdef RESET_AP_WAR
+static void
+wl_ext_reset_ap_timeout(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct dhd_pub *dhd;
+ wl_event_msg_t msg;
+
+ if (!dev) {
+ IAPSTA_ERROR("wlan", "dev is not ready\n");
+ return;
+ }
+
+ dhd = dhd_get_pub(dev);
+
+ bzero(&msg, sizeof(wl_event_msg_t));
+ IAPSTA_TRACE(dev->name, "timer expired\n");
+
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
+ msg.event_type = hton32(WLC_E_RESERVED);
+ msg.reason = hton32(ISAM_RC_AP_RESET);
+ wl_ext_event_send(dhd->event_params, &msg, NULL);
+}
+
+static void
+wl_ext_reset_ap_handler(struct wl_if_info *cur_if,
+ const wl_event_msg_t *e, void *data)
+{
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ uint32 etype = ntoh32(e->event_type);
+ uint32 status = ntoh32(e->status);
+ uint32 reason = ntoh32(e->reason);
+ uint32 txbcnfrm;
+ int ret = 0;
+
+ if (wl_get_isam_status(cur_if, AP_CREATED)) {
+ if ((etype == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
+ (etype == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_INITIAL_ASSOC)) {
+ // Link up
+ wl_ext_counters_update(cur_if, ISAM_RC_AP_RESET);
+ wl_timer_mod(dhd, &cur_if->reset_ap_timer, AP_TXBCNFRM_TIMEOUT);
+ }
+ else if (etype == WLC_E_RESERVED && reason == ISAM_RC_AP_RESET) {
+ txbcnfrm = cur_if->txbcnfrm;
+ ret = wl_ext_counters_update(cur_if, ISAM_RC_AP_RESET);
+ if (ret)
+ goto done;
+ if ((cur_if->txbcnfrm != 0) && (txbcnfrm == cur_if->txbcnfrm)) {
+ WL_MSG(cur_if->ifname, "reset AP mode\n");
+ wl_ext_if_down(apsta_params, cur_if);
+ wl_ext_if_up(apsta_params, cur_if, FALSE, 500);
+ }
+done:
+ wl_timer_mod(dhd, &cur_if->reset_ap_timer, AP_TXBCNFRM_TIMEOUT);
+ }
+ }
+ return;
+}
+#endif /* RESET_AP_WAR */
+
+#ifdef RXF0OVFL_REINIT_WAR
+static void
+wl_ext_rxf0ovfl_reinit_timeout(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct dhd_pub *dhd;
+ wl_event_msg_t msg;
+
+ if (!dev) {
+ IAPSTA_ERROR("wlan", "dev is not ready\n");
+ return;
+ }
+
+ dhd = dhd_get_pub(dev);
+
+ bzero(&msg, sizeof(wl_event_msg_t));
+ IAPSTA_TRACE(dev->name, "timer expired\n");
+
+ msg.ifidx = dhd_net2idx(dhd->info, dev);
+ msg.event_type = hton32(WLC_E_RESERVED);
+ msg.reason = hton32(ISAM_RC_RXF0OVFL_REINIT);
+ wl_ext_event_send(dhd->event_params, &msg, NULL);
}
static void
-wl_acs_detach(struct wl_if_info *cur_if)
+wl_ext_rxf0ovfl_reinit_handler(struct wl_if_info *cur_if, const wl_event_msg_t *e, void *data)
{
- IAPSTA_TRACE(cur_if->dev->name, "Enter\n");
- del_timer_sync(&cur_if->acs_timer);
- if (cur_if->escan) {
- cur_if->escan = NULL;
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ uint32 etype = ntoh32(e->event_type);
+ uint32 reason = ntoh32(e->reason);
+ uint32 status = ntoh32(e->status);
+ uint16 flags = ntoh16(e->flags);
+ uint32 rxbeaconmbss, rxbeaconmbss_diff = 0, rxf0ovfl, rxf0ovfl_diff = 0;
+ int ret = 0;
+ bool reinit = FALSE;
+
+ if ((cur_if->ifmode == ISTA_MODE) &&
+ (etype == WLC_E_LINK) && (flags & WLC_EVENT_MSG_LINK)) {
+ // Link up
+ wl_ext_counters_update(cur_if, ISAM_RC_RXF0OVFL_REINIT);
+ wl_timer_mod(dhd, &apsta_params->rxf0ovfl_timer, RXF0OVFL_POLLING_TIMEOUT);
+ }
+ else if ((cur_if->ifmode == IAP_MODE) &&
+ ((etype == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
+ (etype == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_INITIAL_ASSOC))) {
+ // Link up
+ wl_ext_counters_update(cur_if, ISAM_RC_RXF0OVFL_REINIT);
+ wl_timer_mod(dhd, &apsta_params->rxf0ovfl_timer, RXF0OVFL_POLLING_TIMEOUT);
+ }
+ else if ((etype == WLC_E_RESERVED) && (reason == ISAM_RC_RXF0OVFL_REINIT) &&
+ (wl_ext_iapsta_other_if_enabled(cur_if->dev))) {
+ rxbeaconmbss = apsta_params->rxbeaconmbss;
+ rxf0ovfl = apsta_params->rxf0ovfl;
+ wl_ext_counters_update(cur_if, ISAM_RC_RXF0OVFL_REINIT);
+ if (ret)
+ goto done;
+ rxf0ovfl_diff = apsta_params->rxf0ovfl - rxf0ovfl;
+ rxbeaconmbss_diff = apsta_params->rxbeaconmbss - rxbeaconmbss;
+ if (rxf0ovfl_diff > 0) {
+ IAPSTA_INFO(cur_if->ifname,
+ "rxf0ovfl diff = %d, rxbeaconmbss diff = %d\n",
+ rxf0ovfl_diff, rxbeaconmbss_diff);
+ }
+ if (wl_ext_if_enabled(apsta_params, ISTA_MODE)) {
+ if (rxbeaconmbss_diff < 5 && rxf0ovfl_diff > RXF0OVFL_THRESHOLD)
+ reinit = TRUE;
+ }
+ else if (wl_ext_if_enabled(apsta_params, IAP_MODE)) {
+ if (rxf0ovfl_diff > RXF0OVFL_THRESHOLD)
+ reinit = TRUE;
+ }
+ if (reinit) {
+ WL_MSG(cur_if->ifname, "wl reinit\n");
+ wl_ext_ioctl(cur_if->dev, WLC_INIT, NULL, 0, 1);
+ }
+done:
+ wl_timer_mod(dhd, &apsta_params->rxf0ovfl_timer, RXF0OVFL_POLLING_TIMEOUT);
}
-}
-static void
-wl_acs_attach(dhd_pub_t *dhd, struct wl_if_info *cur_if)
-{
- IAPSTA_TRACE(cur_if->dev->name, "Enter\n");
- cur_if->escan = dhd->escan;
- init_timer_compat(&cur_if->acs_timer, wl_acs_timer, cur_if->dev);
+ return;
}
-#endif /* ACS_MONITOR */
+#endif /* RXF0OVFL_REINIT_WAR */
void
-wl_ext_iapsta_event(struct net_device *dev, void *argu,
+wl_ext_iapsta_link(struct wl_if_info *cur_if,
const wl_event_msg_t *e, void *data)
{
- struct wl_apsta_params *apsta_params = (struct wl_apsta_params *)argu;
- struct wl_if_info *cur_if = NULL;
-#if defined(WLMESH) && defined(WL_ESCAN)
- struct wl_if_info *tmp_if = NULL;
- struct wl_if_info *mesh_if = NULL;
- int i;
-#endif /* WLMESH && WL_ESCAN */
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
uint32 event_type = ntoh32(e->event_type);
uint32 status = ntoh32(e->status);
uint32 reason = ntoh32(e->reason);
uint16 flags = ntoh16(e->flags);
- cur_if = wl_get_cur_if(dev);
-
-#if defined(WLMESH) && defined(WL_ESCAN)
- for (i=0; i<MAX_IF_NUM; i++) {
- tmp_if = &apsta_params->if_info[i];
- if (tmp_if->dev && tmp_if->ifmode == IMESH_MODE) {
- mesh_if = tmp_if;
- break;
- }
- }
-#endif /* WLMESH && WL_ESCAN */
- if (!cur_if || !cur_if->dev) {
- IAPSTA_DBG(dev->name, "ifidx %d is not ready\n", e->ifidx);
- return;
- }
-
if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) {
if (event_type == WLC_E_LINK) {
if (!(flags & WLC_EVENT_MSG_LINK)) {
wl_ext_net_setcarrier(cur_if, FALSE, FALSE);
#endif /* SET_CARRIER */
wl_clr_isam_status(cur_if, STA_CONNECTED);
-#if defined(WLMESH) && defined(WL_ESCAN)
- if (mesh_if && apsta_params->macs)
- wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
-#endif /* WLMESH && WL_ESCAN */
} else {
WL_MSG(cur_if->ifname, "[%c] Link UP with %pM\n",
cur_if->prefix, &e->addr);
wl_ext_net_setcarrier(cur_if, TRUE, FALSE);
#endif /* SET_CARRIER */
wl_set_isam_status(cur_if, STA_CONNECTED);
-#if defined(WLMESH) && defined(WL_ESCAN)
- if (mesh_if && apsta_params->macs)
- wl_mesh_update_master_info(apsta_params, mesh_if);
-#endif /* WLMESH && WL_ESCAN */
}
wl_clr_isam_status(cur_if, STA_CONNECTING);
wake_up_interruptible(&apsta_params->netif_change_event);
#ifdef PROPTX_MAXCOUNT
- wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+ wl_ext_update_wlfc_maxcount(dhd);
#endif /* PROPTX_MAXCOUNT */
}
else if (event_type == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) {
event_type, reason, status);
wl_clr_isam_status(cur_if, STA_CONNECTING);
wake_up_interruptible(&apsta_params->netif_change_event);
-#if defined(WLMESH) && defined(WL_ESCAN)
- if (mesh_if && apsta_params->macs)
- wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
-#endif /* WLMESH && WL_ESCAN */
#ifdef PROPTX_MAXCOUNT
- wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+ wl_ext_update_wlfc_maxcount(dhd);
#endif /* PROPTX_MAXCOUNT */
}
else if (event_type == WLC_E_DEAUTH || event_type == WLC_E_DEAUTH_IND ||
#ifdef SET_CARRIER
wl_ext_net_setcarrier(cur_if, FALSE, FALSE);
#endif /* SET_CARRIER */
-#if defined(WLMESH) && defined(WL_ESCAN)
- if (mesh_if && apsta_params->macs)
- wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
-#endif /* WLMESH && WL_ESCAN */
}
}
else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IGO_MODE ||
wl_ext_net_setcarrier(cur_if, TRUE, FALSE);
#endif /* SET_CARRIER */
#ifdef PROPTX_MAXCOUNT
- wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+ wl_ext_update_wlfc_maxcount(dhd);
#endif /* PROPTX_MAXCOUNT */
}
else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
wl_ext_net_setcarrier(cur_if, FALSE, FALSE);
#endif /* SET_CARRIER */
#ifdef PROPTX_MAXCOUNT
- wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+ wl_ext_update_wlfc_maxcount(dhd);
#endif /* PROPTX_MAXCOUNT */
}
else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
event_type, reason);
wl_ext_isam_status(cur_if->dev, NULL, 0);
}
-#if defined(WLMESH) && defined(WL_ESCAN)
- if (cur_if->ifmode == IMESH_MODE && apsta_params->macs)
- wl_mesh_event_handler(apsta_params, cur_if, e, data);
-#endif /* WLMESH && WL_ESCAN */
+ }
+}
+
+void
+wl_ext_iapsta_event(struct net_device *dev, void *argu,
+ const wl_event_msg_t *e, void *data)
+{
+#ifdef ACS_MONITOR
+ struct wl_apsta_params *apsta_params = (struct wl_apsta_params *)argu;
+#endif /* ACS_MONITOR */
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_if_info *cur_if = NULL;
+
+ cur_if = wl_get_cur_if(dev);
+ if (!cur_if || !cur_if->dev) {
+ IAPSTA_DBG(dev->name, "ifidx %d is not ready\n", e->ifidx);
+ return;
}
+ wl_ext_iapsta_link(cur_if, e, data);
#ifdef TPUT_MONITOR
- if (apsta_params->dhd->conf->tput_monitor_ms)
- wl_tput_monitor_handler(apsta_params, cur_if, e, data);
+ if (dhd->conf->tput_monitor_ms)
+ wl_tput_monitor_handler(cur_if, e, data);
#endif /* TPUT_MONITOR */
+#if defined(WLMESH) && defined(WL_ESCAN)
+ wl_mesh_event_handler(cur_if, e, data);
+#endif /* WLMESH && WL_ESCAN */
#ifdef ACS_MONITOR
if ((apsta_params->acs & ACS_DRV_BIT) && apsta_params->acs_tmo)
wl_acs_handler(cur_if, e, data);
#ifdef EAPOL_RESEND
wl_resend_eapol_handler(cur_if, e, data);
#endif /* EAPOL_RESEND */
+#ifdef KEY_INSTALL_CHECK
+ wl_ext_key_install_handler(cur_if, e, data);
+#endif /* KEY_INSTALL_CHECK */
+#ifdef RESTART_AP_WAR
+ wl_ext_restart_ap_handler(cur_if, e, data);
+#endif /* RESTART_AP_WAR */
+#ifdef RESET_AP_WAR
+ wl_ext_reset_ap_handler(cur_if, e, data);
+#endif /* RESET_AP_WAR */
+#ifdef RXF0OVFL_REINIT_WAR
+ wl_ext_rxf0ovfl_reinit_handler(cur_if, e, data);
+#endif /* RXF0OVFL_REINIT_WAR */
return;
}
{" bgnmode ", NULL, NULL},
{" hidden ", NULL, NULL},
{" maxassoc ", NULL, NULL},
+ {" band ", NULL, NULL},
{" chan ", NULL, NULL},
{" amode ", NULL, NULL},
{" emode ", NULL, NULL},
}
} else if (!strcmp(row->name, " maxassoc ")) {
cur_if->maxassoc = (int)simple_strtol(pick_tmp, NULL, 10);
+ } else if (!strcmp(row->name, " band ")) {
+ if (!strcmp(pick_tmp, "2g"))
+ cur_if->amode = WLC_BAND_2G;
+ else if (!strcmp(pick_tmp, "5g"))
+ cur_if->amode = WLC_BAND_5G;
+#ifdef WL_6G_BAND
+ else if (!strcmp(pick_tmp, "6g"))
+ cur_if->amode = WLC_BAND_6G;
+#endif /* WL_6G_BAND */
+ else {
+ IAPSTA_ERROR(cur_if->dev->name, "band [2g|5g|6g]\n");
+ return -1;
+ }
} else if (!strcmp(row->name, " chan ")) {
- cur_if->channel = (int)simple_strtol(pick_tmp, NULL, 10);
+ cur_if->chan_info.chan = (int)simple_strtol(pick_tmp, NULL, 10);
+ if (!cur_if->chan_info.band)
+ cur_if->chan_info.band = WL_GET_BAND(cur_if->chan_info.chan);
} else if (!strcmp(row->name, " amode ")) {
if (!strcmp(pick_tmp, "open"))
cur_if->amode = AUTH_OPEN;
if (i >= 1 && !strlen(cur_if->ifname))
snprintf(cur_if->ifname, IFNAMSIZ, "wlan%d", i);
if (cur_if->ifmode == ISTA_MODE) {
- cur_if->channel = 0;
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, 0);
cur_if->maxassoc = -1;
cur_if->prio = PRIO_STA;
cur_if->vsdb = TRUE;
cur_if->prefix = 'S';
snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
} else if (cur_if->ifmode == IAP_MODE) {
- cur_if->channel = 1;
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, 1);
cur_if->maxassoc = -1;
cur_if->prio = PRIO_AP;
cur_if->vsdb = FALSE;
snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
#ifdef WLMESH
} else if (cur_if->ifmode == IMESH_MODE) {
- cur_if->channel = 1;
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, 1);
cur_if->maxassoc = -1;
cur_if->prio = PRIO_MESH;
cur_if->vsdb = FALSE;
cur_if->prefix = 'M';
snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
-#ifdef WL_ESCAN
- if (i == 0 && apsta_params->macs)
- wl_mesh_escan_attach(dhd, cur_if);
-#endif /* WL_ESCAN */
#endif /* WLMESH */
}
}
}
#endif /* WLMESH */
- wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
apsta_params->init = TRUE;
WL_MSG(dev->name, "apstamode=%d\n", apstamode);
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
apstamode_t apstamode = apsta_params->apstamode;
struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
- uint16 cur_chan;
+ struct wl_chan_info chan_info;
struct wl_conn_info conn_info;
u32 timeout;
if (wl_ext_master_if(cur_if) && apsta_params->acs) {
uint16 chan_2g, chan_5g;
- uint auto_band;
- auto_band = WL_GET_BAND(cur_if->channel);
wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE);
- if ((chan_2g && auto_band == WLC_BAND_2G) ||
- (chan_5g && auto_band == WLC_BAND_5G)) {
- cur_if->channel = wl_ext_autochannel(cur_if->dev, apsta_params->acs,
- auto_band);
+ if ((chan_2g && cur_if->chan_info.band == WLC_BAND_2G) ||
+ (chan_5g && cur_if->chan_info.band == WLC_BAND_5G)) {
+ cur_if->chan_info.chan = wl_ext_autochannel(cur_if->dev, apsta_params->acs,
+ cur_if->chan_info.band);
} else {
IAPSTA_ERROR(ifname, "invalid channel\n");
ret = -1;
wl_ext_move_cur_channel(apsta_params, cur_if);
- if (wl_ext_master_if(cur_if) && !cur_if->channel) {
+ if (wl_ext_master_if(cur_if) && !cur_if->chan_info.chan) {
IAPSTA_ERROR(ifname, "skip channel 0\n");
ret = -1;
goto exit;
}
- cur_chan = wl_ext_get_chan(apsta_params, cur_if->dev);
- if (cur_chan) {
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(cur_if->dev, &chan_info);
+ if (chan_info.chan) {
IAPSTA_INFO(cur_if->ifname, "Associated\n");
- if (cur_chan != cur_if->channel) {
+ if (!wl_ext_same_chan(&cur_if->chan_info, &chan_info)) {
wl_ext_trigger_csa(apsta_params, cur_if);
}
goto exit;
if (wl_ext_master_if(cur_if)) {
wl_ext_set_bgnmode(cur_if);
- if (!cur_if->channel) {
- cur_if->channel = 1;
+ if (!cur_if->chan_info.chan) {
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, 1);
}
- ret = wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver,
- cur_if->channel, &fw_chspec);
+ ret = wl_ext_set_chanspec(cur_if->dev, &cur_if->chan_info, &fw_chspec);
if (ret)
goto exit;
}
wl_ext_set_amode(cur_if);
- wl_ext_set_emode(apsta_params, cur_if);
+ wl_ext_set_emode(cur_if);
if (cur_if->ifmode == ISTA_MODE) {
conn_info.bssidx = cur_if->bssidx;
- conn_info.channel = cur_if->channel;
+ conn_info.channel = cur_if->chan_info.chan;
memcpy(conn_info.ssid.SSID, cur_if->ssid, strlen(cur_if->ssid));
conn_info.ssid.SSID_len = strlen(cur_if->ssid);
memcpy(&conn_info.bssid, &cur_if->bssid, ETHER_ADDR_LEN);
}
int
-wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
+wl_ext_isam_dev_status(struct net_device *dev, ifmode_t ifmode, char prefix,
+ char *dump_buf, int dump_len)
{
- struct dhd_pub *dhd = dhd_get_pub(dev);
- struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- int i;
- struct wl_if_info *tmp_if;
- uint16 chan = 0;
+ struct wl_chan_info chan_info;
wlc_ssid_t ssid = { 0, {0} };
struct ether_addr bssid;
scb_val_t scb_val;
char sec[64];
u32 chanspec = 0;
- char *dump_buf = NULL;
- int dump_len = WLC_IOCTL_MEDLEN;
int dump_written = 0;
+ if (dev) {
+ memset(&ssid, 0, sizeof(ssid));
+ memset(&bssid, 0, sizeof(bssid));
+ memset(&scb_val, 0, sizeof(scb_val));
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ if (wl_ext_associated(dev)) {
+ wl_ext_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
+ wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
+ wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t), 0);
+ chanspec = wl_ext_get_chanspec(dev, &chan_info);
+ wl_ext_get_sec(dev, ifmode, sec, sizeof(sec), FALSE);
+ dump_written += snprintf(dump_buf+dump_written, dump_len,
+ "\n" DHD_LOG_PREFIXS "[%s-%c]: bssid=%pM, chan=%s-%-3d(0x%x %sMHz), "
+ "rssi=%3d, sec=%-20s, SSID=\"%s\"",
+ dev->name, prefix, &bssid,
+ WLCBAND2STR(chan_info.band), chan_info.chan, chanspec,
+ CHSPEC_IS20(chanspec)?"20":
+ CHSPEC_IS40(chanspec)?"40":
+ CHSPEC_IS80(chanspec)?"80":"160",
+ dtoh32(scb_val.val), sec, ssid.SSID);
+ if (ifmode == IAP_MODE) {
+ dump_written += wl_ext_assoclist(dev, NULL,
+ dump_buf+dump_written, dump_len-dump_written);
+ }
+#ifdef WLMESH
+ else if (ifmode == IMESH_MODE) {
+ dump_written += snprintf(dump_buf+dump_written, dump_len, "\n");
+ dump_written += wl_ext_mesh_peer_status(dev, NULL,
+ dump_buf+dump_written, dump_len-dump_written);
+ }
+#endif /* WLMESH */
+ } else {
+ dump_written += snprintf(dump_buf+dump_written, dump_len,
+ "\n" DHD_LOG_PREFIXS "[%s-%c]:", dev->name, prefix);
+ }
+ }
+
+ return dump_written;
+}
+
+int
+wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *cur_if = NULL;
+ char *dump_buf = NULL;
+ int dump_len = WLC_IOCTL_MEDLEN, dump_written = 0;
+ int i;
+
if (command || android_msg_level & ANDROID_INFO_LEVEL) {
if (command) {
dump_buf = command;
dump_len);
return -1;
}
+ memset(dump_buf, 0, dump_len);
}
dump_written += snprintf(dump_buf+dump_written, dump_len,
"apstamode=%d", apsta_params->apstamode);
for (i=0; i<MAX_IF_NUM; i++) {
- memset(&ssid, 0, sizeof(ssid));
- memset(&bssid, 0, sizeof(bssid));
- memset(&scb_val, 0, sizeof(scb_val));
- tmp_if = &apsta_params->if_info[i];
- if (tmp_if->dev) {
- chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
- if (chan) {
- wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
- wldev_ioctl(tmp_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
- wldev_ioctl(tmp_if->dev, WLC_GET_RSSI, &scb_val,
- sizeof(scb_val_t), 0);
- chanspec = wl_ext_get_chanspec(apsta_params, tmp_if->dev);
- wl_ext_get_sec(tmp_if->dev, tmp_if->ifmode, sec, sizeof(sec), FALSE);
- dump_written += snprintf(dump_buf+dump_written, dump_len,
- "\n" DHD_LOG_PREFIXS "[%s-%c]: bssid=%pM, chan=%3d(0x%x %sMHz), "
- "rssi=%3d, sec=%-15s, SSID=\"%s\"",
- tmp_if->ifname, tmp_if->prefix, &bssid, chan, chanspec,
- CHSPEC_IS20(chanspec)?"20":
- CHSPEC_IS40(chanspec)?"40":
- CHSPEC_IS80(chanspec)?"80":"160",
- dtoh32(scb_val.val), sec, ssid.SSID);
- if (tmp_if->ifmode == IAP_MODE) {
- dump_written += snprintf(dump_buf+dump_written, dump_len, "\n");
- dump_written += wl_ext_assoclist(tmp_if->dev, NULL,
- dump_buf+dump_written, dump_len-dump_written);
- }
-#ifdef WLMESH
- else if (tmp_if->ifmode == IMESH_MODE) {
- dump_written += snprintf(dump_buf+dump_written, dump_len, "\n");
- dump_written += wl_ext_mesh_peer_status(tmp_if->dev, NULL,
+ cur_if = &apsta_params->if_info[i];
+ if (cur_if->dev) {
+ dump_written += wl_ext_isam_dev_status(cur_if->dev,
+ cur_if->ifmode, cur_if->prefix,
+ dump_buf+dump_written, dump_len-dump_written);
+ }
+#ifdef WLDWDS
+ if (cur_if->ifmode == IAP_MODE) {
+ for (i=0; i<MAX_DWDS_IF_NUM; i++) {
+ if (apsta_params->dwds_info[i].dev) {
+ dump_written += wl_ext_isam_dev_status(apsta_params->dwds_info[i].dev,
+ IAP_MODE, 'W',
dump_buf+dump_written, dump_len-dump_written);
}
-#endif /* WLMESH */
- } else {
- dump_written += snprintf(dump_buf+dump_written, dump_len,
- "\n" DHD_LOG_PREFIXS "[%s-%c]:", tmp_if->ifname, tmp_if->prefix);
}
}
+#endif /* WLDWDS */
}
IAPSTA_INFO(dev->name, "%s\n", dump_buf);
}
if (apsta_params->acs_tmo != acs_tmo) {
apsta_params->acs_tmo = acs_tmo;
WL_MSG(dev->name, "acs_timer reset to %d\n", acs_tmo);
- wl_ext_mod_timer(&cur_if->acs_timer, acs_tmo, 0);
+ wl_timer_mod(dhd, &cur_if->acs_timer, 0);
}
ret = 0;
} else {
}
// fix me: how to check it's ISTAAP_MODE or IDUALAP_MODE?
- wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
WL_MSG(dev->name, "apstamode=%d\n", apsta_params->apstamode);
for (i=0; i<MAX_IF_NUM; i++) {
if (i == 2 && !strlen(cur_if->ifname))
strcpy(cur_if->ifname, "wlan2");
if (cur_if->ifmode == ISTA_MODE) {
- cur_if->channel = 0;
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, 0);
cur_if->maxassoc = -1;
wl_set_isam_status(cur_if, IF_READY);
cur_if->prio = PRIO_STA;
snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
}
else if (cur_if->ifmode == IAP_MODE) {
- cur_if->channel = 1;
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, 1);
cur_if->maxassoc = -1;
wl_set_isam_status(cur_if, IF_READY);
cur_if->prio = PRIO_AP;
}
#ifdef WLMESH
else if (cur_if->ifmode == IMESH_MODE) {
- cur_if->channel = 1;
+ wl_ext_set_chan_info(cur_if, WLC_BAND_2G, 1);
cur_if->maxassoc = -1;
wl_set_isam_status(cur_if, IF_READY);
cur_if->prio = PRIO_MESH;
if (dhd->conf->fw_type == FW_TYPE_MESH) {
apsta_params->csa |= (CSA_FW_BIT | CSA_DRV_BIT);
}
+ cur_if->ifmode = ISTA_MODE;
+ cur_if->prio = PRIO_STA;
+ cur_if->vsdb = TRUE;
+ cur_if->prefix = 'S';
if (dhd->conf->vndr_ie_assocreq && strlen(dhd->conf->vndr_ie_assocreq))
wl_ext_add_del_ie(net, VNDR_IE_ASSOCREQ_FLAG, dhd->conf->vndr_ie_assocreq, "add");
} else {
if (apsta_params->apstamode != IUNKNOWN_MODE &&
apsta_params->apstamode != ISTAAPAP_MODE &&
apsta_params->apstamode != ISTASTA_MODE) {
- memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN);
- net->dev_addr[0] |= 0x02;
- wl_ext_iapsta_get_vif_macaddr(dhd, ifidx, net->dev_addr);
+ u8 mac_addr[ETH_ALEN];
+ memcpy(mac_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN);
+ mac_addr[0] |= 0x02;
+ wl_ext_iapsta_get_vif_macaddr(dhd, ifidx, mac_addr);
+ dev_addr_set(net, mac_addr);
}
#endif /* WL_STATIC_IF */
}
return 0;
}
+#ifdef WLDWDS
+int
+wl_ext_iapsta_attach_dwds_netdev(struct net_device *net, int ifidx, uint8 bssidx)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *cur_if = NULL;
+ int i;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[ifidx];
+ if (cur_if->bssidx == bssidx) {
+ break;
+ }
+ }
+
+ if (cur_if) {
+ IAPSTA_TRACE(net->name, "ifidx=%d, bssidx=%d\n", ifidx, bssidx);
+ for (i=0; i<MAX_DWDS_IF_NUM; i++) {
+ if (apsta_params->dwds_info[i].dev == NULL) {
+ apsta_params->dwds_info[i].dev = net;
+ apsta_params->dwds_info[i].ifidx = ifidx;
+ apsta_params->dwds_info[i].bssidx = bssidx;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+wl_ext_iapsta_dettach_dwds_netdev(struct net_device *net, int ifidx, uint8 bssidx)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *cur_if = NULL;
+ int i;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[ifidx];
+ if (cur_if->bssidx == bssidx) {
+ break;
+ }
+ }
+
+ if (cur_if) {
+ IAPSTA_TRACE(net->name, "ifidx=%d, bssidx=%d\n", ifidx, bssidx);
+ for (i=0; i<MAX_DWDS_IF_NUM; i++) {
+ if (apsta_params->dwds_info[i].dev == net) {
+ memset(&apsta_params->dwds_info[i], 0, sizeof(struct wl_dwds_info));
+ }
+ }
+ }
+
+ return 0;
+}
+#endif /* WLDWDS */
+
+static void
+wl_ext_iapsta_init_priv(struct net_device *net)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+
+ if (!apsta_params->ioctl_buf) {
+ apsta_params->ioctl_buf = kmalloc(WL_DUMP_BUF_LEN, GFP_KERNEL);
+ if (unlikely(!apsta_params->ioctl_buf)) {
+ IAPSTA_ERROR(net->name, "Can not allocate ioctl_buf\n");
+ }
+ }
+ init_waitqueue_head(&apsta_params->netif_change_event);
+ mutex_init(&apsta_params->usr_sync);
+ mutex_init(&apsta_params->in4way_sync);
+#ifdef STA_MGMT
+ INIT_LIST_HEAD(&apsta_params->sta_list);
+#endif /* STA_MGMT */
+#ifdef EAPOL_RESEND
+ spin_lock_init(&apsta_params->eapol_lock);
+#endif /* EAPOL_RESEND */
+}
+
+static void
+wl_ext_iapsta_deinit_priv(struct net_device *net)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+
+ if (apsta_params->ioctl_buf) {
+ kfree(apsta_params->ioctl_buf);
+ apsta_params->ioctl_buf = NULL;
+ }
+ memset(apsta_params, 0, sizeof(struct wl_apsta_params));
+}
+
int
wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx)
{
struct dhd_pub *dhd = dhd_get_pub(net);
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- struct wl_if_info *cur_if = NULL, *primary_if;
+ struct wl_if_info *cur_if = NULL;
if (ifidx < MAX_IF_NUM) {
IAPSTA_TRACE(net->name, "ifidx=%d, bssidx=%d\n", ifidx, bssidx);
cur_if = &apsta_params->if_info[ifidx];
}
+
if (ifidx == 0) {
- memset(apsta_params, 0, sizeof(struct wl_apsta_params));
- apsta_params->dhd = dhd;
- cur_if->dev = net;
- cur_if->ifidx = ifidx;
- cur_if->bssidx = bssidx;
- cur_if->ifmode = ISTA_MODE;
- cur_if->prio = PRIO_STA;
- cur_if->vsdb = TRUE;
- cur_if->prefix = 'S';
- wl_ext_event_register(net, dhd, WLC_E_LAST, wl_ext_iapsta_event,
- apsta_params, PRIO_EVENT_IAPSTA);
+ wl_ext_iapsta_init_priv(net);
strcpy(cur_if->ifname, net->name);
- init_waitqueue_head(&apsta_params->netif_change_event);
- init_waitqueue_head(&apsta_params->ap_recon_sta_event);
- mutex_init(&apsta_params->usr_sync);
- mutex_init(&apsta_params->in4way_sync);
- mutex_init(&cur_if->pm_sync);
#ifdef TPUT_MONITOR
- init_timer_compat(&apsta_params->monitor_timer, wl_tput_monitor_timer, net);
+ wl_timer_register(net, &apsta_params->monitor_timer, wl_tput_monitor_timer);
#endif /* TPUT_MONITOR */
-#ifdef ACS_MONITOR
- wl_acs_attach(dhd, cur_if);
-#endif /* ACS_MONITOR */
- INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler);
-#ifdef SET_CARRIER
- wl_ext_net_setcarrier(cur_if, FALSE, TRUE);
-#endif /* SET_CARRIER */
- init_timer_compat(&cur_if->connect_timer, wl_ext_connect_timeout, net);
-#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- init_timer_compat(&cur_if->reconnect_timer, wl_ext_reconnect_timeout, net);
-#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
-#ifdef EAPOL_RESEND
- spin_lock_init(&apsta_params->eapol_lock);
- init_timer_compat(&cur_if->eapol_timer, wl_eapol_timer, net);
-#endif /* EAPOL_RESEND */
- } else if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) {
- primary_if = &apsta_params->if_info[IF_PIF];
+#ifdef RXF0OVFL_REINIT_WAR
+ wl_timer_register(net, &apsta_params->rxf0ovfl_timer, wl_ext_rxf0ovfl_reinit_timeout);
+#endif /* RXF0OVFL_REINIT_WAR */
+ }
+
+ if (ifidx == 0 || (cur_if && wl_get_isam_status(cur_if, IF_ADDING))) {
cur_if->dev = net;
cur_if->ifidx = ifidx;
cur_if->bssidx = bssidx;
+ mutex_init(&cur_if->pm_sync);
+ INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler);
+ init_waitqueue_head(&cur_if->ap_recon_sta_event);
wl_ext_event_register(net, dhd, WLC_E_LAST, wl_ext_iapsta_event,
apsta_params, PRIO_EVENT_IAPSTA);
#if defined(WLMESH) && defined(WL_ESCAN)
- if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) {
- wl_mesh_escan_attach(dhd, cur_if);
- }
+ wl_mesh_escan_attach(dhd, cur_if);
#endif /* WLMESH && WL_ESCAN */
#ifdef ACS_MONITOR
wl_acs_attach(dhd, cur_if);
#endif /* ACS_MONITOR */
- mutex_init(&cur_if->pm_sync);
- INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler);
#ifdef SET_CARRIER
wl_ext_net_setcarrier(cur_if, FALSE, TRUE);
#endif /* SET_CARRIER */
- init_timer_compat(&cur_if->connect_timer, wl_ext_connect_timeout, net);
+ wl_timer_register(net, &cur_if->connect_timer, wl_ext_connect_timeout);
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- init_timer_compat(&cur_if->reconnect_timer, wl_ext_reconnect_timeout, net);
+ wl_timer_register(net, &cur_if->reconnect_timer, wl_ext_reconnect_timeout);
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
+#ifdef RESTART_AP_WAR
+ wl_timer_register(net, &cur_if->restart_ap_timer, wl_ext_restart_ap_timeout);
+#endif /* RESTART_AP_WAR */
+#ifdef RESET_AP_WAR
+ wl_timer_register(net, &cur_if->reset_ap_timer, wl_ext_reset_ap_timeout);
+#endif /* RESET_AP_WAR */
#ifdef EAPOL_RESEND
- init_timer_compat(&cur_if->eapol_timer, wl_eapol_timer, net);
+ wl_timer_register(net, &cur_if->eapol_timer, wl_eapol_timer);
#endif /* EAPOL_RESEND */
+#ifdef KEY_INSTALL_CHECK
+ wl_timer_register(net, &cur_if->key_install_timer, wl_ext_key_install_timeout);
+#endif /* KEY_INSTALL_CHECK */
}
return 0;
cur_if = &apsta_params->if_info[ifidx];
}
- if (ifidx == 0) {
-#ifdef EAPOL_RESEND
- wl_ext_release_eapol_txpkt(dhd, ifidx, FALSE);
-#endif /* EAPOL_RESEND */
- wl_ext_mod_timer(&cur_if->connect_timer, 0, 0);
-#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
-#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
-#ifdef SET_CARRIER
- wl_ext_net_setcarrier(cur_if, FALSE, FALSE);
-#endif /* SET_CARRIER */
- wl_ext_add_remove_pm_enable_work(net, FALSE);
-#ifdef ACS_MONITOR
- wl_acs_detach(cur_if);
-#endif /* ACS_MONITOR */
-#ifdef TPUT_MONITOR
- wl_ext_mod_timer(&apsta_params->monitor_timer, 0, 0);
-#endif /* TPUT_MONITOR */
-#if defined(WLMESH) && defined(WL_ESCAN)
- if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) {
- wl_mesh_escan_detach(dhd, cur_if);
- }
-#endif /* WLMESH && WL_ESCAN */
- wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event);
- memset(apsta_params, 0, sizeof(struct wl_apsta_params));
- }
- else if (cur_if && (wl_get_isam_status(cur_if, IF_READY) ||
- wl_get_isam_status(cur_if, IF_ADDING))) {
+ if (ifidx == 0 || (cur_if && (wl_get_isam_status(cur_if, IF_READY) ||
+ wl_get_isam_status(cur_if, IF_ADDING)))) {
#ifdef EAPOL_RESEND
wl_ext_release_eapol_txpkt(dhd, ifidx, FALSE);
#endif /* EAPOL_RESEND */
- wl_ext_mod_timer(&cur_if->connect_timer, 0, 0);
+#ifdef KEY_INSTALL_CHECK
+ wl_timer_deregister(net, &cur_if->key_install_timer);
+#endif /* KEY_INSTALL_CHECK */
+ wl_timer_deregister(net, &cur_if->connect_timer);
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
- wl_ext_mod_timer(&cur_if->reconnect_timer, 0, 0);
+ wl_timer_deregister(net, &cur_if->reconnect_timer);
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
+#ifdef RESTART_AP_WAR
+ wl_timer_deregister(net, &cur_if->restart_ap_timer);
+#endif /* RESTART_AP_WAR */
+#ifdef RESET_AP_WAR
+ wl_timer_deregister(net, &cur_if->reset_ap_timer);
+#endif /* RESET_AP_WAR */
#ifdef SET_CARRIER
wl_ext_net_setcarrier(cur_if, FALSE, FALSE);
#endif /* SET_CARRIER */
wl_acs_detach(cur_if);
#endif /* ACS_MONITOR */
#if defined(WLMESH) && defined(WL_ESCAN)
- if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) {
- wl_mesh_escan_detach(dhd, cur_if);
- }
+ wl_mesh_escan_detach(dhd, cur_if);
#endif /* WLMESH && WL_ESCAN */
wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event);
+#ifdef STA_MGMT
+ wl_ext_flush_sta_list(net, ifidx);
+#endif /* STA_MGMT */
memset(cur_if, 0, sizeof(struct wl_if_info));
}
+ if (ifidx == 0) {
+#ifdef RXF0OVFL_REINIT_WAR
+ wl_timer_deregister(net, &apsta_params->rxf0ovfl_timer);
+#endif /* RXF0OVFL_REINIT_WAR */
+#ifdef TPUT_MONITOR
+ wl_timer_deregister(net, &apsta_params->monitor_timer);
+#endif /* TPUT_MONITOR */
+ wl_ext_iapsta_deinit_priv(net);
+ }
+
return 0;
}
iapsta_params = kzalloc(sizeof(struct wl_apsta_params), GFP_KERNEL);
if (unlikely(!iapsta_params)) {
- IAPSTA_ERROR("wlan", "Could not allocate apsta_params\n");
+ IAPSTA_ERROR(net->name, "Can not allocate apsta_params\n");
return -ENOMEM;
}
dhd->iapsta_params = (void *)iapsta_params;
IAPSTA_TRACE(net->name, "Enter\n");
if (dhd->iapsta_params) {
+ wl_ext_iapsta_deinit_priv(net);
kfree(dhd->iapsta_params);
dhd->iapsta_params = NULL;
}
} ifmode_t;
enum wl_ext_status {
- WL_EXT_STATUS_DISCONNECTING = 0,
+ WL_EXT_STATUS_PRE_DISCONNECTING = 0,
+ WL_EXT_STATUS_DISCONNECTING,
WL_EXT_STATUS_DISCONNECTED,
WL_EXT_STATUS_SCAN,
WL_EXT_STATUS_SCANNING,
WL_EXT_STATUS_CONNECTING,
WL_EXT_STATUS_RECONNECT,
WL_EXT_STATUS_CONNECTED,
+ WL_EXT_STATUS_ROAMED,
WL_EXT_STATUS_ADD_KEY,
+ WL_EXT_STATUS_AP_ENABLING,
WL_EXT_STATUS_AP_ENABLED,
WL_EXT_STATUS_DELETE_STA,
WL_EXT_STATUS_STA_DISCONNECTED,
WL_EXT_STATUS_STA_CONNECTED,
+ WL_EXT_STATUS_AP_DISABLING,
WL_EXT_STATUS_AP_DISABLED
};
void wl_ext_release_eapol_txpkt(dhd_pub_t *dhd, int ifidx, bool rx);
#endif /* EAPOL_RESEND */
void wl_ext_iapsta_get_vif_macaddr(struct dhd_pub *dhd, int ifidx, u8 *mac_addr);
+#ifdef WLDWDS
+int wl_ext_iapsta_attach_dwds_netdev(struct net_device *net, int ifidx, uint8 bssidx);
+int wl_ext_iapsta_dettach_dwds_netdev(struct net_device *net, int ifidx, uint8 bssidx);
+#endif /* WLDWDS */
int wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx);
int wl_ext_iapsta_attach_name(struct net_device *net, int ifidx);
int wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx);
void wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add);
bool wl_ext_iapsta_other_if_enabled(struct net_device *net);
bool wl_ext_sta_connecting(struct net_device *dev);
+void wl_ext_get_chan_str(struct net_device *dev, char *chan_str, int total_len);
+#ifdef DHD_LOSSLESS_ROAMING
+int wl_ext_any_sta_handshaking(struct dhd_pub *dhd);
+#endif /* DHD_LOSSLESS_ROAMING */
void wl_iapsta_wait_event_complete(struct dhd_pub *dhd);
int wl_iapsta_suspend_resume(dhd_pub_t *dhd, int suspend);
#ifdef USE_IW
void wl_ext_iapsta_ifadding(struct net_device *net, int ifidx);
bool wl_ext_iapsta_mesh_creating(struct net_device *net);
void wl_ext_fw_reinit_incsa(struct net_device *dev);
+void wl_ext_send_event_msg(struct net_device *dev, int event, int status,
+ int reason);
+#ifdef BTC_WAR
+void wl_ext_btc_config(struct net_device *dev, bool enable);
+#endif /* BTC_WAR */
+#ifdef STA_MGMT
+bool wl_ext_del_sta_info(struct net_device *net, u8 *bssid);
+bool wl_ext_add_sta_info(struct net_device *net, u8 *bssid);
+#endif /* STA_MGMT */
#ifdef SCAN_SUPPRESS
-uint16 wl_ext_scan_suppress(struct net_device *dev, void *scan_params, bool scan_v2);
+uint16 wl_ext_scan_suppress(struct net_device *dev, void *scan_params, bool scan_v2,
+ struct wl_chan_info *chan_info);
void wl_ext_reset_scan_busy(dhd_pub_t *dhd);
#endif /* SCAN_SUPPRESS */
#endif
#endif /* !WL_ESCAN */
struct pmk_list {
- pmkid_list_t pmkids;
- pmkid_t foo[MAXPMKID - 1];
+ pmkid_list_v1_t pmkids;
+ pmkid_v1_t foo[MAXPMKID - 1];
};
typedef struct wl_wext_info {
index = dhd_net2idx(dhd->info, dev);
if (index == DHD_BAD_IF) {
- WL_ERROR(("Bad ifidx from dev:%p\n", dev));
+ WL_ERROR(("Bad ifidx from %s\n", dev->name));
return -ENODEV;
}
ret = dhd_ioctl_process(dhd, index, &ioc, arg);
#endif /* WIRELESS_EXT < 13 */
#if WIRELESS_EXT > 12
+#ifdef CONFIG_WEXT_PRIV
static int
wl_iw_set_leddc(
struct net_device *dev,
error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
return error;
}
+#endif /* CONFIG_WEXT_PRIV */
#endif /* WIRELESS_EXT > 12 */
int
wl_iw_config_commit(
struct net_device *dev,
struct iw_request_info *info,
- void *zwrq,
+ union iwreq_data *zwrq,
char *extra
)
{
wl_iw_set_freq(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_freq *fwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_freq *fwrq = &wrqu->freq;
int error, chan;
uint sf = 0;
struct dhd_pub *dhd = dhd_get_pub(dev);
wl_iw_get_freq(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_freq *fwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct iw_freq *fwrq = &wrqu->freq;
int error;
- u32 chanspec = 0;
+ chanspec_t chanspec = 0;
int ctl_chan;
WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
- if ((error = dev_wlc_intvar_get(dev, "chanspec", &chanspec)))
+ DHD_CHECK(dhd, dev);
+ if ((error = dev_wlc_intvar_get(dev, "chanspec", (s32 *)&chanspec)))
return error;
+ chanspec = wl_ext_chspec_driver_to_host(dhd, chanspec);
ctl_chan = wf_chspec_ctlchan(chanspec);
/* Return radio channel in channel form */
wl_iw_set_mode(
struct net_device *dev,
struct iw_request_info *info,
- __u32 *uwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
wext_info->conn_info.channel = 0;
}
- switch (*uwrq) {
+ switch (wrqu->mode) {
case IW_MODE_MASTER:
infra = ap = 1;
break;
wl_iw_get_mode(
struct net_device *dev,
struct iw_request_info *info,
- __u32 *uwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
infra = dtoh32(infra);
ap = dtoh32(ap);
- *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
+ wrqu->mode = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
return 0;
}
wl_iw_get_range(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
struct iw_range *range = (struct iw_range *) extra;
static int channels[MAXCHANNEL+1];
wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
wl_iw_set_spy(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wl_iw_t *iw = IW_DEV_IF(dev);
struct sockaddr *addr = (struct sockaddr *) extra;
int i;
wl_iw_get_spy(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wl_iw_t *iw = IW_DEV_IF(dev);
struct sockaddr *addr = (struct sockaddr *) extra;
struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
wl_iw_set_wap(
struct net_device *dev,
struct iw_request_info *info,
- struct sockaddr *awrq,
+ union iwreq_data *wrqu,
char *extra
)
{
WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
DHD_CHECK(dhd, dev);
wext_info = dhd->wext_info;
- if (awrq->sa_family != ARPHRD_ETHER) {
+ if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) {
WL_ERROR(("Invalid Header...sa_family\n"));
return -EINVAL;
}
/* Ignore "auto" or "off" */
- if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
+ if (ETHER_ISBCAST(wrqu->ap_addr.sa_data) || ETHER_ISNULLADDR(wrqu->ap_addr.sa_data)) {
scb_val_t scbval;
bzero(&scbval, sizeof(scb_val_t));
WL_MSG(dev->name, "WLC_DISASSOC\n");
#endif
return 0;
}
- /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data),
+ /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(wrqu->ap_addr.sa_data),
* eabuf)));
*/
/* Reassociate to the specified AP */
if (wext_info)
- memcpy(&wext_info->conn_info.bssid, awrq->sa_data, ETHER_ADDR_LEN);
+ memcpy(&wext_info->conn_info.bssid, wrqu->ap_addr.sa_data, ETHER_ADDR_LEN);
if (wext_info && wext_info->conn_info.ssid.SSID_len) {
if ((error = wl_ext_connect(dev, &wext_info->conn_info)))
return error;
} else {
- if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) {
+ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, wrqu->ap_addr.sa_data, ETHER_ADDR_LEN))) {
WL_ERROR(("WLC_REASSOC failed (%d).\n", error));
return error;
}
- WL_MSG(dev->name, "join BSSID="MACSTR"\n", MAC2STR((u8 *)awrq->sa_data));
+ WL_MSG(dev->name, "join BSSID="MACSTR"\n", MAC2STR((u8 *)wrqu->ap_addr.sa_data));
}
#ifdef WL_EXT_IAPSTA
wl_ext_in4way_sync_wext(dev, STA_NO_BTC_IN4WAY, WL_EXT_STATUS_CONNECTING, NULL);
wl_iw_get_wap(
struct net_device *dev,
struct iw_request_info *info,
- struct sockaddr *awrq,
+ union iwreq_data *wrqu,
char *extra
)
{
WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
- awrq->sa_family = ARPHRD_ETHER;
- memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu->ap_addr.sa_data, 0, ETHER_ADDR_LEN);
/* Ignore error (may be down or disassociated) */
- (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
+ (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, wrqu->ap_addr.sa_data, ETHER_ADDR_LEN);
return 0;
}
wl_iw_mlme(
struct net_device *dev,
struct iw_request_info *info,
- struct sockaddr *awrq,
+ union iwreq_data *wrqu,
char *extra
)
{
wl_iw_get_aplist(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
- wl_scan_results_t *list;
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
+ wl_scan_results_v109_t *list;
struct sockaddr *addr = (struct sockaddr *) extra;
struct iw_quality qual[IW_MAX_AP];
- wl_bss_info_t *bi = NULL;
+ wl_bss_info_v109_t *bi = NULL;
int error, i;
uint buflen = dwrq->length;
int16 rssi;
ASSERT(list->version == WL_BSS_INFO_VERSION);
for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ bi = bi ? (wl_bss_info_v109_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
buflen));
wl_iw_iscan_get_aplist(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
- wl_scan_results_t *list;
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
+ wl_scan_results_v109_t *list;
iscan_buf_t * buf;
iscan_info_t *iscan;
struct sockaddr *addr = (struct sockaddr *) extra;
struct iw_quality qual[IW_MAX_AP];
- wl_bss_info_t *bi = NULL;
+ wl_bss_info_v109_t *bi = NULL;
int i;
int16 rssi;
struct dhd_pub *dhd = dhd_get_pub(dev);
bi = NULL;
for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ bi = bi ? (wl_bss_info_v109_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
WLC_IW_ISCAN_MAXLEN));
)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
- wl_wext_info_t *wext_info = NULL;
wlc_ssid_t ssid;
#ifdef WL_ESCAN
wl_scan_info_t scan_info;
#else
+ wl_wext_info_t *wext_info = NULL;
iscan_info_t *iscan;
#ifdef WL_EXT_IAPSTA
int err;
#endif
DHD_CHECK(dhd, dev);
- wext_info = dhd->wext_info;
#ifdef WL_ESCAN
/* default Broadcast scan */
memset(&ssid, 0, sizeof(ssid));
scan_info.ssid.SSID_len = ssid.SSID_len;
return wl_escan_set_scan(dev, &scan_info);
#else
+ wext_info = dhd->wext_info;
iscan = &wext_info->iscan;
WL_TRACE(("%s: SIOCSIWSCAN iscan=%p\n", dev->name, iscan));
#ifdef WL_EXT_IAPSTA
#endif
int
wl_iw_handle_scanresults_ies(char **event_p, char *end,
- struct iw_request_info *info, wl_bss_info_t *bi)
+ struct iw_request_info *info, wl_bss_info_v109_t *bi)
{
#if WIRELESS_EXT > 17
struct iw_event iwe;
}
#ifdef BCMWAPI_WPI
- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_v109_t);
ptr_len = bi->ie_length;
while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) {
wl_iw_get_scan(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
channel_info_t ci;
- wl_scan_results_t *list;
+ wl_scan_results_v109_t *list;
struct iw_event iwe;
- wl_bss_info_t *bi = NULL;
+ wl_bss_info_v109_t *bi = NULL;
int error, i, j;
char *event = extra, *end = extra + dwrq->length, *value;
uint buflen = dwrq->length;
ASSERT(list->version == WL_BSS_INFO_VERSION);
for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ bi = bi ? (wl_bss_info_v109_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
buflen));
wl_iw_iscan_get_scan(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
struct dhd_pub *dhd = dhd_get_pub(dev);
- wl_wext_info_t *wext_info = NULL;
#ifndef WL_ESCAN
- wl_scan_results_t *list;
+ wl_wext_info_t *wext_info = NULL;
+ wl_scan_results_v109_t *list;
struct iw_event iwe;
- wl_bss_info_t *bi = NULL;
+ wl_bss_info_v109_t *bi = NULL;
int ii, j;
int apcnt;
char *event = extra, *end = extra + dwrq->length, *value;
#endif
DHD_CHECK(dhd, dev);
- wext_info = dhd->wext_info;
#ifdef WL_ESCAN
return wl_escan_get_scan(dev, info, dwrq, extra);
#else
if (!extra)
return -EINVAL;
+ wext_info = dhd->wext_info;
/* use backup if our thread is not successful */
iscan = &wext_info->iscan;
if ((!iscan) || (iscan->sysioc_pid < 0)) {
bi = NULL;
for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ bi = bi ? (wl_bss_info_v109_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
WLC_IW_ISCAN_MAXLEN));
wl_iw_set_essid(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wlc_ssid_t ssid;
int error;
struct dhd_pub *dhd = dhd_get_pub(dev);
wl_iw_get_essid(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wlc_ssid_t ssid;
int error;
/* Max SSID length check */
if (ssid.SSID_len > IW_ESSID_MAX_SIZE) {
ssid.SSID_len = IW_ESSID_MAX_SIZE;
+ /* Get the current SSID */
+ memcpy(extra, ssid.SSID, ssid.SSID_len);
+ /* NULL terminating as length of extra buffer is IW_ESSID_MAX_SIZE ie 32 */
+ extra[IW_ESSID_MAX_SIZE-1] = '\0';
+ } else {
+ /* Get the current SSID */
+ memcpy(extra, ssid.SSID, ssid.SSID_len);
}
- /* Get the current SSID */
- memcpy(extra, ssid.SSID, ssid.SSID_len);
-
- /* NULL terminating as length of extra buffer is IW_ESSID_MAX_SIZE ie 32 */
- extra[IW_ESSID_MAX_SIZE] = '\0';
-
dwrq->length = ssid.SSID_len;
dwrq->flags = 1; /* active */
wl_iw_set_nick(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wl_iw_t *iw = IW_DEV_IF(dev);
WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
wl_iw_get_nick(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wl_iw_t *iw = IW_DEV_IF(dev);
WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
static int wl_iw_set_rate(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->bitrate;
wl_rateset_t rateset;
int error, rate, i, error_bg, error_a;
static int wl_iw_get_rate(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->bitrate;
int error, rate;
WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
wl_iw_set_rts(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->rts;
int error, rts;
WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
wl_iw_get_rts(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->rts;
int error, rts;
WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
wl_iw_set_frag(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->frag;
int error, frag;
WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
wl_iw_get_frag(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->frag;
int error, fragthreshold;
WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
wl_iw_set_txpow(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->txpower;
int error, disable;
uint16 txpwrmw;
WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
wl_iw_get_txpow(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->txpower;
int error, disable, txpwrdbm;
uint8 result;
wl_iw_set_retry(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->retry;
int error, lrl, srl;
WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
wl_iw_get_retry(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->retry;
int error, lrl, srl;
WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
wl_iw_set_encode(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wl_wsec_key_t key;
int error, val, wsec;
wl_iw_get_encode(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wl_wsec_key_t key;
int error, val, wsec, auth;
wl_iw_set_power(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->power;
int error, pm;
WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
wl_iw_get_power(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->power;
int error, pm;
WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
wl_iw_set_wpaie(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *iwp,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *iwp = (struct iw_point *)wrqu;
#if defined(BCMWAPI_WPI)
uchar buf[WLC_IOCTL_SMLEN] = {0};
uchar *p = buf;
wl_iw_get_wpaie(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *iwp,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *iwp = (struct iw_point *)wrqu;
WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
iwp->length = 64;
dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
wl_iw_set_encodeext(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_point *dwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_point *dwrq = (struct iw_point *)wrqu;
wl_wsec_key_t key;
int error;
struct iw_encode_ext *iwe;
wl_iw_set_pmksa(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
struct iw_pmksa *iwpmksa;
uint i;
char eabuf[ETHER_ADDR_STR_LEN];
- pmkid_t *pmkid_array = NULL;
+ pmkid_v1_t *pmkid_array = NULL;
struct dhd_pub *dhd = dhd_get_pub(dev);
wl_wext_info_t *wext_info = NULL;
bzero((char *)pmk_list, sizeof(struct pmk_list));
}
if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
- pmkid_list_t pmkid, *pmkidptr;
+ pmkid_list_v1_t pmkid, *pmkidptr;
pmkidptr = &pmkid;
bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
wl_iw_get_encodeext(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
wl_iw_set_wpaauth(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->param;
int error = 0;
int paramid;
int paramval;
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP: {
- int fbt_cap = 0;
+// int fbt_cap = 0;
if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
iw->pwsec = paramval;
return error;
}
+#if 0
/* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way
* handshake.
*/
}
}
}
+#endif
break;
}
wl_iw_get_wpaauth(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
+ struct iw_param *vwrq = &wrqu->param;
int error;
int paramid;
int paramval = 0;
};
#if WIRELESS_EXT > 12
+#ifdef CONFIG_WEXT_PRIV
enum {
WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV,
WL_IW_SET_VLANMODE,
},
{ 0, 0, 0, { 0 } }
};
+#endif /* CONFIG_WEXT_PRIV */
const struct iw_handler_def wl_iw_handler_def =
{
.num_standard = ARRAYSIZE(wl_iw_handler),
+ .standard = (const iw_handler *) wl_iw_handler,
+#ifdef CONFIG_WEXT_PRIV
.num_private = ARRAY_SIZE(wl_iw_priv_handler),
.num_private_args = ARRAY_SIZE(wl_iw_priv_args),
- .standard = (const iw_handler *) wl_iw_handler,
.private = wl_iw_priv_handler,
.private_args = wl_iw_priv_args,
+#endif /* CONFIG_WEXT_PRIV */
#if WIRELESS_EXT >= 19
get_wireless_stats: dhd_get_wireless_stats,
#endif /* WIRELESS_EXT >= 19 */
int rssi;
scb_val_t scb_val;
#if WIRELESS_EXT > 11
+#ifdef WL_NAN
char *cntbuf = NULL;
wl_cnt_info_t *cntinfo;
uint16 ver;
uint32 corerev = 0;
+#endif
#endif /* WIRELESS_EXT > 11 */
phy_noise = 0;
#endif /* WIRELESS_EXT > 18 */
#if WIRELESS_EXT > 11
+#ifdef WL_NAN
WL_TRACE(("wl_iw_get_wireless_stats counters\n *****"));
cntbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
cntinfo->version = dtoh16(cntinfo->version);
cntinfo->datalen = dtoh16(cntinfo->datalen);
ver = cntinfo->version;
-#ifdef WL_NAN
CHK_CNTBUF_DATALEN(cntbuf, MAX_WLIW_IOCTL_LEN);
-#endif
- if (ver > WL_CNT_T_VERSION) {
+ if (ver > WL_CNT_VERSION_XTLV) {
WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
- WL_CNT_T_VERSION, ver));
+ WL_CNT_VERSION_XTLV, ver));
res = BCME_VERSION;
goto done;
}
corerev = dtoh32(revinfo.corerev);
}
-#ifdef WL_NAN
res = wl_cntbuf_to_xtlv_format(NULL, cntinfo, MAX_WLIW_IOCTL_LEN, corerev);
if (res) {
WL_ERROR(("wl_cntbuf_to_xtlv_format failed %d\n", res));
done:
#if WIRELESS_EXT > 11
+#ifdef WL_NAN
if (cntbuf) {
kfree(cntbuf);
}
+#endif
#endif /* WIRELESS_EXT > 11 */
return res;
}
}
static int
-wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
+wl_iw_iscan_prep(wl_scan_params_v1_t *params, wlc_ssid_t *ssid)
{
int err = 0;
static int
wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
{
- int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
- wl_iscan_params_t *params;
+ int params_size = (WL_SCAN_PARAMS_V1_FIXED_SIZE + OFFSETOF(wl_iscan_params_v1_t, params));
+ wl_iscan_params_v1_t *params;
int err = 0;
if (ssid && ssid->SSID_len) {
params_size += sizeof(wlc_ssid_t);
}
- params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ params = (wl_iscan_params_v1_t*)kmalloc(params_size, GFP_KERNEL);
if (params == NULL) {
return -ENOMEM;
}
params->action = htod16(action);
params->scan_duration = htod16(0);
- /* params_size += OFFSETOF(wl_iscan_params_t, params); */
+ /* params_size += OFFSETOF(wl_iscan_params_v1_t, params); */
(void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
iscan->ioctlbuf, WLC_IOCTL_SMLEN);
}
iscan_buf_t * ptr;
wl_iscan_results_t * list_buf;
wl_iscan_results_t list;
- wl_scan_results_t *results;
+ wl_scan_results_v109_t *results;
uint32 status;
/* buffers are allocated on demand */
wl_iw_autochannel(struct net_device *dev, char* command, int total_len)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
- wl_wext_info_t *wext_info = NULL;
int ret = 0;
#ifdef WL_ESCAN
int bytes_written = -1;
#endif
DHD_CHECK(dhd, dev);
- wext_info = dhd->wext_info;
#ifdef WL_ESCAN
sscanf(command, "%*s %d", &dhd->escan->autochannel);
if (dhd->escan->autochannel == 0) {
n++;
}
- WL_DBG((" %s: 0x%04X\n", __FUNCTION__, channels[0]));
+ WL_SCAN(("0x%04X\n", channels[0]));
#ifdef WES_SUPPORT
if (cfg->roamscan_mode == ROAMSCAN_MODE_WES) {
ch = wf_chspec_ctlchan(ch) | CHSPEC_BAND(ch) | band_bw;
if (band_match && !is_duplicated_channel(channels, n, ch)) {
- WL_DBG(("%s: Chanspec = %s\n", __FUNCTION__,
+ WL_SCAN(("Chanspec = %s\n",
wf_chspec_ntoa_ex(ch, chanbuf)));
channels[n++] = ch;
if (n >= n_channels) {
band_match && !is_duplicated_channel(channels, n, ch) &&
(memcmp(roam_cache[i].ssid, ssid->SSID, ssid->SSID_len) == 0)) {
/* match found, add it */
- WL_DBG(("%s: Chanspec = %s\n", __FUNCTION__,
+ WL_SCAN(("Chanspec = %s\n",
wf_chspec_ntoa_ex(ch, chanbuf)));
channels[n++] = ch;
if (n >= n_channels) {
--- /dev/null
+#include <wl_android.h>\r
+#ifdef WL_TIMER\r
+\r
+#define TIMER_ERROR(name, arg1, args...) \\r
+ do { \\r
+ if (android_msg_level & ANDROID_ERROR_LEVEL) { \\r
+ printf("[%s] TIMER-ERROR) %s : " arg1, name, __func__, ## args); \\r
+ } \\r
+ } while (0)\r
+#define TIMER_TRACE(name, arg1, args...) \\r
+ do { \\r
+ if (android_msg_level & ANDROID_TRACE_LEVEL) { \\r
+ printf("[%s] TIMER-TRACE) %s : " arg1, name, __func__, ## args); \\r
+ } \\r
+ } while (0)\r
+\r
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \\r
+ 4 && __GNUC_MINOR__ >= 6))\r
+#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \\r
+_Pragma("GCC diagnostic push") \\r
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \\r
+(entry) = list_first_entry((ptr), type, member); \\r
+_Pragma("GCC diagnostic pop") \\r
+\r
+#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \\r
+_Pragma("GCC diagnostic push") \\r
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \\r
+entry = container_of((ptr), type, member); \\r
+_Pragma("GCC diagnostic pop") \\r
+\r
+#else\r
+#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \\r
+(entry) = list_first_entry((ptr), type, member); \\r
+\r
+#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \\r
+entry = container_of((ptr), type, member); \\r
+\r
+#endif /* STRICT_GCC_WARNINGS */\r
+\r
+typedef void(*FUNC_HANDLER) (void *cb_argu);\r
+\r
+struct wl_func_q {\r
+ struct list_head eq_list;\r
+ FUNC_HANDLER cb_func;\r
+ void *cb_argu;\r
+};\r
+\r
+typedef void(*TIMER_HANDLER) (void *cb_argu);\r
+\r
+typedef struct timer_handler_list {\r
+ struct list_head list;\r
+ struct net_device *net;\r
+ timer_list_compat_t *timer;\r
+ TIMER_HANDLER cb_func;\r
+ void *cb_argu;\r
+ uint tmo_ms;\r
+ ulong tmo_jiffies;\r
+} timer_handler_list_t;\r
+\r
+typedef struct wl_timer_params {\r
+ dhd_pub_t *pub;\r
+ struct list_head timer_list;\r
+ struct list_head eq_list;\r
+ timer_list_compat_t timer;\r
+ spinlock_t eq_lock;\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ struct workqueue_struct *timer_workq;\r
+ struct work_struct timer_work;\r
+ struct workqueue_struct *func_workq;\r
+ struct work_struct func_work;\r
+#else\r
+ tsk_ctl_t thr_timer_ctl;\r
+ tsk_ctl_t thr_func_ctl;\r
+#endif\r
+} wl_timer_params_t;\r
+\r
+static unsigned long\r
+wl_func_lock_eq(struct wl_timer_params *timer_params)\r
+{\r
+ unsigned long flags;\r
+\r
+ spin_lock_irqsave(&timer_params->eq_lock, flags);\r
+ return flags;\r
+}\r
+\r
+static void\r
+wl_func_unlock_eq(struct wl_timer_params *timer_params, unsigned long flags)\r
+{\r
+ spin_unlock_irqrestore(&timer_params->eq_lock, flags);\r
+}\r
+\r
+static void\r
+wl_func_init_eq_lock(struct wl_timer_params *timer_params)\r
+{\r
+ spin_lock_init(&timer_params->eq_lock);\r
+}\r
+\r
+static void\r
+wl_func_init_eq(struct wl_timer_params *timer_params)\r
+{\r
+ wl_func_init_eq_lock(timer_params);\r
+ INIT_LIST_HEAD(&timer_params->eq_list);\r
+}\r
+\r
+static void\r
+wl_func_flush_eq(struct wl_timer_params *timer_params)\r
+{\r
+ struct wl_func_q *e;\r
+ unsigned long flags;\r
+\r
+ flags = wl_func_lock_eq(timer_params);\r
+ while (!list_empty_careful(&timer_params->eq_list)) {\r
+ BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);\r
+ list_del(&e->eq_list);\r
+ kfree(e);\r
+ }\r
+ wl_func_unlock_eq(timer_params, flags);\r
+}\r
+\r
+static struct wl_func_q *\r
+wl_func_deq(struct wl_timer_params *timer_params)\r
+{\r
+ struct wl_func_q *e = NULL;\r
+ unsigned long flags;\r
+\r
+ flags = wl_func_lock_eq(timer_params);\r
+ if (likely(!list_empty(&timer_params->eq_list))) {\r
+ BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);\r
+ list_del(&e->eq_list);\r
+ }\r
+ wl_func_unlock_eq(timer_params, flags);\r
+\r
+ return e;\r
+}\r
+\r
+static s32\r
+wl_func_enq(struct wl_timer_params *timer_params,\r
+ void *cb_func, void *cb_argu)\r
+{\r
+ struct wl_func_q *e;\r
+ s32 err = 0;\r
+ uint32 funcq_size;\r
+ unsigned long flags;\r
+ gfp_t aflags;\r
+\r
+ funcq_size = sizeof(struct wl_func_q);\r
+ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;\r
+ e = kzalloc(funcq_size, aflags);\r
+ if (unlikely(!e)) {\r
+ TIMER_ERROR("wlan", "funcq_size alloc failed %d\n", funcq_size);\r
+ return -ENOMEM;\r
+ }\r
+ e->cb_func = cb_func;\r
+ e->cb_argu = cb_argu;\r
+ flags = wl_func_lock_eq(timer_params);\r
+ list_add_tail(&e->eq_list, &timer_params->eq_list);\r
+ wl_func_unlock_eq(timer_params, flags);\r
+\r
+ return err;\r
+}\r
+\r
+static void\r
+wl_func_put(struct wl_func_q *e)\r
+{\r
+ kfree(e);\r
+}\r
+\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+static void wl_func_handler(struct work_struct *data);\r
+#define WL_FUNC_HANDLER() static void wl_func_handler(struct work_struct *data)\r
+#else\r
+static int wl_func_handler(void *data);\r
+#define WL_FUNC_HANDLER() static int wl_func_handler(void *data)\r
+#endif\r
+\r
+WL_FUNC_HANDLER()\r
+{\r
+ struct wl_timer_params *timer_params = NULL;\r
+ struct wl_func_q *e;\r
+ struct net_device *net = NULL;\r
+ dhd_pub_t *dhd;\r
+ unsigned long flags = 0;\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;\r
+ timer_params = (struct wl_timer_params *)tsk->parent;\r
+#else\r
+ BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, func_work);\r
+#endif\r
+\r
+ dhd = timer_params->pub;\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
+ while (1) {\r
+ if (down_interruptible(&tsk->sema) == 0) {\r
+ SMP_RD_BARRIER_DEPENDS();\r
+ if (tsk->terminated) {\r
+ break;\r
+ }\r
+#endif\r
+ DHD_EVENT_WAKE_LOCK(dhd);\r
+ while ((e = wl_func_deq(timer_params))) {\r
+ DHD_GENERAL_LOCK(dhd, flags);\r
+ if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {\r
+ TIMER_ERROR(net->name, "BUS is DOWN.\n");\r
+ DHD_GENERAL_UNLOCK(dhd, flags);\r
+ goto fail;\r
+ }\r
+ DHD_GENERAL_UNLOCK(dhd, flags);\r
+ e->cb_func(e->cb_argu);\r
+fail:\r
+ wl_func_put(e);\r
+ }\r
+ DHD_EVENT_WAKE_UNLOCK(dhd);\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ complete_and_exit(&tsk->completed, 0);\r
+#endif\r
+}\r
+\r
+void\r
+wl_func_send(void *params, void *cb_func, void *cb_argu)\r
+{\r
+ struct wl_timer_params *timer_params = params;\r
+\r
+ if (timer_params == NULL) {\r
+ TIMER_ERROR("wlan", "Stale ignored\n");\r
+ return;\r
+ }\r
+\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ if (timer_params->func_workq == NULL) {\r
+ TIMER_ERROR("wlan", "Event handler is not created\n");\r
+ return;\r
+ }\r
+#endif\r
+\r
+ if (likely(!wl_func_enq(timer_params, cb_func, cb_argu))) {\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ queue_work(timer_params->func_workq, &timer_params->func_work);\r
+#else\r
+ if (timer_params->thr_func_ctl.thr_pid >= 0) {\r
+ up(&timer_params->thr_func_ctl.sema);\r
+ }\r
+#endif\r
+ }\r
+}\r
+\r
+static s32\r
+wl_func_create_handler(struct wl_timer_params *timer_params)\r
+{\r
+ int ret = 0;\r
+ TIMER_TRACE("wlan", "Enter\n");\r
+\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ if (!timer_params->func_workq) {\r
+ timer_params->func_workq = alloc_workqueue("timer_funcd",\r
+ WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);\r
+ }\r
+ if (!timer_params->func_workq) {\r
+ TIMER_ERROR("wlan", "func_workq alloc_workqueue failed\n");\r
+ ret = -ENOMEM;\r
+ } else {\r
+ INIT_WORK(&timer_params->func_work, wl_func_handler);\r
+ }\r
+#else\r
+ PROC_START(wl_func_handler, timer_params, &timer_params->thr_func_ctl, 0, "timer_funcd");\r
+ if (timer_params->thr_func_ctl.thr_pid < 0) {\r
+ ret = -ENOMEM;\r
+ }\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+static void\r
+wl_func_destroy_handler(struct wl_timer_params *timer_params)\r
+{\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ if (timer_params && timer_params->func_workq) {\r
+ cancel_work_sync(&timer_params->func_work);\r
+ destroy_workqueue(timer_params->func_workq);\r
+ timer_params->func_workq = NULL;\r
+ }\r
+#else\r
+ if (timer_params->thr_func_ctl.thr_pid >= 0) {\r
+ PROC_STOP(&timer_params->thr_func_ctl);\r
+ }\r
+#endif\r
+}\r
+\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+static void wl_timer_handler(struct work_struct *data);\r
+#define WL_TIMER_HANDLER() static void wl_timer_handler(struct work_struct *data)\r
+#else\r
+static int wl_timer_handler(void *data);\r
+#define WL_TIMER_HANDLER() static int wl_timer_handler(void *data)\r
+#endif\r
+\r
+WL_TIMER_HANDLER()\r
+{\r
+ struct wl_timer_params *timer_params = NULL;\r
+ struct timer_handler_list *node, *next;\r
+ dhd_pub_t *dhd;\r
+ unsigned long flags = 0;\r
+ unsigned long cur_jiffies, diff_jiffies, min_jiffies = 0;\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;\r
+ timer_params = (struct wl_timer_params *)tsk->parent;\r
+#else\r
+ BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, timer_work);\r
+#endif\r
+\r
+ dhd = timer_params->pub;\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
+ while (1) {\r
+ if (down_interruptible(&tsk->sema) == 0) {\r
+ SMP_RD_BARRIER_DEPENDS();\r
+ if (tsk->terminated) {\r
+ break;\r
+ }\r
+#endif\r
+ DHD_EVENT_WAKE_LOCK(dhd);\r
+ DHD_GENERAL_LOCK(dhd, flags);\r
+ if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {\r
+ TIMER_ERROR("wlan", "BUS is DOWN.\n");\r
+ DHD_GENERAL_UNLOCK(dhd, flags);\r
+ goto exit;\r
+ }\r
+ DHD_GENERAL_UNLOCK(dhd, flags);\r
+ cur_jiffies = jiffies;\r
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
+ if (node->tmo_ms) {\r
+ if (time_after(cur_jiffies, node->tmo_jiffies)) {\r
+ wl_func_send(timer_params, node->cb_func, node->cb_argu);\r
+ node->tmo_ms = 0;\r
+ } else {\r
+ diff_jiffies = node->tmo_jiffies - cur_jiffies;\r
+ if (min_jiffies == 0)\r
+ min_jiffies = diff_jiffies;\r
+ else if (diff_jiffies < min_jiffies)\r
+ min_jiffies = diff_jiffies;\r
+ }\r
+ }\r
+ }\r
+ if (min_jiffies)\r
+ mod_timer(&timer_params->timer, jiffies + min_jiffies);\r
+exit:\r
+ DHD_EVENT_WAKE_UNLOCK(dhd);\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ complete_and_exit(&tsk->completed, 0);\r
+#endif\r
+}\r
+\r
+void\r
+wl_timer_kick_handler(wl_timer_params_t *timer_params)\r
+{\r
+ if (timer_params == NULL) {\r
+ TIMER_ERROR("wlan", "timer_params not ready\n");\r
+ return;\r
+ }\r
+\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ if (timer_params->timer_workq == NULL) {\r
+ TIMER_ERROR("wlan", "timer handler is not created\n");\r
+ return;\r
+ }\r
+ queue_work(timer_params->timer_workq, &timer_params->timer_work);\r
+#else\r
+ if (timer_params->thr_timer_ctl.thr_pid >= 0) {\r
+ up(&timer_params->thr_timer_ctl.sema);\r
+ }\r
+#endif\r
+}\r
+\r
+static void\r
+wl_timer_timeout(unsigned long data)\r
+{\r
+ struct wl_timer_params *timer_params = (struct wl_timer_params *)data;\r
+\r
+ if (!timer_params) {\r
+ TIMER_ERROR("wlan", "timer_params is not ready\n");\r
+ return;\r
+ }\r
+\r
+ TIMER_TRACE("wlan", "timer expired\n");\r
+ wl_timer_kick_handler(timer_params);\r
+}\r
+\r
+static s32\r
+wl_timer_create_handler(struct wl_timer_params *timer_params)\r
+{\r
+ int ret = 0;\r
+\r
+ TIMER_TRACE("wlan", "Enter\n");\r
+ \r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ if (!timer_params->timer_workq) {\r
+ timer_params->timer_workq = alloc_workqueue("timerd",\r
+ WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);\r
+ }\r
+ if (!timer_params->timer_workq) {\r
+ TIMER_ERROR("wlan", "timer_workq alloc_workqueue failed\n");\r
+ ret = -ENOMEM;\r
+ } else {\r
+ INIT_WORK(&timer_params->timer_work, wl_timer_handler);\r
+ }\r
+#else\r
+ PROC_START(wl_timer_handler, timer_params, &timer_params->thr_timer_ctl, 0, "timerd");\r
+ if (timer_params->thr_timer_ctl.thr_pid < 0) {\r
+ ret = -ENOMEM;\r
+ }\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+static void\r
+wl_timer_destroy_handler(struct wl_timer_params *timer_params)\r
+{\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+ if (timer_params && timer_params->timer_workq) {\r
+ cancel_work_sync(&timer_params->timer_work);\r
+ destroy_workqueue(timer_params->timer_workq);\r
+ timer_params->timer_workq = NULL;\r
+ }\r
+#else\r
+ if (timer_params->thr_timer_ctl.thr_pid >= 0) {\r
+ PROC_STOP(&timer_params->thr_timer_ctl);\r
+ }\r
+#endif\r
+}\r
+\r
+static void\r
+wl_timer_free(struct wl_timer_params *timer_params)\r
+{\r
+ timer_handler_list_t *node, *next;\r
+\r
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
+ TIMER_TRACE(node->net->name, "Free timer\n");\r
+ list_del(&node->list);\r
+ kfree(node);\r
+ }\r
+}\r
+\r
+void\r
+wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)\r
+{\r
+ wl_timer_params_t *timer_params = dhd->timer_params;\r
+ timer_handler_list_t *node, *next;\r
+ bool found = FALSE;\r
+\r
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
+ if (node->timer == timer) {\r
+ node->tmo_ms = tmo_ms;\r
+ if (tmo_ms) {\r
+ TIMER_TRACE(node->net->name, "update timer %dms\n", tmo_ms);\r
+ node->tmo_jiffies = jiffies + msecs_to_jiffies(tmo_ms);\r
+ wl_timer_kick_handler(timer_params);\r
+ }\r
+ found = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ if (!found)\r
+ TIMER_ERROR("wlan", "timer not found\n");\r
+}\r
+\r
+void\r
+wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)\r
+{\r
+ dhd_pub_t *dhd = dhd_get_pub(net);\r
+ wl_timer_params_t *timer_params = dhd->timer_params;\r
+ timer_handler_list_t *node, *next, *leaf;\r
+\r
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
+ if (node->timer == timer) {\r
+ TIMER_TRACE(net->name, "timer already registered\n");\r
+ return;\r
+ }\r
+ }\r
+\r
+ leaf = kmalloc(sizeof(timer_handler_list_t), GFP_KERNEL);\r
+ if (!leaf) {\r
+ TIMER_ERROR(net->name, "Memory alloc failure %d\n",\r
+ (int)sizeof(timer_handler_list_t));\r
+ return;\r
+ }\r
+ memset(leaf, 0, sizeof(timer_handler_list_t));\r
+ leaf->net = net;\r
+ leaf->timer = timer;\r
+ leaf->cb_func = cb_func;\r
+ leaf->cb_argu = net;\r
+ TIMER_ERROR(net->name, "timer registered tmo=%d\n", leaf->tmo_ms);\r
+ list_add_tail(&leaf->list, &timer_params->timer_list);\r
+\r
+ return;\r
+}\r
+\r
+void\r
+wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)\r
+{\r
+ dhd_pub_t *dhd = dhd_get_pub(net);\r
+ wl_timer_params_t *timer_params = dhd->timer_params;\r
+ timer_handler_list_t *node, *next;\r
+\r
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
+ if (node->timer == timer) {\r
+ TIMER_TRACE(net->name, "timer deregistered\n");\r
+ list_del(&node->list);\r
+ kfree(node);\r
+ }\r
+ }\r
+ return;\r
+}\r
+\r
+static s32\r
+wl_timer_init_priv(struct wl_timer_params *timer_params)\r
+{\r
+ s32 err = 0;\r
+\r
+ INIT_LIST_HEAD(&timer_params->timer_list);\r
+ if (wl_timer_create_handler(timer_params))\r
+ return -ENOMEM;\r
+ wl_func_init_eq(timer_params);\r
+ if (wl_func_create_handler(timer_params))\r
+ return -ENOMEM;\r
+\r
+ return err;\r
+}\r
+\r
+static void\r
+wl_timer_deinit_priv(struct wl_timer_params *timer_params)\r
+{\r
+ wl_timer_free(timer_params);\r
+ wl_func_destroy_handler(timer_params);\r
+ wl_func_flush_eq(timer_params);\r
+ wl_timer_destroy_handler(timer_params);\r
+}\r
+\r
+void\r
+wl_timer_dettach(dhd_pub_t *dhdp)\r
+{\r
+ struct wl_timer_params *timer_params = dhdp->timer_params;\r
+\r
+ if (timer_params) {\r
+ if (timer_pending(&timer_params->timer))\r
+ del_timer_sync(&timer_params->timer);\r
+ wl_timer_deinit_priv(timer_params);\r
+ kfree(timer_params);\r
+ dhdp->timer_params = NULL;\r
+ }\r
+}\r
+\r
+s32\r
+wl_timer_attach(struct net_device *net)\r
+{\r
+ struct dhd_pub *dhdp = dhd_get_pub(net);\r
+ struct wl_timer_params *timer_params = NULL;\r
+ s32 err = 0;\r
+\r
+ timer_params = kmalloc(sizeof(wl_timer_params_t), GFP_KERNEL);\r
+ if (!timer_params) {\r
+ TIMER_ERROR(net->name, "Failed to allocate memory (%zu)\n",\r
+ sizeof(wl_timer_params_t));\r
+ return -ENOMEM;\r
+ }\r
+ dhdp->timer_params = timer_params;\r
+ memset(timer_params, 0, sizeof(wl_timer_params_t));\r
+ timer_params->pub = dhdp;\r
+\r
+ err = wl_timer_init_priv(timer_params);\r
+ if (err) {\r
+ TIMER_ERROR(net->name, "Failed to wl_timer_init_priv (%d)\n", err);\r
+ goto exit;\r
+ }\r
+ init_timer_compat(&timer_params->timer, wl_timer_timeout, timer_params);\r
+\r
+exit:\r
+ if (err)\r
+ wl_timer_dettach(dhdp);\r
+ return err;\r
+}\r
+#else\r
+void\r
+wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)\r
+{\r
+ if (timer_pending(timer))\r
+ del_timer_sync(timer);\r
+ if (tmo_ms)\r
+ mod_timer(timer, jiffies + msecs_to_jiffies(tmo_ms));\r
+}\r
+\r
+void\r
+wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)\r
+{\r
+ init_timer_compat(timer, cb_func, net);\r
+}\r
+\r
+void\r
+wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)\r
+{\r
+ if (timer_pending(timer))\r
+ del_timer_sync(timer);\r
+}\r
+#endif\r
--- /dev/null
+#ifndef _wl_timer_\r
+#define _wl_timer_\r
+s32 wl_timer_attach(struct net_device *net);\r
+void wl_timer_dettach(dhd_pub_t *dhdp);\r
+void wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func);\r
+void wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer);\r
+void wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms);\r
+#endif\r
int wldev_set_country(
struct net_device *dev, char *country_code, bool notify, int revinfo)
{
+ int error = 0;
#if defined(BCMDONGLEHOST)
- int error = -1;
- wl_country_t cspec = {{0}, 0, {0}};
+ struct dhd_pub *dhd = dhd_get_pub(dev);
if (!country_code)
- return error;
-
- cspec.rev = revinfo;
- strlcpy(cspec.country_abbrev, country_code, WL_CCODE_LEN + 1);
- strlcpy(cspec.ccode, country_code, WL_CCODE_LEN + 1);
- error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec);
- if (error)
- dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);
- error = dhd_conf_set_country(dhd_get_pub(dev), &cspec);
- if (error < 0) {
- WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n",
- __FUNCTION__, country_code, cspec.ccode, cspec.rev));
- return error;
- }
- dhd_conf_fix_country(dhd_get_pub(dev));
- dhd_conf_get_country(dhd_get_pub(dev), &cspec);
- dhd_bus_country_set(dev, &cspec, notify);
+ return -1;
+ error = dhd_conf_country(dhd, "country", country_code);
+ dhd_bus_country_set(dev, &dhd->dhd_cspec, notify);
printf("%s: set country for %s as %s rev %d\n",
- __FUNCTION__, country_code, cspec.ccode, cspec.rev);
+ __FUNCTION__, country_code, dhd->dhd_cspec.ccode, dhd->dhd_cspec.rev);
#endif /* defined(BCMDONGLEHOST) */
- return 0;
+ return error;
}