DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8
# DHDCFLAGS += -DHOSTAPD_BW_SUPPORT
-# DHDCFLAGS += -DHOSTAPD_EID_EXTENSION_SUPPORT
DHDCFLAGS += -DWL_VIRTUAL_APSTA -DSTA_MGMT
DHDCFLAGS += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP
DHDCFLAGS += -DDHD_USE_SCAN_WAKELOCK
DHDCFLAGS += -DWL_IFACE_MGMT
DHDCFLAGS += -DSUPPORT_RSSI_SUM_REPORT
DHDCFLAGS += -DWLFBT -DWL_GCMP_SUPPORT -DWL_OWE
- DHDCFLAGS += -DROAM_CHANNEL_CACHE -DDHD_LOSSLESS_ROAMING -DWL_ROAM_WAR
-# DHDCFLAGS += -DVNDR_IE_WAR -DGET_FW_IE_DATA
+ DHDCFLAGS += -DROAM_CHANNEL_CACHE -DDHD_LOSSLESS_ROAMING
# DHDCFLAGS += -DWL_CFGVENDOR_SEND_HANG_EVENT
DHDCFLAGS += -DGTK_OFFLOAD_SUPPORT
- DHDCFLAGS += -DRESTART_AP_WAR
- DHDCFLAGS += -DWL_STATIC_IF
+ DHDCFLAGS += -DWL_STATIC_IF #-DDHD_MAX_STATIC_IFS=2
DHDCFLAGS += -DWL_CLIENT_SAE
+ DHDCFLAGS += -DCONNECT_INFO_WAR -DWL_ROAM_WAR
+ DHDCFLAGS += -DVNDR_IE_WAR
+ DHDCFLAGS += -DRESTART_AP_WAR -DRXF0OVFL_REINIT_WAR
endif
#BCMDHD_SDIO
-DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DBCMSDIOH_STATIC_COPY_BUF \
-DRXFRAME_THREAD -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS \
-DBCMSDIO_RXLIM_POST -DBCMSDIO_TXSEQ_SYNC -DCONSOLE_DPC \
- -DBCMSDIO_INTSTATUS_WAR -DMMC_SW_RESET -DMMC_HW_RESET
+ -DBCMSDIO_INTSTATUS_WAR
+DHDCFLAGS += -DMMC_HW_RESET -DMMC_SW_RESET #-DBUS_POWER_RESTORE
ifeq ($(CONFIG_BCMDHD_OOB),y)
DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB
ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y)
DHDCFLAGS += -DPKT_STATICS
DHDCFLAGS += -DKSO_DEBUG
# DHDCFLAGS += -DDHD_PKTDUMP_TOFW
+# DHDCFLAGS += -DDHD_DUMP_FILE_WRITE_FROM_KERNEL
endif
# For Debug2
else
DHDCFLAGS += -DDHD_SUPPORT_VFS_CALL
ifeq ($(CONFIG_BCMDHD_FW_PATH),)
- DHDCFLAGS += -DCONFIG_BCMDHD_FW_PATH="\"/system/etc/firmware/fw_bcmdhd.bin\""
- DHDCFLAGS += -DCONFIG_BCMDHD_NVRAM_PATH="\"/system/etc/firmware/nvram.txt\""
- DHDCFLAGS += -DCONFIG_BCMDHD_CLM_PATH="\"/system/etc/firmware/clm_bcmdhd.blob\""
+ DHDCFLAGS += -DCONFIG_BCMDHD_FW_PATH="\"/vendor/etc/firmware/fw_bcmdhd.bin\""
+ DHDCFLAGS += -DCONFIG_BCMDHD_NVRAM_PATH="\"/vendor/etc/firmware/nvram.txt\""
+ DHDCFLAGS += -DCONFIG_BCMDHD_CLM_PATH="\"/vendor/etc/firmware/clm_bcmdhd.blob\""
endif
endif
endif
DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF
DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF
+ifneq ($(filter -DDHD_LOG_DUMP, $(DHDCFLAGS)),)
+ DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP
+endif
+ifneq ($(filter -DDHD_FW_COREDUMP, $(DHDCFLAGS)),)
DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP
+endif
ifneq ($(CONFIG_BCMDHD_PCIE),)
DHDCFLAGS += -DDHD_USE_STATIC_CTRLBUF
endif
#ifdef WL_TWT
BCMEVENT_NAME(WLC_E_TWT),
#endif /* WL_TWT */
+ BCMEVENT_NAME(WLC_E_AMT),
+ BCMEVENT_NAME(WLC_E_ROAM_SCAN_RESULT),
+#if defined(XRAPI)
+ BCMEVENT_NAME(WLC_E_XR_SOFTAP_PSMODE),
+#endif /* XRAPI */
+#ifdef WL_SIB_COEX
+ BCMEVENT_NAME(WLC_E_SIB),
+#endif /* WL_SIB_COEX */
+ BCMEVENT_NAME(WLC_E_MSCS),
+ BCMEVENT_NAME(WLC_E_RXDMA_RECOVERY_ATMPT),
+#ifdef WL_SCHED_SCAN
+ BCMEVENT_NAME(WLC_E_PFN_PARTIAL_RESULT),
+#endif /* WL_SCHED_SCAN */
+ BCMEVENT_NAME(WLC_E_MLO_LINK_INFO),
+ BCMEVENT_NAME(WLC_E_C2C),
+ BCMEVENT_NAME(WLC_E_BCN_TSF),
+ BCMEVENT_NAME(WLC_E_OWE_INFO),
+ BCMEVENT_NAME(WLC_E_ULMU_DISABLED_REASON_UPD),
};
const char *bcmevent_get_name(uint event_type)
static void IRQHandlerF2(struct sdio_func *func);
#endif /* !defined(OOB_INTR_ONLY) */
static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
-#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE)
+#if defined(ENABLE_INSMOD_NO_FW_LOAD)
#if defined(MMC_SW_RESET) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
extern int mmc_sw_reset(struct mmc_card *card);
#else
extern int mmc_hw_reset(struct mmc_host *host);
#endif
+#elif defined(BUS_POWER_RESTORE) && \
+LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
+#undef MMC_SW_RESET
+#undef MMC_HW_RESET
#else
extern int sdio_reset_comm(struct mmc_card *card);
#endif
}
#endif /* NOTUSED */
-#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE)
+#if defined(ENABLE_INSMOD_NO_FW_LOAD)
static int sdio_sw_reset(sdioh_info_t *sd)
{
struct mmc_card *card = sd->func[0]->card;
err = mmc_hw_reset(card->host);
#endif
sdio_release_host(sd->func[0]);
+#elif defined(BUS_POWER_RESTORE) && \
+LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
+ printf("%s: call mmc_power_restore_host\n", __FUNCTION__);
+ mmc_power_restore_host(card->host);
#else
/* sdio_reset_comm */
err = sdio_reset_comm(card);
2.6.27. The implementation prior to that is buggy, and needs broadcom's
patch for it
*/
-#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE)
+#if defined(ENABLE_INSMOD_NO_FW_LOAD)
if ((ret = sdio_sw_reset(sd))) {
sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
return ret;
else
sd_err(("%s Failed\n", __FUNCTION__));
#endif /* defined(OEM_ANDROID) */
+#if !defined(MMC_SW_RESET) && !defined(MMC_HW_RESET)
+#if defined(BUS_POWER_RESTORE) && \
+LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
+ if (sd->func[0]) {
+ struct mmc_card *card = sd->func[0]->card;
+ printf("%s: call mmc_power_save_host\n", __FUNCTION__);
+ mmc_power_save_host(card->host);
+ }
+#endif
+#endif
#if !defined(OOB_INTR_ONLY)
sdio_claim_host_unlock_local(sd);
#endif
if (bus->dhd->up == FALSE) {
return BCME_OK;
}
-
+
dlneeded = dbus_dlneeded(bus);
if (dlneeded == 0) {
ret = dbus_up(bus);
cur_pkt = *pkt;
*pkt = NULL;
+ *pkt_count = 0;
ptr = dhd->reorder_bufs[flow_id];
if (flags & WLHOST_REORDERDATA_DEL_FLOW) {
__FUNCTION__, flow_id));
if (ptr == NULL) {
- DHD_REORDER(("%s: received flags to cleanup, but no flow (%d) yet\n",
+ DHD_ERROR(("%s: received flags to cleanup, but no flow (%d) yet\n",
__FUNCTION__, flow_id));
- *pkt_count = 1;
- *pkt = cur_pkt;
+ if (cur_pkt) {
+ *pkt_count = 1;
+ *pkt = cur_pkt;
+ }
return 0;
}
ptr->exp_idx, ptr->exp_idx);
/* set it to the last packet */
if (plast) {
- PKTSETNEXT(dhd->osh, plast, cur_pkt);
- cnt++;
+ if (cur_pkt) {
+ PKTSETNEXT(dhd->osh, plast, cur_pkt);
+ cnt++;
+ }
}
else {
if (cnt != 0) {
DHD_ERROR(("%s: del flow: something fishy, pending packets %d\n",
__FUNCTION__, cnt));
}
- *pkt = cur_pkt;
- cnt = 1;
+ if (cur_pkt) {
+ *pkt = cur_pkt;
+ cnt = 1;
+ } else {
+ cnt = 0;
+ }
}
buf_size += ((ptr->max_idx + 1) * sizeof(void *));
MFREE(dhd->osh, ptr, buf_size);
ptr = (struct reorder_info *)MALLOC(dhd->osh, buf_size_alloc);
if (ptr == NULL) {
DHD_ERROR(("%s: Malloc failed to alloc buffer\n", __FUNCTION__));
- *pkt_count = 1;
+ if (cur_pkt) {
+ *pkt = cur_pkt;
+ *pkt_count = 1;
+ }
return 0;
}
bzero(ptr, buf_size_alloc);
ptr->p[ptr->cur_idx] = cur_pkt;
ptr->pend_pkts++;
*pkt_count = cnt;
+ /* Corner case: wrong BA WSIZE make 'cur < exp' with FLUSH */
+ if ((ptr->cur_idx < ptr->exp_idx) ||
+ (WLHOST_REORDERDATA_FLUSH_ALL & flags)) {
+ cur_idx = ptr->cur_idx;
+ exp_idx = ptr->exp_idx;
+ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
+ cur_idx, exp_idx);
+ *pkt_count = cnt;
+ DHD_ERROR(("%s: *Warning, new+flush, out=%d, pending=%d\n",
+ __FUNCTION__, cnt, ptr->pend_pkts));
+ }
}
else if (flags & WLHOST_REORDERDATA_CURIDX_VALID) {
cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET];
DHD_REORDER(("%s: got the right one now, cur_idx is %d\n",
__FUNCTION__, cur_idx));
if (ptr->p[cur_idx] != NULL) {
- DHD_REORDER(("%s: Error buffer pending..free it\n",
+ DHD_ERROR(("%s: Error buffer pending..free it\n",
__FUNCTION__));
PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE);
ptr->p[cur_idx] = NULL;
PKTSETNEXT(dhd->osh, plast, cur_pkt);
else
*pkt = cur_pkt;
- cnt++;
+ if (cur_pkt) {
+ cnt++;
+ }
}
else {
ptr->p[cur_idx] = cur_pkt;
PKTSETNEXT(dhd->osh, plast, cur_pkt);
else
*pkt = cur_pkt;
- cnt++;
+ if (cur_pkt) {
+ cnt++;
+ }
*pkt_count = cnt;
/* set the new expected idx */
ptr->exp_idx = exp_idx;
DHD_EVENT(("MACEVENT: %s, type:%d\n", event_name, reason));
break;
#endif /* WL_TWT */
+ case WLC_E_COUNTRY_CODE_CHANGED:
+ DHD_EVENT(("MACEVENT: %s: Country code changed to %s\n", event_name,
+ (char*)event_data));
+ break;
+ case WLC_E_OWE_INFO:
+ DHD_EVENT(("MACEVENT: %s, MAC %s type:%d\n", event_name, eabuf, reason));
+ break;
default:
DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
event_name, event_type, eabuf, (int)status, (int)reason,
}
}
#endif
+
+bool
+dhd_conf_legacy_otp_chip(dhd_pub_t *dhd)
+{
+ uint chip;
+
+ chip = dhd->conf->chip;
+
+ if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
+ chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
+ chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
+ chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
+ chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
+ chip == BCM4371_CHIP_ID ||
+ chip == BCM43430_CHIP_ID ||
+ chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
+ chip == BCM4359_CHIP_ID || chip == BCM43012_CHIP_ID ||
+ chip == BCM43751_CHIP_ID || chip == BCM43752_CHIP_ID) {
+ return true;
+ }
+
+ return false;
+}
#endif
#ifdef BCMPCIE
#endif
const chip_name_map_t *row_chip = NULL;
char *name = NULL;
-
+
#if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME)
row_module = dhd_conf_match_module(dhd);
if (row_module && strlen(row_module->module_name)) {
return bcmerror;
}
-int
+static int
dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec)
{
int bcmerror = -1;
+ struct net_device *net;
+ int bytes_written = 0;
+ char event_msg[32];
memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));
+ net = dhd_idx2net(dhd, 0);
+ snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 0", WLC_E_COUNTRY_CODE_CHANGED);
+ wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written);
+
CONFIG_MSG("set country %s, revision %d\n", cspec->ccode, cspec->rev);
bcmerror = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "country", (char *)cspec,
sizeof(wl_country_t), FALSE);
CONFIG_MSG("Country code: %s (%s/%d)\n",
cspec->country_abbrev, cspec->ccode, cspec->rev);
+ snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 1", WLC_E_COUNTRY_CODE_CHANGED);
+ wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written);
+
return bcmerror;
}
strlcpy(cspec.country_abbrev, buf, WL_CCODE_LEN + 1);
strlcpy(cspec.ccode, buf, WL_CCODE_LEN + 1);
dhd_conf_map_country_list(dhd, &cspec);
- if (!memcmp(&cspec.ccode, &cur_cspec.ccode, WL_CCODE_LEN + 1) &&
+ if (!memcmp(&cspec.ccode, &cur_cspec.ccode, WL_CCODE_LEN) &&
(cspec.rev == cur_cspec.rev)) {
CONFIG_MSG("country code = %s/%d is already configured\n",
cspec.ccode, cspec.rev);
return err;
}
+int
+dhd_conf_autocountry(dhd_pub_t *dhd, char *cmd, char *buf)
+{
+ struct net_device *net;
+ int bytes_written = 0;
+ char event_msg[32];
+ int enable = 0;
+
+ if (buf) {
+ sscanf(buf, "%d", &enable);
+ }
+
+ net = dhd_idx2net(dhd, 0);
+ snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 0", WLC_E_COUNTRY_CODE_CHANGED);
+ wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written);
+
+ CONFIG_MSG("autocountry %d\n", enable);
+ dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "autocountry", enable, 0, FALSE);
+
+ snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 1", WLC_E_COUNTRY_CODE_CHANGED);
+ wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written);
+
+ dhd_conf_country(dhd, "country", dhd->conf->cspec.country_abbrev);
+
+ return 0;
+}
+
typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *name, char *buf);
typedef struct iovar_tpl_t {
{WLC_SET_VAR, "scanmac", dhd_conf_scan_mac},
#endif
{WLC_SET_VAR, "country", dhd_conf_country},
+ {WLC_SET_VAR, "autocountry", dhd_conf_autocountry},
};
static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,
goto err;
}
-#ifdef DHD_LINUX_STD_FW_API
- memblock_len = MAXSZ_CONFIG;
-#else
memblock_len = MAXSZ_CONFIG;
-#endif /* DHD_LINUX_STD_FW_API */
pick = MALLOC(dhd->osh, MAXSZ_BUF);
if (!pick) {
dhd_conf_set_intiovar(dhd, 0, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, FALSE);
dhd_conf_set_intiovar(dhd, 0, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE);
dhd_conf_set_bw_cap(dhd);
- dhd_conf_set_roam(dhd, 0);
#if defined(BCMPCIE)
dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "bus:deepsleep_disable",
}
}
#endif /* WLEASYMESH */
+#if defined(BCMSDIO) || defined(BCMPCIE)
#if defined(BCMSDIO)
if (conf->devid == BCM43751_CHIP_ID)
#elif defined(BCMPCIE)
dhd_conf_set_wl_cmd(dhd, he_features, TRUE);
}
}
+#endif
#ifdef UPDATE_MODULE_NAME
dhd_conf_compat_func(dhd);
#endif
conf->in4way = STA_NO_SCAN_IN4WAY | STA_WAIT_DISCONNECTED |
AP_WAIT_STA_RECONNECT;
if (conf->chip == BCM43752_CHIP_ID)
- conf->war = SET_CHAN_INCONN | FW_REINIT_INCSA | FW_REINIT_EMPTY_SCAN;
+ conf->war = SET_CHAN_INCONN | FW_REINIT_INCSA | FW_REINIT_EMPTY_SCAN |
+ FW_REINIT_RXF0OVFL;
else
conf->war = 0;
#ifdef P2P_AP_CONCURRENT
FW_REINIT_INCSA = (1 << (1)),
FW_REINIT_EMPTY_SCAN = (1 << (2)),
P2P_AP_MAC_CONFLICT = (1 << (3)),
- RESEND_EAPOL_PKT = (1 << (4))
+ RESEND_EAPOL_PKT = (1 << (4)),
+ FW_REINIT_RXF0OVFL = (1 << (5))
};
enum in4way_flags {
CONN_STATE_AUTH_SAE_M2 = 3,
CONN_STATE_AUTH_SAE_M3 = 4,
CONN_STATE_AUTH_SAE_M4 = 5,
- CONN_STATE_REQID = 6,
- CONN_STATE_RSPID = 7,
- CONN_STATE_WSC_START = 8,
- CONN_STATE_WPS_M1 = 9,
- CONN_STATE_WPS_M2 = 10,
- CONN_STATE_WPS_M3 = 11,
- CONN_STATE_WPS_M4 = 12,
- CONN_STATE_WPS_M5 = 13,
- CONN_STATE_WPS_M6 = 14,
- CONN_STATE_WPS_M7 = 15,
- CONN_STATE_WPS_M8 = 16,
- CONN_STATE_WSC_DONE = 17,
- CONN_STATE_4WAY_M1 = 18,
- CONN_STATE_4WAY_M2 = 19,
- CONN_STATE_4WAY_M3 = 20,
- CONN_STATE_4WAY_M4 = 21,
- CONN_STATE_ADD_KEY = 22,
- CONN_STATE_CONNECTED = 23,
- CONN_STATE_GROUPKEY_M1 = 24,
- CONN_STATE_GROUPKEY_M2 = 25,
+ CONN_STATE_ASSOCIATED = 6,
+ CONN_STATE_REQID = 7,
+ CONN_STATE_RSPID = 8,
+ CONN_STATE_WSC_START = 9,
+ CONN_STATE_WPS_M1 = 10,
+ CONN_STATE_WPS_M2 = 11,
+ CONN_STATE_WPS_M3 = 12,
+ CONN_STATE_WPS_M4 = 13,
+ CONN_STATE_WPS_M5 = 14,
+ CONN_STATE_WPS_M6 = 15,
+ CONN_STATE_WPS_M7 = 16,
+ CONN_STATE_WPS_M8 = 17,
+ CONN_STATE_WSC_DONE = 18,
+ CONN_STATE_4WAY_M1 = 19,
+ CONN_STATE_4WAY_M2 = 20,
+ CONN_STATE_4WAY_M3 = 21,
+ CONN_STATE_4WAY_M4 = 22,
+ CONN_STATE_ADD_KEY = 23,
+ CONN_STATE_CONNECTED = 24,
+ CONN_STATE_GROUPKEY_M1 = 25,
+ CONN_STATE_GROUPKEY_M2 = 26,
};
enum enq_pkt_type {
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);
+bool dhd_conf_legacy_otp_chip(dhd_pub_t *dhd);
#endif
#ifdef BCMPCIE
int dhd_conf_get_otp(dhd_pub_t *dhd, si_t *sih);
uint dhd_conf_get_insuspend(dhd_pub_t *dhd, uint mask);
int dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend);
void dhd_conf_postinit_ioctls(dhd_pub_t *dhd);
-#ifdef WL_STATIC_IF
void dhd_conf_preinit_ioctls_sta(dhd_pub_t *dhd, int ifidx);
-#endif /* WL_STATIC_IF */
int dhd_conf_preinit(dhd_pub_t *dhd);
int dhd_conf_reset(dhd_pub_t *dhd);
int dhd_conf_attach(dhd_pub_t *dhd);
*/
while (*data != '\0' && (s = strstr(data, "\n")) != NULL) {
*s = '\0';
- DHD_FWLOG(("[FWLOG] %s\n", data));
+ printf("[FWLOG] %s\n", data);
data = s+1;
}
if (*data)
- DHD_FWLOG(("[FWLOG] %s", data));
+ printf("[FWLOG] %s", data);
}
#ifdef SHOW_LOGTRACE
#define DATA_UNIT_FOR_LOG_CNT 4
#include <linux/platform_device.h>
#endif
-#if defined(BUS_POWER_RESTORE) && defined(BCMSDIO)
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio_func.h>
-#endif /* defined(BUS_POWER_RESTORE) && defined(BCMSDIO) */
-
#ifdef CONFIG_DHD_USE_STATIC_BUF
-#ifdef DHD_STATIC_IN_DRIVER
-extern int dhd_static_buf_init(void);
-extern void dhd_static_buf_exit(void);
-#endif /* DHD_STATIC_IN_DRIVER */
#if defined(BCMDHD_MDRIVER) && !defined(DHD_STATIC_IN_DRIVER)
extern void *bcmdhd_mem_prealloc(uint bus_type, int index,
int section, unsigned long size);
#endif
#endif
#ifdef BUS_POWER_RESTORE
-#ifdef BCMSDIO
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
- if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
- mdelay(100);
- printf("======== mmc_power_restore_host! ========\n");
- mmc_power_restore_host(adapter->sdio_func->card->host);
- }
-#endif
-#elif defined(BCMPCIE)
+#ifdef BCMPCIE
if (adapter->pci_dev) {
mdelay(100);
printf("======== pci_set_power_state PCI_D0! ========\n");
/* Lets customer power to get stable */
} else {
#ifdef BUS_POWER_RESTORE
-#ifdef BCMSDIO
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
- if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
- printf("======== mmc_power_save_host! ========\n");
- mmc_power_save_host(adapter->sdio_func->card->host);
- }
-#endif
-#elif defined(BCMPCIE)
+#ifdef BCMPCIE
if (adapter->pci_dev) {
printf("======== pci_set_power_state PCI_D3hot! ========\n");
pci_save_state(adapter->pci_dev);
{
int err = 0;
-#if !defined(BUS_POWER_RESTORE)
if (present) {
#if defined(BCMSDIO)
printf("======== Card detection to detect SDIO card! ========\n");
#endif
#endif
}
-#endif /* BUS_POWER_RESTORE */
return err;
}
static int
dhd_wlan_get_mac_addr(unsigned char *buf, int ifidx)
{
- int err = 0;
+ int err = -1;
if (ifidx == 1) {
#ifdef EXAMPLE_GET_MAC
if (gpio_wl_reg_on >= 0) {
printf("%s: gpio_free(WL_REG_ON %d)\n", __FUNCTION__, gpio_wl_reg_on);
gpio_free(gpio_wl_reg_on);
- gpio_wl_reg_on = -1;
+ adapter->gpio_wl_reg_on = -1;
}
#ifdef CUSTOMER_OOB
if (gpio_wl_host_wake >= 0) {
printf("%s: gpio_free(WL_HOST_WAKE %d)\n", __FUNCTION__, gpio_wl_host_wake);
gpio_free(gpio_wl_host_wake);
- gpio_wl_host_wake = -1;
+ adapter->gpio_wl_host_wake = -1;
}
#endif /* CUSTOMER_OOB */
}
if (err)
goto exit;
-#ifdef DHD_STATIC_IN_DRIVER
- err = dhd_static_buf_init();
-#endif
-
exit:
return err;
}
void
dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter)
{
-#ifdef DHD_STATIC_IN_DRIVER
- dhd_static_buf_exit();
-#endif
dhd_wlan_deinit_gpio(adapter);
}
static void dhd_natoe_ct_ioctl_handler(void *handle, void *event_info, uint8 event);
#endif /* WL_NATOE */
+#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER)
+extern int dhd_static_buf_init(void);
+extern void dhd_static_buf_exit(void);
+#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */
#ifdef DHD_UPDATE_INTF_MAC
static void dhd_ifupdate_event_handler(void *handle, void *event_info, u8 event);
#endif /* DHD_UPDATE_INTF_MAC */
static int
dhd_ioctl_entry_wrapper(struct net_device *net, struct ifreq *ifr,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
- void __user *data,
+ void __user *data,
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(5, 15, 0) */
int cmd)
{
if (dhd->rx_napi_netdev == NULL) {
dhd->rx_napi_netdev = dhd->iflist[ifidx]->net;
memset(&dhd->rx_napi_struct, 0, sizeof(struct napi_struct));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
+ netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct,
+ dhd_napi_poll);
+#else
netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct,
dhd_napi_poll, dhd_napi_weight);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) */
DHD_INFO(("%s napi<%p> enabled ifp->net<%p,%s> dhd_napi_weight: %d\n",
__FUNCTION__, &dhd->rx_napi_struct, net,
net->name, dhd_napi_weight));
uint32 apsta = 0;
int ap_mode = 1;
#endif /* (defined(AP) || defined(WLP2P)) && !defined(SOFTAP_AND_GC) */
-#ifdef GET_CUSTOM_MAC_ENABLE
struct ether_addr ea_addr;
char hw_ether[62];
-#endif /* GET_CUSTOM_MAC_ENABLE */
+ dhd_if_t *ifp = dhd->info->iflist[0];
+ bool set_mac = FALSE;
#ifdef OKC_SUPPORT
uint32 okc = 1;
#endif
}
#endif /* EVENT_LOG_RATE_HC */
-#ifdef GET_CUSTOM_MAC_ENABLE
memset(hw_ether, 0, sizeof(hw_ether));
- ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, 0);
-#ifdef GET_CUSTOM_MAC_FROM_CONFIG
- if (!memcmp(ðer_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) {
- ret = 0;
- } else
-#endif
- if (!ret) {
- memset(buf, 0, sizeof(buf));
+ if (ifp->set_macaddress) {
+ memcpy(hw_ether, ifp->mac_addr, ETHER_ADDR_LEN);
+ set_mac = TRUE;
+ }
+#ifdef GET_CUSTOM_MAC_ENABLE
#ifdef GET_CUSTOM_MAC_FROM_CONFIG
+ else if (!memcmp(ðer_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) {
+ set_mac = TRUE;
memcpy(hw_ether, &dhd->conf->hw_ether, sizeof(dhd->conf->hw_ether));
+ }
#endif
+ else {
+ ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, 0);
+ if (!ret)
+ set_mac = TRUE;
+ }
+#endif /* GET_CUSTOM_MAC_ENABLE */
+ if (set_mac) {
+ memset(buf, 0, sizeof(buf));
bcopy(hw_ether, ea_addr.octet, sizeof(struct ether_addr));
bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
goto done;
}
}
- } else {
+ }
+#ifdef GET_CUSTOM_MAC_ENABLE
+ else {
DHD_ERROR(("%s: can't get custom MAC address, ret=%d\n", __FUNCTION__, ret));
ret = BCME_NOTUP;
goto done;
// setbit(mask, WLC_E_TXFAIL); // terence 20181106: remove unnecessary event
#endif
setbit(mask, WLC_E_JOIN_START);
+ setbit(mask, WLC_E_OWE_INFO);
// setbit(mask, WLC_E_SCAN_COMPLETE); // terence 20150628: remove redundant event
#ifdef DHD_DEBUG
setbit(mask, WLC_E_SCAN_CONFIRM_IND);
wifi_teardown_dt();
#endif
#endif
+#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER)
+ dhd_static_buf_exit();
+#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */
printf("%s: Exit\n", __FUNCTION__);
}
PRINTF_SYSTEM_TIME, __FUNCTION__, dhd_version);
if (ANDROID_VERSION > 0)
printf("ANDROID_VERSION = %d\n", ANDROID_VERSION);
+#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER)
+ err = dhd_static_buf_init();
+ if (err) {
+ goto exit;
+ }
+#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */
#ifdef CUSTOMER_HW_AMLOGIC
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
if (wifi_setup_dt()) {
}
}
+#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER)
+exit:
+ if (err)
+ dhd_static_buf_exit();
+#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */
printf("%s: Exit err=%d\n", __FUNCTION__, err);
return err;
}
lock_active = (l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || l9 || l10);
/* Indicate to the Host to avoid going to suspend if internal locks are up */
+ DHD_ERROR(("%s wakelock c-%d wl-%d wd-%d rx-%d "
+ "ctl-%d intr-%d scan-%d evt-%d, pm-%d, txfl-%d nan-%d\n",
+ __FUNCTION__, c, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10));
if (lock_active) {
- DHD_ERROR(("%s wakelock c-%d wl-%d wd-%d rx-%d "
- "ctl-%d intr-%d scan-%d evt-%d, pm-%d, txfl-%d nan-%d\n",
- __FUNCTION__, c, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10));
return 1;
}
#elif defined(BCMSDIO)
DHD_INFO(("%s : Entered.\n", __FUNCTION__));
rcu_read_lock();
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0))
+ dev_maps = rcu_dereference(net->xps_maps[XPS_CPUS]);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
dev_maps = rcu_dereference(net->xps_cpus_map);
#else
dev_maps = rcu_dereference(net->xps_maps);
rcu_read_unlock();
if (dev_maps) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0))
+ RCU_INIT_POINTER(net->xps_maps[XPS_CPUS], NULL);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
RCU_INIT_POINTER(net->xps_cpus_map, NULL);
#else
RCU_INIT_POINTER(net->xps_maps, NULL);
if ((adapter->bus_type == -1 || adapter->bus_type == bus_type) &&
(adapter->bus_num == -1 || adapter->bus_num == bus_num) &&
(adapter->slot_num == -1 || adapter->slot_num == slot_num)
-#if defined(ENABLE_INSMOD_NO_FW_LOAD)
+#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(ENABLE_INSMOD_NO_POWER_OFF)
&& (wifi_chk_adapter_status(adapter, status))
#endif
) {
int i;
#endif
-#if !defined(DHD_PRELOAD)
+#if !defined(DHD_PRELOAD) && !defined(ENABLE_INSMOD_NO_POWER_OFF)
/* power down all adapters */
for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
adapter = &dhd_wifi_platdata->adapters[i];
#ifdef REPORT_FATAL_TIMEOUTS
uint16 dhd_xt_id;
#endif
+ int ret = 0;
/* Check for ioctl timeout induce flag, which is set by firing
* dhd iovar to induce IOCTL timeout. If flag is set,
pkt_id, xt_id, prot->ioctl_status, prot->ioctl_resplen));
if (prot->ioctl_resplen > 0) {
+ uint16 copy_len = MIN(prot->ioctl_resplen, prot->retbuf.len);
#ifndef IOCTLRESP_USE_CONSTMEM
- bcopy(PKTDATA(dhd->osh, pkt), prot->retbuf.va, prot->ioctl_resplen);
+ ret = memcpy_s(prot->retbuf.va, prot->retbuf.len, PKTDATA(dhd->osh, pkt), copy_len);
#else
- bcopy(pkt, prot->retbuf.va, prot->ioctl_resplen);
+ ret = memcpy_s(prot->retbuf.va, prot->retbuf.len, pkt, copy_len);
#endif /* !IOCTLRESP_USE_CONSTMEM */
+ if (ret) {
+ DHD_ERROR(("memcpy failed:%d, destsz:%d, n:%u\n",
+ ret, prot->retbuf.len, copy_len));
+ dhd_wakeup_ioctl_event(dhd, IOCTL_RETURN_ON_ERROR);
+ goto exit;
+ }
}
/* wake up any dhd_os_ioctl_resp_wait() */
} else {
nvram_uefi_exists = TRUE;
}
-#ifdef DHD_LINUX_STD_FW_API
- memblock_len = len;
-#else
memblock_len = MAX_NVRAMBUF_SIZE;
-#endif /* DHD_LINUX_STD_FW_API */
DHD_ERROR(("%s: dhd_get_download_buffer len %d\n", __FUNCTION__, len));
if (!bus) {
return ret;
}
+ if (bus->dhd->busstate == DHD_BUS_DOWN) {
+ return ret;
+ }
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 9))
/* On fc30 (linux ver 5.0.9),
static irqreturn_t wlan_oob_irq_isr(int irq, void *data)
{
dhd_bus_t *bus = (dhd_bus_t *)data;
- DHD_TRACE(("%s: IRQ ISR\n", __FUNCTION__));
+ DHD_INTR(("%s: IRQ ISR\n", __FUNCTION__));
bus->last_oob_irq_isr_time = OSL_LOCALTIME_NS();
return IRQ_WAKE_THREAD;
}
bus = (dhd_bus_t *)data;
dhdpcie_oob_intr_set(bus, FALSE);
#ifdef DHD_USE_PCIE_OOB_THREADED_IRQ
- DHD_TRACE(("%s: IRQ Thread\n", __FUNCTION__));
+ DHD_INTR(("%s: IRQ Thread\n", __FUNCTION__));
bus->last_oob_irq_thr_time = OSL_LOCALTIME_NS();
#else
- DHD_TRACE(("%s: IRQ ISR\n", __FUNCTION__));
+ DHD_INTR(("%s: IRQ ISR\n", __FUNCTION__));
bus->last_oob_irq_isr_time = OSL_LOCALTIME_NS();
#endif /* DHD_USE_PCIE_OOB_THREADED_IRQ */
real_pad = pkt_len - act_len;
if (PKTTAILROOM(osh, pkt) < real_pad) {
- DHD_INFO(("%s : insufficient tailroom %d for %d real_pad\n",
+ DHD_INFO(("%s : insufficient tailroom %d for %d real_pad\n",
__func__, (int)PKTTAILROOM(osh, pkt), real_pad));
if (PKTPADTAILROOM(osh, pkt, real_pad)) {
DHD_ERROR(("CHK1: padding error size %d\n", real_pad));
} else
frame = (uint8 *)PKTDATA(osh, pkt);
}
- } else
+ } else
#endif
{
swhdr_offset += SDPCM_HWEXT_LEN;
/* Check window for sanity */
if ((uint8)(txmax - bus->tx_seq) > 0x70) {
- DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
+ DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n",
__FUNCTION__, txmax, bus->tx_seq));
txmax = bus->tx_max;
}
txmax = bus->tx_seq + 2;
} else {
#endif /* BCMSPI */
- DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
+ DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n",
__FUNCTION__, txmax, bus->tx_seq));
txmax = bus->tx_max;
#ifdef BCMSPI
/* Check window for sanity */
if ((uint8)(txmax - bus->tx_seq) > 0x70) {
- DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
+ DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n",
__FUNCTION__, txmax, bus->tx_seq));
txmax = bus->tx_max;
}
DHD_INFO(("Function %d CIS:\n", fn));
for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
- if ((byte % 16) == 0)
- DHD_INFO((" "));
- DHD_INFO(("%02x ", cis[byte]));
- if ((byte % 16) == 15)
- DHD_INFO(("\n"));
if (!tdata--) {
tag = cis[byte];
if (tag == 0xff)
tdata = 0;
else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
tdata = cis[byte + 1] + 1;
- else
- DHD_INFO(("]"));
}
}
- if ((byte % 16) != 15)
- DHD_INFO(("\n"));
+ prhex(NULL, (const u8 *) cis, byte+1);
}
#endif /* DHD_DEBUG */
/* if firmware path present try to download and bring up bus */
bus->dhd->hang_report = TRUE;
-#if 0 // terence 20150325: fix for WPA/WPA2 4-way handshake fail in hostapd
+
+#if defined(BCMDHD_MODULAR) && defined(INSMOD_FW_LOAD)
+ if (1)
+#else
#if defined(LINUX) || defined(linux)
- if (dhd_download_fw_on_driverload) {
+ if (!dhd_conf_legacy_otp_chip(bus->dhd))
#endif /* LINUX || linux */
+#endif
+ {
if ((ret = dhd_bus_start(bus->dhd)) != 0) {
DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__));
#if !defined(OEM_ANDROID)
bus->dhd->mac.octet[2] = 0x4C;
}
#endif /* LINUX || linux */
-#endif
#if defined(BT_OVER_SDIO)
/* At this point Regulators are turned on and iconditionaly sdio bus is started
* based upon dhd_download_fw_on_driverload check, so
if (bcmerror != BCME_OK)
goto err;
-#ifdef DHD_LINUX_STD_FW_API
memblock_len = MAX_NVRAMBUF_SIZE;
-#else
- memblock_len = MAX_NVRAMBUF_SIZE;
-#endif /* DHD_LINUX_STD_FW_API */
if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
bufp = (char *)memblock;
#include <linux/amlogic/wlan_plat.h>
#include <linux/amlogic/dhd_buf.h>
-#define DHD_STATIC_VERSION_STR "101.10.361.28 (wlan=r892223-20221018-1)"
+#define DHD_STATIC_VERSION_STR "101.10.361.31 (wlan=r892223-20230427-1)"
#define STATIC_ERROR_LEVEL BIT(0)
#define STATIC_TRACE_LEVEL BIT(1)
#define STATIC_MSG_LEVEL BIT(0)
} \
} while (0)
-#ifdef DHD_STATIC_IN_DRIVER
-#if ANDROID_VERSION > 0
-#define CONFIG_BCMDHD_VTS { : = y}
-#define CONFIG_BCMDHD_DEBUG { : = y}
-#endif
-#else
+#ifndef DHD_STATIC_IN_DRIVER
+#ifndef BCMSDIO
#define BCMSDIO
+#endif
+#ifndef BCMPCIE
#define BCMPCIE
-//#define BCMDBUS
-#define CONFIG_BCMDHD_VTS { : = y}
-#define CONFIG_BCMDHD_DEBUG { : = y}
+#endif
+#ifndef BCMDBUS
+#define BCMDBUS
+#endif
#define DHD_USE_STATIC_MEMDUMP { : = y}
//#define BCMDHD_UNUSE_MEM
#endif
DHD_PREALLOC_IF_FLOW_LKUP = 9,
#endif /* BCMPCIE */
DHD_PREALLOC_MEMDUMP_BUF = 10,
-#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG)
+#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS)
DHD_PREALLOC_MEMDUMP_RAM = 11,
-#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */
+#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */
#if defined(BCMSDIO) || defined(BCMDBUS)
DHD_PREALLOC_DHD_WLFC_HANGER = 12,
#endif /* BCMSDIO | BCMDBUS */
#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 (43 * 1024)
-#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG)
+#define DHD_PREALLOC_DHD_INFO_SIZE (44 * 1024)
#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024)
-#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */
#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024)
#ifdef DHD_USE_STATIC_MEMDUMP
#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE \
return wlan_static_if_flow_lkup[index];
}
#endif /* BCMPCIE */
-#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG)
+#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS)
if (section == DHD_PREALLOC_MEMDUMP_RAM) {
if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) {
DHD_STATIC_ERROR("request DHD_PREALLOC_MEMDUMP_RAM(%lu) > %d\n",
}
return wlan_static_dhd_memdump_ram_buf[index];
}
-#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */
+#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */
#if defined(BCMSDIO) || defined(BCMDBUS)
if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {
if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {
#ifdef BCMPCIE
kfree(wlan_static_if_flow_lkup[index]);
#endif /* BCMPCIE */
-#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG)
+#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS)
kfree(wlan_static_dhd_memdump_ram_buf[index]);
-#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */
+#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */
#if defined(BCMSDIO) || defined(BCMDBUS)
kfree(wlan_static_dhd_wlfc_hanger_buf[index]);
#endif /* BCMSDIO | BCMDBUS */
#endif /* BCMPCIE */
}
-#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG)
+#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS)
wlan_static_dhd_memdump_ram_buf[index] = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL);
if (!wlan_static_dhd_memdump_ram_buf[index])
goto err_mem_alloc;
size += DHD_PREALLOC_MEMDUMP_RAM_SIZE;
DHD_STATIC_TRACE("section %d, size=%d\n",
DHD_PREALLOC_MEMDUMP_RAM, DHD_PREALLOC_MEMDUMP_RAM_SIZE);
-#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */
+#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */
if (buf_level > 0) {
#if defined(BCMSDIO) || defined(BCMDBUS)
break;
}
+#ifndef DHD_STATIC_IN_DRIVER
if (ret) {
for (i = 0; i < MAX_NUM_ADAPTERS; i++)
dhd_deinit_wlan_mem(i);
}
+#endif
return ret;
}
#define WLC_E_PFN_SCAN_ALLGONE_EXT 193 /* last found PFN network gets lost. */
#define WLC_E_AUTH_START 194 /* notify upper layer to start auth */
#define WLC_E_TWT 195 /* TWT event */
-#define WLC_E_LAST 196 /* highest val + 1 for range checking */
-#if (WLC_E_LAST > 196)
-#error "WLC_E_LAST: Invalid value for last event; must be <= 196."
+#define WLC_E_AMT 196 /* Address Management Table (AMT) */
+#define WLC_E_ROAM_SCAN_RESULT 197 /* roam/reassoc scan result event */
+
+#define WLC_E_MSCS 200 /* MSCS success/failure events */
+#define WLC_E_RXDMA_RECOVERY_ATMPT 201 /* RXDMA Recovery Attempted Event */
+#define WLC_E_PFN_PARTIAL_RESULT 202
+#define WLC_E_MLO_LINK_INFO 203 /* 11be MLO link information */
+#define WLC_E_C2C 204 /* Client to client (C2C) for 6GHz TX */
+#define WLC_E_BCN_TSF 205 /* Report Beacon TSF */
+#define WLC_E_OWE_INFO 206 /* OWE Information */
+#define WLC_E_ULMU_DISABLED_REASON_UPD 207 /* OMI ULMU disable reason code update */
+#define WLC_E_AMSDU_RX_WAKEUP 208 /* When amsdu deagg SM is stuck in D3 condition */
+#define WLC_E_LAST 209 /* highest val + 1 for range checking */
+#if (WLC_E_LAST > 209)
+#error "WLC_E_LAST: Invalid value for last event; must be <= 209."
#endif /* WLC_E_LAST */
/* define an API for getting the string name of an event */
#elif (defined (BCMDBG_ASSERT) && !defined (BCMDBG_ASSERT_DISABLED))
#define EPI_VERSION_STR "101.10.361 (wlan=r892223 ASSRT)"
#else
-#define EPI_VERSION_STR "101.10.361.28 (wlan=r892223-20221202-3)"
+#define EPI_VERSION_STR "101.10.361.32 (wlan=r892223-20230508-1)"
#endif /* BCMINTERNAL */
#endif /* _epivers_h_ */
uint8 tlvs[]; /* variable data (zero in for list ,clearall) */
} wl_filter_ie_iov_v1_t;
+#define WL_ASSOC_RESP_PARAMS_V1 (1u)
+typedef struct wl_assoc_resp_params_v1 {
+ uint16 version; /* Structure version */
+ uint16 len; /* Total length of the structure */
+ uint16 fixed_length; /* Total length of fixed fields */
+ uint8 mac_addr[ETHER_ADDR_LEN]; /* peer MAC address */
+ uint8 resp_ie_len; /* Assoc_resp IE's length */
+ uint8 pad; /* Pad for alignment */
+ uint16 status; /* AREQ status code from Host */
+ uint8 ies[]; /* Variable data (resp_ies) */
+} wl_assoc_resp_params_v1_t;
+
/* Event aggregation config */
#define EVENT_AGGR_CFG_VERSION 1
#define EVENT_AGGR_DISABLED 0x0
#endif /* BCMSDIO */
ret = dhd_dev_init_ioctl(dev);
if (ret < 0) {
- goto retry_bus;
+ goto retry_power;
}
#endif /* BCMSDIO || BCMDBUS */
if (ret == 0) {
break;
}
-#if defined(BCMSDIO) || defined(BCMDBUS)
-retry_bus:
-#ifdef BCMSDIO
- dhd_net_bus_suspend(dev);
-#endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMDBUS */
retry_power:
ANDROID_ERROR(("failed to power up wifi chip, retry again (%d left) **\n\n",
retry));
dhd_net_bus_devreset(dev, TRUE);
+#ifdef BCMSDIO
+ dhd_net_bus_suspend(dev);
+#endif /* BCMSDIO */
dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
#ifdef WBRC
/* Inform BT reset which will internally wait till BT reset is done */
goto done2;
}
+ chosen = wl_ext_autochannel(dev, ACS_DRV_BIT, band);
+ channel = wf_chspec_ctlchan(chosen);
+ if (channel) {
+ acs_band = CHSPEC_BAND(channel);
+ goto done2;
+ } else
+ goto done;
+
/* If AP is started on wlan0 iface,
* do not issue any iovar to fw and choose default ACS channel for softap
*/
}
}
- chosen = wl_ext_autochannel(dev, ACS_DRV_BIT, band);
- channel = wf_chspec_ctlchan(chosen);
- if (channel) {
- acs_band = CHSPEC_BAND(channel);
- goto done2;
- } else
- goto done;
-
ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
if (ret) {
ANDROID_ERROR(("ACS: error getting the spect, ret=%d\n", ret));
#ifdef ENABLE_INSMOD_NO_POWER_OFF
dhd_download_fw_on_driverload = TRUE;
-#elif defined(ENABLE_INSMOD_NO_FW_LOAD) || defined(BUS_POWER_RESTORE)
+#elif defined(ENABLE_INSMOD_NO_FW_LOAD)
dhd_download_fw_on_driverload = FALSE;
#endif /* ENABLE_INSMOD_NO_FW_LOAD */
if (!iface_name[0]) {
{WL_AUTH_OPEN_SYSTEM, 0x20|WPA2_AUTH_PSK_SHA256|WPA2_AUTH_PSK, "wpa3/psk/sha256"},
{WL_AUTH_SAE_KEY, 0x20|WPA2_AUTH_PSK_SHA256|WPA2_AUTH_PSK, "wpa3sae/psk/sha256"},
{WL_AUTH_OPEN_SYSTEM, WPA3_AUTH_OWE, "owe"},
+ {WL_AUTH_OPEN_SYSTEM, BRCM_AUTH_DPT, "owe"},
};
typedef struct wsec_name_map_t {
/* enable:
1. dhd_priv wl pkt_filter_add 150 0 0 0 0xFF 0x50
- 2. dhd_priv wl pkt_filter_enable 150 1
+ 2. dhd_priv wl pkt_filter_enable 150 1
3. dhd_priv wl mpc 0
4. dhd_priv wl 108 1
disable:
typedef struct notify_payload {
int index;
int len;
- char payload[128];
+ char payload[256];
} 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];
+ s8 *iovar_buf = NULL;
notify_payload_t notify, *pnotify = NULL;
- int i, ret = 0, bytes_written = 0;
- char frame_str[WLC_IOCTL_SMLEN+3];
+ int i, ret = 0, bytes_written = 0, len;
+ char *frame_str = NULL;
if (data) {
+ iovar_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (iovar_buf == NULL) {
+ AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_MEDLEN);
+ goto exit;
+ }
+ memset(iovar_buf, 0, WLC_IOCTL_MEDLEN);
+ frame_str = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+ if (frame_str == NULL) {
+ AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_MEDLEN);
+ goto exit;
+ }
+ memset(frame_str, 0, WLC_IOCTL_MEDLEN);
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)) {
+ len = strlen(frame_str);
+ if (len > sizeof(notify.payload)) {
+ AEXT_ERROR(dev->name, "playload size %d > %d\n", len, sizeof(notify.payload));
+ goto exit;
+ }
+ if (len) {
notify.len = wl_pattern_atoh(frame_str, notify.payload);
if (notify.len == -1) {
AEXT_ERROR(dev->name, "rejecting pattern=%s\n", frame_str);
}
exit:
+ if (iovar_buf)
+ kfree(iovar_buf);
+ if (frame_str)
+ kfree(frame_str);
return ret;
}
#endif /* WL_GPIO_NOTIFY */
goto exit;
strncpy(name, pch, sizeof(name));
-
+
data = bcmstrtok(&pick_tmp, "", 0); // pick data
if (!strcmp(name, "pm")) {
#endif /* WL_CFG80211_P2P_DEV_IF */
static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool unicast, bool multicast);
static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params);
static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool pairwise, const u8 *mac_addr);
static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params));
static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx);
static int wl_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
const u8 *aa);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
+static int wl_cfg80211_update_owe_info(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_update_owe_info *oweinfo);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */
/*
* event & event Q handlers for cfg80211 interfaces
return ret;
}
+static s32
+wl_ext_get_scan_rssi(struct bcm_cfg80211 *cfg, u8 *bssid)
+{
+ wl_scan_results_t *bss_list;
+ wl_bss_info_t *bi = NULL;
+ s32 i, rssi = 0;
+
+ mutex_lock(&cfg->scan_sync);
+ bss_list = cfg->bss_list;
+ bi = next_bss(bss_list, bi);
+ for_each_bss(bss_list, bi, i) {
+ if (!memcmp(&bi->BSSID, bssid, ETHER_ADDR_LEN))
+ rssi = dtoh32(bi->RSSI);
+ }
+ mutex_unlock(&cfg->scan_sync);
+
+ return rssi;
+}
+
+#ifdef CONNECT_INFO_WAR
+static chanspec_t
+wl_ext_get_scan_chanspec(struct bcm_cfg80211 *cfg, u8 *bssid)
+{
+ wl_scan_results_t *bss_list;
+ wl_bss_info_t *bi = NULL;
+ chanspec_t chanspec = 0;
+ s32 i;
+
+ mutex_lock(&cfg->scan_sync);
+ bss_list = cfg->bss_list;
+ bi = next_bss(bss_list, bi);
+ for_each_bss(bss_list, bi, i) {
+ if (!memcmp(&bi->BSSID, bssid, ETHER_ADDR_LEN))
+ chanspec = wl_chspec_driver_to_host(bi->chanspec);
+ }
+ mutex_unlock(&cfg->scan_sync);
+
+ return chanspec;
+}
+#endif /* CONNECT_INFO_WAR */
+
static s32
wl_handle_assoc_hints(struct bcm_cfg80211 *cfg, struct net_device *dev,
struct cfg80211_connect_params *sme, wlcfg_assoc_info_t *info)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
bool skip_hints = false;
#endif /* KERNEL >= 3.15 */
- chanspec_t chspec;
+#ifdef CONNECT_INFO_WAR
+ chanspec_t scan_chspec;
+#endif /* CONNECT_INFO_WAR */
+ chanspec_t chspec = 0;
if (!sme || !info) {
WL_ERR(("wrong args\n"));
/* Use user space requested BSSID and channel */
info->targeted_join = true;
(void)memcpy_s(info->bssid, ETH_ALEN, sme->bssid, ETH_ALEN);
- if (sme->channel && ((chspec =
- wl_freq_to_chanspec(sme->channel->center_freq)) != INVCHANSPEC)) {
+ if (sme->channel) {
+ chspec = wl_freq_to_chanspec(sme->channel->center_freq);
+ }
+#ifdef CONNECT_INFO_WAR
+ scan_chspec = wl_ext_get_scan_chanspec(cfg, info->bssid);
+ if (scan_chspec && (scan_chspec != chspec)) {
+ WL_MSG(dev->name, "replace chspec 0x%x to previous scan chanspec 0x%x\n",
+ chspec, scan_chspec);
+ chspec = scan_chspec;
+ }
+#endif /* CONNECT_INFO_WAR */
+ if (chspec && (chspec != INVCHANSPEC)) {
info->chan_cnt = 1;
info->chanspecs[0] = chspec;
/* Skip p2p connection on 6G */
s32 err = BCME_OK;
u8 bssid[ETH_ALEN];
- if (wl_get_drv_status(cfg, CONNECTED, dev) && wl_reassoc_support) {
+ if (wl_get_drv_status(cfg, CONNECTED, dev) && wl_reassoc_support
+#ifdef WL_EXT_IAPSTA
+ && wl_ext_sta_connected(dev)
+#endif /* WL_EXT_IAPSTA */
+ ) {
/* ROAM case */
info->reassoc = true;
} else {
}
#endif /* DBG_PKT_MON && BCMDONGLEHOST */
-static s32
-wl_ext_get_rssi(struct bcm_cfg80211 *cfg, u8 *bssid)
-{
- wl_scan_results_t *bss_list;
- wl_bss_info_t *bi = NULL;
- s32 i, rssi = 0;
-
- mutex_lock(&cfg->scan_sync);
- bss_list = cfg->bss_list;
- bi = next_bss(bss_list, bi);
- for_each_bss(bss_list, bi, i) {
- if (!memcmp(&bi->BSSID, bssid, ETHER_ADDR_LEN))
- rssi = dtoh32(bi->RSSI);
- }
- mutex_unlock(&cfg->scan_sync);
-
- return rssi;
-}
-
void
wl_conn_debug_info(struct bcm_cfg80211 *cfg, struct net_device *dev, wlcfg_assoc_info_t *info)
{
return;
}
- target_rssi = wl_ext_get_rssi(cfg, info->bssid);
+ target_rssi = wl_ext_get_scan_rssi(cfg, info->bssid);
wl_ext_get_sec(dev, 0, sec_info, sizeof(sec_info), TRUE);
if (info->reassoc) {
memset(&scb_val, 0, sizeof(scb_val_t));
s32 err = BCME_OK;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
wlcfg_assoc_info_t assoc_info;
+ chanspec_t scan_chspec = 1;
WL_DBG(("Enter len=%zu\n", sme->ie_len));
RETURN_EIO_IF_NOT_UP(cfg);
goto fail;
}
- err = wl_get_assoc_channels(cfg, dev, &assoc_info);
- if (unlikely(err)) {
- WL_ERR(("get assoc channels failed\n"));
- goto fail;
+#ifdef CONNECT_INFO_WAR
+ if (!ETHER_ISBCAST(assoc_info.bssid)) {
+ scan_chspec = wl_ext_get_scan_chanspec(cfg, assoc_info.bssid);
+ }
+ if(!scan_chspec)
+ WL_MSG(dev->name, "BSSID %pM not in previous scan results\n",
+ assoc_info.bssid);
+#endif /* CONNECT_INFO_WAR */
+ if (scan_chspec) {
+ err = wl_get_assoc_channels(cfg, dev, &assoc_info);
+ if (unlikely(err)) {
+ WL_ERR(("get assoc channels failed\n"));
+ goto fail;
+ }
}
err = wl_config_assoc_ies(cfg, dev, sme, &assoc_info);
static s32
wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool unicast, bool multicast)
static s32
wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool pairwise, const u8 *mac_addr,
static s32
wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool pairwise, const u8 *mac_addr)
/* NOTE : this function cannot work as is and is never called */
static s32
wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
static s32
wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev,
-#if defined(CFG80211_BKPORT_MLO)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO)
int link_id,
#endif
u8 key_idx)
/* Query RSSI sum across antennas */
bzero(&rssi_ant_mimo, sizeof(rssi_ant_mimo));
err = wl_get_rssi_per_ant(dev, dev->name, NULL, &rssi_ant_mimo);
- if (err) {
+ if (err && err != BCME_UNSUPPORTED) {
WL_ERR(("Could not get rssi sum (%d)\n", err));
/* set rssi to zero and do not return error,
* because iovar phy_rssi_ant could return BCME_UNSUPPORTED
*/
err = BCME_OK;
} else {
- cfg->rssi_sum_report = TRUE;
if ((*rssi = rssi_ant_mimo.rssi_sum) >= 0) {
*rssi = 0;
+ } else {
+ cfg->rssi_sum_report = TRUE;
}
}
#endif /* SUPPORT_RSSI_SUM_REPORT */
(void)memset_s(&rssi_ant_mimo,
sizeof(rssi_ant_mimo), 0, sizeof(rssi_ant_mimo));
err = wl_get_rssi_per_ant(dev, dev->name, NULL, &rssi_ant_mimo);
- if (err) {
+ if (err && err != BCME_UNSUPPORTED) {
WL_ERR(("Could not get rssi sum (%d)\n", err));
- } else {
+ } else if (!err) {
chains = 0;
for (cnt = 0; cnt < rssi_ant_mimo.count; cnt++) {
sinfo->chain_signal[cnt] = rssi_ant_mimo.rssi_ant[cnt];
return err;
}
-static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
+static int wl_cfg80211_dump_survey_ap(struct wiphy *wiphy, struct net_device *ndev,
int idx, struct survey_info *info)
{
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
}
#endif /* WL_SUPPORT_ACS */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ * A connected STA typically cannot afford to go off-channel to collect
+ * all form of stats like an AP sounding the air before going up, hence
+ * a dedicated interface. And NL only uses that for the noise field of
+ * wpa_cli's signal_poll.
+ */
+static int wl_cfg80211_dump_survey_sta(struct wiphy *wiphy, struct net_device *ndev,
+ int idx, struct survey_info *info)
+{
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ u16 wl_iftype = 0;
+ u16 wl_mode = 0;
+ chanspec_t *chanspec = NULL;
+ s32 freq = 0;
+ struct ieee80211_channel *channel = NULL;
+ int err, noise, retry;
+
+ if (cfg80211_to_wl_iftype(ndev->ieee80211_ptr->iftype, &wl_iftype, &wl_mode) < 0) {
+ return -ENOENT;
+ }
+
+ if (wl_iftype != WL_IF_TYPE_STA ||
+ !wl_get_drv_status(cfg, CONNECTED, ndev) ||
+ idx != 0) {
+ return -ENOENT;
+ }
+ chanspec = (chanspec_t *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
+ if (chanspec && (*chanspec) && (*chanspec != INVCHANNEL)) {
+ freq = wl_channel_to_frequency(wf_chspec_ctlchan(*chanspec), CHSPEC_BAND(*chanspec));
+ channel = ieee80211_get_channel(wiphy, freq);
+ } else {
+ return -ENOENT;
+ }
+
+ /* Get noise value */
+ retry = IOCTL_RETRY_COUNT;
+ while (retry--) {
+ noise = 0;
+ err = wldev_ioctl_get(ndev, WLC_GET_PHY_NOISE, &noise,
+ sizeof(noise));
+ if (err >= 0) {
+ break;
+ }
+ WL_DBG(("attempt = %d, err = %d, \n",
+ (IOCTL_RETRY_COUNT - retry), err));
+ }
+
+ if (retry <= 0) {
+ WL_ERR(("Get Phy Noise failed, error = %d\n", err));
+ noise = CHAN_NOISE_DUMMY;
+ }
+
+ memset_s(info, sizeof(struct survey_info), 0, sizeof(struct survey_info));
+ info->channel = channel;
+ info->noise = noise;
+ info->filled = SURVEY_INFO_NOISE_DBM ;
+
+ return 0;
+}
+
+static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
+ int idx, struct survey_info *info)
+{
+#ifdef WL_SUPPORT_ACS
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+ if ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
+ return wl_cfg80211_dump_survey_ap(wiphy, ndev, idx, info);
+ } else
+#endif /* WL_SUPPORT_ACS */
+ {
+ return wl_cfg80211_dump_survey_sta(wiphy, ndev, idx, info);
+ }
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
static int
wl_cfg80211_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
.tdls_mgmt = wl_cfg80211_tdls_mgmt,
.tdls_oper = wl_cfg80211_tdls_oper,
#endif /* LINUX_VERSION > VERSION(3, 2, 0) || WL_COMPAT_WIRELESS */
-#ifdef WL_SUPPORT_ACS
.dump_survey = wl_cfg80211_dump_survey,
-#endif /* WL_SUPPORT_ACS */
#ifdef WL_CFG80211_ACL
.set_mac_acl = wl_cfg80211_set_mac_acl,
#endif /* WL_CFG80211_ACL */
.update_ft_ies = wl_cfg80211_update_ft_ies,
#endif /* WLFBT */
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
+ .update_owe_info = wl_cfg80211_update_owe_info,
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)
.get_channel = wl_cfg80211_get_channel,
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0) */
};
/* Query RSSI sum across antennas */
memset(&rssi_ant_mimo, 0, sizeof(rssi_ant_mimo));
err = wl_get_rssi_per_ant(ndev, ndev->name, NULL, &rssi_ant_mimo);
- if (err) {
+ if (err && err != BCME_UNSUPPORTED) {
WL_ERR(("Could not get rssi sum (%d)\n", err));
}
rssi = rssi_ant_mimo.rssi_sum;
wl_cfg80211_ccode_evt_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
const wl_event_msg_t *event, void *data)
{
- dhd_pub_t *dhd = cfg->pub;
s32 err = 0;
struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
char country_str[WLC_CNTRY_BUF_SZ] = { 0 };
- struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
if (strlcpy(country_str, data, WL_CCODE_LEN + 1) >= WLC_CNTRY_BUF_SZ) {
return -EINVAL;
if (strncmp(cfg->country, country_str, WL_CCODE_LEN) == 0) {
/* If country code is updated from command context, skip wiphy update */
- WL_MSG(dev->name, "No change in country (%s)\n", country_str);
+ WL_DBG_MEM(("No change in country (%s)\n", country_str));
return BCME_OK;
}
- WL_MSG(dev->name, "Updating new country %s\n", country_str);
- dhd_conf_country(dhd, "country", country_str);
+ WL_INFORM_MEM(("Updating new country %s\n", country_str));
/* Indicate to upper layer for regdom change */
err = wl_update_wiphybands(cfg, true);
cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
+ cfg->evt_handler[WLC_E_OWE_INFO] = wl_notify_connect_status;
cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
WL_DBG(("%s:SKIP ADDING FILS HLP EXTN ID\n", __func__));
return true;
}
+#ifdef WL_CAP_OCE_STA
+ if (vndrie->oui[0] == FILS_EXTID_MNG_REQ_PARAMS) {
+ /* Skip adding fils FILS_MAX_CHANNEL_TIME, its already done in FW */
+ WL_DBG(("%s:SKIP ADDING FILS MNG REQ PARAMS \n", __func__));
+ return true;
+ }
+#endif /* WL_CAP_OCE_STA */
+ if ((vndrie->oui[0] == EXT_MNG_HE_CAP_ID) ||
+ (vndrie->oui[0] == EXT_MNG_HE_OP_ID)) {
+ /* Skip adding HE Capabilities ie and HE operation IE
+ */
+ WL_DBG(("%s:SKIP ADDING HE EXTN ID\n", __func__));
+ return true;
+ }
+
return false;
}
while (ie) {
if (count >= MAX_VNDR_IE_NUMBER)
break;
-#ifdef HOSTAPD_EID_EXTENSION_SUPPORT
- if (ie->id == DOT11_MNG_VS_ID || (ie->id == DOT11_MNG_ID_EXT_ID))
-#else
- if (ie->id == DOT11_MNG_VS_ID)
-#endif
- {
+ if (ie->id == DOT11_MNG_VS_ID || (ie->id == DOT11_MNG_ID_EXT_ID)) {
vndrie = (const vndr_ie_t *) ie;
if (ie->id == DOT11_MNG_ID_EXT_ID) {
/* len should be bigger than sizeof ID extn field at least */
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
+static int wl_cfg80211_update_owe_info(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_update_owe_info *oweinfo)
+{
+ int err = 0;
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+ dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
+ wl_assoc_resp_params_v1_t *assoc_resp_params;
+ uint8 resp_buf[AP_OWE_IOCTL_BUF_SIZE];
+ uint8 *p_resp_ies_tlv = NULL;
+ uint16 assoc_params_iovsize;
+
+ WL_DBG(("%s: Enter\n", __func__));
+ assoc_params_iovsize = AP_OWE_ASSOC_RESP_PARAMS_BUFSZ +
+ OFFSETOF(wl_assoc_resp_params_v1_t, ies);
+ assoc_resp_params = (wl_assoc_resp_params_v1_t *)MALLOCZ(dhdp->osh, assoc_params_iovsize);
+
+ if (assoc_resp_params == NULL) {
+ WL_ERR(("error: failed to allocate %d bytes of memory\n", assoc_params_iovsize));
+ return BCME_ERROR;
+ }
+ /* setup assoc_resp_params iovar */
+ assoc_resp_params->version = WL_ASSOC_RESP_PARAMS_V1;
+ assoc_resp_params->len = assoc_params_iovsize;
+ assoc_resp_params->fixed_length = OFFSETOF(wl_assoc_resp_params_v1_t, ies);
+ /* setup TLVs */
+ p_resp_ies_tlv = (uint8 *)&assoc_resp_params->ies[0];
+
+ if (wl_dbg_level & WL_DBG_DBG) {
+ if (oweinfo) {
+ prhex("supplicant MAC", oweinfo->peer, ETHER_ADDR_LEN);
+ prhex("supplicant generated OWE IE", oweinfo->ie, oweinfo->ie_len);
+ }
+ }
+
+ if (oweinfo->ie_len > AP_OWE_ASSOC_RESP_PARAMS_BUFSZ) {
+ WL_ERR(("no resp ies buffer left\n"));
+ err = -EINVAL;
+ goto exit;
+ }
+ (void)memcpy_s(assoc_resp_params->mac_addr, ETHER_ADDR_LEN,
+ oweinfo->peer, ETHER_ADDR_LEN);
+ (void)memcpy_s(p_resp_ies_tlv, AP_OWE_ASSOC_RESP_PARAMS_BUFSZ,
+ oweinfo->ie, oweinfo->ie_len);
+ assoc_resp_params->resp_ie_len = oweinfo->ie_len;
+ assoc_resp_params->status = oweinfo->status;
+ err = wldev_iovar_setbuf(dev, "assoc_resp_params", assoc_resp_params,
+ assoc_params_iovsize, resp_buf, AP_OWE_IOCTL_BUF_SIZE, NULL);
+ if (err) {
+ WL_DBG(("ap_assoc_resp_params failed, err=%d\n", err));
+ }
+exit:
+ return err;
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */
+
u64
wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
{
WL_ERR(("Failed to get rssi info, err=%d\n", err));
} else {
memcpy(get_param, iobuf, sizeof(wl_rssi_ant_mimo_t));
- if (get_param->count == 0) {
- WL_ERR(("Not supported on this chip\n"));
+ if (get_param->count == 0 || get_param->rssi_sum >= 0) {
+ WL_INFORM(("Not supported on this chip\n"));
err = BCME_UNSUPPORTED;
}
}
struct net_device *wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg);
#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
-#ifdef WL_SUPPORT_ACS
-#define ACS_MSRMNT_DELAY 1000 /* dump_obss delay in ms */
#define IOCTL_RETRY_COUNT 5
#define CHAN_NOISE_DUMMY -80
+
+#ifdef WL_SUPPORT_ACS
+#define ACS_MSRMNT_DELAY 1000 /* dump_obss delay in ms */
#define OBSS_TOKEN_IDX 15
#define IBSS_TOKEN_IDX 15
#define TX_TOKEN_IDX 14
}
}
- cnt = i;
+ cnt = i;
node = cfg->g_bss_cache_ctrl.m_cache_head;
WL_SCAN(("cached AP count (%d)\n", wl_bss_cache_size(&cfg->g_bss_cache_ctrl)));
for (i=cnt; node && i<WL_AP_MAX; i++) {
err = wl_cfgp2p_discover_enable_search(cfg, false);
if (unlikely(err)) {
wl_clr_drv_status(cfg, SCANNING, ndev);
- return err;
+ goto out_err;
}
p2p_scan(cfg) = false;
}
}
/* abort scan listen */
- _wl_cfgscan_cancel_scan(cfg);
+ /* change _wl_cfgscan_cancel_scan() to wl_cfgscan_scan_abort() to fix DPP connection issue on Android 12 */
+ wl_cfgscan_scan_abort(cfg);
if (notify_user) {
wl_cfgscan_notify_listen_complete(cfg);
} else if (err == BCME_OK) {
reply_len = (num_channels * sizeof(uint32));
} else if (err == BCME_UNSUPPORTED) {
+ MFREE(cfg->osh, reply, CHANINFO_LIST_BUF_SIZE);
reply = dhd_pno_get_gscan(dhdp,
DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
if (!reply) {
pwrstats = (wl_pwrstats_t *) iovar_buf;
if (dtoh16(pwrstats->version) != WL_PWRSTATS_VERSION) {
- WL_ERR(("PWRSTATS Version mismatch\n"));
+ WL_ERR(("PWRSTATS Version mismatch %d\n", dtoh16(pwrstats->version)));
err = BCME_ERROR;
goto exit;
}
[DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 },
[DEBUG_ATTRIBUTE_FW_DUMP_LEN] = { .type = NLA_U32 },
[DEBUG_ATTRIBUTE_FW_DUMP_DATA] = { .type = NLA_U64 },
+#if (ANDROID_VERSION >= 11)
[DEBUG_ATTRIBUTE_FW_ERR_CODE] = { .type = NLA_U32 },
+#endif
[DEBUG_ATTRIBUTE_RING_DATA] = { .type = NLA_BINARY },
[DEBUG_ATTRIBUTE_RING_STATUS] = { .type = NLA_BINARY },
[DEBUG_ATTRIBUTE_RING_NUM] = { .type = NLA_U32 },
#define CFG80211_VENDOR_CMD_REPLY_SKB_SZ 100
#define CFG80211_VENDOR_EVT_SKB_SZ 2048
+#define AP_OWE_IOCTL_BUF_SIZE 1024u
+#define AP_OWE_ASSOC_RESP_PARAMS_BUFSZ 512u
+
#define SUPP_SAE_PWE_LOOP 0x00
#define SUPP_SAE_PWE_H2E 0x01
#define SUPP_SAE_PWE_TRANS 0x02
#endif
chspec = wl_freq_to_chanspec(center_freq);
- WL_MSG(dev->name, "netdev_ifidx(%d) chan_width(%d) target channel(%s-%d %sMHz)\n",
- dev->ifindex, width, CHSPEC2BANDSTR(chspec),
+ WL_MSG(dev->name, "netdev_ifidx(%d) target channel(%s-%d %sMHz)\n",
+ dev->ifindex, CHSPEC2BANDSTR(chspec),
CHSPEC_CHANNEL(chspec), WLCWIDTH2STR(band_width));
#ifdef WL_P2P_6G
break;
#endif /* WL_SAE || WL_CLIENT_SAE */
#endif /* MFP */
+#if defined(WL_OWE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
+ case RSN_AKM_OWE:
+ wpa_auth |= WPA3_AUTH_OWE;
+ break;
+#endif /* WL_OWE && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */
default:
WL_ERR(("No Key Mgmt Info\n"));
}
rsn_cap[0] = *(const u8 *)&mgmt->list[suite_count];
rsn_cap[1] = *((const u8 *)&mgmt->list[suite_count] + 1);
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
+ int wpa_cap = 0, fw_wpa_cap = 0;
+
+ err = wldev_iovar_getint_bsscfg(dev, "wpa_cap", &fw_wpa_cap, bssidx);
+ if (err < 0) {
+ WL_ERR(("get wpa_cap error %d\n", err));
+ return err;
+ }
+
+ /* set FW wpa_cap to sync RSN Capabilities */
+ wpa_cap = rsn_cap[1] << 8 | rsn_cap[0];
+ WL_INFORM(("rsn_cap 0x%02x 0x%02x, wpa_cap = 0x%04x, fw_wpa_cap = 0x%4x\n",
+ wpa_cap, rsn_cap[1], rsn_cap[0], fw_wpa_cap));
+
+ if ((wpa_cap&RSN_CAP_PREAUTH) != (fw_wpa_cap&RSN_CAP_PREAUTH)) {
+ err = wldev_iovar_setint_bsscfg(dev, "wpa_cap", wpa_cap, bssidx);
+ if (err < 0) {
+ WL_ERR(("wpa_cap error %d\n", err));
+ return BCME_ERROR;
+ }
+ }
+ }
+
if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
wme_bss_disable = 0;
} else {
uint32 wme_apsd = 0;
#endif /* SOFTAP_UAPSD_OFF */
s32 err = BCME_OK;
+#ifdef BCM4343X_WAR
dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif
s32 is_rsdb_supported = BCME_ERROR;
char sec[64];
WL_ERR(("Could not get wsec %d\n", err));
goto exit;
}
+#ifdef BCM4343X_WAR
if (dhd->conf->chip == BCM43430_CHIP_ID && bssidx > 0 &&
(wsec & (TKIP_ENABLED|AES_ENABLED))) {
struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
wldev_ioctl_set(primary_ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
}
}
+#endif
if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
WL_DBG(("Applying buffered WEP KEY \n"));
err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
#if defined(WL_CFG80211_STA_EVENT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
struct station_info sinfo;
#endif /* (LINUX_VERSION >= VERSION(3,2,0)) || !WL_CFG80211_STA_EVENT */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
+ struct cfg80211_update_owe_info owe_info;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */
#ifdef BIGDATA_SOFTAP
dhd_pub_t *dhdp;
#endif /* BIGDATA_SOFTAP */
}
#endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
+ else if (event == WLC_E_OWE_INFO) {
+ if (!data) {
+ WL_ERR(("No DH-IEs present in ASSOC/REASSOC_IND"));
+ return -EINVAL;
+ }
+ if (wl_dbg_level & WL_DBG_DBG) {
+ prhex("FW-OWEIE ", (uint8 *)data, len);
+ }
+ eacopy(e->addr.octet, owe_info.peer);
+ owe_info.ie = data;
+ owe_info.ie_len = len;
+ WL_INFORM_MEM(("Recieved owe_info. Mac addr" MACDBG "\n",
+ MAC2STRDBG((const u8*)(&e->addr))));
+ cfg80211_update_owe_info_event(ndev, &owe_info, GFP_ATOMIC);
+ }
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */
return err;
}
}
#endif /* WL_CFG80211_ACL */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
int wl_chspec_chandef(chanspec_t chanspec,
struct cfg80211_chan_def *chandef, struct wiphy *wiphy)
{
return 0;
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
void
wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
{
extern void wl_restore_ap_bw(struct bcm_cfg80211 *cfg);
#endif /* SUPPORT_AP_BWCTRL */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
extern int wl_chspec_chandef(chanspec_t chanspec,
struct cfg80211_chan_def *chandef, struct wiphy *wiphy);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))) */
#endif /* _wl_cfgvif_h_ */
wl_ext_set_emode(struct wl_if_info *cur_if)
{
struct net_device *dev = cur_if->dev;
+#ifdef BCM4343X_WAR
struct dhd_pub *dhd = dhd_get_pub(dev);
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+#endif
struct wl_wsec_key wsec_key;
wsec_pmk_t psk;
authmode_t amode = cur_if->amode;
memcpy(psk.key, key, strlen(key));
IAPSTA_INFO(dev->name, "TKIP/AES key \"%s\"\n", psk.key);
}
+#ifdef BCM4343X_WAR
if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 &&
apsta_params->apstamode == ISTAAP_MODE) {
wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround
}
+#endif
wl_ext_iovar_setint(dev, "wsec", wsec);
{
uint16 chan = 0, ctl_chan;
u32 chanspec = 0;
-
+
chanspec = wl_ext_get_chanspec(dev, chan_info);
if (chanspec) {
ctl_chan = wf_chspec_ctlchan(chanspec);
{
struct net_device *dev = (struct net_device *)data;
struct wl_if_info *cur_if;
+#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+ u8 *curbssid = NULL;
+#endif /* WL_CFG80211 */
if (!dev) {
IAPSTA_ERROR("wlan", "dev is not ready\n");
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
cur_if->assoc_info.reassoc = 0;
+ curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
+ if (curbssid)
+ (void)memcpy_s(&cur_if->bssid, ETH_ALEN, curbssid, ETH_ALEN);
#endif /* WL_EXT_RECONNECT && WL_CFG80211 */
IAPSTA_ERROR(dev->name, "timer expired\n");
wl_ext_send_event_msg(dev, WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WLC_E_STATUS_SUCCESS);
}
}
+ if (target_if) {
+ // skip move target_if while there is other interface's prio is higher than cur_if
+ max_prio = cur_if->prio;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (target_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) &&
+ tmp_if->prio > max_prio) {
+ if (wl_ext_same_chan(&target_if->chan_info, &tmp_if->chan_info)) {
+ target_if = NULL;
+ break;
+ }
+ }
+ }
+ }
+
if (target_if) {
WL_MSG(target_if->ifname, "channel=%s-%d => %s channel=%s-%d\n",
WLCBAND2STR(target_if->chan_info.band), target_chan,
return connecting;
}
+bool
+wl_ext_sta_connected(struct net_device *dev)
+{
+ struct wl_if_info *cur_if = NULL;
+ bool connected = FALSE;
+ int state;
+
+ cur_if = wl_get_cur_if(dev);
+ if (!cur_if)
+ return FALSE;
+
+ if (cur_if->ifmode != ISTA_MODE && cur_if->ifmode != IGC_MODE)
+ return FALSE;
+
+ state = cur_if->conn_state;
+ if (state >= CONN_STATE_CONNECTED) {
+ connected = TRUE;
+ IAPSTA_TRACE(dev->name, "conn_state %d\n", state);
+ }
+
+ return connected;
+}
+
#ifdef DHD_LOSSLESS_ROAMING
int
wl_ext_any_sta_handshaking(struct dhd_pub *dhd)
{
dhd_pub_t *dhd = dhd_get_pub(dev);
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- struct wl_if_info *ap_if = NULL;
+ struct wl_if_info *ap_if = NULL, *tmp_if = NULL;
+ struct wl_chan_info chan_info;
+ int i;
if (apsta_params->radar)
return;
ap_if = wl_ext_get_dfs_master_if(apsta_params);
+ if (!ap_if)
+ return;
+
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if && tmp_if->ifmode == ISTA_MODE &&
+ wl_get_isam_status(tmp_if, IF_READY)) {
+ memset(&chan_info, 0, sizeof(struct wl_chan_info));
+ wl_ext_get_chan(tmp_if->dev, &chan_info);
+ if (wl_ext_same_chan(&chan_info, &tmp_if->chan_info)) {
+ return;
+ }
+ }
+ }
if (ap_if) {
uint16 chan_2g, chan_5g;
+ WL_MSG(tmp_if->ifname, "move DFS channel interface\n");
wl_ext_if_down(apsta_params, ap_if);
wl_ext_iapsta_restart_master(dev);
wl_ext_get_default_chan(ap_if->dev, &chan_2g, &chan_5g, TRUE);
if (ap_if->chan_info.chan) {
wl_ext_move_cur_channel(apsta_params, ap_if);
wl_ext_if_up(apsta_params, ap_if, FALSE, 0);
+ } else {
+ WL_MSG(tmp_if->ifname, "no preferred channel\n");
}
}
}
if (tmp_if && tmp_if->ifmode == ifmode &&
wl_get_isam_status(tmp_if, IF_READY)) {
if (wl_ext_get_chan(tmp_if->dev, &tmp_if->chan_info) == channel) {
- WL_MSG(tmp_if->ifname, "re-enable channel %d\n", channel);
+ WL_MSG(tmp_if->ifname, "re-enable channel %d\n", channel);
if (ifmode == IAP_MODE) {
wl_ext_if_down(apsta_params, tmp_if);
wl_ext_if_up(apsta_params, tmp_if, FALSE, 0);
if (cur_if->ifmode == ISTA_MODE) {
if (conf->war & SET_CHAN_INCONN && chan_info->chan) {
chanspec_t fw_chspec;
- IAPSTA_INFO(dev->name, "set channel %d\n", chan_info->chan);
- wl_ext_set_chanspec(cur_if->dev, chan_info, &fw_chspec);
+ IAPSTA_INFO(dev->name, "set channel %d\n", chan_info->chan);
+ wl_ext_set_chanspec(cur_if->dev, chan_info, &fw_chspec);
}
wl_set_isam_status(cur_if, STA_CONNECTING);
}
connecting = wl_ext_sta_connecting(dev);
handshaking = wl_ext_sta_handshaking(dev);
+ if (cur_if->conn_state == CONN_STATE_ASSOCIATED) {
+ WL_MSG(dev->name, "skip connect retry due to no 4-way M1 received\n");
+ return BCME_BADADDR;
+ }
+
mutex_unlock(&apsta_params->in4way_sync);
mutex_lock(&cfg->connect_sync);
if (associated) {
bzero(&cfg->last_roamed_addr, ETHER_ADDR_LEN);
wl_cfg80211_disassoc(dev, WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
+ OSL_SLEEP(50); // wait WLC_E_DISASSOC
}
if (wl_handle_join(cfg, dev, assoc_info))
goto exit;
+ wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTING);
if (assoc_info->chan_cnt == 0)
max_wait_time = STA_CONNECT_FULL_CHAN_TIMEOUT;
else
#endif /* BTC_WAR */
max_wait_time = 0;
} else {
+ wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_ASSOCIATED);
max_wait_time = STA_4WAY_TIMEOUT;
}
#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211)
case WL_EXT_STATUS_ROAMED:
wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
if ((wpa_auth >= WPA_AUTH_UNSPECIFIED) && !(wpa_auth & WPA2_AUTH_FT)) {
- wl_timer_mod(dhd, &cur_if->connect_timer, STA_CONNECT_TIMEOUT);
- osl_do_gettimeofday(sta_conn_ts);
+ if (cur_if->conn_state >= CONN_STATE_CONNECTED) {
+ wl_timer_mod(dhd, &cur_if->connect_timer, STA_CONNECT_TIMEOUT);
+ osl_do_gettimeofday(sta_conn_ts);
+ }
wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTING);
#ifdef BTC_WAR
wl_ext_btc_config(cur_if->dev, TRUE);
else
conn_state = CONN_STATE_AUTH_SAE_M1;
} else if (auth_seq == 2) {
- if (tx)
+ if (tx)
conn_state = CONN_STATE_AUTH_SAE_M4;
else
conn_state = CONN_STATE_AUTH_SAE_M3;
int ret = 0;
bool reinit = FALSE;
+ if (!(dhd->conf->war & FW_REINIT_RXF0OVFL)) {
+ return;
+ }
+
if ((cur_if->ifmode == ISTA_MODE) &&
(etype == WLC_E_LINK) && (flags & WLC_EVENT_MSG_LINK)) {
// Link up
} else {
WL_MSG(cur_if->ifname, "[%c] Link UP with %pM\n",
cur_if->prefix, &e->addr);
+ wl_ext_isam_status(cur_if->dev, NULL, 0);
#ifdef SET_CARRIER
wl_ext_net_setcarrier(cur_if, TRUE, FALSE);
#endif /* SET_CARRIER */
WL_MSG(cur_if->ifname, "[%c] Link up (etype=%d)\n",
cur_if->prefix, event_type);
wl_set_isam_status(cur_if, AP_CREATED);
+ wl_ext_isam_status(cur_if->dev, NULL, 0);
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);
+ wl_ext_isam_status(cur_if->dev, NULL, 0);
}
#ifdef SET_CARRIER
wl_ext_net_setcarrier(cur_if, TRUE, FALSE);
}
}
+static void
+wl_ext_iapsta_ccode(struct wl_if_info *cur_if,
+ const wl_event_msg_t *e, void *data)
+{
+ struct dhd_pub *dhd = dhd_get_pub(cur_if->dev);
+ uint32 event_type = ntoh32(e->event_type);
+ char country_str[WLC_CNTRY_BUF_SZ] = { 0 };
+
+ if (event_type == WLC_E_COUNTRY_CODE_CHANGED) {
+ if (strlcpy(country_str, data, WL_CCODE_LEN + 1) >= WLC_CNTRY_BUF_SZ) {
+ return;
+ }
+ WL_MSG(cur_if->ifname, "Updating new country %s\n", country_str);
+ dhd_conf_country(dhd, "country", country_str);
+ }
+}
+
void
wl_ext_iapsta_event(struct net_device *dev, void *argu,
const wl_event_msg_t *e, void *data)
}
wl_ext_iapsta_link(cur_if, e, data);
+ wl_ext_iapsta_ccode(cur_if, e, data);
#ifdef TPUT_MONITOR
if (dhd->conf->tput_monitor_ms)
wl_tput_monitor_handler(cur_if, e, data);
if (FW_SUPPORTED(dhd, rsdb)) {
if (apstamode == IDUALAP_MODE)
- apsta_params->rsdb = -1;
+ apsta_params->rsdb = 1;
else if (apstamode == ISTAAPAP_MODE)
apsta_params->rsdb = 0;
if (apstamode == ISTAAPAP_MODE || apstamode == IDUALAP_MODE ||
{
struct dhd_pub *dhd = dhd_get_pub(net);
struct wl_apsta_params *apsta_params = dhd->iapsta_params;
- int pm;
IAPSTA_TRACE(cur_if->ifname, "ifidx=%d\n", cur_if->ifidx);
if (cur_if->ifidx == 0) {
wl_ext_add_del_ie(net, VNDR_IE_ASSOCREQ_FLAG, dhd->conf->vndr_ie_assocreq, "add");
} else {
if (cur_if->ifmode == ISTA_MODE) {
- wl_ext_iovar_setint(cur_if->dev, "roam_off", dhd->conf->roam_off);
- wl_ext_iovar_setint(cur_if->dev, "bcn_timeout", dhd->conf->bcn_timeout);
- if (dhd->conf->pm >= 0)
- pm = dhd->conf->pm;
- 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", 10);
+ dhd_conf_preinit_ioctls_sta(dhd, cur_if->ifidx);
}
#ifdef WLMESH
else if (cur_if->ifmode == IMESH_MODE) {
void wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add);
bool wl_ext_iapsta_other_if_enabled(struct net_device *net);
bool wl_ext_sta_connecting(struct net_device *dev);
+bool wl_ext_sta_connected(struct net_device *dev);
void wl_ext_get_chan_str(struct net_device *dev, char *chan_str, int total_len);
#ifdef DHD_LOSSLESS_ROAMING
int wl_ext_any_sta_handshaking(struct dhd_pub *dhd);
-#include <wl_android.h>\r
-#ifdef WL_TIMER\r
-\r
-#define TIMER_ERROR(name, arg1, args...) \\r
- do { \\r
- if (android_msg_level & ANDROID_ERROR_LEVEL) { \\r
- printf("[%s] TIMER-ERROR) %s : " arg1, name, __func__, ## args); \\r
- } \\r
- } while (0)\r
-#define TIMER_TRACE(name, arg1, args...) \\r
- do { \\r
- if (android_msg_level & ANDROID_TRACE_LEVEL) { \\r
- printf("[%s] TIMER-TRACE) %s : " arg1, name, __func__, ## args); \\r
- } \\r
- } while (0)\r
-\r
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \\r
- 4 && __GNUC_MINOR__ >= 6))\r
-#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \\r
-_Pragma("GCC diagnostic push") \\r
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \\r
-(entry) = list_first_entry((ptr), type, member); \\r
-_Pragma("GCC diagnostic pop") \\r
-\r
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \\r
-_Pragma("GCC diagnostic push") \\r
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \\r
-entry = container_of((ptr), type, member); \\r
-_Pragma("GCC diagnostic pop") \\r
-\r
-#else\r
-#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \\r
-(entry) = list_first_entry((ptr), type, member); \\r
-\r
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \\r
-entry = container_of((ptr), type, member); \\r
-\r
-#endif /* STRICT_GCC_WARNINGS */\r
-\r
-typedef void(*FUNC_HANDLER) (void *cb_argu);\r
-\r
-struct wl_func_q {\r
- struct list_head eq_list;\r
- FUNC_HANDLER cb_func;\r
- void *cb_argu;\r
-};\r
-\r
-typedef void(*TIMER_HANDLER) (void *cb_argu);\r
-\r
-typedef struct timer_handler_list {\r
- struct list_head list;\r
- struct net_device *net;\r
- timer_list_compat_t *timer;\r
- TIMER_HANDLER cb_func;\r
- void *cb_argu;\r
- uint tmo_ms;\r
- ulong tmo_jiffies;\r
-} timer_handler_list_t;\r
-\r
-typedef struct wl_timer_params {\r
- dhd_pub_t *pub;\r
- struct list_head timer_list;\r
- struct list_head eq_list;\r
- timer_list_compat_t timer;\r
- spinlock_t eq_lock;\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- struct workqueue_struct *timer_workq;\r
- struct work_struct timer_work;\r
- struct workqueue_struct *func_workq;\r
- struct work_struct func_work;\r
-#else\r
- tsk_ctl_t thr_timer_ctl;\r
- tsk_ctl_t thr_func_ctl;\r
-#endif\r
-} wl_timer_params_t;\r
-\r
-static unsigned long\r
-wl_func_lock_eq(struct wl_timer_params *timer_params)\r
-{\r
- unsigned long flags;\r
-\r
- spin_lock_irqsave(&timer_params->eq_lock, flags);\r
- return flags;\r
-}\r
-\r
-static void\r
-wl_func_unlock_eq(struct wl_timer_params *timer_params, unsigned long flags)\r
-{\r
- spin_unlock_irqrestore(&timer_params->eq_lock, flags);\r
-}\r
-\r
-static void\r
-wl_func_init_eq_lock(struct wl_timer_params *timer_params)\r
-{\r
- spin_lock_init(&timer_params->eq_lock);\r
-}\r
-\r
-static void\r
-wl_func_init_eq(struct wl_timer_params *timer_params)\r
-{\r
- wl_func_init_eq_lock(timer_params);\r
- INIT_LIST_HEAD(&timer_params->eq_list);\r
-}\r
-\r
-static void\r
-wl_func_flush_eq(struct wl_timer_params *timer_params)\r
-{\r
- struct wl_func_q *e;\r
- unsigned long flags;\r
-\r
- flags = wl_func_lock_eq(timer_params);\r
- while (!list_empty_careful(&timer_params->eq_list)) {\r
- BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);\r
- list_del(&e->eq_list);\r
- kfree(e);\r
- }\r
- wl_func_unlock_eq(timer_params, flags);\r
-}\r
-\r
-static struct wl_func_q *\r
-wl_func_deq(struct wl_timer_params *timer_params)\r
-{\r
- struct wl_func_q *e = NULL;\r
- unsigned long flags;\r
-\r
- flags = wl_func_lock_eq(timer_params);\r
- if (likely(!list_empty(&timer_params->eq_list))) {\r
- BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);\r
- list_del(&e->eq_list);\r
- }\r
- wl_func_unlock_eq(timer_params, flags);\r
-\r
- return e;\r
-}\r
-\r
-static s32\r
-wl_func_enq(struct wl_timer_params *timer_params,\r
- void *cb_func, void *cb_argu)\r
-{\r
- struct wl_func_q *e;\r
- s32 err = 0;\r
- uint32 funcq_size;\r
- unsigned long flags;\r
- gfp_t aflags;\r
-\r
- funcq_size = sizeof(struct wl_func_q);\r
- aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;\r
- e = kzalloc(funcq_size, aflags);\r
- if (unlikely(!e)) {\r
- TIMER_ERROR("wlan", "funcq_size alloc failed %d\n", funcq_size);\r
- return -ENOMEM;\r
- }\r
- e->cb_func = cb_func;\r
- e->cb_argu = cb_argu;\r
- flags = wl_func_lock_eq(timer_params);\r
- list_add_tail(&e->eq_list, &timer_params->eq_list);\r
- wl_func_unlock_eq(timer_params, flags);\r
-\r
- return err;\r
-}\r
-\r
-static void\r
-wl_func_put(struct wl_func_q *e)\r
-{\r
- kfree(e);\r
-}\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-static void wl_func_handler(struct work_struct *data);\r
-#define WL_FUNC_HANDLER() static void wl_func_handler(struct work_struct *data)\r
-#else\r
-static int wl_func_handler(void *data);\r
-#define WL_FUNC_HANDLER() static int wl_func_handler(void *data)\r
-#endif\r
-\r
-WL_FUNC_HANDLER()\r
-{\r
- struct wl_timer_params *timer_params = NULL;\r
- struct wl_func_q *e;\r
- struct net_device *net = NULL;\r
- dhd_pub_t *dhd;\r
- unsigned long flags = 0;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
- tsk_ctl_t *tsk = (tsk_ctl_t *)data;\r
- timer_params = (struct wl_timer_params *)tsk->parent;\r
-#else\r
- BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, func_work);\r
-#endif\r
-\r
- dhd = timer_params->pub;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
- while (1) {\r
- if (down_interruptible(&tsk->sema) == 0) {\r
- SMP_RD_BARRIER_DEPENDS();\r
- if (tsk->terminated) {\r
- break;\r
- }\r
-#endif\r
- DHD_EVENT_WAKE_LOCK(dhd);\r
- while ((e = wl_func_deq(timer_params))) {\r
- DHD_GENERAL_LOCK(dhd, flags);\r
- if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {\r
- TIMER_ERROR(net->name, "BUS is DOWN.\n");\r
- DHD_GENERAL_UNLOCK(dhd, flags);\r
- goto fail;\r
- }\r
- DHD_GENERAL_UNLOCK(dhd, flags);\r
- e->cb_func(e->cb_argu);\r
-fail:\r
- wl_func_put(e);\r
- }\r
- DHD_EVENT_WAKE_UNLOCK(dhd);\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
- } else {\r
- break;\r
- }\r
- }\r
- complete_and_exit(&tsk->completed, 0);\r
-#endif\r
-}\r
-\r
-void\r
-wl_func_send(void *params, void *cb_func, void *cb_argu)\r
-{\r
- struct wl_timer_params *timer_params = params;\r
-\r
- if (timer_params == NULL) {\r
- TIMER_ERROR("wlan", "Stale ignored\n");\r
- return;\r
- }\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- if (timer_params->func_workq == NULL) {\r
- TIMER_ERROR("wlan", "Event handler is not created\n");\r
- return;\r
- }\r
-#endif\r
-\r
- if (likely(!wl_func_enq(timer_params, cb_func, cb_argu))) {\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- queue_work(timer_params->func_workq, &timer_params->func_work);\r
-#else\r
- if (timer_params->thr_func_ctl.thr_pid >= 0) {\r
- up(&timer_params->thr_func_ctl.sema);\r
- }\r
-#endif\r
- }\r
-}\r
-\r
-static s32\r
-wl_func_create_handler(struct wl_timer_params *timer_params)\r
-{\r
- int ret = 0;\r
- TIMER_TRACE("wlan", "Enter\n");\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- if (!timer_params->func_workq) {\r
- timer_params->func_workq = alloc_workqueue("timer_funcd",\r
- WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);\r
- }\r
- if (!timer_params->func_workq) {\r
- TIMER_ERROR("wlan", "func_workq alloc_workqueue failed\n");\r
- ret = -ENOMEM;\r
- } else {\r
- INIT_WORK(&timer_params->func_work, wl_func_handler);\r
- }\r
-#else\r
- PROC_START(wl_func_handler, timer_params, &timer_params->thr_func_ctl, 0, "timer_funcd");\r
- if (timer_params->thr_func_ctl.thr_pid < 0) {\r
- ret = -ENOMEM;\r
- }\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-static void\r
-wl_func_destroy_handler(struct wl_timer_params *timer_params)\r
-{\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- if (timer_params && timer_params->func_workq) {\r
- cancel_work_sync(&timer_params->func_work);\r
- destroy_workqueue(timer_params->func_workq);\r
- timer_params->func_workq = NULL;\r
- }\r
-#else\r
- if (timer_params->thr_func_ctl.thr_pid >= 0) {\r
- PROC_STOP(&timer_params->thr_func_ctl);\r
- }\r
-#endif\r
-}\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-static void wl_timer_handler(struct work_struct *data);\r
-#define WL_TIMER_HANDLER() static void wl_timer_handler(struct work_struct *data)\r
-#else\r
-static int wl_timer_handler(void *data);\r
-#define WL_TIMER_HANDLER() static int wl_timer_handler(void *data)\r
-#endif\r
-\r
-WL_TIMER_HANDLER()\r
-{\r
- struct wl_timer_params *timer_params = NULL;\r
- struct timer_handler_list *node, *next;\r
- dhd_pub_t *dhd;\r
- unsigned long flags = 0;\r
- unsigned long cur_jiffies, diff_jiffies, min_jiffies = 0;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
- tsk_ctl_t *tsk = (tsk_ctl_t *)data;\r
- timer_params = (struct wl_timer_params *)tsk->parent;\r
-#else\r
- BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, timer_work);\r
-#endif\r
-\r
- dhd = timer_params->pub;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
- while (1) {\r
- if (down_interruptible(&tsk->sema) == 0) {\r
- SMP_RD_BARRIER_DEPENDS();\r
- if (tsk->terminated) {\r
- break;\r
- }\r
-#endif\r
- DHD_EVENT_WAKE_LOCK(dhd);\r
- DHD_GENERAL_LOCK(dhd, flags);\r
- if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {\r
- TIMER_ERROR("wlan", "BUS is DOWN.\n");\r
- DHD_GENERAL_UNLOCK(dhd, flags);\r
- goto exit;\r
- }\r
- DHD_GENERAL_UNLOCK(dhd, flags);\r
- cur_jiffies = jiffies;\r
- list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
- if (node->tmo_ms) {\r
- if (time_after(cur_jiffies, node->tmo_jiffies)) {\r
- wl_func_send(timer_params, node->cb_func, node->cb_argu);\r
- node->tmo_ms = 0;\r
- } else {\r
- diff_jiffies = node->tmo_jiffies - cur_jiffies;\r
- if (min_jiffies == 0)\r
- min_jiffies = diff_jiffies;\r
- else if (diff_jiffies < min_jiffies)\r
- min_jiffies = diff_jiffies;\r
- }\r
- }\r
- }\r
- if (min_jiffies)\r
- mod_timer(&timer_params->timer, jiffies + min_jiffies);\r
-exit:\r
- DHD_EVENT_WAKE_UNLOCK(dhd);\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
- } else {\r
- break;\r
- }\r
- }\r
- complete_and_exit(&tsk->completed, 0);\r
-#endif\r
-}\r
-\r
-void\r
-wl_timer_kick_handler(wl_timer_params_t *timer_params)\r
-{\r
- if (timer_params == NULL) {\r
- TIMER_ERROR("wlan", "timer_params not ready\n");\r
- return;\r
- }\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- if (timer_params->timer_workq == NULL) {\r
- TIMER_ERROR("wlan", "timer handler is not created\n");\r
- return;\r
- }\r
- queue_work(timer_params->timer_workq, &timer_params->timer_work);\r
-#else\r
- if (timer_params->thr_timer_ctl.thr_pid >= 0) {\r
- up(&timer_params->thr_timer_ctl.sema);\r
- }\r
-#endif\r
-}\r
-\r
-static void\r
-wl_timer_timeout(unsigned long data)\r
-{\r
- struct wl_timer_params *timer_params = (struct wl_timer_params *)data;\r
-\r
- if (!timer_params) {\r
- TIMER_ERROR("wlan", "timer_params is not ready\n");\r
- return;\r
- }\r
-\r
- TIMER_TRACE("wlan", "timer expired\n");\r
- wl_timer_kick_handler(timer_params);\r
-}\r
-\r
-static s32\r
-wl_timer_create_handler(struct wl_timer_params *timer_params)\r
-{\r
- int ret = 0;\r
-\r
- TIMER_TRACE("wlan", "Enter\n");\r
- \r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- if (!timer_params->timer_workq) {\r
- timer_params->timer_workq = alloc_workqueue("timerd",\r
- WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);\r
- }\r
- if (!timer_params->timer_workq) {\r
- TIMER_ERROR("wlan", "timer_workq alloc_workqueue failed\n");\r
- ret = -ENOMEM;\r
- } else {\r
- INIT_WORK(&timer_params->timer_work, wl_timer_handler);\r
- }\r
-#else\r
- PROC_START(wl_timer_handler, timer_params, &timer_params->thr_timer_ctl, 0, "timerd");\r
- if (timer_params->thr_timer_ctl.thr_pid < 0) {\r
- ret = -ENOMEM;\r
- }\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-static void\r
-wl_timer_destroy_handler(struct wl_timer_params *timer_params)\r
-{\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
- if (timer_params && timer_params->timer_workq) {\r
- cancel_work_sync(&timer_params->timer_work);\r
- destroy_workqueue(timer_params->timer_workq);\r
- timer_params->timer_workq = NULL;\r
- }\r
-#else\r
- if (timer_params->thr_timer_ctl.thr_pid >= 0) {\r
- PROC_STOP(&timer_params->thr_timer_ctl);\r
- }\r
-#endif\r
-}\r
-\r
-static void\r
-wl_timer_free(struct wl_timer_params *timer_params)\r
-{\r
- timer_handler_list_t *node, *next;\r
-\r
- list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
- TIMER_TRACE(node->net->name, "Free timer\n");\r
- list_del(&node->list);\r
- kfree(node);\r
- }\r
-}\r
-\r
-void\r
-wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)\r
-{\r
- wl_timer_params_t *timer_params = dhd->timer_params;\r
- timer_handler_list_t *node, *next;\r
- bool found = FALSE;\r
-\r
- list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
- if (node->timer == timer) {\r
- node->tmo_ms = tmo_ms;\r
- if (tmo_ms) {\r
- TIMER_TRACE(node->net->name, "update timer %dms\n", tmo_ms);\r
- node->tmo_jiffies = jiffies + msecs_to_jiffies(tmo_ms);\r
- wl_timer_kick_handler(timer_params);\r
- }\r
- found = TRUE;\r
- break;\r
- }\r
- }\r
- if (!found)\r
- TIMER_ERROR("wlan", "timer not found\n");\r
-}\r
-\r
-void\r
-wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)\r
-{\r
- dhd_pub_t *dhd = dhd_get_pub(net);\r
- wl_timer_params_t *timer_params = dhd->timer_params;\r
- timer_handler_list_t *node, *next, *leaf;\r
-\r
- list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
- if (node->timer == timer) {\r
- TIMER_TRACE(net->name, "timer already registered\n");\r
- return;\r
- }\r
- }\r
-\r
- leaf = kmalloc(sizeof(timer_handler_list_t), GFP_KERNEL);\r
- if (!leaf) {\r
- TIMER_ERROR(net->name, "Memory alloc failure %d\n",\r
- (int)sizeof(timer_handler_list_t));\r
- return;\r
- }\r
- memset(leaf, 0, sizeof(timer_handler_list_t));\r
- leaf->net = net;\r
- leaf->timer = timer;\r
- leaf->cb_func = cb_func;\r
- leaf->cb_argu = net;\r
- TIMER_ERROR(net->name, "timer registered tmo=%d\n", leaf->tmo_ms);\r
- list_add_tail(&leaf->list, &timer_params->timer_list);\r
-\r
- return;\r
-}\r
-\r
-void\r
-wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)\r
-{\r
- dhd_pub_t *dhd = dhd_get_pub(net);\r
- wl_timer_params_t *timer_params = dhd->timer_params;\r
- timer_handler_list_t *node, *next;\r
-\r
- list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
- if (node->timer == timer) {\r
- TIMER_TRACE(net->name, "timer deregistered\n");\r
- list_del(&node->list);\r
- kfree(node);\r
- }\r
- }\r
- return;\r
-}\r
-\r
-static s32\r
-wl_timer_init_priv(struct wl_timer_params *timer_params)\r
-{\r
- s32 err = 0;\r
-\r
- INIT_LIST_HEAD(&timer_params->timer_list);\r
- if (wl_timer_create_handler(timer_params))\r
- return -ENOMEM;\r
- wl_func_init_eq(timer_params);\r
- if (wl_func_create_handler(timer_params))\r
- return -ENOMEM;\r
-\r
- return err;\r
-}\r
-\r
-static void\r
-wl_timer_deinit_priv(struct wl_timer_params *timer_params)\r
-{\r
- wl_timer_free(timer_params);\r
- wl_func_destroy_handler(timer_params);\r
- wl_func_flush_eq(timer_params);\r
- wl_timer_destroy_handler(timer_params);\r
-}\r
-\r
-void\r
-wl_timer_dettach(dhd_pub_t *dhdp)\r
-{\r
- struct wl_timer_params *timer_params = dhdp->timer_params;\r
-\r
- if (timer_params) {\r
- if (timer_pending(&timer_params->timer))\r
- del_timer_sync(&timer_params->timer);\r
- wl_timer_deinit_priv(timer_params);\r
- kfree(timer_params);\r
- dhdp->timer_params = NULL;\r
- }\r
-}\r
-\r
-s32\r
-wl_timer_attach(struct net_device *net)\r
-{\r
- struct dhd_pub *dhdp = dhd_get_pub(net);\r
- struct wl_timer_params *timer_params = NULL;\r
- s32 err = 0;\r
-\r
- timer_params = kmalloc(sizeof(wl_timer_params_t), GFP_KERNEL);\r
- if (!timer_params) {\r
- TIMER_ERROR(net->name, "Failed to allocate memory (%zu)\n",\r
- sizeof(wl_timer_params_t));\r
- return -ENOMEM;\r
- }\r
- dhdp->timer_params = timer_params;\r
- memset(timer_params, 0, sizeof(wl_timer_params_t));\r
- timer_params->pub = dhdp;\r
-\r
- err = wl_timer_init_priv(timer_params);\r
- if (err) {\r
- TIMER_ERROR(net->name, "Failed to wl_timer_init_priv (%d)\n", err);\r
- goto exit;\r
- }\r
- init_timer_compat(&timer_params->timer, wl_timer_timeout, timer_params);\r
-\r
-exit:\r
- if (err)\r
- wl_timer_dettach(dhdp);\r
- return err;\r
-}\r
-#else\r
-void\r
-wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)\r
-{\r
- if (timer_pending(timer))\r
- del_timer_sync(timer);\r
- if (tmo_ms)\r
- mod_timer(timer, jiffies + msecs_to_jiffies(tmo_ms));\r
-}\r
-\r
-void\r
-wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)\r
-{\r
- init_timer_compat(timer, cb_func, net);\r
-}\r
-\r
-void\r
-wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)\r
-{\r
- if (timer_pending(timer))\r
- del_timer_sync(timer);\r
-}\r
-#endif\r
+#include <wl_android.h>
+#ifdef WL_TIMER
+
+#define TIMER_ERROR(name, arg1, args...) \
+ do { \
+ if (android_msg_level & ANDROID_ERROR_LEVEL) { \
+ printf("[%s] TIMER-ERROR) %s : " arg1, name, __func__, ## args); \
+ } \
+ } while (0)
+#define TIMER_TRACE(name, arg1, args...) \
+ do { \
+ if (android_msg_level & ANDROID_TRACE_LEVEL) { \
+ printf("[%s] TIMER-TRACE) %s : " arg1, name, __func__, ## args); \
+ } \
+ } while (0)
+
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+ 4 && __GNUC_MINOR__ >= 6))
+#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
+(entry) = list_first_entry((ptr), type, member); \
+_Pragma("GCC diagnostic pop") \
+
+#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_LIST_FIRST_ENTRY(entry, ptr, type, member) \
+(entry) = list_first_entry((ptr), type, member); \
+
+#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
+entry = container_of((ptr), type, member); \
+
+#endif /* STRICT_GCC_WARNINGS */
+
+typedef void(*FUNC_HANDLER) (void *cb_argu);
+
+struct wl_func_q {
+ struct list_head eq_list;
+ FUNC_HANDLER cb_func;
+ void *cb_argu;
+};
+
+typedef void(*TIMER_HANDLER) (void *cb_argu);
+
+typedef struct timer_handler_list {
+ struct list_head list;
+ struct net_device *net;
+ timer_list_compat_t *timer;
+ TIMER_HANDLER cb_func;
+ void *cb_argu;
+ uint tmo_ms;
+ ulong tmo_jiffies;
+} timer_handler_list_t;
+
+typedef struct wl_timer_params {
+ dhd_pub_t *pub;
+ struct list_head timer_list;
+ struct list_head eq_list;
+ timer_list_compat_t timer;
+ spinlock_t eq_lock;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ struct workqueue_struct *timer_workq;
+ struct work_struct timer_work;
+ struct workqueue_struct *func_workq;
+ struct work_struct func_work;
+#else
+ tsk_ctl_t thr_timer_ctl;
+ tsk_ctl_t thr_func_ctl;
+#endif
+} wl_timer_params_t;
+
+static unsigned long
+wl_func_lock_eq(struct wl_timer_params *timer_params)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&timer_params->eq_lock, flags);
+ return flags;
+}
+
+static void
+wl_func_unlock_eq(struct wl_timer_params *timer_params, unsigned long flags)
+{
+ spin_unlock_irqrestore(&timer_params->eq_lock, flags);
+}
+
+static void
+wl_func_init_eq_lock(struct wl_timer_params *timer_params)
+{
+ spin_lock_init(&timer_params->eq_lock);
+}
+
+static void
+wl_func_init_eq(struct wl_timer_params *timer_params)
+{
+ wl_func_init_eq_lock(timer_params);
+ INIT_LIST_HEAD(&timer_params->eq_list);
+}
+
+static void
+wl_func_flush_eq(struct wl_timer_params *timer_params)
+{
+ struct wl_func_q *e;
+ unsigned long flags;
+
+ flags = wl_func_lock_eq(timer_params);
+ while (!list_empty_careful(&timer_params->eq_list)) {
+ BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);
+ list_del(&e->eq_list);
+ kfree(e);
+ }
+ wl_func_unlock_eq(timer_params, flags);
+}
+
+static struct wl_func_q *
+wl_func_deq(struct wl_timer_params *timer_params)
+{
+ struct wl_func_q *e = NULL;
+ unsigned long flags;
+
+ flags = wl_func_lock_eq(timer_params);
+ if (likely(!list_empty(&timer_params->eq_list))) {
+ BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);
+ list_del(&e->eq_list);
+ }
+ wl_func_unlock_eq(timer_params, flags);
+
+ return e;
+}
+
+static s32
+wl_func_enq(struct wl_timer_params *timer_params,
+ void *cb_func, void *cb_argu)
+{
+ struct wl_func_q *e;
+ s32 err = 0;
+ uint32 funcq_size;
+ unsigned long flags;
+ gfp_t aflags;
+
+ funcq_size = sizeof(struct wl_func_q);
+ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
+ e = kzalloc(funcq_size, aflags);
+ if (unlikely(!e)) {
+ TIMER_ERROR("wlan", "funcq_size alloc failed %d\n", funcq_size);
+ return -ENOMEM;
+ }
+ e->cb_func = cb_func;
+ e->cb_argu = cb_argu;
+ flags = wl_func_lock_eq(timer_params);
+ list_add_tail(&e->eq_list, &timer_params->eq_list);
+ wl_func_unlock_eq(timer_params, flags);
+
+ return err;
+}
+
+static void
+wl_func_put(struct wl_func_q *e)
+{
+ kfree(e);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+static void wl_func_handler(struct work_struct *data);
+#define WL_FUNC_HANDLER() static void wl_func_handler(struct work_struct *data)
+#else
+static int wl_func_handler(void *data);
+#define WL_FUNC_HANDLER() static int wl_func_handler(void *data)
+#endif
+
+WL_FUNC_HANDLER()
+{
+ struct wl_timer_params *timer_params = NULL;
+ struct wl_func_q *e;
+ struct net_device *net = NULL;
+ dhd_pub_t *dhd;
+ unsigned long flags = 0;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
+ timer_params = (struct wl_timer_params *)tsk->parent;
+#else
+ BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, func_work);
+#endif
+
+ dhd = timer_params->pub;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
+ while (1) {
+ if (down_interruptible(&tsk->sema) == 0) {
+ SMP_RD_BARRIER_DEPENDS();
+ if (tsk->terminated) {
+ break;
+ }
+#endif
+ DHD_EVENT_WAKE_LOCK(dhd);
+ while ((e = wl_func_deq(timer_params))) {
+ DHD_GENERAL_LOCK(dhd, flags);
+ if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {
+ TIMER_ERROR(net->name, "BUS is DOWN.\n");
+ DHD_GENERAL_UNLOCK(dhd, flags);
+ goto fail;
+ }
+ DHD_GENERAL_UNLOCK(dhd, flags);
+ e->cb_func(e->cb_argu);
+fail:
+ wl_func_put(e);
+ }
+ DHD_EVENT_WAKE_UNLOCK(dhd);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
+ } else {
+ break;
+ }
+ }
+ complete_and_exit(&tsk->completed, 0);
+#endif
+}
+
+void
+wl_func_send(void *params, void *cb_func, void *cb_argu)
+{
+ struct wl_timer_params *timer_params = params;
+
+ if (timer_params == NULL) {
+ TIMER_ERROR("wlan", "Stale ignored\n");
+ return;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ if (timer_params->func_workq == NULL) {
+ TIMER_ERROR("wlan", "Event handler is not created\n");
+ return;
+ }
+#endif
+
+ if (likely(!wl_func_enq(timer_params, cb_func, cb_argu))) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ queue_work(timer_params->func_workq, &timer_params->func_work);
+#else
+ if (timer_params->thr_func_ctl.thr_pid >= 0) {
+ up(&timer_params->thr_func_ctl.sema);
+ }
+#endif
+ }
+}
+
+static s32
+wl_func_create_handler(struct wl_timer_params *timer_params)
+{
+ int ret = 0;
+ TIMER_TRACE("wlan", "Enter\n");
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ if (!timer_params->func_workq) {
+ timer_params->func_workq = alloc_workqueue("timer_funcd",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);
+ }
+ if (!timer_params->func_workq) {
+ TIMER_ERROR("wlan", "func_workq alloc_workqueue failed\n");
+ ret = -ENOMEM;
+ } else {
+ INIT_WORK(&timer_params->func_work, wl_func_handler);
+ }
+#else
+ PROC_START(wl_func_handler, timer_params, &timer_params->thr_func_ctl, 0, "timer_funcd");
+ if (timer_params->thr_func_ctl.thr_pid < 0) {
+ ret = -ENOMEM;
+ }
+#endif
+
+ return ret;
+}
+
+static void
+wl_func_destroy_handler(struct wl_timer_params *timer_params)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ if (timer_params && timer_params->func_workq) {
+ cancel_work_sync(&timer_params->func_work);
+ destroy_workqueue(timer_params->func_workq);
+ timer_params->func_workq = NULL;
+ }
+#else
+ if (timer_params->thr_func_ctl.thr_pid >= 0) {
+ PROC_STOP(&timer_params->thr_func_ctl);
+ }
+#endif
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+static void wl_timer_handler(struct work_struct *data);
+#define WL_TIMER_HANDLER() static void wl_timer_handler(struct work_struct *data)
+#else
+static int wl_timer_handler(void *data);
+#define WL_TIMER_HANDLER() static int wl_timer_handler(void *data)
+#endif
+
+WL_TIMER_HANDLER()
+{
+ struct wl_timer_params *timer_params = NULL;
+ struct timer_handler_list *node, *next;
+ dhd_pub_t *dhd;
+ unsigned long flags = 0;
+ unsigned long cur_jiffies, diff_jiffies, min_jiffies = 0;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
+ timer_params = (struct wl_timer_params *)tsk->parent;
+#else
+ BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, timer_work);
+#endif
+
+ dhd = timer_params->pub;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
+ while (1) {
+ if (down_interruptible(&tsk->sema) == 0) {
+ SMP_RD_BARRIER_DEPENDS();
+ if (tsk->terminated) {
+ break;
+ }
+#endif
+ DHD_EVENT_WAKE_LOCK(dhd);
+ DHD_GENERAL_LOCK(dhd, flags);
+ if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {
+ TIMER_ERROR("wlan", "BUS is DOWN.\n");
+ DHD_GENERAL_UNLOCK(dhd, flags);
+ goto exit;
+ }
+ DHD_GENERAL_UNLOCK(dhd, flags);
+ cur_jiffies = jiffies;
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {
+ if (node->tmo_ms) {
+ if (time_after(cur_jiffies, node->tmo_jiffies)) {
+ wl_func_send(timer_params, node->cb_func, node->cb_argu);
+ node->tmo_ms = 0;
+ } else {
+ diff_jiffies = node->tmo_jiffies - cur_jiffies;
+ if (min_jiffies == 0)
+ min_jiffies = diff_jiffies;
+ else if (diff_jiffies < min_jiffies)
+ min_jiffies = diff_jiffies;
+ }
+ }
+ }
+ if (min_jiffies)
+ mod_timer(&timer_params->timer, jiffies + min_jiffies);
+exit:
+ DHD_EVENT_WAKE_UNLOCK(dhd);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
+ } else {
+ break;
+ }
+ }
+ complete_and_exit(&tsk->completed, 0);
+#endif
+}
+
+void
+wl_timer_kick_handler(wl_timer_params_t *timer_params)
+{
+ if (timer_params == NULL) {
+ TIMER_ERROR("wlan", "timer_params not ready\n");
+ return;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ if (timer_params->timer_workq == NULL) {
+ TIMER_ERROR("wlan", "timer handler is not created\n");
+ return;
+ }
+ queue_work(timer_params->timer_workq, &timer_params->timer_work);
+#else
+ if (timer_params->thr_timer_ctl.thr_pid >= 0) {
+ up(&timer_params->thr_timer_ctl.sema);
+ }
+#endif
+}
+
+static void
+wl_timer_timeout(unsigned long data)
+{
+ struct wl_timer_params *timer_params = (struct wl_timer_params *)data;
+
+ if (!timer_params) {
+ TIMER_ERROR("wlan", "timer_params is not ready\n");
+ return;
+ }
+
+ TIMER_TRACE("wlan", "timer expired\n");
+ wl_timer_kick_handler(timer_params);
+}
+
+static s32
+wl_timer_create_handler(struct wl_timer_params *timer_params)
+{
+ int ret = 0;
+
+ TIMER_TRACE("wlan", "Enter\n");
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ if (!timer_params->timer_workq) {
+ timer_params->timer_workq = alloc_workqueue("timerd",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);
+ }
+ if (!timer_params->timer_workq) {
+ TIMER_ERROR("wlan", "timer_workq alloc_workqueue failed\n");
+ ret = -ENOMEM;
+ } else {
+ INIT_WORK(&timer_params->timer_work, wl_timer_handler);
+ }
+#else
+ PROC_START(wl_timer_handler, timer_params, &timer_params->thr_timer_ctl, 0, "timerd");
+ if (timer_params->thr_timer_ctl.thr_pid < 0) {
+ ret = -ENOMEM;
+ }
+#endif
+
+ return ret;
+}
+
+static void
+wl_timer_destroy_handler(struct wl_timer_params *timer_params)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
+ if (timer_params && timer_params->timer_workq) {
+ cancel_work_sync(&timer_params->timer_work);
+ destroy_workqueue(timer_params->timer_workq);
+ timer_params->timer_workq = NULL;
+ }
+#else
+ if (timer_params->thr_timer_ctl.thr_pid >= 0) {
+ PROC_STOP(&timer_params->thr_timer_ctl);
+ }
+#endif
+}
+
+static void
+wl_timer_free(struct wl_timer_params *timer_params)
+{
+ timer_handler_list_t *node, *next;
+
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {
+ TIMER_TRACE(node->net->name, "Free timer\n");
+ list_del(&node->list);
+ kfree(node);
+ }
+}
+
+void
+wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)
+{
+ wl_timer_params_t *timer_params = dhd->timer_params;
+ timer_handler_list_t *node, *next;
+ bool found = FALSE;
+
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {
+ if (node->timer == timer) {
+ node->tmo_ms = tmo_ms;
+ if (tmo_ms) {
+ TIMER_TRACE(node->net->name, "update timer %dms\n", tmo_ms);
+ node->tmo_jiffies = jiffies + msecs_to_jiffies(tmo_ms);
+ wl_timer_kick_handler(timer_params);
+ }
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ TIMER_ERROR("wlan", "timer not found\n");
+}
+
+void
+wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)
+{
+ dhd_pub_t *dhd = dhd_get_pub(net);
+ wl_timer_params_t *timer_params = dhd->timer_params;
+ timer_handler_list_t *node, *next, *leaf;
+
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {
+ if (node->timer == timer) {
+ TIMER_TRACE(net->name, "timer already registered\n");
+ return;
+ }
+ }
+
+ leaf = kmalloc(sizeof(timer_handler_list_t), GFP_KERNEL);
+ if (!leaf) {
+ TIMER_ERROR(net->name, "Memory alloc failure %d\n",
+ (int)sizeof(timer_handler_list_t));
+ return;
+ }
+ memset(leaf, 0, sizeof(timer_handler_list_t));
+ leaf->net = net;
+ leaf->timer = timer;
+ leaf->cb_func = cb_func;
+ leaf->cb_argu = net;
+ TIMER_ERROR(net->name, "timer registered tmo=%d\n", leaf->tmo_ms);
+ list_add_tail(&leaf->list, &timer_params->timer_list);
+
+ return;
+}
+
+void
+wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)
+{
+ dhd_pub_t *dhd = dhd_get_pub(net);
+ wl_timer_params_t *timer_params = dhd->timer_params;
+ timer_handler_list_t *node, *next;
+
+ list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {
+ if (node->timer == timer) {
+ TIMER_TRACE(net->name, "timer deregistered\n");
+ list_del(&node->list);
+ kfree(node);
+ }
+ }
+ return;
+}
+
+static s32
+wl_timer_init_priv(struct wl_timer_params *timer_params)
+{
+ s32 err = 0;
+
+ INIT_LIST_HEAD(&timer_params->timer_list);
+ if (wl_timer_create_handler(timer_params))
+ return -ENOMEM;
+ wl_func_init_eq(timer_params);
+ if (wl_func_create_handler(timer_params))
+ return -ENOMEM;
+
+ return err;
+}
+
+static void
+wl_timer_deinit_priv(struct wl_timer_params *timer_params)
+{
+ wl_timer_free(timer_params);
+ wl_func_destroy_handler(timer_params);
+ wl_func_flush_eq(timer_params);
+ wl_timer_destroy_handler(timer_params);
+}
+
+void
+wl_timer_dettach(dhd_pub_t *dhdp)
+{
+ struct wl_timer_params *timer_params = dhdp->timer_params;
+
+ if (timer_params) {
+ if (timer_pending(&timer_params->timer))
+ del_timer_sync(&timer_params->timer);
+ wl_timer_deinit_priv(timer_params);
+ kfree(timer_params);
+ dhdp->timer_params = NULL;
+ }
+}
+
+s32
+wl_timer_attach(struct net_device *net)
+{
+ struct dhd_pub *dhdp = dhd_get_pub(net);
+ struct wl_timer_params *timer_params = NULL;
+ s32 err = 0;
+
+ timer_params = kmalloc(sizeof(wl_timer_params_t), GFP_KERNEL);
+ if (!timer_params) {
+ TIMER_ERROR(net->name, "Failed to allocate memory (%zu)\n",
+ sizeof(wl_timer_params_t));
+ return -ENOMEM;
+ }
+ dhdp->timer_params = timer_params;
+ memset(timer_params, 0, sizeof(wl_timer_params_t));
+ timer_params->pub = dhdp;
+
+ err = wl_timer_init_priv(timer_params);
+ if (err) {
+ TIMER_ERROR(net->name, "Failed to wl_timer_init_priv (%d)\n", err);
+ goto exit;
+ }
+ init_timer_compat(&timer_params->timer, wl_timer_timeout, timer_params);
+
+exit:
+ if (err)
+ wl_timer_dettach(dhdp);
+ return err;
+}
+#else
+void
+wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)
+{
+ if (timer_pending(timer))
+ del_timer_sync(timer);
+ if (tmo_ms)
+ mod_timer(timer, jiffies + msecs_to_jiffies(tmo_ms));
+}
+
+void
+wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)
+{
+ init_timer_compat(timer, cb_func, net);
+}
+
+void
+wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)
+{
+ if (timer_pending(timer))
+ del_timer_sync(timer);
+}
+#endif
-#ifndef _wl_timer_\r
-#define _wl_timer_\r
-s32 wl_timer_attach(struct net_device *net);\r
-void wl_timer_dettach(dhd_pub_t *dhdp);\r
-void wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func);\r
-void wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer);\r
-void wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms);\r
-#endif\r
+#ifndef _wl_timer_
+#define _wl_timer_
+s32 wl_timer_attach(struct net_device *net);
+void wl_timer_dettach(dhd_pub_t *dhdp);
+void wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func);
+void wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer);
+void wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms);
+#endif