ifeq ($(CONFIG_BCMDHD_SDIO),y)
MODULE_NAME := dhd
else
+ifeq ($(CONFIG_BCMDHD_USB),y)
MODULE_NAME := bcmdhd
+else
+MODULE_NAME := dhdpci
+endif
endif
#CONFIG_BCMDHD := m
#CONFIG_BCMDHD_SDIO := y
-DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \
-DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DDHDTCPACK_SUPPRESS \
-DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT \
- -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP \
+ -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP -DDHD_8021X_DUMP \
-DPOWERUP_MAX_RETRY=0 -DIFACE_HANG_FORCE_DEV_CLOSE -DWAIT_DEQUEUE \
- -DWL_EXT_IAPSTA -DWL_ESCAN \
+ -DWL_EXT_IAPSTA -DWL_ESCAN -DCCODE_LIST \
-DENABLE_INSMOD_NO_FW_LOAD \
-I$(src) -I$(src)/include
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 \
- dhd_linux_exportfs.o dhd_linux_pktdump.o \
- dhd_config.o wl_event.o wl_android_ext.o wl_escan.o
+ dhd_linux_exportfs.o dhd_linux_pktdump.o \
+ dhd_config.o dhd_ccode.o wl_event.o wl_android_ext.o wl_escan.o
+
+ifneq ($(CONFIG_WIRELESS_EXT),)
+ DHDOFILES += wl_iw.o
+ DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW
+endif
+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
+ DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT
+ DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
+ DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10
+ DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL
+ DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES
+ 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 += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP
+ DHDCFLAGS += -DDHD_USE_SCAN_WAKELOCK
+ DHDCFLAGS += -DWL_STATIC_IF
+# DHDCFLAGS += -DWL_SAE
+endif
#BCMDHD_SDIO
ifneq ($(CONFIG_BCMDHD_SDIO),)
DHDCFLAGS += -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \
-DSDTEST -DBDC -DDHD_USE_IDLECOUNT -DCUSTOM_SDIO_F2_BLKSIZE=256 \
-DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DRXFRAME_THREAD \
- -DBCMSDIO_RXLIM_POST
+ -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS \
+ -DBCMSDIO_RXLIM_POST -DCONSOLE_DPC
ifeq ($(CONFIG_BCMDHD_OOB),y)
DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB
ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y)
-DDONGLE_ENABLE_ISOLATION
DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_STATS -DDHD_LB_TXP
DHDCFLAGS += -DDHD_PKTID_AUDIT_ENABLED
+ifeq ($(CONFIG_BCMDHD_OOB),y)
+ DHDCFLAGS += -DCUSTOMER_OOB -DBCMPCIE_OOB_HOST_WAKE
+endif
ifneq ($(CONFIG_PCI_MSI),)
- DHDCFLAGS += -DDHD_USE_MSI
+ DHDCFLAGS += -DDHD_MSI_SUPPORT
endif
+DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB
+DHDCFLAGS += -DSET_RPS_CPUS -DSET_XPS_CPUS
+DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15
+DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10
+DHDCFLAGS += -DDHDTCPACK_SUPPRESS
+DHDCFLAGS += -DDHD_DISABLE_ASPM
+
DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \
dhd_msgbuf.o dhd_linux_lb.o
endif
DHDCFLAGS += -DPROP_TXSTATUS
endif
ifneq ($(CONFIG_BCMDHD_SDIO),)
- DHDCFLAGS += -DPROP_TXSTATUS
+ DHDCFLAGS += -DPROP_TXSTATUS -DPROPTX_MAXCOUNT
endif
ifneq ($(CONFIG_CFG80211),)
DHDCFLAGS += -DPROP_TXSTATUS_VSDB
endif
DHDCFLAGS += -DDHD_UPDATE_INTF_MAC
DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS))
- DHDCFLAGS :=$(filter-out -DSET_RANDOM_MAC_SOFTAP,$(DHDCFLAGS))
+ DHDCFLAGS :=$(filter-out -DWL_STATIC_IF,$(DHDCFLAGS))
endif
ifeq ($(CONFIG_WL_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 -DWL_STATIC_IF -DWLDWDS -DFOURADDR_AUTO_BRG
+endif
+
+#CSI_SUPPORT
+ifneq ($(CONFIG_CSI_SUPPORT),)
+ DHDCFLAGS += -DCSI_SUPPORT
+ DHDOFILES += dhd_csi.o
endif
obj-$(CONFIG_BCMDHD) += $(MODULE_NAME).o
DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT
endif
DHDCFLAGS += -DCUSTOMER_HW_AMLOGIC
+
+# for config custom MAC
+# DHDCFLAGS += -DGET_CUSTOM_MAC_ENABLE -DCUSTOM_MULTI_MAC
+# if also need config AP MAC
+# DHDCFLAGS += -DCUSTOM_AP_MAC
+#
+
# DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI
endif
ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y)
# obj-m += dhd_static_buf.o
DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF
- DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -DCONFIG_DHD_USE_STATIC_BUF
+ DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF
+ DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP
endif
-ifneq ($(CONFIG_WIRELESS_EXT),)
- DHDOFILES += wl_iw.o
- DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW
-endif
-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
- DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT
- DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
- DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10
- DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL
- DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES
- 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 += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP
- DHDCFLAGS += -DDHD_USE_SCAN_WAKELOCK
- DHDCFLAGS += -DWL_STATIC_IF
-endif
EXTRA_CFLAGS = $(DHDCFLAGS)
ifeq ($(CONFIG_BCMDHD),m)
EXTRA_LDFLAGS += --strip-debug
} bcmsdh_os_info_t;
/* debugging macros */
+#define SDLX_ERR(x) printf x
#define SDLX_MSG(x) printf x
/**
bcmsdh = bcmsdh_attach(osh, sdioh, ®s);
if (bcmsdh == NULL) {
- SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
+ SDLX_ERR(("%s: bcmsdh_attach failed\n", __FUNCTION__));
goto err;
}
bcmsdh_osinfo = MALLOC(osh, sizeof(bcmsdh_os_info_t));
if (bcmsdh_osinfo == NULL) {
- SDLX_MSG(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__));
+ SDLX_ERR(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__));
goto err;
}
bzero((char *)bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
bcmsdh_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter_info,
&bcmsdh_osinfo->oob_irq_flags);
if (bcmsdh_osinfo->oob_irq_num < 0) {
- SDLX_MSG(("%s: Host OOB irq is not defined\n", __FUNCTION__));
+ SDLX_ERR(("%s: Host OOB irq is not defined\n", __FUNCTION__));
goto err;
}
#endif /* defined(BCMLXSDMMC) */
bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num,
slot_num, 0, bus_type, (void *)regs, osh, bcmsdh);
if (bcmsdh_osinfo->context == NULL) {
- SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
+ SDLX_ERR(("%s: device attach failed\n", __FUNCTION__));
goto err;
}
SDLX_MSG(("%s: register client driver\n", __FUNCTION__));
error = bcmsdh_register_client_driver();
if (error)
- SDLX_MSG(("%s: failed %d\n", __FUNCTION__, error));
+ SDLX_ERR(("%s: failed %d\n", __FUNCTION__, error));
return error;
}
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
if (bcmsdh_osinfo->oob_irq_registered) {
- SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__));
+ SDLX_ERR(("%s: irq is already registered\n", __FUNCTION__));
return -EBUSY;
}
#ifdef HW_OOB
- printf("%s: HW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
- (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags);
+ SDLX_MSG(("%s: HW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
+ (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
#else
- printf("%s: SW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
- (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags);
+ SDLX_MSG(("%s: SW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
+ (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
#endif
bcmsdh_osinfo->oob_irq_handler = oob_irq_handler;
bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context;
err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
if (err) {
- SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err));
+ SDLX_ERR(("%s: request_irq failed with %d\n", __FUNCTION__, err));
bcmsdh_osinfo->oob_irq_enabled = FALSE;
bcmsdh_osinfo->oob_irq_registered = FALSE;
return err;
#endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */
err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num);
if (err)
- SDLX_MSG(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err));
+ SDLX_ERR(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err));
else
bcmsdh_osinfo->oob_irq_wake_enabled = TRUE;
#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI)
* a restriction on max tx/glom count (based on host->max_segs).
*/
if (sg_count >= ARRAYSIZE(sd->sg_list)) {
+ sd_err(("%s: sg list entries(%u) exceed limit(%zu),"
+ " sd blk_size=%u\n",
+ __FUNCTION__, sg_count, (size_t)ARRAYSIZE(sd->sg_list), blk_size));
return (SDIOH_API_RC_FAIL);
}
pdata += pkt_offset;
pkt_len += blk_size - (pkt_len % blk_size);
if ((write) && (!fifo))
- err_ret = sdio_memcpy_toio(
- sd->func[func],
- addr, buf, pkt_len);
+ err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, pkt_len);
else if (write)
- err_ret = sdio_memcpy_toio(
- sd->func[func],
- addr, buf, pkt_len);
+ err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, pkt_len);
else if (fifo)
- err_ret = sdio_readsb(
- sd->func[func],
- buf, addr, pkt_len);
+ err_ret = sdio_readsb(sd->func[func], buf, addr, pkt_len);
else
- err_ret = sdio_memcpy_fromio(
- sd->func[func],
- buf, addr, pkt_len);
+ err_ret = sdio_memcpy_fromio(sd->func[func], buf, addr, pkt_len);
if (err_ret)
sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n",
}
#endif /* !__STDC_WANT_SECURE_LIB__ && !(__STDC_LIB_EXT1__ && __STDC_WANT_LIB_EXT1__) */
-#if !defined(FREEBSD) && !defined(BCM_USE_PLATFORM_STRLCPY)
+#if 0
/**
* strlcpy - Copy a %NUL terminated string into a sized buffer
* @dest: Where to copy the string to
if ((flags & mask) == bit) {
if (len > (int)strlen(name)) {
slen = (int)strlen(name);
- strncpy(buf, name, (size_t)slen+1);
+ strncpy(buf, name, (size_t)len);
}
break;
}
if (len <= slen)
break;
/* copy NULL char but don't count it */
- strncpy(p, name, (size_t)nlen + 1);
+ strncpy(p, name, (size_t)len);
p += nlen;
/* copy btwn flag space and NULL char */
if (flags != 0)
bus->dhd->clm_path = pclm_path;
bus->dhd->conf_path = pconf_path;
- dhd_conf_set_path_params(bus->dhd, NULL, NULL, bus->fw_path, bus->nv_path);
+ dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
}
#if defined(CONFIG_HAS_WAKELOCK)
#include <linux/wakelock.h>
#endif /* defined CONFIG_HAS_WAKELOCK */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
+#include <uapi/linux/sched/types.h>
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/types.h>
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */
/* The kernel threading is sdio-specific */
void *pktcnts;
#endif /* DHD_PKTDUMP_ROAM */
bool disable_dtim_in_suspend; /* Disable set bcn_li_dtim in suspend */
+#ifdef CSI_SUPPORT
+ struct list_head csi_list;
+ int csi_count;
+#endif /* CSI_SUPPORT */
char *clm_path; /* module_param: path to clm vars file */
char *conf_path; /* module_param: path to config vars file */
struct dhd_conf *conf; /* Bus module handle */
extern uint android_msg_level;
extern uint config_msg_level;
extern uint sd_msglevel;
+extern uint dump_msg_level;
#ifdef BCMDBUS
extern uint dbus_msglevel;
#endif /* BCMDBUS */
void* dhd_get_fwdump_buf(dhd_pub_t *dhd_pub, uint32 length);
#endif /* DHD_FW_COREDUMP */
+#if defined(SET_XPS_CPUS)
+int dhd_xps_cpus_enable(struct net_device *net, int enable);
+int custom_xps_map_set(struct net_device *net, char *buf, size_t len);
+void custom_xps_map_clear(struct net_device *net);
+#endif
+
#if defined(SET_RPS_CPUS)
int dhd_rps_cpus_enable(struct net_device *net, int enable);
int custom_rps_map_set(struct netdev_rx_queue *queue, char *buf, size_t len);
#define RPS_CPUS_MASK_IBSS "10"
#define RPS_CPUS_WLAN_CORE_ID 4
#else
-#define RPS_CPUS_MASK "6"
-#define RPS_CPUS_MASK_P2P "6"
-#define RPS_CPUS_MASK_IBSS "6"
+#define RPS_CPUS_MASK "f"
+#define RPS_CPUS_MASK_P2P "f"
+#define RPS_CPUS_MASK_IBSS "f"
#endif /* CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 */
#endif // endif
/* Device console input function */
extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#ifdef CONSOLE_DPC
+extern int dhd_bus_txcons(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#endif
/* Deferred processing for the bus, return TRUE requests reschedule */
extern bool dhd_bus_dpc(struct dhd_bus *bus);
--- /dev/null
+\r
+#ifdef CCODE_LIST\r
+#ifdef CONFIG_COMPAT\r
+#include <linux/compat.h>\r
+#endif /* COMFIG_COMPAT */\r
+#include <typedefs.h>\r
+#include <dhd_config.h>\r
+\r
+#ifdef BCMSDIO\r
+#define CCODE_43438\r
+#define CCODE_43455C0\r
+#define CCODE_43456C5\r
+#endif\r
+#if defined(BCMSDIO) || defined(BCMPCIE)\r
+#define CCODE_4356A2\r
+#define CCODE_4359C0\r
+#endif\r
+#ifdef BCMDBUS\r
+#define CCODE_4358U\r
+#endif\r
+\r
+#ifdef BCMSDIO\r
+#ifdef CCODE_43438\r
+const char ccode_43438[] = "RU/13";\r
+#else\r
+const char ccode_43438 = "";\r
+#endif\r
+\r
+#ifdef CCODE_43455C0\r
+const char ccode_43455c0[] = \\r
+"AE/6 AG/2 AI/1 AL/2 AS/12 AT/4 AU/6 AW/2 AZ/2 "\\r
+"BA/2 BD/1 BE/4 BG/4 BH/4 BM/12 BN/4 BR/2 BS/2 BY/3 "\\r
+"CA/2 CA/31 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\\r
+"DE/3 DE/7 DK/4 "\\r
+"EC/21 EE/4 EG/13 ES/4 ET/2 "\\r
+"FI/4 FR/5 "\\r
+"GB/1 GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/30 "\\r
+"HK/2 HR/4 HU/4 "\\r
+"ID/1 IE/5 IL/14 IN/3 IS/4 IT/4 "\\r
+"JO/3 JP/45 JP/58 "\\r
+"KH/2 KR/45 KR/48 KR/49 KR/70 KR/71 KR/96 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\\r
+"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MQ/2 MR/2 MT/4 MU/2 MV/3 MW/1 MX/44 MY/3 "\\r
+"NI/2 NL/4 NO/4 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PH/5 PL/4 PR/38 PT/4 PY/2 "\\r
+"Q2/993 "\\r
+"RE/2 RO/4 RS/2 RU/13 "\\r
+"SE/4 SI/4 SK/4 SV/25 "\\r
+"TH/5 TN/1 TR/7 TT/3 TW/1 "\\r
+"UA/8 US/988 "\\r
+"VA/2 VE/3 VG/2 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZA/6";\r
+#else\r
+const char ccode_43455c0[] = "";\r
+#endif\r
+\r
+#ifdef CCODE_43456C5\r
+const char ccode_43456c5[] = \\r
+"AE/6 AG/2 AI/1 AL/2 AS/12 AT/4 AU/6 AW/2 AZ/2 "\\r
+"BA/2 BD/1 BE/4 BG/4 BH/4 BM/12 BN/4 BR/4 BS/2 BY/3 "\\r
+"CA/2 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\\r
+"DE/7 DK/4 "\\r
+"EC/21 EE/4 EG/13 ES/4 ET/2 "\\r
+"FI/4 FR/5 "\\r
+"GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/30 "\\r
+"HK/2 HR/4 HU/4 "\\r
+"ID/1 IE/5 IL/14 IN/3 IS/4 IT/4 "\\r
+"JO/3 JP/58 "\\r
+"KH/2 KR/96 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\\r
+"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MQ/2 MR/2 MT/4 MU/2 MV/3 MW/1 MX/44 MY/3 "\\r
+"NI/2 NL/4 NO/4 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PH/5 PL/4 PR/38 PT/4 PY/2 "\\r
+"Q2/993 "\\r
+"RE/2 RO/4 RS/2 RU/13 "\\r
+"SE/4 SI/4 SK/4 SV/25 "\\r
+"TH/5 TN/1 TR/7 TT/3 TW/65 "\\r
+"UA/8 US/988 "\\r
+"VA/2 VE/3 VG/2 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZA/6";\r
+#else\r
+const char ccode_43456c5[] = "";\r
+#endif\r
+#endif\r
+\r
+#ifdef CCODE_4356A2\r
+const char ccode_4356a2[] = \\r
+"AE/6 AG/2 AI/1 AL/2 AN/2 AR/21 AS/12 AT/4 AU/6 AW/2 AZ/2 "\\r
+"BA/2 BD/2 BE/4 BG/4 BH/4 BM/12 BN/4 BR/4 BS/2 BY/3 "\\r
+"CA/31 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\\r
+"DE/7 DK/4 DZ/1 "\\r
+"EC/21 EE/4 ES/4 ET/2 "\\r
+"FI/4 FR/5 "\\r
+"GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/12 "\\r
+"HK/2 HR/4 HU/4 "\\r
+"ID/13 IE/5 IL/7 IN/28 IS/4 IT/4 "\\r
+"JO/3 JP/58 "\\r
+"KH/2 KR/57 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\\r
+"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MO/2 MR/2 MT/4 MQ/2 MU/2 MV/3 MW/1 MX/20 MY/16 "\\r
+"NI/2 NL/4 NO/4 NP/3 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PG/2 PH/5 PL/4 PR/20 PT/4 PY/2 "\\r
+"RE/2 RO/4 RS/2 RU/986 "\\r
+"SE/4 SG/4 SG/19 SI/4 SK/4 SN/2 SV/19 "\\r
+"TH/9 TN/1 TR/7 TT/3 TW/1 "\\r
+"UA/8 UG/2 US/1 UY/1 "\\r
+"VA/2 UA/16 VE/3 VG/2 VI/13 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZM/2 "\\r
+"E0/32";\r
+#else\r
+const char ccode_4356a2[] = "";\r
+#endif\r
+\r
+#ifdef CCODE_4359C0\r
+const char ccode_4359c0[] = \\r
+"AD/1 AE/6 AG/2 AI/1 AL/3 AS/12 AT/21 AU/6 AW/2 AZ/8 "\\r
+"BA/4 BD/1 BE/19 BG/18 BH/4 BM/12 BN/4 BR/2 BS/2 BY/3 "\\r
+"CN/38 CO/17 CR/17 CY/18 CZ/18 "\\r
+"DE/30 DK/19 "\\r
+"E0/32 EC/21 EE/18 EG/13 ES/21 ET/2 "\\r
+"FI/19 FR/21 "\\r
+"GB/996 GD/2 GE/1 GF/2 GP/2 GR/18 GT/1 GU/30 "\\r
+"HK/2 HR/18 HU/18 "\\r
+"ID/1 IE/21 IL/14 IN/3 IS/17 IT/20 "\\r
+"JO/3 JP/967 "\\r
+"KH/2 KR/70 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/17 LI/4 LK/1 LS/2 LT/18 LU/18 LV/18 "\\r
+"MA/2 MC/2 MD/3 ME/5 MK/4 MN/1 MQ/2 MR/2 MT/18 MU/2 MV/3 MW/1 MX/44 MY/3 "\\r
+"NI/2 NL/19 NO/18 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PH/5 PL/18 PR/38 PT/20 PY/2 "\\r
+"Q1/947 Q2/993 "\\r
+"RE/2 RO/18 RS/4 RU/986 "\\r
+"SE/19 SI/18 SK/18 SM/1 SV/25 "\\r
+"TH/5 TN/1 TR/18 TT/3 TW/1 "\\r
+"UA/16 US/988 "\\r
+"VA/3 VE/3 VG/2 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZA/6";\r
+#else\r
+const char ccode_4359c0[] = "";\r
+#endif\r
+\r
+#ifdef CCODE_4358U\r
+const char ccode_4358u[] = \\r
+"BE/4 BR/4 CA/2 CH/4 CN/38 CY/4 DE/7 DK/4 ES/4 "\\r
+"FI/4 FR/5 GB/6 GR/4 HK/2 HU/4 IE/5 IL/7 IS/4 "\\r
+"IT/4 JP/72 KE/0 MY/3 NL/4 PT/4 SA/5 SE/4 SG/0 "\\r
+"SZ/0 TH/5 TR/7 TW/230 US/0 VN/4";\r
+#else\r
+const char ccode_4358u[] = "";\r
+#endif\r
+\r
+typedef struct ccode_list_map_t {\r
+ uint chip;\r
+ uint chiprev;\r
+ const char *ccode_list;\r
+ const char *ccode_ww;\r
+} ccode_list_map_t;\r
+\r
+extern const char ccode_43438[];\r
+extern const char ccode_43455c0[];\r
+extern const char ccode_43456c5[];\r
+extern const char ccode_4356a2[];\r
+extern const char ccode_4359c0[];\r
+extern const char ccode_4358u[];\r
+\r
+const ccode_list_map_t ccode_list_map[] = {\r
+ /* ChipID Chiprev ccode */\r
+#ifdef BCMSDIO\r
+ {BCM43430_CHIP_ID, 0, ccode_43438, ""},\r
+ {BCM43430_CHIP_ID, 1, ccode_43438, ""},\r
+ {BCM4345_CHIP_ID, 6, ccode_43455c0, "XZ/11"},\r
+ {BCM43454_CHIP_ID, 6, ccode_43455c0, "XZ/11"},\r
+ {BCM4345_CHIP_ID, 9, ccode_43456c5, "XZ/11"},\r
+ {BCM43454_CHIP_ID, 9, ccode_43456c5, "XZ/11"},\r
+ {BCM4354_CHIP_ID, 2, ccode_4356a2, "XZ/11"},\r
+ {BCM4356_CHIP_ID, 2, ccode_4356a2, "XZ/11"},\r
+ {BCM4371_CHIP_ID, 2, ccode_4356a2, "XZ/11"},\r
+ {BCM4359_CHIP_ID, 9, ccode_4359c0, "XZ/11"},\r
+#endif\r
+#ifdef BCMPCIE\r
+ {BCM4354_CHIP_ID, 2, ccode_4356a2, "XZ/11"},\r
+ {BCM4356_CHIP_ID, 2, ccode_4356a2, "XZ/11"},\r
+ {BCM4359_CHIP_ID, 9, ccode_4359c0, "XZ/11"},\r
+#endif\r
+#ifdef BCMDBUS\r
+ {BCM43569_CHIP_ID, 2, ccode_4358u, "XW/0"},\r
+#endif\r
+};\r
+\r
+int\r
+dhd_ccode_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)\r
+{\r
+ int bcmerror = -1, i;\r
+ uint chip = dhd->conf->chip, chiprev = dhd->conf->chiprev; \r
+ const char *ccode_list = NULL, *ccode_ww = NULL;\r
+ char *pch;\r
+\r
+ for (i=0; i<sizeof(ccode_list_map)/sizeof(ccode_list_map[0]); i++) {\r
+ const ccode_list_map_t* row = &ccode_list_map[i];\r
+ if (row->chip == chip && row->chiprev == chiprev) {\r
+ ccode_list = row->ccode_list;\r
+ ccode_ww = row->ccode_ww;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (ccode_list) {\r
+ pch = strstr(ccode_list, cspec->ccode);\r
+ if (pch) {\r
+ cspec->rev = (int)simple_strtol(pch+strlen(cspec->ccode)+1, NULL, 0);\r
+ bcmerror = 0;\r
+ }\r
+ }\r
+\r
+ if (bcmerror && ccode_ww && strlen(ccode_ww)>=4) {\r
+ memcpy(cspec->ccode, ccode_ww, 2);\r
+ cspec->rev = (int)simple_strtol(ccode_ww+3, NULL, 0);\r
+ }\r
+\r
+ return bcmerror;\r
+}\r
+#endif\r
#ifdef DHD_LOG_PRINT_RATE_LIMIT
int log_print_threshold = 0;
#endif /* DHD_LOG_PRINT_RATE_LIMIT */
-int dhd_msg_level = DHD_ERROR_VAL;// | DHD_FWLOG_VAL | DHD_EVENT_VAL
+int dhd_msg_level = DHD_ERROR_VAL | DHD_FWLOG_VAL;// | DHD_EVENT_VAL
/* For CUSTOMER_HW4 do not enable DHD_IOVAR_MEM_VAL by default */
// | DHD_PKT_MON_VAL;
#include <linux/pm_runtime.h>
#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */
+#ifdef CSI_SUPPORT
+#include <dhd_csi.h>
+#endif /* CSI_SUPPORT */
+
#ifdef SOFTAP
char fw_path2[MOD_PARAM_PATHLEN];
extern bool softap_enabled;
#if defined(DHD_DEBUG)
case IOV_SVAL(IOV_CONS):
- if (len > 0)
+ if (len > 0) {
+#ifdef CONSOLE_DPC
+ bcmerror = dhd_bus_txcons(dhd_pub, arg, len - 1);
+#else
bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+#endif
+ }
break;
#endif /* DHD_DEBUG */
#endif /* !BCMDBUS */
break;
}
default:
- DHD_INFO(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
+ DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
event_name, event_type, eabuf, (int)status, (int)reason,
(int)auth_type));
break;
}
break;
#endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */
+#if defined(CSI_SUPPORT)
+ case WLC_E_CSI:
+ dhd_csi_event_handler(dhd_pub, event, (void *)event_data);
+ break;
+#endif /* CSI_SUPPORT */
case WLC_E_LINK:
#ifdef PCIE_FULL_DONGLE
if (dhd_update_interface_link_status(dhd_pub, (uint8)dhd_ifname2idx(dhd_pub->info,
}
}
+ if (dhd->conf->suspend_bcn_li_dtim >= 0)
+ bcn_li_dtim = dhd->conf->suspend_bcn_li_dtim;
DHD_ERROR(("%s beacon=%d bcn_li_dtim=%d DTIM=%d Listen=%d\n",
__FUNCTION__, *bcn_interval, bcn_li_dtim, *dtim_period, CUSTOM_LISTEN_INTERVAL));
if (bcn_li_dtim == 0) {
bcn_li_dtim = 1;
}
- bcn_li_dtim = MAX(dhd->suspend_bcn_li_dtim, bcn_li_dtim);
} else {
/* attemp to use platform defined dtim skip interval */
bcn_li_dtim = dhd->suspend_bcn_li_dtim;
/* message levels */\r
#define CONFIG_ERROR_LEVEL (1 << 0)\r
#define CONFIG_TRACE_LEVEL (1 << 1)\r
-#define CONFIG_MSG_LEVEL (1 << 15)\r
+#define CONFIG_MSG_LEVEL (1 << 0)\r
\r
uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL;\r
+uint dump_msg_level = 0;\r
\r
#define CONFIG_MSG(x, args...) \\r
do { \\r
#define CONFIG_TRACE(x, args...) \\r
do { \\r
if (config_msg_level & CONFIG_TRACE_LEVEL) { \\r
- printk(KERN_ERR "[dhd] CONFIG-TRACE) %s : " x, __func__, ## args); \\r
+ printk(KERN_INFO "[dhd] CONFIG-TRACE) %s : " x, __func__, ## args); \\r
} \\r
} while (0)\r
\r
-#define MAXSZ_BUF 1000\r
-#define MAXSZ_CONFIG 4096\r
+#define MAXSZ_BUF 4096\r
+#define MAXSZ_CONFIG 8192\r
\r
#ifndef WL_CFG80211\r
#define htod32(i) i\r
#define dtohchanspec(i) i\r
#endif\r
\r
-#if defined(SUSPEND_EVENT) && defined(PROP_TXSTATUS)\r
-#if defined(BCMSDIO) || defined(BCMDBUS)\r
+#if defined(PROP_TXSTATUS)\r
#include <dhd_wlfc.h>\r
-#endif /* BCMSDIO || BCMDBUS */\r
-#endif /* SUSPEND_EVENT && PROP_TXSTATUS */\r
+#endif /* PROP_TXSTATUS */\r
\r
#define MAX_EVENT_BUF_NUM 16\r
typedef struct eventmsg_buf {\r
{BCM43430_CHIP_ID, 2, DONT_CARE, "bcm43436b0", "ap6236"},\r
{BCM43012_CHIP_ID, 1, FW_TYPE_G, "bcm43013b0", ""},\r
{BCM43012_CHIP_ID, 1, FW_TYPE_AG, "bcm43013c0_ag", ""},\r
+ {BCM43012_CHIP_ID, 2, DONT_CARE, "bcm43013c1_ag", ""},\r
{BCM4334_CHIP_ID, 3, DONT_CARE, "bcm4334b1_ag", ""},\r
{BCM43340_CHIP_ID, 2, DONT_CARE, "bcm43341b0_ag", ""},\r
{BCM43341_CHIP_ID, 2, DONT_CARE, "bcm43341b0_ag", ""},\r
#endif\r
};\r
\r
+void\r
+dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)\r
+{\r
+ CONFIG_TRACE("called\n");\r
+\r
+ if (chip_nv_list->m_chip_nv_path_head) {\r
+ CONFIG_TRACE("Free %p\n", chip_nv_list->m_chip_nv_path_head);\r
+ kfree(chip_nv_list->m_chip_nv_path_head);\r
+ }\r
+ chip_nv_list->count = 0;\r
+}\r
+\r
#ifdef BCMSDIO\r
void\r
dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)\r
mac_list->count = 0;\r
}\r
\r
-void\r
-dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)\r
-{\r
- CONFIG_TRACE("called\n");\r
-\r
- if (chip_nv_list->m_chip_nv_path_head) {\r
- CONFIG_TRACE("Free %p\n", chip_nv_list->m_chip_nv_path_head);\r
- kfree(chip_nv_list->m_chip_nv_path_head);\r
- }\r
- chip_nv_list->count = 0;\r
-}\r
-\r
#if defined(HW_OOB) || defined(FORCE_WOWLAN)\r
void\r
dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih)\r
#endif\r
\r
#define SBSDIO_CIS_SIZE_LIMIT 0x200\r
-#define F0_BLOCK_SIZE 32\r
-int\r
-dhd_conf_set_blksize(bcmsdh_info_t *sdh)\r
-{\r
- int err = 0;\r
- uint fn, numfn;\r
- int32 blksize = 0, cur_blksize = 0;\r
- uint8 cisd;\r
-\r
- numfn = bcmsdh_query_iofnum(sdh);\r
-\r
- for (fn = 0; fn <= numfn; fn++) {\r
- if (!fn)\r
- blksize = F0_BLOCK_SIZE;\r
- else {\r
- bcmsdh_cisaddr_read(sdh, fn, &cisd, 24);\r
- blksize = cisd;\r
- bcmsdh_cisaddr_read(sdh, fn, &cisd, 25);\r
- blksize |= cisd << 8;\r
- }\r
-#ifdef CUSTOM_SDIO_F2_BLKSIZE\r
- if (fn == 2 && blksize > CUSTOM_SDIO_F2_BLKSIZE) {\r
- blksize = CUSTOM_SDIO_F2_BLKSIZE;\r
- }\r
-#endif\r
- bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32),\r
- &cur_blksize, sizeof(int32), FALSE);\r
- if (cur_blksize != blksize) {\r
- CONFIG_MSG("fn=%d, blksize=%d, cur_blksize=%d\n",\r
- fn, blksize, cur_blksize);\r
- blksize |= (fn<<16);\r
- if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &blksize,\r
- sizeof(blksize), TRUE) != BCME_OK) {\r
- CONFIG_ERROR("fail on get sd_blocksize");\r
- err = -1;\r
- }\r
- }\r
- }\r
-\r
- return err;\r
-}\r
-\r
-int\r
-dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac)\r
+void\r
+dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih)\r
{\r
int i, err = -1;\r
- uint8 *ptr = 0;\r
+ uint8 *ptr = 0, *ptpl_code = NULL;\r
unsigned char tpl_code, tpl_link='\0';\r
- uint8 header[3] = {0x80, 0x07, 0x19};\r
+ uint8 mac_header[3] = {0x80, 0x07, 0x19};\r
uint8 *cis;\r
\r
if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) {\r
CONFIG_ERROR("cis malloc failed\n");\r
- return err;\r
}\r
bzero(cis, SBSDIO_CIS_SIZE_LIMIT);\r
\r
if ((err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT))) {\r
CONFIG_ERROR("cis read err %d\n", err);\r
MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
- return err;\r
+ return;\r
}\r
- err = -1; // reset err;\r
ptr = cis;\r
do {\r
/* 0xff means we're done */\r
tpl_code = *ptr;\r
+ ptpl_code = ptr;\r
ptr++;\r
if (tpl_code == 0xff)\r
break;\r
if (tpl_link == 0xff)\r
break;\r
if (config_msg_level & CONFIG_TRACE_LEVEL) {\r
- CONFIG_MSG("tpl_code=0x%02x, tpl_link=0x%02x, tag=0x%02x\n",\r
- tpl_code, tpl_link, *ptr);\r
- printk("%s: value:", __FUNCTION__);\r
- for (i=0; i<tpl_link-1; i++) {\r
- printk("%02x ", ptr[i+1]);\r
- if ((i+1) % 16 == 0)\r
- printk("\n");\r
- }\r
- printk("\n");\r
+ prhex("TPL", ptpl_code, tpl_link+2);\r
}\r
\r
- if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19)\r
- break;\r
+ if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) {\r
+ memcpy(&dhd->conf->otp_mac, ptr+1, 6);\r
+ }\r
+#ifdef GET_OTP_MODULE_NAME\r
+ else if (tpl_code == 0x8e && *ptr == 0x41) {\r
+ int len = tpl_link - 1;\r
+ if (len <= sizeof(dhd->conf->module_name) - 1) {\r
+ strncpy(dhd->conf->module_name, ptr+1, len);\r
+ CONFIG_MSG("module_name=%s\n", dhd->conf->module_name);\r
+ } else {\r
+ CONFIG_ERROR("len is too long %d >= %d\n",\r
+ len, (int)sizeof(dhd->conf->module_name) - 1);\r
+ }\r
+ }\r
+#endif\r
\r
ptr += tpl_link;\r
} while (1);\r
\r
- if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) {\r
- /* Normal OTP */\r
- memcpy(mac, ptr+1, 6);\r
- err = 0;\r
- } else {\r
+ if (!memcmp(ðer_null, &dhd->conf->otp_mac, ETHER_ADDR_LEN)) {\r
ptr = cis;\r
/* Special OTP */\r
if (bcmsdh_reg_read(sdh, SI_ENUM_BASE(sih), 4) == 0x16044330) {\r
for (i=0; i<SBSDIO_CIS_SIZE_LIMIT; i++) {\r
- if (!memcmp(header, ptr, 3)) {\r
- memcpy(mac, ptr+3, 6);\r
- err = 0;\r
+ if (!memcmp(mac_header, ptr, 3)) {\r
+ memcpy(&dhd->conf->otp_mac, ptr+3, 6);\r
break;\r
}\r
ptr++;\r
\r
ASSERT(cis);\r
MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
-\r
- return err;\r
}\r
\r
void\r
-dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,\r
- si_t *sih, char *fw_path)\r
+dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, char *fw_path)\r
{\r
int i, j;\r
- uint8 mac[6]={0};\r
+ uint8 *mac = (uint8 *)&dhd->conf->otp_mac;\r
int fw_num=0, mac_num=0;\r
uint32 oui, nic;\r
wl_mac_list_t *mac_list;\r
if (!mac_list || !fw_num)\r
return;\r
\r
- if (dhd_conf_get_mac(dhd, sdh, sih, mac)) {\r
- CONFIG_ERROR("Can not read MAC address\n");\r
- return;\r
- }\r
oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
\r
}\r
\r
void\r
-dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,\r
- si_t *sih, char *nv_path)\r
+dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, char *nv_path)\r
{\r
int i, j;\r
- uint8 mac[6]={0};\r
+ uint8 *mac = (uint8 *)&dhd->conf->otp_mac;\r
int nv_num=0, mac_num=0;\r
uint32 oui, nic;\r
wl_mac_list_t *mac_list;\r
if (!mac_list || !nv_num)\r
return;\r
\r
- if (dhd_conf_get_mac(dhd, sdh, sih, mac)) {\r
- CONFIG_ERROR("Can not read MAC address\n");\r
- return;\r
- }\r
oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
\r
#endif\r
\r
void\r
-dhd_conf_free_country_list(conf_country_list_t *country_list)\r
+dhd_conf_free_country_list(struct dhd_conf *conf)\r
{\r
- int i;\r
+ country_list_t *country = conf->country_head;\r
+ int count = 0;\r
\r
CONFIG_TRACE("called\n");\r
- for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
- if (country_list->cspec[i]) {\r
- CONFIG_TRACE("Free cspec %p\n", country_list->cspec[i]);\r
- kfree(country_list->cspec[i]);\r
- country_list->cspec[i] = NULL;\r
- }\r
+ while (country) {\r
+ CONFIG_TRACE("Free cspec %s\n", country->cspec.country_abbrev);\r
+ conf->country_head = country->next;\r
+ kfree(country);\r
+ country = conf->country_head;\r
+ count++;\r
+ }\r
+ CONFIG_TRACE("%d country released\n", count);\r
+}\r
+\r
+void\r
+dhd_conf_free_mchan_list(struct dhd_conf *conf)\r
+{\r
+ mchan_params_t *mchan = conf->mchan;\r
+ int count = 0;\r
+\r
+ CONFIG_TRACE("called\n");\r
+ while (mchan) {\r
+ CONFIG_TRACE("Free cspec %p\n", mchan);\r
+ conf->mchan = mchan->next;\r
+ kfree(mchan);\r
+ mchan = conf->mchan;\r
+ count++;\r
}\r
+ CONFIG_TRACE("%d mchan released\n", count);\r
}\r
\r
int\r
}\r
}\r
#ifndef FW_PATH_AUTO_SELECT\r
- return;\r
+ return DONT_CARE;\r
#endif\r
\r
/* find out the last '/' */\r
for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {\r
const cihp_name_map_t* row = &chip_name_map[i];\r
if (row->chip == chip && row->chiprev == chiprev &&\r
- (row->ag_type == ag_type || row->ag_type == DONT_CARE) &&\r
- strlen(row->module_name)) {\r
- strcpy(name_ptr, "nvram_");\r
- strcat(name_ptr, row->module_name);\r
+ (row->ag_type == ag_type || row->ag_type == DONT_CARE)) {\r
+#ifdef GET_OTP_MODULE_NAME\r
+ if (strlen(dhd->conf->module_name)) {\r
+ strcpy(name_ptr, "nvram_");\r
+ strcat(name_ptr, dhd->conf->module_name);\r
+ } else\r
+#endif\r
+ if (strlen(row->module_name)){\r
+ strcpy(name_ptr, "nvram_");\r
+ strcat(name_ptr, row->module_name);\r
+ } else\r
+ continue;\r
#ifdef BCMUSBDEV_COMPOSITE\r
strcat(name_ptr, "_cusb");\r
#endif\r
#endif\r
\r
void\r
-dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, void *sih,\r
- char *fw_path, char *nv_path)\r
+dhd_conf_set_path_params(dhd_pub_t *dhd, char *fw_path, char *nv_path)\r
{\r
int ag_type;\r
\r
dhd_conf_set_nv_name_by_chip(dhd, nv_path, ag_type);\r
dhd_conf_set_clm_name_by_chip(dhd, dhd->clm_path, ag_type);\r
#ifdef BCMSDIO\r
- dhd_conf_set_fw_name_by_mac(dhd, (bcmsdh_info_t *)sdh, (si_t *)sih, fw_path);\r
- dhd_conf_set_nv_name_by_mac(dhd, (bcmsdh_info_t *)sdh, (si_t *)sih, nv_path);\r
+ dhd_conf_set_fw_name_by_mac(dhd, fw_path);\r
+ dhd_conf_set_nv_name_by_mac(dhd, nv_path);\r
#endif\r
\r
CONFIG_MSG("Final fw_path=%s\n", fw_path);\r
return ret;\r
}\r
\r
+static int\r
+dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf)\r
+{\r
+ wl_config_t rsdb_mode_cfg = {1, 0};\r
+\r
+ if (buf) {\r
+ rsdb_mode_cfg.config = (int)simple_strtol(buf, NULL, 0);\r
+ CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config);\r
+ dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg,\r
+ sizeof(rsdb_mode_cfg), TRUE);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+typedef struct sub_cmd_t {\r
+ char *name;\r
+ uint16 id; /* id for the dongle f/w switch/case */\r
+ uint16 type; /* base type of argument IOVT_XXXX */\r
+} sub_cmd_t;\r
+\r
+/* wl he sub cmd list */\r
+static const sub_cmd_t he_cmd_list[] = {\r
+ {"enab", WL_HE_CMD_ENAB, IOVT_UINT8},\r
+ {"features", WL_HE_CMD_FEATURES, IOVT_UINT32},\r
+ {"bsscolor", WL_HE_CMD_BSSCOLOR, IOVT_UINT8},\r
+ {"partialbsscolor", WL_HE_CMD_PARTIAL_BSSCOLOR, IOVT_UINT8},\r
+ {"cap", WL_HE_CMD_CAP, IOVT_UINT8},\r
+ {"staid", WL_HE_CMD_STAID, IOVT_UINT16},\r
+ {"rtsdurthresh", WL_HE_CMD_RTSDURTHRESH, IOVT_UINT16},\r
+ {"peduration", WL_HE_CMD_PEDURATION, IOVT_UINT8},\r
+ {"testbed_mode", WL_HE_CMD_TESTBED_MODE, IOVT_UINT32},\r
+ {"omi_ulmu_throttle", WL_HE_CMD_OMI_ULMU_THROTTLE, IOVT_UINT16},\r
+ {"omi_dlmu_rr_mpf_map", WL_HE_CMD_OMI_DLMU_RSD_RCM_MPF_MAP, IOVT_UINT32},\r
+ {"ulmu_disable_policy", WL_HE_CMD_ULMU_DISABLE_POLICY, IOVT_UINT8},\r
+ {"sr_prohibit", WL_HE_CMD_SR_PROHIBIT, IOVT_UINT8},\r
+};\r
+\r
+static uint\r
+wl_he_iovt2len(uint iovt)\r
+{\r
+ switch (iovt) {\r
+ case IOVT_BOOL:\r
+ case IOVT_INT8:\r
+ case IOVT_UINT8:\r
+ return sizeof(uint8);\r
+ case IOVT_INT16:\r
+ case IOVT_UINT16:\r
+ return sizeof(uint16);\r
+ case IOVT_INT32:\r
+ case IOVT_UINT32:\r
+ return sizeof(uint32);\r
+ default:\r
+ /* ASSERT(0); */\r
+ return 0;\r
+ }\r
+}\r
+\r
+static int\r
+dhd_conf_he_cmd(dhd_pub_t * dhd, char *buf)\r
+{\r
+ int ret = BCME_OK, i;\r
+ bcm_xtlv_t *pxtlv = NULL;\r
+ uint8 mybuf[128];\r
+ uint16 he_id = -1, he_len = 0, mybuf_len = sizeof(mybuf);\r
+ uint32 he_val;\r
+ const sub_cmd_t *tpl = he_cmd_list;\r
+ char sub_cmd[32], he_val_str[10];\r
+\r
+ if (buf) {\r
+ sscanf(buf, "%s %s", sub_cmd, he_val_str);\r
+ }\r
+\r
+ for (i=0; i<ARRAY_SIZE(he_cmd_list); i++, tpl++) {\r
+ if (!strcmp(tpl->name, sub_cmd)) {\r
+ he_id = tpl->id;\r
+ he_len = wl_he_iovt2len(tpl->type);\r
+ break;\r
+ }\r
+ }\r
+ if (he_id < 0) {\r
+ CONFIG_ERROR("No he id found for %s\n", sub_cmd);\r
+ return 0;\r
+ }\r
+\r
+ pxtlv = (bcm_xtlv_t *)mybuf;\r
+\r
+ if (strlen(he_val_str)) {\r
+ he_val = simple_strtol(he_val_str, NULL, 0);\r
+ ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &mybuf_len, he_id,\r
+ he_len, (uint8 *)&he_val, BCM_XTLV_OPTION_ALIGN32);\r
+ if (ret != BCME_OK) {\r
+ CONFIG_ERROR("failed to pack he enab, err: %s\n", bcmerrorstr(ret));\r
+ return 0;\r
+ }\r
+ CONFIG_MSG("he %s 0x%x\n", sub_cmd, he_val);\r
+ dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "he", (char *)&mybuf,\r
+ sizeof(mybuf), TRUE);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf);\r
+\r
+typedef struct iovar_tpl_t {\r
+ int cmd;\r
+ char *name;\r
+ tpl_parse_t *parse;\r
+} iovar_tpl_t;\r
+\r
+const iovar_tpl_t iovar_tpl_list[] = {\r
+ {WLC_SET_VAR, "rsdb_mode", dhd_conf_rsdb_mode},\r
+ {WLC_SET_VAR, "he", dhd_conf_he_cmd},\r
+};\r
+\r
+static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,\r
+ dhd_pub_t *dhd, int cmd, char *name, char *buf)\r
+{\r
+ int i, ret = 0;\r
+\r
+ /* look for a matching code in the table */\r
+ for (i = 0; i < tpl_count; i++, tpl++) {\r
+ if (tpl->cmd == cmd && !strcmp(tpl->name, name))\r
+ break;\r
+ }\r
+ if (i < tpl_count && tpl->parse) {\r
+ ret = tpl->parse(dhd, buf);\r
+ } else {\r
+ ret = -1;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+bool\r
+dhd_conf_set_wl_cmd(dhd_pub_t *dhd, char *data, bool down)\r
+{\r
+ int cmd, val, ret = 0, len;\r
+ char name[32], *pch, *pick_tmp, *pick_tmp2, *pdata = NULL;\r
+\r
+ /* Process wl_preinit:\r
+ * wl_preinit=[cmd]=[val], [cmd]=[val]\r
+ * Ex: wl_preinit=86=0, mpc=0\r
+ */\r
+\r
+ if (data == NULL)\r
+ return FALSE;\r
+\r
+ len = strlen(data);\r
+ pdata = kmalloc(len+1, GFP_KERNEL);\r
+ if (pdata == NULL) {\r
+ CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", len+1);\r
+ goto exit;\r
+ }\r
+ memset(pdata, 0, len+1);\r
+ strcpy(pdata, data);\r
+\r
+ pick_tmp = pdata;\r
+ while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {\r
+ pch = bcmstrtok(&pick_tmp2, "=", 0);\r
+ if (!pch)\r
+ break;\r
+ if (*pch == ' ') {\r
+ pch++;\r
+ }\r
+ memset(name, 0 , sizeof (name));\r
+ cmd = (int)simple_strtol(pch, NULL, 0);\r
+ if (cmd == 0) {\r
+ cmd = WLC_SET_VAR;\r
+ strcpy(name, pch);\r
+ }\r
+ pch = bcmstrtok(&pick_tmp2, ",", 0);\r
+ if (!pch) {\r
+ break;\r
+ }\r
+ ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list),\r
+ dhd, cmd, name, pch);\r
+ if (ret) {\r
+ val = (int)simple_strtol(pch, NULL, 0);\r
+ dhd_conf_set_intiovar(dhd, cmd, name, val, -1, down);\r
+ }\r
+ }\r
+\r
+exit:\r
+ if (pdata)\r
+ kfree(pdata);\r
+ return true;\r
+}\r
+\r
int\r
dhd_conf_get_band(dhd_pub_t *dhd)\r
{\r
int\r
dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)\r
{\r
- int bcmerror = -1, i;\r
+ int bcmerror = -1;\r
struct dhd_conf *conf = dhd->conf;\r
- conf_country_list_t *country_list = &conf->country_list;\r
-\r
- for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
- if (country_list->cspec[i] != NULL) {\r
- if (!strncmp("**", country_list->cspec[i]->country_abbrev, 2)) {\r
- memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ);\r
- cspec->rev = country_list->cspec[i]->rev;\r
- bcmerror = 0;\r
- break;\r
- } else if (!strncmp(cspec->country_abbrev,\r
- country_list->cspec[i]->country_abbrev, 2)) {\r
- memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ);\r
- cspec->rev = country_list->cspec[i]->rev;\r
- bcmerror = 0;\r
- break;\r
- }\r
+ country_list_t *country = conf->country_head;\r
+\r
+#ifdef CCODE_LIST\r
+ bcmerror = dhd_ccode_map_country_list(dhd, cspec);\r
+#endif\r
+\r
+ while (country != NULL) {\r
+ if (!strncmp("**", country->cspec.country_abbrev, 2)) {\r
+ memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);\r
+ cspec->rev = country->cspec.rev;\r
+ bcmerror = 0;\r
+ break;\r
+ } else if (!strncmp(cspec->country_abbrev,\r
+ country->cspec.country_abbrev, 2)) {\r
+ memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);\r
+ cspec->rev = country->cspec.rev;\r
+ bcmerror = 0;\r
+ break;\r
}\r
+ country = country->next;\r
}\r
\r
if (!bcmerror)\r
param.bw_cap = (uint)dhd->conf->bw_cap[0];\r
CONFIG_MSG("set bw_cap 2g 0x%x\n", param.bw_cap);\r
dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m,\r
- sizeof(param), FALSE);\r
+ sizeof(param), TRUE);\r
}\r
\r
if (dhd->conf->bw_cap[1] >= 0) {\r
param.bw_cap = (uint)dhd->conf->bw_cap[1];\r
CONFIG_MSG("set bw_cap 5g 0x%x\n", param.bw_cap);\r
dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m,\r
- sizeof(param), FALSE);\r
+ sizeof(param), TRUE);\r
}\r
}\r
\r
void\r
dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int p2p_mode, int miracast_mode)\r
{\r
- int i;\r
struct dhd_conf *conf = dhd->conf;\r
+ mchan_params_t *mchan = conf->mchan;\r
bool set = true;\r
\r
- for (i=0; i<MCHAN_MAX_NUM; i++) {\r
+ while (mchan != NULL) {\r
set = true;\r
- set &= (conf->mchan[i].bw >= 0);\r
- set &= ((conf->mchan[i].p2p_mode == -1) | (conf->mchan[i].p2p_mode == p2p_mode));\r
- set &= ((conf->mchan[i].miracast_mode == -1) | (conf->mchan[i].miracast_mode == miracast_mode));\r
+ set &= (mchan->bw >= 0);\r
+ set &= ((mchan->p2p_mode == -1) | (mchan->p2p_mode == p2p_mode));\r
+ set &= ((mchan->miracast_mode == -1) | (mchan->miracast_mode == miracast_mode));\r
if (set) {\r
- dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", conf->mchan[i].bw, 0, FALSE);\r
+ dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", mchan->bw, 0, FALSE);\r
}\r
+ mchan = mchan->next;\r
}\r
\r
return;\r
goto exit;\r
}\r
}\r
+#ifdef NO_POWER_SAVE\r
+ if (cmd == WLC_SET_PM) {\r
+ if (*(const u32*)buf != 0) {\r
+ CONFIG_TRACE("skip PM\n");\r
+ *ret = BCME_OK;\r
+ goto exit;\r
+ }\r
+ } else if (cmd == WLC_SET_VAR) {\r
+ int cmd_len = strlen("mpc");\r
+ if (!strncmp(buf, "mpc", cmd_len)) {\r
+ if (*((u32 *)((u8*)buf+cmd_len+1)) != 0) {\r
+ CONFIG_TRACE("skip mpc\n");\r
+ *ret = BCME_OK;\r
+ goto exit;\r
+ }\r
+ }\r
+ }\r
+#endif\r
\r
return 0;\r
exit:\r
wl_mkeep_alive_pkt_t *mkeep_alive_pktp;\r
int ret = 0, len_bytes=0, buf_len=0;\r
char *buf = NULL, *iovar_buf = NULL;\r
- struct ether_addr bssid;\r
uint8 *pdata;\r
\r
CONFIG_TRACE("id=%d, period=%d, packet=%s\n", id, period, packet);\r
mkeep_alive_pktp->keep_alive_id = id;\r
buf_len += WL_MKEEP_ALIVE_FIXED_LEN;\r
mkeep_alive_pktp->period_msec = period;\r
- if (strlen(packet)) {\r
+ if (packet && strlen(packet)) {\r
len_bytes = wl_pattern_atoh(packet, (char *)mkeep_alive_pktp->data);\r
buf_len += len_bytes;\r
if (bcast) {\r
memcpy(mkeep_alive_pktp->data, ðer_bcast, ETHER_ADDR_LEN);\r
- } else {\r
- memset(&bssid, 0, ETHER_ADDR_LEN);\r
- ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN,\r
- FALSE, ifidx);\r
- if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN))\r
- memcpy(mkeep_alive_pktp->data, &bssid, ETHER_ADDR_LEN);\r
}\r
ret = dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "cur_etheraddr",\r
iovar_buf, WLC_IOCTL_SMLEN);\r
for (i=0; i<ETHER_ADDR_LEN; i++)\r
len += snprintf(packet+len, total_len, "%02x", iovar_buf[i]);\r
len += snprintf(packet+len, total_len, "08060001080006040001");\r
+ // Sender Hardware Addr.\r
for (i=0; i<ETHER_ADDR_LEN; i++)\r
len += snprintf(packet+len, total_len, "%02x", iovar_buf[i]);\r
+ // Sender IP Addr.\r
+ len += snprintf(packet+len, total_len, "%02x%02x%02x%02x",\r
+ ipa&0xff, (ipa>>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff);\r
+ // Target Hardware Addr.\r
+ len += snprintf(packet+len, total_len, "ffffffffffff");\r
+ // Target IP Addr.\r
len += snprintf(packet+len, total_len, "%02x%02x%02x%02x",\r
ipa&0xff, (ipa>>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff);\r
- len += snprintf(packet+len, total_len, "ffffffffffffc0a80101000000000000000000000000000000000000");\r
+ len += snprintf(packet+len, total_len, "000000000000000000000000000000000000");\r
}\r
\r
dhd_conf_mkeep_alive(dhd, ifidx, 0, dhd->conf->keep_alive_period, packet, TRUE);\r
struct net_device *net;\r
#endif /* defined(WL_CFG80211) */\r
\r
+ CONFIG_TRACE("Enter\n");\r
if (suspend) {\r
#ifdef PROP_TXSTATUS\r
#if defined(BCMSDIO) || defined(BCMDBUS)\r
}\r
#endif\r
\r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+static void\r
+dhd_conf_wait_event_complete(struct dhd_pub *dhd, int ifidx)\r
+{\r
+ s32 timeout = -1;\r
+\r
+ timeout = wait_event_interruptible_timeout(dhd->conf->event_complete,\r
+ wl_ext_event_complete(dhd, ifidx), msecs_to_jiffies(10000));\r
+ if (timeout <= 0 || !wl_ext_event_complete(dhd, ifidx)) {\r
+ wl_ext_event_complete(dhd, ifidx);\r
+ CONFIG_ERROR("timeout\n");\r
+ }\r
+}\r
+#endif\r
+\r
int\r
dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend)\r
{\r
- uint insuspend = 0;\r
struct dhd_conf *conf = dhd->conf;\r
+ uint insuspend = 0;\r
+ int pm;\r
+#ifdef BCMSDIO\r
+ uint32 intstatus = 0;\r
+ int ret = 0;\r
+#endif\r
#ifdef WL_EXT_WOWL\r
int i;\r
#endif\r
\r
insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND);\r
if (insuspend)\r
- CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x\n",\r
- dhd->op_mode, suspend, conf->suspended, insuspend);\r
+ CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x, suspend_mode=%d\n",\r
+ dhd->op_mode, suspend, conf->suspended, insuspend, conf->suspend_mode);\r
\r
- if (conf->suspended == suspend) {\r
+ if (conf->suspended == suspend || !dhd->up) {\r
return 0;\r
}\r
\r
if (suspend) {\r
if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
+ dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off",\r
+ dhd->conf->roam_off_suspend, 0, FALSE);\r
+ dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_li_dtim",\r
+ dhd->conf->suspend_bcn_li_dtim, 0, FALSE);\r
if (insuspend & ROAM_OFFLOAD_IN_SUSPEND)\r
dhd_conf_enable_roam_offload(dhd, 2);\r
} else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {\r
dhd_conf_set_intiovar(dhd, WLC_DOWN, "WLC_DOWN", 1, 0, FALSE);\r
}\r
}\r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+ if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {\r
+ if (conf->suspend_mode == PM_NOTIFIER)\r
+ dhd_conf_wait_event_complete(dhd, 0);\r
+ }\r
+#endif\r
+ if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
+ dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);\r
+ }\r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+ if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {\r
+ if (conf->suspend_mode == PM_NOTIFIER)\r
+ wl_ext_user_sync(dhd, 0, TRUE);\r
+ }\r
+#endif\r
#ifdef SUSPEND_EVENT\r
if (insuspend & NO_EVENT_IN_SUSPEND) {\r
dhd_conf_set_suspend_event(dhd, suspend);\r
}\r
#endif\r
- if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
- dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);\r
+ if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
+ if (conf->pm_in_suspend >= 0)\r
+ pm = conf->pm_in_suspend;\r
+ else if (conf->pm >= 0)\r
+ pm = conf->pm;\r
+ else\r
+ pm = PM_FAST;\r
+ dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);\r
}\r
+ dhd_conf_set_wl_cmd(dhd, conf->wl_suspend, FALSE);\r
#ifdef WL_EXT_WOWL\r
if ((insuspend & WOWL_IN_SUSPEND) && dhd_master_mode) {\r
dhd_conf_wowl_pattern(dhd, FALSE, "clr");\r
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "wowl_activate", 1, 0, FALSE);\r
dhd_conf_wowl_wakeind(dhd, TRUE);\r
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "hostsleep", 1, 0, FALSE);\r
+#ifdef BCMSDIO\r
+ ret = dhd_bus_sleep(dhd, TRUE, &intstatus);\r
+ CONFIG_TRACE("ret = %d, intstatus = 0x%x\n", ret, intstatus);\r
+#endif\r
} else\r
#endif\r
if (insuspend & NO_TXCTL_IN_SUSPEND) {\r
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "hostsleep", 2, 0, FALSE);\r
+#ifdef BCMSDIO\r
+ ret = dhd_bus_sleep(dhd, TRUE, &intstatus);\r
+ CONFIG_TRACE("ret = %d, intstatus = 0x%x\n", ret, intstatus);\r
+#endif\r
}\r
conf->suspended = TRUE;\r
} else {\r
dhd_conf_wowl_pattern(dhd, FALSE, "clr");\r
}\r
#endif\r
+ dhd_conf_set_wl_cmd(dhd, conf->wl_resume, FALSE);\r
+ dhd_conf_get_iovar(dhd, 0, WLC_GET_PM, "WLC_GET_PM", (char *)&pm, sizeof(pm));\r
+ CONFIG_TRACE("PM in suspend = %d\n", pm);\r
#ifdef SUSPEND_EVENT\r
if (insuspend & NO_EVENT_IN_SUSPEND) {\r
dhd_conf_set_suspend_event(dhd, suspend);\r
}\r
#endif\r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+ if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {\r
+ if (conf->suspend_mode == PM_NOTIFIER)\r
+ wl_ext_user_sync(dhd, 0, FALSE);\r
+ }\r
+#endif\r
+ if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
+ dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);\r
+ }\r
if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
if (insuspend & ROAM_OFFLOAD_IN_SUSPEND)\r
dhd_conf_enable_roam_offload(dhd, 0);\r
+ dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_li_dtim", 0, 0, FALSE);\r
+ dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off",\r
+ dhd->conf->roam_off, 0, FALSE);\r
} else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {\r
if (insuspend & AP_DOWN_IN_SUSPEND) {\r
dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE);\r
}\r
}\r
- if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
- dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);\r
+ if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
+ if (conf->pm >= 0)\r
+ pm = conf->pm;\r
+ else\r
+ pm = PM_FAST;\r
+ dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);\r
}\r
conf->suspended = FALSE;\r
}\r
#endif\r
\r
uint\r
-pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf)\r
+pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf, int picklen)\r
{\r
bool findNewline, changenewline=FALSE, pick=FALSE;\r
int column;\r
if (pick) {\r
if (varbuf[n] == 0x9)\r
continue;\r
+ if (pick_column >= picklen)\r
+ break;\r
pickbuf[pick_column] = varbuf[n];\r
pick_column++;\r
}\r
dhd_msg_level = (int)simple_strtol(data, NULL, 0);\r
CONFIG_MSG("dhd_msg_level = 0x%X\n", dhd_msg_level);\r
}\r
+ else if (!strncmp("dump_msg_level=", full_param, len_param)) {\r
+ dump_msg_level = (int)simple_strtol(data, NULL, 0);\r
+ CONFIG_MSG("dump_msg_level = 0x%X\n", dump_msg_level);\r
+ }\r
#ifdef BCMSDIO\r
else if (!strncmp("sd_msglevel=", full_param, len_param)) {\r
sd_msglevel = (int)simple_strtol(data, NULL, 0);\r
*/\r
\r
if (!strncmp("fw_by_mac=", full_param, len_param)) {\r
+ dhd_conf_free_mac_list(&conf->fw_by_mac);\r
pick_tmp = data;\r
pch = bcmstrtok(&pick_tmp, " ", 0);\r
conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
* [nv_by_mac]: The same format as fw_by_mac\r
*/\r
if (!strncmp("nv_by_mac=", full_param, len_param)) {\r
+ dhd_conf_free_mac_list(&conf->nv_by_mac);\r
pick_tmp = data;\r
pch = bcmstrtok(&pick_tmp, " ", 0);\r
conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
* 43430 0 nvram_ap6212.txt 43430 1 nvram_ap6212a.txt \\r
*/\r
if (!strncmp("nv_by_chip=", full_param, len_param)) {\r
+ dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
pick_tmp = data;\r
pch = bcmstrtok(&pick_tmp, " ", 0);\r
conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0);\r
}\r
\r
bool\r
-dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)\r
+dhd_conf_read_country(dhd_pub_t *dhd, char *full_param, uint len_param)\r
{\r
struct dhd_conf *conf = dhd->conf;\r
- conf_country_list_t *country_list = &conf->country_list;\r
+ country_list_t *country_next = NULL, *country;\r
int i, count = 0;\r
char *pch, *pick_tmp, *pick_tmp2;\r
char *data = full_param+len_param;\r
- wl_country_t *cspec;\r
uint len_data = strlen(data);\r
\r
/* Process country_list:\r
CONFIG_MSG("regrev = %d\n", conf->cspec.rev);\r
}\r
else if (!strncmp("country_list=", full_param, len_param)) {\r
+ dhd_conf_free_country_list(conf);\r
pick_tmp = data;\r
for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);\r
pch = bcmstrtok(&pick_tmp2, ":", 0);\r
if (!pch)\r
break;\r
- cspec = NULL;\r
- if (!(cspec = kmalloc(sizeof(wl_country_t), GFP_KERNEL))) {\r
+ country = NULL;\r
+ if (!(country = kmalloc(sizeof(country_list_t), GFP_KERNEL))) {\r
CONFIG_ERROR("kmalloc failed\n");\r
break;\r
}\r
- memset(cspec, 0, sizeof(wl_country_t));\r
+ memset(country, 0, sizeof(country_list_t));\r
\r
- strcpy(cspec->country_abbrev, pch);\r
+ memcpy(country->cspec.country_abbrev, pch, 2);\r
pch = bcmstrtok(&pick_tmp2, "/", 0);\r
if (!pch) {\r
- kfree(cspec);\r
+ kfree(country);\r
break;\r
}\r
- memcpy(cspec->ccode, pch, 2);\r
+ memcpy(country->cspec.ccode, pch, 2);\r
pch = bcmstrtok(&pick_tmp2, "/", 0);\r
if (!pch) {\r
- kfree(cspec);\r
+ kfree(country);\r
break;\r
}\r
- cspec->rev = (int32)simple_strtol(pch, NULL, 10);\r
+ country->cspec.rev = (int32)simple_strtol(pch, NULL, 10);\r
count++;\r
- country_list->cspec[i] = cspec;\r
- CONFIG_TRACE("country_list abbrev=%s, ccode=%s, regrev=%d\n",\r
- cspec->country_abbrev, cspec->ccode, cspec->rev);\r
+ if (!conf->country_head) {\r
+ conf->country_head = country;\r
+ country_next = country;\r
+ } else {\r
+ country_next->next = country;\r
+ country_next = country;\r
+ }\r
+ CONFIG_TRACE("abbrev=%s, ccode=%s, regrev=%d\n",\r
+ country->cspec.country_abbrev, country->cspec.ccode, country->cspec.rev);\r
}\r
CONFIG_MSG("%d country in list\n", count);\r
}\r
int i;\r
char *pch, *pick_tmp, *pick_tmp2;\r
struct dhd_conf *conf = dhd->conf;\r
+ mchan_params_t *mchan_next = NULL, *mchan;\r
char *data = full_param+len_param;\r
\r
/* Process mchan_bw:\r
* Ex: mchan_bw=80/go/source, 30/gc/sink\r
*/\r
if (!strncmp("mchan_bw=", full_param, len_param)) {\r
+ dhd_conf_free_mchan_list(conf);\r
pick_tmp = data;\r
for (i=0; i<MCHAN_MAX_NUM; i++) {\r
pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);\r
if (!pick_tmp2)\r
break;\r
pch = bcmstrtok(&pick_tmp2, "/", 0);\r
- if (!pch) {\r
+ if (!pch)\r
+ break;\r
+\r
+ mchan = NULL;\r
+ if (!(mchan = kmalloc(sizeof(mchan_params_t), GFP_KERNEL))) {\r
+ CONFIG_ERROR("kmalloc failed\n");\r
break;\r
- } else {\r
- conf->mchan[i].bw = (int)simple_strtol(pch, NULL, 0);\r
- if (conf->mchan[i].bw < 0 || conf->mchan[i].bw > 100) {\r
- CONFIG_ERROR("wrong bw %d\n", conf->mchan[i].bw);\r
- conf->mchan[i].bw = 0;\r
- break;\r
- }\r
}\r
+ memset(mchan, 0, sizeof(mchan_params_t));\r
+\r
+ mchan->bw = (int)simple_strtol(pch, NULL, 0);\r
+ if (mchan->bw < 0 || mchan->bw > 100) {\r
+ CONFIG_ERROR("wrong bw %d\n", mchan->bw);\r
+ kfree(mchan);\r
+ break;\r
+ }\r
+\r
pch = bcmstrtok(&pick_tmp2, "/", 0);\r
if (!pch) {\r
+ kfree(mchan);\r
break;\r
} else {\r
if (bcmstrstr(pch, "any")) {\r
- conf->mchan[i].p2p_mode = -1;\r
+ mchan->p2p_mode = -1;\r
} else if (bcmstrstr(pch, "go")) {\r
- conf->mchan[i].p2p_mode = WL_P2P_IF_GO;\r
+ mchan->p2p_mode = WL_P2P_IF_GO;\r
} else if (bcmstrstr(pch, "gc")) {\r
- conf->mchan[i].p2p_mode = WL_P2P_IF_CLIENT;\r
+ mchan->p2p_mode = WL_P2P_IF_CLIENT;\r
}\r
}\r
pch = bcmstrtok(&pick_tmp2, "/", 0);\r
if (!pch) {\r
+ kfree(mchan);\r
break;\r
} else {\r
if (bcmstrstr(pch, "any")) {\r
- conf->mchan[i].miracast_mode = -1;\r
+ mchan->miracast_mode = -1;\r
} else if (bcmstrstr(pch, "source")) {\r
- conf->mchan[i].miracast_mode = MIRACAST_SOURCE;\r
+ mchan->miracast_mode = MIRACAST_SOURCE;\r
} else if (bcmstrstr(pch, "sink")) {\r
- conf->mchan[i].miracast_mode = MIRACAST_SINK;\r
+ mchan->miracast_mode = MIRACAST_SINK;\r
}\r
}\r
- }\r
- for (i=0; i<MCHAN_MAX_NUM; i++) {\r
- if (conf->mchan[i].bw >= 0)\r
- CONFIG_MSG("mchan_bw=%d/%d/%d\n", conf->mchan[i].bw,\r
- conf->mchan[i].p2p_mode, conf->mchan[i].miracast_mode);\r
+ if (!conf->mchan) {\r
+ conf->mchan = mchan;\r
+ mchan_next = mchan;\r
+ } else {\r
+ mchan_next->next = mchan;\r
+ mchan_next = mchan;\r
+ }\r
+ CONFIG_TRACE("mchan_bw=%d/%d/%d\n", mchan->bw,mchan->p2p_mode,\r
+ mchan->miracast_mode);\r
}\r
}\r
else\r
printf("\n");\r
}\r
else if (!strncmp("magic_pkt_filter_add=", full_param, len_param)) {\r
+ if (conf->magic_pkt_filter_add) {\r
+ kfree(conf->magic_pkt_filter_add);\r
+ conf->magic_pkt_filter_add = NULL;\r
+ }\r
if (!(conf->magic_pkt_filter_add = kmalloc(MAGIC_PKT_FILTER_LEN, GFP_KERNEL))) {\r
CONFIG_ERROR("kmalloc failed\n");\r
} else {\r
conf->pm_in_suspend = (int)simple_strtol(data, NULL, 10);\r
CONFIG_MSG("pm_in_suspend = %d\n", conf->pm_in_suspend);\r
}\r
+ else if (!strncmp("suspend_mode=", full_param, len_param)) {\r
+ conf->suspend_mode = (int)simple_strtol(data, NULL, 0);\r
+ CONFIG_MSG("suspend_mode = %d\n", conf->suspend_mode);\r
+ if (conf->suspend_mode == PM_NOTIFIER)\r
+ conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND);\r
+ }\r
else if (!strncmp("suspend_bcn_li_dtim=", full_param, len_param)) {\r
conf->suspend_bcn_li_dtim = (int)simple_strtol(data, NULL, 10);\r
CONFIG_MSG("suspend_bcn_li_dtim = %d\n", conf->suspend_bcn_li_dtim);\r
CONFIG_MSG("in4way = 0x%x\n", conf->in4way);\r
}\r
else if (!strncmp("wl_preinit=", full_param, len_param)) {\r
+ if (conf->wl_preinit) {\r
+ kfree(conf->wl_preinit);\r
+ conf->wl_preinit = NULL;\r
+ }\r
if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) {\r
CONFIG_ERROR("kmalloc failed\n");\r
} else {\r
CONFIG_MSG("wl_preinit = %s\n", conf->wl_preinit);\r
}\r
}\r
+ else if (!strncmp("wl_suspend=", full_param, len_param)) {\r
+ if (conf->wl_suspend) {\r
+ kfree(conf->wl_suspend);\r
+ conf->wl_suspend = NULL;\r
+ }\r
+ if (!(conf->wl_suspend = kmalloc(len_param+1, GFP_KERNEL))) {\r
+ CONFIG_ERROR("kmalloc failed\n");\r
+ } else {\r
+ memset(conf->wl_suspend, 0, len_param+1);\r
+ strcpy(conf->wl_suspend, data);\r
+ CONFIG_MSG("wl_suspend = %s\n", conf->wl_suspend);\r
+ }\r
+ }\r
+ else if (!strncmp("wl_resume=", full_param, len_param)) {\r
+ if (conf->wl_resume) {\r
+ kfree(conf->wl_resume);\r
+ conf->wl_resume = NULL;\r
+ }\r
+ if (!(conf->wl_resume = kmalloc(len_param+1, GFP_KERNEL))) {\r
+ CONFIG_ERROR("kmalloc failed\n");\r
+ } else {\r
+ memset(conf->wl_resume, 0, len_param+1);\r
+ strcpy(conf->wl_resume, data);\r
+ CONFIG_MSG("wl_resume = %s\n", conf->wl_resume);\r
+ }\r
+ }\r
#ifdef GET_CUSTOM_MAC_FROM_CONFIG\r
else if (!strncmp("mac=", full_param, len_param)) {\r
if (!bcm_ether_atoe(data, &ea_addr)) {\r
}\r
}\r
}\r
+#endif\r
+#ifdef PROPTX_MAXCOUNT\r
+ else if (!strncmp("proptx_maxcnt_2g=", full_param, len_param)) {\r
+ conf->proptx_maxcnt_2g = (int)simple_strtol(data, NULL, 0);\r
+ CONFIG_MSG("proptx_maxcnt_2g = 0x%x\n", conf->proptx_maxcnt_2g);\r
+ }\r
+ else if (!strncmp("proptx_maxcnt_5g=", full_param, len_param)) {\r
+ conf->proptx_maxcnt_5g = (int)simple_strtol(data, NULL, 0);\r
+ CONFIG_MSG("proptx_maxcnt_5g = 0x%x\n", conf->proptx_maxcnt_5g);\r
+ }\r
#endif\r
else\r
return false;\r
dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)\r
{\r
int bcmerror = -1, chip_match = -1;\r
- uint len = 0, start_pos=0;\r
- void * image = NULL;\r
- char * memblock = NULL;\r
+ uint len = 0, start_pos=0, end_pos=0;\r
+ void *image = NULL;\r
+ char *memblock = NULL;\r
char *bufp, *pick = NULL, *pch;\r
bool conf_file_exists;\r
uint len_param;\r
\r
conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));\r
if (!conf_file_exists) {\r
- printf("%s: config path %s\n", __FUNCTION__, conf_path);\r
+ CONFIG_MSG("config path %s\n", conf_path);\r
return (0);\r
}\r
\r
\r
while (start_pos < len) {\r
memset(pick, 0, MAXSZ_BUF);\r
- start_pos = pick_config_vars(bufp, len, start_pos, pick);\r
+ end_pos = pick_config_vars(bufp, len, start_pos, pick, MAXSZ_BUF);\r
+ if (end_pos - start_pos >= MAXSZ_BUF)\r
+ CONFIG_ERROR("out of buf to read MAXSIZ_BUF=%d\n", MAXSZ_BUF);\r
+ start_pos = end_pos;\r
pch = strchr(pick, '=');\r
if (pch != NULL) {\r
len_param = pch-pick+1;\r
#endif\r
else if (dhd_conf_read_nv_by_chip(dhd, pick, len_param))\r
continue;\r
- else if (dhd_conf_read_country_list(dhd, pick, len_param))\r
+ else if (dhd_conf_read_country(dhd, pick, len_param))\r
continue;\r
else if (dhd_conf_read_mchan_params(dhd, pick, len_param))\r
continue;\r
}\r
#endif\r
\r
-static int\r
-dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf)\r
-{\r
- char *pch;\r
- wl_config_t rsdb_mode_cfg = {1, 0};\r
-\r
- pch = buf;\r
- rsdb_mode_cfg.config = (int)simple_strtol(pch, NULL, 0);\r
-\r
- if (pch) {\r
- dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg,\r
- sizeof(rsdb_mode_cfg), TRUE);\r
- CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config);\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf);\r
-\r
-typedef struct iovar_tpl_t {\r
- int cmd;\r
- char *name;\r
- tpl_parse_t *parse;\r
-} iovar_tpl_t;\r
-\r
-const iovar_tpl_t iovar_tpl_list[] = {\r
- {WLC_SET_VAR, "rsdb_mode", dhd_conf_rsdb_mode},\r
-};\r
-\r
-static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,\r
- dhd_pub_t *dhd, int cmd, char *name, char *buf)\r
-{\r
- int i, ret = 0;\r
-\r
- /* look for a matching code in the table */\r
- for (i = 0; i < tpl_count; i++, tpl++) {\r
- if (tpl->cmd == cmd && !strcmp(tpl->name, name))\r
- break;\r
- }\r
- if (i < tpl_count && tpl->parse) {\r
- ret = tpl->parse(dhd, buf);\r
- } else {\r
- ret = -1;\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-bool\r
-dhd_conf_set_wl_preinit(dhd_pub_t *dhd, char *data)\r
-{\r
- int cmd, val, ret = 0;\r
- char name[32], *pch, *pick_tmp, *pick_tmp2;\r
-\r
- /* Process wl_preinit:\r
- * wl_preinit=[cmd]=[val], [cmd]=[val]\r
- * Ex: wl_preinit=86=0, mpc=0\r
- */\r
- pick_tmp = data;\r
- while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {\r
- pch = bcmstrtok(&pick_tmp2, "=", 0);\r
- if (!pch)\r
- break;\r
- if (*pch == ' ') {\r
- pch++;\r
- }\r
- memset(name, 0 , sizeof (name));\r
- cmd = (int)simple_strtol(pch, NULL, 0);\r
- if (cmd == 0) {\r
- cmd = WLC_SET_VAR;\r
- strcpy(name, pch);\r
- }\r
- pch = bcmstrtok(&pick_tmp2, ",", 0);\r
- if (!pch) {\r
- break;\r
- }\r
- ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list),\r
- dhd, cmd, name, pch);\r
- if (ret) {\r
- val = (int)simple_strtol(pch, NULL, 0);\r
- dhd_conf_set_intiovar(dhd, cmd, name, val, -1, TRUE);\r
- }\r
- }\r
-\r
- return true;\r
-}\r
-\r
void\r
dhd_conf_postinit_ioctls(dhd_pub_t *dhd)\r
{\r
struct dhd_conf *conf = dhd->conf;\r
- char wl_preinit[] = "assoc_retry_max=30";\r
+ char wl_preinit[] = "assoc_retry_max=20";\r
+#ifdef NO_POWER_SAVE\r
+ char wl_no_power_save[] = "mpc=0, 86=0";\r
+ dhd_conf_set_wl_cmd(dhd, wl_no_power_save, FALSE);\r
+#endif\r
\r
dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE);\r
dhd_conf_map_country_list(dhd, &conf->cspec);\r
dhd_conf_set_intiovar(dhd, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG",\r
conf->frameburst, 0, FALSE);\r
\r
- dhd_conf_set_wl_preinit(dhd, wl_preinit);\r
+ dhd_conf_set_wl_cmd(dhd, wl_preinit, TRUE);\r
#if defined(BCMSDIO)\r
{\r
char ampdu_mpdu[] = "ampdu_mpdu=16";\r
- dhd_conf_set_wl_preinit(dhd, ampdu_mpdu);\r
+ dhd_conf_set_wl_cmd(dhd, ampdu_mpdu, TRUE);\r
}\r
#endif\r
if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
conf->chip == BCM4371_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||\r
- conf->chip == BCM43569_CHIP_ID) {\r
+ conf->chip == BCM43569_CHIP_ID ||\r
+ conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID) {\r
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "txbf", 1, 0, FALSE);\r
}\r
#if defined(WLEASYMESH)\r
{\r
char ezmesh[] = "mbss=1, rsdb_mode=0";\r
- dhd_conf_set_wl_preinit(dhd, ezmesh);\r
+ dhd_conf_set_wl_cmd(dhd, ezmesh, TRUE);\r
}\r
#endif\r
- dhd_conf_set_wl_preinit(dhd, conf->wl_preinit);\r
+ dhd_conf_set_wl_cmd(dhd, conf->wl_preinit, TRUE);\r
\r
#ifndef WL_CFG80211\r
dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE);\r
dhd_conf_preinit(dhd_pub_t *dhd)\r
{\r
struct dhd_conf *conf = dhd->conf;\r
- int i;\r
\r
CONFIG_TRACE("Enter\n");\r
\r
#ifdef BCMSDIO\r
dhd_conf_free_mac_list(&conf->fw_by_mac);\r
dhd_conf_free_mac_list(&conf->nv_by_mac);\r
- dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
#endif\r
- dhd_conf_free_country_list(&conf->country_list);\r
+ dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
+ dhd_conf_free_country_list(conf);\r
+ dhd_conf_free_mchan_list(conf);\r
if (conf->magic_pkt_filter_add) {\r
kfree(conf->magic_pkt_filter_add);\r
conf->magic_pkt_filter_add = NULL;\r
kfree(conf->wl_preinit);\r
conf->wl_preinit = NULL;\r
}\r
- memset(&conf->country_list, 0, sizeof(conf_country_list_t));\r
+ if (conf->wl_suspend) {\r
+ kfree(conf->wl_suspend);\r
+ conf->wl_suspend = NULL;\r
+ }\r
+ if (conf->wl_resume) {\r
+ kfree(conf->wl_resume);\r
+ conf->wl_resume = NULL;\r
+ }\r
conf->band = -1;\r
memset(&conf->bw_cap, -1, sizeof(conf->bw_cap));\r
if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {\r
} else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||\r
conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||\r
- conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||\r
- conf->chip == BCM4362_CHIP_ID || conf->chip == BCM43751_CHIP_ID) {\r
+ conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID) {\r
strcpy(conf->cspec.country_abbrev, "CN");\r
strcpy(conf->cspec.ccode, "CN");\r
conf->cspec.rev = 38;\r
conf->deepsleep = FALSE;\r
conf->pm = -1;\r
conf->pm_in_suspend = -1;\r
+ conf->insuspend = 0;\r
+ conf->suspend_mode = EARLY_SUSPEND;\r
conf->suspend_bcn_li_dtim = -1;\r
#ifdef WL_EXT_WOWL\r
dhd_master_mode = TRUE;\r
conf->wowl = WL_WOWL_NET|WL_WOWL_DIS|WL_WOWL_BCN;\r
- conf->insuspend = WOWL_IN_SUSPEND | NO_TXDATA_IN_SUSPEND;\r
-#else\r
- conf->insuspend = 0;\r
+ conf->insuspend |= (WOWL_IN_SUSPEND | NO_TXDATA_IN_SUSPEND);\r
#endif\r
+ if (conf->suspend_mode == PM_NOTIFIER)\r
+ conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND);\r
conf->suspended = FALSE;\r
#ifdef SUSPEND_EVENT\r
memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask));\r
#endif\r
conf->pktprio8021x = -1;\r
conf->ctrl_resched = 2;\r
- conf->in4way = NO_SCAN_IN4WAY | WAIT_DISCONNECTED;\r
+ conf->in4way = NO_SCAN_IN4WAY | DONT_DELETE_GC_AFTER_WPS | WAIT_DISCONNECTED;\r
+#ifdef PROPTX_MAXCOUNT\r
+ conf->proptx_maxcnt_2g = 46;\r
+ conf->proptx_maxcnt_5g = WL_TXSTATUS_FREERUNCTR_MASK;\r
+#endif /* DYNAMIC_PROPTX_MAXCOUNT */\r
#ifdef ISAM_PREINIT\r
memset(conf->isam_init, 0, sizeof(conf->isam_init));\r
memset(conf->isam_config, 0, sizeof(conf->isam_config));\r
memset(conf->isam_enable, 0, sizeof(conf->isam_enable));\r
#endif\r
- for (i=0; i<MCHAN_MAX_NUM; i++) {\r
- memset(&conf->mchan[i], -1, sizeof(mchan_params_t));\r
- }\r
#ifdef CUSTOMER_HW_AMLOGIC\r
dhd_slpauto = FALSE;\r
#ifdef BCMSDIO\r
conf->chip == BCM43454_CHIP_ID || conf->chip == BCM4345_CHIP_ID ||\r
conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||\r
- conf->chip == BCM4359_CHIP_ID || conf->chip == BCM43751_CHIP_ID || \r
- conf->chip == BCM43752_CHIP_ID) {\r
+ conf->chip == BCM4359_CHIP_ID ||\r
+ conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID) {\r
conf->intr_extn = TRUE;\r
}\r
#endif\r
if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)\r
conf->txglomsize = SDPCM_MAXGLOM_SIZE;\r
#endif\r
+ init_waitqueue_head(&conf->event_complete);\r
\r
return 0;\r
}\r
int\r
dhd_conf_reset(dhd_pub_t *dhd)\r
{\r
+ struct dhd_conf *conf = dhd->conf;\r
+\r
#ifdef BCMSDIO\r
- dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
- dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
- dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
+ dhd_conf_free_mac_list(&conf->fw_by_mac);\r
+ dhd_conf_free_mac_list(&conf->nv_by_mac);\r
#endif\r
- dhd_conf_free_country_list(&dhd->conf->country_list);\r
- if (dhd->conf->magic_pkt_filter_add) {\r
- kfree(dhd->conf->magic_pkt_filter_add);\r
- dhd->conf->magic_pkt_filter_add = NULL;\r
+ dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
+ dhd_conf_free_country_list(conf);\r
+ dhd_conf_free_mchan_list(conf);\r
+ if (conf->magic_pkt_filter_add) {\r
+ kfree(conf->magic_pkt_filter_add);\r
+ conf->magic_pkt_filter_add = NULL;\r
}\r
- if (dhd->conf->wl_preinit) {\r
- kfree(dhd->conf->wl_preinit);\r
- dhd->conf->wl_preinit = NULL;\r
+ if (conf->wl_preinit) {\r
+ kfree(conf->wl_preinit);\r
+ conf->wl_preinit = NULL;\r
}\r
- memset(dhd->conf, 0, sizeof(dhd_conf_t));\r
+ if (conf->wl_suspend) {\r
+ kfree(conf->wl_suspend);\r
+ conf->wl_suspend = NULL;\r
+ }\r
+ if (conf->wl_resume) {\r
+ kfree(conf->wl_resume);\r
+ conf->wl_resume = NULL;\r
+ }\r
+ memset(conf, 0, sizeof(dhd_conf_t));\r
return 0;\r
}\r
\r
void\r
dhd_conf_detach(dhd_pub_t *dhd)\r
{\r
- CONFIG_TRACE("Enter\n");\r
+ struct dhd_conf *conf = dhd->conf;\r
\r
+ CONFIG_TRACE("Enter\n");\r
if (dhd->conf) {\r
#ifdef BCMSDIO\r
- dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
- dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
- dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
+ dhd_conf_free_mac_list(&conf->fw_by_mac);\r
+ dhd_conf_free_mac_list(&conf->nv_by_mac);\r
#endif\r
- dhd_conf_free_country_list(&dhd->conf->country_list);\r
- if (dhd->conf->magic_pkt_filter_add) {\r
- kfree(dhd->conf->magic_pkt_filter_add);\r
- dhd->conf->magic_pkt_filter_add = NULL;\r
+ dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
+ dhd_conf_free_country_list(conf);\r
+ dhd_conf_free_mchan_list(conf);\r
+ if (conf->magic_pkt_filter_add) {\r
+ kfree(conf->magic_pkt_filter_add);\r
+ conf->magic_pkt_filter_add = NULL;\r
}\r
- if (dhd->conf->wl_preinit) {\r
- kfree(dhd->conf->wl_preinit);\r
- dhd->conf->wl_preinit = NULL;\r
+ if (conf->wl_preinit) {\r
+ kfree(conf->wl_preinit);\r
+ conf->wl_preinit = NULL;\r
}\r
- MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));\r
+ if (conf->wl_suspend) {\r
+ kfree(conf->wl_suspend);\r
+ conf->wl_suspend = NULL;\r
+ }\r
+ if (conf->wl_resume) {\r
+ kfree(conf->wl_resume);\r
+ conf->wl_resume = NULL;\r
+ }\r
+ MFREE(dhd->osh, conf, sizeof(dhd_conf_t));\r
}\r
dhd->conf = NULL;\r
}\r
} conf_pkt_filter_del_t;
#endif
-#define CONFIG_COUNTRY_LIST_SIZE 100
-typedef struct conf_country_list {
- wl_country_t *cspec[CONFIG_COUNTRY_LIST_SIZE];
-} conf_country_list_t;
+#define CONFIG_COUNTRY_LIST_SIZE 500
+typedef struct country_list {
+ struct country_list *next;
+ wl_country_t cspec;
+} country_list_t;
/* mchan_params */
#define MCHAN_MAX_NUM 4
#define MIRACAST_SOURCE 1
#define MIRACAST_SINK 2
typedef struct mchan_params {
+ struct mchan_params *next;
int bw;
int p2p_mode;
int miracast_mode;
ALL_IN_SUSPEND = 0xFFFFFFFF,
};
+enum in_suspend_mode {
+ EARLY_SUSPEND = 0,
+ PM_NOTIFIER = 1
+};
+
enum eapol_status {
EAPOL_STATUS_NONE = 0,
EAPOL_STATUS_REQID = 1,
typedef struct dhd_conf {
uint chip;
uint chiprev;
+#ifdef GET_OTP_MODULE_NAME
+ char module_name[16];
+#endif
+ struct ether_addr otp_mac;
int fw_type;
#ifdef BCMSDIO
wl_mac_list_ctrl_t fw_by_mac;
wl_mac_list_ctrl_t nv_by_mac;
#endif
wl_chip_nv_path_list_ctrl_t nv_by_chip;
- conf_country_list_t country_list;
+ country_list_t *country_head;
int band;
int bw_cap[2];
wl_country_t cspec;
bool deepsleep;
int pm;
int pm_in_suspend;
+ int suspend_mode;
int suspend_bcn_li_dtim;
#ifdef DHDTCPACK_SUPPRESS
uint8 tcpack_sup_mode;
char isam_enable[50];
#endif
int ctrl_resched;
- struct mchan_params mchan[MCHAN_MAX_NUM];
+ mchan_params_t *mchan;
char *wl_preinit;
+ char *wl_suspend;
+ char *wl_resume;
int tsq;
int orphan_move;
uint eapol_status;
#ifdef GET_CUSTOM_MAC_FROM_CONFIG
char hw_ether[62];
#endif
+ wait_queue_head_t event_complete;
+#ifdef PROPTX_MAXCOUNT
+ int proptx_maxcnt_2g;
+ int proptx_maxcnt_5g;
+#endif /* DYNAMIC_PROPTX_MAXCOUNT */
} dhd_conf_t;
#ifdef BCMSDIO
-int dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac);
+void dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih);
#if defined(HW_OOB) || defined(FORCE_WOWLAN)
void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih);
#endif
void dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable);
-int dhd_conf_set_blksize(bcmsdh_info_t *sdh);
#endif
-void dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, void *sih,
- char *fw_path, char *nv_path);
+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, 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_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_detach(dhd_pub_t *dhd);
void *dhd_get_pub(struct net_device *dev);
int wl_pattern_atoh(char *src, char *dst);
+#ifdef BCMSDIO
+extern int dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus);
+#endif
#endif /* _dhd_config_ */
--- /dev/null
+/*\r
+ * Broadcom Dongle Host Driver (DHD)\r
+ *\r
+ * Copyright (C) 1999-2018, Broadcom.\r
+ *\r
+ * Unless you and Broadcom execute a separate written software license\r
+ * agreement governing use of this software, this software is licensed to you\r
+ * under the terms of the GNU General Public License version 2 (the "GPL"),\r
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the\r
+ * following added to such license:\r
+ *\r
+ * As a special exception, the copyright holders of this software give you\r
+ * permission to link this software with independent modules, and to copy and\r
+ * distribute the resulting executable under terms of your choice, provided that\r
+ * you also meet, for each linked independent module, the terms and conditions of\r
+ * the license of that module. An independent module is a module which is not\r
+ * derived from this software. The special exception does not apply to any\r
+ * modifications of the software.\r
+ *\r
+ * Notwithstanding the above, under no circumstances may you combine this\r
+ * software in any way with any other Broadcom software provided under a license\r
+ * other than the GPL, without Broadcom's express prior written consent.\r
+ *\r
+ * $Id: dhd_csi.c 606280 2015-12-15 05:28:25Z $\r
+ */\r
+#include <osl.h>\r
+\r
+#include <bcmutils.h>\r
+\r
+#include <bcmendian.h>\r
+#include <linuxver.h>\r
+#include <linux/list.h>\r
+#include <linux/sort.h>\r
+#include <dngl_stats.h>\r
+#include <wlioctl.h>\r
+\r
+#include <bcmevent.h>\r
+#include <dhd.h>\r
+#include <dhd_dbg.h>\r
+#include <dhd_csi.h>\r
+\r
+#define NULL_CHECK(p, s, err) \\r
+ do { \\r
+ if (!(p)) { \\r
+ printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \\r
+ err = BCME_ERROR; \\r
+ return err; \\r
+ } \\r
+ } while (0)\r
+\r
+#define TIMESPEC_TO_US(ts) (((uint64)(ts).tv_sec * USEC_PER_SEC) + \\r
+ (ts).tv_nsec / NSEC_PER_USEC)\r
+\r
+#define NULL_ADDR "\x00\x00\x00\x00\x00\x00"\r
+\r
+int\r
+dhd_csi_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)\r
+{\r
+ int ret = BCME_OK;\r
+ bool is_new = TRUE;\r
+ cfr_dump_data_t *p_event;\r
+ cfr_dump_list_t *ptr, *next, *new;\r
+\r
+ NULL_CHECK(dhd, "dhd is NULL", ret);\r
+\r
+ DHD_TRACE(("Enter %s\n", __FUNCTION__));\r
+\r
+ if (!event_data) {\r
+ DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__));\r
+ return -EINVAL;\r
+ }\r
+ p_event = (cfr_dump_data_t *)event_data;\r
+\r
+ /* check if this addr exist */\r
+ if (!list_empty(&dhd->csi_list)) {\r
+ list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+ if (bcmp(&ptr->entry.header.peer_macaddr, &p_event->header.peer_macaddr,\r
+ ETHER_ADDR_LEN) == 0) {\r
+ int pos = 0, dump_len = 0, remain = 0;\r
+ is_new = FALSE;\r
+ DHD_INFO(("CSI data exist\n"));\r
+ if (p_event->header.status == 0) {\r
+ bcopy(&p_event->header, &ptr->entry.header, sizeof(cfr_dump_header_t));\r
+ dump_len = p_event->header.cfr_dump_length;\r
+ if (dump_len < MAX_EVENT_SIZE) {\r
+ bcopy(&p_event->data, &ptr->entry.data, dump_len);\r
+ } else { \r
+ /* for big csi data */\r
+ uint8 *p = (uint8 *)&ptr->entry.data;\r
+ remain = p_event->header.remain_length;\r
+ if (remain) {\r
+ pos = dump_len - remain - MAX_EVENT_SIZE;\r
+ p += pos;\r
+ bcopy(&p_event->data, p, MAX_EVENT_SIZE);\r
+ }\r
+ /* copy rest of csi data */\r
+ else {\r
+ pos = dump_len - (dump_len % MAX_EVENT_SIZE);\r
+ p += pos;\r
+ bcopy(&p_event->data, p, (dump_len % MAX_EVENT_SIZE));\r
+ }\r
+ }\r
+ return BCME_OK;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (is_new) {\r
+ if (dhd->csi_count < MAX_CSI_NUM) {\r
+ new = (cfr_dump_list_t *)MALLOCZ(dhd->osh, sizeof(cfr_dump_list_t));\r
+ if (!new){\r
+ DHD_ERROR(("Malloc cfr dump list error\n"));\r
+ return BCME_NOMEM;\r
+ }\r
+ bcopy(&p_event->header, &new->entry.header, sizeof(cfr_dump_header_t));\r
+ DHD_INFO(("New entry data size %d\n", p_event->header.cfr_dump_length));\r
+ /* for big csi data */\r
+ if (p_event->header.remain_length) {\r
+ DHD_TRACE(("remain %d\n", p_event->header.remain_length));\r
+ bcopy(&p_event->data, &new->entry.data, MAX_EVENT_SIZE);\r
+ }\r
+ else\r
+ bcopy(&p_event->data, &new->entry.data, p_event->header.cfr_dump_length);\r
+ INIT_LIST_HEAD(&(new->list));\r
+ list_add_tail(&(new->list), &dhd->csi_list);\r
+ dhd->csi_count++;\r
+ }\r
+ else {\r
+ DHD_TRACE(("Over maximum CSI Number 8. SKIP it.\n"));\r
+ }\r
+ }\r
+ return ret;\r
+}\r
+\r
+int\r
+dhd_csi_init(dhd_pub_t *dhd)\r
+{\r
+ int err = BCME_OK;\r
+\r
+ NULL_CHECK(dhd, "dhd is NULL", err);\r
+ INIT_LIST_HEAD(&dhd->csi_list);\r
+ dhd->csi_count = 0;\r
+\r
+ return err;\r
+}\r
+\r
+int\r
+dhd_csi_deinit(dhd_pub_t *dhd)\r
+{\r
+ int err = BCME_OK;\r
+ cfr_dump_list_t *ptr, *next;\r
+\r
+ NULL_CHECK(dhd, "dhd is NULL", err);\r
+\r
+ if (!list_empty(&dhd->csi_list)) {\r
+ list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+ list_del(&ptr->list);\r
+ MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t));\r
+ }\r
+ }\r
+ return err;\r
+}\r
+\r
+void\r
+dhd_csi_clean_list(dhd_pub_t *dhd)\r
+{\r
+ cfr_dump_list_t *ptr, *next;\r
+ int num = 0;\r
+\r
+ if (!dhd) {\r
+ DHD_ERROR(("NULL POINTER: %s\n", __FUNCTION__));\r
+ return;\r
+ }\r
+\r
+ if (!list_empty(&dhd->csi_list)) {\r
+ list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+ if (0 == ptr->entry.header.remain_length) {\r
+ list_del(&ptr->list);\r
+ num++;\r
+ MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t));\r
+ }\r
+ }\r
+ }\r
+ dhd->csi_count = 0;\r
+ DHD_TRACE(("Clean up %d record\n", num));\r
+}\r
+\r
+int\r
+dhd_csi_dump_list(dhd_pub_t *dhd, char *buf)\r
+{\r
+ int ret = BCME_OK;\r
+ cfr_dump_list_t *ptr, *next;\r
+ uint8 * pbuf = buf;\r
+ int num = 0;\r
+ int length = 0;\r
+\r
+ NULL_CHECK(dhd, "dhd is NULL", ret);\r
+\r
+ /* check if this addr exist */\r
+ if (!list_empty(&dhd->csi_list)) {\r
+ list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+ if (ptr->entry.header.remain_length) {\r
+ DHD_ERROR(("data not ready %d\n", ptr->entry.header.remain_length));\r
+ continue;\r
+ }\r
+ bcopy(&ptr->entry.header, pbuf, sizeof(cfr_dump_header_t));\r
+ length += sizeof(cfr_dump_header_t);\r
+ pbuf += sizeof(cfr_dump_header_t);\r
+ DHD_TRACE(("Copy data size %d\n", ptr->entry.header.cfr_dump_length));\r
+ bcopy(&ptr->entry.data, pbuf, ptr->entry.header.cfr_dump_length);\r
+ length += ptr->entry.header.cfr_dump_length;\r
+ pbuf += ptr->entry.header.cfr_dump_length;\r
+ num++;\r
+ }\r
+ }\r
+ DHD_TRACE(("dump %d record %d bytes\n", num, length));\r
+\r
+ return length;\r
+}\r
+\r
--- /dev/null
+/*\r
+ * Broadcom Dongle Host Driver (DHD), CSI\r
+ *\r
+ * Copyright (C) 1999-2018, Broadcom.\r
+ *\r
+ * Unless you and Broadcom execute a separate written software license\r
+ * agreement governing use of this software, this software is licensed to you\r
+ * under the terms of the GNU General Public License version 2 (the "GPL"),\r
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the\r
+ * following added to such license:\r
+ *\r
+ * As a special exception, the copyright holders of this software give you\r
+ * permission to link this software with independent modules, and to copy and\r
+ * distribute the resulting executable under terms of your choice, provided that\r
+ * you also meet, for each linked independent module, the terms and conditions of\r
+ * the license of that module. An independent module is a module which is not\r
+ * derived from this software. The special exception does not apply to any\r
+ * modifications of the software.\r
+ *\r
+ * Notwithstanding the above, under no circumstances may you combine this\r
+ * software in any way with any other Broadcom software provided under a license\r
+ * other than the GPL, without Broadcom's express prior written consent.\r
+ *\r
+ * $Id: dhd_csi.h 558438 2015-05-22 06:05:11Z $\r
+ */\r
+#ifndef __DHD_CSI_H__\r
+#define __DHD_CSI_H__\r
+\r
+/* Maxinum csi file dump size */\r
+#define MAX_CSI_FILESZ (32 * 1024)\r
+/* Maxinum subcarrier number */\r
+#define MAXINUM_CFR_DATA 256 * 4\r
+#define CSI_DUMP_PATH "/sys/bcm-dhd/csi"\r
+#define MAX_EVENT_SIZE 1400\r
+/* maximun csi number stored at dhd */\r
+#define MAX_CSI_NUM 8\r
+\r
+typedef struct cfr_dump_header {\r
+ /* 0 - successful; 1 - Failed */\r
+ uint8 status;\r
+ /* Peer MAC address */\r
+ uint8 peer_macaddr[6];\r
+ /* Number of Space Time Streams */\r
+ uint8 sts;\r
+ /* Number of RX chain */\r
+ uint8 num_rx;\r
+ /* Number of subcarrier */\r
+ uint16 num_carrier;\r
+ /* Length of the CSI dump */\r
+ uint32 cfr_dump_length;\r
+ /* remain unsend CSI data length */\r
+ uint32 remain_length;\r
+ /* RSSI */\r
+ int8 rssi;\r
+} __attribute__((packed)) cfr_dump_header_t;\r
+\r
+typedef struct cfr_dump_data {\r
+ cfr_dump_header_t header;\r
+ uint32 data[MAXINUM_CFR_DATA];\r
+} cfr_dump_data_t;\r
+\r
+typedef struct {\r
+ struct list_head list;\r
+ cfr_dump_data_t entry;\r
+} cfr_dump_list_t;\r
+\r
+int dhd_csi_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data);\r
+\r
+int dhd_csi_init(dhd_pub_t *dhd);\r
+\r
+int dhd_csi_deinit(dhd_pub_t *dhd);\r
+\r
+void dhd_csi_clean_list(dhd_pub_t *dhd);\r
+\r
+int dhd_csi_dump_list(dhd_pub_t *dhd, char *buf);\r
+#endif /* __DHD_CSI_H__ */\r
+\r
return err;
}
-#ifdef GET_CUSTOM_MAC_ENABLE
+#if 0
/* Function to get custom MAC address */
int
dhd_custom_get_mac_address(void *adapter, unsigned char *buf)
#include <linux/amlogic/aml_gpio_consumer.h>
extern int wifi_irq_trigger_level(void);
extern u8 *wifi_get_mac(void);
+extern u8 *wifi_get_ap_mac(void);
#endif
extern void sdio_reinit(void);
extern void set_usb_bt_power(int is_power);
return err;
}
-static int dhd_wlan_get_mac_addr(unsigned char *buf)
+static int dhd_wlan_get_mac_addr(unsigned char *buf
+#ifdef CUSTOM_MULTI_MAC
+ , char *name
+#endif
+)
{
int err = 0;
- printf("======== %s ========\n", __FUNCTION__);
-#ifdef EXAMPLE_GET_MAC
- /* EXAMPLE code */
+#ifdef CUSTOM_MULTI_MAC
+ if (!strcmp("wlan1", name)) {
+#ifdef CUSTOMER_HW_AMLOGIC
+#ifdef CUSTOM_AP_MAC
+ bcopy((char *)wifi_get_ap_mac(), buf, sizeof(struct ether_addr));
+ if (buf[0] == 0xff) {
+ printf("custom wifi ap mac is not set\n");
+ err = -1;
+ } else
+ printf("custom wifi ap mac-addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ buf[0], buf[1], buf[2],
+ buf[3], buf[4], buf[5]);
+#else
+ err = -1;
+#endif
+#endif
+ } else
+#endif /* CUSTOM_MULTI_MAC */
{
- struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
- bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+#ifdef CUSTOMER_HW_AMLOGIC
+ bcopy((char *)wifi_get_mac(), buf, sizeof(struct ether_addr));
+ if (buf[0] == 0xff) {
+ printf("custom wifi mac is not set\n");
+ err = -1;
+ } else
+ printf("custom wifi mac-addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ buf[0], buf[1], buf[2],
+ buf[3], buf[4], buf[5]);
+#endif
}
-#endif /* EXAMPLE_GET_MAC */
+
#ifdef EXAMPLE_GET_MAC_VER2
/* EXAMPLE code */
{
}
#endif /* EXAMPLE_GET_MAC_VER2 */
+ printf("======== %s err=%d ========\n", __FUNCTION__, err);
+
return err;
}
#ifdef CUSTOMER_HW_AMLOGIC
#if defined(BCMPCIE)
printf("======== Card detection to detect PCIE card! ========\n");
- pci_remove_reinit(0x14e4, 0x43ec, 1);
+ //pci_remove_reinit(0x14e4, 0x449d, 1);
#endif
#endif
#include <dhd_rtt.h>
#endif // endif
+#ifdef CSI_SUPPORT
+#include <dhd_csi.h>
+#endif /* CSI_SUPPORT */
+
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#endif // endif
DEFINE_MUTEX(_dhd_mutex_lock_);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
#endif
+static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force);
#ifdef CONFIG_BCM_DETECT_CONSECUTIVE_HANG
#define MAX_CONSECUTIVE_HANG_COUNTS 5
break;
}
-#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS)
+ printf("%s: action=%ld, suspend=%d, suspend_mode=%d\n",
+ __FUNCTION__, action, suspend, dhdinfo->pub.conf->suspend_mode);
if (suspend) {
DHD_OS_WAKE_LOCK_WAIVE(&dhdinfo->pub);
+ if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+ dhd_suspend_resume_helper(dhdinfo, suspend, 0);
+#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS)
dhd_wlfc_suspend(&dhdinfo->pub);
+#endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */
+ if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+ dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend);
DHD_OS_WAKE_LOCK_RESTORE(&dhdinfo->pub);
} else {
+ if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+ dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend);
+#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS)
dhd_wlfc_resume(&dhdinfo->pub);
- }
#endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */
+ if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+ dhd_suspend_resume_helper(dhdinfo, suspend, 0);
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(2, 6, 39))
dhd_mmc_suspend = suspend;
smp_mb();
+#endif
return ret;
}
static int dhd_set_suspend(int value, dhd_pub_t *dhd)
{
+#ifndef SUPPORT_PM2_ONLY
int power_mode = PM_MAX;
+#endif /* SUPPORT_PM2_ONLY */
/* wl_pkt_filter_enable_t enable_parm; */
int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */
int ret = 0;
int roam_time_thresh = 0; /* (ms) */
#endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */
#ifndef ENABLE_FW_ROAM_SUSPEND
- uint roamvar = dhd->conf->roam_off_suspend;
+ uint roamvar = 1;
#endif /* ENABLE_FW_ROAM_SUSPEND */
#ifdef ENABLE_BCN_LI_BCN_WAKEUP
int bcn_li_bcn = 1;
/* set specific cpucore */
dhd_set_cpucore(dhd, TRUE);
#endif /* CUSTOM_SET_CPUCORE */
-
- if (dhd->conf->pm >= 0)
- power_mode = dhd->conf->pm;
- else
- power_mode = PM_FAST;
-
if (dhd->up) {
if (value && dhd->in_suspend) {
#ifdef PKT_FILTER_SUPPORT
/* Kernel suspended */
DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__));
- if (dhd->conf->pm_in_suspend >= 0)
- power_mode = dhd->conf->pm_in_suspend;
+#ifndef SUPPORT_PM2_ONLY
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
sizeof(power_mode), TRUE, 0);
+#endif /* SUPPORT_PM2_ONLY */
#ifdef PKT_FILTER_SUPPORT
/* Enable packet filter,
DHD_ERROR(("failed to set intr_width (%d)\n", ret));
}
#endif /* DYNAMIC_SWOOB_DURATION */
+#ifndef SUPPORT_PM2_ONLY
+ power_mode = PM_FAST;
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
sizeof(power_mode), TRUE, 0);
+#endif /* SUPPORT_PM2_ONLY */
#if defined(WL_CFG80211) && defined(WL_BCNRECV)
ret = wl_android_bcnrecv_resume(dhd_linux_get_primary_netdev(dhd));
if (ret != BCME_OK) {
struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
- if (dhd)
+ if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) {
dhd_suspend_resume_helper(dhd, 1, 0);
+ dhd_conf_set_suspend_resume(&dhd->pub, 1);
+ }
}
static void dhd_late_resume(struct early_suspend *h)
struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
- if (dhd)
+ if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) {
+ dhd_conf_set_suspend_resume(&dhd->pub, 0);
dhd_suspend_resume_helper(dhd, 0, 0);
+ }
}
#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, __FUNCTION__, __LINE__);
+ skb_orphan(skb);
+
/* re-align socket buffer if "skb->data" is odd address */
if (((unsigned long)(skb->data)) & 0x1) {
unsigned char *data = skb->data;
netif_stop_queue(net);
dhd_prot_update_pktid_txq_stop_cnt(dhdp);
} else if (state == ON) {
- DHD_ERROR(("%s: Netif Queue has already stopped\n", __FUNCTION__));
+ DHD_INFO(("%s: Netif Queue has already stopped\n", __FUNCTION__));
}
if ((state == OFF) && (dhdp->txoff == TRUE)) {
netif_wake_queue(net);
dhd_prot_update_pktid_txq_start_cnt(dhdp);
} else if (state == OFF) {
- DHD_ERROR(("%s: Netif Queue has already started\n", __FUNCTION__));
+ DHD_INFO(("%s: Netif Queue has already started\n", __FUNCTION__));
}
}
* logtrace_pkt_sendup is true
*/
if (event_type == WLC_E_TRACE) {
- DHD_TRACE(("%s: WLC_E_TRACE\n", __FUNCTION__));
+ DHD_EVENT(("%s: WLC_E_TRACE\n", __FUNCTION__));
dhd_event_logtrace_enqueue(dhdp, ifidx, pktbuf);
continue;
}
continue;
}
- if (dhdp->wl_event_enabled) {
+#ifdef SENDPROB
+ if (dhdp->wl_event_enabled ||
+ (dhdp->recv_probereq && (event.event_type == WLC_E_PROBREQ_MSG)))
+#else
+ if (dhdp->wl_event_enabled)
+#endif
+ {
#ifdef DHD_USE_STATIC_CTRLBUF
/* If event bufs are allocated via static buf pool
* and wl events are enabled, make a copy, free the
/* Copy out any request driver name */
if (copy_from_user(&info, uaddr, sizeof(info)))
return -EFAULT;
- strncpy(drvname, info.driver, sizeof(info.driver));
- drvname[sizeof(info.driver)-1] = '\0';
+ strncpy(drvname, info.driver, sizeof(drvname) - 1);
+ drvname[sizeof(drvname) - 1] = '\0';
/* clear struct for return */
memset(&info, 0, sizeof(info));
}
}
+#ifndef CONFIG_VTS_SUPPORT
if (!capable(CAP_NET_ADMIN)) {
bcmerror = BCME_EPERM;
goto done;
}
+#endif
/* Take backup of ioc.buf and restore later */
ioc_buf_user = ioc.buf;
/* Allow transmit calls */
netif_start_queue(net);
DHD_ERROR(("[%s] tx queue started\n", net->name));
+
+#if defined(SET_RPS_CPUS)
+ dhd_rps_cpus_enable(net, TRUE);
+ DHD_ERROR(("[%s] RPS started\n", net->name));
+#endif
+
+#if defined(SET_XPS_CPUS)
+ dhd_xps_cpus_enable(net, TRUE);
+ DHD_ERROR(("[%s] XPS started\n", net->name));
+#endif
+
return ret;
}
#endif /* DHD_DEBUG */
#ifdef GET_CUSTOM_MAC_ENABLE
- wifi_platform_get_mac_addr(dhd->adapter, hw_ether);
+ wifi_platform_get_mac_addr(dhd->adapter, hw_ether, iface_name);
bcopy(hw_ether, dhd->pub.mac.octet, sizeof(struct ether_addr));
#endif /* GET_CUSTOM_MAC_ENABLE */
#ifdef CUSTOM_FORCE_NODFS_FLAG
len = strlen(if_name);
ch = if_name[len - 1];
if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
- strncat(if_name, "%d", 2);
+ strncat(if_name, "%d", IFNAMSIZ - len - 1);
}
/* Passing NULL to dngl_name to ensure host gets if_name in dngl_name member */
dhd->dhd_state = dhd_state;
dhd_found++;
+
+#ifdef CSI_SUPPORT
+ dhd_csi_init(&dhd->pub);
+#endif /* CSI_SUPPORT */
#ifdef DHD_DUMP_MNGR
dhd->pub.dump_file_manage =
#ifdef GET_CUSTOM_MAC_ENABLE
memset(hw_ether, 0, sizeof(hw_ether));
- ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether);
+ ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, iface_name);
#ifdef GET_CUSTOM_MAC_FROM_CONFIG
if (!memcmp(ðer_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) {
ret = 0;
#ifdef WL_ESCAN
setbit(eventmask, WLC_E_ESCAN_RESULT);
#endif /* WL_ESCAN */
+#ifdef CSI_SUPPORT
+ setbit(eventmask, WLC_E_CSI);
+#endif /* CSI_SUPPORT */
#ifdef RTT_SUPPORT
setbit(eventmask, WLC_E_PROXD);
#endif /* RTT_SUPPORT */
setbit(eventmask, WLC_E_TRACE);
#else
clrbit(eventmask, WLC_E_TRACE);
+ if (dhd->conf->chip == BCM43752_CHIP_ID)
+ setbit(eventmask, WLC_E_TRACE);
#endif /* defined(SHOW_LOGTRACE) && defined(LOGTRACE_FROM_FILE) */
setbit(eventmask, WLC_E_CSA_COMPLETE_IND);
#ifdef WL_MBO
setbit(eventmask_msg->mask, WLC_E_MBO);
#endif /* WL_MBO */
+#ifdef WL_CLIENT_SAE
+ setbit(eventmask_msg->mask, WLC_E_JOIN_START);
+#endif /* WL_CLIENT_SAE */
#ifdef WL_BCNRECV
setbit(eventmask_msg->mask, WLC_E_BCNRECV_ABORTED);
#endif /* WL_BCNRECV */
memset(buf, 0, sizeof(buf));
ret = dhd_iovar(dhd, 0, "clmver", NULL, 0, buf, sizeof(buf), FALSE);
if (ret < 0)
- DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
+ DHD_ERROR(("%s clmver failed %d\n", __FUNCTION__, ret));
else {
char *ver_temp_buf = NULL, *ver_date_buf = NULL;
int len;
/* query for 'wlc_ver' to get version info from firmware */
memset(&wlc_ver, 0, sizeof(wl_wlc_version_t));
- ret = dhd_iovar(dhd, 0, "wlc_ver", NULL, 0, (char *)&wlc_ver,
+ ret2 = dhd_iovar(dhd, 0, "wlc_ver", NULL, 0, (char *)&wlc_ver,
sizeof(wl_wlc_version_t), FALSE);
- if (ret < 0)
- DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
- else {
+ if (ret2 < 0) {
+ DHD_ERROR(("%s wlc_ver failed %d\n", __FUNCTION__, ret2));
+ if (ret2 != BCME_UNSUPPORTED)
+ ret = ret2;
+ } else {
dhd->wlc_ver_major = wlc_ver.wlc_ver_major;
dhd->wlc_ver_minor = wlc_ver.wlc_ver_minor;
}
if (ifidx == 0)
printf("%s\n", dhd_version);
else {
-#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN)
- wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
-#ifdef WL_ESCAN
- wl_escan_event_attach(net, dhdp);
-#endif /* WL_ESCAN */
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
+ wl_ext_iapsta_update_net_device(net, ifidx);
#endif /* WL_EXT_IAPSTA */
-#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */
- }
- if (ifidx != 0) {
if (_dhd_set_mac_address(dhd, ifidx, net->dev_addr) == 0)
DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__));
else
DHD_ERROR(("couldn't register the net device [%s], err %d\n", net->name, err));
goto fail;
}
- if (ifidx == 0) {
#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN)
- wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
+ wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
#ifdef WL_ESCAN
- wl_escan_event_attach(net, dhdp);
+ wl_escan_event_attach(net, dhdp);
#endif /* WL_ESCAN */
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
-#endif /* WL_EXT_IAPSTA */
-#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */
- }
-#ifdef WL_EXT_IAPSTA
+ wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
wl_ext_iapsta_attach_name(net, ifidx);
#endif /* WL_EXT_IAPSTA */
+#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */
printf("Register interface [%s] MAC: "MACDBG"\n\n", net->name,
MAC2STRDBG(net->dev_addr));
if (dev) {
rtnl_lock();
+#if defined(WL_CFG80211) && defined(WL_STATIC_IF)
+ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
+ cfg = wl_get_cfg(dev);
+ if (cfg && cfg->static_ndev && (cfg->static_ndev->flags & IFF_UP)) {
+ dev_close(cfg->static_ndev);
+ }
+ }
+#endif /* WL_CFG80211 && WL_STATIC_IF */
if (dev->flags & IFF_UP) {
/* If IFF_UP is still up, it indicates that
* "ifconfig wlan0 down" hasn't been called.
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
dhd->iflist[0] = NULL;
+#ifdef WL_CFG80211
+ if (cfg && cfg->wdev)
+ cfg->wdev->netdev = NULL;
+#endif
}
}
}
#endif /* DHD_LB */
+#ifdef CSI_SUPPORT
+ dhd_csi_deinit(dhdp);
+#endif /* CSI_SUPPORT */
+
#if defined(DNGL_AXI_ERROR_LOGGING) && defined(DHD_USE_WQ_FOR_DNGL_AXI_ERROR)
cancel_work_sync(&dhd->axi_error_dispatcher_work);
#endif /* DNGL_AXI_ERROR_LOGGING && DHD_USE_WQ_FOR_DNGL_AXI_ERROR */
return NULL;
}
+ if (!(dev->flags & IFF_UP)) {
+ return NULL;
+ }
+
res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats);
if (res == 0)
int ret = 0;
dhd_info_t *dhd = DHD_DEV_INFO(dev);
- if (dhd) {
+ if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) {
+ if (!val)
+ dhd_conf_set_suspend_resume(&dhd->pub, val);
#ifdef CONFIG_MACH_UNIVERSAL7420
#endif /* CONFIG_MACH_UNIVERSAL7420 */
#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
#ifdef WL_CFG80211
wl_cfg80211_update_power_mode(dev);
#endif // endif
+ if (val)
+ dhd_conf_set_suspend_resume(&dhd->pub, val);
}
return ret;
}
if (ntimes == 0)
{
atomic_set(&dhd->pend_8021x_cnt, 0);
- DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__));
+ WL_MSG(dev->name, "TIMEOUT\n");
}
return pend;
}
}
#endif /* DHD_L2_FILTER */
+#if defined(SET_XPS_CPUS)
+int dhd_xps_cpus_enable(struct net_device *net, int enable)
+{
+ dhd_info_t *dhd = DHD_DEV_INFO(net);
+ dhd_if_t *ifp;
+ int ifidx;
+ char * XPS_CPU_SETBUF;
+
+ ifidx = dhd_net2idx(dhd, net);
+ if (ifidx == DHD_BAD_IF) {
+ DHD_ERROR(("%s bad ifidx\n", __FUNCTION__));
+ return -ENODEV;
+ }
+
+ if (ifidx == PRIMARY_INF) {
+ if (dhd->pub.op_mode == DHD_FLAG_IBSS_MODE) {
+ DHD_INFO(("%s : set for IBSS.\n", __FUNCTION__));
+ XPS_CPU_SETBUF = RPS_CPUS_MASK_IBSS;
+ } else {
+ DHD_INFO(("%s : set for BSS.\n", __FUNCTION__));
+ XPS_CPU_SETBUF = RPS_CPUS_MASK;
+ }
+ } else if (ifidx == VIRTUAL_INF) {
+ DHD_INFO(("%s : set for P2P.\n", __FUNCTION__));
+ XPS_CPU_SETBUF = RPS_CPUS_MASK_P2P;
+ } else {
+ DHD_ERROR(("%s : Invalid index : %d.\n", __FUNCTION__, ifidx));
+ return -EINVAL;
+ }
+
+ ifp = dhd->iflist[ifidx];
+ if (ifp) {
+ if (enable) {
+ DHD_INFO(("%s : set xps_cpus as [%s]\n", __FUNCTION__, XPS_CPU_SETBUF));
+ custom_xps_map_set(ifp->net, XPS_CPU_SETBUF, strlen(XPS_CPU_SETBUF));
+ } else {
+ custom_xps_map_clear(ifp->net);
+ }
+ } else {
+ DHD_ERROR(("%s : ifp is NULL!!\n", __FUNCTION__));
+ return -ENODEV;
+ }
+ return BCME_OK;
+}
+
+int custom_xps_map_set(struct net_device *net, char *buf, size_t len)
+{
+ cpumask_var_t mask;
+ int err;
+
+ DHD_INFO(("%s : Entered.\n", __FUNCTION__));
+
+ if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
+ DHD_ERROR(("%s : alloc_cpumask_var fail.\n", __FUNCTION__));
+ return -ENOMEM;
+ }
+
+ err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
+ if (err) {
+ free_cpumask_var(mask);
+ DHD_ERROR(("%s : bitmap_parse fail.\n", __FUNCTION__));
+ return err;
+ }
+
+ err = netif_set_xps_queue(net, mask, 0);
+
+ free_cpumask_var(mask);
+
+ if (0 == err)
+ DHD_ERROR(("%s : Done. mapping cpu\n", __FUNCTION__));
+
+ return err;
+}
+
+void custom_xps_map_clear(struct net_device *net)
+{
+ struct xps_dev_maps *dev_maps;
+
+ DHD_INFO(("%s : Entered.\n", __FUNCTION__));
+
+ rcu_read_lock();
+ dev_maps = rcu_dereference(net->xps_maps);
+ rcu_read_unlock();
+
+ if (dev_maps) {
+ RCU_INIT_POINTER(net->xps_maps, NULL);
+ kfree_rcu(dev_maps, rcu);
+ DHD_INFO(("%s : xps_cpus map clear.\n", __FUNCTION__));
+ }
+}
+#endif // endif
+
#if defined(SET_RPS_CPUS)
int dhd_rps_cpus_enable(struct net_device *net, int enable)
{
}
free_cpumask_var(mask);
- DHD_INFO(("%s : Done. mapping cpu nummber : %d\n", __FUNCTION__, map->len));
+ DHD_ERROR(("%s : Done. mapping cpu nummber : %d\n", __FUNCTION__, map->len));
return map->len;
}
#define WLAN_PLAT_NODFS_FLAG 0x01
#define WLAN_PLAT_AP_FLAG 0x02
+#if !defined(CONFIG_WIFI_CONTROL_FUNC)
struct wifi_platform_data {
#ifdef BUS_POWER_RESTORE
int (*set_power)(int val, wifi_adapter_info_t *adapter);
int (*set_reset)(int val);
int (*set_carddetect)(int val);
void *(*mem_prealloc)(int section, unsigned long size);
+#ifdef CUSTOM_MULTI_MAC
+ int (*get_mac_addr)(unsigned char *buf, char *name);
+#else
int (*get_mac_addr)(unsigned char *buf);
+#endif
#ifdef BCMSDIO
int (*get_wake_irq)(void);
#endif // endif
void *(*get_country_code)(char *ccode);
#endif
};
+#endif
typedef struct bcmdhd_wifi_platdata {
uint num_adapters;
int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec);
int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present);
int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr);
-int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf);
+int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf, char *name);
#ifdef CUSTOM_COUNTRY_CODE
void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode,
u32 flags);
#ifdef DHD_ADPS_BAM_EXPORT
#include <wl_bam.h>
#endif // endif
+#ifdef CSI_SUPPORT
+#include <dhd_csi.h>
+#endif /* CSI_SUPPORT */
#ifdef SHOW_LOGTRACE
extern dhd_pub_t* g_dhd_pub;
#ifdef DHD_FW_COREDUMP
-#define MEMDUMPINFO "/data/vendor/misc/wifi/.memdump.info"
+#define MEMDUMPINFO "/data/misc/wifi/.memdump.info"
uint32
get_mem_val_from_file(void)
#endif /* DHD_FW_COREDUMP */
#ifdef BCMASSERT_LOG
-#define ASSERTINFO "/data/vendor/misc/wifi/.assert.info"
+#define ASSERTINFO "/data/misc/wifi/.assert.info"
int
get_assert_val_from_file(void)
{
.default_attrs = control_file_attrs,
};
+#ifdef CSI_SUPPORT
+/* Function to show current ccode */
+static ssize_t read_csi_data(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+{
+ dhd_info_t *dhd = to_dhd(kobj);
+ int n = 0;
+
+ n = dhd_csi_dump_list(&dhd->pub, buf);
+ DHD_INFO(("Dump data to file, size %d\n", n));
+ dhd_csi_clean_list(&dhd->pub);
+
+ return n;
+}
+
+static struct bin_attribute dhd_attr_csi = {
+ .attr = { .name = "csi",
+ .mode = 0660, },
+ .size = MAX_CSI_FILESZ,
+ .read = read_csi_data,
+};
+#endif /* CSI_SUPPORT */
+
/* Create a kobject and attach to sysfs interface */
int dhd_sysfs_init(dhd_info_t *dhd)
{
return ret;
}
+#ifdef CSI_SUPPORT
+ ret = sysfs_create_bin_file(&dhd->dhd_kobj, &dhd_attr_csi);
+ if (ret) {
+ DHD_ERROR(("%s: can't create %s\n", __FUNCTION__, dhd_attr_csi.attr.name));
+ kobject_put(&dhd->dhd_kobj);
+ return ret;
+ }
+#endif /* CSI_SUPPORT */
+
/*
* We are always responsible for sending the uevent that the kobject
* was added to the system.
#include <dhd_linux_pktdump.h>
#include <dhd_config.h>
-#define DHD_PKTDUMP(arg) DHD_ERROR(arg)
-#define DHD_PKTDUMP_MEM(arg) DHD_ERROR(arg)
+#define DHD_PKTDUMP(arg) printk arg
+#define DHD_PKTDUMP_MEM(arg) printk arg
#define PACKED_STRUCT __attribute__ ((packed))
#define EAPOL_HDR_LEN 4
#define PKT_CNT_RSN_VALID(rsn) \
(((rsn) > (PKT_CNT_RSN_INVALID)) && ((rsn) < (PKT_CNT_RSN_MAX)))
+#ifdef DHD_PKTDUMP_ROAM
static const char pkt_cnt_msg[][20] = {
"INVALID",
"ROAM_SUCCESS",
"CONNECT_SUCCESS",
"INVALID"
};
+#endif
static const char tx_pktfate[][30] = {
"TX_PKT_FATE_ACKED", /* 0: WLFC_CTL_PKTFLAG_DISCARD */
#define TX_FATE(fate) ((fate) ? (TX_FATE_STR(fate)) : "N/A")
#define TX_FATE_ACKED(fate) ((fate) ? ((*fate) == (WLFC_CTL_PKTFLAG_DISCARD)) : (0))
-#define EAP_PRINT(str) \
+#define EAP_PRINT(x, args...) \
do { \
- if (tx) { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \
- str TXFATE_FMT "\n", ifname, \
- TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
- } else { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \
- str "\n", ifname)); \
+ if (dump_msg_level & DUMP_EAPOL_VAL) { \
+ if (tx) { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"TXFATE_FMT"\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+ } else { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf)); \
+ } \
} \
} while (0)
-#define EAP_PRINT_REPLAY(str) \
+#define EAP_PRINT_REPLAY(x, args...) \
do { \
- if (tx) { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \
- str DBGREPLAY TXFATE_FMT "\n", ifname, \
- REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), \
- TX_FATE(pktfate))); \
- } else { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \
- str DBGREPLAY "\n", ifname, \
- REPLAY_FMT(eap_key))); \
+ if (dump_msg_level & DUMP_EAPOL_VAL) { \
+ if (tx) { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"DBGREPLAY TXFATE_FMT"\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+ REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+ } else { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)"DBGREPLAY"\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+ REPLAY_FMT(eap_key))); \
+ } \
} \
} while (0)
-#define EAP_PRINT_OTHER(str) \
+#define EAP_PRINT_OTHER(x, args...) \
do { \
- if (tx) { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \
- str "ver %d, type %d" TXFATE_FMT "\n", ifname, \
- eapol_hdr->version, eapol_hdr->type, \
- TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
- } else { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \
- str "ver %d, type %d\n", ifname, \
- eapol_hdr->version, eapol_hdr->type)); \
+ if (dump_msg_level & DUMP_EAPOL_VAL) { \
+ if (tx) { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \
+ "ver %d, type %d"TXFATE_FMT"\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+ eapol_hdr->version, eapol_hdr->type, \
+ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+ } else { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \
+ "ver %d, type %d\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+ eapol_hdr->version, eapol_hdr->type)); \
+ } \
} \
} while (0)
-#define EAP_PRINT_OTHER_4WAY(str) \
+#define EAP_PRINT_OTHER_4WAY(x, args...) \
do { \
- if (tx) { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " str \
- "ver %d type %d keytype %d keyinfo 0x%02X" \
- TXFATE_FMT "\n", ifname, eapol_hdr->version, \
- eapol_hdr->type, eap_key->type, \
- (uint32)hton16(eap_key->key_info), \
- TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
- } else { \
- DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " str \
- "ver %d type %d keytype %d keyinfo 0x%02X\n", \
- ifname, eapol_hdr->version, eapol_hdr->type, \
- eap_key->type, (uint32)hton16(eap_key->key_info))); \
+ if (dump_msg_level & DUMP_EAPOL_VAL) { \
+ if (tx) { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \
+ "ver %d type %d keytype %d keyinfo 0x%02X"TXFATE_FMT"\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+ eapol_hdr->version, eapol_hdr->type, eap_key->type, \
+ (uint32)hton16(eap_key->key_info), \
+ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+ } else { \
+ DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \
+ "ver %d type %d keytype %d keyinfo 0x%02X\n", \
+ ifname, ## args, \
+ tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+ eapol_hdr->version, eapol_hdr->type, eap_key->type, \
+ (uint32)hton16(eap_key->key_info))); \
+ } \
} \
} while (0)
char *ifname;
uint16 eap_len;
bool cond;
+ char seabuf[ETHER_ADDR_STR_LEN]="";
+ char deabuf[ETHER_ADDR_STR_LEN]="";
if (!pktdata) {
DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__));
return;
}
+ bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+ bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
eapol_hdr = (eapol_header_t *)pktdata;
eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body);
if (eap_hdr->type != EAP_TYPE_EXP) {
eap_header_fmt_t *eap_hdr;
char *ifname;
bool cond;
+ char seabuf[ETHER_ADDR_STR_LEN]="";
+ char deabuf[ETHER_ADDR_STR_LEN]="";
if (!pktdata) {
DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__));
return;
}
+ bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+ bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
eapol_hdr = (eapol_header_t *)pktdata;
eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body);
ifname = dhd_ifname(dhd, ifidx);
msg_eapol_t type;
char *ifname;
bool cond;
+ char seabuf[ETHER_ADDR_STR_LEN]="";
+ char deabuf[ETHER_ADDR_STR_LEN]="";
if (!pktdata) {
DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__));
return;
}
+ bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+ bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
type = dhd_is_4way_msg(pktdata);
ifname = dhd_ifname(dhd, ifidx);
eapol_hdr = (eapol_header_t *)pktdata;
char *ifname;
eapol_header_t *eapol_hdr = (eapol_header_t *)pktdata;
bool cond;
+ char seabuf[ETHER_ADDR_STR_LEN]="";
+ char deabuf[ETHER_ADDR_STR_LEN]="";
if (!pktdata) {
DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__));
return;
}
+ bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+ bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
eapol_hdr = (eapol_header_t *)pktdata;
ifname = dhd_ifname(dhd, ifidx);
cond = (tx && pktfate) ? FALSE : TRUE;
#define DHCP_PRINT(str) \
do { \
if (tx) { \
- DHD_PKTDUMP(("[dhd-%s] "str " %s[%s] [TX] -" TXFATE_FMT "\n", \
- ifname, typestr, opstr, \
+ DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
+ ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} else { \
- DHD_PKTDUMP(("[dhd-%s] "str" %s[%s] [RX]\n", \
- ifname, typestr, opstr)); \
+ DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [RX] : %s(%s) %s %s(%s)\n", \
+ ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \
} \
} while (0)
int dhcp_type = 0, len, opt_len;
char *ifname = NULL, *typestr = NULL, *opstr = NULL;
bool cond;
+ char sabuf[20]="", dabuf[20]="";
+ char seabuf[ETHER_ADDR_STR_LEN]="";
+ char deabuf[ETHER_ADDR_STR_LEN]="";
+
+ if (!(dump_msg_level & DUMP_DHCP_VAL))
+ return;
/* check IP header */
if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
if (ntohs(iph->tot_len) < ntohs(b->udph.len) + sizeof(struct bcmudp_hdr)) {
return;
}
+ bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf);
+ bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf);
+ bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+ bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
ifname = dhd_ifname(dhdp, ifidx);
cond = (tx && pktfate) ? FALSE : TRUE;
do { \
if (tx) { \
DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) SEQNUM=%d" \
- TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ TXFATE_FMT"\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, seqnum, \
TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} else { \
char seabuf[ETHER_ADDR_STR_LEN]="";
char deabuf[ETHER_ADDR_STR_LEN]="";
+ if (!(dump_msg_level & DUMP_ICMP_VAL))
+ return;
+
/* check IP header */
if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
IP_VER(iph) != IP_VER_4 ||
do { \
if (tx) { \
if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
- DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)" TXFATE_FMT "\n", \
+ DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} else { \
- DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)" TXFATE_FMT "\n", \
+ DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
do { \
if (tx) { \
if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
- DHD_PKTDUMP(("[dhd-%s] "str " [TX] op_code=%d" \
- TXFATE_FMT "\n", ifname, opcode, \
- TX_PKTHASH(pkthash), \
- TX_FATE(pktfate))); \
+ DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
+ TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
+ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} else { \
- DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] op_code=%d" \
- TXFATE_FMT "\n", ifname, opcode, \
+ DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
+ TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} \
} else { \
- DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] op_code=%d\n", \
- ifname, opcode)); \
+ DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] : %s(%s) %s %s(%s) op_code=%d\n", \
+ ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode)); \
} \
} while (0)
char seabuf[ETHER_ADDR_STR_LEN]="";
char deabuf[ETHER_ADDR_STR_LEN]="";
+ if (!(dump_msg_level & DUMP_ARP_VAL))
+ return;
+
/* validation check */
if (arph->htype != hton16(HTYPE_ETHERNET) ||
arph->hlen != ETHER_ADDR_LEN ||
do { \
if (tx) { \
if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
- DHD_PKTDUMP(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s" \
- TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
- TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+ DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
+ TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
+ id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} else { \
- DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s" \
- TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
- TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+ DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
+ TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
+ id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} \
} else { \
- DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] ID:0x%04X OPCODE:%s\n", \
- ifname, id, DNSOPCODE(opcode))); \
+ DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s\n", \
+ ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, tx?"->":"<-", \
+ tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode))); \
} \
} while (0)
do { \
if (tx) { \
if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
- DHD_PKTDUMP(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s RCODE:%d" \
- TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
- GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), \
- TX_FATE(pktfate))); \
+ DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
+ TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
+ GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} else { \
- DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s RCODE:%d" \
- TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
- GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), \
- TX_FATE(pktfate))); \
+ DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
+ TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
+ GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
} \
} else { \
- DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] ID:0x%04X OPCODE:%s RCODE:%d\n", \
- ifname, id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \
+ DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d\n", \
+ ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
+ id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \
} \
} while (0)
uint16 flags, opcode, id;
char *ifname;
bool cond, dump_enabled;
+ char sabuf[20]="", dabuf[20]="";
+ char seabuf[ETHER_ADDR_STR_LEN]="";
+ char deabuf[ETHER_ADDR_STR_LEN]="";
+
+ if (!(dump_msg_level & DUMP_DNS_VAL))
+ return;
/* check IP header */
if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
flags = hton16(dnsh->flags);
opcode = GET_DNS_OPCODE(flags);
id = hton16(dnsh->id);
+ bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf);
+ bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf);
+ bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+ bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
if (GET_DNS_QR(flags)) {
/* Response */
DHD_STATLOG_DATA(dhdp, ST(DNS_RESP), ifidx, tx, cond);
uint16 protocol;
char *pkttype = "UNKNOWN";
+ if (!(dump_msg_level & DUMP_TRX_VAL))
+ return;
+
if (!dhdp) {
DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
return;
}
-int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf)
+int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf,
+ char *name)
{
struct wifi_platform_data *plat_data;
return -EINVAL;
plat_data = adapter->wifi_plat_data;
if (plat_data->get_mac_addr) {
+#ifdef CUSTOM_MULTI_MAC
+ return plat_data->get_mac_addr(buf, name);
+#else
return plat_data->get_mac_addr(buf);
+#endif
}
return -EOPNOTSUPP;
}
ASSERT(dhd_wifi_platdata != NULL);
ASSERT(dhd_wifi_platdata->num_adapters == 1);
adapter = &dhd_wifi_platdata->adapters[0];
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
+ adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data);
+#else
adapter->wifi_plat_data = (void *)&dhd_wlan_control;
-// adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data);
+#endif
resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
if (resource == NULL)
if (prot->curr_ioctl_cmd == WLC_SET_VAR ||
prot->curr_ioctl_cmd == WLC_GET_VAR) {
char iovbuf[32];
- int i;
int dump_size = 128;
uint8 *ioctl_buf = (uint8 *)prot->ioctbuf.va;
memset(iovbuf, 0, sizeof(iovbuf));
prot->curr_ioctl_cmd == WLC_SET_VAR ?
"WLC_SET_VAR" : "WLC_GET_VAR", iovbuf));
DHD_ERROR(("========== START IOCTL REQBUF DUMP ==========\n"));
- for (i = 0; i < dump_size; i++) {
- DHD_ERROR(("%02X ", ioctl_buf[i]));
- if ((i % 32) == 31) {
- DHD_ERROR(("\n"));
- }
- }
+ prhex("ioctl_buf", (const u8 *) ioctl_buf, dump_size);
DHD_ERROR(("\n========== END IOCTL REQBUF DUMP ==========\n"));
}
bool
dhdpcie_chip_support_msi(dhd_bus_t *bus)
{
- DHD_ERROR(("%s: buscorerev=%d chipid=0x%x\n",
+ DHD_INFO(("%s: buscorerev=%d chipid=0x%x\n",
__FUNCTION__, bus->sih->buscorerev, si_chipid(bus->sih)));
if (bus->sih->buscorerev <= 14 ||
si_chipid(bus->sih) == BCM4375_CHIP_ID ||
si_chipid(bus->sih) == BCM4362_CHIP_ID ||
si_chipid(bus->sih) == BCM43751_CHIP_ID ||
- si_chipid(bus->sih) == BCM43752_CHIP_ID ||
si_chipid(bus->sih) == BCM4361_CHIP_ID ||
si_chipid(bus->sih) == BCM4359_CHIP_ID) {
return FALSE;
DHD_OS_WAKE_LOCK(bus->dhd);
- dhd_conf_set_path_params(bus->dhd, NULL, NULL, bus->fw_path, bus->nv_path);
+ dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
dhd_set_bus_params(bus);
ret = _dhdpcie_download_firmware(bus);
}
}
+ if (bus->d2h_intr_method == PCIE_MSI)
+ printf("%s: MSI enabled\n", __FUNCTION__);
+ else
+ printf("%s: INTx enabled\n", __FUNCTION__);
+
if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED,
dhdpcie_info->pciname, bus) < 0) {
DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
if (bus->dev->bus) {
/* self member of structure pci_bus is bridge device as seen by parent */
bus->rc_dev = bus->dev->bus->self;
- DHD_ERROR(("%s: rc_dev from dev->bus->self (%x:%x) is %pK\n", __FUNCTION__,
- bus->rc_dev->vendor, bus->rc_dev->device, bus->rc_dev));
+ if (bus->rc_dev)
+ DHD_ERROR(("%s: rc_dev from dev->bus->self (%x:%x) is %pK\n", __FUNCTION__,
+ bus->rc_dev->vendor, bus->rc_dev->device, bus->rc_dev));
+ else
+ DHD_ERROR(("%s: bus->dev->bus->self is NULL\n", __FUNCTION__));
} else {
DHD_ERROR(("%s: unable to get rc_dev as dev->bus is NULL\n", __FUNCTION__));
}
dhdpcie_osinfo->oob_irq_registered = TRUE;
- return err;
+ return 0;
}
void dhdpcie_oob_intr_unregister(dhd_bus_t *bus)
STATIC_ASSERT(sizeof(wl_pfn_net_info_v1_t) == sizeof(wl_pfn_net_info_v2_t));
STATIC_ASSERT(sizeof(wl_pfn_lnet_info_v1_t) == sizeof(wl_pfn_lnet_info_v2_t));
STATIC_ASSERT(sizeof(wl_pfn_subnet_info_v1_t) == sizeof(wl_pfn_subnet_info_v2_t));
- STATIC_ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) ==
+ ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) ==
OFFSETOF(wl_pfn_subnet_info_v2_t, u.SSID));
DHD_PNO(("%s enter\n", __FUNCTION__));
uint txglomframes; /* Number of tx glom frames (superframes) */
uint txglompkts; /* Number of packets from tx glom frames */
uint8 *membuf; /* Buffer for dhdsdio_membytes */
+#ifdef CONSOLE_DPC
+ char cons_cmd[16];
+#endif
} dhd_bus_t;
/*
if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
dhdsdio_sendpendctl(bus);
+#ifdef CONSOLE_DPC
+ else if (DATAOK(bus) && strlen(bus->cons_cmd) && (bus->clkstate == CLK_AVAIL) &&
+ !bus->fcstate) {
+ dhd_bus_console_in(bus->dhd, bus->cons_cmd, strlen(bus->cons_cmd));
+ }
+#endif
/* Send queued frames (limit 1 if rx may still be pending) */
else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
int rv;
void *pkt;
- /* Address could be zero if CONSOLE := 0 in dongle Makefile */
- if (bus->console_addr == 0)
- return BCME_UNSUPPORTED;
-
+#ifndef CONSOLE_DPC
/* Exclusive bus access */
dhd_os_sdlock(bus->dhd);
+#endif
+
+ /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+ if (bus->console_addr == 0) {
+ rv = BCME_UNSUPPORTED;
+ goto exit;
+ }
/* Don't allow input if dongle is in reset */
if (bus->dhd->dongle_reset) {
- dhd_os_sdunlock(bus->dhd);
- return BCME_NOTREADY;
+ rv = BCME_NOTREADY;
+ goto exit;
+ }
+
+#ifndef CONSOLE_DPC
+ if (!DATAOK(bus)) {
+ DHD_CTL(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d, pktq_len %d\n",
+ __FUNCTION__, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
+ rv = BCME_NOTREADY;
+ goto exit;
}
/* Request clock to allow SDIO accesses */
BUS_WAKE(bus);
/* No pend allowed since txpkt is called later, ht clk has to be on */
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+#endif
/* Zero cbuf_index */
addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx);
if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
goto done;
- if (!DATAOK(bus)) {
- rv = BCME_NOTREADY;
- goto done;
- }
-
/* Bump dongle by sending an empty packet on the event channel.
* sdpcm_sendup (RX) checks for virtual console input.
*/
rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
done:
+#ifndef CONSOLE_DPC
if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
NO_OTHER_ACTIVE_BUS_USER(bus)) {
bus->activity = FALSE;
dhdsdio_bussleep(bus, TRUE);
dhdsdio_clkctl(bus, CLK_NONE, FALSE);
}
+#endif
+exit:
+#ifdef CONSOLE_DPC
+ memset(bus->cons_cmd, 0, sizeof(bus->cons_cmd));
+#else
dhd_os_sdunlock(bus->dhd);
-
+#endif
return rv;
}
+#ifdef CONSOLE_DPC
+extern int
+dhd_bus_txcons(dhd_pub_t *dhdp, uchar *msg, uint msglen)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ int ret = BCME_OK;
+
+ dhd_os_sdlock(bus->dhd);
+
+ /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+ if (bus->console_addr == 0) {
+ ret = BCME_UNSUPPORTED;
+ goto exit;
+ }
+
+ /* Don't allow input if dongle is in reset */
+ if (bus->dhd->dongle_reset) {
+ ret = BCME_NOTREADY;
+ goto exit;
+ }
+
+ if (msglen >= sizeof(bus->cons_cmd)) {
+ DHD_ERROR(("%s: \"%s\"(%d) too long\n", __FUNCTION__, msg, msglen));
+ ret = BCME_BADARG;
+ goto exit;
+ }
+
+ if (!strlen(bus->cons_cmd)) {
+ strncpy(bus->cons_cmd, msg, sizeof(bus->cons_cmd));
+ DHD_CTL(("%s: \"%s\" delay send, tx_max %d, tx_seq %d, pktq_len %d\n",
+ __FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
+ if (!bus->dpc_sched) {
+ bus->dpc_sched = TRUE;
+ dhd_sched_dpc(bus->dhd);
+ }
+ } else {
+ DHD_CTL(("%s: \"%s\" is pending, tx_max %d, tx_seq %d, pktq_len %d\n",
+ __FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
+ ret = BCME_NOTREADY;
+ }
+
+exit:
+ dhd_os_sdunlock(bus->dhd);
+
+ return ret;
+}
+#endif
+
#if defined(DHD_DEBUG) && !defined(BCMSDIOLITE)
static void
dhd_dump_cis(uint fn, uint8 *cis)
{
int ret;
dhd_bus_t *bus;
-#ifdef GET_OTP_MAC_ENABLE
- struct ether_addr ea_addr;
-#endif
DHD_MUTEX_LOCK();
goto fail;
}
+#if defined(GET_OTP_MAC_ENABLE) || defined(GET_OTP_MODULE_NAME)
+ dhd_conf_get_otp(bus->dhd, sdh, bus->sih);
+#endif
+
/* Allocate buffers */
if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
#endif /* BT_OVER_SDIO */
#ifdef GET_OTP_MAC_ENABLE
- if (dhd_conf_get_mac(bus->dhd, sdh, bus->sih, ea_addr.octet)) {
- DHD_TRACE(("%s: Can not read MAC address\n", __FUNCTION__));
- } else
- memcpy(bus->dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN);
+ if (memcmp(ðer_null, &bus->dhd->conf->otp_mac, ETHER_ADDR_LEN))
+ memcpy(bus->dhd->mac.octet, (void *)&bus->dhd->conf->otp_mac, ETHER_ADDR_LEN);
#endif /* GET_CUSTOM_MAC_ENABLE */
/* Ok, have the per-port tell the stack we're open for business */
__FUNCTION__, bus->fw_path, bus->nv_path));
DHD_OS_WAKE_LOCK(bus->dhd);
+ dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
+ dhd_set_bus_params(bus);
+
/* Download the firmware */
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
- dhd_conf_set_path_params(bus->dhd, bus->sdh, bus->sih, bus->fw_path, bus->nv_path);
- dhd_set_bus_params(bus);
-
ret = _dhdsdio_download_firmware(bus);
dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
return bcmsdh_set_get_wake(dhd->bus->sdh, 0);
}
#endif /* DHD_WAKE_STATUS */
+
+int
+dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ uint32 retry = 0;
+ int ret = 0;
+
+ if (bus) {
+ dhd_os_sdlock(dhdp);
+ BUS_WAKE(bus);
+ R_SDREG(*intstatus, &bus->regs->intstatus, retry);
+ if (sleep) {
+ if (SLPAUTO_ENAB(bus)) {
+ ret = dhdsdio_bussleep(bus, sleep);
+ if (ret != BCME_BUSY)
+ dhd_os_wd_timer(bus->dhd, 0);
+ } else
+ dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+ }
+ dhd_os_sdunlock(dhdp);
+ } else {
+ DHD_ERROR(("bus is NULL\n"));
+ ret = -1;
+ }
+
+ return ret;
+}
\ No newline at end of file
-/*
- * 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/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/skbuff.h>
-#include <linux/wlan_plat.h>
-#include <linux/amlogic/dhd_buf.h>
-
-#define DHD_STATIC_VERSION_STR "100.10.545.3"
-
-#define BCMDHD_SDIO
-#define BCMDHD_PCIE
-
-enum dhd_prealloc_index {
- DHD_PREALLOC_PROT = 0,
-#if defined(BCMDHD_SDIO)
- DHD_PREALLOC_RXBUF = 1,
- DHD_PREALLOC_DATABUF = 2,
-#endif
- DHD_PREALLOC_OSL_BUF = 3,
- DHD_PREALLOC_SKB_BUF = 4,
- DHD_PREALLOC_WIPHY_ESCAN0 = 5,
- DHD_PREALLOC_WIPHY_ESCAN1 = 6,
- DHD_PREALLOC_DHD_INFO = 7,
- DHD_PREALLOC_DHD_WLFC_INFO = 8,
-#ifdef BCMDHD_PCIE
- DHD_PREALLOC_IF_FLOW_LKUP = 9,
-#endif
- DHD_PREALLOC_MEMDUMP_BUF = 10,
- DHD_PREALLOC_MEMDUMP_RAM = 11,
- DHD_PREALLOC_DHD_WLFC_HANGER = 12,
- DHD_PREALLOC_PKTID_MAP = 13,
- DHD_PREALLOC_PKTID_MAP_IOCTL = 14,
- DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15,
- DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16,
- DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17,
- DHD_PREALLOC_STAT_REPORT_BUF = 18,
- DHD_PREALLOC_WL_WEXT_INFO = 19,
- DHD_PREALLOC_FW_VERBOSE_RING = 20,
- DHD_PREALLOC_FW_EVENT_RING = 21,
- DHD_PREALLOC_DHD_EVENT_RING = 22,
- DHD_PREALLOC_NAN_EVENT_RING = 23,
- DHD_PREALLOC_MAX
-};
-
-#define STATIC_BUF_MAX_NUM 20
-#define STATIC_BUF_SIZE (PAGE_SIZE*2)
-
-#define DHD_PREALLOC_PROT_SIZE (16 * 1024)
-#define DHD_PREALLOC_RXBUF_SIZE (24 * 1024)
-#define DHD_PREALLOC_DATABUF_SIZE (64 * 1024)
-#define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
-#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)
-#define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024)
-#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024)
-#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024)
-#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB)
-#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024)
-#define DHD_PREALLOC_WL_WEXT_INFO_SIZE (70 * 1024)
-#ifdef CONFIG_64BIT
-#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2)
-#else
-#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024)
-#endif
-#define FW_VERBOSE_RING_SIZE (256 * 1024)
-#define FW_EVENT_RING_SIZE (64 * 1024)
-#define DHD_EVENT_RING_SIZE (64 * 1024)
-#define NAN_EVENT_RING_SIZE (64 * 1024)
-
-#if defined(CONFIG_64BIT)
-#define WLAN_DHD_INFO_BUF_SIZE (24 * 1024)
-#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)
-#define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024)
-#else
-#define WLAN_DHD_INFO_BUF_SIZE (16 * 1024)
-#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)
-#define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024)
-#endif /* CONFIG_64BIT */
-#define WLAN_DHD_MEMDUMP_SIZE (800 * 1024)
-
-#define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE*1)
-#define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE*2)
-#define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE*4)
-
-#define DHD_SKB_1PAGE_BUF_NUM 8
-#define DHD_SKB_2PAGE_BUF_NUM 64
-#define DHD_SKB_4PAGE_BUF_NUM 1
-
-/* The number is defined in linux_osl.c
- * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM
- * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM
- */
-#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \
- (DHD_SKB_2PAGE_BUF_NUM))
-#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM))
-
-void *wlan_static_prot;
-void *wlan_static_rxbuf;
-void *wlan_static_databuf;
-void *wlan_static_osl_buf;
-void *wlan_static_scan_buf0;
-void *wlan_static_scan_buf1;
-void *wlan_static_dhd_info_buf;
-void *wlan_static_dhd_wlfc_info_buf;
-void *wlan_static_if_flow_lkup;
-void *wlan_static_dhd_memdump_ram_buf;
-void *wlan_static_dhd_wlfc_hanger_buf;
-void *wlan_static_dhd_log_dump_buf;
-void *wlan_static_dhd_log_dump_buf_ex;
-void *wlan_static_wl_escan_info_buf;
-void *wlan_static_fw_verbose_ring_buf;
-void *wlan_static_fw_event_ring_buf;
-void *wlan_static_dhd_event_ring_buf;
-void *wlan_static_nan_event_ring_buf;
-
-static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
-
-void *bcmdhd_mem_prealloc(int section, unsigned long size)
-{
- pr_info("sectoin %d, size %ld\n", section, size);
- if (section == DHD_PREALLOC_PROT)
- return wlan_static_prot;
-
-#if defined(BCMDHD_SDIO)
- if (section == DHD_PREALLOC_RXBUF)
- return wlan_static_rxbuf;
-
- if (section == DHD_PREALLOC_DATABUF)
- return wlan_static_databuf;
-#endif /* BCMDHD_SDIO */
-
- if (section == DHD_PREALLOC_SKB_BUF)
- return wlan_static_skb;
-
- if (section == DHD_PREALLOC_WIPHY_ESCAN0)
- return wlan_static_scan_buf0;
-
- if (section == DHD_PREALLOC_WIPHY_ESCAN1)
- return wlan_static_scan_buf1;
-
- if (section == DHD_PREALLOC_OSL_BUF) {
- if (size > DHD_PREALLOC_OSL_BUF_SIZE) {
- pr_err("request OSL_BUF(%lu) > %ld\n",
- size, DHD_PREALLOC_OSL_BUF_SIZE);
- return NULL;
- }
- return wlan_static_osl_buf;
- }
-
- if (section == DHD_PREALLOC_DHD_INFO) {
- if (size > DHD_PREALLOC_DHD_INFO_SIZE) {
- pr_err("request DHD_INFO size(%lu) > %d\n",
- size, DHD_PREALLOC_DHD_INFO_SIZE);
- return NULL;
- }
- return wlan_static_dhd_info_buf;
- }
- if (section == DHD_PREALLOC_DHD_WLFC_INFO) {
- if (size > WLAN_DHD_WLFC_BUF_SIZE) {
- pr_err("request DHD_WLFC_INFO size(%lu) > %d\n",
- size, WLAN_DHD_WLFC_BUF_SIZE);
- return NULL;
- }
- return wlan_static_dhd_wlfc_info_buf;
- }
-#ifdef BCMDHD_PCIE
- if (section == DHD_PREALLOC_IF_FLOW_LKUP) {
- if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) {
- pr_err("request DHD_IF_FLOW_LKUP size(%lu) > %d\n",
- size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);
- return NULL;
- }
-
- return wlan_static_if_flow_lkup;
- }
-#endif /* BCMDHD_PCIE */
- if (section == DHD_PREALLOC_MEMDUMP_RAM) {
- if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) {
- pr_err("request DHD_PREALLOC_MEMDUMP_RAM_SIZE(%lu) > %d\n",
- size, DHD_PREALLOC_MEMDUMP_RAM_SIZE);
- return NULL;
- }
-
- return wlan_static_dhd_memdump_ram_buf;
- }
- if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {
- if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {
- pr_err("request DHD_WLFC_HANGER size(%lu) > %d\n",
- size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);
- return NULL;
- }
- return wlan_static_dhd_wlfc_hanger_buf;
- }
- if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF) {
- if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE) {
- pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE(%lu) > %d\n",
- size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE);
- return NULL;
- }
-
- return wlan_static_dhd_log_dump_buf;
- }
- if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX) {
- if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE) {
- pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE(%lu) > %d\n",
- size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE);
- return NULL;
- }
-
- return wlan_static_dhd_log_dump_buf_ex;
- }
- if (section == DHD_PREALLOC_WL_WEXT_INFO) {
- if (size > DHD_PREALLOC_WL_WEXT_INFO_SIZE) {
- pr_err("request DHD_PREALLOC_WL_WEXT_INFO_SIZE(%lu) > %d\n",
- size, DHD_PREALLOC_WL_WEXT_INFO_SIZE);
- return NULL;
- }
-
- return wlan_static_wl_escan_info_buf;
- }
- if (section == DHD_PREALLOC_FW_VERBOSE_RING) {
- if (size > FW_VERBOSE_RING_SIZE) {
- pr_err("request DHD_PREALLOC_FW_VERBOSE_RING(%lu) > %d\n",
- size, FW_VERBOSE_RING_SIZE);
- return NULL;
- }
-
- return wlan_static_fw_verbose_ring_buf;
- }
- if (section == DHD_PREALLOC_FW_EVENT_RING) {
- if (size > FW_EVENT_RING_SIZE) {
- pr_err("request DHD_PREALLOC_FW_EVENT_RING(%lu) > %d\n",
- size, FW_EVENT_RING_SIZE);
- return NULL;
- }
-
- return wlan_static_fw_event_ring_buf;
- }
- if (section == DHD_PREALLOC_DHD_EVENT_RING) {
- if (size > DHD_EVENT_RING_SIZE) {
- pr_err("request DHD_PREALLOC_DHD_EVENT_RING(%lu) > %d\n",
- size, DHD_EVENT_RING_SIZE);
- return NULL;
- }
-
- return wlan_static_dhd_event_ring_buf;
- }
- if (section == DHD_PREALLOC_NAN_EVENT_RING) {
- if (size > NAN_EVENT_RING_SIZE) {
- pr_err("request DHD_PREALLOC_NAN_EVENT_RING(%lu) > %d\n",
- size, NAN_EVENT_RING_SIZE);
- return NULL;
- }
-
- return wlan_static_nan_event_ring_buf;
- }
- if ((section < 0) || (section > DHD_PREALLOC_MAX))
- pr_err("request section id(%d) is out of max index %d\n",
- section, DHD_PREALLOC_MAX);
-
- pr_err("%s: failed to alloc section %d, size=%ld\n",
- __func__, section, size);
-
- return NULL;
-}
-EXPORT_SYMBOL(bcmdhd_mem_prealloc);
-
-int bcmdhd_init_wlan_mem(void)
-{
- int i;
- int j;
- pr_info("%s(): %s\n", __func__, DHD_STATIC_VERSION_STR);
-
- for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {
- wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);
- if (!wlan_static_skb[i])
- goto err_skb_alloc;
- }
-
- for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {
- wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);
- if (!wlan_static_skb[i])
- goto err_skb_alloc;
- }
-
-#if defined(BCMDHD_SDIO)
- wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);
- if (!wlan_static_skb[i])
- goto err_skb_alloc;
-#endif /* BCMDHD_SDIO */
-
- wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL);
- if (!wlan_static_prot)
- goto err_mem_alloc;
-
-#if defined(BCMDHD_SDIO)
- wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL);
- if (!wlan_static_rxbuf)
- goto err_mem_alloc;
-
- wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL);
- if (!wlan_static_databuf)
- goto err_mem_alloc;
-#endif /* BCMDHD_SDIO */
-
- wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL);
- if (!wlan_static_osl_buf)
- goto err_mem_alloc;
-
- wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);
- if (!wlan_static_scan_buf0)
- goto err_mem_alloc;
-
- wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL);
- if (!wlan_static_dhd_info_buf)
- goto err_mem_alloc;
-
- wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL);
- if (!wlan_static_dhd_wlfc_info_buf)
- goto err_mem_alloc;
-
-#ifdef BCMDHD_PCIE
- wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);
- if (!wlan_static_if_flow_lkup)
- goto err_mem_alloc;
-#endif /* BCMDHD_PCIE */
-
- wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL);
- if (!wlan_static_dhd_memdump_ram_buf)
- goto err_mem_alloc;
-
- wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);
- if (!wlan_static_dhd_wlfc_hanger_buf)
- goto err_mem_alloc;
-
- wlan_static_dhd_log_dump_buf = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE, GFP_KERNEL);
- if (!wlan_static_dhd_log_dump_buf)
- goto err_mem_alloc;
-
- wlan_static_dhd_log_dump_buf_ex = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE, GFP_KERNEL);
- if (!wlan_static_dhd_log_dump_buf_ex)
- goto err_mem_alloc;
-
- wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_WEXT_INFO_SIZE, GFP_KERNEL);
- if (!wlan_static_wl_escan_info_buf)
- goto err_mem_alloc;
-
- wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL);
- if (!wlan_static_fw_verbose_ring_buf)
- goto err_mem_alloc;
-
- wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL);
- if (!wlan_static_fw_event_ring_buf)
- goto err_mem_alloc;
-
- wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL);
- if (!wlan_static_dhd_event_ring_buf)
- goto err_mem_alloc;
-
- wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL);
- if (!wlan_static_nan_event_ring_buf)
- goto err_mem_alloc;
-
- pr_info("bcmdhd_init_wlan_mem prealloc ok\n");
- return 0;
-
-err_mem_alloc:
-
- if (wlan_static_prot)
- kfree(wlan_static_prot);
-
-#if defined(BCMDHD_SDIO)
- if (wlan_static_rxbuf)
- kfree(wlan_static_rxbuf);
-
- if (wlan_static_databuf)
- kfree(wlan_static_databuf);
-#endif /* BCMDHD_SDIO */
-
- if (wlan_static_osl_buf)
- kfree(wlan_static_osl_buf);
-
- if (wlan_static_scan_buf0)
- kfree(wlan_static_scan_buf0);
-
- if (wlan_static_scan_buf1)
- kfree(wlan_static_scan_buf1);
-
- if (wlan_static_dhd_info_buf)
- kfree(wlan_static_dhd_info_buf);
-
- if (wlan_static_dhd_wlfc_info_buf)
- kfree(wlan_static_dhd_wlfc_info_buf);
-
-#ifdef BCMDHD_PCIE
- if (wlan_static_if_flow_lkup)
- kfree(wlan_static_if_flow_lkup);
-#endif /* BCMDHD_PCIE */
-
- if (wlan_static_dhd_memdump_ram_buf)
- kfree(wlan_static_dhd_memdump_ram_buf);
-
- if (wlan_static_dhd_wlfc_hanger_buf)
- kfree(wlan_static_dhd_wlfc_hanger_buf);
-
- if (wlan_static_dhd_log_dump_buf)
- kfree(wlan_static_dhd_log_dump_buf);
-
- if (wlan_static_dhd_log_dump_buf_ex)
- kfree(wlan_static_dhd_log_dump_buf_ex);
-
- if (wlan_static_wl_escan_info_buf)
- kfree(wlan_static_wl_escan_info_buf);
-
-#ifdef BCMDHD_PCIE
- if (wlan_static_fw_verbose_ring_buf)
- kfree(wlan_static_fw_verbose_ring_buf);
-
- if (wlan_static_fw_event_ring_buf)
- kfree(wlan_static_fw_event_ring_buf);
-
- if (wlan_static_dhd_event_ring_buf)
- kfree(wlan_static_dhd_event_ring_buf);
-
- if (wlan_static_nan_event_ring_buf)
- kfree(wlan_static_nan_event_ring_buf);
-#endif /* BCMDHD_PCIE */
-
- pr_err("%s: Failed to mem_alloc for WLAN\n", __func__);
-
- i = WLAN_SKB_BUF_NUM;
-
-err_skb_alloc:
- pr_err("%s: Failed to skb_alloc for WLAN\n", __func__);
- for (j = 0; j < i; j++)
- dev_kfree_skb(wlan_static_skb[j]);
-
- return -ENOMEM;
-}
-EXPORT_SYMBOL(bcmdhd_init_wlan_mem);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("AMLOGIC");
-MODULE_DESCRIPTION("wifi device tree driver");
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/init.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/delay.h>\r
+#include <linux/err.h>\r
+#include <linux/skbuff.h>\r
+\r
+#define DHD_STATIC_VERSION_STR "100.10.545.7 (r826445-20200110-2)"\r
+\r
+#define BCMDHD_SDIO\r
+#define BCMDHD_PCIE\r
+\r
+enum dhd_prealloc_index {\r
+ DHD_PREALLOC_PROT = 0,\r
+#if defined(BCMDHD_SDIO)\r
+ DHD_PREALLOC_RXBUF = 1,\r
+ DHD_PREALLOC_DATABUF = 2,\r
+#endif\r
+ DHD_PREALLOC_OSL_BUF = 3,\r
+ DHD_PREALLOC_SKB_BUF = 4,\r
+ DHD_PREALLOC_WIPHY_ESCAN0 = 5,\r
+ DHD_PREALLOC_WIPHY_ESCAN1 = 6,\r
+ DHD_PREALLOC_DHD_INFO = 7,\r
+ DHD_PREALLOC_DHD_WLFC_INFO = 8,\r
+#ifdef BCMDHD_PCIE\r
+ DHD_PREALLOC_IF_FLOW_LKUP = 9,\r
+#endif\r
+ DHD_PREALLOC_MEMDUMP_BUF = 10,\r
+ DHD_PREALLOC_MEMDUMP_RAM = 11,\r
+ DHD_PREALLOC_DHD_WLFC_HANGER = 12,\r
+ DHD_PREALLOC_PKTID_MAP = 13,\r
+ DHD_PREALLOC_PKTID_MAP_IOCTL = 14,\r
+ DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15,\r
+ DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16,\r
+ DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17,\r
+ DHD_PREALLOC_STAT_REPORT_BUF = 18,\r
+ DHD_PREALLOC_WL_ESCAN = 19,\r
+ DHD_PREALLOC_FW_VERBOSE_RING = 20,\r
+ DHD_PREALLOC_FW_EVENT_RING = 21,\r
+ DHD_PREALLOC_DHD_EVENT_RING = 22,\r
+ DHD_PREALLOC_NAN_EVENT_RING = 23,\r
+ DHD_PREALLOC_MAX\r
+};\r
+\r
+#define STATIC_BUF_MAX_NUM 20\r
+#define STATIC_BUF_SIZE (PAGE_SIZE*2)\r
+\r
+#ifndef CUSTOM_LOG_DUMP_BUFSIZE_MB\r
+#define CUSTOM_LOG_DUMP_BUFSIZE_MB 4 /* DHD_LOG_DUMP_BUF_SIZE 4 MB static memory in kernel */\r
+#endif /* CUSTOM_LOG_DUMP_BUFSIZE_MB */\r
+\r
+#define DHD_PREALLOC_PROT_SIZE (16 * 1024)\r
+#define DHD_PREALLOC_RXBUF_SIZE (24 * 1024)\r
+#define DHD_PREALLOC_DATABUF_SIZE (64 * 1024)\r
+#define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)\r
+#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)\r
+#define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024)\r
+#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024)\r
+#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024)\r
+#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB)\r
+#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024)\r
+#define DHD_PREALLOC_WL_ESCAN_SIZE (70 * 1024)\r
+#ifdef CONFIG_64BIT\r
+#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2)\r
+#else\r
+#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024)\r
+#endif\r
+#define FW_VERBOSE_RING_SIZE (256 * 1024)\r
+#define FW_EVENT_RING_SIZE (64 * 1024)\r
+#define DHD_EVENT_RING_SIZE (64 * 1024)\r
+#define NAN_EVENT_RING_SIZE (64 * 1024)\r
+\r
+#if defined(CONFIG_64BIT)\r
+#define WLAN_DHD_INFO_BUF_SIZE (24 * 1024)\r
+#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)\r
+#define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024)\r
+#else\r
+#define WLAN_DHD_INFO_BUF_SIZE (16 * 1024)\r
+#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)\r
+#define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024)\r
+#endif /* CONFIG_64BIT */\r
+#define WLAN_DHD_MEMDUMP_SIZE (800 * 1024)\r
+\r
+#define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE*1)\r
+#define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE*2)\r
+#define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE*4)\r
+\r
+#define DHD_SKB_1PAGE_BUF_NUM 8\r
+#ifdef BCMDHD_PCIE\r
+#define DHD_SKB_2PAGE_BUF_NUM 64\r
+#elif defined(BCMDHD_SDIO)\r
+#define DHD_SKB_2PAGE_BUF_NUM 8\r
+#endif\r
+#define DHD_SKB_4PAGE_BUF_NUM 1\r
+\r
+/* The number is defined in linux_osl.c\r
+ * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM\r
+ * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM\r
+ */\r
+#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \\r
+ (DHD_SKB_2PAGE_BUF_NUM))\r
+#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM))\r
+\r
+void *wlan_static_prot = NULL;\r
+void *wlan_static_rxbuf = NULL;\r
+void *wlan_static_databuf = NULL;\r
+void *wlan_static_osl_buf = NULL;\r
+void *wlan_static_scan_buf0 = NULL;\r
+void *wlan_static_scan_buf1 = NULL;\r
+void *wlan_static_dhd_info_buf = NULL;\r
+void *wlan_static_dhd_wlfc_info_buf = NULL;\r
+void *wlan_static_if_flow_lkup = NULL;\r
+void *wlan_static_dhd_memdump_ram_buf = NULL;\r
+void *wlan_static_dhd_wlfc_hanger_buf = NULL;\r
+void *wlan_static_dhd_log_dump_buf = NULL;\r
+void *wlan_static_dhd_log_dump_buf_ex = NULL;\r
+void *wlan_static_wl_escan_info_buf = NULL;\r
+void *wlan_static_fw_verbose_ring_buf = NULL;\r
+void *wlan_static_fw_event_ring_buf = NULL;\r
+void *wlan_static_dhd_event_ring_buf = NULL;\r
+void *wlan_static_nan_event_ring_buf = NULL;\r
+\r
+static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];\r
+\r
+void *dhd_wlan_mem_prealloc(int section, unsigned long size)\r
+{\r
+ pr_err("%s: sectoin %d, %ld\n", __func__, section, size);\r
+ if (section == DHD_PREALLOC_PROT)\r
+ return wlan_static_prot;\r
+\r
+#if defined(BCMDHD_SDIO)\r
+ if (section == DHD_PREALLOC_RXBUF)\r
+ return wlan_static_rxbuf;\r
+\r
+ if (section == DHD_PREALLOC_DATABUF)\r
+ return wlan_static_databuf;\r
+#endif /* BCMDHD_SDIO */\r
+\r
+ if (section == DHD_PREALLOC_SKB_BUF)\r
+ return wlan_static_skb;\r
+\r
+ if (section == DHD_PREALLOC_WIPHY_ESCAN0)\r
+ return wlan_static_scan_buf0;\r
+\r
+ if (section == DHD_PREALLOC_WIPHY_ESCAN1)\r
+ return wlan_static_scan_buf1;\r
+\r
+ if (section == DHD_PREALLOC_OSL_BUF) {\r
+ if (size > DHD_PREALLOC_OSL_BUF_SIZE) {\r
+ pr_err("request OSL_BUF(%lu) > %ld\n",\r
+ size, DHD_PREALLOC_OSL_BUF_SIZE);\r
+ return NULL;\r
+ }\r
+ return wlan_static_osl_buf;\r
+ }\r
+\r
+ if (section == DHD_PREALLOC_DHD_INFO) {\r
+ if (size > DHD_PREALLOC_DHD_INFO_SIZE) {\r
+ pr_err("request DHD_INFO size(%lu) > %d\n",\r
+ size, DHD_PREALLOC_DHD_INFO_SIZE);\r
+ return NULL;\r
+ }\r
+ return wlan_static_dhd_info_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_DHD_WLFC_INFO) {\r
+ if (size > WLAN_DHD_WLFC_BUF_SIZE) {\r
+ pr_err("request DHD_WLFC_INFO size(%lu) > %d\n",\r
+ size, WLAN_DHD_WLFC_BUF_SIZE);\r
+ return NULL;\r
+ }\r
+ return wlan_static_dhd_wlfc_info_buf;\r
+ }\r
+#ifdef BCMDHD_PCIE\r
+ if (section == DHD_PREALLOC_IF_FLOW_LKUP) {\r
+ if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) {\r
+ pr_err("request DHD_IF_FLOW_LKUP size(%lu) > %d\n",\r
+ size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_if_flow_lkup;\r
+ }\r
+#endif /* BCMDHD_PCIE */\r
+ if (section == DHD_PREALLOC_MEMDUMP_RAM) {\r
+ if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) {\r
+ pr_err("request DHD_PREALLOC_MEMDUMP_RAM_SIZE(%lu) > %d\n",\r
+ size, DHD_PREALLOC_MEMDUMP_RAM_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_dhd_memdump_ram_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {\r
+ if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {\r
+ pr_err("request DHD_WLFC_HANGER size(%lu) > %d\n",\r
+ size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);\r
+ return NULL;\r
+ }\r
+ return wlan_static_dhd_wlfc_hanger_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF) {\r
+ if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE) {\r
+ pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE(%lu) > %d\n",\r
+ size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_dhd_log_dump_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX) {\r
+ if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE) {\r
+ pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE(%lu) > %d\n",\r
+ size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_dhd_log_dump_buf_ex;\r
+ }\r
+ if (section == DHD_PREALLOC_WL_ESCAN) {\r
+ if (size > DHD_PREALLOC_WL_ESCAN_SIZE) {\r
+ pr_err("request DHD_PREALLOC_WL_ESCAN_SIZE(%lu) > %d\n",\r
+ size, DHD_PREALLOC_WL_ESCAN_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_wl_escan_info_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_FW_VERBOSE_RING) {\r
+ if (size > FW_VERBOSE_RING_SIZE) {\r
+ pr_err("request DHD_PREALLOC_FW_VERBOSE_RING(%lu) > %d\n",\r
+ size, FW_VERBOSE_RING_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_fw_verbose_ring_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_FW_EVENT_RING) {\r
+ if (size > FW_EVENT_RING_SIZE) {\r
+ pr_err("request DHD_PREALLOC_FW_EVENT_RING(%lu) > %d\n",\r
+ size, FW_EVENT_RING_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_fw_event_ring_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_DHD_EVENT_RING) {\r
+ if (size > DHD_EVENT_RING_SIZE) {\r
+ pr_err("request DHD_PREALLOC_DHD_EVENT_RING(%lu) > %d\n",\r
+ size, DHD_EVENT_RING_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_dhd_event_ring_buf;\r
+ }\r
+ if (section == DHD_PREALLOC_NAN_EVENT_RING) {\r
+ if (size > NAN_EVENT_RING_SIZE) {\r
+ pr_err("request DHD_PREALLOC_NAN_EVENT_RING(%lu) > %d\n",\r
+ size, NAN_EVENT_RING_SIZE);\r
+ return NULL;\r
+ }\r
+\r
+ return wlan_static_nan_event_ring_buf;\r
+ }\r
+ if ((section < 0) || (section > DHD_PREALLOC_MAX))\r
+ pr_err("request section id(%d) is out of max index %d\n",\r
+ section, DHD_PREALLOC_MAX);\r
+\r
+ pr_err("%s: failed to alloc section %d, size=%ld\n",\r
+ __func__, section, size);\r
+\r
+ return NULL;\r
+}\r
+EXPORT_SYMBOL(dhd_wlan_mem_prealloc);\r
+\r
+static int dhd_init_wlan_mem(void)\r
+{\r
+ int i;\r
+ int j;\r
+ printk(KERN_ERR "%s(): %s\n", __func__, DHD_STATIC_VERSION_STR);\r
+\r
+ for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {\r
+ wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);\r
+ if (!wlan_static_skb[i]) {\r
+ goto err_skb_alloc;\r
+ }\r
+ pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__,\r
+ DHD_PREALLOC_SKB_BUF, i, DHD_SKB_1PAGE_BUFSIZE);\r
+ }\r
+\r
+ for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {\r
+ wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);\r
+ if (!wlan_static_skb[i]) {\r
+ goto err_skb_alloc;\r
+ }\r
+ pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__,\r
+ DHD_PREALLOC_SKB_BUF, i, DHD_SKB_2PAGE_BUFSIZE);\r
+ }\r
+\r
+#if defined(BCMDHD_SDIO)\r
+ wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);\r
+ if (!wlan_static_skb[i])\r
+ goto err_skb_alloc;\r
+ pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__,\r
+ DHD_PREALLOC_SKB_BUF, i, DHD_SKB_4PAGE_BUFSIZE);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+ wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_prot)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_PROT, DHD_PREALLOC_PROT_SIZE);\r
+\r
+#if defined(BCMDHD_SDIO)\r
+ wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_rxbuf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_RXBUF, DHD_PREALLOC_RXBUF_SIZE);\r
+\r
+ wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_databuf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_DATABUF, DHD_PREALLOC_DATABUF_SIZE);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+ wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_osl_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%ld\n", __func__,\r
+ DHD_PREALLOC_OSL_BUF, DHD_PREALLOC_OSL_BUF_SIZE);\r
+\r
+ wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_scan_buf0)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_WIPHY_ESCAN0, DHD_PREALLOC_WIPHY_ESCAN0_SIZE);\r
+\r
+ wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_dhd_info_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_DHD_INFO, DHD_PREALLOC_DHD_INFO_SIZE);\r
+\r
+ wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_dhd_wlfc_info_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_DHD_WLFC_INFO, WLAN_DHD_WLFC_BUF_SIZE);\r
+\r
+#ifdef BCMDHD_PCIE\r
+ wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_if_flow_lkup)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_IF_FLOW_LKUP, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+ wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_dhd_memdump_ram_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_MEMDUMP_RAM, DHD_PREALLOC_MEMDUMP_RAM_SIZE);\r
+\r
+ wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_dhd_wlfc_hanger_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_DHD_WLFC_HANGER, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);\r
+\r
+ wlan_static_dhd_log_dump_buf = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_dhd_log_dump_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_DHD_LOG_DUMP_BUF, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE);\r
+\r
+ wlan_static_dhd_log_dump_buf_ex = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_dhd_log_dump_buf_ex)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE);\r
+\r
+ wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_ESCAN_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_wl_escan_info_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_WL_ESCAN, DHD_PREALLOC_WL_ESCAN_SIZE);\r
+\r
+ wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_fw_verbose_ring_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_FW_VERBOSE_RING, FW_VERBOSE_RING_SIZE);\r
+\r
+ wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_fw_event_ring_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_FW_EVENT_RING, FW_EVENT_RING_SIZE);\r
+\r
+ wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_dhd_event_ring_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_DHD_EVENT_RING, DHD_EVENT_RING_SIZE);\r
+\r
+ wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL);\r
+ if (!wlan_static_nan_event_ring_buf)\r
+ goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_NAN_EVENT_RING, NAN_EVENT_RING_SIZE);\r
+\r
+ return 0;\r
+\r
+err_mem_alloc:\r
+\r
+ if (wlan_static_prot)\r
+ kfree(wlan_static_prot);\r
+\r
+#if defined(BCMDHD_SDIO)\r
+ if (wlan_static_rxbuf)\r
+ kfree(wlan_static_rxbuf);\r
+\r
+ if (wlan_static_databuf)\r
+ kfree(wlan_static_databuf);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+ if (wlan_static_osl_buf)\r
+ kfree(wlan_static_osl_buf);\r
+\r
+ if (wlan_static_scan_buf0)\r
+ kfree(wlan_static_scan_buf0);\r
+\r
+ if (wlan_static_scan_buf1)\r
+ kfree(wlan_static_scan_buf1);\r
+\r
+ if (wlan_static_dhd_info_buf)\r
+ kfree(wlan_static_dhd_info_buf);\r
+\r
+ if (wlan_static_dhd_wlfc_info_buf)\r
+ kfree(wlan_static_dhd_wlfc_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+ if (wlan_static_if_flow_lkup)\r
+ kfree(wlan_static_if_flow_lkup);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+ if (wlan_static_dhd_memdump_ram_buf)\r
+ kfree(wlan_static_dhd_memdump_ram_buf);\r
+\r
+ if (wlan_static_dhd_wlfc_hanger_buf)\r
+ kfree(wlan_static_dhd_wlfc_hanger_buf);\r
+\r
+ if (wlan_static_dhd_log_dump_buf)\r
+ kfree(wlan_static_dhd_log_dump_buf);\r
+\r
+ if (wlan_static_dhd_log_dump_buf_ex)\r
+ kfree(wlan_static_dhd_log_dump_buf_ex);\r
+\r
+ if (wlan_static_wl_escan_info_buf)\r
+ kfree(wlan_static_wl_escan_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+ if (wlan_static_fw_verbose_ring_buf)\r
+ kfree(wlan_static_fw_verbose_ring_buf);\r
+\r
+ if (wlan_static_fw_event_ring_buf)\r
+ kfree(wlan_static_fw_event_ring_buf);\r
+\r
+ if (wlan_static_dhd_event_ring_buf)\r
+ kfree(wlan_static_dhd_event_ring_buf);\r
+\r
+ if (wlan_static_nan_event_ring_buf)\r
+ kfree(wlan_static_nan_event_ring_buf);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+ pr_err("%s: Failed to mem_alloc for WLAN\n", __func__);\r
+\r
+ i = WLAN_SKB_BUF_NUM;\r
+\r
+err_skb_alloc:\r
+ pr_err("%s: Failed to skb_alloc for WLAN\n", __func__);\r
+ for (j = 0; j < i; j++)\r
+ dev_kfree_skb(wlan_static_skb[j]);\r
+\r
+ return -ENOMEM;\r
+}\r
+\r
+static int __init\r
+dhd_static_buf_init(void)\r
+{\r
+ dhd_init_wlan_mem();\r
+\r
+ return 0;\r
+}\r
+\r
+static void __exit\r
+dhd_static_buf_exit(void)\r
+{\r
+ int i;\r
+\r
+ pr_err("%s()\n", __FUNCTION__);\r
+\r
+ for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {\r
+ if (wlan_static_skb[i])\r
+ dev_kfree_skb(wlan_static_skb[i]);\r
+ }\r
+\r
+ for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {\r
+ if (wlan_static_skb[i])\r
+ dev_kfree_skb(wlan_static_skb[i]);\r
+ }\r
+\r
+#if defined(BCMDHD_SDIO)\r
+ if (wlan_static_skb[i])\r
+ dev_kfree_skb(wlan_static_skb[i]);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+ if (wlan_static_prot)\r
+ kfree(wlan_static_prot);\r
+\r
+#if defined(BCMDHD_SDIO)\r
+ if (wlan_static_rxbuf)\r
+ kfree(wlan_static_rxbuf);\r
+\r
+ if (wlan_static_databuf)\r
+ kfree(wlan_static_databuf);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+ if (wlan_static_osl_buf)\r
+ kfree(wlan_static_osl_buf);\r
+\r
+ if (wlan_static_scan_buf0)\r
+ kfree(wlan_static_scan_buf0);\r
+\r
+ if (wlan_static_scan_buf1)\r
+ kfree(wlan_static_scan_buf1);\r
+\r
+ if (wlan_static_dhd_info_buf)\r
+ kfree(wlan_static_dhd_info_buf);\r
+\r
+ if (wlan_static_dhd_wlfc_info_buf)\r
+ kfree(wlan_static_dhd_wlfc_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+ if (wlan_static_if_flow_lkup)\r
+ kfree(wlan_static_if_flow_lkup);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+ if (wlan_static_dhd_memdump_ram_buf)\r
+ kfree(wlan_static_dhd_memdump_ram_buf);\r
+\r
+ if (wlan_static_dhd_wlfc_hanger_buf)\r
+ kfree(wlan_static_dhd_wlfc_hanger_buf);\r
+\r
+ if (wlan_static_dhd_log_dump_buf)\r
+ kfree(wlan_static_dhd_log_dump_buf);\r
+\r
+ if (wlan_static_dhd_log_dump_buf_ex)\r
+ kfree(wlan_static_dhd_log_dump_buf_ex);\r
+\r
+ if (wlan_static_wl_escan_info_buf)\r
+ kfree(wlan_static_wl_escan_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+ if (wlan_static_fw_verbose_ring_buf)\r
+ kfree(wlan_static_fw_verbose_ring_buf);\r
+\r
+ if (wlan_static_fw_event_ring_buf)\r
+ kfree(wlan_static_fw_event_ring_buf);\r
+\r
+ if (wlan_static_dhd_event_ring_buf)\r
+ kfree(wlan_static_dhd_event_ring_buf);\r
+\r
+ if (wlan_static_nan_event_ring_buf)\r
+ kfree(wlan_static_nan_event_ring_buf);\r
+#endif\r
+\r
+ return;\r
+}\r
+\r
+module_init(dhd_static_buf_init);\r
+\r
+module_exit(dhd_static_buf_exit);\r
#include <dhd_dbg.h>
#include <dhd_config.h>
+#include <wl_android.h>
#ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */
#include <wlfc_proto.h>
ASSERT(entry);
if (entry->occupied && _dhd_wlfc_is_destination_open(ctx, entry, prec) &&
+#ifdef PROPTX_MAXCOUNT
+ (entry->transit_count < entry->transit_maxcount) &&
+#endif /* PROPTX_MAXCOUNT */
(entry->transit_count < WL_TXSTATUS_FREERUNCTR_MASK) &&
(!entry->suppressed)) {
*ac_credit_spent = credit_spent;
if (action == eWLFC_MAC_ENTRY_ACTION_ADD) {
entry->suppressed = FALSE;
entry->transit_count = 0;
+#ifdef PROPTX_MAXCOUNT
+ entry->transit_maxcount = wl_ext_get_wlfc_maxcount(ctx->dhdp, ifid);
+#endif /* PROPTX_MAXCOUNT */
entry->suppr_transit_count = 0;
entry->onbus_pkts_count = 0;
}
return BCME_OK;
}
+#ifdef PROPTX_MAXCOUNT
+int dhd_wlfc_update_maxcount(dhd_pub_t *dhdp, uint8 ifid, int maxcount)
+{
+ athost_wl_status_info_t* ctx;
+ int rc = 0;
+
+ if (dhdp == NULL) {
+ DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
+ return BCME_BADARG;
+ }
+
+ dhd_os_wlfc_block(dhdp);
+
+ if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+ rc = WLFC_UNSUPPORTED;
+ goto exit;
+ }
+
+ if (ifid >= WLFC_MAX_IFNUM) {
+ DHD_ERROR(("%s: bad ifid\n", __FUNCTION__));
+ rc = BCME_BADARG;
+ goto exit;
+ }
+
+ ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
+ ctx->destination_entries.interfaces[ifid].transit_maxcount = maxcount;
+exit:
+ dhd_os_wlfc_unblock(dhdp);
+ return rc;
+}
+#endif /* PROPTX_MAXCOUNT */
+
#endif /* PROP_TXSTATUS */
uint32 opened_ct;
uint32 closed_ct;
#endif // endif
+#ifdef PROPTX_MAXCOUNT
+ /** Max Number of packets at dongle for this entry. */
+ int transit_maxcount;
+#endif /* PROPTX_MAXCOUNT */
struct wlfc_mac_descriptor* prev;
struct wlfc_mac_descriptor* next;
} wlfc_mac_descriptor_t;
int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val);
int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val);
+#ifdef PROPTX_MAXCOUNT
+int dhd_wlfc_update_maxcount(dhd_pub_t *dhdp, uint8 ifid, int maxcount);
+#endif /* PROPTX_MAXCOUNT */
#endif /* __wlfc_host_driver_definitions_h__ */
#define BCM4362_D11AX_ID 0x4490 /* 4362 802.11ax dualband device */
#define BCM4362_D11AX2G_ID 0x4491 /* 4362 802.11ax 2.4G device */
#define BCM4362_D11AX5G_ID 0x4492 /* 4362 802.11ax 5G device */
-#define BCM43751_D11AX_ID 0x4490 /* 43751 802.11ax dualband device */
-#define BCM43751_D11AX2G_ID 0x4491 /* 43751 802.11ax 2.4G device */
-#define BCM43751_D11AX5G_ID 0x4492 /* 43751 802.11ax 5G device */
-#define BCM43752_D11AX_ID 0x4490 /* 43752 802.11ax dualband device */
-#define BCM43752_D11AX2G_ID 0x4491 /* 43752 802.11ax 2.4G device */
-#define BCM43752_D11AX5G_ID 0x4492 /* 43752 802.11ax 5G device */
+#define BCM43751_D11AX_ID 0x449a /* 43751 802.11ax dualband device */
+#define BCM43751_D11AX2G_ID 0x449b /* 43751 802.11ax 2.4G device */
+#define BCM43751_D11AX5G_ID 0x449c /* 43751 802.11ax 5G device */
+#define BCM43752_D11AX_ID 0x449d /* 43752 802.11ax dualband device */
+#define BCM43752_D11AX2G_ID 0x449e /* 43752 802.11ax 2.4G device */
+#define BCM43752_D11AX5G_ID 0x449f /* 43752 802.11ax 5G device */
#define BCM4364_D11AC_ID 0x4464 /* 4364 802.11ac dualband device */
#define BCM4364_D11AC2G_ID 0x446a /* 4364 802.11ac 2.4G device */
#define BCM4369_CHIP_GRPID BCM4369_CHIP_ID: \
case BCM4377_CHIP_ID
-#define BCM4362_CHIP(chipid) (CHIPID(chipid) == BCM4362_CHIP_ID)
-#define BCM4362_CHIP_GRPID BCM4362_CHIP_ID
+#define BCM4362_CHIP(chipid) ((CHIPID(chipid) == BCM4362_CHIP_ID) || \
+ (CHIPID(chipid) == BCM43751_CHIP_ID) || \
+ (CHIPID(chipid) == BCM43752_CHIP_ID))
+#define BCM4362_CHIP_GRPID BCM4362_CHIP_ID: \
+ case BCM43751_CHIP_ID: \
+ case BCM43752_CHIP_ID
#define BCM4365_CHIP_ID 0x4365 /* 4365 chipcommon chipid */
#define BCM4366_CHIP_ID 0x4366 /* 4366 chipcommon chipid */
#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */
#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */
#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */
+#ifdef CSI_SUPPORT
+#define WLC_E_CSI 63
+#else
#define WLC_E_CHANNEL_ADOPTED 63
+#endif /* CSI_SUPPORT */
#define WLC_E_AP_STARTED 64 /* AP started */
#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */
#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */
#define WLC_E_IF_ROLE_WDS 2 /* WDS link */
#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */
#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */
+#ifdef WLMESH_CFG80211
+#define WLC_E_IF_ROLE_MESH 5 /* MESH */
+#endif /* WLMESH_CFG80211 */
#define WLC_E_IF_ROLE_IBSS 8 /* IBSS */
#define WLC_E_IF_ROLE_NAN 9 /* NAN */
#define DHD_IW_VAL 0x20000
#define DHD_CFG_VAL 0x40000
#define DHD_CONFIG_VAL 0x80000
+#define DUMP_EAPOL_VAL 0x0001
+#define DUMP_ARP_VAL 0x0002
+#define DUMP_DHCP_VAL 0x0004
+#define DUMP_ICMP_VAL 0x0008
+#define DUMP_DNS_VAL 0x0010
+#define DUMP_TRX_VAL 0x0080
#ifdef SDTEST
/* For pktgen iovar */
#define EPI_VERSION_DEV 100.10.545
/* Driver Version String, ASCII, 32 chars max */
-#define EPI_VERSION_STR "100.10.545.4 (r826445-20190826-1) (amlogic-20190916-1)"
+#define EPI_VERSION_STR "100.10.545.11 (r826445-20200610-1)"
#endif /* _epivers_h_ */
#define OSL_LOCALTIME_NS() osl_localtime_ns()
#define OSL_GET_LOCALTIME(sec, usec) osl_get_localtime((sec), (usec))
#define OSL_SYSTZTIME_US() osl_systztime_us()
-#define printf(fmt, args...) printk(fmt , ## args)
+#define printf(fmt, args...) printk("[dhd] " fmt , ## args)
#include <linux/kernel.h> /* for vsn/printf's */
#include <linux/string.h> /* for mem*, str* */
/* bcopy's: Linux kernel doesn't provide these (anymore) */
/* map/unmap physical to virtual I/O */
#if !defined(CONFIG_MMC_MSM7X00A)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+#define REG_MAP(pa, size) ioremap((unsigned long)(pa), (unsigned long)(size))
+#else
#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size))
+#endif
#else
#define REG_MAP(pa, size) (void *)(0)
#endif /* !defined(CONFIG_MMC_MSM7X00A */
extern void osl_spin_unlock(void *lock, unsigned long flags);
typedef struct osl_timespec {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+ __kernel_old_time_t tv_sec; /* seconds */
+#else
__kernel_time_t tv_sec; /* seconds */
+#endif
__kernel_suseconds_t tv_usec; /* microseconds */
long tv_nsec; /* nanoseconds */
} osl_timespec_t;
WL_SC_CMD_LAST
};
+typedef struct wl_ext_auth_evt {
+ wlc_ssid_t ssid;
+ struct ether_addr bssid;
+ unsigned int key_mgmt_suite;
+ int status;
+} wl_ext_auth_evt_t;
+
/* WBUS sub-command IDs for unit test */
#define WL_WBUS_INA_SLOT_START 0x01u /**< Inactive slot start sub command ID. */
#define WL_WBUS_INA_SLOT_STOP 0x02u /**< Inactive slot stop sub command ID. */
#define WLC_GET_RSSI_QDB 321 /* qdB portion of the RSSI */
#define WLC_DUMP_RATESET 322
#define WLC_ECHO 323
-#define WLC_LAST 324 /* The last ioctl. Also push this
+#define WLC_SCB_AUTHENTICATE 325
+#define WLC_LAST 326 /* The last ioctl. Also push this
* number when adding new ioctls
*/
/*
#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */
+#define WL_AUTH_SAE_KEY 3 /* d11 sae authentication */
#define WL_AUTH_FILS_SHARED 4 /* d11 fils shared key authentication */
#define WL_AUTH_FILS_SHARED_PFS 5 /* d11 fils shared key w/ pfs authentication */
#define WL_AUTH_FILS_PUBLIC 6 /* d11 fils public key authentication */
uint64
osl_systztime_us(void)
{
- struct timeval tv;
+ struct osl_timespec tv;
uint64 tzusec;
- do_gettimeofday(&tv);
+ osl_do_gettimeofday(&tv);
/* apply timezone */
tzusec = (uint64)((tv.tv_sec - (sys_tz.tz_minuteswest * 60)) *
USEC_PER_SEC);
void
osl_do_gettimeofday(struct osl_timespec *ts)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+ struct timespec64 curtime;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
struct timespec curtime;
#else
struct timeval curtime;
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+ ktime_get_real_ts64(&curtime);
+ ts->tv_nsec = curtime.tv_nsec;
+ ts->tv_usec = curtime.tv_nsec / 1000;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
getnstimeofday(&curtime);
ts->tv_nsec = curtime.tv_nsec;
ts->tv_usec = curtime.tv_nsec / 1000;
void
osl_get_monotonic_boottime(struct osl_timespec *ts)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+ struct timespec64 curtime;
+#else
struct timespec curtime;
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+ curtime = ktime_to_timespec64(ktime_get_boottime());
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
curtime = ktime_to_timespec(ktime_get_boottime());
#else
get_monotonic_boottime(&curtime);
pmuaddr = SI_ENUM_BASE(sih) + offset;
done:
- printf("%s: addrRET: %x\n", __FUNCTION__, pmuaddr);
+ SI_MSG(("%s: addrRET: %x\n", __FUNCTION__, pmuaddr));
return pmuaddr;
}
#define APCS_DEFAULT_2G_CH 1
#define APCS_DEFAULT_5G_CH 149
-#ifdef WL_ESCAN
-static int
-wl_android_escan_autochannel(struct net_device *dev, uint32 band)
-{
- struct dhd_pub *dhd = dhd_get_pub(dev);
- wlc_ssid_t ssid;
- struct wl_escan_info *escan = NULL;
- int ret = 0, retry = 0, retry_max, retry_interval = 250, channel = 0, up = 1;
-#ifdef WL_CFG80211
- struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
-#endif
-
- escan = dhd->escan;
- if (dhd) {
- retry_max = WL_ESCAN_TIMER_INTERVAL_MS/retry_interval;
- memset(&ssid, 0, sizeof(ssid));
- ret = wldev_ioctl_get(dev, WLC_GET_UP, &up, sizeof(s32));
- if (ret < 0 || up == 0) {
- ret = wldev_ioctl_set(dev, WLC_UP, &up, sizeof(s32));
- }
- retry = retry_max;
- while (retry--) {
-#ifdef WL_CFG80211
- if (wl_get_drv_status_all(cfg, SCANNING) ||
- escan->escan_state == ESCAN_STATE_SCANING)
-#else
- if (escan->escan_state == ESCAN_STATE_SCANING)
-#endif
- {
- ANDROID_INFO(("Scanning %d tried, ret = %d\n",
- (retry_max - retry), ret));
- } else {
- escan->autochannel = 1;
- ret = wl_escan_set_scan(dev, dhd, &ssid, TRUE);
- if (!ret)
- break;
- }
- OSL_SLEEP(retry_interval);
- }
- if ((retry == 0) || (ret < 0))
- goto done;
- retry = retry_max;
- while (retry--) {
- if (escan->escan_state == ESCAN_STATE_IDLE) {
- if (band == WLC_BAND_5G)
- channel = escan->best_5g_ch;
- else
- channel = escan->best_2g_ch;
- WL_MSG(dev->name, "selected channel = %d\n", channel);
- goto done;
- }
- ANDROID_INFO(("escan_state=%d, %d tried, ret = %d\n",
- escan->escan_state, (retry_max - retry), ret));
- OSL_SLEEP(retry_interval);
- }
- if ((retry == 0) || (ret < 0))
- goto done;
- }
-
-done:
- if (escan)
- escan->autochannel = 0;
-
- return channel;
-}
-#endif /* WL_ESCAN */
-
static int
wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
char* command, int total_len)
goto done2;
}
-#ifdef WL_ESCAN
- channel = wl_android_escan_autochannel(dev, band);
+ channel = wl_ext_autochannel(dev, ACS_FW_BIT|ACS_DRV_BIT, band);
if (channel)
goto done2;
else
goto done;
-#endif /* WL_ESCAN */
ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
if (ret) {
enable = command[strlen(CMD_RPSMODE) + 1] - '0';
error = dhd_rps_cpus_enable(dev, enable);
-#if defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211)
+#if 0 //defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211)
if (!error) {
void *dhdp = wl_cfg80211_get_dhdp(net);
if (enable) {
#endif /* BT_OVER_SDIO */
#ifdef WL_STATIC_IF
+#include <dhd_linux_priv.h>
struct net_device *
wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifname)
{
#ifdef DHD_USE_RANDMAC
struct ether_addr ea_addr;
#endif /* DHD_USE_RANDMAC */
+#ifdef CUSTOM_MULTI_MAC
+ char hw_ether[62];
+ dhd_pub_t *dhd = cfg->pub;
+#endif
WL_INFORM_MEM(("[STATIC_IF] Enter (%s) iftype:%d\n", ifname, iftype));
dhd_generate_mac_addr(&ea_addr);
(void)memcpy_s(mac_addr, ETH_ALEN, ea_addr.octet, ETH_ALEN);
#else
+#if defined(CUSTOM_MULTI_MAC)
+ if (wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, "wlan1")) {
+#endif
/* Use primary mac with locally admin bit set */
(void)memcpy_s(mac_addr, ETH_ALEN, primary_ndev->dev_addr, ETH_ALEN);
mac_addr[0] |= 0x02;
+#if defined(CUSTOM_MULTI_MAC)
+ } else {
+ (void)memcpy_s(mac_addr, ETH_ALEN, hw_ether, ETH_ALEN);
+ }
+#endif
#endif /* DHD_USE_RANDMAC */
ndev = wl_cfg80211_allocate_if(cfg, ifidx, ifname, mac_addr,
struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
u16 iftype = net->ieee80211_ptr ? net->ieee80211_ptr->iftype : 0;
u16 wl_iftype, wl_mode;
+#ifdef CUSTOM_MULTI_MAC
+ char hw_ether[62];
+ dhd_pub_t *dhd = dhd_get_pub(net);
+#endif
WL_INFORM_MEM(("[STATIC_IF] dev_open ndev %p and wdev %p\n", net, net->ieee80211_ptr));
ASSERT(cfg->static_ndev == net);
#ifdef DHD_USE_RANDMAC
wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, net->dev_addr);
#else
+#if defined(CUSTOM_MULTI_MAC)
+ if (wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, net->name)) {
+#endif
wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, NULL);
+#if defined(CUSTOM_MULTI_MAC)
+ } else {
+ wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, hw_ether);
+ }
+#endif
#endif // endif
if (!wdev) {
ANDROID_ERROR(("[STATIC_IF] wdev is NULL, can't proceed"));
} \
} while (0)
+#define WL_MSG_PRINT_RATE_LIMIT_PERIOD 1000000000u /* 1s in units of ns */
+#define WL_MSG_RLMT(name, cmp, size, arg1, args...) \
+do { \
+ if (android_msg_level & ANDROID_MSG_LEVEL) { \
+ static uint64 __err_ts = 0; \
+ static uint32 __err_cnt = 0; \
+ uint64 __cur_ts = 0; \
+ static uint8 static_tmp[size]; \
+ __cur_ts = local_clock(); \
+ if (__err_ts == 0 || (__cur_ts > __err_ts && \
+ (__cur_ts - __err_ts > WL_MSG_PRINT_RATE_LIMIT_PERIOD)) || \
+ memcmp(&static_tmp, cmp, size)) { \
+ __err_ts = __cur_ts; \
+ memcpy(static_tmp, cmp, size); \
+ printk(KERN_ERR "[dhd-%s] %s : [%u times] " arg1, \
+ name, __func__, __err_cnt, ## args); \
+ __err_cnt = 0; \
+ } else { \
+ ++__err_cnt; \
+ } \
+ } \
+} while (0)
+
/**
* wl_android_init will be called from module init function (dhd_module_init now), similarly
* wl_android_exit will be called from module exit function (dhd_module_cleanup now)
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);
-u32 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, u32 channel);
+int wl_ext_iapsta_update_net_device(struct net_device *net, int ifidx);
+void wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add);
+#ifdef PROPTX_MAXCOUNT
+void wl_ext_update_wlfc_maxcount(struct dhd_pub *dhd);
+int wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx);
+#endif /* PROPTX_MAXCOUNT */
int wl_ext_iapsta_alive_preinit(struct net_device *dev);
int wl_ext_iapsta_alive_postinit(struct net_device *dev);
int wl_ext_iapsta_attach(dhd_pub_t *pub);
void wl_ext_iapsta_dettach(dhd_pub_t *pub);
-bool wl_ext_check_mesh_creating(struct net_device *net);
#ifdef WL_CFG80211
+u32 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, u32 channel);
void wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype);
-#endif
-#ifdef WL_STATIC_IF
+bool wl_ext_iapsta_iftype_enabled(struct net_device *net, int wl_iftype);
void wl_ext_iapsta_ifadding(struct net_device *net, int ifidx);
+bool wl_ext_iapsta_mesh_creating(struct net_device *net);
#endif
extern int op_mode;
#endif
char ptk[64];
char replay[8];
} bcol_gtk_para_t;
+#define ACS_FW_BIT (1<<0)
+#define ACS_DRV_BIT (1<<1)
#if defined(WL_EXT_IAPSTA) || defined(USE_IW)
typedef enum WL_EVENT_PRIO {
PRIO_EVENT_IAPSTA,
uint32 event, void *cb_func);
void wl_ext_event_send(void *params, const wl_event_msg_t * e, void *data);
#endif
+int wl_ext_autochannel(struct net_device *dev, uint acs, uint32 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 wl_ext_check_scan(struct net_device *dev, dhd_pub_t *dhdp);
+#if defined(WL_CFG80211) || defined(WL_ESCAN)
+void wl_ext_user_sync(struct dhd_pub *dhd, int ifidx, bool lock);
+bool wl_ext_event_complete(struct dhd_pub *dhd, int ifidx);
+#endif
+#if defined(WL_CFG80211)
+void wl_ext_bss_iovar_war(struct net_device *dev, s32 *val);
+#endif
enum wl_ext_status {
WL_EXT_STATUS_DISCONNECTING = 0,
WL_EXT_STATUS_DISCONNECTED,
typedef struct wl_bss_cache {
struct wl_bss_cache *next;
int dirty;
- struct timeval tv;
+ struct osl_timespec tv;
wl_scan_results_t results;
} wl_bss_cache_t;
#include <linux/wireless.h>
#if defined(WL_WIRELESS_EXT)
#include <wl_iw.h>
-#endif
+#endif /* WL_WIRELESS_EXT */
#include <wldev_common.h>
#include <wlioctl.h>
#include <bcmutils.h>
#include <dhd_config.h>
#ifdef WL_CFG80211
#include <wl_cfg80211.h>
-#endif
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+#include <wl_escan.h>
+#endif /* WL_ESCAN */
#define AEXT_ERROR(name, arg1, args...) \
do { \
#define AEXT_TRACE(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_TRACE_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] AEXT-TRACE) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] AEXT-TRACE) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
#define AEXT_INFO(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_INFO_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] AEXT-INFO) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] AEXT-INFO) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
#define AEXT_DBG(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_DBG_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] AEXT-DBG) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] AEXT-DBG) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20
#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320
#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400
-#endif
+#endif /* WL_CFG80211 */
#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
#ifndef IW_CUSTOM_MAX
#define CMD_ISAM_ENABLE "ISAM_ENABLE"
#define CMD_ISAM_DISABLE "ISAM_DISABLE"
#define CMD_ISAM_STATUS "ISAM_STATUS"
+#define CMD_ISAM_PEER_PATH "ISAM_PEER_PATH"
+#define CMD_ISAM_PARAM "ISAM_PARAM"
#ifdef PROP_TXSTATUS
#ifdef PROP_TXSTATUS_VSDB
#include <dhd_wlfc.h>
extern int disable_proptx;
#endif /* PROP_TXSTATUS_VSDB */
-#endif
-#endif
+#endif /* PROP_TXSTATUS */
+#endif /* WL_EXT_IAPSTA */
#define CMD_AUTOCHANNEL "AUTOCHANNEL"
#define CMD_WL "WL"
#ifdef WL_EXT_IAPSTA
typedef enum APSTAMODE {
+ IUNKNOWN_MODE = 0,
ISTAONLY_MODE = 1,
IAPONLY_MODE = 2,
ISTAAP_MODE = 3,
typedef enum IFMODE {
ISTA_MODE = 1,
IAP_MODE,
+ IGO_MODE,
+ IGC_MODE,
IMESH_MODE
} ifmode_t;
authmode_t amode;
encmode_t emode;
char key[100];
+#if defined(WLMESH) && defined(WL_ESCAN)
+ struct wl_escan_info *escan;
+ timer_list_compat_t delay_scan;
+#endif /* WLMESH && WL_ESCAN */
+ struct delayed_work pm_enable_work;
+ struct mutex pm_sync;
+#ifdef PROPTX_MAXCOUNT
+ int transit_maxcount;
+#endif /* PROP_TXSTATUS_VSDB */
} wl_if_info_t;
#define CSA_FW_BIT (1<<0)
struct dhd_pub *dhd;
int ioctl_ver;
bool init;
- bool rsdb;
+ int rsdb;
bool vsdb;
uint csa;
+ uint acs;
+ bool radar;
apstamode_t apstamode;
wait_queue_head_t netif_change_event;
struct mutex usr_sync;
+#if defined(WLMESH) && defined(WL_ESCAN)
+ int macs;
+ struct wl_mesh_params mesh_info;
+#endif /* WLMESH && WL_ESCAN */
} wl_apsta_params_t;
#define MAX_AP_LINK_WAIT_TIME 3000
#define wl_chg_isam_status(cur_if, stat) \
(change_bit(ISAM_STATUS_ ## stat, &(cur_if)->status))
-static int wl_ext_enable_iface(struct net_device *dev, char *ifname);
-#endif
+static int wl_ext_enable_iface(struct net_device *dev, char *ifname, int wait_up);
+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 */
+#endif /* WL_EXT_IAPSTA */
#ifdef IDHCP
typedef struct dhcpc_parameter {
uint32 ip_serv;
uint32 lease_time;
} dhcpc_para_t;
-#endif
+#endif /* IDHCP */
#ifdef WL_EXT_WOWL
#define WL_WOWL_TCPFIN (1 << 26)
char cmd[4];
wl_wowl_pattern_t wowl_pattern;
} wl_wowl_pattern2_t;
-#endif
+#endif /* WL_EXT_WOWL */
#ifdef WL_EXT_TCPKA
typedef struct tcpka_conn {
uint32 seq;
uint32 ack;
} tcpka_conn_sess_info_t;
-#endif
+#endif /* WL_EXT_TCPKA */
static int wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len);
join_params->params.chanspec_num =
htod32(join_params->params.chanspec_num);
- AEXT_ERROR("wlan", "join_params->params.chanspec_list[0]= %X, %d channels\n",
- join_params->params.chanspec_list[0],
- join_params->params.chanspec_num);
}
}
return chanspec;
}
+#endif /* WL_EXT_IAPSTA || WL_CFG80211 || WL_ESCAN */
+
+bool
+wl_ext_check_scan(struct net_device *dev, dhd_pub_t *dhdp)
+{
+#ifdef WL_CFG80211
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+ struct wl_escan_info *escan = dhdp->escan;
+#endif /* WL_ESCAN */
+
+#ifdef WL_CFG80211
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ AEXT_ERROR(dev->name, "cfg80211 scanning...\n");
+ return TRUE;
+ }
+#endif /* WL_CFG80211 */
+
+#ifdef WL_ESCAN
+ if (escan->escan_state == ESCAN_STATE_SCANING) {
+ AEXT_ERROR(dev->name, "escan scanning...\n");
+ return TRUE;
+ }
+#endif /* WL_ESCAN */
+
+ return FALSE;
+}
+
+#if defined(WL_CFG80211) || defined(WL_ESCAN)
+void
+wl_ext_user_sync(struct dhd_pub *dhd, int ifidx, bool lock)
+{
+ struct net_device *dev = dhd_idx2net(dhd, ifidx);
+#ifdef WL_CFG80211
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+ struct wl_escan_info *escan = dhd->escan;
+#endif /* WL_ESCAN */
+
+ AEXT_INFO(dev->name, "lock=%d\n", lock);
+
+ if (lock) {
+#if defined(WL_CFG80211)
+ mutex_lock(&cfg->usr_sync);
+#endif
+#if defined(WL_ESCAN)
+ mutex_lock(&escan->usr_sync);
#endif
+ } else {
+#if defined(WL_CFG80211)
+ mutex_unlock(&cfg->usr_sync);
+#endif
+#if defined(WL_ESCAN)
+ mutex_unlock(&escan->usr_sync);
+#endif
+ }
+}
+
+bool
+wl_ext_event_complete(struct dhd_pub *dhd, int ifidx)
+{
+ struct net_device *dev = dhd_idx2net(dhd, ifidx);
+#ifdef WL_CFG80211
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+ struct wl_escan_info *escan = dhd->escan;
+#endif /* WL_ESCAN */
+ bool complete = TRUE;
+
+#ifdef WL_CFG80211
+ if (wl_get_drv_status_all(cfg, SCANNING)) {
+ AEXT_INFO(dev->name, "SCANNING\n");
+ complete = FALSE;
+ }
+ if (wl_get_drv_status_all(cfg, CONNECTING)) {
+ AEXT_INFO(dev->name, "CONNECTING\n");
+ complete = FALSE;
+ }
+ if (wl_get_drv_status_all(cfg, DISCONNECTING)) {
+ AEXT_INFO(dev->name, "DISCONNECTING\n");
+ complete = FALSE;
+ }
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+ if (escan->escan_state == ESCAN_STATE_SCANING) {
+ AEXT_INFO(dev->name, "ESCAN_STATE_SCANING\n");
+ complete = FALSE;
+ }
+#endif /* WL_ESCAN */
+ if (dhd->conf->eapol_status >= EAPOL_STATUS_4WAY_START &&
+ dhd->conf->eapol_status < EAPOL_STATUS_4WAY_DONE) {
+ AEXT_INFO(dev->name, "4-WAY handshaking\n");
+ complete = FALSE;
+ }
+
+ return complete;
+}
+#endif /* WL_CFG80211 && WL_ESCAN */
static int
wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
return ret;
}
+void
+wl_ext_bss_iovar_war(struct net_device *ndev, s32 *val)
+{
+ dhd_pub_t *dhd = dhd_get_pub(ndev);
+ uint chip;
+ bool need_war = false;
+
+ chip = dhd_conf_get_chip(dhd);
+
+ if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
+ chip == BCM43430_CHIP_ID || chip == BCM43012_CHIP_ID ||
+ chip == BCM4345_CHIP_ID || chip == BCM4356_CHIP_ID ||
+ chip == BCM4359_CHIP_ID) {
+ need_war = true;
+ }
+
+ if (need_war) {
+ /* Few firmware branches have issues in bss iovar handling and
+ * that can't be changed since they are in production.
+ */
+ if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) {
+ *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
+ } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) {
+ *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
+ } else {
+ /* Ignore for other bss enums */
+ return;
+ }
+ AEXT_TRACE(ndev->name, "wl bss %d\n", *val);
+ }
+}
+
static int
wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver,
uint16 channel, chanspec_t *ret_chspec)
if ((err = wl_ext_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) {
if (bw == WL_CHANSPEC_BW_80)
goto change_bw;
- wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
+ err = wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
WL_MSG(dev->name, "channel %d\n", _chan);
} else if (err) {
AEXT_ERROR(dev->name, "failed to set chanspec error %d\n", err);
int ioctl_ver = 0;
char sec[32];
+ wl_ext_get_ioctl_ver(dev, &ioctl_ver);
+
if (dhd->conf->chip == BCM43362_CHIP_ID)
goto set_ssid;
err = -ENOMEM;
goto exit;
}
- wl_ext_get_ioctl_ver(dev, &ioctl_ver);
ext_join_params->ssid.SSID_len = min((uint32)sizeof(ext_join_params->ssid.SSID),
conn_info->ssid.SSID_len);
memcpy(&ext_join_params->ssid.SSID, conn_info->ssid.SSID, ext_join_params->ssid.SSID_len);
memset(&join_params, 0, sizeof(join_params));
join_params_size = sizeof(join_params.ssid);
- join_params.ssid.SSID_len = min((uint32)sizeof(join_params.ssid.SSID), conn_info->ssid.SSID_len);
+ join_params.ssid.SSID_len = min((uint32)sizeof(join_params.ssid.SSID),
+ conn_info->ssid.SSID_len);
memcpy(&join_params.ssid.SSID, conn_info->ssid.SSID, join_params.ssid.SSID_len);
join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
if (memcmp(ðer_null, &conn_info->bssid, ETHER_ADDR_LEN))
"Connecting with %pM channel (%d) ssid \"%s\", len (%d), sec=%s\n\n",
&join_params.params.bssid, conn_info->channel,
join_params.ssid.SSID, join_params.ssid.SSID_len, sec);
- err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params,join_params_size, 1);
+ err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, 1);
exit:
+#ifdef WL_EXT_IAPSTA
+ if (!err)
+ wl_ext_add_remove_pm_enable_work(dev, TRUE);
+#endif /* WL_EXT_IAPSTA */
if (iovar_buf)
kfree(iovar_buf);
if (ext_join_params)
void
wl_ext_get_sec(struct net_device *dev, int ifmode, char *sec, int total_len)
{
- int auth=-1, wpa_auth=-1, wsec=0;
+ int auth=0, wpa_auth=0, wsec=0, mfp=0;
int bytes_written=0;
memset(sec, 0, total_len);
wl_ext_iovar_getint(dev, "auth", &auth);
wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
wl_ext_iovar_getint(dev, "wsec", &wsec);
+ wldev_iovar_getint(dev, "mfp", &mfp);
-#if defined(WL_EXT_IAPSTA) && defined(WLMESH)
+#ifdef WL_EXT_IAPSTA
if (ifmode == IMESH_MODE) {
- if (auth == 0 && wpa_auth == 0) {
+ if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_DISABLED) {
bytes_written += snprintf(sec+bytes_written, total_len, "open");
- } else if (auth == 0 && wpa_auth == 128) {
+ } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA2_AUTH_PSK) {
bytes_written += snprintf(sec+bytes_written, total_len, "sae");
} else {
- bytes_written += snprintf(sec+bytes_written, total_len, "unknown");
+ bytes_written += snprintf(sec+bytes_written, total_len, "%d/0x%x",
+ auth, wpa_auth);
}
} else
-#endif
- if (auth == 0 && wpa_auth == 0) {
- bytes_written += snprintf(sec+bytes_written, total_len, "open");
- } else if (auth == 1 && wpa_auth == 0) {
- bytes_written += snprintf(sec+bytes_written, total_len, "shared");
- } else if (auth == 0 && wpa_auth == 4) {
- bytes_written += snprintf(sec+bytes_written, total_len, "wpapsk");
- } else if (auth == 0 && wpa_auth == 128) {
- bytes_written += snprintf(sec+bytes_written, total_len, "wpa2psk");
- } else if (auth == 0 && wpa_auth == 132) {
- bytes_written += snprintf(sec+bytes_written, total_len, "wpawpa2psk");
+#endif /* WL_EXT_IAPSTA */
+ {
+ if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_DISABLED) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "open");
+ } else if (auth == WL_AUTH_SHARED_KEY && wpa_auth == WPA_AUTH_DISABLED) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "shared");
+ } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_PSK) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "wpapsk");
+ } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA2_AUTH_PSK) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "wpa2psk");
+ } else if (auth == WL_AUTH_OPEN_SHARED && wpa_auth == WPA3_AUTH_SAE_PSK) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "wpa3");
+ } else if ((auth == WL_AUTH_OPEN_SYSTEM || auth == WL_AUTH_SAE_KEY) &&
+ wpa_auth == 0x20) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "wpa3");
+ } else {
+ bytes_written += snprintf(sec+bytes_written, total_len, "%d/0x%x",
+ auth, wpa_auth);
+ }
+ }
+
+ if (mfp == WL_MFP_NONE) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/mfpn");
+ } else if (mfp == WL_MFP_CAPABLE) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/mfpc");
+ } else if (mfp == WL_MFP_REQUIRED) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/mfpr");
} else {
- bytes_written += snprintf(sec+bytes_written, total_len, "(%d/%d)",
- auth, wpa_auth);
+ bytes_written += snprintf(sec+bytes_written, total_len, "/%d", mfp);
}
-#if defined(WL_EXT_IAPSTA) && defined(WLMESH)
+#ifdef WL_EXT_IAPSTA
if (ifmode == IMESH_MODE) {
- if (wsec == 0) {
+ if (wsec == WSEC_NONE) {
bytes_written += snprintf(sec+bytes_written, total_len, "/none");
} else {
- bytes_written += snprintf(sec+bytes_written, total_len, "/sae");
+ bytes_written += snprintf(sec+bytes_written, total_len, "/aes");
}
} else
-#endif
- if (wsec == 0) {
- bytes_written += snprintf(sec+bytes_written, total_len, "/none");
- } else if (wsec == 1) {
- bytes_written += snprintf(sec+bytes_written, total_len, "/wep");
- } else if (wsec == 2 || wsec == 10) {
- bytes_written += snprintf(sec+bytes_written, total_len, "/tkip");
- } else if (wsec == 4 || wsec == 12) {
- bytes_written += snprintf(sec+bytes_written, total_len, "/aes");
- } else if (wsec == 6 || wsec == 14) {
- bytes_written += snprintf(sec+bytes_written, total_len, "/tkipaes");
- } else {
- bytes_written += snprintf(sec+bytes_written, total_len, "/%d", wsec);
+#endif /* WL_EXT_IAPSTA */
+ {
+ if (wsec == WSEC_NONE) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/none");
+ } else if (wsec == WEP_ENABLED) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/wep");
+ } else if (wsec == (TKIP_ENABLED|AES_ENABLED) ||
+ wsec == (WSEC_SWFLAG|TKIP_ENABLED|AES_ENABLED)) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/tkipaes");
+ } else if (wsec == TKIP_ENABLED || wsec == (WSEC_SWFLAG|TKIP_ENABLED)) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/tkip");
+ } else if (wsec == AES_ENABLED || wsec == (WSEC_SWFLAG|AES_ENABLED)) {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/aes");
+ } else {
+ bytes_written += snprintf(sec+bytes_written, total_len, "/0x%x", wsec);
+ }
+ }
+
+}
+
+static bool
+wl_ext_dfs_chan(uint16 chan)
+{
+ if (chan >= 52 && chan <= 144)
+ return TRUE;
+ return FALSE;
+}
+
+static 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);
+ uint16 chan_tmp = 0, chan = 0;
+ wl_uint32_list_t *list;
+ u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+ s32 ret = BCME_OK;
+ int i;
+
+ *chan_2g = 0;
+ *chan_5g = 0;
+ 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(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
+ sizeof(valid_chan_list), 0);
+ if (ret == 0) {
+ for (i=0; i<dtoh32(list->count); i++) {
+ chan_tmp = dtoh32(list->element[i]);
+ if (!dhd_conf_match_channel(dhd, chan_tmp))
+ continue;
+ if (chan_tmp <= 13) {
+ *chan_2g = chan_tmp;
+ } else {
+ if (wl_ext_dfs_chan(chan_tmp) && nodfs)
+ continue;
+ else if (chan_tmp >= 36 && chan_tmp <= 161)
+ *chan_5g = chan_tmp;
+ }
+ }
+ }
+
+ return chan;
+}
+
+#if defined(SENDPROB) || (defined(WLMESH) && defined(WL_ESCAN))
+static int
+wl_ext_add_del_ie(struct net_device *dev, uint pktflag, char *ie_data, const char* add_del_cmd)
+{
+ vndr_ie_setbuf_t *vndr_ie = NULL;
+ char iovar_buf[WLC_IOCTL_SMLEN]="\0";
+ int ie_data_len = 0, tot_len = 0, iecount;
+ int err = -1;
+
+ if (!strlen(ie_data)) {
+ AEXT_ERROR(dev->name, "wrong ie %s\n", ie_data);
+ goto exit;
+ }
+
+ tot_len = (int)(sizeof(vndr_ie_setbuf_t) + ((strlen(ie_data)-2)/2));
+ vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, GFP_KERNEL);
+ if (!vndr_ie) {
+ AEXT_ERROR(dev->name, "IE memory alloc failed\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+ strncpy(vndr_ie->cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
+ vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+ /* Set the IE count - the buffer contains only 1 IE */
+ iecount = htod32(1);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+ /* Set packet flag to indicate that BEACON's will contain this IE */
+ pktflag = htod32(pktflag);
+ memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
+ sizeof(u32));
+
+ /* Set the IE ID */
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar)DOT11_MNG_VS_ID;
+
+ /* Set the IE LEN */
+ vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (strlen(ie_data)-2)/2;
+
+ /* Set the IE OUI and DATA */
+ ie_data_len = wl_pattern_atoh(ie_data,
+ (char *)vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui);
+ if (ie_data_len <= 0) {
+ AEXT_ERROR(dev->name, "wrong ie_data_len %d\n", (int)strlen(ie_data)-2);
+ goto exit;
+ }
+
+ err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, tot_len, iovar_buf,
+ sizeof(iovar_buf), NULL);
+
+exit:
+ if (vndr_ie) {
+ kfree(vndr_ie);
}
+ return err;
}
+#endif /* SENDPROB || (WLMESH && WL_ESCAN) */
#ifdef WL_EXT_IAPSTA
+#define WL_PM_ENABLE_TIMEOUT 10000
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
+entry = container_of((ptr), type, member); \
+_Pragma("GCC diagnostic pop")
+#else
+#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
+entry = container_of((ptr), type, member);
+#endif /* STRICT_GCC_WARNINGS */
+
+static void
+wl_ext_pm_work_handler(struct work_struct *work)
+{
+ struct wl_if_info *cur_if;
+ s32 pm = PM_FAST;
+ dhd_pub_t *dhd;
+
+ BCM_SET_CONTAINER_OF(cur_if, work, struct wl_if_info, pm_enable_work.work);
+
+ WL_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ if (cur_if->dev == NULL)
+ return;
+
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#endif
+
+ dhd = dhd_get_pub(cur_if->dev);
+
+ if (!dhd || !dhd->up) {
+ AEXT_TRACE(cur_if->ifname, "dhd is null or not up\n");
+ return;
+ }
+ if (dhd_conf_get_pm(dhd) >= 0)
+ pm = dhd_conf_get_pm(dhd);
+ wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic pop")
+#endif
+ DHD_PM_WAKE_UNLOCK(dhd);
+
+}
+
+void
+wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add)
+{
+ dhd_pub_t *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
+ u16 wq_duration = 0;
+ s32 pm = PM_OFF;
+ int i;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->dev && tmp_if->dev == dev) {
+ cur_if = tmp_if;
+ break;
+ }
+ }
+
+ if (!cur_if)
+ return;
+
+ mutex_lock(&cur_if->pm_sync);
+ /*
+ * Make cancel and schedule work part mutually exclusive
+ * so that while cancelling, we are sure that there is no
+ * work getting scheduled.
+ */
+
+ if (delayed_work_pending(&cur_if->pm_enable_work)) {
+ cancel_delayed_work_sync(&cur_if->pm_enable_work);
+ DHD_PM_WAKE_UNLOCK(dhd);
+ }
+
+ if (add) {
+ wq_duration = (WL_PM_ENABLE_TIMEOUT);
+ }
+
+ /* It should schedule work item only if driver is up */
+ if (dhd->up) {
+ if (dhd_conf_get_pm(dhd) >= 0)
+ pm = dhd_conf_get_pm(dhd);
+ wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
+ if (wq_duration) {
+ if (schedule_delayed_work(&cur_if->pm_enable_work,
+ msecs_to_jiffies((const unsigned int)wq_duration))) {
+ DHD_PM_WAKE_LOCK_TIMEOUT(dhd, wq_duration);
+ } else {
+ AEXT_ERROR(cur_if->ifname, "Can't schedule pm work handler\n");
+ }
+ }
+ }
+ mutex_unlock(&cur_if->pm_sync);
+
+}
+
static int
wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key)
{
#ifdef WLMESH
if (cur_if->ifmode == IMESH_MODE) {
if (amode == AUTH_SAE) {
- auth = 0;
- wpa_auth = 128;
+ auth = WL_AUTH_OPEN_SYSTEM;
+ wpa_auth = WPA2_AUTH_PSK;
AEXT_INFO(dev->name, "SAE\n");
} else {
- auth = 0;
- wpa_auth = 0;
+ auth = WL_AUTH_OPEN_SYSTEM;
+ wpa_auth = WPA_AUTH_DISABLED;
AEXT_INFO(dev->name, "Open System\n");
}
} else
-#endif
+#endif /* WLMESH */
if (amode == AUTH_OPEN) {
- auth = 0;
- wpa_auth = 0;
+ auth = WL_AUTH_OPEN_SYSTEM;
+ wpa_auth = WPA_AUTH_DISABLED;
AEXT_INFO(dev->name, "Open System\n");
} else if (amode == AUTH_SHARED) {
- auth = 1;
- wpa_auth = 0;
+ auth = WL_AUTH_SHARED_KEY;
+ wpa_auth = WPA_AUTH_DISABLED;
AEXT_INFO(dev->name, "Shared Key\n");
} else if (amode == AUTH_WPAPSK) {
- auth = 0;
- wpa_auth = 4;
+ auth = WL_AUTH_OPEN_SYSTEM;
+ wpa_auth = WPA_AUTH_PSK;
AEXT_INFO(dev->name, "WPA-PSK\n");
} else if (amode == AUTH_WPA2PSK) {
- auth = 0;
- wpa_auth = 128;
+ auth = WL_AUTH_OPEN_SYSTEM;
+ wpa_auth = WPA2_AUTH_PSK;
AEXT_INFO(dev->name, "WPA2-PSK\n");
} else if (amode == AUTH_WPAWPA2PSK) {
- auth = 0;
- wpa_auth = 132;
+ auth = WL_AUTH_OPEN_SYSTEM;
+ wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK;
AEXT_INFO(dev->name, "WPA/WPA2-PSK\n");
}
#ifdef WLMESH
s32 val = WL_BSSTYPE_MESH;
wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1);
} else
-#endif
+#endif /* WLMESH */
if (cur_if->ifmode == ISTA_MODE) {
s32 val = WL_BSSTYPE_INFRA;
wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1);
#ifdef WLMESH
if (cur_if->ifmode == IMESH_MODE) {
if (amode == AUTH_SAE) {
- wsec = 4;
+ wsec = AES_ENABLED;
} else {
- wsec = 0;
+ wsec = WSEC_NONE;
}
} else
-#endif
+#endif /* WLMESH */
if (emode == ENC_NONE) {
- wsec = 0;
+ wsec = WSEC_NONE;
AEXT_INFO(dev->name, "No securiy\n");
} else if (emode == ENC_WEP) {
- wsec = 1;
+ wsec = WEP_ENABLED;
wl_ext_parse_wep(key, &wsec_key);
AEXT_INFO(dev->name, "WEP key \"%s\"\n", wsec_key.data);
} else if (emode == ENC_TKIP) {
- wsec = 2;
+ wsec = TKIP_ENABLED;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
AEXT_INFO(dev->name, "TKIP key \"%s\"\n", psk.key);
} else if (emode == ENC_AES || amode == AUTH_SAE) {
- wsec = 4;
+ wsec = AES_ENABLED;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
AEXT_INFO(dev->name, "AES key \"%s\"\n", psk.key);
} else if (emode == ENC_TKIPAES) {
- wsec = 6;
+ wsec = TKIP_ENABLED | AES_ENABLED;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
}
if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 &&
apsta_params->apstamode == ISTAAP_MODE) {
- wsec |= 0x8; // terence 20180628: fix me, this is a workaround
+ wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround
}
wl_ext_iovar_setint(dev, "wsec", wsec);
if (cur_if->ifmode == IMESH_MODE) {
if (amode == AUTH_SAE) {
s8 iovar_buf[WLC_IOCTL_SMLEN];
- AEXT_INFO(dev->name, "SAE key \"%s\"\n", key);
+ AEXT_INFO(dev->name, "AES key \"%s\"\n", key);
wl_ext_iovar_setint(dev, "mesh_auth_proto", 1);
wl_ext_iovar_setint(dev, "mfp", WL_MFP_REQUIRED);
wl_ext_iovar_setbuf(dev, "sae_password", key, strlen(key),
wl_ext_iovar_setint(dev, "mfp", WL_MFP_NONE);
}
} else
-#endif
+#endif /* WLMESH */
if (emode == ENC_WEP) {
wl_ext_ioctl(dev, WLC_SET_KEY, &wsec_key, sizeof(wsec_key), 1);
} else if (emode == ENC_TKIP || emode == ENC_AES || emode == ENC_TKIPAES) {
}
static bool
-wl_ext_dfs_chan(struct wl_apsta_params *apsta_params, struct net_device *dev,
- uint16 chan)
+wl_ext_radar_detect(struct net_device *dev)
{
- u32 channel = chan;
- s32 err = BCME_OK;
- bool dfs = FALSE;
-
- if (chan <= CH_MAX_2G_CHANNEL)
- return FALSE;
+ int ret = BCME_OK;
+ bool radar = FALSE;
+ s32 val = 0;
- channel |= WL_CHANSPEC_BAND_5G;
- channel |= WL_CHANSPEC_BW_20;
- channel = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, channel);
- err = wl_ext_iovar_getint(dev, "per_chan_info", &channel);
- if (!err) {
- if (channel & WL_CHAN_PASSIVE) {
- dfs = TRUE;
- }
+ if ((ret = wldev_ioctl(dev, WLC_GET_RADAR, &val, sizeof(int), false) == 0)) {
+ radar = TRUE;
}
- return dfs;
-}
-
-static void
-wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params,
- struct wl_if_info *cur_if)
-{
- rtnl_unlock();
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- wl_get_isam_status(cur_if, IF_READY),
- msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
- rtnl_lock();
+ return radar;
}
-bool
-wl_ext_check_mesh_creating(struct net_device *net)
+static struct wl_if_info *
+wl_ext_if_enabled(struct wl_apsta_params *apsta_params, ifmode_t ifmode)
{
- struct dhd_pub *dhd = dhd_get_pub(net);
- struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- struct wl_if_info *cur_if;
+ struct wl_if_info *tmp_if, *target_if = NULL;
int i;
- if (apsta_params) {
- for (i=0; i<MAX_IF_NUM; i++) {
- cur_if = &apsta_params->if_info[i];
- if (cur_if->ifmode==IMESH_MODE && wl_get_isam_status(cur_if, IF_ADDING))
- return TRUE;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ 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)) {
+ target_if = tmp_if;
+ break;
+ }
}
}
- return FALSE;
+
+ return target_if;
}
-bool
-wl_ext_check_other_enabling(struct wl_apsta_params *apsta_params,
- struct wl_if_info *cur_if)
+#ifndef WL_STATIC_IF
+s32
+wl_ext_add_del_bss(struct net_device *ndev, s32 bsscfg_idx,
+ int iftype, s32 del, u8 *addr)
{
- struct wl_if_info *tmp_if;
- bool enabling = FALSE;
- u32 timeout = 1;
- int i;
+ s32 ret = BCME_OK;
+ s32 val = 0;
+ u8 ioctl_buf[WLC_IOCTL_SMLEN];
+ struct {
+ s32 cfg;
+ s32 val;
+ struct ether_addr ea;
+ } bss_setbuf;
- for (i=0; i<MAX_IF_NUM; i++) {
- tmp_if = &apsta_params->if_info[i];
- if (tmp_if->dev && tmp_if->dev != cur_if->dev) {
- if (tmp_if->ifmode == ISTA_MODE)
- enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
- else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
- enabling = wl_get_isam_status(tmp_if, AP_CREATING);
- if (enabling)
- WL_MSG(cur_if->ifname, "waiting for %s[%c] enabling...\n",
- tmp_if->ifname, tmp_if->prefix);
- if (enabling && tmp_if->ifmode == ISTA_MODE) {
- timeout = wait_event_interruptible_timeout(
- apsta_params->netif_change_event,
- !wl_get_isam_status(tmp_if, STA_CONNECTING),
- msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
- } else if (enabling &&
- (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)) {
- timeout = wait_event_interruptible_timeout(
- apsta_params->netif_change_event,
- !wl_get_isam_status(tmp_if, AP_CREATING),
- msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
+ AEXT_TRACE(ndev->name, "wl_iftype:%d del:%d \n", iftype, del);
+
+ bzero(&bss_setbuf, sizeof(bss_setbuf));
+
+ /* AP=2, STA=3, up=1, down=0, val=-1 */
+ if (del) {
+ val = WLC_AP_IOV_OP_DELETE;
+ } else if (iftype == WL_INTERFACE_CREATE_AP) {
+ /* Add/role change to AP Interface */
+ AEXT_TRACE(ndev->name, "Adding AP Interface\n");
+ val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
+ } else if (iftype == WL_INTERFACE_CREATE_STA) {
+ /* Add/role change to STA Interface */
+ AEXT_TRACE(ndev->name, "Adding STA Interface\n");
+ val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
+ } else {
+ AEXT_ERROR(ndev->name, "add_del_bss NOT supported for IFACE type:0x%x", iftype);
+ return -EINVAL;
+ }
+
+ if (!del) {
+ wl_ext_bss_iovar_war(ndev, &val);
+ }
+
+ bss_setbuf.cfg = htod32(bsscfg_idx);
+ bss_setbuf.val = htod32(val);
+
+ if (addr) {
+ memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
+ }
+
+ AEXT_INFO(ndev->name, "wl bss %d bssidx:%d\n", val, bsscfg_idx);
+ ret = wl_ext_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+ ioctl_buf, WLC_IOCTL_SMLEN, NULL);
+ if (ret != 0)
+ WL_ERR(("'bss %d' failed with %d\n", val, ret));
+
+ return ret;
+}
+
+static int
+wl_ext_interface_ops(struct net_device *dev,
+ struct wl_apsta_params *apsta_params, int iftype, u8 *addr)
+{
+ s32 ret;
+ struct wl_interface_create_v2 iface;
+ wl_interface_create_v3_t iface_v3;
+ struct wl_interface_info_v1 *info;
+ wl_interface_info_v2_t *info_v2;
+ uint32 ifflags = 0;
+ bool use_iface_info_v2 = false;
+ u8 ioctl_buf[WLC_IOCTL_SMLEN];
+ wl_wlc_version_t wlc_ver;
+
+ /* Interface create */
+ bzero(&iface, sizeof(iface));
+
+ if (addr) {
+ ifflags |= WL_INTERFACE_MAC_USE;
+ }
+
+ ret = wldev_iovar_getbuf(dev, "wlc_ver", NULL, 0,
+ &wlc_ver, sizeof(wl_wlc_version_t), NULL);
+ if ((ret == BCME_OK) && (wlc_ver.wlc_ver_major >= 5)) {
+ ret = wldev_iovar_getbuf(dev, "interface_create",
+ &iface, sizeof(struct wl_interface_create_v2),
+ ioctl_buf, sizeof(ioctl_buf), NULL);
+ if ((ret == BCME_OK) && (*((uint32 *)ioctl_buf) == WL_INTERFACE_CREATE_VER_3)) {
+ use_iface_info_v2 = true;
+ bzero(&iface_v3, sizeof(wl_interface_create_v3_t));
+ iface_v3.ver = WL_INTERFACE_CREATE_VER_3;
+ iface_v3.iftype = iftype;
+ iface_v3.flags = ifflags;
+ if (addr) {
+ memcpy(&iface_v3.mac_addr.octet, addr, ETH_ALEN);
}
- if (tmp_if->ifmode == ISTA_MODE)
- enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
- else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
- enabling = wl_get_isam_status(tmp_if, AP_CREATING);
- if (timeout <= 0 || enabling) {
- WL_MSG(cur_if->ifname, "%s[%c] is still enabling...\n",
- tmp_if->ifname, tmp_if->prefix);
+ ret = wl_ext_iovar_getbuf(dev, "interface_create",
+ &iface_v3, sizeof(wl_interface_create_v3_t),
+ ioctl_buf, sizeof(ioctl_buf), NULL);
+ if (unlikely(ret)) {
+ WL_ERR(("Interface v3 create failed!! ret %d\n", ret));
+ return ret;
}
}
}
- return enabling;
+ /* success case */
+ if (use_iface_info_v2 == true) {
+ info_v2 = (wl_interface_info_v2_t *)ioctl_buf;
+ ret = info_v2->bsscfgidx;
+ } else {
+ /* Use v1 struct */
+ iface.ver = WL_INTERFACE_CREATE_VER_2;
+ iface.iftype = iftype;
+ iface.flags = ifflags;
+ if (addr) {
+ memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
+ }
+ ret = wldev_iovar_getbuf(dev, "interface_create",
+ &iface, sizeof(struct wl_interface_create_v2),
+ ioctl_buf, sizeof(ioctl_buf), NULL);
+ if (ret == BCME_OK) {
+ info = (struct wl_interface_info_v1 *)ioctl_buf;
+ ret = info->bsscfgidx;
+ }
+ }
+
+ AEXT_INFO(dev->name, "wl interface create success!! bssidx:%d \n", ret);
+ return ret;
+}
+
+static void
+wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params,
+ struct wl_if_info *cur_if)
+{
+ rtnl_unlock();
+ wait_event_interruptible_timeout(apsta_params->netif_change_event,
+ wl_get_isam_status(cur_if, IF_READY),
+ msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
+ rtnl_lock();
+}
+
+static void
+wl_ext_interface_create(struct net_device *dev, struct wl_apsta_params *apsta_params,
+ struct wl_if_info *cur_if, int iftype, u8 *addr)
+{
+ s32 ret;
+
+ wl_set_isam_status(cur_if, IF_ADDING);
+ ret = wl_ext_interface_ops(dev, apsta_params, iftype, addr);
+ if (ret == BCME_UNSUPPORTED) {
+ wl_ext_add_del_bss(dev, 1, iftype, 0, addr);
+ }
+ wl_ext_wait_netif_change(apsta_params, cur_if);
}
+static void
+wl_ext_iapsta_intf_add(struct net_device *dev, struct wl_apsta_params *apsta_params)
+{
+ struct dhd_pub *dhd;
+ apstamode_t apstamode = apsta_params->apstamode;
+ struct wl_if_info *cur_if;
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ wl_p2p_if_t ifreq;
+ struct ether_addr mac_addr;
+
+ dhd = dhd_get_pub(dev);
+ bzero(&mac_addr, sizeof(mac_addr));
+
+ if (apstamode == ISTAAP_MODE) {
+ cur_if = &apsta_params->if_info[IF_VIF];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+ }
+ else if (apstamode == ISTAGO_MODE) {
+ bzero(&ifreq, sizeof(wl_p2p_if_t));
+ ifreq.type = htod32(WL_P2P_IF_GO);
+ cur_if = &apsta_params->if_info[IF_VIF];
+ wl_set_isam_status(cur_if, IF_ADDING);
+ wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, cur_if);
+ }
+ else if (apstamode == ISTASTA_MODE) {
+ cur_if = &apsta_params->if_info[IF_VIF];
+ memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+ mac_addr.octet[0] |= 0x02;
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA,
+ (u8*)&mac_addr);
+ }
+ else if (apstamode == IDUALAP_MODE) {
+ cur_if = &apsta_params->if_info[IF_VIF];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+ }
+ else if (apstamode == ISTAAPAP_MODE) {
+ u8 rand_bytes[2] = {0, };
+ get_random_bytes(&rand_bytes, sizeof(rand_bytes));
+ cur_if = &apsta_params->if_info[IF_VIF];
+ memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+ mac_addr.octet[0] |= 0x02;
+ mac_addr.octet[5] += 0x01;
+ memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
+ (u8*)&mac_addr);
+ cur_if = &apsta_params->if_info[IF_VIF2];
+ memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+ mac_addr.octet[0] |= 0x02;
+ mac_addr.octet[5] += 0x02;
+ memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
+ (u8*)&mac_addr);
+ }
+#ifdef WLMESH
+ else if (apstamode == ISTAMESH_MODE) {
+ cur_if = &apsta_params->if_info[IF_VIF];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
+ }
+ else if (apstamode == IMESHAP_MODE) {
+ cur_if = &apsta_params->if_info[IF_VIF];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+ }
+ else if (apstamode == ISTAAPMESH_MODE) {
+ cur_if = &apsta_params->if_info[IF_VIF];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+ cur_if = &apsta_params->if_info[IF_VIF2];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
+ }
+ else if (apstamode == IMESHAPAP_MODE) {
+ cur_if = &apsta_params->if_info[IF_VIF];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+ cur_if = &apsta_params->if_info[IF_VIF2];
+ wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+ }
+#endif /* WLMESH */
+
+}
+#endif /* WL_STATIC_IF */
+
static void
wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_params)
{
struct wl_if_info *cur_if;
s8 iovar_buf[WLC_IOCTL_SMLEN];
s32 val = 0;
- int i, dfs = 1, disable_5g_band = 0;
+ int i;
dhd = dhd_get_pub(dev);
cur_if->prio = PRIO_AP;
cur_if->prefix = 'A';
snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
- dfs = 0;
#ifdef WLMESH
} else if (cur_if->ifmode == IMESH_MODE) {
cur_if->channel = 1;
cur_if->prio = PRIO_MESH;
cur_if->prefix = 'M';
snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
- dfs = 0;
-#endif
- }
- }
-
- if (!dfs && !apsta_params->vsdb) {
- wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
- wl_ext_iovar_getint(dev, "disable_5g_band", &disable_5g_band);
- disable_5g_band |= 0x6;
- wl_ext_iovar_setint(dev, "disable_5g_band", disable_5g_band);
- wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
-#ifdef WL_CFG80211
- if (dhd->up) {
- struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
- wl_update_wiphybands(cfg, true);
+#ifdef WL_ESCAN
+ if (i == 0 && apsta_params->macs)
+ wl_mesh_escan_attach(dhd, cur_if);
+#endif /* WL_ESCAN */
+#endif /* WLMESH */
}
-#endif
}
if (FW_SUPPORTED(dhd, rsdb)) {
if (apstamode == IDUALAP_MODE)
- apsta_params->rsdb = TRUE;
+ apsta_params->rsdb = -1;
else if (apstamode == ISTAAPAP_MODE)
- apsta_params->rsdb = FALSE;
- if (apstamode == ISTAAP_MODE || apstamode == ISTAAPAP_MODE ||
+ apsta_params->rsdb = 0;
+ if (apstamode == ISTAAPAP_MODE || apstamode == IDUALAP_MODE ||
apstamode == IMESHONLY_MODE || apstamode == ISTAMESH_MODE ||
apstamode == IMESHAP_MODE || apstamode == ISTAAPMESH_MODE ||
apstamode == IMESHAPAP_MODE) {
wl_config_t rsdb_mode_cfg = {0, 0};
- if (apsta_params->rsdb)
- rsdb_mode_cfg.config = 1;
+ rsdb_mode_cfg.config = apsta_params->rsdb;
AEXT_INFO(dev->name, "set rsdb_mode %d\n", rsdb_mode_cfg.config);
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
}
} else {
- apsta_params->rsdb = FALSE;
+ apsta_params->rsdb = 0;
}
if (apstamode == ISTAONLY_MODE) {
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
}
}
-#endif
+#endif /* BCMSDIO */
#endif /* PROP_TXSTATUS_VSDB */
}
else if (apstamode == ISTAAP_MODE) {
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
}
-#endif
+#endif /* WLMESH */
wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
apsta_params->init = TRUE;
- WL_MSG(dev->name, "apstamode=%d\n", apstamode);
-}
-
-static void
-wl_ext_interface_create(struct net_device *dev, struct wl_apsta_params *apsta_params,
- struct wl_if_info *cur_if, int iftype, u8 *addr)
-{
- wl_interface_create_t iface;
- u8 iovar_buf[WLC_IOCTL_SMLEN];
-
- bzero(&iface, sizeof(iface));
- if (addr) {
- iftype |= WL_INTERFACE_MAC_USE;
- }
- iface.ver = WL_INTERFACE_CREATE_VER;
- iface.flags = iftype;
- if (addr) {
- memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
- }
- wl_set_isam_status(cur_if, IF_ADDING);
- wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, NULL);
- wl_ext_wait_netif_change(apsta_params, cur_if);
-}
-
-static void
-wl_ext_iapsta_intf_add(struct net_device *dev, struct wl_apsta_params *apsta_params)
-{
- struct dhd_pub *dhd;
- apstamode_t apstamode = apsta_params->apstamode;
- struct wl_if_info *cur_if;
- wlc_ssid_t ssid = { 0, {0} };
- s8 iovar_buf[WLC_IOCTL_SMLEN];
- wl_p2p_if_t ifreq;
- struct ether_addr mac_addr;
-
- dhd = dhd_get_pub(dev);
- bzero(&mac_addr, sizeof(mac_addr));
-
- if (apstamode == ISTAAP_MODE) {
- cur_if = &apsta_params->if_info[IF_VIF];
- if (FW_SUPPORTED(dhd, rsdb)) {
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
- } else {
- wl_set_isam_status(cur_if, IF_ADDING);
- wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid),
- iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
- wl_ext_wait_netif_change(apsta_params, cur_if);
- }
- }
- else if (apstamode == ISTAGO_MODE) {
- bzero(&ifreq, sizeof(wl_p2p_if_t));
- ifreq.type = htod32(WL_P2P_IF_GO);
- cur_if = &apsta_params->if_info[IF_VIF];
- wl_set_isam_status(cur_if, IF_ADDING);
- wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
- iovar_buf, WLC_IOCTL_SMLEN, NULL);
- wl_ext_wait_netif_change(apsta_params, cur_if);
- }
- else if (apstamode == ISTASTA_MODE) {
- cur_if = &apsta_params->if_info[IF_VIF];
- memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
- mac_addr.octet[0] |= 0x02;
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA,
- (u8*)&mac_addr);
- }
- else if (apstamode == IDUALAP_MODE) {
- cur_if = &apsta_params->if_info[IF_VIF];
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
- }
- else if (apstamode == ISTAAPAP_MODE) {
- u8 rand_bytes[2] = {0, };
- get_random_bytes(&rand_bytes, sizeof(rand_bytes));
- cur_if = &apsta_params->if_info[IF_VIF];
- memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
- mac_addr.octet[0] |= 0x02;
- mac_addr.octet[5] += 0x01;
- memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
- (u8*)&mac_addr);
- cur_if = &apsta_params->if_info[IF_VIF2];
- memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
- mac_addr.octet[0] |= 0x02;
- mac_addr.octet[5] += 0x02;
- memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
- (u8*)&mac_addr);
- }
-#ifdef WLMESH
- else if (apstamode == ISTAMESH_MODE) {
- cur_if = &apsta_params->if_info[IF_VIF];
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
- }
- else if (apstamode == IMESHAP_MODE) {
- cur_if = &apsta_params->if_info[IF_VIF];
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
- }
- else if (apstamode == ISTAAPMESH_MODE) {
- cur_if = &apsta_params->if_info[IF_VIF];
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
- cur_if = &apsta_params->if_info[IF_VIF2];
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
- }
- else if (apstamode == IMESHAPAP_MODE) {
- cur_if = &apsta_params->if_info[IF_VIF];
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
- cur_if = &apsta_params->if_info[IF_VIF2];
- wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+ WL_MSG(dev->name, "apstamode=%d\n", apstamode);
+}
+
+static int
+wl_ext_isam_param(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;
+ int ret = -1;
+ char *pick_tmp, *data, *param;
+ int bytes_written=-1;
+
+ AEXT_TRACE(dev->name, "command=%s, len=%d\n", command, total_len);
+
+ pick_tmp = command;
+ param = bcmstrtok(&pick_tmp, " ", 0); // pick isam_param
+ param = bcmstrtok(&pick_tmp, " ", 0); // pick cmd
+ while (param != NULL) {
+ data = bcmstrtok(&pick_tmp, " ", 0); // pick data
+ if (!strcmp(param, "acs")) {
+ if (data) {
+ apsta_params->acs = simple_strtol(data, NULL, 0);
+ ret = 0;
+ } else {
+ bytes_written = snprintf(command, total_len, "%d", apsta_params->acs);
+ ret = bytes_written;
+ goto exit;
+ }
+ }
+ param = bcmstrtok(&pick_tmp, " ", 0); // pick cmd
}
-#endif
+exit:
+ return ret;
}
static int
char *pch, *pick_tmp, *pick_tmp2, *param;
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
int i;
-
-#ifdef WL_STATIC_IF
- AEXT_ERROR(dev->name, "please remove WL_STATIC_IF from Makefile\n");
- return -1;
-#endif
if (apsta_params->init) {
AEXT_ERROR(dev->name, "don't init twice\n");
param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_init
param = bcmstrtok(&pick_tmp, " ", 0);
while (param != NULL) {
+ pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
+ if (!pick_tmp2) {
+ AEXT_ERROR(dev->name, "wrong param %s\n", param);
+ return -1;
+ }
if (!strcmp(param, "mode")) {
pch = NULL;
- pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
- if (pick_tmp2) {
- if (!strcmp(pick_tmp2, "sta")) {
- apsta_params->apstamode = ISTAONLY_MODE;
- } else if (!strcmp(pick_tmp2, "ap")) {
- apsta_params->apstamode = IAPONLY_MODE;
- } else if (!strcmp(pick_tmp2, "sta-ap")) {
- apsta_params->apstamode = ISTAAP_MODE;
- } else if (!strcmp(pick_tmp2, "sta-sta")) {
- apsta_params->apstamode = ISTASTA_MODE;
- apsta_params->vsdb = TRUE;
- } else if (!strcmp(pick_tmp2, "ap-ap")) {
- apsta_params->apstamode = IDUALAP_MODE;
- } else if (!strcmp(pick_tmp2, "sta-ap-ap")) {
- apsta_params->apstamode = ISTAAPAP_MODE;
- } else if (!strcmp(pick_tmp2, "apsta")) {
- apsta_params->apstamode = ISTAAP_MODE;
- apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
- apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
- } else if (!strcmp(pick_tmp2, "dualap")) {
- apsta_params->apstamode = IDUALAP_MODE;
- apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
- apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
- } else if (!strcmp(pick_tmp2, "sta-go") ||
- !strcmp(pick_tmp2, "gosta")) {
- if (!FW_SUPPORTED(dhd, p2p)) {
- return -1;
- }
- apsta_params->apstamode = ISTAGO_MODE;
- apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
- apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
-#ifdef WLMESH
- } else if (!strcmp(pick_tmp2, "mesh")) {
- apsta_params->apstamode = IMESHONLY_MODE;
- } else if (!strcmp(pick_tmp2, "sta-mesh")) {
- apsta_params->apstamode = ISTAMESH_MODE;
- } else if (!strcmp(pick_tmp2, "sta-ap-mesh")) {
- apsta_params->apstamode = ISTAAPMESH_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap")) {
- apsta_params->apstamode = IMESHAP_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) {
- apsta_params->apstamode = IMESHAPAP_MODE;
-#endif
- } else {
- AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n");
+ if (!strcmp(pick_tmp2, "sta")) {
+ apsta_params->apstamode = ISTAONLY_MODE;
+ } else if (!strcmp(pick_tmp2, "ap")) {
+ apsta_params->apstamode = IAPONLY_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-ap")) {
+ apsta_params->apstamode = ISTAAP_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-sta")) {
+ apsta_params->apstamode = ISTASTA_MODE;
+ apsta_params->vsdb = TRUE;
+ } else if (!strcmp(pick_tmp2, "ap-ap")) {
+ apsta_params->apstamode = IDUALAP_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-ap-ap")) {
+ apsta_params->apstamode = ISTAAPAP_MODE;
+ } else if (!strcmp(pick_tmp2, "apsta")) {
+ apsta_params->apstamode = ISTAAP_MODE;
+ apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
+ apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
+ } else if (!strcmp(pick_tmp2, "dualap")) {
+ apsta_params->apstamode = IDUALAP_MODE;
+ apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
+ apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-go") ||
+ !strcmp(pick_tmp2, "gosta")) {
+ if (!FW_SUPPORTED(dhd, p2p)) {
return -1;
}
- pch = bcmstrtok(&pick_tmp2, " -", 0);
- for (i=0; i<MAX_IF_NUM && pch; i++) {
- if (!strcmp(pch, "sta"))
- apsta_params->if_info[i].ifmode = ISTA_MODE;
- else if (!strcmp(pch, "ap"))
- apsta_params->if_info[i].ifmode = IAP_MODE;
+ apsta_params->apstamode = ISTAGO_MODE;
+ apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
+ apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
#ifdef WLMESH
- else if (!strcmp(pch, "mesh")) {
- if (dhd->conf->fw_type != FW_TYPE_MESH) {
- AEXT_ERROR(dev->name, "wrong fw type\n");
- return -1;
- }
- apsta_params->if_info[i].ifmode = IMESH_MODE;
+ } else if (!strcmp(pick_tmp2, "mesh")) {
+ apsta_params->apstamode = IMESHONLY_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-mesh")) {
+ apsta_params->apstamode = ISTAMESH_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-ap-mesh")) {
+ apsta_params->apstamode = ISTAAPMESH_MODE;
+ } else if (!strcmp(pick_tmp2, "mesh-ap")) {
+ apsta_params->apstamode = IMESHAP_MODE;
+ } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) {
+ apsta_params->apstamode = IMESHAPAP_MODE;
+#endif /* WLMESH */
+ } else {
+ AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n");
+ return -1;
+ }
+ pch = bcmstrtok(&pick_tmp2, " -", 0);
+ for (i=0; i<MAX_IF_NUM && pch; i++) {
+ if (!strcmp(pch, "sta"))
+ apsta_params->if_info[i].ifmode = ISTA_MODE;
+ else if (!strcmp(pch, "ap"))
+ apsta_params->if_info[i].ifmode = IAP_MODE;
+#ifdef WLMESH
+ else if (!strcmp(pch, "mesh")) {
+ if (dhd->conf->fw_type != FW_TYPE_MESH) {
+ AEXT_ERROR(dev->name, "wrong fw type\n");
+ return -1;
}
-#endif
- pch = bcmstrtok(&pick_tmp2, " -", 0);
+ apsta_params->if_info[i].ifmode = IMESH_MODE;
}
+#endif /* WLMESH */
+ pch = bcmstrtok(&pick_tmp2, " -", 0);
}
}
else if (!strcmp(param, "rsdb")) {
- pch = bcmstrtok(&pick_tmp, " ", 0);
- if (pch) {
- if (!strcmp(pch, "y")) {
- apsta_params->rsdb = TRUE;
- } else if (!strcmp(pch, "n")) {
- apsta_params->rsdb = FALSE;
- } else {
- AEXT_ERROR(dev->name, "rsdb [y|n]\n");
- return -1;
- }
- }
+ apsta_params->rsdb = (int)simple_strtol(pick_tmp2, NULL, 0);
} else if (!strcmp(param, "vsdb")) {
- pch = bcmstrtok(&pick_tmp, " ", 0);
- if (pch) {
- if (!strcmp(pch, "y")) {
- apsta_params->vsdb = TRUE;
- } else if (!strcmp(pch, "n")) {
- apsta_params->vsdb = FALSE;
- } else {
- AEXT_ERROR(dev->name, "vsdb [y|n]\n");
- return -1;
- }
+ if (!strcmp(pick_tmp2, "y")) {
+ apsta_params->vsdb = TRUE;
+ } else if (!strcmp(pick_tmp2, "n")) {
+ apsta_params->vsdb = FALSE;
+ } else {
+ AEXT_ERROR(dev->name, "vsdb [y|n]\n");
+ return -1;
}
} else if (!strcmp(param, "csa")) {
- pch = bcmstrtok(&pick_tmp, " ", 0);
- if (pch) {
- apsta_params->csa = (int)simple_strtol(pch, NULL, 0);
- }
+ apsta_params->csa = (int)simple_strtol(pick_tmp2, NULL, 0);
+ } else if (!strcmp(param, "acs")) {
+ apsta_params->acs = (int)simple_strtol(pick_tmp2, NULL, 0);
+#if defined(WLMESH) && defined(WL_ESCAN)
+ } else if (!strcmp(param, "macs")) {
+ apsta_params->macs = (int)simple_strtol(pick_tmp2, NULL, 0);
+#endif /* WLMESH && WL_ESCAN */
} else if (!strcmp(param, "ifname")) {
pch = NULL;
- pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
- if (pick_tmp2)
- pch = bcmstrtok(&pick_tmp2, " -", 0);
+ pch = bcmstrtok(&pick_tmp2, " -", 0);
for (i=0; i<MAX_IF_NUM && pch; i++) {
strcpy(apsta_params->if_info[i].ifname, pch);
pch = bcmstrtok(&pick_tmp2, " -", 0);
}
} else if (!strcmp(param, "vifname")) {
- pch = bcmstrtok(&pick_tmp, " ", 0);
- if (pch)
- strcpy(apsta_params->if_info[IF_VIF].ifname, pch);
- else {
- AEXT_ERROR(dev->name, "vifname [wlan1]\n");
- return -1;
- }
+ strcpy(apsta_params->if_info[IF_VIF].ifname, pick_tmp2);
}
param = bcmstrtok(&pick_tmp, " ", 0);
}
}
wl_ext_iapsta_preinit(dev, apsta_params);
+#ifndef WL_STATIC_IF
wl_ext_iapsta_intf_add(dev, apsta_params);
+#endif /* WL_STATIC_IF */
return 0;
}
ret = peer_results->count;
}
- return ret;
+ return ret;
+}
+
+static int
+wl_ext_mesh_peer_status(struct net_device *dev, char *data, char *command,
+ int total_len)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ int i;
+ struct wl_if_info *cur_if;
+ mesh_peer_info_dump_t *peer_results;
+ mesh_peer_info_ext_t *mpi_ext;
+ char *peer_buf = NULL;
+ int peer_len = WLC_IOCTL_MAXLEN;
+ int dump_written = 0, ret;
+
+ if (!data) {
+ peer_buf = kmalloc(peer_len, GFP_KERNEL);
+ if (peer_buf == NULL) {
+ AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
+ peer_len);
+ return -1;
+ }
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[i];
+ if (cur_if && dev == cur_if->dev && cur_if->ifmode == IMESH_MODE) {
+ memset(peer_buf, 0, peer_len);
+ ret = wl_mesh_get_peer_results(dev, peer_buf, peer_len);
+ if (ret >= 0) {
+ peer_results = (mesh_peer_info_dump_t *)peer_buf;
+ mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
+ dump_written += wl_mesh_print_peer_info(mpi_ext,
+ peer_results->count, command+dump_written,
+ total_len-dump_written);
+ }
+ } else if (cur_if && dev == cur_if->dev) {
+ AEXT_ERROR(dev->name, "[%s][%c] is not mesh interface\n",
+ cur_if->ifname, cur_if->prefix);
+ }
+ }
+ }
+
+ if (peer_buf)
+ kfree(peer_buf);
+ return dump_written;
+}
+
+#ifdef WL_ESCAN
+#define WL_MESH_DELAY_SCAN_MS 3000
+static void
+wl_mesh_timer(unsigned long data)
+{
+ wl_event_msg_t msg;
+ struct wl_if_info *mesh_if = (struct wl_if_info *)data;
+ struct dhd_pub *dhd;
+
+ if (!mesh_if) {
+ AEXT_ERROR("wlan", "mesh_if is not ready\n");
+ return;
+ }
+
+ if (!mesh_if->dev) {
+ AEXT_ERROR("wlan", "ifidx %d is not ready\n", mesh_if->ifidx);
+ return;
+ }
+ dhd = dhd_get_pub(mesh_if->dev);
+
+ bzero(&msg, sizeof(wl_event_msg_t));
+ AEXT_TRACE(mesh_if->dev->name, "timer expired\n");
+
+ msg.ifidx = mesh_if->ifidx;
+ msg.event_type = hton32(WLC_E_RESERVED);
+ msg.reason = 0xFFFFFFFF;
+ wl_ext_event_send(dhd->event_params, &msg, NULL);
+}
+
+static void
+wl_mesh_set_timer(struct wl_if_info *mesh_if, uint timeout)
+{
+ AEXT_TRACE(mesh_if->dev->name, "timeout=%d\n", timeout);
+
+ if (timer_pending(&mesh_if->delay_scan))
+ del_timer_sync(&mesh_if->delay_scan);
+
+ if (timeout) {
+ if (timer_pending(&mesh_if->delay_scan))
+ del_timer_sync(&mesh_if->delay_scan);
+ mod_timer(&mesh_if->delay_scan, jiffies + msecs_to_jiffies(timeout));
+ }
+}
+
+static int
+wl_mesh_clear_vndr_ie(struct net_device *dev, uchar *oui)
+{
+ char *vndr_ie_buf = NULL;
+ vndr_ie_setbuf_t *vndr_ie = NULL;
+ ie_getbuf_t vndr_ie_tmp;
+ char *iovar_buf = NULL;
+ int err = -1, i;
+ vndr_ie_buf_t *vndr_ie_dump = NULL;
+ uchar *iebuf;
+ vndr_ie_info_t *ie_info;
+ vndr_ie_t *ie;
+
+ vndr_ie_buf = kzalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
+ if (!vndr_ie_buf) {
+ AEXT_ERROR(dev->name, "IE memory alloc failed\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ iovar_buf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (!iovar_buf) {
+ AEXT_ERROR(dev->name, "iovar_buf alloc failed\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ memset(iovar_buf, 0, WLC_IOCTL_MEDLEN);
+ vndr_ie_tmp.pktflag = (uint32) -1;
+ vndr_ie_tmp.id = (uint8) DOT11_MNG_PROPR_ID;
+ err = wl_ext_iovar_getbuf(dev, "vndr_ie", &vndr_ie_tmp, sizeof(vndr_ie_tmp),
+ iovar_buf, WLC_IOCTL_MEDLEN, NULL);
+ if (err)
+ goto exit;
+
+ vndr_ie_dump = (vndr_ie_buf_t *)iovar_buf;
+ if (!vndr_ie_dump->iecount)
+ goto exit;
+
+ iebuf = (uchar *)&vndr_ie_dump->vndr_ie_list[0];
+ for (i=0; i<vndr_ie_dump->iecount; i++) {
+ ie_info = (vndr_ie_info_t *) iebuf;
+ ie = &ie_info->vndr_ie_data;
+ if (memcmp(ie->oui, oui, 3))
+ memset(ie->oui, 0, 3);
+ iebuf += sizeof(uint32) + ie->len + VNDR_IE_HDR_LEN;
+ }
+
+ vndr_ie = (vndr_ie_setbuf_t *) vndr_ie_buf;
+ strncpy(vndr_ie->cmd, "del", VNDR_IE_CMD_LEN - 1);
+ vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+ memcpy(&vndr_ie->vndr_ie_buffer, vndr_ie_dump, WLC_IOCTL_SMLEN-VNDR_IE_CMD_LEN-1);
+
+ memset(iovar_buf, 0, WLC_IOCTL_MEDLEN);
+ err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, WLC_IOCTL_SMLEN, iovar_buf,
+ WLC_IOCTL_MEDLEN, NULL);
+
+exit:
+ if (vndr_ie) {
+ kfree(vndr_ie);
+ }
+ if (iovar_buf) {
+ kfree(iovar_buf);
+ }
+ return err;
+}
+
+static int
+wl_mesh_clear_mesh_info(struct wl_apsta_params *apsta_params,
+ struct wl_if_info *mesh_if, bool scan)
+{
+ struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+ uchar mesh_oui[]={0x00, 0x22, 0xf4};
+ int ret;
+
+ AEXT_TRACE(mesh_if->dev->name, "Enter\n");
+
+ 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_mesh_set_timer(mesh_if, 100);
+ }
+
+ return ret;
+}
+
+static int
+wl_mesh_update_vndr_ie(struct wl_apsta_params *apsta_params,
+ struct wl_if_info *mesh_if)
+{
+ struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+ char *vndr_ie;
+ uchar mesh_oui[]={0x00, 0x22, 0xf4};
+ int bytes_written = 0;
+ int ret = 0, i, vndr_ie_len;
+ uint8 *peer_bssid;
+
+ wl_mesh_clear_vndr_ie(mesh_if->dev, mesh_oui);
+
+ vndr_ie_len = WLC_IOCTL_MEDLEN;
+ vndr_ie = kmalloc(vndr_ie_len, GFP_KERNEL);
+ if (vndr_ie == NULL) {
+ AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n",
+ WLC_IOCTL_MEDLEN);
+ ret = -1;
+ goto exit;
+ }
+
+ bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+ "0x%02x%02x%02x", mesh_oui[0], mesh_oui[1], mesh_oui[2]);
+
+ bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+ "%02x%02x%02x%02x%02x%02x%02x%02x", MESH_INFO_MASTER_BSSID, ETHER_ADDR_LEN,
+ ((u8 *)(&mesh_info->master_bssid))[0], ((u8 *)(&mesh_info->master_bssid))[1],
+ ((u8 *)(&mesh_info->master_bssid))[2], ((u8 *)(&mesh_info->master_bssid))[3],
+ ((u8 *)(&mesh_info->master_bssid))[4], ((u8 *)(&mesh_info->master_bssid))[5]);
+
+ bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+ "%02x%02x%02x", MESH_INFO_MASTER_CHANNEL, 1, mesh_info->master_channel);
+
+ bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+ "%02x%02x%02x", MESH_INFO_HOP_CNT, 1, mesh_info->hop_cnt);
+
+ bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+ "%02x%02x", MESH_INFO_PEER_BSSID, mesh_info->hop_cnt*ETHER_ADDR_LEN);
+ for (i=0; i<mesh_info->hop_cnt && i<MAX_HOP_LIST; i++) {
+ peer_bssid = (uint8 *)&mesh_info->peer_bssid[i];
+ bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+ "%02x%02x%02x%02x%02x%02x",
+ peer_bssid[0], peer_bssid[1], peer_bssid[2],
+ peer_bssid[3], peer_bssid[4], peer_bssid[5]);
+ }
+
+ ret = wl_ext_add_del_ie(mesh_if->dev, VNDR_IE_BEACON_FLAG|VNDR_IE_PRBRSP_FLAG,
+ vndr_ie, "add");
+ if (!ret) {
+ AEXT_INFO(mesh_if->dev->name, "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM\n",
+ &mesh_info->master_bssid, mesh_info->master_channel, mesh_info->hop_cnt,
+ mesh_info->peer_bssid);
+ }
+
+exit:
+ if (vndr_ie)
+ kfree(vndr_ie);
+ return ret;
+}
+
+static bool
+wl_mesh_update_master_info(struct wl_apsta_params *apsta_params,
+ struct wl_if_info *mesh_if)
+{
+ struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+ struct wl_if_info *sta_if = NULL;
+ bool updated = FALSE;
+
+ sta_if = wl_ext_if_enabled(apsta_params, ISTA_MODE);
+ 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->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))
+ updated = TRUE;
+ }
+
+ return updated;
+}
+
+static bool
+wl_mesh_update_mesh_info(struct wl_apsta_params *apsta_params,
+ struct wl_if_info *mesh_if)
+{
+ struct wl_mesh_params *mesh_info = &apsta_params->mesh_info, peer_mesh_info;
+ uint32 count = 0;
+ char *dump_buf = NULL;
+ mesh_peer_info_dump_t *peer_results;
+ mesh_peer_info_ext_t *mpi_ext;
+ struct ether_addr bssid;
+ bool updated = FALSE, bss_found = FALSE;
+ uint16 cur_chan;
+
+ dump_buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+ if (dump_buf == NULL) {
+ AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n",
+ WLC_IOCTL_MAXLEN);
+ return FALSE;
+ }
+ count = wl_mesh_get_peer_results(mesh_if->dev, dump_buf, WLC_IOCTL_MAXLEN);
+ if (count > 0) {
+ memset(&bssid, 0, ETHER_ADDR_LEN);
+ wldev_ioctl(mesh_if->dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, 0);
+ peer_results = (mesh_peer_info_dump_t *)dump_buf;
+ mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
+ for (count = 0; count < peer_results->count; count++) {
+ if (mpi_ext->entry_state != MESH_SELF_PEER_ENTRY_STATE_TIMEDOUT &&
+ mpi_ext->peer_info.state == MESH_PEERING_ESTAB) {
+ memset(&peer_mesh_info, 0, sizeof(struct wl_mesh_params));
+ bss_found = wl_escan_mesh_info(mesh_if->dev, mesh_if->escan,
+ &mpi_ext->ea, &peer_mesh_info);
+ if (bss_found && (mesh_info->master_channel == 0 ||
+ peer_mesh_info.hop_cnt <= mesh_info->hop_cnt) &&
+ memcmp(&peer_mesh_info.peer_bssid, &bssid, ETHER_ADDR_LEN)) {
+ memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+ ETHER_ADDR_LEN);
+ mesh_info->master_channel = peer_mesh_info.master_channel;
+ mesh_info->hop_cnt = peer_mesh_info.hop_cnt+1;
+ memset(mesh_info->peer_bssid, 0, MAX_HOP_LIST*ETHER_ADDR_LEN);
+ memcpy(&mesh_info->peer_bssid, &mpi_ext->ea, ETHER_ADDR_LEN);
+ memcpy(&mesh_info->peer_bssid[1], peer_mesh_info.peer_bssid,
+ (MAX_HOP_LIST-1)*ETHER_ADDR_LEN);
+ updated = TRUE;
+ }
+ }
+ mpi_ext++;
+ }
+ if (updated) {
+ if (wl_mesh_update_vndr_ie(apsta_params, mesh_if)) {
+ AEXT_ERROR(mesh_if->dev->name, "update failed\n");
+ mesh_info->master_channel = 0;
+ updated = FALSE;
+ goto exit;
+ }
+ }
+ }
+
+ if (!mesh_info->master_channel) {
+ wlc_ssid_t cur_ssid;
+ char sec[32];
+ bool sae = FALSE;
+ memset(&peer_mesh_info, 0, sizeof(struct wl_mesh_params));
+ wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &cur_ssid, sizeof(cur_ssid), 0);
+ wl_ext_get_sec(mesh_if->dev, mesh_if->ifmode, sec, sizeof(sec));
+ if (strnicmp(sec, "sae/sae", strlen("sae/sae")) == 0)
+ sae = TRUE;
+ cur_chan = wl_ext_get_chan(apsta_params, mesh_if->dev);
+ bss_found = wl_escan_mesh_peer(mesh_if->dev, mesh_if->escan, &cur_ssid, cur_chan,
+ sae, &peer_mesh_info);
+
+ if (bss_found && peer_mesh_info.master_channel&&
+ (cur_chan != peer_mesh_info.master_channel)) {
+ WL_MSG(mesh_if->ifname, "moving channel %d -> %d\n",
+ cur_chan, peer_mesh_info.master_channel);
+ wl_ext_disable_iface(mesh_if->dev, mesh_if->ifname);
+ mesh_if->channel = peer_mesh_info.master_channel;
+ wl_ext_enable_iface(mesh_if->dev, mesh_if->ifname, 500);
+ }
+ }
+
+exit:
+ if (dump_buf)
+ kfree(dump_buf);
+ return updated;
+}
+
+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)
+{
+ 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);
+ wlc_ssid_t ssid;
+ int ret;
+
+ 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_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS);
+ }
+ }
+ 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_mesh_set_timer(mesh_if, 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 == 0xFFFFFFFF) {
+ if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
+ wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
+ ret = wl_escan_set_scan(mesh_if->dev, apsta_params->dhd, &ssid,
+ mesh_info->scan_channel, FALSE);
+ if (ret)
+ wl_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS);
+ }
+ }
+ 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_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS);
+ }
+ }
+ }
+}
+
+static void
+wl_mesh_escan_detach(dhd_pub_t *dhd, struct wl_if_info *mesh_if)
+{
+ AEXT_TRACE(mesh_if->dev->name, "Enter\n");
+
+ del_timer_sync(&mesh_if->delay_scan);
+
+ if (mesh_if->escan) {
+ mesh_if->escan = NULL;
+ }
+}
+
+static int
+wl_mesh_escan_attach(dhd_pub_t *dhd, struct wl_if_info *mesh_if)
+{
+ AEXT_TRACE(mesh_if->dev->name, "Enter\n");
+
+ mesh_if->escan = dhd->escan;
+ init_timer_compat(&mesh_if->delay_scan, wl_mesh_timer, mesh_if);
+
+ return 0;
+}
+
+static uint
+wl_mesh_update_peer_path(struct wl_if_info *mesh_if, char *command,
+ int total_len)
+{
+ struct wl_mesh_params peer_mesh_info;
+ uint32 count = 0;
+ char *dump_buf = NULL;
+ mesh_peer_info_dump_t *peer_results;
+ mesh_peer_info_ext_t *mpi_ext;
+ int bytes_written = 0, j, k;
+ bool bss_found = FALSE;
+
+ dump_buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+ if (dump_buf == NULL) {
+ AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n",
+ WLC_IOCTL_MAXLEN);
+ return FALSE;
+ }
+ count = wl_mesh_get_peer_results(mesh_if->dev, dump_buf, WLC_IOCTL_MAXLEN);
+ if (count > 0) {
+ peer_results = (mesh_peer_info_dump_t *)dump_buf;
+ mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
+ for (count = 0; count < peer_results->count; count++) {
+ if (mpi_ext->entry_state != MESH_SELF_PEER_ENTRY_STATE_TIMEDOUT &&
+ mpi_ext->peer_info.state == MESH_PEERING_ESTAB) {
+ memset(&peer_mesh_info, 0, sizeof(struct wl_mesh_params));
+ bss_found = wl_escan_mesh_info(mesh_if->dev, mesh_if->escan,
+ &mpi_ext->ea, &peer_mesh_info);
+ if (bss_found) {
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "\npeer=%pM, hop=%d",
+ &mpi_ext->ea, peer_mesh_info.hop_cnt);
+ for (j=1; j<peer_mesh_info.hop_cnt; j++) {
+ bytes_written += snprintf(command+bytes_written,
+ total_len, "\n");
+ for (k=0; k<j; k++) {
+ bytes_written += snprintf(command+bytes_written,
+ total_len, " ");
+ }
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "%pM", &peer_mesh_info.peer_bssid[j]);
+ }
+ }
+ }
+ mpi_ext++;
+ }
+ }
+
+ if (dump_buf)
+ kfree(dump_buf);
+ return bytes_written;
}
static int
-wl_ext_mesh_peer_status(struct net_device *dev, char *data, char *command,
- int total_len)
+wl_ext_isam_peer_path(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_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;
int i;
- struct wl_if_info *cur_if;
- mesh_peer_info_dump_t *peer_results;
- mesh_peer_info_ext_t *mpi_ext;
- char *peer_buf = NULL;
- int peer_len = WLC_IOCTL_MAXLEN;
- int dump_written = 0, ret;
- if (!data) {
- peer_buf = kmalloc(peer_len, GFP_KERNEL);
- if (peer_buf == NULL) {
- AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
- peer_len);
- return -1;
+ if (command || android_msg_level & ANDROID_INFO_LEVEL) {
+ if (command) {
+ dump_buf = command;
+ dump_len = total_len;
+ } else {
+ dump_buf = kmalloc(dump_len, GFP_KERNEL);
+ if (dump_buf == NULL) {
+ AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
+ dump_len);
+ return -1;
+ }
}
for (i=0; i<MAX_IF_NUM; i++) {
- cur_if = &apsta_params->if_info[i];
- if (cur_if && dev == cur_if->dev && cur_if->ifmode == IMESH_MODE) {
- memset(peer_buf, 0, peer_len);
- ret = wl_mesh_get_peer_results(dev, peer_buf, peer_len);
- if (ret >= 0) {
- peer_results = (mesh_peer_info_dump_t *)peer_buf;
- mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
- dump_written += wl_mesh_print_peer_info(mpi_ext,
- peer_results->count, command+dump_written,
- total_len-dump_written);
+ 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) {
+ dump_written += snprintf(dump_buf+dump_written, dump_len,
+ "[dhd-%s-%c] mbssid=%pM, mchan=%d, hop=%d, pbssid=%pM",
+ tmp_if->ifname, tmp_if->prefix, &mesh_info->master_bssid,
+ mesh_info->master_channel, mesh_info->hop_cnt,
+ &mesh_info->peer_bssid);
+ dump_written += wl_mesh_update_peer_path(tmp_if,
+ dump_buf+dump_written, dump_len-dump_written);
}
- } else if (cur_if && dev == cur_if->dev) {
- AEXT_ERROR(dev->name, "[%s][%c] is not mesh interface\n",
- cur_if->ifname, cur_if->prefix);
}
}
+ AEXT_INFO(dev->name, "%s\n", dump_buf);
}
- if (peer_buf)
- kfree(peer_buf);
+ if (!command && dump_buf)
+ kfree(dump_buf);
return dump_written;
}
-#endif
+#endif /* WL_ESCAN */
+#endif /* WLMESH */
static 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;
int i;
- bool now_if;
struct wl_if_info *tmp_if;
uint16 chan = 0;
wlc_ssid_t ssid = { 0, {0} };
dump_written += snprintf(dump_buf+dump_written, dump_len,
"apstamode=%d", apsta_params->apstamode);
for (i=0; i<MAX_IF_NUM; i++) {
- now_if = FALSE;
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 (dev == tmp_if->dev)
- now_if = TRUE;
if (tmp_if->dev) {
chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
if (chan) {
chanspec = wl_ext_get_chanspec(apsta_params, tmp_if->dev);
wl_ext_get_sec(tmp_if->dev, tmp_if->ifmode, sec, sizeof(sec));
dump_written += snprintf(dump_buf+dump_written, dump_len,
- "\n[dhd-%s][%c-%c%s]: bssid=%pM, chan=%3d(0x%x), "
+ "\n[dhd-%s-%c]: bssid=%pM, chan=%3d(0x%x %sMHz), "
"rssi=%3d, sec=%-15s, SSID=\"%s\"",
- tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
- now_if?"*":" ", &bssid, chan, chanspec,
+ 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_mesh_peer_status(tmp_if->dev, NULL,
dump_buf+dump_written, dump_len-dump_written);
}
-#endif
+#endif /* WLMESH */
} else {
dump_written += snprintf(dump_buf+dump_written, dump_len,
- "\n[dhd-%s][%c-%c%s]:",
- tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
- now_if?"*":" ");
+ "\n[dhd-%s-%c]:", tmp_if->ifname, tmp_if->prefix);
}
}
}
return dump_written;
}
+static bool
+wl_ext_master_if(struct wl_if_info *cur_if)
+{
+ if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
static int
wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
{
return 0;
}
- if (wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) {
+ if (wl_ext_dfs_chan(cur_if->channel) && !apsta_params->radar) {
WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
cur_if->prefix, cur_if->channel);
return 0;
+ } else if (!cur_if->channel) {
+ 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);
if (cur_if->ifmode == ISTA_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
+ wl_ext_add_remove_pm_enable_work(dev, FALSE);
} else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
// deauthenticate all STA first
memcpy(scbval.ea.octet, ðer_bcast, ETHER_ADDR_LEN);
dhd_wlfc_deinit(dhd);
}
}
-#endif
+#endif /* BCMSDIO */
#endif /* PROP_TXSTATUS_VSDB */
}
- else if (apstamode == IDUALAP_MODE) {
+ else if (apstamode == IDUALAP_MODE || apstamode == ISTAAPAP_MODE) {
bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
#ifdef WLMESH
} else if (apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE ||
- apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE ||
- apstamode == ISTAAPAP_MODE) {
+ apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE) {
bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
-#endif
- }
-#ifdef WLMESH
- if ((cur_if->ifmode == IMESH_MODE) &&
- (apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE ||
- apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE)) {
- int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME;
- 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_ioctl(tmp_if->dev, WLC_SET_SCAN_CHANNEL_TIME,
- &scan_assoc_time, sizeof(scan_assoc_time), 1);
+ if (cur_if->ifmode == IMESH_MODE) {
+ int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME;
+ 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_ioctl(tmp_if->dev, WLC_SET_SCAN_CHANNEL_TIME,
+ &scan_assoc_time, sizeof(scan_assoc_time), 1);
+ }
}
}
+#endif /* WLMESH */
}
-#endif
wl_clr_isam_status(cur_if, AP_CREATED);
return FALSE;
}
+static uint16
+wl_ext_same_band(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;
+ wl_prio_t max_prio;
+ int i;
+
+ // find the max prio
+ max_prio = cur_if->prio;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ 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)
+ continue;
+ if (tmp_chan && !wl_ext_diff_band(cur_if->channel, tmp_chan)) {
+ target_chan = tmp_chan;
+ max_prio = tmp_if->prio;
+ }
+ }
+ }
+
+ return target_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)
s8 iovar_buf[WLC_IOCTL_SMLEN];
bool core_conflict = FALSE;
- if (apsta_params->csa & CSA_DRV_BIT &&
- (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) {
+ if (wl_ext_master_if(cur_if) && (apsta_params->csa & CSA_DRV_BIT)) {
if (!cur_if->channel) {
- WL_MSG(cur_if->ifname, "[%c] skip channel %d\n",
- cur_if->prefix, cur_if->channel);
- } else if (wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) {
+ 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) {
WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
cur_if->prefix, cur_if->channel);
wl_ext_if_down(apsta_params, cur_if);
return 0;
}
+static void
+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;
+ 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 (!chan_2g && !chan_5g) {
+ cur_if->channel = 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 (other_chan)
+ cur_if->channel = other_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);
+ }
+ } 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 (other_chan)
+ cur_if->channel = other_chan;
+ } else {
+ 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)) {
+ cur_if->channel = 0;
+ }
+ else if (!other_chan) {
+ other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+ auto_band);
+ }
+ if (other_chan)
+ cur_if->channel = other_chan;
+ }
+ WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n",
+ cur_if->prefix, cur_chan, cur_if->channel);
+ }
+}
+
+static void
+wl_ext_move_other_dfs_channel(struct wl_apsta_params *apsta_params,
+ struct wl_if_info *cur_if)
+{
+ uint16 other_chan = 0, cur_chan = cur_if->channel;
+ 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 (!chan_2g && !chan_5g) {
+ cur_if->channel = 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 (other_chan)
+ cur_if->channel = other_chan;
+ } 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);
+ }
+ } else {
+ cur_if->channel = 0;
+ }
+ if (other_chan)
+ cur_if->channel = other_chan;
+ } else {
+ cur_if->channel = 0;
+ }
+ WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n",
+ cur_if->prefix, cur_chan, cur_if->channel);
+ }
+}
+
static uint16
wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params,
- struct net_device *dev, struct wl_if_info *cur_if)
+ struct wl_if_info *cur_if)
{
struct wl_if_info *tmp_if, *target_if = NULL;
uint16 tmp_chan, target_chan = 0;
}
}
}
+
if (target_chan) {
tmp_chan = wl_ext_get_chan(apsta_params, cur_if->dev);
if (apsta_params->rsdb && tmp_chan &&
cur_if->channel = target_chan;
}
}
+
exit:
- if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) &&
- wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) {
- WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
- cur_if->prefix, cur_if->channel);
- cur_if->channel = 0;
- }
+ wl_ext_move_cur_dfs_channel(apsta_params, cur_if);
return cur_if->channel;
}
static void
wl_ext_move_other_channel(struct wl_apsta_params *apsta_params,
- struct net_device *dev, struct wl_if_info *cur_if)
+ struct wl_if_info *cur_if)
{
struct wl_if_info *tmp_if, *target_if=NULL;
uint16 tmp_chan, target_chan = 0;
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_ext_move_other_dfs_channel(apsta_params, target_if);
if (apsta_params->csa == 0) {
wl_ext_if_down(apsta_params, target_if);
- wl_ext_move_other_channel(apsta_params, dev, target_if);
+ wl_ext_move_other_channel(apsta_params, cur_if);
if (target_if->ifmode == ISTA_MODE || target_if->ifmode == IMESH_MODE) {
- wl_ext_enable_iface(target_if->dev, target_if->ifname);
+ wl_ext_enable_iface(target_if->dev, target_if->ifname, 0);
} else if (target_if->ifmode == IAP_MODE) {
wl_ext_if_up(apsta_params, target_if);
}
}
+static bool
+wl_ext_wait_other_enabling(struct wl_apsta_params *apsta_params,
+ struct wl_if_info *cur_if)
+{
+ struct wl_if_info *tmp_if;
+ bool enabling = FALSE;
+ u32 timeout = 1;
+ int i;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->dev && tmp_if->dev != cur_if->dev) {
+ if (tmp_if->ifmode == ISTA_MODE)
+ enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
+ else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
+ enabling = wl_get_isam_status(tmp_if, AP_CREATING);
+ if (enabling)
+ WL_MSG(cur_if->ifname, "waiting for %s[%c] enabling...\n",
+ tmp_if->ifname, tmp_if->prefix);
+ if (enabling && tmp_if->ifmode == ISTA_MODE) {
+ timeout = wait_event_interruptible_timeout(
+ apsta_params->netif_change_event,
+ !wl_get_isam_status(tmp_if, STA_CONNECTING),
+ msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
+ } else if (enabling &&
+ (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)) {
+ timeout = wait_event_interruptible_timeout(
+ apsta_params->netif_change_event,
+ !wl_get_isam_status(tmp_if, AP_CREATING),
+ msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
+ }
+ if (tmp_if->ifmode == ISTA_MODE)
+ enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
+ else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
+ enabling = wl_get_isam_status(tmp_if, AP_CREATING);
+ if (timeout <= 0 || enabling) {
+ WL_MSG(cur_if->ifname, "%s[%c] is still enabling...\n",
+ tmp_if->ifname, tmp_if->prefix);
+ }
+ }
+ }
+
+ return enabling;
+}
+
static int
-wl_ext_enable_iface(struct net_device *dev, char *ifname)
+wl_ext_enable_iface(struct net_device *dev, char *ifname, int wait_up)
{
struct dhd_pub *dhd = dhd_get_pub(dev);
int i, ret = 0;
wl_ext_isam_status(cur_if->dev, NULL, 0);
WL_MSG(ifname, "[%c] Enabling...\n", cur_if->prefix);
- wl_ext_check_other_enabling(apsta_params, cur_if);
+ wl_ext_wait_other_enabling(apsta_params, cur_if);
+
+ 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);
+ } else {
+ AEXT_ERROR(ifname, "invalid channel\n");
+ ret = -1;
+ goto exit;
+ }
+ }
+
+ wl_ext_move_cur_channel(apsta_params, cur_if);
- wl_ext_move_cur_channel(apsta_params, dev, cur_if);
- if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) {
+ if (wl_ext_master_if(cur_if) && !cur_if->channel) {
+ AEXT_ERROR(ifname, "skip channel 0\n");
+ ret = -1;
goto exit;
}
wl_clr_isam_status(cur_if, AP_CREATED);
}
- wl_ext_move_other_channel(apsta_params, dev, cur_if);
+ wl_ext_move_other_channel(apsta_params, cur_if);
if (cur_if->ifidx > 0) {
wl_ext_iovar_setbuf(cur_if->dev, "cur_etheraddr", (u8 *)cur_if->dev->dev_addr,
}
}
- if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+ if (wl_ext_master_if(cur_if)) {
wl_ext_set_bgnmode(cur_if);
if (!cur_if->channel) {
-#ifdef WL_CFG80211
- char *pick_tmp, *param;
- char cmd[128];
- uint16 cur_chan;
- cur_chan = 1;
- snprintf(cmd, 128, "get_best_channels");
- wl_cfg80211_get_best_channels(dev, cmd, strlen(cmd));
- pick_tmp = cmd;
- param = bcmstrtok(&pick_tmp, " ", 0);
- while (param != NULL) {
- if (!strnicmp(param, "2g=", strlen("2g="))) {
- cur_chan = (int)simple_strtol(param+strlen("2g="), NULL, 10);
- } else if (!strnicmp(param, "5g=", strlen("5g="))) {
- cur_chan = (int)simple_strtol(param+strlen("5g="), NULL, 10);
- }
- param = bcmstrtok(&pick_tmp, " ", 0);
- }
- cur_if->channel = cur_chan;
-#else
cur_if->channel = 1;
-#endif
}
- wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
- &fw_chspec);
+ ret = wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver,
+ cur_if->channel, &fw_chspec);
+ if (ret)
+ goto exit;
}
wl_ext_set_amode(cur_if);
if (cur_if->ifmode == ISTA_MODE) {
wl_ext_connect(cur_if->dev, &conn_info);
} else {
- if (apsta_params->rsdb) {
+ if (FW_SUPPORTED(dhd, rsdb)) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
} else {
bss_setbuf.cfg = htod32(cur_if->bssidx);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
}
}
-#endif
+#endif /* BCMSDIO */
#endif /* PROP_TXSTATUS_VSDB */
}
}
} else {
AEXT_ERROR(cur_if->ifname, "wrong ifmode %d\n", cur_if->ifmode);
}
-#endif
+#endif /* WLMESH */
}
- if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+ if (wait_up) {
+ OSL_SLEEP(wait_up);
+ } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
timeout = wait_event_interruptible_timeout(apsta_params->netif_change_event,
wl_get_isam_status(cur_if, AP_CREATED),
msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
if (timeout <= 0 || !wl_get_isam_status(cur_if, AP_CREATED)) {
+ mutex_unlock(&apsta_params->usr_sync);
wl_ext_disable_iface(dev, cur_if->ifname);
WL_MSG(ifname, "[%c] failed to enable with SSID: \"%s\"\n",
cur_if->prefix, cur_if->ssid);
if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
wl_clr_isam_status(cur_if, AP_CREATING);
}
- WL_MSG(ifname, "[%c] Exit\n", cur_if->prefix);
+ WL_MSG(ifname, "[%c] Exit ret=%d\n", cur_if->prefix, ret);
mutex_unlock(&apsta_params->usr_sync);
return ret;
}
pch = bcmstrtok(&pick_tmp, " ", 0);
if (pch) {
strcpy(ifname, pch);
- ret = wl_ext_enable_iface(dev, ifname);
+ ret = wl_ext_enable_iface(dev, ifname, 0);
if (ret)
return ret;
} else {
return ret;
}
+#ifdef PROPTX_MAXCOUNT
int
-wl_ext_iapsta_alive_preinit(struct net_device *dev)
+wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx)
{
- struct dhd_pub *dhd = dhd_get_pub(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;
- if (apsta_params->init == TRUE) {
- AEXT_ERROR(dev->name, "don't init twice\n");
- return -1;
- }
-
- AEXT_TRACE(dev->name, "Enter\n");
-
- apsta_params->init = TRUE;
-
- return 0;
-}
-
-int
-wl_ext_iapsta_alive_postinit(struct net_device *dev)
-{
- struct dhd_pub *dhd = dhd_get_pub(dev);
- struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- s32 apsta = 0;
- struct wl_if_info *cur_if;
- int i;
+ if (!apsta_params->rsdb)
+ return maxcount;
- wl_ext_iovar_getint(dev, "apsta", &apsta);
- if (apsta == 1) {
- apsta_params->apstamode = ISTAONLY_MODE;
- apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
- op_mode = DHD_FLAG_STA_MODE;
- } else {
- apsta_params->apstamode = IAPONLY_MODE;
- apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
- op_mode = DHD_FLAG_HOSTAP_MODE;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->dev && tmp_if->ifidx == ifidx) {
+ cur_if = tmp_if;
+ maxcount = cur_if->transit_maxcount;
+ }
}
- // 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);
+ if (cur_if)
+ AEXT_INFO(cur_if->ifname, "update maxcount %d\n", maxcount);
+ else
+ AEXT_INFO("wlan", "update maxcount %d for ifidx %d\n", maxcount, ifidx);
+ return maxcount;
+}
+
+void
+wl_ext_update_wlfc_maxcount(struct dhd_pub *dhd)
+{
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *tmp_if;
+ bool band_5g = FALSE;
+ uint16 chan = 0;
+ int i, ret;
+
+ if (!apsta_params->rsdb)
+ return;
for (i=0; i<MAX_IF_NUM; i++) {
- cur_if = &apsta_params->if_info[i];
- if (i == 1 && !strlen(cur_if->ifname))
- strcpy(cur_if->ifname, "wlan1");
- if (i == 2 && !strlen(cur_if->ifname))
- strcpy(cur_if->ifname, "wlan2");
- if (cur_if->ifmode == ISTA_MODE) {
- cur_if->channel = 0;
- cur_if->maxassoc = -1;
- wl_set_isam_status(cur_if, IF_READY);
- cur_if->prio = PRIO_STA;
- 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;
- cur_if->maxassoc = -1;
- wl_set_isam_status(cur_if, IF_READY);
- cur_if->prio = PRIO_AP;
- cur_if->prefix = 'A';
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
-#ifdef WLMESH
- } else if (cur_if->ifmode == IMESH_MODE) {
- cur_if->channel = 1;
- cur_if->maxassoc = -1;
- wl_set_isam_status(cur_if, IF_READY);
- cur_if->prio = PRIO_MESH;
- cur_if->prefix = 'M';
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
-#endif
+ 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) {
+ tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_5g;
+ ret = dhd_wlfc_update_maxcount(dhd, tmp_if->ifidx,
+ tmp_if->transit_maxcount);
+ if (ret == 0)
+ AEXT_INFO(tmp_if->ifname, "updated maxcount %d\n",
+ tmp_if->transit_maxcount);
+ band_5g = TRUE;
+ }
}
}
- return op_mode;
+ 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) {
+ tmp_if->transit_maxcount = WL_TXSTATUS_FREERUNCTR_MASK;
+ } else if (band_5g) {
+ tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_2g;
+ } else {
+ tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_5g;
+ }
+ ret = dhd_wlfc_update_maxcount(dhd, tmp_if->ifidx,
+ tmp_if->transit_maxcount);
+ if (ret == 0)
+ AEXT_INFO(tmp_if->ifname, "updated maxcount %d\n",
+ tmp_if->transit_maxcount);
+ }
+ }
+ }
}
+#endif /* PROPTX_MAXCOUNT */
-int
+static int
wl_ext_iapsta_event(struct net_device *dev,
struct wl_apsta_params *apsta_params, wl_event_msg_t *e, void* data)
{
struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
+#if defined(WLMESH) && defined(WL_ESCAN)
+ struct wl_if_info *mesh_if = NULL;
+#endif /* WLMESH && WL_ESCAN */
int i;
uint32 event_type = ntoh32(e->event_type);
uint32 status = ntoh32(e->status);
break;
}
}
+#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) {
AEXT_DBG(dev->name, "ifidx %d is not ready\n", e->ifidx);
return -1;
}
- if (cur_if->ifmode == ISTA_MODE) {
+ if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) {
if (event_type == WLC_E_LINK) {
if (!(flags & WLC_EVENT_MSG_LINK)) {
WL_MSG(cur_if->ifname,
cur_if->prefix, &e->addr, bcmevent_get_name(event_type),
event_type, reason);
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_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);
+#endif /* PROPTX_MAXCOUNT */
} else if (event_type == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) {
WL_MSG(cur_if->ifname,
"connect failed event=%d, reason=%d, status=%d\n",
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);
+#endif /* PROPTX_MAXCOUNT */
} else if (event_type == WLC_E_DEAUTH || event_type == WLC_E_DEAUTH_IND ||
event_type == WLC_E_DISASSOC || event_type == WLC_E_DISASSOC_IND) {
WL_MSG(cur_if->ifname, "[%c] Link down with %pM, %s(%d), reason %d\n",
cur_if->prefix, &e->addr, bcmevent_get_name(event_type),
event_type, reason);
+#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 == IMESH_MODE) {
wl_set_isam_status(cur_if, AP_CREATED);
wake_up_interruptible(&apsta_params->netif_change_event);
} else {
+ wl_set_isam_status(cur_if, AP_CREATED);
WL_MSG(cur_if->ifname, "[%c] Link up w/o creating? (etype=%d)\n",
cur_if->prefix, event_type);
}
- } else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
+#ifdef PROPTX_MAXCOUNT
+ wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+#endif /* PROPTX_MAXCOUNT */
+ }
+ 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_clr_isam_status(cur_if, AP_CREATED);
WL_MSG(cur_if->ifname, "[%c] Link down, reason=%d\n",
cur_if->prefix, reason);
+#ifdef PROPTX_MAXCOUNT
+ wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+#endif /* PROPTX_MAXCOUNT */
}
else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
reason == DOT11_SC_SUCCESS) {
WL_MSG(cur_if->ifname, "[%c] connected device %pM\n",
cur_if->prefix, &e->addr);
wl_ext_isam_status(cur_if->dev, NULL, 0);
- } else if (event_type == WLC_E_DISASSOC_IND ||
+ }
+ else if (event_type == WLC_E_DISASSOC_IND ||
event_type == WLC_E_DEAUTH_IND ||
(event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
- WL_MSG(cur_if->ifname,
+ WL_MSG_RLMT(cur_if->ifname, &e->addr, ETHER_ADDR_LEN,
"[%c] disconnected device %pM, %s(%d), reason=%d\n",
cur_if->prefix, &e->addr, bcmevent_get_name(event_type),
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 */
}
return 0;
}
+#ifdef WL_CFG80211
u32
wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev,
u32 channel)
}
if (cur_if) {
- if (cur_if->ifmode == ISTA_MODE)
- wl_set_isam_status(cur_if, STA_CONNECTING);
wl_ext_isam_status(cur_if->dev, NULL, 0);
cur_if->channel = channel;
- channel = wl_ext_move_cur_channel(apsta_params,
- apsta_params->if_info[IF_PIF].dev, cur_if);
+ 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)
- wl_ext_move_other_channel(apsta_params,
- apsta_params->if_info[IF_PIF].dev, cur_if);
+ wl_ext_move_other_channel(apsta_params, cur_if);
+ if (cur_if->ifmode == ISTA_MODE)
+ wl_set_isam_status(cur_if, STA_CONNECTING);
}
return channel;
}
-#ifdef WL_CFG80211
+static int
+wl_ext_iftype_to_ifmode(struct net_device *net, int wl_iftype, ifmode_t *ifmode)
+{
+ switch (wl_iftype) {
+ case WL_IF_TYPE_STA:
+ *ifmode = ISTA_MODE;
+ break;
+ case WL_IF_TYPE_AP:
+ *ifmode = IAP_MODE;
+ break;
+ case WL_IF_TYPE_P2P_GO:
+ *ifmode = IGO_MODE;
+ break;
+ case WL_IF_TYPE_P2P_GC:
+ *ifmode = IGC_MODE;
+ break;
+ default:
+ AEXT_ERROR(net->name, "Unknown interface wl_iftype:0x%x\n", wl_iftype);
+ return BCME_ERROR;
+ }
+ return BCME_OK;
+}
+
void
wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype)
{
cur_if->ifmode = ISTA_MODE;
cur_if->prio = PRIO_STA;
cur_if->prefix = 'S';
- } else if (wl_iftype == WL_IF_TYPE_AP) {
+ } else if (wl_iftype == WL_IF_TYPE_AP && cur_if->ifmode != IMESH_MODE) {
cur_if->ifmode = IAP_MODE;
cur_if->prio = PRIO_AP;
cur_if->prefix = 'A';
+ } else if (wl_iftype == WL_IF_TYPE_P2P_GO) {
+ cur_if->ifmode = IGO_MODE;
+ cur_if->prio = PRIO_AP;
+ cur_if->prefix = 'P';
+ apsta_params->vsdb = TRUE;
+ } else if (wl_iftype == WL_IF_TYPE_P2P_GC) {
+ cur_if->ifmode = IGC_MODE;
+ cur_if->prio = PRIO_STA;
+ cur_if->prefix = 'P';
+ apsta_params->vsdb = TRUE;
+ wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 3);
}
}
}
-#endif
-#ifdef WL_STATIC_IF
void
wl_ext_iapsta_ifadding(struct net_device *net, int ifidx)
{
wl_set_isam_status(cur_if, IF_ADDING);
}
}
-#endif
+
+bool
+wl_ext_iapsta_iftype_enabled(struct net_device *net, int wl_iftype)
+{
+ struct dhd_pub *dhd = dhd_get_pub(net);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ struct wl_if_info *cur_if = NULL;
+ ifmode_t ifmode = 0;
+
+ wl_ext_iftype_to_ifmode(net, wl_iftype, &ifmode);
+ cur_if = wl_ext_if_enabled(apsta_params, ifmode);
+ if (cur_if)
+ return TRUE;
+
+ return FALSE;
+}
+
+bool
+wl_ext_iapsta_mesh_creating(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 *cur_if;
+ int i;
+
+ if (apsta_params) {
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[i];
+ if (cur_if->ifmode==IMESH_MODE && wl_get_isam_status(cur_if, IF_ADDING))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+#endif /* WL_CFG80211 */
+
+int
+wl_ext_iapsta_alive_preinit(struct net_device *dev)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+
+ if (apsta_params->init == TRUE) {
+ AEXT_ERROR(dev->name, "don't init twice\n");
+ return -1;
+ }
+
+ AEXT_TRACE(dev->name, "Enter\n");
+
+ apsta_params->init = TRUE;
+
+ return 0;
+}
+
+int
+wl_ext_iapsta_alive_postinit(struct net_device *dev)
+{
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+ s32 apsta = 0, ap = 0;
+ struct wl_if_info *cur_if;
+ int i;
+
+ wl_ext_iovar_getint(dev, "apsta", &apsta);
+ wl_ext_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap), 0);
+ if (apsta == 1 || ap == 0) {
+ apsta_params->apstamode = ISTAONLY_MODE;
+ apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
+ op_mode = DHD_FLAG_STA_MODE;
+ } else {
+ apsta_params->apstamode = IAPONLY_MODE;
+ apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
+ op_mode = DHD_FLAG_HOSTAP_MODE;
+ }
+ // 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++) {
+ cur_if = &apsta_params->if_info[i];
+ if (i == 1 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan1");
+ if (i == 2 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan2");
+ if (cur_if->ifmode == ISTA_MODE) {
+ cur_if->channel = 0;
+ cur_if->maxassoc = -1;
+ wl_set_isam_status(cur_if, IF_READY);
+ cur_if->prio = PRIO_STA;
+ 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;
+ cur_if->maxassoc = -1;
+ wl_set_isam_status(cur_if, IF_READY);
+ cur_if->prio = PRIO_AP;
+ cur_if->prefix = 'A';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
+#ifdef WLMESH
+ } else if (cur_if->ifmode == IMESH_MODE) {
+ cur_if->channel = 1;
+ cur_if->maxassoc = -1;
+ wl_set_isam_status(cur_if, IF_READY);
+ cur_if->prio = PRIO_MESH;
+ cur_if->prefix = 'M';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
+#endif /* WLMESH */
+ }
+ }
+
+ return op_mode;
+}
+
+static int
+wl_ext_iapsta_get_rsdb(struct net_device *net, struct dhd_pub *dhd)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ wl_config_t *rsdb_p;
+ int ret = 0, rsdb = 0;
+
+ if (dhd->conf->chip == BCM4359_CHIP_ID) {
+ ret = wldev_iovar_getbuf(net, "rsdb_mode", NULL, 0,
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ if (!ret) {
+ if (dhd->conf->fw_type == FW_TYPE_MESH) {
+ rsdb = 1;
+ } else {
+ rsdb_p = (wl_config_t *) iovar_buf;
+ rsdb = rsdb_p->config;
+ }
+ }
+ }
+
+ AEXT_INFO(net->name, "rsdb_mode=%d\n", rsdb);
+
+ return rsdb;
+}
static void
wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if)
AEXT_TRACE(cur_if->ifname, "ifidx=%d\n", cur_if->ifidx);
if (cur_if->ifidx == 0) {
- apsta_params->csa |= CSA_FW_BIT;
- if (dhd->conf->chip == BCM4359_CHIP_ID) {
- apsta_params->rsdb = TRUE;
- }
+ apsta_params->rsdb = wl_ext_iapsta_get_rsdb(net, dhd);
+ apsta_params->vsdb = FALSE;
+ apsta_params->csa = 0;
+ apsta_params->acs = 0;
+ apsta_params->radar = wl_ext_radar_detect(net);
if (dhd->conf->fw_type == FW_TYPE_MESH) {
apsta_params->csa |= (CSA_FW_BIT | CSA_DRV_BIT);
}
else
pm = PM_FAST;
wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
- wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 30);
+ wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 20);
}
#ifdef WLMESH
else if (cur_if->ifmode == IMESH_MODE) {
pm = 0;
wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
}
-#endif
+#endif /* WLMESH */
}
+#ifdef PROPTX_MAXCOUNT
+ wl_ext_update_wlfc_maxcount(dhd);
+#endif /* PROPTX_MAXCOUNT */
}
wl_set_isam_status(cur_if, IF_READY);
#ifndef WL_STATIC_IF
wake_up_interruptible(&apsta_params->netif_change_event);
-#endif
+#endif /* WL_STATIC_IF */
+ }
+
+ return 0;
+}
+
+int
+wl_ext_iapsta_update_net_device(struct net_device *net, int ifidx)
+{
+ 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;
+
+ AEXT_TRACE(net->name, "ifidx=%d\n", ifidx);
+ if (ifidx < MAX_IF_NUM) {
+ cur_if = &apsta_params->if_info[ifidx];
+ }
+ if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) {
+ primary_if = &apsta_params->if_info[IF_PIF];
+ if (strlen(cur_if->ifname)) {
+ memset(net->name, 0, sizeof(IFNAMSIZ));
+ strcpy(net->name, cur_if->ifname);
+ net->name[IFNAMSIZ-1] = '\0';
+ }
+#ifndef WL_STATIC_IF
+ 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;
+ if (ifidx >= 2) {
+ net->dev_addr[4] ^= 0x80;
+ net->dev_addr[4] += ifidx;
+ net->dev_addr[5] += (ifidx-1);
+ }
+ }
+#endif /* WL_STATIC_IF */
}
return 0;
if (ifidx == 0) {
memset(apsta_params, 0, sizeof(struct wl_apsta_params));
apsta_params->dhd = dhd;
- apsta_params->vsdb = FALSE;
cur_if->dev = net;
cur_if->ifidx = ifidx;
cur_if->bssidx = bssidx;
strcpy(cur_if->ifname, net->name);
init_waitqueue_head(&apsta_params->netif_change_event);
mutex_init(&apsta_params->usr_sync);
+ mutex_init(&cur_if->pm_sync);
+ INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler);
} else if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) {
primary_if = &apsta_params->if_info[IF_PIF];
cur_if->dev = net;
- cur_if->ifidx = ifidx;
- cur_if->bssidx = bssidx;
- wl_ext_event_register(net, dhd, WLC_E_LAST, wl_ext_iapsta_event,
- apsta_params, PRIO_EVENT_IAPSTA);
- if (strlen(cur_if->ifname)) {
- memset(net->name, 0, sizeof(IFNAMSIZ));
- strcpy(net->name, cur_if->ifname);
- net->name[IFNAMSIZ-1] = '\0';
- }
-#ifndef WL_STATIC_IF
- if (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;
- if (ifidx >= 2) {
- net->dev_addr[4] ^= 0x80;
- net->dev_addr[4] += ifidx;
- net->dev_addr[5] += (ifidx-1);
- }
+ cur_if->ifidx = ifidx;
+ cur_if->bssidx = bssidx;
+ 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);
}
-#endif
+#endif /* WLMESH && WL_ESCAN */
+ mutex_init(&cur_if->pm_sync);
+ INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler);
}
return 0;
}
if (ifidx == 0) {
+ wl_ext_add_remove_pm_enable_work(net, FALSE);
wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event);
+#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 */
memset(apsta_params, 0, sizeof(struct wl_apsta_params));
- } else if (cur_if && wl_get_isam_status(cur_if, IF_READY)) {
+ } else if (cur_if && (wl_get_isam_status(cur_if, IF_READY) ||
+ wl_get_isam_status(cur_if, IF_ADDING))) {
+ wl_ext_add_remove_pm_enable_work(net, FALSE);
wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event);
+#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 */
memset(cur_if, 0, sizeof(struct wl_if_info));
}
pub->iapsta_params = NULL;
}
}
-#endif
+#endif /* WL_EXT_IAPSTA */
#ifdef IDHCP
/*
exit:
return ret;
}
-#endif
+#endif /* IDHCP */
int
wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command,
AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
goto exit;
}
- packet = kmalloc(total_len, GFP_KERNEL);
+ packet = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
if (packet == NULL) {
AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
goto exit;
if (id < 0)
id = 0;
ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf,
- sizeof(buf), NULL);
+ total_len, NULL);
if (!ret) {
mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf;
bytes_written += snprintf(command+bytes_written, total_len,
memset(src_ip, 0, sizeof(src_ip));
memset(dst_ip, 0, sizeof(dst_ip));
memset(ka_payload, 0, sizeof(ka_payload));
- sscanf(data, "%d %s %s %s %d %d %d %u %u %d %u %u %u %u %32s",
+ sscanf(data, "%d %s %s %s %d %d %d %u %u %d %u %u %u %32s",
&sess_id, dst_mac, src_ip, dst_ip, &ipid, &srcport, &dstport, &seq,
- &ack, &tcpwin, &tsval, &tsecr, &len, &ka_payload_len, ka_payload);
+ &ack, &tcpwin, &tsval, &tsecr, &len, ka_payload);
+ ka_payload_len = strlen(ka_payload) / 2;
tcpka = kmalloc(sizeof(struct tcpka_conn) + ka_payload_len, GFP_KERNEL);
if (tcpka == NULL) {
AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
tcpka->tsval = tsval;
tcpka->tsecr = tsecr;
tcpka->len = len;
+ ka_payload_len = wl_pattern_atoh(ka_payload, (char *)tcpka->ka_payload);
+ if (ka_payload_len == -1) {
+ AEXT_ERROR(dev->name,"rejecting ka_payload=%s\n", ka_payload);
+ goto exit;
+ }
tcpka->ka_payload_len = ka_payload_len;
- strncpy(tcpka->ka_payload, ka_payload, ka_payload_len);
AEXT_INFO(dev->name,
"tcpka_conn_add %d %pM %pM %pM %d %d %d %u %u %d %u %u %u %u \"%s\"\n",
{
s8 iovar_buf[WLC_IOCTL_SMLEN];
tcpka_conn_sess_t tcpka_conn;
- int ret;
+ int ret = 0;
uint32 sess_id = 0, flag, interval = 0, retry_interval = 0, retry_count = 0;
if (data) {
s8 iovar_buf[WLC_IOCTL_SMLEN];
tcpka_conn_sess_info_t *info = NULL;
uint32 sess_id = 0;
- int ret = 0;
+ int ret = 0, bytes_written = 0;
if (data) {
sscanf(data, "%d", &sess_id);
sizeof(uint32), iovar_buf, sizeof(iovar_buf), NULL);
if (!ret) {
info = (tcpka_conn_sess_info_t *) iovar_buf;
- ret = snprintf(command, total_len, "id=%d, ipid=%d, seq=%u, ack=%u",
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "id :%d\n"
+ "ipid :%d\n"
+ "seq :%u\n"
+ "ack :%u",
sess_id, info->ipid, info->seq, info->ack);
AEXT_INFO(dev->name, "%s\n", command);
+ ret = bytes_written;
}
}
return ret;
}
-#endif
+#endif /* WL_EXT_TCPKA */
static int
wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command,
return err;
}
-#endif
+#endif /* PKT_FILTER_SUPPORT */
#ifdef SENDPROB
-static int
-wl_ext_add_del_ie(struct net_device *dev, uint pktflag, char *ie_data, const char* add_del_cmd)
-{
- vndr_ie_setbuf_t *vndr_ie = NULL;
- char iovar_buf[WLC_IOCTL_SMLEN]="\0";
- int ie_data_len = 0, tot_len = 0, iecount;
- int err = -1;
-
- if (!strlen(ie_data)) {
- AEXT_ERROR(dev->name, "wrong ie %s\n", ie_data);
- goto exit;
- }
-
- tot_len = (int)(sizeof(vndr_ie_setbuf_t) + ((strlen(ie_data)-2)/2));
- vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, GFP_KERNEL);
- if (!vndr_ie) {
- AEXT_ERROR(dev->name, "IE memory alloc failed\n");
- err = -ENOMEM;
- goto exit;
- }
-
- /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
- strncpy(vndr_ie->cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
- vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
-
- /* Set the IE count - the buffer contains only 1 IE */
- iecount = htod32(1);
- memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
-
- /* Set packet flag to indicate that BEACON's will contain this IE */
- pktflag = htod32(pktflag);
- memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
- sizeof(u32));
-
- /* Set the IE ID */
- vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar)DOT11_MNG_VS_ID;
-
- /* Set the IE LEN */
- vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (strlen(ie_data)-2)/2;
-
- /* Set the IE OUI and DATA */
- ie_data_len = wl_pattern_atoh(ie_data,
- (char *)vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui);
- if (ie_data_len <= 0) {
- AEXT_ERROR(dev->name, "wrong ie_data_len %d\n", strlen(ie_data)-2);
- goto exit;
- }
-
- err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, tot_len, iovar_buf,
- sizeof(iovar_buf), NULL);
-
-exit:
- if (vndr_ie) {
- kfree(vndr_ie);
- }
- return err;
-}
-
static int
wl_ext_send_probreq(struct net_device *dev, char *data, char *command,
int total_len)
exit:
return err;
}
-#endif
+#endif /* SENDPROB */
static int
wl_ext_gtk_key_info(struct net_device *dev, char *data, char *command, int total_len)
return ret;
}
-#endif
+#endif /* WL_EXT_WOWL */
+
+#ifdef WL_GPIO_NOTIFY
+typedef struct notify_payload {
+ int index;
+ int len;
+ char payload[128];
+} notify_payload_t;
+
+static int
+wl_ext_gpio_notify(struct net_device *dev, char *data, char *command,
+ int total_len)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ notify_payload_t notify, *pnotify = NULL;
+ int i, ret = 0, bytes_written = 0;
+ char frame_str[WLC_IOCTL_SMLEN+3];
+
+ if (data) {
+ memset(¬ify, 0, sizeof(notify));
+ memset(frame_str, 0, sizeof(frame_str));
+ sscanf(data, "%d %s", ¬ify.index, frame_str);
+
+ if (notify.index < 0)
+ notify.index = 0;
+
+ if (strlen(frame_str)) {
+ notify.len = wl_pattern_atoh(frame_str, notify.payload);
+ if (notify.len == -1) {
+ AEXT_ERROR(dev->name, "rejecting pattern=%s\n", frame_str);
+ goto exit;
+ }
+ AEXT_INFO(dev->name, "index=%d, len=%d\n", notify.index, notify.len);
+ if (android_msg_level & ANDROID_INFO_LEVEL)
+ prhex("payload", (uchar *)notify.payload, notify.len);
+ ret = wl_ext_iovar_setbuf(dev, "bcol_gpio_noti", (char *)¬ify,
+ sizeof(notify), iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ } else {
+ AEXT_INFO(dev->name, "index=%d\n", notify.index);
+ ret = wl_ext_iovar_getbuf(dev, "bcol_gpio_noti", ¬ify.index,
+ sizeof(notify.index), iovar_buf, sizeof(iovar_buf), NULL);
+ if (!ret) {
+ pnotify = (notify_payload_t *)iovar_buf;
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "Id :%d\n"
+ "Packet :0x",
+ pnotify->index);
+ for (i=0; i<pnotify->len; i++) {
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "%02x", pnotify->payload[i]);
+ }
+ AEXT_TRACE(dev->name, "command result is\n%s\n", command);
+ ret = bytes_written;
+ }
+ }
+ }
+
+exit:
+ return ret;
+}
+#endif /* WL_GPIO_NOTIFY */
+
+#ifdef CSI_SUPPORT
+typedef struct csi_config {
+ /* Peer device mac address. */
+ struct ether_addr addr;
+ /* BW to be used in the measurements. This needs to be supported both by the */
+ /* device itself and the peer. */
+ uint32 bw;
+ /* Time interval between measurements (units: 1 ms). */
+ uint32 period;
+ /* CSI method */
+ uint32 method;
+} csi_config_t;
+
+typedef struct csi_list {
+ uint32 cnt;
+ 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)
+{
+ csi_config_t csi, *csip;
+ csi_list_t *csi_list;
+ int ret = -1, period=-1, i;
+ char mac[32], *buf = NULL;
+ struct ether_addr ea;
+ int bytes_written = 0;
+
+ buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
+ if (buf == NULL) {
+ AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
+ goto exit;
+ }
+ memset(buf, 0, WLC_IOCTL_SMLEN);
+
+ if (data) {
+ sscanf(data, "%s %d", mac, &period);
+ ret = wl_ether_atoe(mac, &ea);
+ if (!ret) {
+ AEXT_ERROR(dev->name, "rejecting mac=%s, ret=%d\n", mac, ret);
+ goto exit;
+ }
+ AEXT_TRACE(dev->name, "mac=%pM, period=%d", &ea, period);
+ if (period > 0) {
+ memset(&csi, 0, sizeof(csi_config_t));
+ bcopy(&ea, &csi.addr, ETHER_ADDR_LEN);
+ csi.period = period;
+ ret = wl_ext_iovar_setbuf(dev, "csi", (char *)&csi, sizeof(csi),
+ buf, WLC_IOCTL_SMLEN, NULL);
+ } else if (period == 0) {
+ memset(&csi, 0, sizeof(csi_config_t));
+ bcopy(&ea, &csi.addr, ETHER_ADDR_LEN);
+ ret = wl_ext_iovar_setbuf(dev, "csi_del", (char *)&csi, sizeof(csi),
+ buf, WLC_IOCTL_SMLEN, NULL);
+ } else {
+ ret = wl_ext_iovar_getbuf(dev, "csi", &ea, ETHER_ADDR_LEN, buf,
+ WLC_IOCTL_SMLEN, NULL);
+ if (!ret) {
+ csip = (csi_config_t *) buf;
+ /* Dump all lists */
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "Mac :%pM\n"
+ "Period :%d\n"
+ "BW :%d\n"
+ "Method :%d\n",
+ &csip->addr, csip->period, csip->bw, csip->method);
+ AEXT_TRACE(dev->name, "command result is %s\n", command);
+ ret = bytes_written;
+ }
+ }
+ }
+ else {
+ ret = wl_ext_iovar_getbuf(dev, "csi_list", NULL, 0, buf, WLC_IOCTL_SMLEN, NULL);
+ if (!ret) {
+ csi_list = (csi_list_t *)buf;
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "Total number :%d\n", csi_list->cnt);
+ for (i=0; i<csi_list->cnt; i++) {
+ csip = &csi_list->configs[i];
+ bytes_written += snprintf(command+bytes_written, total_len,
+ "Idx :%d\n"
+ "Mac :%pM\n"
+ "Period :%d\n"
+ "BW :%d\n"
+ "Method :%d\n\n",
+ i+1, &csip->addr, csip->period, csip->bw, csip->method);
+ }
+ AEXT_TRACE(dev->name, "command result is %s\n", command);
+ ret = bytes_written;
+ }
+ }
+
+exit:
+ if (buf)
+ kfree(buf);
+ return ret;
+}
+#endif /* CSI_SUPPORT */
typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command,
int total_len);
{WLC_GET_VAR, WLC_SET_VAR, "pkt_filter_add", wl_ext_pkt_filter_add},
{WLC_GET_VAR, WLC_SET_VAR, "pkt_filter_delete", wl_ext_pkt_filter_delete},
{WLC_GET_VAR, WLC_SET_VAR, "pkt_filter_enable", wl_ext_pkt_filter_enable},
-#endif
+#endif /* PKT_FILTER_SUPPORT */
#if defined(WL_EXT_IAPSTA) && defined(WLMESH)
{WLC_GET_VAR, WLC_SET_VAR, "mesh_peer_status", wl_ext_mesh_peer_status},
-#endif
+#endif /* WL_EXT_IAPSTA && WLMESH */
#ifdef SENDPROB
{WLC_GET_VAR, WLC_SET_VAR, "send_probreq", wl_ext_send_probreq},
{WLC_GET_VAR, WLC_SET_VAR, "send_probresp", wl_ext_send_probresp},
{WLC_GET_VAR, WLC_SET_VAR, "recv_probreq", wl_ext_recv_probreq},
{WLC_GET_VAR, WLC_SET_VAR, "recv_probresp", wl_ext_recv_probresp},
-#endif
+#endif /* SENDPROB */
#ifdef WL_EXT_TCPKA
{WLC_GET_VAR, WLC_SET_VAR, "tcpka_conn_add", wl_ext_tcpka_conn_add},
{WLC_GET_VAR, WLC_SET_VAR, "tcpka_conn_enable", wl_ext_tcpka_conn_enable},
{WLC_GET_VAR, WLC_SET_VAR, "tcpka_conn_sess_info", wl_ext_tcpka_conn_info},
-#endif
+#endif /* WL_EXT_TCPKA */
#ifdef WL_EXT_WOWL
{WLC_GET_VAR, WLC_SET_VAR, "wowl_pattern", wl_ext_wowl_pattern},
{WLC_GET_VAR, WLC_SET_VAR, "wowl_wakeind", wl_ext_wowl_wakeind},
-#endif
+#endif /* WL_EXT_WOWL */
#ifdef IDHCP
{WLC_GET_VAR, WLC_SET_VAR, "dhcpc_dump", wl_ext_dhcpc_dump},
{WLC_GET_VAR, WLC_SET_VAR, "dhcpc_param", wl_ext_dhcpc_param},
-#endif
+#endif /* IDHCP */
+#ifdef WL_GPIO_NOTIFY
+ {WLC_GET_VAR, WLC_SET_VAR, "bcol_gpio_noti", wl_ext_gpio_notify},
+#endif /* WL_GPIO_NOTIFY */
+#ifdef CSI_SUPPORT
+ {WLC_GET_VAR, WLC_SET_VAR, "csi", wl_ext_csi},
+#endif /* CSI_SUPPORT */
};
/*
else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) {
*bytes_written = wl_ext_isam_status(net, command, total_len);
}
-#endif
+ else if (strnicmp(command, CMD_ISAM_PARAM, strlen(CMD_ISAM_PARAM)) == 0) {
+ *bytes_written = wl_ext_isam_param(net, command, total_len);
+ }
+#if defined(WLMESH) && defined(WL_ESCAN)
+ else if (strnicmp(command, CMD_ISAM_PEER_PATH, strlen(CMD_ISAM_PEER_PATH)) == 0) {
+ *bytes_written = wl_ext_isam_peer_path(net, command, total_len);
+ }
+#endif /* WLMESH && WL_ESCAN */
+#endif /* WL_EXT_IAPSTA */
#ifdef WL_CFG80211
else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
*bytes_written = wl_cfg80211_autochannel(net, command, total_len);
}
-#endif
+#endif /* WL_CFG80211 */
#if defined(WL_WIRELESS_EXT) && defined(WL_ESCAN)
else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
*bytes_written = wl_iw_autochannel(net, command, total_len);
}
-#endif
+#endif /* WL_WIRELESS_EXT && WL_ESCAN */
else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) {
*bytes_written = wl_ext_wl_iovar(net, command, total_len);
}
wl_bss_cache_ctrl_t *bss_cache_ctrl,
#else
struct wl_scan_results *bss_list,
-#endif
+#endif /* BSSCACHE */
int ioctl_ver, int *best_2g_ch, int *best_5g_ch
)
{
s32 i, j;
#if defined(BSSCACHE)
wl_bss_cache_t *node;
-#endif
+#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)];
wl_uint32_list_t *list;
int ret;
chanspec_t chanspec;
+ struct dhd_pub *dhd = dhd_get_pub(net);
memset(b_band, -1, sizeof(b_band));
memset(a_band1, -1, sizeof(a_band1));
} else {
for (i = 0; i < dtoh32(list->count); i++) {
ch = dtoh32(list->element[i]);
+ if (!dhd_conf_match_channel(dhd, ch))
+ continue;
if (ch < CH_MAX_2G_CHANNEL)
b_band[ch-1] = 0;
else if (ch <= 48)
for (i=0; node && i<256; i++)
#else
for (i=0; i < bss_list->count; i++)
-#endif
+#endif /* BSSCACHE */
{
#if defined(BSSCACHE)
bi = node->results.bss_info;
#else
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : bss_list->bss_info;
-#endif
+#endif /* BSSCACHE */
chanspec = wl_ext_chspec_driver_to_host(ioctl_ver, bi->chanspec);
cen_ch = CHSPEC_CHANNEL(bi->chanspec);
distance = 0;
distance += distance_2g;
for (j=0; j<ARRAYSIZE(b_band); j++) {
if (b_band[j] >= 0 && abs(cen_ch-(1+j)) <= distance)
- b_band[j] += 1;
+ b_band[j] += 1;
}
} else {
distance += distance_5g;
}
#if defined(BSSCACHE)
node = node->next;
-#endif
+#endif /* BSSCACHE */
}
*best_2g_ch = 0;
exit:
return 0;
}
+#endif /* WL_CFG80211 || WL_ESCAN */
+
+#ifdef WL_CFG80211
+#define APCS_MAX_RETRY 10
+static int
+wl_ext_fw_apcs(struct net_device *dev, uint32 band)
+{
+ int channel = 0, chosen = 0, retry = 0, ret = 0, spect = 0;
+ u8 *reqbuf = NULL;
+ uint32 buf_size;
+
+ ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
+ if (ret) {
+ AEXT_ERROR(dev->name, "ACS: error getting the spect, ret=%d\n", ret);
+ goto done;
+ }
+
+ if (spect > 0) {
+ ret = wl_cfg80211_set_spect(dev, 0);
+ if (ret < 0) {
+ AEXT_ERROR(dev->name, "ACS: error while setting spect, ret=%d\n", ret);
+ goto done;
+ }
+ }
+
+ reqbuf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
+ if (reqbuf == NULL) {
+ AEXT_ERROR(dev->name, "failed to allocate chanspec buffer\n");
+ goto done;
+ }
+ 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");
+ if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 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");
+ if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
+ AEXT_ERROR(dev->name, "ACS 2g chanspec retreival failed! \n");
+ goto done;
+ }
+ } else {
+ AEXT_ERROR(dev->name, "ACS: No band chosen\n");
+ goto done;
+ }
+
+ buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
+ ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
+ buf_size);
+ if (ret < 0) {
+ AEXT_ERROR(dev->name, "can't start auto channel scan, err = %d\n", ret);
+ channel = 0;
+ goto done;
+ }
+
+ /* Wait for auto channel selection, max 3000 ms */
+ if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G)) {
+ OSL_SLEEP(500);
+ } else {
+ /*
+ * Full channel scan at the minimum takes 1.2secs
+ * even with parallel scan. max wait time: 3500ms
+ */
+ OSL_SLEEP(1000);
+ }
+
+ retry = APCS_MAX_RETRY;
+ while (retry--) {
+ ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &chosen,
+ sizeof(chosen));
+ if (ret < 0) {
+ chosen = 0;
+ } 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;
+ }
+ }
+ AEXT_INFO(dev->name, "%d tried, ret = %d, chosen = 0x%x\n",
+ (APCS_MAX_RETRY - retry), ret, chosen);
+ OSL_SLEEP(250);
+ }
+
+done:
+ if (spect > 0) {
+ if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) {
+ AEXT_ERROR(dev->name, "ACS: error while setting spect\n");
+ }
+ }
+
+ if (reqbuf) {
+ kfree(reqbuf);
+ }
+
+ return channel;
+}
+#endif /* WL_CFG80211 */
+
+#ifdef WL_ESCAN
+int
+wl_ext_drv_apcs(struct net_device *dev, uint32 band)
+{
+ int ret = 0, channel = 0;
+ struct dhd_pub *dhd = dhd_get_pub(dev);
+ struct wl_escan_info *escan = NULL;
+ int retry = 0, retry_max, retry_interval = 250, up = 1;
+#ifdef WL_CFG80211
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+
+ escan = dhd->escan;
+ if (dhd) {
+ retry_max = WL_ESCAN_TIMER_INTERVAL_MS/retry_interval;
+ ret = wldev_ioctl_get(dev, WLC_GET_UP, &up, sizeof(s32));
+ if (ret < 0 || up == 0) {
+ ret = wldev_ioctl_set(dev, WLC_UP, &up, sizeof(s32));
+ }
+ retry = retry_max;
+ while (retry--) {
+ if (escan->escan_state == ESCAN_STATE_SCANING
+#ifdef WL_CFG80211
+ || wl_get_drv_status_all(cfg, SCANNING)
+#endif
+ )
+ {
+ AEXT_INFO(dev->name, "Scanning %d tried, ret = %d\n",
+ (retry_max - retry), ret);
+ } else {
+ escan->autochannel = 1;
+ ret = wl_escan_set_scan(dev, dhd, NULL, 0, TRUE);
+ if (!ret)
+ break;
+ }
+ OSL_SLEEP(retry_interval);
+ }
+ if ((retry == 0) || (ret < 0))
+ goto done;
+ retry = retry_max;
+ while (retry--) {
+ if (escan->escan_state == ESCAN_STATE_IDLE) {
+ if (band == WLC_BAND_5G)
+ channel = escan->best_5g_ch;
+ else
+ channel = escan->best_2g_ch;
+ WL_MSG(dev->name, "selected channel = %d\n", channel);
+ goto done;
+ }
+ AEXT_INFO(dev->name, "escan_state=%d, %d tried, ret = %d\n",
+ escan->escan_state, (retry_max - retry), ret);
+ OSL_SLEEP(retry_interval);
+ }
+ if ((retry == 0) || (ret < 0))
+ goto done;
+ }
+
+done:
+ if (escan)
+ escan->autochannel = 0;
+
+ return channel;
+}
+#endif /* WL_ESCAN */
+
+int
+wl_ext_autochannel(struct net_device *dev, uint acs, uint32 band)
+{
+ int channel = 0;
+ uint16 chan_2g, chan_5g;
+
+ AEXT_INFO(dev->name, "acs=0x%x, band=%d \n", acs, band);
+
+#ifdef WL_CFG80211
+ if (acs & ACS_FW_BIT) {
+ int ret = 0;
+ ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &channel, sizeof(channel));
+ channel = 0;
+ if (ret != BCME_UNSUPPORTED)
+ channel = wl_ext_fw_apcs(dev, band);
+ if (channel)
+ return channel;
+ }
#endif
+#ifdef WL_ESCAN
+ if (acs & ACS_DRV_BIT)
+ channel = wl_ext_drv_apcs(dev, band);
+#endif /* WL_ESCAN */
+
+ if (channel == 0) {
+ wl_ext_get_default_chan(dev, &chan_2g, &chan_5g, TRUE);
+ if (band == WLC_BAND_5G) {
+ channel = chan_5g;
+ } else {
+ channel = chan_2g;
+ }
+ AEXT_ERROR(dev->name, "ACS failed. Fall back to default channel (%d) \n", channel);
+ }
+
+ return channel;
+}
+
#if defined(RSSIAVG)
void
wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
}
return (int16)rssi;
}
-#endif
+#endif /* RSSIAVG */
#if defined(RSSIOFFSET)
int
{
#if defined(RSSIOFFSET_NEW)
int j;
-#endif
+#endif /* RSSIOFFSET_NEW */
if (!g_wifi_on)
return rssi;
rssi += j;
#else
rssi += RSSI_OFFSET;
-#endif
+#endif /* RSSIOFFSET_NEW */
return MIN(rssi, RSSI_MAXVAL);
}
-#endif
+#endif /* RSSIOFFSET */
#if defined(BSSCACHE)
void
void dump_bss_cache(
#if defined(RSSIAVG)
wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
-#endif
+#endif /* RSSIAVG */
wl_bss_cache_t *node)
{
int k = 0;
rssi = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
#else
rssi = dtoh16(node->results.bss_info->RSSI);
-#endif
+#endif /* RSSIAVG */
AEXT_TRACE("wlan", "dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID);
k++;
wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
#if defined(RSSIAVG)
wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
-#endif
+#endif /* RSSIAVG */
wl_scan_results_t *ss_list)
{
wl_bss_cache_t *node, *prev, *leaf, **bss_head;
int i, k=0;
#if defined(SORT_BSS_BY_RSSI)
int16 rssi, rssi_node;
-#endif
+#endif /* SORT_BSS_BY_RSSI */
struct osl_timespec now, timeout;
if (!ss_list->count)
rssi = wl_get_avg_rssi(rssi_cache_ctrl, &leaf->results.bss_info->BSSID);
#else
rssi = dtoh16(leaf->results.bss_info->RSSI);
-#endif
+#endif /* RSSIAVG */
for (;node;) {
#if defined(RSSIAVG)
rssi_node = wl_get_avg_rssi(rssi_cache_ctrl,
&node->results.bss_info->BSSID);
#else
rssi_node = dtoh16(node->results.bss_info->RSSI);
-#endif
+#endif /* RSSIAVG */
if (rssi > rssi_node) {
leaf->next = node;
if (node == *bss_head)
#else
leaf->next = *bss_head;
*bss_head = leaf;
-#endif
+#endif /* SORT_BSS_BY_RSSI */
}
}
dump_bss_cache(
#if defined(RSSIAVG)
rssi_cache_ctrl,
-#endif
+#endif /* RSSIAVG */
*bss_head);
}
AEXT_TRACE("wlan", "Enter\n");
wl_free_bss_cache(bss_cache_ctrl);
}
-#endif
+#endif /* BSSCACHE */
struct cfg80211_pmksa *pmksa);
static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
struct net_device *dev);
+#ifdef WL_CLIENT_SAE
+static bool wl_is_pmkid_available(struct net_device *dev, const u8 *bssid);
+#endif /* WL_CLIENT_SAE */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
#if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
const wl_event_msg_t *e, void *data);
#endif /* WL_MBO */
+#ifdef WL_CLIENT_SAE
+static s32 wl_notify_connect_status_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_start_auth(struct bcm_cfg80211 *cfg,
+ bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
+static s32 wl_cfg80211_external_auth(struct wiphy *wiphy,
+ struct net_device *dev, struct cfg80211_external_auth_params *ext_auth);
+#endif /* WL_CLIENT_SAE */
+
/*
* register/deregister parent device
*/
static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, dhd_pub_t *data);
static void wl_free_wdev(struct bcm_cfg80211 *cfg);
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
+static int
+#else
+static void
+#endif /* kernel version < 3.10.11 */
+wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi, bool update_ssid);
static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool update_ssid);
/* There isn't a lot of sense in it, but you can transmit anything you like */
static const struct ieee80211_txrx_stypes
wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+#ifdef WLMESH_CFG80211
+ [NL80211_IFTYPE_MESH_POINT] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4)
+ },
+#endif /* WLMESH_CFG80211 */
[NL80211_IFTYPE_ADHOC] = {
.tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4)
.tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+#ifdef WL_CLIENT_SAE
+ | BIT(IEEE80211_STYPE_AUTH >> 4)
+#endif /* WL_CLIENT_SAE */
},
[NL80211_IFTYPE_AP] = {
.tx = 0xffff,
return ret;
}
-bool
-wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg,
- struct net_device *ndev)
-{
- u32 chipnum;
- wlc_rev_info_t revinfo;
- int ret;
-
- /* Get the device rev info */
- memset(&revinfo, 0, sizeof(revinfo));
- ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
- if (ret < 0) {
- WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
- ASSERT(0);
- return false;
- }
-
- WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
- dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
- chipnum = revinfo.chipnum;
- if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) ||
- (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID) ||
- (chipnum == BCM43362_CHIP_ID) || (chipnum == BCM43012_CHIP_ID) ||
- (chipnum == BCM4356_CHIP_ID)) {
- /* WAR required */
- return true;
- }
-
- return false;
-}
-
-void
-wl_bss_iovar_war(struct bcm_cfg80211 *cfg,
- struct net_device *ndev, s32 *val)
-{
- u32 chipnum;
- wlc_rev_info_t revinfo;
- int ret;
- bool need_war = false;
-
- /* Get the device rev info */
- memset(&revinfo, 0, sizeof(revinfo));
- ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
- if (ret < 0) {
- WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
- } else {
- WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
- dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
- chipnum = revinfo.chipnum;
- if ((chipnum == BCM4359_CHIP_ID) || (chipnum == BCM43596_CHIP_ID)) {
- /* WAR required */
- need_war = true;
- }
- }
-
- if (wl_customer6_legacy_chip_check(cfg, ndev) || need_war) {
- /* Few firmware branches have issues in bss iovar handling and
- * that can't be changed since they are in production.
- */
- if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) {
- *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
- } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) {
- *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
- } else {
- /* Ignore for other bss enums */
- return;
- }
- WL_DBG(("wl bss %d\n", *val));
- }
-}
-
s32
wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
struct net_device *ndev, s32 bsscfg_idx,
}
if (!del) {
- wl_bss_iovar_war(cfg, ndev, &val);
+ wl_ext_bss_iovar_war(ndev, &val);
}
bss_setbuf.cfg = htod32(bsscfg_idx);
memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
}
- WL_INFORM_MEM(("wl bss %d bssidx:%d iface:%s \n", val, bsscfg_idx, ndev->name));
+ WL_MSG(ndev->name, "wl bss %d bssidx:%d\n", val, bsscfg_idx);
ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (ret != 0)
case WL_IF_TYPE_IBSS:
mode = WL_MODE_IBSS;
break;
+#ifdef WLMESH_CFG80211
+ case WL_IF_TYPE_MESH:
+ mode = WL_MODE_MESH;
+ break;
+#endif /* WLMESH_CFG80211 */
default:
WL_ERR(("Unsupported type:%d\n", iftype));
break;
*mode = WL_MODE_NAN;
break;
#endif // endif
+#ifdef WLMESH_CFG80211
+ case NL80211_IFTYPE_MESH_POINT:
+ *role = WLC_E_IF_ROLE_AP;
+ *mode = WL_MODE_MESH;
+ break;
+#endif /* WLMESH_CFG80211 */
default:
WL_ERR(("Unknown interface type:0x%x\n", type));
return BCME_ERROR;
*mode = WL_MODE_AP;
return NL80211_IFTYPE_AP;
#endif
+#ifdef WLMESH_CFG80211
+ case WLC_E_IF_ROLE_MESH:
+ *wl_iftype = WL_IF_TYPE_MESH;
+ *mode = WL_MODE_MESH;
+ return NL80211_IFTYPE_MESH_POINT;
+#endif /* WLMESH_CFG80211 */
default:
WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role));
return NULL;
}
+#if defined(WLMESH_CFG80211) && defined(WL_EXT_IAPSTA)
+ if (wl_ext_iapsta_mesh_creating(ndev)) {
+ event->role = WLC_E_IF_ROLE_MESH;
+ WL_MSG(ndev->name, "change role to WLC_E_IF_ROLE_MESH\n");
+ }
+#endif /* WLMESH_CFG80211 && WL_EXT_IAPSTA */
+
iface_type = wl_role_to_cfg80211_type(event->role, &wl_iftype, &mode);
if (iface_type < 0) {
/* Unknown iface type */
return NULL;
}
-#ifdef WL_EXT_IAPSTA
- if (wl_ext_check_mesh_creating(ndev)) {
- WL_MSG(ndev->name, "change iface_type to NL80211_IFTYPE_MESH_POINT\n");
- iface_type = NL80211_IFTYPE_MESH_POINT;
- }
-#endif
-
WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG "\n",
addr, name, event->role, iface_type, MAC2STRDBG(event->mac)));
if (!name) {
return NULL;
}
wdev = new_ndev->ieee80211_ptr;
-#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_update_iftype(new_ndev, event->ifidx, wl_iftype);
-#endif
} else
#endif /* WL_STATIC_IF */
{
SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
+#ifdef WL_EXT_IAPSTA
+ 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) {
WL_ERR(("IFACE register failed \n"));
if (mode == WL_MODE_AP) {
wl_set_drv_status(cfg, AP_CREATING, new_ndev);
}
+#ifdef WL_EXT_IAPSTA
+ wl_ext_iapsta_update_iftype(new_ndev, event->ifidx, wl_iftype);
+#endif
WL_INFORM_MEM(("Network Interface (%s) registered with host."
" cfg_iftype:%d wl_role:%d " MACDBG "\n",
val = WL_AUTH_FILS_PUBLIC;
break;
#endif /* WL_FILS */
+#ifdef WL_CLIENT_SAE
+ case NL80211_AUTHTYPE_SAE:
+ if (!wl_is_pmkid_available(dev, sme->bssid)) {
+ val = WL_AUTH_SAE_KEY;
+ } else {
+ /* Fw will choose right auth type
+ * dynamically based on PMKID availability
+ */
+ val = WL_AUTH_OPEN_SHARED;
+ }
+ WL_DBG(("sae auth type %d\n", val));
+ break;
+#endif /* WL_CLIENT_SAE */
default:
val = 2;
WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
return err;
}
+#ifdef WL_CLIENT_SAE
+static bool
+wl_is_pmkid_available(struct net_device *dev, const u8 *bssid)
+{
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+ int i;
+ int npmkids = (cfg->pmk_list->pmkids.length - sizeof(uint16)*2) / sizeof(pmkid_v2_t);
+
+ /* check the bssid is null or not */
+ if (!bssid) return FALSE;
+
+ for (i = 0; i < npmkids; i++) {
+ if (!memcmp(bssid, &cfg->pmk_list->pmkids.pmkid[i].bssid, ETHER_ADDR_LEN)) {
+ WL_DBG(("FOUND PMKID\n"));
+ return TRUE;
+ }
+ }
+ WL_ERR(("PMKID NOT FOUND\n"));
+ return FALSE;
+}
+#endif /* WL_CLIENT_SAE */
+
static u32
wl_rsn_cipher_wsec_algo_lookup(uint32 cipher)
{
return err;
}
#ifdef WL_GCMP
- if (wl_set_wsec_info_algos(dev, algos, mask)) {
- WL_ERR(("set wsec_info error (%d)\n", err));
- }
+ wl_set_wsec_info_algos(dev, algos, mask);
#endif /* WL_GCMP */
sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
tlv_data_len = sizeof(tlv_data);
err = memcpy_s(tlv_data, sizeof(tlv_data), &algos, sizeof(algos));
if (err) {
+ WL_ERR(("memcpy_s algos error (%d)\n", err));
goto exit;
}
err = memcpy_s(tlv_data + sizeof(algos), sizeof(mask), &mask, sizeof(mask));
if (err) {
+ WL_ERR(("memcpy_s mask error (%d)\n", err));
goto exit;
}
bcm_xtlv_pack_xtlv(wsec_info_tlv, WL_WSEC_INFO_BSS_ALGOS, tlv_data_len, tlv_data, 0);
#ifdef WL_OWE
case WLAN_AKM_SUITE_OWE:
#endif /* WL_OWE */
-#ifdef WL_SAE
- case WLAN_AKM_SUITE_SAE:
-#endif /* WL_SAE */
case WLAN_AKM_SUITE_FT_8021X_SHA384:
val = wl_rsn_akm_wpa_auth_lookup(sme->crypto.akm_suites[0]);
break;
case WLAN_AKM_SUITE_FT_FILS_SHA384:
val = WPA2_AUTH_FILS_SHA384 | WPA2_AUTH_FT;
break;
+#if defined(WL_SAE) || defined(WL_CLIENT_SAE)
+ case WLAN_AKM_SUITE_SAE:
+ val = WPA3_AUTH_SAE_PSK;
+ break;
+#endif /* WL_SAE || WL_CLIENT_SAE */
default:
WL_ERR(("invalid akm suite (0x%x)\n",
sme->crypto.akm_suites[0]));
s32 bssidx = 0;
dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
- WL_MSG(dev->name, "Reason %d\n", reason_code);
RETURN_EIO_IF_NOT_UP(cfg);
act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
+ WL_MSG(dev->name, "Reason %d, act %d\n", reason_code, act);
BCM_REFERENCE(dhdp);
DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_START),
if (pmksa->pmk_len) {
if (memcpy_s(&cfg->pmk_list->pmkids.pmkid[i].pmk, PMK_LEN_MAX, pmksa->pmk,
pmksa->pmk_len)) {
- WL_ERR(("invalid pmk len = %lu", pmksa->pmk_len));
+ WL_ERR(("invalid pmk len = %zu", pmksa->pmk_len));
} else {
cfg->pmk_list->pmkids.pmkid[i].pmk_len = pmksa->pmk_len;
}
wl_cfg80211_cancel_scan(cfg);
#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
}
+#ifdef WL_CLIENT_SAE
+ else if (ieee80211_is_auth(mgmt->frame_control)) {
+ int err = 0;
+ wl_assoc_mgr_cmd_t *cmd;
+ char *ambuf = NULL;
+ int param_len;
+ ack = true;
+ if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
+ bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
+ }
+ param_len = sizeof(wl_assoc_mgr_cmd_t) + len;
+ ambuf = MALLOCZ(cfg->osh, param_len);
+ if (ambuf == NULL) {
+ WL_ERR(("unable to allocate frame\n"));
+ return -ENOMEM;
+ }
+ cmd = (wl_assoc_mgr_cmd_t*)ambuf;
+ cmd->version = WL_ASSOC_MGR_CURRENT_VERSION;
+ cmd->length = len;
+ cmd->cmd = WL_ASSOC_MGR_CMD_SEND_AUTH;
+ memcpy(&cmd->params, buf, len);
+ err = wldev_iovar_setbuf(dev, "assoc_mgr_cmd", ambuf, param_len,
+ cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("Failed to send auth(%d)\n", err));
+ ack = false;
+ }
+ MFREE(cfg->osh, ambuf, param_len);
+ cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
+ goto exit;
+ }
+#endif /* WL_CLIENT_SAE */
} else {
WL_ERR(("Driver only allows MGMT packet type\n"));
goto exit;
dev = ndev_to_wlc_ndev(dev, cfg);
_chan = ieee80211_frequency_to_channel(chan->center_freq);
#ifdef WL_EXT_IAPSTA
- _chan = wl_ext_iapsta_update_channel(dhd, dev, _chan);
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
+ wl_ext_iapsta_update_iftype(dev, dhd_net2idx(dhd->info, dev), WL_IF_TYPE_AP);
+ _chan = wl_ext_iapsta_update_channel(dhd, dev, _chan);
+ }
#endif
WL_MSG(dev->name, "netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
dev->ifindex, channel_type, _chan);
}
if (!ap) {
-#ifdef WLEASYMESH
- WL_ERR(("ap should not be 0\n"));
-#endif
/* AP mode switch not supported. Try setting up AP explicitly */
err = wldev_iovar_getint(dev, "apsta", (s32 *)&apsta);
if (unlikely(err)) {
return err;
}
if (apsta == 0) {
-#ifdef WLEASYMESH
- WL_ERR(("apsta should not be 0\n"));
-#endif
/* If apsta is not set, set it */
/* Check for any connected interfaces before wl down */
/* Do abort scan before creating GO */
wl_cfg80211_scan_abort(cfg);
- wl_ext_get_sec(dev, 0, sec, sizeof(sec));
- WL_MSG(dev->name, "Creating AP/GO with sec=%s\n", sec);
if (dev_role == NL80211_IFTYPE_P2P_GO) {
+ wl_ext_get_sec(dev, 0, sec, sizeof(sec));
+ WL_MSG(dev->name, "Creating GO with sec=%s\n", sec);
is_bssup = wl_cfg80211_bss_isup(dev, bssidx);
if (!is_bssup && (ies->wpa2_ie != NULL)) {
WL_ERR(("Could not get wsec %d\n", err));
goto exit;
}
- if (dhdp->conf->chip == BCM43430_CHIP_ID && bssidx > 0 && wsec >= 2) {
- wsec |= 0x8; // terence 20180628: fix me, this is a workaround
+ if (dhdp->conf->chip == BCM43430_CHIP_ID && bssidx > 0 &&
+ (wsec & (TKIP_ENABLED|AES_ENABLED))) {
+ 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));
join_params.ssid.SSID_len);
join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+ wl_ext_get_sec(dev, 0, sec, sizeof(sec));
+ WL_MSG(dev->name, "Creating AP with sec=%s\n", sec);
/* create softap */
if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
join_params_size)) != 0) {
} else
#endif /* WL_WPS_SYNC */
{
-
+ scb_val.val = DOT11_RC_DEAUTH_LEAVING;
+ WL_MSG(dev->name, "Disconnect STA : " MACDBG " scb_val.val %d\n",
+ MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mac_addr,
+ eabuf)), scb_val.val);
/* need to guarantee EAP-Failure send out before deauth */
dhd_wait_pend8021x(dev);
- scb_val.val = DOT11_RC_DEAUTH_LEAVING;
err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
sizeof(scb_val_t));
if (err < 0) {
WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
}
- WL_MSG(dev->name, "Disconnect STA : " MACDBG " scb_val.val %d\n",
- MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mac_addr,
- eabuf)), scb_val.val);
}
#ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
if (err) {
WL_ERR(("Disabling NDO Failed %d\n", err));
}
+#ifdef WL_EXT_IAPSTA
+ wl_ext_iapsta_update_iftype(dev, dhd_net2idx(dhd->info, dev), WL_IF_TYPE_AP);
+#endif /* WL_EXT_IAPSTA */
#ifdef PKT_FILTER_SUPPORT
/* Disable packet filter */
if (dhd->early_suspended) {
wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
wl_cfg80211_stop_ap(wiphy, dev);
if (dev_role == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+ if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
#ifdef PKT_FILTER_SUPPORT
/* Enable packet filter */
#ifdef DISABLE_WL_FRAMEBURST_SOFTAP
wl_cfg80211_set_frameburst(cfg, TRUE);
#endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
+#ifdef WL_EXT_IAPSTA
+ }
+#endif /* WL_EXT_IAPSTA */
}
#ifdef WLTDLS
if (bssidx == 0) {
#endif /* WLTDLS */
if (dev_role == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+ if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
/* clear the AP mode */
dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
+#ifdef WL_EXT_IAPSTA
+ }
+#endif /* WL_EXT_IAPSTA */
}
return err;
}
if (err) {
WL_ERR(("ADD/SET beacon failed\n"));
if (dev_role == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+ if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
/* clear the AP mode */
dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
+#ifdef WL_EXT_IAPSTA
+ }
+#endif /* WL_EXT_IAPSTA */
}
}
return err;
wl_cfg80211_clear_per_bss_ies(cfg, dev->ieee80211_ptr);
if (wdev->iftype == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+ if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
/* clear the AP mode */
dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
+#ifdef WL_EXT_IAPSTA
+ }
+#endif /* WL_EXT_IAPSTA */
}
return 0;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
.channel_switch = wl_cfg80211_channel_switch,
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
+#ifdef WL_CLIENT_SAE
+ .external_auth = wl_cfg80211_external_auth,
+#endif /* WL_CLIENT_SAE */
};
s32 wl_mode_to_nl80211_iftype(s32 mode)
return NL80211_IFTYPE_ADHOC;
case WL_MODE_AP:
return NL80211_IFTYPE_AP;
+#ifdef WLMESH_CFG80211
+ case WL_MODE_MESH:
+ return NL80211_IFTYPE_MESH_POINT;
+#endif /* WLMESH_CFG80211 */
default:
return NL80211_IFTYPE_UNSPECIFIED;
}
return ret;
}
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
+#define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+#else
+#define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+#endif /* kernel version < 3.9.0 */
+#endif
+
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+WL_CFG80211_REG_NOTIFIER()
+{
+ struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
+ int ret = 0;
+ int revinfo = -1;
+
+ if (!request || !cfg) {
+ WL_ERR(("Invalid arg\n"));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
+ return -EINVAL;
+#else
+ return;
+#endif /* kernel version < 3.10.11 */
+ }
+
+ WL_DBG(("ccode: %c%c Initiator: %d\n",
+ request->alpha2[0], request->alpha2[1], request->initiator));
+
+ /* We support only REGDOM_SET_BY_USER as of now */
+ if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
+ (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
+ WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
+ request->initiator));
+ /* in case of no supported country by regdb
+ lets driver setup platform default Locale
+ */
+ }
+
+ WL_ERR(("Set country code %c%c from %s\n",
+ request->alpha2[0], request->alpha2[1],
+ ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
+
+ if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
+ false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
+ revinfo)) < 0) {
+ WL_ERR(("set country Failed :%d\n", ret));
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
+ return ret;
+#else
+ return;
+#endif /* kernel version < 3.10.11 */
+}
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
+
#ifdef CONFIG_PM
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
static const struct wiphy_wowlan_support brcm_wowlan_support = {
wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
#endif /* LINUX_VER < 4.12 */
#endif /* WL_SCHED_SCAN */
+#ifdef WLMESH_CFG80211
+ wdev->wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
+#endif /* WLMESH_CFG80211 */
wdev->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION)
| BIT(NL80211_IFTYPE_ADHOC)
#if defined(WL_CFG80211_P2P_DEV_IF)
| BIT(NL80211_IFTYPE_P2P_DEVICE)
#endif /* WL_CFG80211_P2P_DEV_IF */
+#ifdef WLMESH_CFG80211
+ | BIT(NL80211_IFTYPE_MESH_POINT)
+#endif /* WLMESH_CFG80211 */
| BIT(NL80211_IFTYPE_AP);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
wiphy_ext_feature_set(wdev->wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
#endif /* WL_FILS */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
wdev->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wdev->wiphy->max_num_csa_counters = WL_MAX_NUM_CSA_COUNTERS;
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 12, 0) */
wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
#endif // endif
-#ifdef WL_SAE
- wdev->wiphy->features |= NL80211_FEATURE_SAE;
-#endif /* WL_SAE */
+#if defined(WL_SAE) || defined(WL_CLIENT_SAE)
+ 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)
if (FW_SUPPORTED(dhd, idsup)) {
err = wiphy_ext_feature_set(wdev->wiphy,
wl_delete_all_netinfo(cfg);
if (wiphy) {
+ if (wdev->netdev)
+ wdev->netdev->ieee80211_ptr = NULL;
+ wdev->netdev = NULL;
MFREE(cfg->osh, wdev, sizeof(*wdev));
+ cfg->wdev = NULL;
wiphy_free(wiphy);
}
*/
}
-s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
+#if defined(BSSCACHE) || defined(RSSIAVG)
+void wl_cfg80211_update_bss_cache(struct bcm_cfg80211 *cfg)
{
- struct wl_scan_results *bss_list;
- wl_bss_info_t *bi = NULL; /* must be initialized */
- s32 err = 0;
- s32 i;
- struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
#if defined(RSSIAVG)
int rssi;
#endif
-#if defined(BSSCACHE)
- wl_bss_cache_t *node;
-#endif
-
- bss_list = cfg->bss_list;
+ struct wl_scan_results *bss_list = cfg->bss_list;
/* Free cache in p2p scanning*/
if (p2p_is_on(cfg) && p2p_scan(cfg)) {
/* Delete disconnected cache */
#if defined(BSSCACHE)
- wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+ wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl,
+ (u8*)&cfg->disconnected_bssid);
#if defined(RSSIAVG)
- wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+ wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl,
+ (u8*)&cfg->disconnected_bssid);
#endif
if (cfg->p2p_disconnected == 0)
memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
wl_reset_bss_cache(&cfg->g_bss_cache_ctrl);
#endif
+}
+#endif
+
+#if defined(BSSCACHE)
+s32 wl_inform_bss_cache(struct bcm_cfg80211 *cfg)
+{
+ struct wl_scan_results *bss_list = cfg->bss_list;
+ wl_bss_info_t *bi = NULL; /* must be initialized */
+ s32 err = 0;
+ s32 i;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
#if defined(BSSCACHE)
+ wl_bss_cache_t *node;
+#endif
+
if (cfg->p2p_disconnected > 0) {
// terence 20130703: Fix for wrong group_capab (timing issue)
wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
if (cfg->autochannel)
wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version,
&cfg->best_2g_ch, &cfg->best_5g_ch);
+
+ return err;
+}
+#endif
+
+s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
+{
+#if !defined(BSSCACHE)
+ struct wl_scan_results *bss_list;
+ wl_bss_info_t *bi = NULL; /* must be initialized */
+ s32 i;
+ struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+#endif
+ s32 err = 0;
+
+#if defined(BSSCACHE) || defined(RSSIAVG)
+ wl_cfg80211_update_bss_cache(cfg);
+#endif
+
+#if defined(BSSCACHE)
+ err = wl_inform_bss_cache(cfg);
#else
+ bss_list = cfg->bss_list;
WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
#ifdef ESCAN_CHANNEL_CACHE
reset_roam_cache(cfg);
preempt_disable();
bi = next_bss(bss_list, bi);
for_each_bss(bss_list, bi, i) {
- if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
+ if (cfg->p2p_disconnected > 0 &&
+ !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN)) {
+ WL_SCAN(("Skip %pM\n", &bi->BSSID));
continue;
+ }
#ifdef ESCAN_CHANNEL_CACHE
add_roam_cache(cfg, bi);
#endif /* ESCAN_CHANNEL_CACHE */
if (cfg->p2p_disconnected > 0) {
// terence 20130703: Fix for wrong group_capab (timing issue)
cfg->p2p_disconnected++;
- if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
+ if (cfg->p2p_disconnected >= 2) {
cfg->p2p_disconnected = 0;
memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
}
}
if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
- WL_MSG(ndev->name, "event %s(%d) status %d reason %d\n",
- bcmevent_get_name(event), event, ntoh32(e->status), reason);
+ WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN,
+ "event %s(%d) status %d reason %d\n",
+ bcmevent_get_name(event), event, ntoh32(e->status), reason);
}
#if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
} else if ((event == WLC_E_DEAUTH_IND) ||
((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) ||
(event == WLC_E_DISASSOC_IND)) {
- WL_MSG(ndev->name, "del sta event for "MACDBG "\n",
- MAC2STRDBG(e->addr.octet));
+ WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN,
+ "del sta event for "MACDBG "\n", MAC2STRDBG(e->addr.octet));
wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS,
WL_EXT_STATUS_STA_DISCONNECTED, NULL);
cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
return err;
}
+#ifdef WL_CLIENT_SAE
static s32
-wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+wl_notify_start_auth(struct bcm_cfg80211 *cfg,
+ bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data)
+{
+ struct cfg80211_external_auth_params ext_auth_param;
+ struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+ u32 datalen = be32_to_cpu(e->datalen);
+ wl_ext_auth_evt_t *evt_data = (wl_ext_auth_evt_t *)data;
+ wl_assoc_mgr_cmd_t cmd;
+ int err;
+
+ WL_DBG(("Enter\n"));
+
+ if (!datalen || !data)
+ return BCME_ERROR;
+
+ ext_auth_param.ssid.ssid_len = MIN(evt_data->ssid.SSID_len, DOT11_MAX_SSID_LEN);
+ if (ext_auth_param.ssid.ssid_len)
+ memcpy(&ext_auth_param.ssid.ssid, evt_data->ssid.SSID,
+ ext_auth_param.ssid.ssid_len);
+
+ memcpy(&ext_auth_param.bssid, &evt_data->bssid, ETHER_ADDR_LEN);
+ ext_auth_param.action = NL80211_EXTERNAL_AUTH_START;
+ ext_auth_param.key_mgmt_suite = ntoh32(WLAN_AKM_SUITE_SAE_SHA256);
+
+ WL_MSG(ndev->name, "BSSID: "MACDBG"\n", MAC2STRDBG(&evt_data->bssid));
+
+ cfg80211_external_auth_request(ndev, &ext_auth_param, GFP_KERNEL);
+
+ cmd.version = WL_ASSOC_MGR_CURRENT_VERSION;
+ cmd.length = sizeof(cmd);
+ cmd.cmd = WL_ASSOC_MGR_CMD_PAUSE_ON_EVT;
+ cmd.params = WL_ASSOC_MGR_PARAMS_PAUSE_EVENT_AUTH_RESP;
+ err = wldev_iovar_setbuf(ndev, "assoc_mgr_cmd", (void *)&cmd, sizeof(cmd),
+ cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("Failed to pause assoc(%d)\n", err));
+ }
+
+ return BCME_OK;
+}
+
+static s32
+wl_notify_connect_status_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
const wl_event_msg_t *e, void *data)
{
s32 err = 0;
u32 event = ntoh32(e->event_type);
- u16 flags = ntoh16(e->flags);
- u32 status = ntoh32(e->status);
- bool active;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
- struct ieee80211_channel *channel = NULL;
+ u32 reason = ntoh32(e->reason);
+ u32 len = ntoh32(e->datalen);
+ u32 status = ntoh32(e->status);
+
+ bool isfree = false;
+ u8 *mgmt_frame;
+ u8 bsscfgidx = e->bsscfgidx;
+ s32 freq;
+ s32 channel;
+ u8 *body = NULL;
+ u16 fc = 0, rssi = 0;
+ bcm_struct_cfgdev *cfgdev = ndev_to_cfgdev(ndev);
+
+ struct ieee80211_supported_band *band;
+ struct ether_addr da;
+ struct ether_addr bssid;
struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
- u32 chanspec, chan;
- u32 freq, band;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
+ channel_info_t ci;
- if (event == WLC_E_JOIN) {
- WL_INFORM_MEM(("[%s] joined in IBSS network\n", ndev->name));
+ WL_DBG(("event %d status %d reason %d\n", event, status, reason));
+
+ if (event == WLC_E_AUTH) {
+ struct wl_security *sec;
+ sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
+
+ if (!(sec->auth_type == NL80211_AUTHTYPE_SAE)) {
+ WL_DBG(("Abort AUTH processing due to NOT SAE\n"));
+ return 0;
+ } else {
+ if (status != WLC_E_STATUS_SUCCESS && !len) {
+ WL_ERR(("SAE AUTH FAIL EVENT\n"));
+ wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED,
+ WL_EXT_STATUS_DISCONNECTED, NULL);
+ return 0;
+ }
+ }
}
- if (event == WLC_E_START) {
- WL_INFORM_MEM(("[%s] started IBSS network\n", ndev->name));
+
+ if (!len && (event == WLC_E_DEAUTH)) {
+ len = 2; /* reason code field */
+ data = &reason;
}
- if (event == WLC_E_JOIN || event == WLC_E_START ||
- (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
- err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
- if (unlikely(err)) {
- WL_ERR(("Could not get chanspec %d\n", err));
- return err;
- }
- chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
+
+ if (len) {
+ body = kzalloc(len, GFP_KERNEL);
+ if (body == NULL) {
+ WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
+ return WL_INVALID;
+ }
+ }
+
+ memset(&bssid, 0, ETHER_ADDR_LEN);
+ if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
+ kfree(body);
+ return WL_INVALID;
+ }
+ if (len)
+ memcpy(body, data, len);
+
+ wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+ NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
+ memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
+ err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
+ /* Use e->addr as bssid for Sta case , before association completed */
+ if (err == BCME_NOTASSOCIATED)
+ memcpy(&bssid, &e->addr, ETHER_ADDR_LEN);
+
+ switch (event) {
+ case WLC_E_ASSOC_IND:
+ fc = FC_ASSOC_REQ;
+ break;
+ case WLC_E_REASSOC_IND:
+ fc = FC_REASSOC_REQ;
+ break;
+ case WLC_E_DISASSOC_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_AUTH:
+ fc = FC_AUTH;
+ break;
+ default:
+ fc = 0;
+ goto exit;
+ }
+ if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) {
+ kfree(body);
+ return err;
+ }
+
+ channel = dtoh32(ci.hw_channel);
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+ if (!band) {
+ WL_ERR(("No valid band\n"));
+ if (body)
+ kfree(body);
+ return -EINVAL;
+ }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
+ freq = ieee80211_channel_to_frequency(channel);
+ (void)band->band;
+#else
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+
+ err = wl_frame_get_mgmt(cfg, fc, &da, &e->addr, &bssid,
+ &mgmt_frame, &len, body);
+ if (err < 0) {
+ goto exit;
+ }
+ isfree = true;
+
+ if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+ } else if (event == WLC_E_DISASSOC_IND) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+ } else if (event == WLC_E_AUTH) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+ }
+exit:
+ if (isfree)
+ kfree(mgmt_frame);
+ if (body)
+ kfree(body);
+ return err;
+}
+#endif /* WL_CLIENT_SAE */
+
+static s32
+wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 event = ntoh32(e->event_type);
+ u16 flags = ntoh16(e->flags);
+ u32 status = ntoh32(e->status);
+ bool active;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ struct ieee80211_channel *channel = NULL;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ u32 chanspec, chan;
+ u32 freq, band;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
+
+ if (event == WLC_E_JOIN) {
+ WL_INFORM_MEM(("[%s] joined in IBSS network\n", ndev->name));
+ }
+ if (event == WLC_E_START) {
+ WL_INFORM_MEM(("[%s] started IBSS network\n", ndev->name));
+ }
+ if (event == WLC_E_JOIN || event == WLC_E_START ||
+ (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
+ if (unlikely(err)) {
+ WL_ERR(("Could not get chanspec %d\n", err));
+ return err;
+ }
+ chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
freq = ieee80211_channel_to_frequency(chan, band);
channel = ieee80211_get_channel(wiphy, freq);
}
}
+#ifdef WLMESH_CFG80211
+static s32
+wl_notify_connect_status_mesh(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 event = ntoh32(e->event_type);
+ u32 reason = ntoh32(e->reason);
+ u32 len = ntoh32(e->datalen);
+ u32 status = ntoh32(e->status);
+
+#if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
+ (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+ bool isfree = false;
+ u8 *mgmt_frame;
+ u8 bsscfgidx = e->bsscfgidx;
+ s32 freq;
+ s32 channel;
+ u8 *body = NULL;
+ u16 fc = 0;
+ u32 body_len = 0;
+
+ struct ieee80211_supported_band *band;
+ struct ether_addr da;
+ struct ether_addr bssid;
+ struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+ channel_info_t ci;
+ u8 ioctl_buf[WLC_IOCTL_SMLEN];
+#else
+ struct station_info sinfo;
+#endif /* (LINUX_VERSION < VERSION(3,2,0)) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+
+ WL_INFORM_MEM(("[%s] Mode Mesh. Event:%d status:%d reason:%d\n",
+ ndev->name, event, ntoh32(e->status), reason));
+
+ /* if link down, bsscfg is disabled. */
+ if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
+ (ndev != bcmcfg_to_prmry_ndev(cfg))) {
+ WL_MSG(ndev->name, "Mesh mode link down !! \n");
+ return 0;
+ }
+
+ if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
+ (reason == WLC_E_REASON_INITIAL_ASSOC)) {
+ /* AP/GO brought up successfull in firmware */
+ WL_MSG(ndev->name, "Mesh Link up\n");
+ return 0;
+ }
+
+ if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
+ WL_MSG(ndev->name, "event %s(%d) status %d reason %d\n",
+ bcmevent_get_name(event), event, ntoh32(e->status), reason);
+ }
+
+#if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
+ (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+ WL_DBG(("Enter \n"));
+ if (!len && (event == WLC_E_DEAUTH)) {
+ len = 2; /* reason code field */
+ data = &reason;
+ }
+ if (len) {
+ body = (u8 *)MALLOCZ(cfg->osh, len);
+ if (body == NULL) {
+ WL_ERR(("Failed to allocate body\n"));
+ return WL_INVALID;
+ }
+ }
+ bzero(&bssid, ETHER_ADDR_LEN);
+ WL_DBG(("Enter event %d ndev %p\n", event, ndev));
+ if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
+ MFREE(cfg->osh, body, len);
+ return WL_INVALID;
+ }
+ if (len)
+ memcpy(body, data, len);
+
+ wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+ NULL, 0, ioctl_buf, sizeof(ioctl_buf), bsscfgidx, NULL);
+ memcpy(da.octet, ioctl_buf, ETHER_ADDR_LEN);
+ bzero(&bssid, sizeof(bssid));
+ err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
+ switch (event) {
+ case WLC_E_ASSOC_IND:
+ fc = FC_ASSOC_REQ;
+ break;
+ case WLC_E_REASSOC_IND:
+ fc = FC_REASSOC_REQ;
+ break;
+ case WLC_E_DISASSOC_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH_IND:
+ fc = FC_DISASSOC;
+ break;
+ case WLC_E_DEAUTH:
+ fc = FC_DISASSOC;
+ break;
+ default:
+ fc = 0;
+ goto exit;
+ }
+ bzero(&ci, sizeof(ci));
+ if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) {
+ MFREE(cfg->osh, body, len);
+ return err;
+ }
+
+ channel = dtoh32(ci.hw_channel);
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+ if (!band) {
+ WL_ERR(("No valid band\n"));
+ if (body) {
+ MFREE(cfg->osh, body, len);
+ }
+ return -EINVAL;
+ }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
+ freq = ieee80211_channel_to_frequency(channel);
+ (void)band->band;
+#else
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif // endif
+ body_len = len;
+ err = wl_frame_get_mgmt(cfg, fc, &da, &e->addr, &bssid,
+ &mgmt_frame, &len, body);
+ if (err < 0)
+ goto exit;
+ isfree = true;
+
+ if ((event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) ||
+ (event == WLC_E_DISASSOC_IND) ||
+ ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH))) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
+ defined(WL_COMPAT_WIRELESS)
+ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif /* LINUX_VERSION >= VERSION(3, 18,0) || WL_COMPAT_WIRELESS */
+ }
+
+exit:
+ if (isfree) {
+ MFREE(cfg->osh, mgmt_frame, len);
+ }
+ if (body) {
+ MFREE(cfg->osh, body, body_len);
+ }
+#else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+ memset(&sinfo, 0, sizeof(struct station_info));
+ sinfo.filled = 0;
+ if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
+ reason == DOT11_SC_SUCCESS) {
+ /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
+ * STATION_INFO_ASSOC_REQ_IES flag
+ */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
+ sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
+ if (!data) {
+ WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
+ return -EINVAL;
+ }
+ sinfo.assoc_req_ies = data;
+ sinfo.assoc_req_ies_len = len;
+ WL_MSG(ndev->name, "new sta event for "MACDBG "\n",
+ MAC2STRDBG(e->addr.octet));
+ cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
+ } else if ((event == WLC_E_DEAUTH_IND) ||
+ ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) ||
+ (event == WLC_E_DISASSOC_IND)) {
+ WL_MSG(ndev->name, "del sta event for "MACDBG "\n",
+ MAC2STRDBG(e->addr.octet));
+ cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
+ }
+#endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+ return err;
+}
+#endif /* WLMESH_CFG80211 */
+
static s32
wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
const wl_event_msg_t *e, void *data)
ntoh32(e->status), ntoh32(e->reason)));
if (mode == WL_MODE_AP) {
err = wl_notify_connect_status_ap(cfg, ndev, e, data);
+#ifdef WLMESH_CFG80211
+ } else if (mode == WL_MODE_MESH) {
+ err = wl_notify_connect_status_mesh(cfg, ndev, e, data);
+#endif /* WLMESH_CFG80211 */
} else if (mode == WL_MODE_IBSS) {
err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
} else if (mode == WL_MODE_BSS) {
" connect state. Ignore\n"));
return BCME_OK;
}
+#ifdef WL_CLIENT_SAE
+ if (event == WLC_E_AUTH)
+ wl_notify_connect_status_bss(cfg, ndev, e, data);
+#endif /* WL_CLIENT_SAE */
if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
wl_get_auth_assoc_status(cfg, ndev, e, data);
dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg),
FALSE, 0, 0);
#endif /* RSSI_MONITOR_SUPPORT */
- if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
+ if (dhdp->conf->eapol_status == EAPOL_STATUS_4WAY_DONE &&
+ !memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
// terence 20130703: Fix for wrong group_capab (timing issue)
cfg->p2p_disconnected = 1;
}
if ((*channel == cur_channel) && ((memcmp(curbssid, &e->addr,
ETHER_ADDR_LEN) == 0) || (memcmp(&cfg->last_roamed_addr,
&e->addr, ETHER_ADDR_LEN) == 0))) {
- WL_ERR(("BSS already present, Skipping roamed event to"
+ WL_DBG(("BSS already present, Skipping roamed event to"
" upper layer\n"));
goto fail;
}
completed = false;
sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
}
+ if (completed) {
+ WL_MSG(ndev->name, "Report connect result - connection succeeded\n");
+ wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL);
+ } else {
+ WL_MSG(ndev->name, "Report connect result - connection failed\n");
+ wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED,
+ WL_EXT_STATUS_DISCONNECTED, NULL);
+ }
#ifdef WL_FILS
if ((sec->auth_type == DOT11_FILS_SKEY_PFS)||(sec->auth_type == DOT11_FILS_SKEY)) {
wl_get_fils_connect_params(cfg, ndev);
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
}
- if (completed) {
- WL_MSG(ndev->name, "Report connect result - "
- "connection succeeded\n");
- wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL);
- } else {
- WL_MSG(ndev->name, "Report connect result - connection failed\n");
- wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED,
- WL_EXT_STATUS_DISCONNECTED, NULL);
- }
} else {
WL_INFORM_MEM(("[%s] Ignore event:%d. drv status"
" connecting:%x. connected:%d\n",
#ifdef WL_CHAN_UTIL
cfg->evt_handler[WLC_E_BSS_LOAD] = wl_cfg80211_bssload_report_event_handler;
#endif /* WL_CHAN_UTIL */
+#ifdef WL_CLIENT_SAE
+ cfg->evt_handler[WLC_E_JOIN_START] = wl_notify_start_auth;
+#endif /* WL_CLIENT_SAE */
}
+#ifdef WL_CLIENT_SAE
+/** Called by the cfg80211 framework */
+static s32
+wl_cfg80211_external_auth(struct wiphy *wiphy,
+ struct net_device *ndev, struct cfg80211_external_auth_params *ext_auth_param)
+{
+ int err = 0;
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ wl_assoc_mgr_cmd_t cmd;
+
+ WL_DBG(("Enter\n"));
+
+ if (!ext_auth_param ||
+ ETHER_ISNULLADDR(ext_auth_param->bssid)) {
+ WL_ERR(("Invalid wl_cfg80211_external_auth param\n"));
+ return -EINVAL;
+ }
+
+ cmd.version = WL_ASSOC_MGR_CURRENT_VERSION;
+ cmd.length = sizeof(cmd);
+ cmd.cmd = WL_ASSOC_MGR_CMD_PAUSE_ON_EVT;
+ cmd.params = WL_ASSOC_MGR_PARAMS_EVENT_NONE;
+ err = wldev_iovar_setbuf(ndev, "assoc_mgr_cmd", (void *)&cmd, sizeof(cmd), cfg->ioctl_buf,
+ WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+ if (unlikely(err)) {
+ WL_ERR(("Failed to pause assoc(%d)\n", err));
+ }
+
+ return err;
+}
+#endif /* WL_CLIENT_SAE */
+
#if defined(STATIC_WL_PRIV_STRUCT)
static int
wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
MFREE(dhd->osh, wdev, sizeof(*wdev));
return -ENOMEM;
}
+#ifdef WLMESH_CFG80211
+ wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_MESH);
+#else
wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
+#endif
cfg = wiphy_priv(wdev->wiphy);
cfg->wdev = wdev;
cfg->pub = context;
goto cfg80211_attach_out;
#endif // endif
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+ wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
+
#if defined(WL_ENABLE_P2P_IF)
err = wl_cfg80211_attach_p2p(cfg);
if (err)
/* Intentional fall through */
infra = 1;
break;
+#ifdef WLMESH_CFG80211
+ case NL80211_IFTYPE_MESH_POINT:
+ infra = WL_BSSTYPE_MESH;
+ break;
+#endif /* WLMESH_CFG80211 */
case WL_IF_TYPE_MONITOR:
case WL_IF_TYPE_NAN:
/* Intentionall fall through */
return err;
}
}
+#ifdef WLMESH_CFG80211
+ cfg->wdev->wiphy->features |= NL80211_FEATURE_USERSPACE_MPM;
+#endif /* WLMESH_CFG80211 */
#if defined(BCMSUP_4WAY_HANDSHAKE)
if (dhd->fw_4way_handshake) {
/* This is a hacky method to indicate fw 4WHS support and
mutex_lock(&cfg->in4way_sync);
max_wait_cnt--;
}
+ wake_up_interruptible(&dhdp->conf->event_complete);
}
break;
case WL_EXT_STATUS_CONNECTING:
mutex_lock(&cfg->in4way_sync);
max_wait_cnt--;
}
+ wake_up_interruptible(&dhdp->conf->event_complete);
}
break;
case WL_EXT_STATUS_CONNECTED:
ifidx = dhd_net2idx(dhdp->info, dev);
if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION && ifidx >= 0) {
dhd_conf_set_wme(cfg->pub, ifidx, 0);
+ wake_up_interruptible(&dhdp->conf->event_complete);
}
else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1);
if (action & WAIT_DISCONNECTED) {
cfg->disconnected_jiffies = jiffies;
}
+ wake_up_interruptible(&dhdp->conf->event_complete);
break;
case WL_EXT_STATUS_ADD_KEY:
dhdp->conf->eapol_status = EAPOL_STATUS_4WAY_DONE;
cfg->handshaking = 0;
}
}
+ wake_up_interruptible(&dhdp->conf->event_complete);
break;
case WL_EXT_STATUS_AP_ENABLED:
ifidx = dhd_net2idx(dhdp->info, dev);
struct wl_security;
struct wl_ibss;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) && !defined(WL_SAE))
-#define WL_SAE
-#endif // endif
+#if !defined(WL_CLIENT_SAE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
+#define WL_CLIENT_SAE
+#endif
+#if defined(WL_SAE) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+#error "Can not support WL_SAE befor kernel 3.14"
+#endif
+#if defined(WL_CLIENT_SAE) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
+#error "Can not support WL_CLIENT_SAE before kernel 4.17"
+#endif
+#if defined(WL_CLIENT_SAE) && defined(WL_SAE)
+#error "WL_SAE is for dongle-offload and WL_CLIENT_SAE is for wpa_supplicant. Please choose one."
+#endif
+
+#if defined(WL_CLIENT_SAE)
+#ifndef WL_ASSOC_MGR_CMD_SEND_AUTH
+#define WL_ASSOC_MGR_CMD_SEND_AUTH 3
+#endif /* WL_ASSOC_MGR_CMD_SEND_AUTH */
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) && !defined(WL_SCAN_TYPE))
#define WL_SCAN_TYPE
#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
#endif /* WLAN_AKM_SUITE_FT_PSK */
+#define WLAN_AKM_SUITE_SAE_SHA256 0x000FAC08
+
#ifndef WLAN_AKM_SUITE_8021X_SUITE_B
#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC0B
#define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC0C
typedef enum wl_iftype {
WL_IF_TYPE_STA = 0,
WL_IF_TYPE_AP = 1,
+#ifdef WLMESH_CFG80211
+ WL_IF_TYPE_MESH = 2,
+#endif /* WLMESH_CFG80211 */
WL_IF_TYPE_NAN_NMI = 3,
WL_IF_TYPE_NAN = 4,
WL_IF_TYPE_P2P_GO = 5,
WL_MODE_IBSS = 1,
WL_MODE_AP = 2,
WL_MODE_NAN = 4,
+#ifdef WLMESH_CFG80211
+ WL_MODE_MESH = 5,
+#endif /* WLMESH_CFG80211 */
WL_MODE_MAX
};
err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (unlikely(err < 0)) {
- printk("'cfg p2p_ifadd' error %d\n", err);
+ CFGP2P_ERR(("'cfg p2p_ifadd' error %d\n", err));
return err;
}
ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (unlikely(ret < 0)) {
- printk("'cfg p2p_ifdis' error %d\n", ret);
+ CFGP2P_ERR(("'cfg p2p_ifdis' error %d\n", ret));
}
return ret;
}
ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (unlikely(ret < 0)) {
- printk("'cfg p2p_ifdel' error %d\n", ret);
+ CFGP2P_ERR(("'cfg p2p_ifdel' error %d\n", ret));
}
#ifdef WL_DISABLE_HE_P2P
if ((bssidx = wl_get_bssidx_by_wdev(cfg, netdev->ieee80211_ptr)) < 0) {
err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
if (unlikely(err < 0)) {
- printk("'cfg p2p_ifupd' error %d\n", err);
+ CFGP2P_ERR(("'cfg p2p_ifupd' error %d\n", err));
} else if (if_type == WL_P2P_IF_GO) {
cfg->p2p->p2p_go_count++;
}
cfg->p2p_wdev = wdev;
cfg->p2p_net = net;
- printk("%s: P2P Interface Registered\n", net->name);
+ WL_MSG(net->name, "P2P Interface Registered\n");
return ret;
}
/* dword align allocation */
#define WLC_IOCTL_MAXLEN 8192
-#define CFGP2P_ERROR_TEXT "CFGP2P-ERROR) "
+#define CFGP2P_ERROR_TEXT "[dhd] CFGP2P-ERROR) "
#ifdef DHD_LOG_DUMP
-#define CFGP2P_ERR(args) \
- do { \
- if (wl_dbg_level & WL_DBG_ERR) { \
- printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__); \
- printk args; \
- DHD_LOG_DUMP_WRITE("[%s] %s: ", \
- dhd_log_dump_get_timestamp(), __func__); \
- DHD_LOG_DUMP_WRITE args; \
- } \
+#define CFGP2P_ERR_MSG(x, args...) \
+ do { \
+ if (wl_dbg_level & WL_DBG_ERR) { \
+ printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : " x, __func__, ## args); \
+ DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \
+ DHD_LOG_DUMP_WRITE(x, ## args); \
+ } \
} while (0)
-#define CFGP2P_INFO(args) \
+#define CFGP2P_ERR(x) CFGP2P_ERR_MSG x
+#define CFGP2P_INFO_MSG(x, args...) \
do { \
if (wl_dbg_level & WL_DBG_INFO) { \
- printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__); \
- printk args; \
- DHD_LOG_DUMP_WRITE("[%s] %s: ", \
- dhd_log_dump_get_timestamp(), __func__); \
- DHD_LOG_DUMP_WRITE args; \
+ printk(KERN_INFO "[dhd] CFGP2P-INFO) %s : " x, __func__, ## args); \
+ DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \
+ DHD_LOG_DUMP_WRITE(x, ## args); \
} \
} while (0)
-#define CFGP2P_ACTION(args) \
+#define CFGP2P_INFO(x) CFGP2P_INFO_MSG x
+#define CFGP2P_ACTION_MSG(x, args...) \
do { \
if (wl_dbg_level & WL_DBG_P2P_ACTION) { \
- printk(KERN_DEBUG "CFGP2P-ACTION) %s :", __func__); \
- printk args; \
- DHD_LOG_DUMP_WRITE("[%s] %s: ", \
- dhd_log_dump_get_timestamp(), __func__); \
- DHD_LOG_DUMP_WRITE args; \
+ printk(KERN_INFO "[dhd] CFGP2P-ACTION) %s :" x, __func__, ## args); \
+ DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \
+ DHD_LOG_DUMP_WRITE(x, ## args); \
} \
} while (0)
+#define CFGP2P_ACTION(x) CFGP2P_ACTION_MSG x
#else
-#define CFGP2P_ERR(args) \
+#define CFGP2P_ERR_MSG(x, args...) \
do { \
if (wl_dbg_level & WL_DBG_ERR) { \
- printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__); \
- printk args; \
+ printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : " x, __func__, ## args); \
} \
} while (0)
-#define CFGP2P_INFO(args) \
+#define CFGP2P_ERR(x) CFGP2P_ERR_MSG x
+#define CFGP2P_INFO_MSG(x, args...) \
do { \
if (wl_dbg_level & WL_DBG_INFO) { \
- printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__); \
- printk args; \
+ printk(KERN_INFO "[dhd] CFGP2P-INFO) %s : " x, __func__, ## args); \
} \
} while (0)
-#define CFGP2P_ACTION(args) \
+#define CFGP2P_INFO(x) CFGP2P_INFO_MSG x
+#define CFGP2P_ACTION_MSG(x, args...) \
do { \
if (wl_dbg_level & WL_DBG_P2P_ACTION) { \
- printk(KERN_INFO "CFGP2P-ACTION) %s :", __func__); \
- printk args; \
+ printk(KERN_INFO "[dhd] CFGP2P-ACTION) %s :" x, __func__, ## args); \
} \
} while (0)
+#define CFGP2P_ACTION(x) CFGP2P_ACTION_MSG x
#endif /* DHD_LOG_DUMP */
-#define CFGP2P_DBG(args) \
+#define CFGP2P_DBG_MSG(x, args...) \
do { \
if (wl_dbg_level & WL_DBG_DBG) { \
- printk(KERN_INFO "CFGP2P-DEBUG) %s :", __func__); \
- printk args; \
+ printk(KERN_INFO "[dhd] CFGP2P-DEBUG) %s :" x, __func__, ## args); \
} \
} while (0)
+#define CFGP2P_DBG(x) CFGP2P_DBG_MSG x
#define INIT_TIMER(timer, func, duration, extra_delay) \
do { \
return -ENODEV;
}
}
- err = wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY,
+ err = wl_cfg80211_check_in4way(cfg, ndev_to_wlc_ndev(ndev, cfg), NO_SCAN_IN4WAY,
WL_EXT_STATUS_SCAN, NULL);
if (err)
return err;
#if defined(ESCAN_RESULT_PATCH)
if (likely(cfg->scan_request)) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
- if (aborted && p2p_scan(cfg) &&
+ if (aborted && cfg->p2p && p2p_scan(cfg) &&
(cfg->scan_request->flags & NL80211_SCAN_FLAG_FLUSH)) {
WL_ERR(("scan list is changed"));
cfg->bss_list = wl_escan_get_buf(cfg, !aborted);
if (p2p_is_on(cfg))
wl_clr_p2p_status(cfg, SCANNING);
wl_clr_drv_status(cfg, SCANNING, dev);
+ wake_up_interruptible(&dhdp->conf->event_complete);
DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
dhd_bus_mem_dump(dhdp);
}
+#endif /* DHD_FW_COREDUMP */
/*
* For the memdump sanity, blocking bus transactions for a while
* Keeping it TRUE causes the sequential private cmd error
*/
dhdp->scan_timeout_occurred = FALSE;
-#endif /* DHD_FW_COREDUMP */
msg.event_type = hton32(WLC_E_ESCAN_RESULT);
msg.status = hton32(WLC_E_STATUS_TIMEOUT);
msg.reason = 0xFFFFFFFF;
}
}
if (buf_len > 0 && user_buf) {
+#if 0
+ mem_buf = vmalloc(buf_len);
+ if (!mem_buf) {
+ WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len));
+ ret = BCME_NOMEM;
+ goto exit;
+ }
+#endif
ret = dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg), &mem_buf, &buf_len);
if (ret) {
WL_ERR(("failed to get_socram_dump : %d\n", ret));
}
free_mem:
+// vfree(mem_buf);
/* Free skb memory */
if (skb) {
kfree_skb(skb);
.subcmd = BRCM_VENDOR_SCMD_PRIV_STR
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_priv_string_handler
},
#ifdef BCM_PRIV_CMD_SUPPORT
.subcmd = BRCM_VENDOR_SCMD_BCM_STR
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_priv_bcm_handler
},
#endif /* BCM_PRIV_CMD_SUPPORT */
.subcmd = BRCM_VENDOR_SCMD_BCM_PSK
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_sae_password
},
#endif /* WL_SAE */
.subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_gscan_get_capabilities
},
{
.subcmd = GSCAN_SUBCMD_SET_CONFIG
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_scan_cfg
},
{
.subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_batch_scan_cfg
},
{
.subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_initiate_gscan
},
{
.subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_enable_full_scan_result
},
{
.subcmd = GSCAN_SUBCMD_SET_HOTLIST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_hotlist_cfg
},
{
.subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_gscan_get_batch_results
},
#endif /* GSCAN_SUPPORT */
.subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_gscan_get_channel_list
},
#endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
.subcmd = RTT_SUBCMD_SET_CONFIG
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_rtt_set_config
},
{
.subcmd = RTT_SUBCMD_CANCEL_CONFIG
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_rtt_cancel_config
},
{
.subcmd = RTT_SUBCMD_GETCAPABILITY
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_rtt_get_capability
},
{
.subcmd = RTT_SUBCMD_GETAVAILCHANNEL
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_rtt_get_responder_info
},
{
.subcmd = RTT_SUBCMD_SET_RESPONDER
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_rtt_set_responder
},
{
.subcmd = RTT_SUBCMD_CANCEL_RESPONDER
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_rtt_cancel_responder
},
#endif /* RTT_SUPPORT */
.subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_get_feature_set
},
{
.subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_get_feature_set_matrix
},
{
.subcmd = ANDR_WIFI_RANDOM_MAC_OUI
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_rand_mac_oui
},
#ifdef CUSTOM_FORCE_NODFS_FLAG
.subcmd = ANDR_WIFI_NODFS_CHANNELS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_nodfs_flag
},
#endif /* CUSTOM_FORCE_NODFS_FLAG */
.subcmd = ANDR_WIFI_SET_COUNTRY
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_country
},
#ifdef LINKSTAT_SUPPORT
.subcmd = LSTATS_SUBCMD_GET_INFO
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_lstats_get_info
},
#endif /* LINKSTAT_SUPPORT */
.subcmd = GSCAN_SUBCMD_SET_EPNO_SSID
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_epno_cfg
},
.subcmd = WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_lazy_roam_cfg
},
.subcmd = WIFI_SUBCMD_ENABLE_LAZY_ROAM
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_enable_lazy_roam
},
.subcmd = WIFI_SUBCMD_SET_BSSID_PREF
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_bssid_pref
},
.subcmd = WIFI_SUBCMD_SET_SSID_WHITELIST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_ssid_whitelist
},
.subcmd = WIFI_SUBCMD_SET_BSSID_BLACKLIST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_bssid_blacklist
},
#endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
.subcmd = WIFI_SUBCMD_FW_ROAM_POLICY
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_fw_roaming_state
},
{
.subcmd = WIFI_SUBCMD_ROAM_CAPABILITY
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_fw_roam_get_capability
},
#endif /* ROAMEXP_SUPPORT */
.subcmd = DEBUG_GET_VER
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_get_version
},
#ifdef DHD_LOG_DUMP
.subcmd = DEBUG_GET_FILE_DUMP_BUF
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_file_dump
},
#endif /* DHD_LOG_DUMP */
.subcmd = DEBUG_TRIGGER_MEM_DUMP
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_trigger_mem_dump
},
{
.subcmd = DEBUG_GET_MEM_DUMP
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_get_mem_dump
},
{
.subcmd = DEBUG_START_LOGGING
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_start_logging
},
{
.subcmd = DEBUG_RESET_LOGGING
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_reset_logging
},
{
.subcmd = DEBUG_GET_RING_STATUS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_get_ring_status
},
{
.subcmd = DEBUG_GET_RING_DATA
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_get_ring_data
},
#endif /* DEBUGABILITY */
.subcmd = DEBUG_GET_FEATURE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_get_feature
},
#ifdef DBG_PKT_MON
.subcmd = DEBUG_START_PKT_FATE_MONITORING
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_start_pkt_fate_monitoring
},
{
.subcmd = DEBUG_GET_TX_PKT_FATES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_get_tx_pkt_fates
},
{
.subcmd = DEBUG_GET_RX_PKT_FATES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_dbg_get_rx_pkt_fates
},
#endif /* DBG_PKT_MON */
.subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_start_mkeep_alive
},
{
.subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_stop_mkeep_alive
},
#endif /* KEEP_ALIVE */
.subcmd = NAN_WIFI_SUBCMD_ENABLE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_start_handler
},
{
.subcmd = NAN_WIFI_SUBCMD_DISABLE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_stop_handler
},
{
.subcmd = NAN_WIFI_SUBCMD_CONFIG
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_config_handler
},
{
.subcmd = NAN_WIFI_SUBCMD_REQUEST_PUBLISH
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_req_publish
},
{
.subcmd = NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_req_subscribe
},
{
.subcmd = NAN_WIFI_SUBCMD_CANCEL_PUBLISH
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_cancel_publish
},
{
.subcmd = NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_cancel_subscribe
},
{
.subcmd = NAN_WIFI_SUBCMD_TRANSMIT
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_transmit
},
{
.subcmd = NAN_WIFI_SUBCMD_GET_CAPABILITIES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_get_capablities
},
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_data_path_iface_create
},
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_data_path_iface_delete
},
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_data_path_request
},
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_data_path_response
},
{
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_END
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_data_path_end
},
#ifdef WL_NAN_DISC_CACHE
.subcmd = NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_data_path_sec_info
},
#endif /* WL_NAN_DISC_CACHE */
.subcmd = NAN_WIFI_SUBCMD_VERSION_INFO
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_nan_version_info
},
#endif /* WL_NAN */
.subcmd = APF_SUBCMD_GET_CAPABILITIES
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_apf_get_capabilities
},
.subcmd = APF_SUBCMD_SET_FILTER
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_apf_set_filter
},
#endif /* PKT_FILTER_SUPPORT && APF */
.subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_configure_nd_offload
},
#endif /* NDO_CONFIG_SUPPORT */
.subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_rssi_monitor
},
#endif /* RSSI_MONITOR_SUPPORT */
.subcmd = DEBUG_GET_WAKE_REASON_STATS
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_get_wake_reason_stats
},
#endif /* DHD_WAKE_STATUS */
.subcmd = WIFI_SUBCMD_CONFIG_TCPACK_SUP
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_tcpack_sup_mode
},
#endif /* DHDTCPACK_SUPPRESS */
.subcmd = BRCM_VENDOR_SCMD_SET_PMK
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_pmk
},
#endif /* 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,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_get_driver_feature
},
#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT)
.subcmd = DEBUG_FILE_DUMP_DONE_IND
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_notify_dump_completion
},
#endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */
.subcmd = DEBUG_SET_HAL_START
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_set_hal_started
},
{
.subcmd = DEBUG_SET_HAL_STOP
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+ .policy = VENDOR_CMD_RAW_DATA,
+#endif
.doit = wl_cfgvendor_stop_hal
}
#endif /* WL_CFG80211 */
#define ESCAN_TRACE(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_TRACE_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
#define ESCAN_SCAN(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_SCAN_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] ESCAN-SCAN) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] ESCAN-SCAN) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
#define ESCAN_DBG(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_DBG_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] ESCAN-DBG) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] ESCAN-DBG) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
* Returns INVCHANSPEC on error
*/
static chanspec_t
-wl_ch_host_to_driver(int ioctl_ver, s32 bssidx, u16 channel)
+wl_ch_host_to_driver(int ioctl_ver, u16 channel)
{
chanspec_t chanspec;
(struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info;
}
+#if defined(ESCAN_RESULT_PATCH)
static s32
wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan)
{
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->ioctl_ver, &escan->best_2g_ch, &escan->best_5g_ch);
#else
if (escan->autochannel)
wl_ext_get_best_channel(dev, bss_list, escan->ioctl_ver,
return err;
}
+#endif /* ESCAN_RESULT_PATCH */
static wl_scan_params_t *
wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan,
wl_scan_params_t *params;
int params_size;
int num_chans;
- int bssidx = 0;
*out_params_size = 0;
if (channel == -1)
params->channel_list[0] = htodchanspec(channel);
else
- params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, bssidx, channel);
+ params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, channel);
/* Our scan params have 1 channel and 0 ssids */
params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
char extra[IW_CUSTOM_MAX + 1];
#endif
#endif
+ struct dhd_pub *dhd = dhd_get_pub(dev);
ESCAN_TRACE(dev->name, "Enter\n");
if (timer_pending(&escan->scan_timeout))
del_timer_sync(&escan->scan_timeout);
+
#if defined(ESCAN_RESULT_PATCH)
escan->bss_list = wl_escan_get_buf(escan);
wl_escan_inform_bss(dev, escan);
#endif /* ESCAN_RESULT_PATCH */
+ escan->escan_state = ESCAN_STATE_IDLE;
+ wake_up_interruptible(&dhd->conf->event_complete);
+
#if defined(WL_WIRELESS_EXT)
#if WIRELESS_EXT > 13
#if WIRELESS_EXT > 14
}
#endif /* ESCAN_BUF_OVERFLOW_MGMT */
-s32
-wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan,
+static s32
+wl_escan_handler(struct net_device *dev, struct wl_escan_info *escan,
const wl_event_msg_t *e, void *data)
{
s32 err = BCME_OK;
escan->bss_list = wl_escan_get_buf(escan);
ESCAN_DBG(dev->name, "SCAN COMPLETED: scanned AP count=%d\n",
escan->bss_list->count);
- wl_escan_inform_bss(dev, escan);
wl_escan_notify_complete(dev, escan, false);
- escan->escan_state = ESCAN_STATE_IDLE;
} else if ((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)) {
escan->bss_list = wl_escan_get_buf(escan);
ESCAN_DBG(dev->name, "SCAN ABORT: scanned AP count=%d\n",
escan->bss_list->count);
- wl_escan_inform_bss(dev, escan);
wl_escan_notify_complete(dev, escan, false);
- escan->escan_state = ESCAN_STATE_IDLE;
} else if (status == WLC_E_STATUS_TIMEOUT) {
ESCAN_ERROR(dev->name, "WLC_E_STATUS_TIMEOUT\n");
ESCAN_ERROR(dev->name, "reason[0x%x]\n", e->reason);
if (e->reason == 0xFFFFFFFF) {
wl_escan_notify_complete(dev, escan, true);
}
- escan->escan_state = ESCAN_STATE_IDLE;
} else {
ESCAN_ERROR(dev->name, "unexpected Escan Event %d : abort\n", status);
escan->bss_list = wl_escan_get_buf(escan);
ESCAN_DBG(dev->name, "SCAN ABORTED(UNEXPECTED): scanned AP count=%d\n",
escan->bss_list->count);
- wl_escan_inform_bss(dev, escan);
wl_escan_notify_complete(dev, escan, false);
- escan->escan_state = ESCAN_STATE_IDLE;
}
exit:
mutex_unlock(&escan->usr_sync);
bzero(&msg, sizeof(wl_event_msg_t));
ESCAN_ERROR(escan->dev->name, "timer expired\n");
+ msg.ifidx = dhd_net2idx(escan->pub->info, escan->dev);
msg.event_type = hton32(WLC_E_ESCAN_RESULT);
msg.status = hton32(WLC_E_STATUS_TIMEOUT);
msg.reason = 0xFFFFFFFF;
int
wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp,
- wlc_ssid_t *ssid, bool bcast)
+ wlc_ssid_t *ssid, uint16 channel, bool bcast)
{
struct wl_escan_info *escan = dhdp->escan;
s32 err = BCME_OK;
mutex_lock(&escan->usr_sync);
if (escan->escan_state == ESCAN_STATE_DOWN) {
ESCAN_ERROR(dev->name, "STATE is down\n");
- err = -EIO;
+ err = -EINVAL;
goto exit2;
}
- if (escan->escan_state == ESCAN_STATE_SCANING) {
- ESCAN_ERROR(dev->name, "Scanning already\n");
+
+ if (wl_ext_check_scan(dev, dhdp)) {
+ err = -EBUSY;
goto exit;
}
/* if scan request is not empty parse scan request paramters */
memset(valid_chan_list, 0, sizeof(valid_chan_list));
list = (wl_uint32_list_t *)(void *) valid_chan_list;
- list->count = htod32(WL_NUMCHANNELS);
- err = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
- sizeof(valid_chan_list), false);
- if (err != 0) {
- ESCAN_ERROR(dev->name, "get channels failed with %d\n", err);
- goto exit;
+
+ if (channel) {
+ list->count = htod32(1);
+ list->element[0] = htod32(channel);
+ } else {
+ list->count = htod32(WL_NUMCHANNELS);
+ err = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
+ sizeof(valid_chan_list), false);
+ 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)
ESCAN_TRACE(dev->name, "Escan not permitted at this time (%d)\n", err);
else
ESCAN_ERROR(dev->name, "Escan set error (%d)\n", err);
- wl_escan_reset(escan);
}
kfree(params);
-exit:
if (unlikely(err)) {
/* Don't print Error incase of Scan suppress */
- if ((err == BCME_EPERM))
+ if (err == BCME_EPERM)
ESCAN_TRACE(dev->name, "Escan failed: Scan Suppressed\n");
else {
cnt++;
cnt = 0;
escan->dev = dev;
}
+exit:
+ if (unlikely(err)) {
+ wl_escan_reset(escan);
+ }
exit2:
mutex_unlock(&escan->usr_sync);
return err;
char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
int16 rssi;
int channel;
+ chanspec_t chanspec;
/* overflow check cover fields before wpa IEs */
if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
// terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
#endif
- channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
- ESCAN_SCAN(dev->name, "BSSID=%pM, channel=%3d, RSSI=%3d, SSID=\"%s\"\n",
- &bi->BSSID, channel, rssi, bi->SSID);
+ chanspec = wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec);
+ channel = wf_chspec_ctlchan(chanspec);
+ ESCAN_SCAN(dev->name, "BSSID %pM, channel %3d(%3d %sMHz), rssi %3d, SSID \"%s\"\n",
+ &bi->BSSID, channel, CHSPEC_CHANNEL(chanspec),
+ CHSPEC_IS20(chanspec)?"20":
+ CHSPEC_IS40(chanspec)?"40":
+ CHSPEC_IS80(chanspec)?"80":"160",
+ rssi, bi->SSID);
/* First entry must be the BSSID */
iwe.cmd = SIOCGIWAP;
#endif
char *buf = NULL;
struct ether_addr cur_bssid;
+ u8 ioctl_buf[WLC_IOCTL_SMLEN];
if (!extra) {
ESCAN_TRACE(dev->name, "extra is null\n");
ESCAN_SCAN(dev->name, "SIOCGIWSCAN, len=%d\n", dwrq->length);
+ wldev_iovar_getbuf(dev, "cur_etheraddr", NULL, 0, ioctl_buf, WLC_IOCTL_SMLEN, NULL);
err = wldev_ioctl(dev, WLC_GET_BSSID, &cur_bssid, sizeof(cur_bssid), false);
- if (err != BCME_NOTASSOCIATED && memcmp(ðer_null, &cur_bssid, ETHER_ADDR_LEN)) {
+ if (err != BCME_NOTASSOCIATED &&
+ memcmp(ðer_null, &cur_bssid, ETHER_ADDR_LEN) &&
+ memcmp(ioctl_buf, &cur_bssid, ETHER_ADDR_LEN)) {
// merge current connected bss
buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_ATOMIC);
if (!buf) {
mutex_unlock(&escan->usr_sync);
return err;
}
-#endif
+#endif /* WL_WIRELESS_EXT */
+
+#ifdef WLMESH
+bool
+wl_escan_meshid_ie(u8 *parse, u32 len, wlc_ssid_t *mesh_id)
+{
+ bcm_tlv_t *ie;
+
+ if((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_MESH_ID)) != NULL) {
+ mesh_id->SSID_len = ie->len;
+ if (ie->len) {
+ strncpy(mesh_id->SSID, ie->data, ie->len);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool
+wl_escan_rsn_ie(u8 *parse, u32 len)
+{
+ if (bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_RSN_ID)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool
+wl_escan_mesh_info_ie(struct net_device *dev, u8 *parse, u32 len,
+ struct wl_mesh_params *mesh_info)
+{
+ bcm_tlv_t *ie;
+ uchar mesh_oui[]={0x00, 0x22, 0xf4};
+ int totl_len;
+ uint8 *pie;
+ uint max_len;
+ bool found = FALSE;
+
+ memset(mesh_info, 0, sizeof(struct wl_mesh_params));
+ if((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID)) != NULL) {
+ totl_len = ie->len;
+ if (!memcmp(ie->data, &mesh_oui, sizeof(mesh_oui))) {
+ pie = ie->data + sizeof(mesh_oui);
+ ie = (bcm_tlv_t *)pie;
+ totl_len -= sizeof(mesh_oui);
+ while (totl_len > 2 && ie->len) {
+ if (ie->id == MESH_INFO_MASTER_BSSID && ie->len == ETHER_ADDR_LEN) {
+ memcpy(&mesh_info->master_bssid, ie->data, ETHER_ADDR_LEN);
+ } else if (ie->id == MESH_INFO_MASTER_CHANNEL) {
+ mesh_info->master_channel = ie->data[0];
+ found = TRUE;
+ } else if (ie->id == MESH_INFO_HOP_CNT) {
+ mesh_info->hop_cnt = ie->data[0];
+ } else if (ie->id == MESH_INFO_PEER_BSSID) {
+ max_len = min(MAX_HOP_LIST*ETHER_ADDR_LEN, (int)ie->len);
+ memcpy(mesh_info->peer_bssid, ie->data, max_len);
+ }
+ totl_len -= (ie->len + 2);
+ pie = ie->data + ie->len;
+ ie = (bcm_tlv_t *)pie;
+ }
+ }
+ }
+
+ return found;
+}
+
+bool
+wl_escan_mesh_info(struct net_device *dev, struct wl_escan_info *escan,
+ struct ether_addr *peer_bssid, struct wl_mesh_params *mesh_info)
+{
+ int i = 0;
+ wl_bss_info_t *bi = NULL;
+ struct wl_scan_results *bss_list;
+ int16 bi_rssi, bi_chan;
+ wlc_ssid_t bi_meshid;
+ bool is_mesh_peer = FALSE, found = FALSE;
+ struct wl_mesh_params peer_mesh_info;
+
+ mutex_lock(&escan->usr_sync);
+
+ /* Check for scan in progress */
+ if (escan->escan_state == ESCAN_STATE_SCANING) {
+ ESCAN_ERROR(dev->name, "SIOCGIWSCAN GET still scanning\n");
+ goto exit;
+ }
+ if (!escan->bss_list) {
+ ESCAN_ERROR(dev->name, "scan not ready\n");
+ goto exit;
+ }
+ if (dev != escan->dev) {
+ ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name);
+ goto exit;
+ }
+
+ bss_list = escan->bss_list;
+ bi = next_bss(bss_list, bi);
+ ESCAN_SCAN(dev->name, "scanned AP/Mesh count (%d)\n", bss_list->count);
+ for_each_bss(bss_list, bi, i)
+ {
+ memset(&bi_meshid, 0, sizeof(bi_meshid));
+ is_mesh_peer = FALSE;
+ bi_chan = wf_chspec_ctlchan(
+ wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
+ bi_rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
+ is_mesh_peer = wl_escan_meshid_ie(((u8*)bi)+bi->ie_offset,
+ bi->ie_length, &bi_meshid);
+ if (!(bi->capability & (DOT11_CAP_ESS|DOT11_CAP_IBSS)) && is_mesh_peer) {
+ bool bi_sae = FALSE, bss_found = FALSE, prefer = FALSE;
+ if (!memcmp(peer_bssid, &bi->BSSID, ETHER_ADDR_LEN)) {
+ bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length);
+ bss_found = wl_escan_mesh_info_ie(dev, ((u8*)bi)+bi->ie_offset,
+ bi->ie_length, &peer_mesh_info);
+ if (bss_found) {
+ memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+ ETHER_ADDR_LEN);
+ mesh_info->master_channel = peer_mesh_info.master_channel;
+ mesh_info->hop_cnt = peer_mesh_info.hop_cnt;
+ memcpy(mesh_info->peer_bssid, peer_mesh_info.peer_bssid,
+ sizeof(peer_mesh_info.peer_bssid));
+ prefer = TRUE;
+ found = TRUE;
+ }
+ }
+ ESCAN_SCAN(dev->name,
+ "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, "
+ "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n",
+ prefer?"*":" ", &bi->BSSID, bi_chan, bi_rssi, bi_sae?"SAE":"OPEN",
+ &peer_mesh_info.master_bssid, peer_mesh_info.master_channel,
+ peer_mesh_info.hop_cnt, &peer_mesh_info.peer_bssid, bi_meshid.SSID);
+ }
+ }
+
+exit:
+ mutex_unlock(&escan->usr_sync);
+ return found;
+}
+
+bool
+wl_escan_mesh_peer(struct net_device *dev, struct wl_escan_info *escan,
+ wlc_ssid_t *cur_ssid, uint16 cur_chan, bool sae,
+ struct wl_mesh_params *mesh_info)
+{
+ int i = 0;
+ wl_bss_info_t *bi = NULL;
+ struct wl_scan_results *bss_list;
+ int16 bi_rssi, bi_chan, max_rssi = -100;
+ uint min_hop_cnt = 255;
+ wlc_ssid_t bi_meshid;
+ bool is_mesh_peer = FALSE, chan_matched = FALSE, found = FALSE;
+ struct wl_mesh_params peer_mesh_info;
+
+ mutex_lock(&escan->usr_sync);
+
+ /* Check for scan in progress */
+ if (escan->escan_state == ESCAN_STATE_SCANING) {
+ ESCAN_ERROR(dev->name, "SIOCGIWSCAN GET still scanning\n");
+ goto exit;
+ }
+ if (!escan->bss_list) {
+ ESCAN_ERROR(dev->name, "scan not ready\n");
+ goto exit;
+ }
+ if (dev != escan->dev) {
+ ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name);
+ goto exit;
+ }
+
+ bss_list = escan->bss_list;
+ bi = next_bss(bss_list, bi);
+ ESCAN_SCAN(dev->name, "scanned AP/Mesh count (%d)\n", bss_list->count);
+ for_each_bss(bss_list, bi, i)
+ {
+ memset(&bi_meshid, 0, sizeof(bi_meshid));
+ is_mesh_peer = FALSE;
+ bi_chan = wf_chspec_ctlchan(
+ wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
+ bi_rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
+ is_mesh_peer = wl_escan_meshid_ie(((u8*)bi)+bi->ie_offset,
+ bi->ie_length, &bi_meshid);
+ if (!(bi->capability & (DOT11_CAP_ESS|DOT11_CAP_IBSS)) && is_mesh_peer) {
+ bool meshid_matched = FALSE, sec_matched = FALSE, bi_sae = FALSE,
+ bss_found = FALSE, prefer = FALSE;
+
+ if (cur_ssid->SSID_len && cur_ssid->SSID_len == bi_meshid.SSID_len &&
+ !memcmp(cur_ssid->SSID, bi_meshid.SSID, bi_meshid.SSID_len))
+ meshid_matched = TRUE;
+
+ bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length);
+ if (bi_sae == sae)
+ sec_matched = TRUE;
+
+ bss_found = wl_escan_mesh_info_ie(dev, ((u8*)bi)+bi->ie_offset, bi->ie_length,
+ &peer_mesh_info);
+ if (meshid_matched && sec_matched && bss_found &&
+ (cur_chan == bi_chan)) {
+ if (peer_mesh_info.hop_cnt < min_hop_cnt) {
+ memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+ ETHER_ADDR_LEN);
+ mesh_info->master_channel = peer_mesh_info.master_channel;
+ mesh_info->hop_cnt = peer_mesh_info.hop_cnt;
+ memcpy(mesh_info->peer_bssid, peer_mesh_info.peer_bssid,
+ sizeof(peer_mesh_info.peer_bssid));
+ min_hop_cnt = peer_mesh_info.hop_cnt;
+ prefer = TRUE;
+ chan_matched = TRUE;
+ found = TRUE;
+ }
+ }
+ else if (meshid_matched && sec_matched && bss_found &&
+ (cur_chan != bi_chan) && !chan_matched) {
+ if (bi_rssi > max_rssi) {
+ memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+ ETHER_ADDR_LEN);
+ mesh_info->master_channel = peer_mesh_info.master_channel;
+ mesh_info->hop_cnt = peer_mesh_info.hop_cnt;
+ memcpy(mesh_info->peer_bssid, peer_mesh_info.peer_bssid,
+ sizeof(peer_mesh_info.peer_bssid));
+ max_rssi = bi_rssi;
+ prefer = TRUE;
+ found = TRUE;
+ }
+ }
+
+ ESCAN_SCAN(dev->name,
+ "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, "
+ "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n",
+ prefer?"*":" ", &bi->BSSID, bi_chan, bi_rssi, bi_sae?"SAE":"OPEN",
+ &peer_mesh_info.master_bssid, peer_mesh_info.master_channel,
+ peer_mesh_info.hop_cnt, &peer_mesh_info.peer_bssid, bi_meshid.SSID);
+ } else {
+ ESCAN_SCAN(dev->name,
+ "[AP] BSSID=%pM, channel=%d, RSSI=%d, SSID=\"%s\"\n",
+ &bi->BSSID, bi_chan, bi_rssi, bi->SSID);
+ }
+ }
+
+exit:
+ mutex_unlock(&escan->usr_sync);
+ return found;
+}
+#endif /* WLMESH */
static void
wl_escan_deinit(struct net_device *dev, struct wl_escan_info *escan)
return ret;
}
- wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2);
+ wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler);
return 0;
}
return ret;
}
- ret = wl_ext_event_register(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2,
+ ret = wl_ext_event_register(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler,
escan, PRIO_EVENT_ESCAN);
if (ret) {
ESCAN_ERROR(dev->name, "wl_ext_event_register err %d\n", ret);
kfree(escan->escan_ioctl_buf);
escan->escan_ioctl_buf = NULL;
}
- wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2);
+ wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler);
DHD_OS_PREFREE(dhdp, escan, sizeof(struct wl_escan_info));
dhdp->escan = NULL;
\r
#ifndef _wl_escan_\r
#define _wl_escan_\r
+#include <linuxver.h>\r
#include <wl_iw.h>\r
\r
#define ESCAN_BUF_SIZE (64 * 1024)\r
typedef struct wl_escan_info {\r
struct net_device *dev;\r
dhd_pub_t *pub;\r
- struct timer_list scan_timeout; /* Timer for catch scan event timeout */\r
+ timer_list_compat_t scan_timeout; /* Timer for catch scan event timeout */\r
int escan_state;\r
int ioctl_ver;\r
u8 escan_buf[ESCAN_BUF_SIZE];\r
struct wl_scan_results *bss_list;\r
struct ether_addr disconnected_bssid;\r
u8 *escan_ioctl_buf;\r
- struct mutex usr_sync; /* maily for up/down synchronization */\r
+ struct mutex usr_sync; /* maily for up/down synchronization */\r
int autochannel;\r
int best_2g_ch;\r
int best_5g_ch;\r
#endif\r
} wl_escan_info_t;\r
\r
+#if defined(WLMESH)\r
+enum mesh_info_id {\r
+ MESH_INFO_MASTER_BSSID = 1,\r
+ MESH_INFO_MASTER_CHANNEL,\r
+ MESH_INFO_HOP_CNT,\r
+ MESH_INFO_PEER_BSSID\r
+};\r
+\r
+#define MAX_HOP_LIST 10\r
+typedef struct wl_mesh_params {\r
+ struct ether_addr master_bssid;\r
+ uint16 master_channel;\r
+ uint hop_cnt;\r
+ struct ether_addr peer_bssid[MAX_HOP_LIST];\r
+ uint16 scan_channel;\r
+} wl_mesh_params_t;\r
+bool wl_escan_mesh_info(struct net_device *dev,\r
+ struct wl_escan_info *escan, struct ether_addr *peer_bssid,\r
+ struct wl_mesh_params *mesh_info);\r
+bool wl_escan_mesh_peer(struct net_device *dev,\r
+ struct wl_escan_info *escan, wlc_ssid_t *cur_ssid, uint16 cur_chan, bool sae,\r
+ struct wl_mesh_params *mesh_info);\r
+#endif /* WLMESH */\r
+\r
int wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp,\r
- wlc_ssid_t *ssid, bool bcast);\r
+ wlc_ssid_t *ssid, uint16 channel, bool bcast);\r
int wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp,\r
struct iw_request_info *info, struct iw_point *dwrq, char *extra);\r
-s32 wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan,\r
- const wl_event_msg_t *e, void *data);\r
int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp);\r
void wl_escan_detach(struct net_device *dev, dhd_pub_t *dhdp);\r
int wl_escan_event_attach(struct net_device *dev, dhd_pub_t *dhdp);\r
#define EVENT_TRACE(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_TRACE_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] EVENT-TRACE) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] EVENT-TRACE) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
#define EVENT_DBG(name, arg1, args...) \
do { \
if (android_msg_level & ANDROID_DBG_LEVEL) { \
- printk(KERN_ERR "[dhd-%s] EVENT-DBG) %s : " arg1, name, __func__, ## args); \
+ printk(KERN_INFO "[dhd-%s] EVENT-DBG) %s : " arg1, name, __func__, ## args); \
} \
} while (0)
struct net_device *dev = NULL;
struct event_handler_list *evt_node;
dhd_pub_t *dhd;
+ unsigned long flags = 0;
BCM_SET_CONTAINER_OF(event_params, work_data, struct wl_event_params, event_work);
DHD_EVENT_WAKE_LOCK(event_params->pub);
EVENT_TRACE(dev->name, "Unknown Event (%d): ignoring\n", e->etype);
goto fail;
}
- if (dhd->busstate == DHD_BUS_DOWN) {
+ DHD_GENERAL_LOCK(dhd, flags);
+ if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {
EVENT_ERROR(dev->name, "BUS is DOWN.\n");
+ DHD_GENERAL_UNLOCK(dhd, flags);
goto fail;
}
+ DHD_GENERAL_UNLOCK(dhd, flags);
EVENT_DBG(dev->name, "event type (%d)\n", e->etype);
mutex_lock(&event_params->event_sync);
evt_node = event_params->evt_head.evt_head;
#define WL_TRACE_MSG(x, args...) \
do { \
if (iw_msg_level & WL_TRACE_LEVEL) { \
- printk(KERN_ERR "[dhd] WEXT-TRACE) %s : " x, __func__, ## args); \
+ printk(KERN_INFO "[dhd] WEXT-TRACE) %s : " x, __func__, ## args); \
} \
} while (0)
#define WL_SCAN_MSG(x, args...) \
do { \
if (iw_msg_level & WL_SCAN_LEVEL) { \
- printk(KERN_ERR "[dhd] WEXT-SCAN) %s : " x, __func__, ## args); \
+ printk(KERN_INFO "[dhd] WEXT-SCAN) %s : " x, __func__, ## args); \
} \
} while (0)
#define WL_WSEC_MSG(x, args...) \
do { \
if (iw_msg_level & WL_WSEC_LEVEL) { \
- printk(KERN_ERR "[dhd] WEXT-WSEC) %s : " x, __func__, ## args); \
+ printk(KERN_INFO "[dhd] WEXT-WSEC) %s : " x, __func__, ## args); \
} \
} while (0)
#define WL_ERROR(x) WL_ERROR_MSG x
typedef struct iscan_info {
struct net_device *dev;
- struct timer_list timer;
+ timer_list_compat_t timer;
uint32 timer_ms;
uint32 timer_on;
int iscan_state;
}
#endif /* WIRELESS_EXT > 12 */
-#define WL_PM_ENABLE_TIMEOUT 10000
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
- 4 && __GNUC_MINOR__ >= 6))
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
-_Pragma("GCC diagnostic push") \
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
-entry = container_of((ptr), type, member); \
-_Pragma("GCC diagnostic pop")
-#else
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
-entry = container_of((ptr), type, member);
-#endif /* STRICT_GCC_WARNINGS */
-
-void wl_ext_pm_work_handler(struct work_struct *work)
-{
- struct wl_wext_info *wext_info;
- s32 pm = PM_FAST;
- dhd_pub_t *dhd;
- int ret = 0;
-
- BCM_SET_CONTAINER_OF(wext_info, work, struct wl_wext_info, pm_enable_work.work);
-
- WL_TRACE(("%s: Enter\n", __FUNCTION__));
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
- 4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-
- dhd = (dhd_pub_t *)(wext_info->dhd);
- if (!dhd || !wext_info->dhd->up) {
- WL_TRACE(("%s: dhd is null or not up\n", __FUNCTION__));
- return;
- }
- if (dhd_conf_get_pm(dhd) >= 0)
- pm = dhd_conf_get_pm(dhd);
- ret = dev_wlc_ioctl(wext_info->dev, WLC_SET_PM, &pm, sizeof(pm));
- if (ret)
- WL_ERROR(("%s: WLC_SET_PM failed %d\n", __FUNCTION__, ret));
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
- 4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
- DHD_PM_WAKE_UNLOCK(wext_info->dhd);
-
-}
-
-void wl_ext_add_remove_pm_enable_work(struct wl_wext_info *wext_info,
- bool add)
-{
- u16 wq_duration = 0;
- s32 pm = PM_OFF;
- int ret = 0;
-
- if (wext_info == NULL || wext_info->dhd == NULL)
- return;
-
- mutex_lock(&wext_info->pm_sync);
- /*
- * Make cancel and schedule work part mutually exclusive
- * so that while cancelling, we are sure that there is no
- * work getting scheduled.
- */
-
- if (delayed_work_pending(&wext_info->pm_enable_work)) {
- cancel_delayed_work_sync(&wext_info->pm_enable_work);
- DHD_PM_WAKE_UNLOCK(wext_info->dhd);
- }
-
- if (add) {
- wq_duration = (WL_PM_ENABLE_TIMEOUT);
- }
-
- /* It should schedule work item only if driver is up */
- if (wq_duration && wext_info->dhd->up) {
- if (dhd_conf_get_pm(wext_info->dhd) >= 0)
- pm = dhd_conf_get_pm(wext_info->dhd);
- ret = dev_wlc_ioctl(wext_info->dev, WLC_SET_PM, &pm, sizeof(pm));
- if (ret)
- WL_ERROR(("%s: WLC_SET_PM failed %d\n", __FUNCTION__, ret));
- if (schedule_delayed_work(&wext_info->pm_enable_work,
- msecs_to_jiffies((const unsigned int)wq_duration))) {
- DHD_PM_WAKE_LOCK_TIMEOUT(wext_info->dhd, wq_duration);
- } else {
- WL_ERROR(("%s: Can't schedule pm work handler\n", __FUNCTION__));
- }
- }
- mutex_unlock(&wext_info->pm_sync);
-
-}
-
static void
wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status)
{
cur_eapol_status = dhd->conf->eapol_status;
if (status == WL_EXT_STATUS_CONNECTING) {
- wl_ext_add_remove_pm_enable_work(wext_info, TRUE);
+#ifdef WL_EXT_IAPSTA
+ wl_ext_add_remove_pm_enable_work(dev, TRUE);
+#endif /* WL_EXT_IAPSTA */
if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &wpa_auth))) {
WL_ERROR(("wpa_auth get error %d\n", error));
return;
dhd->conf->eapol_status = EAPOL_STATUS_NONE;
} else if (status == WL_EXT_STATUS_ADD_KEY) {
dhd->conf->eapol_status = EAPOL_STATUS_4WAY_DONE;
+ wake_up_interruptible(&dhd->conf->event_complete);
} else if (status == WL_EXT_STATUS_DISCONNECTING) {
- wl_ext_add_remove_pm_enable_work(wext_info, FALSE);
+#ifdef WL_EXT_IAPSTA
+ wl_ext_add_remove_pm_enable_work(dev, FALSE);
+#endif /* WL_EXT_IAPSTA */
if (cur_eapol_status >= EAPOL_STATUS_4WAY_START &&
cur_eapol_status < EAPOL_STATUS_4WAY_DONE) {
WL_ERROR(("WPA failed at %d\n", cur_eapol_status));
cur_eapol_status < EAPOL_STATUS_4WAY_DONE) {
WL_ERROR(("WPA failed at %d\n", cur_eapol_status));
dhd->conf->eapol_status = EAPOL_STATUS_NONE;
+ wake_up_interruptible(&dhd->conf->event_complete);
} else if (cur_eapol_status >= EAPOL_STATUS_WSC_START &&
cur_eapol_status < EAPOL_STATUS_WSC_DONE) {
WL_ERROR(("WPS failed at %d\n", cur_eapol_status));
}
}
#endif
- return wl_escan_set_scan(dev, dhd, &ssid, TRUE);
+ return wl_escan_set_scan(dev, dhd, &ssid, 0, TRUE);
#else
iscan = &wext_info->iscan;
WL_TRACE(("%s: SIOCSIWSCAN iscan=%p\n", dev->name, iscan));
case WLC_E_DEAUTH:
case WLC_E_DISASSOC:
wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED);
- WL_MSG(dev->name, "disconnected with "MACSTR", event %d, reason %d\n",
+ WL_MSG_RLMT(dev->name, &e->addr, ETHER_ADDR_LEN,
+ "disconnected with "MACSTR", event %d, reason %d\n",
MAC2STR((u8 *)wrqu.addr.sa_data), event_type, reason);
break;
case WLC_E_DEAUTH_IND:
phy_noise = 0;
if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) {
- WL_ERROR(("WLC_GET_PHY_NOISE error=%d\n", res));
+ WL_TRACE(("WLC_GET_PHY_NOISE error=%d\n", res));
goto done;
}
memset(&scb_val, 0, sizeof(scb_val));
if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) {
- WL_ERROR(("WLC_GET_RSSI error=%d\n", res));
+ WL_TRACE(("WLC_GET_RSSI error=%d\n", res));
goto done;
}
#ifndef WL_ESCAN
static void
-wl_iw_timerfunc(unsigned long data)
+wl_iw_timerfunc(ulong data)
{
iscan_info_t *iscan = (iscan_info_t *)data;
-
iscan->timer_on = 0;
if (iscan->iscan_state != ISCAN_STATE_IDLE) {
WL_TRACE(("timer trigger\n"));
iscan->list_hdr = buf;
}
#endif
- wl_ext_add_remove_pm_enable_work(wext_info, FALSE);
wl_ext_event_deregister(dev, dhdp, WLC_E_LAST, wl_iw_event);
if (wext_info) {
kfree(wext_info);
/* Set up the timer */
iscan->timer_ms = 2000;
- init_timer_compat(&iscan->scan_timeout, wl_iw_timerfunc, iscan);
+ init_timer_compat(&iscan->timer, wl_iw_timerfunc, iscan);
sema_init(&iscan->sysioc_sem, 0);
init_completion(&iscan->sysioc_exited);
goto exit;
}
#endif
- mutex_init(&wext_info->pm_sync);
- INIT_DELAYED_WORK(&wext_info->pm_enable_work, wl_ext_pm_work_handler);
ret = wl_ext_event_register(dev, dhdp, WLC_E_LAST, wl_iw_event, dhdp->wext_info,
PRIO_EVENT_WEXT);
if (ret) {
WL_ERROR (("dhd is NULL\n"));
return;
}
- wl_ext_add_remove_pm_enable_work(wext_info, FALSE);
}
int
#include <dngl_stats.h>
#include <dhd.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+#define get_ds() (KERNEL_DS)
+#endif
+
#define WL_SCAN_PARAMS_SSID_MAX 10
#define GET_SSID "SSID="
#define GET_CHANNEL "CH="
} wl_iw_t;
struct wl_ctrl {
- struct timer_list *timer;
+ timer_list_compat_t *timer;
struct net_device *dev;
long sysioc_pid;
struct semaphore sysioc_sem;
#define htodchanspec(i) (i)
#define dtohchanspec(i) (i)
-#define WLDEV_ERROR(args) \
- do { \
- printk(KERN_ERR "WLDEV-ERROR) "); \
- printk args; \
+#define WLDEV_ERROR_MSG(x, args...) \
+ do { \
+ printk(KERN_INFO "[dhd] WLDEV-ERROR) " x, ## args); \
} while (0)
+#define WLDEV_ERROR(x) WLDEV_ERROR_MSG x
-#define WLDEV_INFO(args) \
- do { \
- printk(KERN_INFO "WLDEV-INFO) "); \
- printk args; \
+#define WLDEV_INFO_MSG(x, args...) \
+ do { \
+ printk(KERN_INFO "[dhd] WLDEV-INFO) " x, ## args); \
} while (0)
+#define WLDEV_INFO(x) WLDEV_INFO_MSG x
extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd);