diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile index 5588178bfce2..2550ff67477e 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile @@ -12,7 +12,6 @@ CONFIG_BCMDHD_PROPTXSTATUS := y CONFIG_BCMDHD_AG := y #CONFIG_DHD_USE_STATIC_BUF := y CONFIG_VTS_SUPPORT := y -#CONFIG_LOGTRACE := y CONFIG_MACH_PLATFORM := y #CONFIG_BCMDHD_DTS := y @@ -33,6 +32,7 @@ DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \ dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o \ dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o \ bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \ + dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o \ hnd_pktq.o hnd_pktpool.o dhd_config.o wl_android_ext.o #BCMDHD_SDIO @@ -60,9 +60,6 @@ DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1 \ ifneq ($(CONFIG_PCI_MSI),) DHDCFLAGS += -DDHD_USE_MSI endif -ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y) - DHDCFLAGS += -DDHD_USE_STATIC_CTRLBUF -endif DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \ dhd_msgbuf.o @@ -74,10 +71,15 @@ DHDCFLAGS += -DUSBOS_TX_THREAD -DBCMDBUS -DBCMTRXV2 -DDBUS_USB_LOOPBACK \ -DBDC DHDCFLAGS += -DBCM_REQUEST_FW -DEXTERNAL_FW_PATH #DHDCFLAGS :=$(filter-out -DENABLE_INSMOD_NO_FW_LOAD,$(DHDCFLAGS)) +ifneq ($(CONFIG_BCMDHD_CUSB),) + DHDCFLAGS += -DBCMUSBDEV_COMPOSITE + DHDCFLAGS :=$(filter-out -DENABLE_INSMOD_NO_FW_LOAD,$(DHDCFLAGS)) +endif DHDOFILES += dbus.o dbus_usb.o dbus_usb_linux.o dhd_cdc.o dhd_wlfc.o endif +#PROPTXSTATUS ifeq ($(CONFIG_BCMDHD_PROPTXSTATUS),y) ifneq ($(CONFIG_BCMDHD_USB),) DHDCFLAGS += -DPROP_TXSTATUS @@ -99,16 +101,9 @@ DHDCFLAGS += -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG \ -DCUSTOM_COUNTRY_CODE -DDHD_FW_COREDUMP -DEXPLICIT_DISCIF_CLEANUP DHDOFILES += bcmxtlv.o dhd_rtt.o bcm_app_utils.o -CONFIG_LOGTRACE := y endif endif -#LOGTRACE -ifeq ($(CONFIG_LOGTRACE),y) - DHDCFLAGS += -DSHOW_LOGTRACE - DHDOFILES += dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o -endif - # MESH support for kernel 3.10 later ifeq ($(CONFIG_WL_MESH),y) DHDCFLAGS += -DWLMESH diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmevent.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmevent.c old mode 100755 new mode 100644 diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c index 31b05ce71b72..eafeb17f5c1a 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c @@ -1711,7 +1711,7 @@ sdioh_gpio_init(sdioh_info_t *sd) uint sdmmc_get_clock_rate(sdioh_info_t *sd) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) return 0; #else struct sdio_func *sdio_func = sd->func[0]; @@ -1724,7 +1724,7 @@ sdmmc_get_clock_rate(sdioh_info_t *sd) void sdmmc_set_clock_rate(sdioh_info_t *sd, uint hz) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) return; #else struct sdio_func *sdio_func = sd->func[0]; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c index aeec7761fdc3..00a75e6101b2 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c @@ -1443,7 +1443,7 @@ dbus_attach(osl_t *osh, int rxsize, int nrxq, int ntxq, dhd_pub_t *pub, dhd_bus = MALLOC(osh, sizeof(dhd_bus_t)); if (dhd_bus == NULL) { - DBUSERR(("%s: malloc failed %d\n", __FUNCTION__, sizeof(dhd_bus_t))); + DBUSERR(("%s: malloc failed %zu\n", __FUNCTION__, sizeof(dhd_bus_t))); return NULL; } @@ -2767,6 +2767,7 @@ dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype, } } else { pub = g_pub; + osh = pub->osh; } if (pub->bus) { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h index eb6edcb9b3ea..4a92d2f86715 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h @@ -1036,13 +1036,23 @@ typedef struct dhd_pub { #if defined(STAT_REPORT) void *stat_report_info; #endif - char *clm_path; /* module_param: path to clm vars file */ - char *conf_path; /* module_param: path to config vars file */ + char *clm_path; /* module_param: path to clm vars file */ + char *conf_path; /* module_param: path to config vars file */ struct dhd_conf *conf; /* Bus module handle */ void *adapter; /* adapter information, interrupt, fw path etc. */ #ifdef BCMDBUS bool dhd_remove; #endif /* BCMDBUS */ +#if defined(WL_WIRELESS_EXT) +#if defined(WL_ESCAN) + void *escan; +#else + void *iscan; +#endif +#endif +#ifdef WL_EXT_IAPSTA + void *iapsta_params; +#endif } dhd_pub_t; typedef struct { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c index bbab84aebdc6..a556587b1cb9 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c @@ -4997,9 +4997,13 @@ void dhd_free_download_buffer(dhd_pub_t *dhd, void *buffer, int length) #define EAP_PRINT(str) \ DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: " str "\n", \ ifname, direction ? "TX" : "RX")); +#else +#define EAP_PRINT(str) +#endif /* DHD_8021X_DUMP */ /* Parse EAPOL 4 way handshake messages */ void -dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction) +dhd_dump_eapol_4way_message(dhd_pub_t *dhd, char *ifname, + char *dump_data, bool direction) { unsigned char type; int pair, ack, mic, kerr, req, sec, install; @@ -5008,31 +5012,43 @@ dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction) type = dump_data[15]; if (type == 0) { if ((dump_data[22] == 1) && (dump_data[18] == 1)) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_REQID; EAP_PRINT("EAP Packet, Request, Identity"); } else if ((dump_data[22] == 1) && (dump_data[18] == 2)) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_RSPID; EAP_PRINT("EAP Packet, Response, Identity"); } else if (dump_data[22] == 254) { if (dump_data[30] == 1) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_WSC_START; EAP_PRINT("EAP Packet, WSC Start"); } else if (dump_data[30] == 4) { if (dump_data[41] == 4) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M1; EAP_PRINT("EAP Packet, WPS M1"); } else if (dump_data[41] == 5) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M2; EAP_PRINT("EAP Packet, WPS M2"); } else if (dump_data[41] == 7) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M3; EAP_PRINT("EAP Packet, WPS M3"); } else if (dump_data[41] == 8) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M4; EAP_PRINT("EAP Packet, WPS M4"); } else if (dump_data[41] == 9) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M5; EAP_PRINT("EAP Packet, WPS M5"); } else if (dump_data[41] == 10) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M6; EAP_PRINT("EAP Packet, WPS M6"); } else if (dump_data[41] == 11) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M7; EAP_PRINT("EAP Packet, WPS M7"); } else if (dump_data[41] == 12) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_M8; EAP_PRINT("EAP Packet, WPS M8"); } } else if (dump_data[30] == 5) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_DONE; EAP_PRINT("EAP Packet, WSC Done"); } } else { @@ -5051,12 +5067,16 @@ dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction) install = 0 != (us_tmp & 0x40); if (!sec && !mic && ack && !install && pair && !kerr && !req) { + dhd->conf->eapol_status = EAPOL_STATUS_WPA_M1; EAP_PRINT("EAPOL Packet, 4-way handshake, M1"); } else if (pair && !install && !ack && mic && !sec && !kerr && !req) { + dhd->conf->eapol_status = EAPOL_STATUS_WPA_M2; EAP_PRINT("EAPOL Packet, 4-way handshake, M2"); } else if (pair && ack && mic && sec && !kerr && !req) { + dhd->conf->eapol_status = EAPOL_STATUS_WPA_M3; EAP_PRINT("EAPOL Packet, 4-way handshake, M3"); } else if (pair && !install && !ack && mic && sec && !req && !kerr) { + dhd->conf->eapol_status = EAPOL_STATUS_WPA_M4; EAP_PRINT("EAPOL Packet, 4-way handshake, M4"); } else { DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: ver %d, type %d, replay %d\n", @@ -5069,7 +5089,6 @@ dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction) dump_data[14], dump_data[15], dump_data[30])); } } -#endif /* DHD_8021X_DUMP */ #ifdef REPORT_FATAL_TIMEOUTS void init_dhd_timeouts(dhd_pub_t *pub) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c index 4f333a464fda..d11a4b1311cd 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c @@ -61,31 +61,31 @@ const cihp_name_map_t chip_name_map [] = { /* ChipID Chiprev AG CLM ChipName ModuleName */ #ifdef BCMSDIO {BCM43362_CHIP_ID, 0, DONT_CARE, FALSE, "RK901a0", ""}, - //{BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "RK901a2", "nvram_AP6210.txt"}, - {BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "bcm40181a2", "nvram_ap6181.txt"}, + //{BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "RK901a2", "AP6210"}, + {BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "bcm40181a2", "ap6181"}, {BCM4330_CHIP_ID, 4, FW_TYPE_G, FALSE, "RK903b2", ""}, - {BCM4330_CHIP_ID, 4, FW_TYPE_AG, FALSE, "RK903_ag", "nvram_AP6330.txt"}, - {BCM43430_CHIP_ID, 0, DONT_CARE, FALSE, "bcm43438a0", "nvram_ap6212.txt"}, - {BCM43430_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43438a1", "nvram_ap6212a.txt"}, - {BCM43430_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43436b0", "nvram_ap6236.txt"}, + {BCM4330_CHIP_ID, 4, FW_TYPE_AG, FALSE, "RK903_ag", "AP6330"}, + {BCM43430_CHIP_ID, 0, DONT_CARE, FALSE, "bcm43438a0", "ap6212"}, + {BCM43430_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43438a1", "ap6212a"}, + {BCM43430_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43436b0", "ap6236"}, {BCM43012_CHIP_ID, 1, DONT_CARE, TRUE, "bcm43013b0", ""}, {BCM4334_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4334b1_ag", ""}, {BCM43340_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""}, {BCM43341_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""}, - {BCM4324_CHIP_ID, 5, DONT_CARE, FALSE, "bcm43241b4_ag", "nvram_ap62x2.txt"}, - {BCM4335_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4339a0_ag", "nvram_AP6335.txt"}, - {BCM4339_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4339a0_ag", "nvram_AP6335.txt"}, - {BCM4345_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", "nvram_ap6255.txt"}, + {BCM4324_CHIP_ID, 5, DONT_CARE, FALSE, "bcm43241b4_ag", "ap62x2"}, + {BCM4335_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4339a0_ag", "AP6335"}, + {BCM4339_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4339a0_ag", "AP6335"}, + {BCM4345_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", "ap6255"}, {BCM43454_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", ""}, - {BCM4345_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", "nvram_ap6256.txt"}, + {BCM4345_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", "ap6256"}, {BCM43454_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", ""}, - {BCM4354_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4354a1_ag", "nvram_ap6354.txt"}, - {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "nvram_ap6356.txt"}, - {BCM4356_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "nvram_ap6356.txt"}, + {BCM4354_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4354a1_ag", "ap6354"}, + {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "ap6356"}, + {BCM4356_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "ap6356"}, {BCM4371_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", ""}, {BCM43569_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4358a3_ag", ""}, {BCM4359_CHIP_ID, 5, DONT_CARE, FALSE, "bcm4359b1_ag", ""}, - {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_ag", "nvram_ap6398s.txt"}, + {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_ag", "ap6398s"}, {BCM4362_CHIP_ID, 0, DONT_CARE, TRUE, "bcm43752a0_ag", ""}, #endif #ifdef BCMPCIE @@ -480,6 +480,9 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) (row->ag_type == ag_type || row->ag_type == DONT_CARE)) { strcpy(name_ptr, "fw_"); strcat(fw_path, row->chip_name); +#ifdef BCMUSBDEV_COMPOSITE + strcat(fw_path, "_cusb"); +#endif if (fw_type == FW_TYPE_APSTA) strcat(fw_path, "_apsta.bin"); else if (fw_type == FW_TYPE_P2P) @@ -573,7 +576,12 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path) for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { const cihp_name_map_t* row = &chip_name_map[i]; if (row->chip == chip && row->chiprev == chiprev && strlen(row->module_name)) { - strcpy(name_ptr, row->module_name); + strcpy(name_ptr, "nvram_"); + strcat(name_ptr, row->module_name); +#ifdef BCMUSBDEV_COMPOSITE + strcat(name_ptr, "_cusb"); +#endif + strcat(name_ptr, ".txt"); } } @@ -638,7 +646,7 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path) } i--; } - name_ptr = conf_path[i]; + name_ptr = &conf_path[i]; for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { const cihp_name_map_t* row = &chip_name_map[i]; @@ -757,28 +765,23 @@ dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec) } int -dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec, int nodfs) +dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec) { int bcmerror = -1, i; struct dhd_conf *conf = dhd->conf; - conf_country_list_t *country_list; - - if ((nodfs > 0 || dhd->op_mode & DHD_FLAG_HOSTAP_MODE) && - conf->country_list_nodfs.count > 0) { - country_list = &conf->country_list_nodfs; - } else { - country_list = &conf->country_list; - } + conf_country_list_t *country_list = &conf->country_list; for (i = 0; i < country_list->count; i++) { if (!strncmp(cspec->country_abbrev, country_list->cspec[i]->country_abbrev, 2)) { memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ); cspec->rev = country_list->cspec[i]->rev; - printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev); - return 0; + bcmerror = 0; } } + if (!bcmerror) + printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev); + return bcmerror; } @@ -823,12 +826,12 @@ dhd_conf_fix_country(dhd_pub_t *dhd) dtoh32(list->count)<11)) { CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n", __FUNCTION__, bcmerror, dtoh32(list->count))); - dhd_conf_map_country_list(dhd, &dhd->conf->cspec, 0); + dhd_conf_map_country_list(dhd, &dhd->conf->cspec); if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) { strcpy(cspec.country_abbrev, "US"); cspec.rev = 0; strcpy(cspec.ccode, "US"); - dhd_conf_map_country_list(dhd, &cspec, 0); + dhd_conf_map_country_list(dhd, &cspec); dhd_conf_set_country(dhd, &cspec); } } @@ -1677,8 +1680,6 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param) */ if (!strncmp("country_list=", full_param, len_param)) { country_list = &dhd->conf->country_list; - } else if (!strncmp("country_list_nodfs=", full_param, len_param)) { - country_list = &dhd->conf->country_list_nodfs; } if (country_list) { pick_tmp = data; @@ -1716,8 +1717,6 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param) } if (!strncmp("country_list=", full_param, len_param)) { printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count); - } else if (!strncmp("country_list_nodfs=", full_param, len_param)) { - printf("%s: %d nodfs country in list\n", __FUNCTION__, conf->country_list.count); } } else @@ -1976,6 +1975,7 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->sd_f2_blocksize = (int)simple_strtol(data, NULL, 10); printf("%s: sd_f2_blocksize = %d\n", __FUNCTION__, conf->sd_f2_blocksize); } +#if defined(HW_OOB) else if (!strncmp("oob_enabled_later=", full_param, len_param)) { if (!strncmp(data, "0", 1)) conf->oob_enabled_later = FALSE; @@ -1983,6 +1983,7 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->oob_enabled_later = TRUE; printf("%s: oob_enabled_later = %d\n", __FUNCTION__, conf->oob_enabled_later); } +#endif else if (!strncmp("dpc_cpucore=", full_param, len_param)) { conf->dpc_cpucore = (int)simple_strtol(data, NULL, 10); printf("%s: dpc_cpucore = %d\n", __FUNCTION__, conf->dpc_cpucore); @@ -2029,16 +2030,9 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len); } else if (!strncmp("txctl_tmo_fix=", full_param, len_param)) { - conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 10); + conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 0); printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix); } - else if (!strncmp("tx_in_rx=", full_param, len_param)) { - if (!strncmp(data, "0", 1)) - conf->tx_in_rx = FALSE; - else - conf->tx_in_rx = TRUE; - printf("%s: tx_in_rx = %d\n", __FUNCTION__, conf->tx_in_rx); - } else if (!strncmp("tx_max_offset=", full_param, len_param)) { conf->tx_max_offset = (int)simple_strtol(data, NULL, 10); printf("%s: tx_max_offset = %d\n", __FUNCTION__, conf->tx_max_offset); @@ -2261,10 +2255,6 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound); } #endif - else if (!strncmp("num_different_channels=", full_param, len_param)) { - conf->num_different_channels = (int)simple_strtol(data, NULL, 10); - printf("%s: num_different_channels = %d\n", __FUNCTION__, conf->num_different_channels); - } else if (!strncmp("tsq=", full_param, len_param)) { conf->tsq = (int)simple_strtol(data, NULL, 10); printf("%s: tsq = %d\n", __FUNCTION__, conf->tsq); @@ -2277,6 +2267,14 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) conf->dhd_ioctl_timeout_msec = (int)simple_strtol(data, NULL, 10); printf("%s: dhd_ioctl_timeout_msec = %d\n", __FUNCTION__, conf->dhd_ioctl_timeout_msec); } + else if (!strncmp("in4way=", full_param, len_param)) { + conf->in4way = (int)simple_strtol(data, NULL, 0); + printf("%s: in4way = 0x%x\n", __FUNCTION__, conf->in4way); + } + else if (!strncmp("max_wait_gc_time=", full_param, len_param)) { + conf->max_wait_gc_time = (int)simple_strtol(data, NULL, 0); + printf("%s: max_wait_gc_time = %d\n", __FUNCTION__, conf->max_wait_gc_time); + } else if (!strncmp("wl_preinit=", full_param, len_param)) { if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) { CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); @@ -2475,8 +2473,8 @@ dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable) conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy"); printf("%s: txglomsize=%d, deferred_tx_len=%d\n", __FUNCTION__, conf->txglomsize, conf->deferred_tx_len); - printf("%s: tx_in_rx=%d, txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__, - conf->tx_in_rx, conf->txinrx_thres, conf->dhd_txminmax); + printf("%s: txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__, + conf->txinrx_thres, conf->dhd_txminmax); printf("%s: tx_max_offset=%d, txctl_tmo_fix=%d\n", __FUNCTION__, conf->tx_max_offset, conf->txctl_tmo_fix); @@ -2539,8 +2537,8 @@ dhd_conf_set_wl_preinit(dhd_pub_t *dhd, char *data) char name[32], *pch, *pick_tmp, *pick_tmp2; /* Process wl_preinit: - * wl_preinit=[cmd]/[val], [cmd]/[val] \ - * Ex: wl_preinit=86/0, mpc/0 + * wl_preinit=[cmd]=[val], [cmd]=[val] + * Ex: wl_preinit=86=0, mpc=0 */ pick_tmp = data; while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) { @@ -2577,15 +2575,13 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) struct dhd_conf *conf = dhd->conf; dhd_conf_set_intiovar(dhd, WLC_UP, "up", 0, 0, FALSE); - dhd_conf_map_country_list(dhd, &conf->cspec, 0); + dhd_conf_map_country_list(dhd, &conf->cspec); dhd_conf_set_country(dhd, &conf->cspec); dhd_conf_fix_country(dhd); dhd_conf_get_country(dhd, &dhd->dhd_cspec); dhd_conf_set_intiovar(dhd, WLC_SET_BAND, "WLC_SET_BAND", conf->band, 0, FALSE); dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_timeout", conf->bcn_timeout, 0, FALSE); - if (conf->fw_type == FW_TYPE_MESH) - conf->pm = PM_OFF; dhd_conf_set_intiovar(dhd, WLC_SET_PM, "PM", conf->pm, 0, FALSE); dhd_conf_set_intiovar(dhd, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, TRUE); dhd_conf_set_intiovar(dhd, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE); @@ -2637,7 +2633,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip); #endif dhd_conf_free_country_list(&conf->country_list); - dhd_conf_free_country_list(&conf->country_list_nodfs); if (conf->magic_pkt_filter_add) { kfree(conf->magic_pkt_filter_add); conf->magic_pkt_filter_add = NULL; @@ -2713,14 +2708,15 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->txglom_ext = FALSE; conf->tx_max_offset = 0; conf->txglomsize = SDPCM_DEFGLOM_SIZE; - conf->txctl_tmo_fix = 300; - conf->tx_in_rx = TRUE; + conf->txctl_tmo_fix = -1; conf->txglom_mode = SDPCM_TXGLOM_CPY; conf->deferred_tx_len = 0; conf->dhd_txminmax = 1; conf->txinrx_thres = -1; conf->sd_f2_blocksize = 0; +#if defined(HW_OOB) conf->oob_enabled_later = FALSE; +#endif conf->orphan_move = 0; #endif #ifdef BCMPCIE @@ -2733,7 +2729,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->pm = -1; conf->pm_in_suspend = -1; conf->suspend_bcn_li_dtim = -1; - conf->num_different_channels = -1; conf->xmit_in_suspend = TRUE; conf->ap_in_suspend = 0; #ifdef SUSPEND_EVENT @@ -2760,6 +2755,8 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->pktprio8021x = -1; conf->ctrl_resched = 2; conf->dhd_ioctl_timeout_msec = 0; + conf->in4way = NO_SCAN_IN4WAY | WAIT_DISCONNECTED; + conf->max_wait_gc_time = 300; #ifdef ISAM_PREINIT memset(conf->isam_init, 0, sizeof(conf->isam_init)); memset(conf->isam_config, 0, sizeof(conf->isam_config)); @@ -2768,9 +2765,11 @@ dhd_conf_preinit(dhd_pub_t *dhd) for (i=0; imchan[i], -1, sizeof(mchan_params_t)); } - if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || - conf->chip == BCM4371_CHIP_ID || conf->chip == BCM43569_CHIP_ID || - conf->chip == BCM4359_CHIP_ID || conf->chip == BCM4362_CHIP_ID) { + if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID || + conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || + conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID || + conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID || + conf->chip == BCM4362_CHIP_ID) { #ifdef DHDTCPACK_SUPPRESS #ifdef BCMSDIO conf->tcpack_sup_mode = TCPACK_SUP_REPLACE; @@ -2786,7 +2785,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->dhd_txminmax = -1; conf->txinrx_thres = 128; conf->sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE; - conf->oob_enabled_later = TRUE; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) conf->orphan_move = 1; #else @@ -2830,7 +2828,6 @@ dhd_conf_reset(dhd_pub_t *dhd) dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip); #endif dhd_conf_free_country_list(&dhd->conf->country_list); - dhd_conf_free_country_list(&dhd->conf->country_list_nodfs); if (dhd->conf->magic_pkt_filter_add) { kfree(dhd->conf->magic_pkt_filter_add); dhd->conf->magic_pkt_filter_add = NULL; @@ -2883,7 +2880,6 @@ dhd_conf_detach(dhd_pub_t *dhd) dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip); #endif dhd_conf_free_country_list(&dhd->conf->country_list); - dhd_conf_free_country_list(&dhd->conf->country_list_nodfs); if (dhd->conf->magic_pkt_filter_add) { kfree(dhd->conf->magic_pkt_filter_add); dhd->conf->magic_pkt_filter_add = NULL; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h index 6adf2d070750..6bf5574b9b0f 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h @@ -101,6 +101,35 @@ typedef struct mchan_params { int miracast_mode; } mchan_params_t; +enum in4way_flags { + NO_SCAN_IN4WAY = (1 << (0)), + NO_BTC_IN4WAY = (1 << (1)), + DONT_DELETE_GC_AFTER_WPS = (1 << (2)), + WAIT_DISCONNECTED = (1 << (3)), +}; + +enum eapol_status { + EAPOL_STATUS_NONE = 0, + EAPOL_STATUS_WPS_REQID, + EAPOL_STATUS_WPS_RSPID, + EAPOL_STATUS_WPS_WSC_START, + EAPOL_STATUS_WPS_M1, + EAPOL_STATUS_WPS_M2, + EAPOL_STATUS_WPS_M3, + EAPOL_STATUS_WPS_M4, + EAPOL_STATUS_WPS_M5, + EAPOL_STATUS_WPS_M6, + EAPOL_STATUS_WPS_M7, + EAPOL_STATUS_WPS_M8, + EAPOL_STATUS_WPS_DONE, + EAPOL_STATUS_WPA_START, + EAPOL_STATUS_WPA_M1, + EAPOL_STATUS_WPA_M2, + EAPOL_STATUS_WPA_M3, + EAPOL_STATUS_WPA_M4, + EAPOL_STATUS_WPA_END +}; + typedef struct dhd_conf { uint chip; uint chiprev; @@ -109,7 +138,6 @@ typedef struct dhd_conf { wl_mac_list_ctrl_t nv_by_mac; wl_chip_nv_path_list_ctrl_t nv_by_chip; conf_country_list_t country_list; - conf_country_list_t country_list_nodfs; int band; int bw_cap[2]; wl_country_t cspec; @@ -148,7 +176,6 @@ typedef struct dhd_conf { int tx_max_offset; uint txglomsize; int txctl_tmo_fix; - bool tx_in_rx; bool txglom_mode; uint deferred_tx_len; /*txglom_bucket_size: @@ -176,7 +203,6 @@ typedef struct dhd_conf { uint8 tcpack_sup_mode; #endif int pktprio8021x; - int num_different_channels; int xmit_in_suspend; int ap_in_suspend; #ifdef SUSPEND_EVENT @@ -202,6 +228,9 @@ typedef struct dhd_conf { struct mchan_params mchan[MCHAN_MAX_NUM]; char *wl_preinit; int tsq; + uint eapol_status; + uint in4way; + uint max_wait_gc_time; } dhd_conf_t; #ifdef BCMSDIO @@ -227,7 +256,7 @@ int dhd_conf_set_bufiovar(dhd_pub_t *dhd, uint cmd, char *name, char *buf, int l uint dhd_conf_get_band(dhd_pub_t *dhd); int dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec); int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec); -int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec, int nodfs); +int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec); int dhd_conf_fix_country(dhd_pub_t *dhd); bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel); void dhd_conf_set_wme(dhd_pub_t *dhd, int mode); @@ -240,6 +269,7 @@ int dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev); uint dhd_conf_get_chip(void *context); uint dhd_conf_get_chiprev(void *context); int dhd_conf_get_pm(dhd_pub_t *dhd); + #ifdef PROP_TXSTATUS int dhd_conf_get_disable_proptx(dhd_pub_t *dhd); #endif diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c index dbdcbfa77f0d..7a407d5a0586 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c @@ -301,9 +301,10 @@ int dhd_wlan_init_gpio(void) dhd_wlan_resources[0].start = dhd_wlan_resources[0].end = host_oob_irq; dhd_wlan_resources[0].flags = host_oob_irq_flags; - printf("%s: WL_REG_ON=%d, WL_HOST_WAKE=%d\n", __FUNCTION__, gpio_wl_reg_on, gpio_wl_host_wake); - printf("%s: oob_irq=%d, oob_irq_flags=0x%x\n", __FUNCTION__, host_oob_irq, host_oob_irq_flags); + printf("%s: WL_HOST_WAKE=%d, oob_irq=%d, oob_irq_flags=0x%x\n", __FUNCTION__, + gpio_wl_host_wake, host_oob_irq, host_oob_irq_flags); #endif /* CUSTOMER_OOB */ + printf("%s: WL_REG_ON=%d\n", __FUNCTION__, gpio_wl_reg_on); return 0; } diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c index d8be26cd8cef..47cfe8ac72ff 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c @@ -378,8 +378,8 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) goto exit; } - DHD_TRACE(("%s: TCP ACK Suppress mode %d -> mode %d\n", - __FUNCTION__, dhdp->tcpack_sup_mode, mode)); + printf("%s: TCP ACK Suppress mode %d -> mode %d\n", + __FUNCTION__, dhdp->tcpack_sup_mode, mode); /* Pre-process routines to change a new mode as per previous mode */ switch (prev_mode) { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c index 87c5df2a8a0f..f3ad4029e18c 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c @@ -84,9 +84,6 @@ #include #include #include -#ifdef WL_ESCAN -#include -#endif #include #include #ifdef CONFIG_HAS_WAKELOCK @@ -259,9 +256,8 @@ extern bool ap_cfg_running; extern bool ap_fw_loaded; #endif -#ifdef DHD_8021X_DUMP -extern void dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction); -#endif /* DHD_8021X_DUMP */ +extern void dhd_dump_eapol_4way_message(dhd_pub_t *dhd, char *ifname, + char *dump_data, bool direction); #ifdef FIX_CPU_MIN_CLOCK #include @@ -294,6 +290,9 @@ static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL; #endif #include +#ifdef WL_ESCAN +#include +#endif /* Maximum STA per radio */ #define DHD_MAX_STA 32 @@ -4094,11 +4093,6 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, uint8 *addr) return ret; } -#ifdef SOFTAP -extern struct net_device *ap_net_dev; -extern tsk_ctl_t ap_eth_ctl; /* ap netdev heper thread ctl */ -#endif - #ifdef DHD_WMF void dhd_update_psta_interface_for_sta(dhd_pub_t* dhdp, char* ifname, void* ea, void* event_data) @@ -4475,22 +4469,6 @@ dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event) DHD_OS_WAKE_LOCK(&dhd->pub); DHD_PERIM_LOCK(&dhd->pub); -#ifdef SOFTAP - { - unsigned long flags; - bool in_ap = FALSE; - DHD_GENERAL_LOCK(&dhd->pub, flags); - in_ap = (ap_net_dev != NULL); - DHD_GENERAL_UNLOCK(&dhd->pub, flags); - - if (in_ap) { - DHD_ERROR(("attempt to set MAC for %s in AP Mode, blocked. \n", - ifp->net->name)); - goto done; - } - } -#endif /* SOFTAP */ - // terence 20160907: fix for not able to set mac when wlan0 is down if (ifp == NULL || !ifp->set_macaddress) { goto done; @@ -4541,23 +4519,6 @@ dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event) goto done; } -#ifdef SOFTAP - { - bool in_ap = FALSE; - unsigned long flags; - DHD_GENERAL_LOCK(&dhd->pub, flags); - in_ap = (ap_net_dev != NULL); - DHD_GENERAL_UNLOCK(&dhd->pub, flags); - - if (in_ap) { - DHD_ERROR(("set MULTICAST list for %s in AP Mode, blocked. \n", - ifp->net->name)); - ifp->set_multicast = FALSE; - goto done; - } - } -#endif /* SOFTAP */ - if (ifp == NULL || !dhd->pub.up) { DHD_ERROR(("%s: interface info not available/down \n", __FUNCTION__)); goto done; @@ -4693,42 +4654,25 @@ static const char *_get_packet_type_str(uint16 type) return packet_type_info[n].str; } -#endif /* DHD_RX_DUMP || DHD_TX_DUMP */ -#if defined(DHD_TX_DUMP) void -dhd_tx_dump(struct net_device *ndev, osl_t *osh, void *pkt) +dhd_trx_dump(struct net_device *ndev, uint8 *dump_data, uint datalen, bool tx) { - uint8 *dump_data; uint16 protocol; char *ifname; - dump_data = PKTDATA(osh, pkt); protocol = (dump_data[12] << 8) | dump_data[13]; ifname = ndev ? ndev->name : "N/A"; - DHD_ERROR(("TX DUMP[%s] - %s\n", ifname, _get_packet_type_str(protocol))); - - if (protocol == ETHER_TYPE_802_1X) { - dhd_dump_eapol_4way_message(ifname, dump_data, TRUE); + if (protocol != ETHER_TYPE_BRCM) { + DHD_ERROR(("%s DUMP[%s] - %s\n", tx?"Tx":"Rx", ifname, + _get_packet_type_str(protocol))); +#if defined(DHD_TX_FULL_DUMP) || defined(DHD_RX_FULL_DUMP) + prhex("Data", dump_data, datalen); +#endif /* DHD_TX_FULL_DUMP || DHD_RX_FULL_DUMP */ } - -#if defined(DHD_TX_FULL_DUMP) - { - int i; - uint datalen; - datalen = PKTLEN(osh, pkt); - - for (i = 0; i < datalen; i++) { - printk("%02X ", dump_data[i]); - if ((i & 15) == 15) - printk("\n"); - } - printk("\n"); - } -#endif /* DHD_TX_FULL_DUMP */ } -#endif /* DHD_TX_DUMP */ +#endif /* DHD_TX_DUMP || DHD_RX_DUMP */ /* This routine do not support Packet chain feature, Currently tested for * proxy arp feature @@ -4888,9 +4832,7 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) #endif /* DHD_LOSSLESS_ROAMING */ DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED); atomic_inc(&dhd->pend_8021x_cnt); -#if defined(DHD_8021X_DUMP) - dhd_dump_eapol_4way_message(dhd_ifname(dhdp, ifidx), pktdata, TRUE); -#endif /* DHD_8021X_DUMP */ + dhd_dump_eapol_4way_message(dhdp, dhd_ifname(dhdp, ifidx), pktdata, TRUE); } if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { @@ -4943,8 +4885,8 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) #endif #if defined(DHD_TX_DUMP) - ndev = dhd_idx2net(dhdp, ifidx); - dhd_tx_dump(ndev, dhdp->osh, pktbuf); + dhd_trx_dump(dhd_idx2net(dhdp, ifidx), PKTDATA(dhdp->osh, pktbuf), + PKTLEN(dhdp->osh, pktbuf), TRUE); #endif /* terence 20150901: Micky add to ajust the 802.1X priority */ /* Set the 802.1X packet with the highest priority 7 */ @@ -5719,10 +5661,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) void *skbhead = NULL; void *skbprev = NULL; uint16 protocol; -#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) || defined(DHD_DHCP_DUMP) || \ - defined(DHD_ICMP_DUMP) || defined(DHD_WAKE_STATUS) unsigned char *dump_data; -#endif /* DHD_RX_DUMP || DHD_8021X_DUMP || DHD_DHCP_DUMP || DHD_ICMP_DUMP || DHD_WAKE_STATUS */ #ifdef DHD_MCAST_REGEN uint8 interface_role; if_flow_lkup_t *if_flow_lkup; @@ -5953,17 +5892,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) eth = skb->data; len = skb->len; -#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) || defined(DHD_DHCP_DUMP) || \ - defined(DHD_ICMP_DUMP) || defined(DHD_WAKE_STATUS) dump_data = skb->data; -#endif /* DHD_RX_DUMP || DHD_8021X_DUMP || DHD_DHCP_DUMP || DHD_ICMP_DUMP || DHD_WAKE_STATUS */ protocol = (skb->data[12] << 8) | skb->data[13]; if (protocol == ETHER_TYPE_802_1X) { DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED); -#ifdef DHD_8021X_DUMP - dhd_dump_eapol_4way_message(dhd_ifname(dhdp, ifidx), dump_data, FALSE); -#endif /* DHD_8021X_DUMP */ + dhd_dump_eapol_4way_message(dhdp, dhd_ifname(dhdp, ifidx), dump_data, FALSE); } if (protocol != ETHER_TYPE_BRCM && protocol == ETHER_TYPE_IP) { @@ -5975,33 +5909,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* DHD_ICMP_DUMP */ } #ifdef DHD_RX_DUMP - DHD_ERROR(("RX DUMP[%s] - %s\n", - dhd_ifname(dhdp, ifidx), _get_packet_type_str(protocol))); - if (protocol != ETHER_TYPE_BRCM) { - if (dump_data[0] == 0xFF) { - DHD_ERROR(("%s: BROADCAST\n", __FUNCTION__)); - - if ((dump_data[12] == 8) && - (dump_data[13] == 6)) { - DHD_ERROR(("%s: ARP %d\n", - __FUNCTION__, dump_data[0x15])); - } - } else if (dump_data[0] & 1) { - DHD_ERROR(("%s: MULTICAST: " MACDBG "\n", - __FUNCTION__, MAC2STRDBG(dump_data))); - } -#ifdef DHD_RX_FULL_DUMP - { - int k; - for (k = 0; k < skb->len; k++) { - printk("%02X ", dump_data[k]); - if ((k & 15) == 15) - printk("\n"); - } - printk("\n"); - } -#endif /* DHD_RX_FULL_DUMP */ - } + dhd_trx_dump(dhd_idx2net(dhdp, ifidx), dump_data, skb->len, FALSE); #endif /* DHD_RX_DUMP */ #if defined(DHD_WAKE_STATUS) && defined(DHD_WAKEPKT_DUMP) if (pkt_wake) { @@ -8376,7 +8284,7 @@ dhd_stop(struct net_device *net) #else wl_android_wifi_off(net, TRUE); #ifdef WL_EXT_IAPSTA - wl_ext_iapsta_dettach_netdev(); + wl_ext_iapsta_dettach_netdev(net, ifidx); #endif } else { if (dhd->pub.conf->deepsleep) @@ -8550,7 +8458,7 @@ dhd_open(struct net_device *net) if (!dhd_download_fw_on_driverload) { DHD_ERROR(("\n%s\n", dhd_version)); #ifdef WL_EXT_IAPSTA - wl_ext_iapsta_attach_netdev(net, ifidx); + wl_ext_iapsta_attach_netdev(net, ifidx, dhd->iflist[ifidx]->bssidx); #endif #if defined(USE_INITIAL_SHORT_DWELL_TIME) g_first_broadcast_scan = TRUE; @@ -9079,6 +8987,9 @@ dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock) unregister_netdev(ifp->net); else unregister_netdevice(ifp->net); +#ifdef WL_EXT_IAPSTA + wl_ext_iapsta_dettach_netdev(ifp->net, ifidx); +#endif } ifp->net = NULL; } @@ -9428,6 +9339,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen #elif defined(BCMDBUS) wifi_adapter_info_t *adapter = data; #endif +#ifdef GET_CUSTOM_MAC_ENABLE + char hw_ether[62]; +#endif /* GET_CUSTOM_MAC_ENABLE */ dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -9472,7 +9386,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen #endif /* BT_OVER_SDIO */ #ifdef GET_CUSTOM_MAC_ENABLE - wifi_platform_get_mac_addr(dhd->adapter, dhd->pub.mac.octet); + wifi_platform_get_mac_addr(dhd->adapter, hw_ether); + bcopy(hw_ether, dhd->pub.mac.octet, sizeof(struct ether_addr)); #endif /* GET_CUSTOM_MAC_ENABLE */ #ifdef CUSTOM_FORCE_NODFS_FLAG dhd->pub.dhd_cflags |= WLAN_PLAT_NODFS_FLAG; @@ -9658,18 +9573,26 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen dhd_log_dump_init(&dhd->pub); #endif /* DHD_LOG_DUMP */ #if defined(WL_WIRELESS_EXT) - /* Attach and link in the iw */ - if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { - if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { - DHD_ERROR(("wl_iw_attach failed\n")); - goto fail; - } - dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; - } #ifdef WL_ESCAN - wl_escan_attach(net, &dhd->pub); + if (wl_escan_attach(net, &dhd->pub) != 0) { + DHD_ERROR(("wl_escan_attach failed\n")); + goto fail; + } +#else + /* Attach and link in the iw */ + if (wl_iw_attach(net, &dhd->pub) != 0) { + DHD_ERROR(("wl_iw_attach failed\n")); + goto fail; + } + dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; #endif /* WL_ESCAN */ #endif /* defined(WL_WIRELESS_EXT) */ +#ifdef WL_EXT_IAPSTA + if (wl_ext_iapsta_attach(&dhd->pub) != 0) { + DHD_ERROR(("wl_ext_iapsta_attach failed\n")); + goto fail; + } +#endif #ifdef SHOW_LOGTRACE ret = dhd_init_logstrs_array(osh, &dhd->event_data); @@ -11002,7 +10925,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_TRACE(("Enter %s\n", __FUNCTION__)); #ifdef DHDTCPACK_SUPPRESS - printf("%s: Set tcpack_sup_mode %d\n", __FUNCTION__, dhd->conf->tcpack_sup_mode); dhd_tcpack_suppress_set(dhd, dhd->conf->tcpack_sup_mode); #endif dhd->op_mode = 0; @@ -11946,7 +11868,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } else if (ret >= 1) { disable_proptx = 1; wlfc_enable = FALSE; - /* terence 20161229: we should set ampdu_hostreorder=0 when disalbe_proptx=1 */ + /* terence 20161229: we should set ampdu_hostreorder=0 when disable_proptx=1 */ hostreorder = 0; } @@ -12675,16 +12597,14 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) printf("%s\n", dhd_version); #ifdef WL_EXT_IAPSTA else - wl_ext_iapsta_attach_netdev(net, ifidx); + wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx); #endif -#ifdef WLMESH - if (ifidx != 0 && dhdp->conf->fw_type == FW_TYPE_MESH) { - if (_dhd_set_mac_address(dhd, ifidx, temp_addr) == 0) + if (ifidx != 0) { + if (_dhd_set_mac_address(dhd, ifidx, net->dev_addr) == 0) DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__)); else DHD_ERROR(("%s: _dhd_set_mac_address() failed\n", __FUNCTION__)); } -#endif if (need_rtnl_lock) err = register_netdev(net); @@ -12697,7 +12617,7 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) } #ifdef WL_EXT_IAPSTA if (ifidx == 0) - wl_ext_iapsta_attach_netdev(net, ifidx); + wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx); wl_ext_iapsta_attach_name(net, ifidx); #endif @@ -12912,14 +12832,18 @@ void dhd_detach(dhd_pub_t *dhdp) #endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ #if defined(WL_WIRELESS_EXT) - if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { - /* Detatch and unlink in the iw */ - wl_iw_detach(); - } #ifdef WL_ESCAN wl_escan_detach(dhdp); +#else + if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { + /* Detatch and unlink in the iw */ + wl_iw_detach(dhdp); + } #endif /* WL_ESCAN */ #endif /* defined(WL_WIRELESS_EXT) */ +#ifdef WL_EXT_IAPSTA + wl_ext_iapsta_dettach(dhdp); +#endif #ifdef DHD_ULP dhd_ulp_deinit(dhd->pub.osh, dhdp); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c index 342a53a4eb5e..84fa6e91608c 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c @@ -117,6 +117,7 @@ static int dhdsdio_resume(void *context); #define MAX_MEMBLOCK (32 * 1024) /* Block size used for downloading of dongle image */ #define MAX_DATA_BUF (64 * 1024) /* Must be large enough to hold biggest possible glom */ +#define MAX_MEM_BUF 4096 #ifndef DHD_FIRSTREAD #define DHD_FIRSTREAD 32 @@ -440,6 +441,7 @@ typedef struct dhd_bus { #endif /* defined (BT_OVER_SDIO) */ uint txglomframes; /* Number of tx glom frames (superframes) */ uint txglompkts; /* Number of packets from tx glom frames */ + uint8 *membuf; /* Buffer for dhdsdio_membytes */ } dhd_bus_t; @@ -2773,13 +2775,15 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) /* Need to lock here to protect txseq and SDIO tx calls */ + dhd_os_sdlock(bus->dhd); if (bus->dhd->conf->txctl_tmo_fix > 0 && !TXCTLOK(bus)) { bus->ctrl_wait = TRUE; + dhd_os_sdunlock(bus->dhd); wait_event_interruptible_timeout(bus->ctrl_tx_wait, TXCTLOK(bus), msecs_to_jiffies(bus->dhd->conf->txctl_tmo_fix)); + dhd_os_sdlock(bus->dhd); bus->ctrl_wait = FALSE; } - dhd_os_sdlock(bus->dhd); BUS_WAKE(bus); @@ -3372,6 +3376,7 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint s int bcmerror = 0; uint32 sdaddr; uint dsize; + uint8 *pdata; /* In remap mode, adjust address beyond socram and redirect * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize @@ -3400,10 +3405,19 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint s DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n", __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK))); - if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) { + if (dsize <= MAX_MEM_BUF) { + pdata = bus->membuf; + if (write) + memcpy(bus->membuf, data, dsize); + } else { + pdata = data; + } + if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, pdata, dsize))) { DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__)); break; } + if (dsize <= MAX_MEM_BUF && !write) + memcpy(data, bus->membuf, dsize); /* Adjust for next transfer (if any) */ if ((size -= dsize)) { @@ -5848,8 +5862,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) dhdsdio_sendpendctl(bus); } else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) && !bus->fcstate && DATAOK(bus) && - (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres) && - bus->dhd->conf->tx_in_rx) { + (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) { dhdsdio_sendfromq(bus, dhd_txbound); #ifdef DHDTCPACK_SUPPRESS /* In TCPACK_SUP_DELAYTX mode, do txinrx only if @@ -6736,7 +6749,8 @@ dhdsdio_dpc(dhd_bus_t *bus) * or clock availability. (Allows tx loop to check ipend if desired.) * (Unless register access seems hosed, as we may not be able to ACK...) */ - if (!bus->dhd->conf->oob_enabled_later && bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) { + if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) && + !(bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) { DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n", __FUNCTION__, rxdone, framecnt)); bus->intdis = FALSE; @@ -6794,7 +6808,7 @@ dhdsdio_dpc(dhd_bus_t *bus) } /* Resched the DPC if ctrl cmd is pending on bus credit */ if (bus->ctrl_frame_stat) { - if (bus->dhd->conf->txctl_tmo_fix > 0) { + if (bus->dhd->conf->txctl_tmo_fix) { set_current_state(TASK_INTERRUPTIBLE); if (!kthread_should_stop()) schedule_timeout(1); @@ -6842,7 +6856,8 @@ dhdsdio_dpc(dhd_bus_t *bus) * or clock availability. (Allows tx loop to check ipend if desired.) * (Unless register access seems hosed, as we may not be able to ACK...) */ - if (bus->dhd->conf->oob_enabled_later && bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) { + if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) && + (bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) { DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n", __FUNCTION__, rxdone, framecnt)); bus->intdis = FALSE; @@ -8151,6 +8166,23 @@ dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh) DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen); goto fail; } + /* Allocate buffer to membuf */ + bus->membuf = MALLOC(osh, MAX_MEM_BUF); + if (bus->membuf == NULL) { + DHD_ERROR(("%s: MALLOC of %d-byte membuf failed\n", + __FUNCTION__, MAX_MEM_BUF)); + if (bus->databuf) { +#ifndef CONFIG_DHD_USE_STATIC_BUF + MFREE(osh, bus->databuf, MAX_DATA_BUF); +#endif + bus->databuf = NULL; + } + /* release rxbuf which was already located as above */ + if (!bus->rxblen) + DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen); + goto fail; + } + memset(bus->membuf, 0, MAX_MEM_BUF); /* Align the buffer */ if ((uintptr)bus->databuf % DHD_SDALIGN) @@ -8427,6 +8459,11 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) bus->databuf = NULL; } + if (bus->membuf) { + MFREE(osh, bus->membuf, MAX_DATA_BUF); + bus->membuf = NULL; + } + if (bus->vars && bus->varsz) { MFREE(osh, bus->vars, bus->varsz); bus->vars = NULL; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c index 188a0ac00dc8..56605d336208 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c @@ -52,7 +52,7 @@ enum dhd_prealloc_index { #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 (30 * 1024) +#define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024) #define DHD_PREALLOC_MEMDUMP_RAM_SIZE (810 * 1024) #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) #define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (66 * 1024) @@ -252,6 +252,7 @@ static int dhd_init_wlan_mem(void) { int i; int j; + printk(KERN_ERR "%s(): %s\n", __func__, DHD_STATIC_VERSION_STR); for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) { wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE); @@ -332,7 +333,7 @@ static int dhd_init_wlan_mem(void) #endif /* BCMDHD_PCIE */ wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_memdump_ram_buf) + if (!wlan_static_dhd_memdump_ram_buf) goto err_mem_alloc; pr_err("%s: sectoin %d, size=%d\n", __func__, DHD_PREALLOC_MEMDUMP_RAM, DHD_PREALLOC_MEMDUMP_RAM_SIZE); @@ -446,8 +447,6 @@ static int dhd_init_wlan_mem(void) static int __init dhd_static_buf_init(void) { - printk(KERN_ERR "%s(): %s\n", __func__, DHD_STATIC_VERSION_STR); - dhd_init_wlan_mem(); return 0; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11s.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11s.h index 2d66d0b52e1a..8ad1693a97d0 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11s.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11s.h @@ -255,6 +255,7 @@ typedef struct mesh_config_ie mesh_config_ie_t; #define MESH_PEERING_STATE_STRINGS \ {"IDLE ", "OPNSNT", "CNFRCV", "OPNRCV", "ESTAB ", "HOLDNG"} +#ifdef WLMESH typedef BWL_PRE_PACKED_STRUCT struct mesh_peer_info { /* mesh_peer_instance as given in the spec. Note that, peer address * is stored in scb @@ -275,6 +276,27 @@ typedef BWL_PRE_PACKED_STRUCT struct mesh_peer_info { */ } BWL_POST_PACKED_STRUCT mesh_peer_info_t; +typedef BWL_PRE_PACKED_STRUCT struct mesh_peer_info_ext { + mesh_peer_info_t peer_info; + uint16 local_aid; /* AID generated by *local* to peer */ + struct ether_addr ea; /* peer ea */ + uint32 entry_state; /* see MESH_PEER_ENTRY_STATE_ACTIVE etc; valid + * ONLY for internal peering requests + */ + int rssi; +} BWL_POST_PACKED_STRUCT mesh_peer_info_ext_t; + +/* #ifdef WLMESH */ +typedef BWL_PRE_PACKED_STRUCT struct mesh_peer_info_dump { + uint32 buflen; + uint32 version; + uint32 count; /* number of results */ + mesh_peer_info_ext_t mpi_ext[1]; +} BWL_POST_PACKED_STRUCT mesh_peer_info_dump_t; +#define WL_MESH_PEER_RES_FIXED_SIZE (sizeof(mesh_peer_info_dump_t) - sizeof(mesh_peer_info_ext_t)) + +#endif /* WLMESH */ + /* once an entry is added into mesh_peer_list, if peering is lost, it will * get retried for peering, MAX_MESH_PEER_ENTRY_RETRIES times. after wards, it * wont get retried and will be moved to MESH_PEER_ENTRY_STATE_TIMEDOUT state, diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h index c014bb62f540..f3fe5e9f4629 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h @@ -46,6 +46,6 @@ #define EPI_VERSION_DEV 1.579.77.41 /* Driver Version String, ASCII, 32 chars max */ -#define EPI_VERSION_STR "1.579.77.41.9 (r)" +#define EPI_VERSION_STR "1.579.77.41.10 (r)" #endif /* _epivers_h_ */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h index 812182af77b0..da8392dc9b0f 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h @@ -12416,31 +12416,6 @@ typedef enum { #define WL_MESH_IOCTL_VERSION 1 #define MESH_IOC_BUFSZ 512 /* sufficient ioc buff size for mesh */ - -#ifdef WLMESH -typedef struct mesh_peer_info_ext { - mesh_peer_info_t peer_info; - uint8 pad1; - uint16 local_aid; /* AID generated by *local* to peer */ - uint32 entry_state; /* see MESH_PEER_ENTRY_STATE_ACTIVE etc; valid - * ONLY for internal peering requests - */ - int8 rssi; - uint8 pad2; - struct ether_addr ea; /* peer ea */ -} mesh_peer_info_ext_t; - -/* #ifdef WLMESH */ -typedef struct mesh_peer_info_dump { - uint32 buflen; - uint32 version; - uint16 count; /* number of results */ - uint16 remaining; /* remaining rsults */ - mesh_peer_info_ext_t mpi_ext[1]; -} mesh_peer_info_dump_t; -#define WL_MESH_PEER_RES_FIXED_SIZE (sizeof(mesh_peer_info_dump_t) - sizeof(mesh_peer_info_ext_t)) - -#endif /* WLMESH */ /* container for mesh iovtls & events */ typedef struct wl_mesh_ioc { uint16 version; /* interface command or event version */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h index 39fd6ff86efb..710380e4af92 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h @@ -33,6 +33,8 @@ #include #include #include +#include +#include /* If any feature uses the Generic Netlink Interface, put it here to enable WL_GENL * automatically @@ -67,6 +69,7 @@ typedef struct _compat_android_wifi_priv_cmd { #define ANDROID_ERROR_LEVEL 0x0001 #define ANDROID_TRACE_LEVEL 0x0002 #define ANDROID_INFO_LEVEL 0x0004 +#define ANDROID_EVENT_LEVEL 0x0008 #define ANDROID_ERROR(x) \ do { \ @@ -89,6 +92,13 @@ typedef struct _compat_android_wifi_priv_cmd { printk x; \ } \ } while (0) +#define ANDROID_EVENT(x) \ + do { \ + if (android_msg_level & ANDROID_EVENT_LEVEL) { \ + printk(KERN_ERR "ANDROID-EVENT) "); \ + printk x; \ + } \ + } while (0) /** * wl_android_init will be called from module init function (dhd_module_init now), similarly @@ -104,17 +114,26 @@ int wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len); s32 wl_netlink_send_msg(int pid, int type, int seq, const void *data, size_t size); #ifdef WL_EXT_IAPSTA -int wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx); -int wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx); -int wl_ext_iapsta_dettach_netdev(void); -u32 wl_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel); +int wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx); +int wl_ext_iapsta_attach_name(struct net_device *net, int ifidx); +int wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx); +u32 wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel); int wl_ext_iapsta_alive_preinit(struct net_device *dev); int wl_ext_iapsta_alive_postinit(struct net_device *dev); int wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data); +int wl_ext_iapsta_attach(dhd_pub_t *pub); +void wl_ext_iapsta_dettach(dhd_pub_t *pub); extern int op_mode; #endif int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len, int *bytes_written); +typedef struct wl_conn_info { + uint8 bssidx; + wlc_ssid_t ssid; + struct ether_addr bssid; + uint16 channel; +} wl_conn_info_t; +s32 wl_ext_connect(struct net_device *dev, wl_conn_info_t *conn_info); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) #define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len)) #endif @@ -231,6 +250,6 @@ int wl_ext_get_best_channel(struct net_device *net, #else struct wl_scan_results *bss_list, #endif - int *best_2g_ch, int *best_5g_ch + int ioctl_ver, int *best_2g_ch, int *best_5g_ch ); #endif /* _wl_android_ */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c index 6e7ad34812dc..1049663326bc 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c @@ -14,7 +14,9 @@ #include #include #include +#if defined(WL_WIRELESS_EXT) #include +#endif #include #include #include @@ -67,7 +69,7 @@ #define CMD_ISAM_CONFIG "ISAM_CONFIG" #define CMD_ISAM_ENABLE "ISAM_ENABLE" #define CMD_ISAM_DISABLE "ISAM_DISABLE" -#define CMD_ISAM_DUMP "ISAM_DUMP" +#define CMD_ISAM_STATUS "ISAM_STATUS" #ifdef PROP_TXSTATUS #ifdef PROP_TXSTATUS_VSDB #include @@ -138,6 +140,20 @@ int wl_ext_iovar_setbuf(struct net_device *dev, s8 *iovar_name, return ret; } +static int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name, + void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, + struct mutex* buf_sync) +{ + int ret; + + ret = wldev_iovar_setbuf_bsscfg(dev, iovar_name, param, paramlen, + buf, buflen, bsscfg_idx, buf_sync); + if (ret < 0) + ANDROID_ERROR(("%s: iovar_name=%s ret=%d\n", __FUNCTION__, iovar_name, ret)); + + return ret; +} + #ifdef WL_EXT_IAPSTA typedef enum IF_STATE { IF_STATE_INIT = 1, @@ -150,6 +166,7 @@ typedef enum APSTAMODE { IAPONLY_MODE, IAPSTA_MODE, IDUALAP_MODE, + ISTAAPAP_MODE, IMESHONLY_MODE, IMESHSTA_MODE, IMESHAP_MODE, @@ -208,7 +225,8 @@ typedef struct wl_if_info { ifmode_t ifmode; char prefix; wl_prio_t prio; - uint bssidx; + int ifidx; + uint8 bssidx; char ifname[IFNAMSIZ+1]; char ssid[DOT11_MAX_SSID_LEN]; struct ether_addr bssid; @@ -226,6 +244,7 @@ typedef struct wl_if_info { typedef struct wl_apsta_params { struct wl_if_info if_info[MAX_IF_NUM]; + struct dhd_pub *dhd; int ioctl_ver; bool init; bool rsdb; @@ -236,32 +255,7 @@ typedef struct wl_apsta_params { wait_queue_head_t netif_change_event; } wl_apsta_params_t; -static int wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len); -int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) -{ - int ret; - - ret = wldev_iovar_setbuf_bsscfg(dev, iovar_name, param, paramlen, - buf, buflen, bsscfg_idx, buf_sync); - if (ret < 0) - ANDROID_ERROR(("%s: iovar_name=%s ret=%d\n", __FUNCTION__, iovar_name, ret)); - - return ret; -} - -int wl_ext_iovar_getbuf_bsscfg(struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) -{ - int ret; - - ret = wldev_iovar_getbuf_bsscfg(dev, iovar_name, param, paramlen, - buf, buflen, bsscfg_idx, buf_sync); - if (ret < 0) - ANDROID_ERROR(("%s: iovar_name=%s ret=%d\n", __FUNCTION__, iovar_name, ret)); - - return ret; -} +static int wl_ext_enable_iface(struct net_device *dev, char *ifname); #endif /* Return a legacy chanspec given a new chanspec @@ -330,6 +324,41 @@ wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec) return chanspec; } +static void +wl_ext_ch_to_chanspec(int ioctl_ver, int ch, + struct wl_join_params *join_params, size_t *join_params_size) +{ + chanspec_t chanspec = 0; + + if (ch != 0) { + join_params->params.chanspec_num = 1; + join_params->params.chanspec_list[0] = ch; + + if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL) + chanspec |= WL_CHANSPEC_BAND_2G; + else + chanspec |= WL_CHANSPEC_BAND_5G; + + chanspec |= WL_CHANSPEC_BW_20; + chanspec |= WL_CHANSPEC_CTL_SB_NONE; + + *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE + + join_params->params.chanspec_num * sizeof(chanspec_t); + + join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; + join_params->params.chanspec_list[0] |= chanspec; + join_params->params.chanspec_list[0] = + wl_ext_chspec_host_to_driver(ioctl_ver, + join_params->params.chanspec_list[0]); + + join_params->params.chanspec_num = + htod32(join_params->params.chanspec_num); + ANDROID_TRACE(("join_params->params.chanspec_list[0]= %X, %d channels\n", + join_params->params.chanspec_list[0], + join_params->params.chanspec_num)); + } +} + #if defined(WL_EXT_IAPSTA) || defined(WL_CFG80211) || defined(WL_ESCAN) static chanspec_t wl_ext_chspec_from_legacy(chanspec_t legacy_chspec) @@ -388,7 +417,6 @@ wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver) val = 1; ret = wl_ext_ioctl(dev, WLC_GET_VERSION, &val, sizeof(val), 0); if (ret) { - ANDROID_ERROR(("WLC_GET_VERSION failed, err=%d\n", ret)); return ret; } val = dtoh32(val); @@ -403,7 +431,8 @@ wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver) } static int -wl_ext_set_chanspec(struct net_device *dev, uint16 channel, chanspec_t *ret_chspec) +wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver, + uint16 channel, chanspec_t *ret_chspec) { s32 _chan = channel; chanspec_t chspec = 0; @@ -417,27 +446,22 @@ wl_ext_set_chanspec(struct net_device *dev, uint16 channel, chanspec_t *ret_chsp u32 bw_cap; } param = {0, 0}; uint band; - int ioctl_ver = 0; if (_chan <= CH_MAX_2G_CHANNEL) band = IEEE80211_BAND_2GHZ; else band = IEEE80211_BAND_5GHZ; - wl_ext_get_ioctl_ver(dev, &ioctl_ver); if (band == IEEE80211_BAND_5GHZ) { param.band = WLC_BAND_5G; - err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param), + err = wl_ext_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param), iovar_buf, WLC_IOCTL_SMLEN, NULL); if (err) { if (err != BCME_UNSUPPORTED) { ANDROID_ERROR(("bw_cap failed, %d\n", err)); return err; } else { - err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); - if (err) { - ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err)); - } + err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap); if (bw_cap != WLC_N_BW_20ALL) bw = WL_CHANSPEC_BW_40; } @@ -459,17 +483,20 @@ wl_ext_set_chanspec(struct net_device *dev, uint16 channel, chanspec_t *ret_chsp if (wf_chspec_valid(chspec)) { fw_chspec = wl_ext_chspec_host_to_driver(ioctl_ver, chspec); if (fw_chspec != INVCHANSPEC) { - if ((err = wldev_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) { + if ((err = wl_ext_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) { if (bw == WL_CHANSPEC_BW_80) goto change_bw; wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1); printf("%s: channel %d\n", __FUNCTION__, _chan); } else if (err) { - ANDROID_ERROR(("%s: failed to set chanspec error %d\n", __FUNCTION__, err)); + ANDROID_ERROR(("%s: failed to set chanspec error %d\n", + __FUNCTION__, err)); } else - printf("%s: channel %d, 0x%x\n", __FUNCTION__, channel, chspec); + printf("%s: %s channel %d, 0x%x\n", __FUNCTION__, + dev->name, channel, chspec); } else { - ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", __FUNCTION__)); + ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", + __FUNCTION__)); err = BCME_ERROR; } } else { @@ -498,19 +525,23 @@ wl_ext_channel(struct net_device *dev, char* command, int total_len) channel_info_t ci; int bytes_written = 0; chanspec_t fw_chspec; + int ioctl_ver = 0; ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); sscanf(command, "%*s %d", &channel); if (channel > 0) { - ret = wl_ext_set_chanspec(dev, channel, &fw_chspec); + wl_ext_get_ioctl_ver(dev, &ioctl_ver); + ret = wl_ext_set_chanspec(dev, ioctl_ver, channel, &fw_chspec); } else { - if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) { + if (!(ret = wl_ext_ioctl(dev, WLC_GET_CHANNEL, &ci, + sizeof(channel_info_t), FALSE))) { ANDROID_TRACE(("hw_channel %d\n", ci.hw_channel)); ANDROID_TRACE(("target_channel %d\n", ci.target_channel)); ANDROID_TRACE(("scan_channel %d\n", ci.scan_channel)); - bytes_written = snprintf(command, sizeof(channel_info_t)+2, "channel %d", ci.hw_channel); + bytes_written = snprintf(command, sizeof(channel_info_t)+2, + "channel %d", ci.hw_channel); ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); ret = bytes_written; } @@ -532,13 +563,15 @@ wl_ext_channels(struct net_device *dev, char* command, int total_len) memset(valid_chan_list, 0, sizeof(valid_chan_list)); list = (wl_uint32_list_t *)(void *) valid_chan_list; list->count = htod32(WL_NUMCHANNELS); - ret = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), 0); + ret = wl_ext_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, + sizeof(valid_chan_list), 0); if (ret<0) { ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret)); } else { bytes_written = snprintf(command, total_len, "channels"); for (i = 0; i < dtoh32(list->count); i++) { - bytes_written += snprintf(command+bytes_written, total_len, " %d", dtoh32(list->element[i])); + bytes_written += snprintf(command+bytes_written, total_len, " %d", + dtoh32(list->element[i])); printf("%d ", dtoh32(list->element[i])); } printf("\n"); @@ -560,23 +593,20 @@ wl_ext_roam_trigger(struct net_device *dev, char* command, int total_len) if (roam_trigger[0]) { roam_trigger[1] = WLC_BAND_ALL; - ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 1); - if (ret) - ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret)); + ret = wl_ext_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, + sizeof(roam_trigger), 1); } else { roam_trigger[1] = WLC_BAND_2G; - ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0); + ret = wl_ext_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, + sizeof(roam_trigger), 0); if (!ret) trigger[0] = roam_trigger[0]; - else - ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret)); roam_trigger[1] = WLC_BAND_5G; - ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0); + ret = wl_ext_ioctl(dev, WLC_GET_ROAM_TRIGGER, &roam_trigger, + sizeof(roam_trigger), 0); if (!ret) trigger[1] = roam_trigger[0]; - else - ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret)); ANDROID_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1])); bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]); @@ -642,7 +672,8 @@ wl_ext_keep_alive(struct net_device *dev, char *command, int total_len) } else { if (id < 0) id = 0; - ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, sizeof(buf), NULL); + ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, + sizeof(buf), NULL); if (ret) { goto exit; } else { @@ -659,10 +690,12 @@ wl_ext_keep_alive(struct net_device *dev, char *command, int total_len) } printf("\n"); } - bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ", dtoh32(mkeep_alive_pktp->period_msec)); + bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ", + dtoh32(mkeep_alive_pktp->period_msec)); bytes_written += snprintf(command+bytes_written, total_len, "0x"); for (i=0; ilen_bytes; i++) { - bytes_written += snprintf(command+bytes_written, total_len, "%x", mkeep_alive_pktp->data[i]); + bytes_written += snprintf(command+bytes_written, total_len, "%x", + mkeep_alive_pktp->data[i]); } ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); ret = bytes_written; @@ -684,11 +717,9 @@ wl_ext_pm(struct net_device *dev, char *command, int total_len) sscanf(command, "%*s %d", &pm); if (pm >= 0) { - ret = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE); - if (ret) - ANDROID_ERROR(("WLC_SET_PM ERROR %d ret=%d\n", pm, ret)); + ret = wl_ext_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1); } else { - ret = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), FALSE); + ret = wl_ext_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), 0); if (!ret) { ANDROID_TRACE(("%s: PM = %d\n", __func__, pm)); if (pm == PM_OFF) @@ -719,11 +750,9 @@ wl_ext_monitor(struct net_device *dev, char *command, int total_len) sscanf(command, "%*s %d", &val); if (val >=0) { - ret = wldev_ioctl(dev, WLC_SET_MONITOR, &val, sizeof(int), 1); - if (ret) - ANDROID_ERROR(("WLC_SET_MONITOR ERROR %d ret=%d\n", val, ret)); + ret = wl_ext_ioctl(dev, WLC_SET_MONITOR, &val, sizeof(val), 1); } else { - ret = wldev_ioctl(dev, WLC_GET_MONITOR, &val, sizeof(val), FALSE); + ret = wl_ext_ioctl(dev, WLC_GET_MONITOR, &val, sizeof(val), 0); if (!ret) { ANDROID_TRACE(("%s: monitor = %d\n", __FUNCTION__, val)); bytes_written = snprintf(command, total_len, "monitor %d", val); @@ -735,8 +764,115 @@ wl_ext_monitor(struct net_device *dev, char *command, int total_len) return ret; } +s32 +wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info) +{ + wl_extjoin_params_t *ext_join_params; + struct wl_join_params join_params; + size_t join_params_size; + s32 err = 0; + u32 chan_cnt = 0; + s8 iovar_buf[WLC_IOCTL_SMLEN]; + int ioctl_ver = 0; + + if (conn_info->channel) { + chan_cnt = 1; + } + + /* + * Join with specific BSSID and cached SSID + * If SSID is zero join based on BSSID only + */ + join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE + + chan_cnt * sizeof(chanspec_t); + ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL); + if (ext_join_params == NULL) { + err = -ENOMEM; + goto exit; + } + wl_ext_get_ioctl_ver(dev, &ioctl_ver); + ext_join_params->ssid.SSID_len = min((uint32)sizeof(ext_join_params->ssid.SSID), + conn_info->ssid.SSID_len); + memcpy(&ext_join_params->ssid.SSID, conn_info->ssid.SSID, ext_join_params->ssid.SSID_len); + ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len); + /* increate dwell time to receive probe response or detect Beacon + * from target AP at a noisy air only during connect command + */ + ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1; + ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1; + /* Set up join scan parameters */ + ext_join_params->scan.scan_type = -1; + ext_join_params->scan.nprobes = chan_cnt ? + (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1; + ext_join_params->scan.home_time = -1; + + if (memcmp(ðer_null, &conn_info->bssid, ETHER_ADDR_LEN)) + memcpy(&ext_join_params->assoc.bssid, &conn_info->bssid, ETH_ALEN); + else + memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN); + ext_join_params->assoc.chanspec_num = chan_cnt; + if (chan_cnt) { + u16 band, bw, ctl_sb; + chanspec_t chspec; + band = (conn_info->channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G + : WL_CHANSPEC_BAND_5G; + bw = WL_CHANSPEC_BW_20; + ctl_sb = WL_CHANSPEC_CTL_SB_NONE; + chspec = (conn_info->channel | band | bw | ctl_sb); + ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; + ext_join_params->assoc.chanspec_list[0] |= chspec; + ext_join_params->assoc.chanspec_list[0] = + wl_ext_chspec_host_to_driver(ioctl_ver, + ext_join_params->assoc.chanspec_list[0]); + } + ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num); + + err = wl_ext_iovar_setbuf_bsscfg(dev, "join", ext_join_params, + join_params_size, iovar_buf, WLC_IOCTL_SMLEN, conn_info->bssidx, NULL); + + printf("Connecting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n", + MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), conn_info->channel, + ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len); + + kfree(ext_join_params); + if (err) { + if (err == BCME_UNSUPPORTED) { + ANDROID_TRACE(("join iovar is not supported\n")); + goto set_ssid; + } else { + ANDROID_ERROR(("error (%d)\n", err)); + goto exit; + } + } else + goto exit; + +set_ssid: + memset(&join_params, 0, sizeof(join_params)); + join_params_size = sizeof(join_params.ssid); + + join_params.ssid.SSID_len = min((uint32)sizeof(join_params.ssid.SSID), conn_info->ssid.SSID_len); + memcpy(&join_params.ssid.SSID, conn_info->ssid.SSID, join_params.ssid.SSID_len); + join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len); + if (memcmp(ðer_null, &conn_info->bssid, ETHER_ADDR_LEN)) + memcpy(&join_params.params.bssid, &conn_info->bssid, ETH_ALEN); + else + memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN); + + wl_ext_ch_to_chanspec(ioctl_ver, conn_info->channel, &join_params, &join_params_size); + ANDROID_TRACE(("join_param_size %zu\n", join_params_size)); + + if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { + ANDROID_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, + join_params.ssid.SSID_len)); + } + err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params,join_params_size, 1); + +exit: + return err; + +} + #ifdef WL_EXT_IAPSTA -struct wl_apsta_params g_apsta_params; static int wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key) { @@ -855,13 +991,16 @@ wl_ext_get_amode(struct wl_if_info *cur_if, char *amode) wl_ext_iovar_getint(dev, "auth", &auth); wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth); +#ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { if (auth == 0 && wpa_auth == 0) { strcpy(amode, "open"); } else if (auth == 0 && wpa_auth == 128) { strcpy(amode, "sae"); } - } else if (auth == 0 && wpa_auth == 0) { + } else +#endif + if (auth == 0 && wpa_auth == 0) { strcpy(amode, "open"); } else if (auth == 1 && wpa_auth == 0) { strcpy(amode, "shared"); @@ -882,13 +1021,16 @@ wl_ext_get_emode(struct wl_if_info *cur_if, char *emode) wl_ext_iovar_getint(dev, "wsec", &wsec); +#ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { if (wsec == 0) { strcpy(emode, "none"); } else { strcpy(emode, "sae"); } - } else if (wsec == 0) { + } else +#endif + if (wsec == 0) { strcpy(emode, "none"); } else if (wsec == 1) { strcpy(emode, "wep"); @@ -908,6 +1050,7 @@ wl_ext_set_amode(struct wl_if_info *cur_if) authmode_t amode = cur_if->amode; int auth=0, wpa_auth=0; +#ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { auth = 0; @@ -918,7 +1061,9 @@ wl_ext_set_amode(struct wl_if_info *cur_if) wpa_auth = 0; ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__)); } - } else if (amode == AUTH_OPEN) { + } else +#endif + if (amode == AUTH_OPEN) { auth = 0; wpa_auth = 0; ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__)); @@ -939,10 +1084,13 @@ wl_ext_set_amode(struct wl_if_info *cur_if) wpa_auth = 132; ANDROID_INFO(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__)); } +#ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { s32 val = WL_BSSTYPE_MESH; wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1); - } else if (cur_if->ifmode == ISTA_MODE) { + } else +#endif + if (cur_if->ifmode == ISTA_MODE) { s32 val = WL_BSSTYPE_INFRA; wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1); } @@ -954,7 +1102,7 @@ wl_ext_set_amode(struct wl_if_info *cur_if) } static int -wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params) +wl_ext_set_emode(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) { struct net_device *dev = cur_if->dev; int wsec=0; @@ -963,12 +1111,12 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params authmode_t amode = cur_if->amode; encmode_t emode = cur_if->emode; char *key = cur_if->key; - s8 iovar_buf[WLC_IOCTL_SMLEN]; struct dhd_pub *dhd = dhd_get_pub(dev); memset(&wsec_key, 0, sizeof(wsec_key)); memset(&psk, 0, sizeof(psk)); +#ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { wsec = 4; @@ -977,7 +1125,9 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params wsec = 0; ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__)); } - } else if (emode == ENC_NONE) { + } else +#endif + if (emode == ENC_NONE) { wsec = 0; ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__)); } else if (emode == ENC_WEP) { @@ -1007,15 +1157,17 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params ANDROID_INFO(("%s: Encryption: TKIP/AES\n", __FUNCTION__)); ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key)); } - if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->bssidx > 0 && wsec >= 2 && + if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 && apsta_params->apstamode == IAPSTA_MODE) { wsec |= 0x8; // terence 20180628: fix me, this is a workaround } wl_ext_iovar_setint(dev, "wsec", wsec); +#ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { + s8 iovar_buf[WLC_IOCTL_SMLEN]; ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, key)); wl_ext_iovar_setint(dev, "mesh_auth_proto", 1); wl_ext_iovar_setint(dev, "mfp", WL_MFP_REQUIRED); @@ -1025,7 +1177,9 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params wl_ext_iovar_setint(dev, "mesh_auth_proto", 0); wl_ext_iovar_setint(dev, "mfp", WL_MFP_NONE); } - } else if (emode == ENC_WEP) { + } else +#endif + if (emode == ENC_WEP) { wl_ext_ioctl(dev, WLC_SET_KEY, &wsec_key, sizeof(wsec_key), 1); } else if (emode == ENC_TKIP || emode == ENC_AES || emode == ENC_TKIPAES) { if (dev) { @@ -1040,8 +1194,32 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params return 0; } +static uint16 +wl_ext_get_chan(struct wl_apsta_params *apsta_params, struct net_device *dev) +{ + int ret = 0; + uint16 chan = 0, ctl_chan; + struct ether_addr bssid; + u32 chanspec = 0; + + ret = wl_ext_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); + if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) { + if (wl_ext_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) { + chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec); + ctl_chan = wf_chspec_ctlchan(chanspec); + chan = (u16)(ctl_chan & 0x00FF); + ANDROID_INFO(("%s: cur_chan=%d(0x%x)\n", __FUNCTION__, + chan, chanspec)); + return chan; + } + } + + return 0; +} + static chanspec_t -wl_ext_get_chanspec(struct net_device *dev, uint16 channel) +wl_ext_get_chanspec(struct wl_apsta_params *apsta_params, + struct net_device *dev, uint16 channel) { s32 _chan = channel; chanspec_t chspec = 0; @@ -1055,27 +1233,22 @@ wl_ext_get_chanspec(struct net_device *dev, uint16 channel) u32 bw_cap; } param = {0, 0}; uint band; - int ioctl_ver = 0; if (_chan <= CH_MAX_2G_CHANNEL) band = IEEE80211_BAND_2GHZ; else band = IEEE80211_BAND_5GHZ; - wl_ext_get_ioctl_ver(dev, &ioctl_ver); if (band == IEEE80211_BAND_5GHZ) { param.band = WLC_BAND_5G; - err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param), + err = wl_ext_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param), iovar_buf, WLC_IOCTL_SMLEN, NULL); if (err) { if (err != BCME_UNSUPPORTED) { ANDROID_ERROR(("bw_cap failed, %d\n", err)); return err; } else { - err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); - if (err) { - ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err)); - } + err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap); if (bw_cap != WLC_N_BW_20ALL) bw = WL_CHANSPEC_BW_40; } @@ -1086,176 +1259,36 @@ wl_ext_get_chanspec(struct net_device *dev, uint16 channel) bw = WL_CHANSPEC_BW_40; else bw = WL_CHANSPEC_BW_20; - } } else if (band == IEEE80211_BAND_2GHZ) bw = WL_CHANSPEC_BW_20; +set_channel: chspec = wf_channel2chspec(_chan, bw); if (wf_chspec_valid(chspec)) { - fw_chspec = wl_ext_chspec_host_to_driver(ioctl_ver, chspec); + fw_chspec = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, chspec); if (fw_chspec == INVCHANSPEC) { ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", __FUNCTION__)); fw_chspec = 0; } + } else { + if (bw == WL_CHANSPEC_BW_80) + bw = WL_CHANSPEC_BW_40; + else if (bw == WL_CHANSPEC_BW_40) + bw = WL_CHANSPEC_BW_20; + else + bw = 0; + if (bw) + goto set_channel; + ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec)); + err = BCME_ERROR; } return fw_chspec; } -static void -wl_ext_ch_to_chanspec(int ch, struct wl_join_params *join_params, - size_t *join_params_size) -{ - struct wl_apsta_params *apsta_params = &g_apsta_params; - chanspec_t chanspec = 0; - - if (ch != 0) { - join_params->params.chanspec_num = 1; - join_params->params.chanspec_list[0] = ch; - - if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL) - chanspec |= WL_CHANSPEC_BAND_2G; - else - chanspec |= WL_CHANSPEC_BAND_5G; - - chanspec |= WL_CHANSPEC_BW_20; - chanspec |= WL_CHANSPEC_CTL_SB_NONE; - - *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE + - join_params->params.chanspec_num * sizeof(chanspec_t); - - join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; - join_params->params.chanspec_list[0] |= chanspec; - join_params->params.chanspec_list[0] = - wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, - join_params->params.chanspec_list[0]); - - join_params->params.chanspec_num = - htod32(join_params->params.chanspec_num); - ANDROID_TRACE(("join_params->params.chanspec_list[0]= %X, %d channels\n", - join_params->params.chanspec_list[0], - join_params->params.chanspec_num)); - } -} - -static s32 -wl_ext_connect(struct wl_if_info *cur_if) -{ - struct wl_apsta_params *apsta_params = &g_apsta_params; - wl_extjoin_params_t *ext_join_params; - struct wl_join_params join_params; - size_t join_params_size; - s32 err = 0; - u32 chan_cnt = 0; - s8 iovar_buf[WLC_IOCTL_SMLEN]; - - if (cur_if->channel) { - chan_cnt = 1; - } - - /* - * Join with specific BSSID and cached SSID - * If SSID is zero join based on BSSID only - */ - join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE + - chan_cnt * sizeof(chanspec_t); - ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL); - if (ext_join_params == NULL) { - err = -ENOMEM; - goto exit; - } - ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), - strlen(cur_if->ssid)); - memcpy(&ext_join_params->ssid.SSID, cur_if->ssid, ext_join_params->ssid.SSID_len); - ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len); - /* increate dwell time to receive probe response or detect Beacon - * from target AP at a noisy air only during connect command - */ - ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1; - ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1; - /* Set up join scan parameters */ - ext_join_params->scan.scan_type = -1; - ext_join_params->scan.nprobes = chan_cnt ? - (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1; - ext_join_params->scan.home_time = -1; - - if (memcmp(ðer_null, &cur_if->bssid, ETHER_ADDR_LEN)) - memcpy(&ext_join_params->assoc.bssid, &cur_if->bssid, ETH_ALEN); - else - memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN); - ext_join_params->assoc.chanspec_num = chan_cnt; - if (chan_cnt) { - u16 channel, band, bw, ctl_sb; - chanspec_t chspec; - channel = cur_if->channel; - band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G - : WL_CHANSPEC_BAND_5G; - bw = WL_CHANSPEC_BW_20; - ctl_sb = WL_CHANSPEC_CTL_SB_NONE; - chspec = (channel | band | bw | ctl_sb); - ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; - ext_join_params->assoc.chanspec_list[0] |= chspec; - ext_join_params->assoc.chanspec_list[0] = - wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, - ext_join_params->assoc.chanspec_list[0]); - } - ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num); - if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { - ANDROID_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID, - ext_join_params->ssid.SSID_len)); - } - - err = wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "join", ext_join_params, - join_params_size, iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL); - - printf("Connecting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n", - MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), cur_if->channel, - ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len); - - kfree(ext_join_params); - if (err) { - if (err == BCME_UNSUPPORTED) { - ANDROID_TRACE(("join iovar is not supported\n")); - goto set_ssid; - } else { - ANDROID_ERROR(("error (%d)\n", err)); - goto exit; - } - } else - goto exit; - -set_ssid: - memset(&join_params, 0, sizeof(join_params)); - join_params_size = sizeof(join_params.ssid); - - join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), strlen(cur_if->ssid)); - memcpy(&join_params.ssid.SSID, cur_if->ssid, join_params.ssid.SSID_len); - join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len); - if (memcmp(ðer_null, &cur_if->bssid, ETHER_ADDR_LEN)) - memcpy(&join_params.params.bssid, &cur_if->bssid, ETH_ALEN); - else - memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN); - - wl_ext_ch_to_chanspec(cur_if->channel, &join_params, &join_params_size); - ANDROID_TRACE(("join_param_size %zu\n", join_params_size)); - - if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { - ANDROID_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, - join_params.ssid.SSID_len)); - } - err = wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &join_params,join_params_size, 1); - if (err) { - ANDROID_ERROR(("error (%d)\n", err)); - } - -exit: - return err; - -} - static void wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params, bool need_rtnl_unlock) @@ -1305,6 +1338,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para cur_if->prefix = 'A'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap"); dfs = 0; +#ifdef WLMESH } else if (cur_if->ifmode == IMESH_MODE) { cur_if->channel = 1; cur_if->maxassoc = -1; @@ -1313,11 +1347,13 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para cur_if->prefix = 'M'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh"); dfs = 0; +#endif } } - if (dfs == 0) { + + if (!dfs && !apsta_params->vsdb) { dhd_conf_get_country(dhd, &cspec); - if (!dhd_conf_map_country_list(dhd, &cspec, 1)) { + if (!dhd_conf_map_country_list(dhd, &cspec)) { dhd_conf_set_country(dhd, &cspec); dhd_bus_country_set(dev, &cspec, TRUE); } @@ -1326,21 +1362,26 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); } - if (apstamode == IMESHONLY_MODE || apstamode == IMESHSTA_MODE || + if (FW_SUPPORTED(dhd, rsdb)) { + if (apstamode == IDUALAP_MODE) + apsta_params->rsdb = TRUE; + else if (apstamode == ISTAAPAP_MODE) + apsta_params->rsdb = FALSE; + if (apstamode == IDUALAP_MODE || apstamode == ISTAAPAP_MODE || + apstamode == IMESHONLY_MODE || apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE || apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - if (FW_SUPPORTED(dhd, rsdb)) { - wl_config_t rsdb_mode_cfg = {1, 0}; - if (apsta_params->rsdb == 0) { - rsdb_mode_cfg.config = 0; - } - // mesh-ap must set rsdb_mode=1 in same channel or AP mode not easy to be found + wl_config_t rsdb_mode_cfg = {0, 0}; + if (apsta_params->rsdb) + rsdb_mode_cfg.config = 1; printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config); + wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg, sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL); + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); } - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + } else { + apsta_params->rsdb = FALSE; } if (apstamode == ISTAONLY_MODE) { @@ -1382,8 +1423,8 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para bzero(&iface, sizeof(wl_interface_create_t)); iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_AP; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, - sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, 1, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, + sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL); } else { wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), iovar_buf, WLC_IOCTL_SMLEN, 1, NULL); @@ -1408,14 +1449,49 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_AP; apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, 1, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); } + else if (apstamode == ISTAAPAP_MODE) { + u8 rand_bytes[2] = {0, }; + get_random_bytes(&rand_bytes, sizeof(rand_bytes)); + wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); + wl_ext_iovar_setint(dev, "mpc", 0); + wl_ext_iovar_setint(dev, "mbss", 1); + wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off + bzero(&iface, sizeof(wl_interface_create_t)); + iface.ver = WL_INTERFACE_CREATE_VER; + iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE; + memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN); + iface.mac_addr.octet[0] |= 0x02; + iface.mac_addr.octet[5] += 0x01; + memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes)); + apsta_params->netif_change = FALSE; + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + wl_ext_wait_netif_change(apsta_params, TRUE); + bzero(&iface, sizeof(wl_interface_create_t)); + iface.ver = WL_INTERFACE_CREATE_VER; + iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE; + memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN); + iface.mac_addr.octet[0] |= 0x02; + iface.mac_addr.octet[5] += 0x02; + memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes)); + apsta_params->netif_change = FALSE; + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + wl_ext_wait_netif_change(apsta_params, TRUE); + } +#ifdef WLMESH else if (apstamode == IMESHONLY_MODE) { + int pm = 0; wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_iovar_setint(dev, "mpc", 0); wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls + wl_ext_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1); wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off } @@ -1429,8 +1505,8 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_STA; apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, 0, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); } else if (apstamode == IMESHAP_MODE) { @@ -1444,8 +1520,8 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_AP; apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, 0, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); } else if (apstamode == IMESHAPSTA_MODE) { @@ -1459,15 +1535,15 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_AP; apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, 0, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); bzero(&iface, sizeof(wl_interface_create_t)); iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_STA; apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, 0, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); } else if (apstamode == IMESHAPAP_MODE) { @@ -1481,17 +1557,18 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_AP; apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, 0, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); bzero(&iface, sizeof(wl_interface_create_t)); iface.ver = WL_INTERFACE_CREATE_VER; iface.flags = WL_INTERFACE_CREATE_AP; apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, 0, NULL); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); } +#endif else if (apstamode == IGOSTA_MODE) { wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_iovar_setint(dev, "apsta", 1); @@ -1513,9 +1590,9 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para static int wl_ext_isam_init(struct net_device *dev, char *command, int total_len) { + struct dhd_pub *dhd = dhd_get_pub(dev); char *pch, *pick_tmp, *pick_tmp2, *param; - struct wl_apsta_params *apsta_params = &g_apsta_params; - struct dhd_pub *dhd; + struct wl_apsta_params *apsta_params = dhd->iapsta_params; int i; if (apsta_params->init) { @@ -1523,8 +1600,6 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) return -1; } - dhd = dhd_get_pub(dev); - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); pick_tmp = command; @@ -1543,6 +1618,9 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) apsta_params->apstamode = IAPSTA_MODE; } else if (!strcmp(pick_tmp2, "ap-ap")) { apsta_params->apstamode = IDUALAP_MODE; + } else if (!strcmp(pick_tmp2, "sta-ap-ap")) { + apsta_params->apstamode = ISTAAPAP_MODE; +#ifdef WLMESH } else if (!strcmp(pick_tmp2, "mesh")) { apsta_params->apstamode = IMESHONLY_MODE; } else if (!strcmp(pick_tmp2, "mesh-sta") || @@ -1558,6 +1636,7 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) } else if (!strcmp(pick_tmp2, "mesh-ap-ap") || !strcmp(pick_tmp2, "ap-ap-mesh")) { apsta_params->apstamode = IMESHAPAP_MODE; +#endif } else if (!strcmp(pick_tmp2, "apsta")) { apsta_params->apstamode = IAPSTA_MODE; apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE; @@ -1583,6 +1662,7 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) apsta_params->if_info[i].ifmode = ISTA_MODE; else if (!strcmp(pch, "ap")) apsta_params->if_info[i].ifmode = IAP_MODE; +#ifdef WLMESH else if (!strcmp(pch, "mesh")) { if (dhd->conf->fw_type != FW_TYPE_MESH) { ANDROID_ERROR(("%s: wrong fw type\n", __FUNCTION__)); @@ -1590,6 +1670,7 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) } apsta_params->if_info[i].ifmode = IMESH_MODE; } +#endif pch = bcmstrtok(&pick_tmp2, " -", 0); } } @@ -1843,9 +1924,10 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next) static int wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len) { + struct dhd_pub *dhd = dhd_get_pub(dev); int ret=0, i; char *pch, *pch2, *pick_tmp, *pick_next=NULL, *param; - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct wl_apsta_params *apsta_params = dhd->iapsta_params; char ifname[IFNAMSIZ+1]; struct wl_if_info *cur_if = NULL; @@ -1878,8 +1960,8 @@ wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len) } } if (!cur_if) { - ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n", __FUNCTION__, - ifname, apsta_params->apstamode)); + ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n", + __FUNCTION__, ifname, apsta_params->apstamode)); return -1; } ret = wl_ext_parse_config(cur_if, pick_tmp, &pick_next); @@ -1896,23 +1978,249 @@ wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len) return 0; } +static int +wl_ext_isam_status(struct net_device *dev, char *command, int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + int i; + bool now_if; + struct wl_if_info *tmp_if; + uint16 chan = 0; + wlc_ssid_t ssid = { 0, {0} }; + char amode[16], emode[16]; + int bytes_written=0; + + if (apsta_params->init == FALSE) { + return 0; + } + + ANDROID_INFO(("****************************\n")); + ANDROID_INFO(("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode)); + for (i=0; iif_info[i]; + if (dev == tmp_if->dev) + now_if = TRUE; + if (tmp_if->dev) { + chan = wl_ext_get_chan(apsta_params, tmp_if->dev); + if (chan) { + wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0); + wl_ext_get_amode(tmp_if, amode); + wl_ext_get_emode(tmp_if, emode); + ANDROID_INFO(("%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n", + tmp_if->ifname, tmp_if->prefix, chan?'E':'D', + now_if?"*":" ", chan, amode, emode, ssid.SSID)); + if (command) + bytes_written += snprintf(command+bytes_written, total_len, + "%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n", + tmp_if->ifname, tmp_if->prefix, chan?'E':'D', + now_if?"*":" ", chan, amode, emode, ssid.SSID); + } else { + ANDROID_INFO(("%s[%c-%c%s]:\n", + tmp_if->ifname, tmp_if->prefix, chan?'E':'D', now_if?"*":" ")); + if (command) + bytes_written += snprintf(command+bytes_written, total_len, "%s[%c-%c%s]:\n", + tmp_if->ifname, tmp_if->prefix, chan?'E':'D', now_if?"*":" "); + } + } + } + ANDROID_INFO(("****************************\n")); + + return bytes_written; +} + +#ifdef WLMESH +static int +wl_mesh_print_peer_info(mesh_peer_info_ext_t *mpi_ext, + uint32 peer_results_count, char *command, int total_len) +{ + char *peering_map[] = MESH_PEERING_STATE_STRINGS; + uint32 count = 0; + int bytes_written = 0; + + bytes_written += snprintf(command+bytes_written, total_len, + "%2s: %12s : %6s : %-6s : %6s :" + " %5s : %4s : %4s : %11s : %4s", + "no", "------addr------ ", "l.aid", "state", "p.aid", + "mppid", "llid", "plid", "entry_state", "rssi"); + for (count = 0; count < peer_results_count; count++) { + if (mpi_ext->entry_state != MESH_SELF_PEER_ENTRY_STATE_TIMEDOUT) { + bytes_written += snprintf(command+bytes_written, total_len, + "\n%2d: %pM : 0x%4x : %6s : 0x%4x :" + " %5d : %4d : %4d : %11s : %4d", + count, &mpi_ext->ea, mpi_ext->local_aid, + peering_map[mpi_ext->peer_info.state], + mpi_ext->peer_info.peer_aid, + mpi_ext->peer_info.mesh_peer_prot_id, + mpi_ext->peer_info.local_link_id, + mpi_ext->peer_info.peer_link_id, + (mpi_ext->entry_state == MESH_SELF_PEER_ENTRY_STATE_ACTIVE) ? + "ACTIVE" : + "EXTERNAL", + mpi_ext->rssi); + } else { + bytes_written += snprintf(command+bytes_written, total_len, + "\n%d: %pM : %6s : %5s : %6s :" + " %5s : %4s : %4s : %11s : %4s", + count, &mpi_ext->ea, " NA ", " NA ", " NA ", + " NA ", " NA ", " NA ", " TIMEDOUT ", " NA "); + } + mpi_ext++; + } + ANDROID_INFO(("\n%s\n", command)); + + return bytes_written; +} + +static int +wl_ext_mesh_peer_status(struct net_device *dev, char *data, char *command, + int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + int i; + struct wl_if_info *cur_if; + int bytes_written = -1; + int indata, inlen; + char *dump_buf; + mesh_peer_info_dump_t *peer_results; + mesh_peer_info_ext_t *mpi_ext; + + if (apsta_params->init == FALSE) { + ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); + return -1; + } + + if (!data) { + dump_buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); + if (dump_buf == NULL) { + ANDROID_ERROR(("Failed to allocate buffer of %d bytes\n", WLC_IOCTL_MAXLEN)); + return -1; + } + memset(dump_buf, 0, WLC_IOCTL_MAXLEN); + + for (i=0; iif_info[i]; + if (dev == cur_if->dev && cur_if->ifmode == IMESH_MODE) { + peer_results = (mesh_peer_info_dump_t *)dump_buf; + indata = htod32(WLC_IOCTL_MAXLEN); + inlen = 4; + bytes_written = wl_ext_iovar_getbuf(dev, "mesh_peer_status", + &indata, inlen, dump_buf, WLC_IOCTL_MAXLEN, NULL); + if (!bytes_written) { + peer_results = (mesh_peer_info_dump_t *)dump_buf; + mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext; + bytes_written = wl_mesh_print_peer_info(mpi_ext, peer_results->count, + command, total_len); + } + } else if (dev == cur_if->dev) { + ANDROID_ERROR(("%s: %s[%c] is not mesh interface\n", + __FUNCTION__, cur_if->ifname, cur_if->prefix)); + } + } + kfree(dump_buf); + } + + return bytes_written; +} +#endif + +static int +wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + scb_val_t scbval; + struct { + s32 cfg; + s32 val; + } bss_setbuf; + apstamode_t apstamode = apsta_params->apstamode; + + printf("%s: %s[%c] Turning off\n", __FUNCTION__, cur_if->ifname, cur_if->prefix); + + if (cur_if->ifmode == ISTA_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1); + } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { + // deauthenticate all STA first + memcpy(scbval.ea.octet, ðer_bcast, ETHER_ADDR_LEN); + wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1); + } + + if (apstamode == IAPONLY_MODE || apstamode == IMESHONLY_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_DOWN, NULL, 0, 1); + } else { + bss_setbuf.cfg = 0xffffffff; + bss_setbuf.val = htod32(0); + wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + } + + return 0; +} + +static int +wl_ext_if_up(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + struct { + s32 cfg; + s32 val; + } bss_setbuf; + apstamode_t apstamode = apsta_params->apstamode; + chanspec_t fw_chspec; + + if (cur_if->ifmode != IAP_MODE) { + ANDROID_ERROR(("%s: Wrong ifmode on %s[%c]\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix)); + return 0; + } + + if (cur_if->channel >= 52 && cur_if->channel <= 148) { + printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, cur_if->channel); + return 0; + } + + printf("%s: %s[%c] Turning on\n", __FUNCTION__, cur_if->ifname, cur_if->prefix); + + wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel, + &fw_chspec); + + if (apstamode == IAPONLY_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_UP, NULL, 0, 1); + } else { + bss_setbuf.cfg = 0xffffffff; + bss_setbuf.val = htod32(1); + wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, + sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); + } + + OSL_SLEEP(500); + wl_ext_isam_status(cur_if->dev, NULL, 0); + + return 0; +} + static int wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) { + struct dhd_pub *dhd = dhd_get_pub(dev); char *pch, *pick_tmp, *param; s8 iovar_buf[WLC_IOCTL_SMLEN]; wlc_ssid_t ssid = { 0, {0} }; scb_val_t scbval; struct { - s32 tmp; s32 cfg; s32 val; } bss_setbuf; - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct wl_apsta_params *apsta_params = dhd->iapsta_params; apstamode_t apstamode = apsta_params->apstamode; char ifname[IFNAMSIZ+1]; struct wl_if_info *cur_if = NULL; - struct dhd_pub *dhd; int i; if (!apsta_params->init) { @@ -1921,7 +2229,6 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) } ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); - dhd = dhd_get_pub(dev); pick_tmp = command; param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_disable @@ -1951,7 +2258,7 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) return -1; } - printf("%s: Disabling %s\n", __FUNCTION__, ifname); + printf("%s: %s[%c] Disabling\n", __FUNCTION__, ifname, cur_if->prefix); if (cur_if->ifmode == ISTA_MODE) { wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1); @@ -1967,8 +2274,7 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) wl_ext_iovar_setint(dev, "mpc", 1); } else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) && cur_if->ifmode == IAP_MODE) { - bss_setbuf.tmp = 0xffffffff; - bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down + bss_setbuf.cfg = 0xffffffff; bss_setbuf.val = htod32(0); wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); @@ -1989,75 +2295,50 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) } #endif #endif /* PROP_TXSTATUS_VSDB */ - } else if (apstamode == IDUALAP_MODE) { - bss_setbuf.tmp = 0xffffffff; - bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down + } + else if (apstamode == IDUALAP_MODE) { + bss_setbuf.cfg = 0xffffffff; bss_setbuf.val = htod32(0); wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); +#ifdef WLMESH } else if (apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE || - apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) { - bss_setbuf.tmp = 0xffffffff; - bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down + apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE || + apstamode == ISTAAPAP_MODE) { + bss_setbuf.cfg = 0xffffffff; bss_setbuf.val = htod32(0); wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); +#endif } cur_if->ifstate = IF_STATE_DISALBE; - printf("%s: disabled %s SSID: \"%s\"\n", __FUNCTION__, ifname, cur_if->ssid); + printf("%s: %s[%c] disabled\n", __FUNCTION__, ifname, cur_if->prefix); return 0; } static uint16 -wl_ext_get_chan(struct net_device *dev) +wl_ext_get_vsdb_chan(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if, struct wl_if_info *target_if) { - struct wl_apsta_params *apsta_params = &g_apsta_params; - int ret = 0; - uint16 chan = 0, ctl_chan; - struct ether_addr bssid; - u32 chanspec = 0; - - ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); - if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) { - if (wldev_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) { - chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec); - ctl_chan = wf_chspec_ctlchan(chanspec); - chan = (u16)(ctl_chan & 0x00FF); - ANDROID_INFO(("%s: cur_chan=%d(0x%x)\n", __FUNCTION__, - chan, chanspec)); - return chan; - } - } + uint16 target_chan = 0, cur_chan = cur_if->channel, cur_working_chan = 0; - return 0; -} - -static uint16 -wl_ext_get_vsdb_chan(struct net_device *dev, - struct wl_if_info *cur_if, struct wl_if_info *another_if) -{ - struct wl_apsta_params *apsta_params = &g_apsta_params; - uint16 another_chan = 0, cur_chan = cur_if->channel; - struct dhd_pub *dhd; - - dhd = dhd_get_pub(dev); - - another_chan = wl_ext_get_chan(another_if->dev); - if (another_chan) { - ANDROID_INFO(("%s: cur_chan=%d, another_chan=%d\n", - __FUNCTION__, cur_chan, another_chan)); - if ((cur_chan <= CH_MAX_2G_CHANNEL && another_chan > CH_MAX_2G_CHANNEL) || - (cur_chan > CH_MAX_2G_CHANNEL && another_chan <= CH_MAX_2G_CHANNEL)) { - // different band - if (!FW_SUPPORTED(dhd, rsdb) || !apsta_params->rsdb) - return another_chan; + target_chan = wl_ext_get_chan(apsta_params, target_if->dev); + if (target_chan) { + ANDROID_INFO(("%s: cur_chan=%d, target_chan=%d\n", __FUNCTION__, + cur_chan, target_chan)); + if ((cur_chan <= CH_MAX_2G_CHANNEL && target_chan > CH_MAX_2G_CHANNEL) || + (cur_chan > CH_MAX_2G_CHANNEL && target_chan <= CH_MAX_2G_CHANNEL)) { + if (!FW_SUPPORTED(apsta_params->dhd, rsdb) || !apsta_params->rsdb) + return target_chan; + cur_working_chan = wl_ext_get_chan(apsta_params, cur_if->dev); + if (cur_working_chan) + return cur_working_chan; } else { - // same band - if (another_chan != cur_chan) - return another_chan; + if (target_chan != cur_chan) + return target_chan; } } @@ -2065,190 +2346,152 @@ wl_ext_get_vsdb_chan(struct net_device *dev, } static int -wl_ext_triger_csa(struct wl_if_info *cur_if) +wl_ext_triger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) { - struct wl_apsta_params *apsta_params = &g_apsta_params; s8 iovar_buf[WLC_IOCTL_SMLEN]; if (apsta_params->csa & CSA_DRV_BIT && (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) { - wl_chan_switch_t csa_arg; - memset(&csa_arg, 0, sizeof(csa_arg)); - csa_arg.mode = 1; - csa_arg.count = 3; - csa_arg.chspec = wl_ext_get_chanspec(cur_if->dev, cur_if->channel); - printf("%s: Trigger CSA to channel %d\n", __FUNCTION__, cur_if->channel); - wl_ext_iovar_setbuf(cur_if->dev, "csa", &csa_arg, sizeof(csa_arg), - iovar_buf, sizeof(iovar_buf), NULL); - OSL_SLEEP(500); + if (!cur_if->channel) { + printf("%s: %s[%c] skip channel %d\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, cur_if->channel); + } else if (cur_if->channel >= 52 && cur_if->channel <= 148) { + printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, cur_if->channel); + wl_ext_if_down(apsta_params, cur_if); + } else { + wl_chan_switch_t csa_arg; + memset(&csa_arg, 0, sizeof(csa_arg)); + csa_arg.mode = 1; + csa_arg.count = 3; + csa_arg.chspec = wl_ext_get_chanspec(apsta_params, cur_if->dev, + cur_if->channel); + if (csa_arg.chspec) { + printf("%s: Trigger CSA to channel %d(0x%x)\n", __FUNCTION__, + cur_if->channel, csa_arg.chspec); + wl_ext_iovar_setbuf(cur_if->dev, "csa", &csa_arg, sizeof(csa_arg), + iovar_buf, sizeof(iovar_buf), NULL); + OSL_SLEEP(500); + wl_ext_isam_status(cur_if->dev, NULL, 0); + } else { + printf("%s: fail to get chanspec\n", __FUNCTION__); + } + } } return 0; } -static void -wl_ext_move_channel(struct wl_if_info *cur_if, uint16 chan) -{ - struct wl_apsta_params *apsta_params = &g_apsta_params; - - if (chan) { - char cmd[32] = ""; - cur_if->channel = chan; - if (apsta_params->csa == 0) { - printf("%s: %s deauthenticate all STA and move to channel %d\n", - __FUNCTION__, cur_if->ifname, chan); - snprintf(cmd, 32, "%s %s", "isam_disable ifname", cur_if->ifname); - wl_ext_iapsta_disable(cur_if->dev, cmd, strlen(cmd)); - - snprintf(cmd, 32, "%s %s", "isam_enable ifname", cur_if->ifname); - wl_ext_iapsta_enable(cur_if->dev, cmd, strlen(cmd)); - } else { - wl_ext_triger_csa(cur_if); - } - } -} - static uint16 -wl_ext_move_cur_channel(struct net_device *dev, - struct wl_if_info *cur_if) +wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params, + struct net_device *dev, struct wl_if_info *cur_if) { - struct wl_apsta_params *apsta_params = &g_apsta_params; - struct wl_if_info *another_if, *final_if = NULL; - uint16 new_chan = 0; - wl_prio_t cur_prio; + struct wl_if_info *tmp_if, *target_if = NULL; + uint16 tmp_chan, target_chan = 0; + wl_prio_t max_prio; int i; if (apsta_params->vsdb) { - return cur_if->channel; + target_chan = cur_if->channel; + goto exit; } // find the max prio - cur_prio = cur_if->prio; + max_prio = cur_if->prio; for (i=0; iif_info[i]; - if (another_if->ifstate >= IF_STATE_INIT && cur_if != another_if && - another_if->prio > cur_prio) { - new_chan = wl_ext_get_vsdb_chan(dev, cur_if, another_if); - if (new_chan) { - final_if = another_if; - cur_prio = another_if->prio; + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if && + tmp_if->prio > max_prio) { + tmp_chan = wl_ext_get_vsdb_chan(apsta_params, cur_if, tmp_if); + if (tmp_chan) { + target_if = tmp_if; + target_chan = tmp_chan; + max_prio = tmp_if->prio; } } } - if (new_chan) { - printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__, - cur_if->ifname, cur_if->channel, final_if->ifname, new_chan); - cur_if->channel = new_chan; + if (target_chan) { + printf("%s: %s[%c] channel=%d => %s[%c] channel=%d\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, cur_if->channel, + target_if->ifname, target_if->prefix, target_chan); + cur_if->channel = target_chan; + } +exit: + if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) && + (cur_if->channel >= 52 && cur_if->channel <= 148)) { + printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, cur_if->channel); + cur_if->channel = 0; } return cur_if->channel; } static void -wl_ext_move_other_channel(struct net_device *dev, - struct wl_if_info *cur_if) +wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, + struct net_device *dev, struct wl_if_info *cur_if) { - struct wl_apsta_params *apsta_params = &g_apsta_params; - struct wl_if_info *another_if, *final_if=NULL; - uint16 new_chan = 0; - wl_prio_t prio = 0, cur_prio; + struct wl_if_info *tmp_if, *target_if=NULL; + uint16 tmp_chan, target_chan = 0; + wl_prio_t max_prio = 0, cur_prio; int i; - if (apsta_params->vsdb) { + if (apsta_params->vsdb || !cur_if->channel) { return; } // find the max prio, but lower than cur_if cur_prio = cur_if->prio; for (i=0; iif_info[i]; - if (another_if->ifstate >= IF_STATE_INIT && cur_if != another_if && - another_if->prio >= prio && another_if->prio < cur_prio) { - new_chan = wl_ext_get_vsdb_chan(dev, cur_if, another_if); - if (new_chan) { - final_if = another_if; - prio = another_if->prio; - } - } - } - - if (new_chan) { - printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__, - final_if->ifname, final_if->channel, cur_if->ifname, cur_if->channel); - wl_ext_move_channel(final_if, cur_if->channel); - } - -} - -static int -wl_ext_isam_dump_status(struct net_device *dev) -{ - struct wl_apsta_params *apsta_params = &g_apsta_params; - int i; - bool now_if; - struct wl_if_info *tmp_if; - uint16 chan = 0; - wlc_ssid_t ssid = { 0, {0} }; - char amode[16], emode[16]; - - if (apsta_params->init == FALSE) { - return 0; - } - - printf("****************************\n"); - printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode); - for (i=0; iif_info[i]; - if (dev == tmp_if->dev) - now_if = TRUE; - if (tmp_if->dev) { - chan = wl_ext_get_chan(tmp_if->dev); - if (chan) { - wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0); - wl_ext_get_amode(tmp_if, amode); - wl_ext_get_emode(tmp_if, emode); - } - if (chan) { - printf("%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n", - tmp_if->ifname, tmp_if->prefix, chan?'E':'D', - now_if?"*":" ", chan, amode, emode, ssid.SSID); - } else { - printf("%s[%c-%c%s]:\n", - tmp_if->ifname, tmp_if->prefix, chan?'E':'D', - now_if?"*":" "); + if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if && + tmp_if->prio >= max_prio && tmp_if->prio <= cur_prio) { + tmp_chan = wl_ext_get_vsdb_chan(apsta_params, cur_if, tmp_if); + if (tmp_chan) { + target_if = tmp_if; + target_chan = tmp_chan; + max_prio = tmp_if->prio; } } } - printf("****************************\n"); - return 0; + if (target_if) { + printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__, + target_if->ifname, target_chan, cur_if->ifname, cur_if->channel); + target_if->channel = cur_if->channel; + if (apsta_params->csa == 0) { + wl_ext_if_down(apsta_params, target_if); + wl_ext_move_other_channel(apsta_params, dev, target_if); + if (target_if->ifmode == ISTA_MODE || target_if->ifmode == IMESH_MODE) { + wl_ext_enable_iface(target_if->dev, target_if->ifname); + } else if (target_if->ifmode == IAP_MODE) { + wl_ext_if_up(apsta_params, target_if); + } + } else { + wl_ext_triger_csa(apsta_params, target_if); + } + } + } static int wl_ext_enable_iface(struct net_device *dev, char *ifname) { + struct dhd_pub *dhd = dhd_get_pub(dev); int i; s8 iovar_buf[WLC_IOCTL_SMLEN]; wlc_ssid_t ssid = { 0, {0} }; chanspec_t fw_chspec; - struct wl_join_params join_params; - size_t join_params_size; struct { s32 cfg; s32 val; } bss_setbuf; - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct wl_apsta_params *apsta_params = dhd->iapsta_params; apstamode_t apstamode = apsta_params->apstamode; struct wl_if_info *cur_if = NULL; - struct dhd_pub *dhd; uint16 cur_chan; - - dhd = dhd_get_pub(dev); + struct wl_conn_info conn_info; for (i=0; iif_info[i].dev && @@ -2262,23 +2505,27 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) return -1; } - printf("%s: Enabling %s\n", __FUNCTION__, ifname); + printf("%s: %s[%c] Enabling\n", __FUNCTION__, ifname, cur_if->prefix); - wl_ext_isam_dump_status(cur_if->dev); + wl_ext_isam_status(cur_if->dev, NULL, 0); - wl_ext_move_cur_channel(dev, cur_if); - - cur_chan = wl_ext_get_chan(cur_if->dev); - if (cur_chan) { - ANDROID_INFO(("%s: Associated!\n", __FUNCTION__)); - if (cur_chan != cur_if->channel) - wl_ext_triger_csa(cur_if); + wl_ext_move_cur_channel(apsta_params, dev, cur_if); + if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) { return 0; } - wl_ext_move_other_channel(dev, cur_if); + cur_chan = wl_ext_get_chan(apsta_params, cur_if->dev); + if (cur_chan) { + ANDROID_INFO(("%s: Associated!\n", __FUNCTION__)); + if (cur_chan != cur_if->channel) { + wl_ext_triger_csa(apsta_params, cur_if); + } + return 0; + } - if (cur_if->bssidx > 0) { + wl_ext_move_other_channel(apsta_params, dev, cur_if); + + if (cur_if->ifidx > 0) { wl_ext_iovar_setbuf(cur_if->dev, "cur_etheraddr", (u8 *)cur_if->dev->dev_addr, ETHER_ADDR_LEN, iovar_buf, WLC_IOCTL_SMLEN, NULL); } @@ -2321,12 +2568,20 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) cur_if->channel = 1; #endif } - wl_ext_set_chanspec(cur_if->dev, cur_if->channel, &fw_chspec); + wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel, + &fw_chspec); } wl_ext_set_amode(cur_if); - wl_ext_set_emode(cur_if, apsta_params); + wl_ext_set_emode(apsta_params, cur_if); + if (cur_if->ifmode == ISTA_MODE) { + conn_info.bssidx = cur_if->bssidx; + conn_info.channel = cur_if->channel; + memcpy(conn_info.ssid.SSID, cur_if->ssid, strlen(cur_if->ssid)); + conn_info.ssid.SSID_len = strlen(cur_if->ssid); + memcpy(&conn_info.bssid, &cur_if->bssid, ETHER_ADDR_LEN); + } if (cur_if->ifmode == IAP_MODE) { if (cur_if->maxassoc >= 0) wl_ext_iovar_setint(dev, "maxassoc", cur_if->maxassoc); @@ -2340,13 +2595,13 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } if (apstamode == ISTAONLY_MODE) { - wl_ext_connect(cur_if); + wl_ext_connect(cur_if->dev, &conn_info); } else if (apstamode == IAPONLY_MODE) { wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); } else if (apstamode == IAPSTA_MODE || apstamode == IGOSTA_MODE) { if (cur_if->ifmode == ISTA_MODE) { - wl_ext_connect(cur_if); + wl_ext_connect(cur_if->dev, &conn_info); } else { if (FW_SUPPORTED(dhd, rsdb)) { wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); @@ -2377,30 +2632,41 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } else if (apstamode == IDUALAP_MODE) { wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); + } else if (apstamode == ISTAAPAP_MODE) { + if (cur_if->ifmode == ISTA_MODE) { + wl_ext_connect(cur_if->dev, &conn_info); + } else if (cur_if->ifmode == IAP_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); + } else { + printf("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode); + } +#ifdef WLMESH } else if (apstamode == IMESHONLY_MODE || apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE || apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) { if (cur_if->ifmode == ISTA_MODE) { - wl_ext_connect(cur_if); + wl_ext_connect(cur_if->dev, &conn_info); } else if (cur_if->ifmode == IAP_MODE) { wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); } else if (cur_if->ifmode == IMESH_MODE) { + struct wl_join_params join_params; // need to up before setting ssid - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); memset(&join_params, 0, sizeof(join_params)); join_params.ssid.SSID_len = strlen(cur_if->ssid); - memcpy((void *)join_params.ssid.SSID, cur_if->ssid, ssid.SSID_len); + memcpy((void *)join_params.ssid.SSID, cur_if->ssid, strlen(cur_if->ssid)); join_params.params.chanspec_list[0] = fw_chspec; join_params.params.chanspec_num = 1; - join_params_size = sizeof(join_params); - wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &join_params, join_params_size, 1); + wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &join_params, sizeof(join_params), 1); } else { printf("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode); } +#endif } - OSL_SLEEP(1000); - printf("%s: enabled %s SSID: \"%s\"\n", __FUNCTION__, ifname, cur_if->ssid); + OSL_SLEEP(500); + printf("%s: %s[%c] enabled with SSID: \"%s\"\n", __FUNCTION__, + ifname, cur_if->prefix, cur_if->ssid); + wl_ext_isam_status(cur_if->dev, NULL, 0); cur_if->ifstate = IF_STATE_ENABLE; @@ -2410,9 +2676,10 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) static int wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len) { + struct dhd_pub *dhd = dhd_get_pub(dev); int ret = 0; char *pch, *pick_tmp, *param; - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct wl_apsta_params *apsta_params = dhd->iapsta_params; char ifname[IFNAMSIZ+1]; if (!apsta_params->init) { @@ -2447,7 +2714,8 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len) int wl_ext_iapsta_alive_preinit(struct net_device *dev) { - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if; int i; @@ -2478,6 +2746,7 @@ wl_ext_iapsta_alive_preinit(struct net_device *dev) cur_if->prio = PRIO_AP; cur_if->prefix = 'A'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap"); +#ifdef WLMESH } else if (cur_if->ifmode == IMESH_MODE) { cur_if->channel = 1; cur_if->maxassoc = -1; @@ -2485,6 +2754,7 @@ wl_ext_iapsta_alive_preinit(struct net_device *dev) cur_if->prio = PRIO_MESH; cur_if->prefix = 'M'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh"); +#endif } } @@ -2496,8 +2766,9 @@ wl_ext_iapsta_alive_preinit(struct net_device *dev) int wl_ext_iapsta_alive_postinit(struct net_device *dev) { + struct dhd_pub *dhd = dhd_get_pub(dev); s32 apsta = 0; - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct wl_apsta_params *apsta_params = dhd->iapsta_params; wl_ext_iovar_getint(dev, "apsta", &apsta); if (apsta == 1) { @@ -2564,7 +2835,8 @@ wl_ext_conn_status_str(uint32 event_type, int wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) { - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if = NULL; int i; #if defined(WL_WIRELESS_EXT) @@ -2582,7 +2854,7 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) } for (i=0; iif_info[i].bssidx == e->ifidx) { + if (apsta_params->if_info[i].ifidx == e->ifidx) { cur_if = &apsta_params->if_info[i]; break; } @@ -2596,11 +2868,11 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) if (cur_if->ifmode == ISTA_MODE) { if (event_type == WLC_E_LINK) { if (!(flags & WLC_EVENT_MSG_LINK)) { - printf("%s: %s[%c] Link Down with "MACSTR"\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, MAC2STR((u8 *)&e->addr)); + printf("%s: %s[%c] Link Down with %pM\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, &e->addr); } else { - printf("%s: %s[%c] Link UP with "MACSTR"\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, MAC2STR((u8 *)&e->addr)); + printf("%s: %s[%c] Link UP with %pM\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, &e->addr); } } } @@ -2618,15 +2890,15 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) } else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) && reason == DOT11_SC_SUCCESS) { - printf("%s: %s[%c] connected device "MACDBG"\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, MAC2STRDBG(e->addr.octet)); + printf("%s: %s[%c] connected device %pM\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, &e->addr); } else if (event_type == WLC_E_DISASSOC_IND) { - printf("%s: %s[%c] disassociated device "MACDBG"\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, MAC2STRDBG(e->addr.octet)); + printf("%s: %s[%c] disassociated device %pM\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, &e->addr); } else if (event_type == WLC_E_DEAUTH_IND || (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) { - printf("%s: %s[%c] deauthenticated device "MACDBG"\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, MAC2STRDBG(e->addr.octet)); + printf("%s: %s[%c] deauthenticated device %pM\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, &e->addr); } } @@ -2638,13 +2910,13 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) { wrqu.data.length = strlen(extra); wireless_send_event(cur_if->dev, IWEVCUSTOM, &wrqu, extra); - ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d sent up\n", + ANDROID_EVENT(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d sent up\n", __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status, reason, flags)); } else #endif /* WL_WIRELESS_EXT */ { - ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d\n", + ANDROID_EVENT(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d\n", __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status, reason, flags)); } @@ -2653,39 +2925,46 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) } u32 -wl_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel) +wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel) { - struct wl_apsta_params *apsta_params = &g_apsta_params; - struct wl_if_info *cur_if = NULL; + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *cur_if = NULL, *tmp_if = NULL; int i; - wl_ext_isam_dump_status(dev); for (i=0; iif_info[i]; - if (cur_if->dev == dev) { - cur_if->channel = channel; - channel = wl_ext_move_cur_channel(apsta_params->if_info[IF_PIF].dev, cur_if); - wl_ext_move_other_channel(apsta_params->if_info[IF_PIF].dev, cur_if); + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->dev && tmp_if->dev == dev) { + cur_if = tmp_if; break; } } + + if (cur_if) { + wl_ext_isam_status(cur_if->dev, NULL, 0); + cur_if->channel = channel; + channel = wl_ext_move_cur_channel(apsta_params, + apsta_params->if_info[IF_PIF].dev, cur_if); + if (channel) + wl_ext_move_other_channel(apsta_params, + apsta_params->if_info[IF_PIF].dev, cur_if); + } + return channel; } int -wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx) +wl_ext_iapsta_attach_name(struct net_device *net, int ifidx) { - struct wl_apsta_params *apsta_params = &g_apsta_params; - struct dhd_pub *dhd; + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if = NULL; - dhd = dhd_get_pub(net); - - ANDROID_TRACE(("%s: bssidx=%d, %s\n", __FUNCTION__, bssidx, net->name)); - if (bssidx < MAX_IF_NUM) { - cur_if = &apsta_params->if_info[bssidx]; + ANDROID_TRACE(("%s: ifidx=%d, %s\n", __FUNCTION__, ifidx, net->name)); + if (ifidx < MAX_IF_NUM) { + cur_if = &apsta_params->if_info[ifidx]; } - if (bssidx == 0) { + if (ifidx == 0) { if (dhd->conf->fw_type == FW_TYPE_MESH) { apsta_params->rsdb = TRUE; apsta_params->csa = CSA_FW_BIT | CSA_DRV_BIT; @@ -2701,44 +2980,52 @@ wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx) } int -wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx) +wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) { - struct wl_apsta_params *apsta_params = &g_apsta_params; - struct dhd_pub *dhd; + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if = NULL, *primary_if; - dhd = dhd_get_pub(net); - - printf("%s: bssidx=%d\n", __FUNCTION__, bssidx); - if (bssidx < MAX_IF_NUM) { - cur_if = &apsta_params->if_info[bssidx]; + printf("%s: ifidx=%d, bssidx=%d\n", __FUNCTION__, ifidx, bssidx); + if (ifidx < MAX_IF_NUM) { + cur_if = &apsta_params->if_info[ifidx]; } - if (bssidx == 0) { + if (ifidx == 0) { memset(apsta_params, 0, sizeof(struct wl_apsta_params)); + apsta_params->dhd = dhd; apsta_params->vsdb = FALSE; cur_if->dev = net; + cur_if->ifidx = ifidx; cur_if->bssidx = bssidx; strcpy(cur_if->ifname, net->name); init_waitqueue_head(&apsta_params->netif_change_event); } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) { primary_if = &apsta_params->if_info[IF_PIF]; cur_if->dev = net; + cur_if->ifidx = ifidx; cur_if->bssidx = bssidx; if (strlen(cur_if->ifname)) { memset(net->name, 0, sizeof(IFNAMSIZ)); strcpy(net->name, cur_if->ifname); net->name[IFNAMSIZ-1] = '\0'; } - memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN); - net->dev_addr[0] |= 0x02; - if (bssidx >= 2) { - net->dev_addr[4] ^= 0x80; - net->dev_addr[4] += bssidx; - net->dev_addr[5] += bssidx; + if (apsta_params->apstamode != ISTAAPAP_MODE) { + memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN); + net->dev_addr[0] |= 0x02; + if (ifidx >= 2) { + net->dev_addr[4] ^= 0x80; + net->dev_addr[4] += ifidx; + net->dev_addr[5] += (ifidx-1); + } } if (cur_if->ifmode == ISTA_MODE) { wl_ext_iovar_setint(net, "roam_off", dhd->conf->roam_off); wl_ext_iovar_setint(net, "bcn_timeout", dhd->conf->bcn_timeout); +#ifdef WLMESH + } else if (cur_if->ifmode == IMESH_MODE) { + int pm = 0; + wl_ext_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), 1); +#endif } } @@ -2746,15 +3033,50 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx) } int -wl_ext_iapsta_dettach_netdev(void) +wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx) { - struct wl_apsta_params *apsta_params = &g_apsta_params; + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *cur_if = NULL; - printf("%s: Enter\n", __FUNCTION__); - memset(apsta_params, 0, sizeof(struct wl_apsta_params)); + if (!apsta_params) + return 0; + + printf("%s: ifidx=%d\n", __FUNCTION__, ifidx); + if (ifidx < MAX_IF_NUM) { + cur_if = &apsta_params->if_info[ifidx]; + } + + if (ifidx == 0) { + memset(apsta_params, 0, sizeof(struct wl_apsta_params)); + } else if (cur_if && cur_if->ifstate >= IF_STATE_INIT) { + memset(cur_if, 0, sizeof(struct wl_if_info)); + } return 0; } + +int wl_ext_iapsta_attach(dhd_pub_t *pub) +{ + struct wl_apsta_params *iapsta_params; + + iapsta_params = kzalloc(sizeof(struct wl_apsta_params), GFP_KERNEL); + if (unlikely(!iapsta_params)) { + printf("%s: Could not allocate apsta_params\n", __FUNCTION__); + return -ENOMEM; + } + pub->iapsta_params = (void *)iapsta_params; + + return 0; +} + +void wl_ext_iapsta_dettach(dhd_pub_t *pub) +{ + if (pub->iapsta_params) { + kfree(pub->iapsta_params); + pub->iapsta_params = NULL; + } +} #endif #ifdef IDHCP @@ -2843,71 +3165,134 @@ wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len) } #endif -/* -dhd_priv dhd [string] ==> Not ready -1. Get dhd val: - Ex: dhd_priv dhd bussleep -2. Set dhd val: - Ex: dhd_priv dhd bussleep 1 - -dhd_priv wl [WLC_GET_PM] ==> Ready to get int val -dhd_priv wl [WLC_SET_PM] [int] ==> Ready to set int val -dhd_priv wl [string] ==> Ready to get int val -dhd_priv wl [string] [int] ==> Ready to set int val -Ex: get/set WLC_PM - dhd_priv wl 85 - dhd_priv wl 86 1 -Ex: get/set mpc - dhd_priv wl mpc - dhd_priv wl mpc 1 -*/ -int -wl_ext_iovar(struct net_device *dev, char *command, int total_len) +static int +wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command, + int total_len) { + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wl_config_t rsdb_mode_cfg = {1, 0}, *rsdb_p; int ret = 0; - char wl[3]="\0", arg[20]="\0", cmd_str[20]="\0", val_str[20]="\0"; - int cmd=-1, val=0; - int bytes_written=-1; - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + ANDROID_TRACE(("%s: Enter\n", __FUNCTION__)); - sscanf(command, "%s %d %s", wl, &cmd, arg); - if (cmd < 0) - sscanf(command, "%s %s %s", wl, cmd_str, val_str); - - if (!strcmp(wl, "wl")) { - if (cmd>=0 && cmd!=WLC_GET_VAR && cmd!=WLC_SET_VAR) { - ret = sscanf(arg, "%d", &val); - if (ret > 0) { // set - ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), TRUE); - } else { // get - ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), FALSE); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - } else if (strlen(cmd_str)) { - ret = sscanf(val_str, "%d", &val); - if (ret > 0) { // set - ret = wl_ext_iovar_setint(dev, cmd_str, val); - } else { // get - ret = wl_ext_iovar_getint(dev, cmd_str, &val); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } + if (data) { + rsdb_mode_cfg.config = (int)simple_strtol(data, NULL, 0); + ret = wl_ext_iovar_setbuf(dev, "rsdb_mode", (char *)&rsdb_mode_cfg, + sizeof(rsdb_mode_cfg), iovar_buf, WLC_IOCTL_SMLEN, NULL); + printf("%s: rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config); + } else { + ret = wl_ext_iovar_getbuf(dev, "rsdb_mode", NULL, 0, + iovar_buf, WLC_IOCTL_SMLEN, NULL); + if (!ret) { + rsdb_p = (wl_config_t *) iovar_buf; + ret = snprintf(command, total_len, "%d", rsdb_p->config); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, + command)); } } return ret; } -int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len, - int *bytes_written) +typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command, + int total_len); + +typedef struct wl_ext_iovar_tpl_t { + int get; + int set; + char *name; + wl_ext_tpl_parse_t *parse; +} wl_ext_iovar_tpl_t; + +const wl_ext_iovar_tpl_t wl_ext_iovar_tpl_list[] = { + {WLC_GET_VAR, WLC_SET_VAR, "rsdb_mode", wl_ext_rsdb_mode}, +#ifdef WLMESH + {WLC_GET_VAR, WLC_SET_VAR, "mesh_peer_status", wl_ext_mesh_peer_status}, +#endif +}; + +/* +Ex: dhd_priv wl [cmd] [val] + dhd_priv wl 85 + dhd_priv wl 86 1 + dhd_priv wl mpc + dhd_priv wl mpc 1 +*/ +int +wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len) +{ + int cmd, val, ret = -1, i; + char name[32], *pch, *pick_tmp, *data; + int bytes_written=-1; + const wl_ext_iovar_tpl_t *tpl = wl_ext_iovar_tpl_list; + int tpl_count = ARRAY_SIZE(wl_ext_iovar_tpl_list); + + ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + pick_tmp = command; + + pch = bcmstrtok(&pick_tmp, " ", 0); // pick wl + if (!pch || strncmp(pch, "wl", 2)) + goto exit; + + pch = bcmstrtok(&pick_tmp, " ", 0); // pick cmd + if (!pch) + goto exit; + + memset(name, 0 , sizeof (name)); + cmd = (int)simple_strtol(pch, NULL, 0); + if (cmd == 0) { + strcpy(name, pch); + } + data = bcmstrtok(&pick_tmp, " ", 0); // pick data + if (data && cmd == 0) { + cmd = WLC_SET_VAR; + } else if (cmd == 0) { + cmd = WLC_GET_VAR; + } + + /* look for a matching code in the table */ + for (i = 0; i < tpl_count; i++, tpl++) { + if ((tpl->get == cmd || tpl->set == cmd) && !strcmp(tpl->name, name)) + break; + } + if (i < tpl_count && tpl->parse) { + ret = tpl->parse(dev, data, command, total_len); + } else { + if (cmd == WLC_SET_VAR) { + val = (int)simple_strtol(data, NULL, 0); + ANDROID_TRACE(("%s: set %s %d\n", __FUNCTION__, name, val)); + ret = wl_ext_iovar_setint(dev, name, val); + } else if (cmd == WLC_GET_VAR) { + ANDROID_TRACE(("%s: get %s\n", __FUNCTION__, name)); + ret = wl_ext_iovar_getint(dev, name, &val); + if (!ret) { + bytes_written = snprintf(command, total_len, "%d", val); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, + command)); + ret = bytes_written; + } + } else if (data) { + val = (int)simple_strtol(data, NULL, 0); + ANDROID_TRACE(("%s: set %d %d\n", __FUNCTION__, cmd, val)); + ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), TRUE); + } else { + ANDROID_TRACE(("%s: get %d\n", __FUNCTION__, cmd)); + ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), FALSE); + if (!ret) { + bytes_written = snprintf(command, total_len, "%d", val); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, + command)); + ret = bytes_written; + } + } + } + +exit: + return ret; +} + +int wl_android_ext_priv_cmd(struct net_device *net, char *command, + int total_len, int *bytes_written) { int ret = 0; @@ -2959,8 +3344,8 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len else if (strnicmp(command, CMD_ISAM_DISABLE, strlen(CMD_ISAM_DISABLE)) == 0) { *bytes_written = wl_ext_iapsta_disable(net, command, total_len); } - else if (strnicmp(command, CMD_ISAM_DUMP, strlen(CMD_ISAM_DUMP)) == 0) { - *bytes_written = wl_ext_isam_dump_status(net); + else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) { + *bytes_written = wl_ext_isam_status(net, command, total_len); } #endif #ifdef IDHCP @@ -2982,7 +3367,7 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len } #endif else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) { - *bytes_written = wl_ext_iovar(net, command, total_len); + *bytes_written = wl_ext_wl_iovar(net, command, total_len); } else ret = -1; @@ -3004,16 +3389,14 @@ wl_ext_get_distance(struct net_device *net, u32 band) s32 err = BCME_OK; param.band = band; - err = wldev_iovar_getbuf(net, "bw_cap", ¶m, sizeof(param), buf, sizeof(buf), NULL); + err = wl_ext_iovar_getbuf(net, "bw_cap", ¶m, sizeof(param), buf, + sizeof(buf), NULL); if (err) { if (err != BCME_UNSUPPORTED) { ANDROID_ERROR(("bw_cap failed, %d\n", err)); return err; } else { err = wl_ext_iovar_getint(net, "mimo_bw_cap", &bw_cap); - if (err) { - ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err)); - } if (bw_cap != WLC_N_BW_20ALL) bw = WL_CHANSPEC_BW_40; } @@ -3046,7 +3429,7 @@ wl_ext_get_best_channel(struct net_device *net, #else struct wl_scan_results *bss_list, #endif - int *best_2g_ch, int *best_5g_ch + int ioctl_ver, int *best_2g_ch, int *best_5g_ch ) { struct wl_bss_info *bi = NULL; /* must be initialized */ @@ -3059,7 +3442,6 @@ wl_ext_get_best_channel(struct net_device *net, u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; wl_uint32_list_t *list; int ret; - int ioctl_ver = 0; chanspec_t chanspec; memset(b_band, -1, sizeof(b_band)); @@ -3069,7 +3451,8 @@ wl_ext_get_best_channel(struct net_device *net, memset(valid_chan_list, 0, sizeof(valid_chan_list)); list = (wl_uint32_list_t *)(void *) valid_chan_list; list->count = htod32(WL_NUMCHANNELS); - ret = wldev_ioctl(net, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), 0); + ret = wl_ext_ioctl(net, WLC_GET_VALID_CHANNELS, &valid_chan_list, + sizeof(valid_chan_list), 0); if (ret<0) { ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret)); return 0; @@ -3084,7 +3467,6 @@ wl_ext_get_best_channel(struct net_device *net, a_band4[(ch-149)/4] = 0; } } - wl_ext_get_ioctl_ver(net, &ioctl_ver); distance_2g = wl_ext_get_distance(net, WLC_BAND_2G); distance_5g = wl_ext_get_distance(net, WLC_BAND_5G); @@ -3174,7 +3556,8 @@ wl_ext_get_best_channel(struct net_device *net, for (j=0; jresults.bss_info->RSSI); #endif ANDROID_TRACE(("%s: dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID)); + __FUNCTION__, k, &node->results.bss_info->BSSID, rssi, + node->results.bss_info->SSID)); k++; node = node->next; } @@ -3720,7 +4108,8 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, #endif for (;node;) { #if defined(RSSIAVG) - rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID); + rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, + &node->results.bss_info->BSSID); #else rssi_node = dtoh16(node->results.bss_info->RSSI); #endif diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c index 1123b86f9406..f4838a8d9f8c 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c @@ -272,7 +272,7 @@ static const struct ieee80211_iface_limit common_if_limits[] = { #else #define NUM_DIFF_CHANNELS 2 #endif -static struct ieee80211_iface_combination +static const struct ieee80211_iface_combination common_iface_combinations[] = { { .num_different_channels = NUM_DIFF_CHANNELS, @@ -912,6 +912,8 @@ extern int dhd_wait_pend8021x(struct net_device *dev); #ifdef PROP_TXSTATUS_VSDB extern int disable_proptx; #endif /* PROP_TXSTATUS_VSDB */ +static int wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, + struct net_device *dev, uint action, enum wl_ext_status status, void *context); extern int passive_channel_skip; @@ -1813,7 +1815,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, * requests. */ if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) { - WL_ERR(("Fw doesnot support multiple Go")); + WL_ERR(("Fw does not support multiple Go\n")); err = -ENOTSUPP; goto fail; } @@ -1831,7 +1833,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, cfg_type = wl_cfgp2p_get_conn_idx(cfg); if (cfg_type == BCME_ERROR) { wl_clr_p2p_status(cfg, IF_ADDING); - WL_ERR(("Failed to get connection idx for p2p interface")); + WL_ERR(("Failed to get connection idx for p2p interface\n")); err = -ENOTSUPP; goto fail; } @@ -2296,7 +2298,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, */ if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) { wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS); - WL_ERR(("Fw doesnot support multiple GO ")); + WL_ERR(("Fw does not support multiple GO\n")); err = BCME_ERROR; goto error; } @@ -3354,6 +3356,10 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, return -ENODEV; } } + err = wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY, + WL_EXT_STATUS_SCAN, NULL); + if (err) + return err; mutex_lock(&cfg->usr_sync); err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); @@ -3856,7 +3862,8 @@ wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg, dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum))); chipnum = revinfo.chipnum; if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) || - (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID)) { + (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID) || + (chipnum == BCM43362_CHIP_ID)) { /* WAR required */ return true; } @@ -3877,15 +3884,15 @@ wl_bss_iovar_war(struct bcm_cfg80211 *cfg, memset(&revinfo, 0, sizeof(revinfo)); ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)); if (ret < 0) { - WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret)); + WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret)); } else { - WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__, - dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum))); - chipnum = revinfo.chipnum; - if ((chipnum == BCM4359_CHIP_ID) || (chipnum == BCM43596_CHIP_ID)) { - /* WAR required */ - need_war = true; - } + WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__, + dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum))); + chipnum = revinfo.chipnum; + if ((chipnum == BCM4359_CHIP_ID) || (chipnum == BCM43596_CHIP_ID)) { + /* WAR required */ + need_war = true; + } } if (wl_customer6_legacy_chip_check(cfg, ndev) || need_war) { @@ -4158,8 +4165,8 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev, addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, event->bssidx, &cfg->ioctl_buf_sync); if (unlikely(ret)) { - WL_ERR(("set cur_etheraddr Error (%d)\n", ret)); - goto fail; + WL_ERR(("set cur_etheraddr Error (%d)\n", ret)); + goto fail; } memcpy(new_ndev->dev_addr, addr, ETH_ALEN); WL_ERR(("Applying updated mac address to firmware\n")); @@ -5472,6 +5479,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, TRUE); } } + wl_cfg80211_check_in4way(cfg, dev, WAIT_DISCONNECTED, + WL_EXT_STATUS_CONNECTING, NULL); /* 'connect' request received */ wl_set_drv_status(cfg, CONNECTING, dev); @@ -5653,7 +5662,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub); #endif /* BCMDONGLEHOST && CUSTOMER_HW2 */ #ifdef WL_EXT_IAPSTA - wl_ext_iapsta_disconnect_sta(dev, cfg->channel); + wl_ext_iapsta_update_channel(dev, cfg->channel); #endif err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync); @@ -5711,6 +5720,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("error (%d)\n", err)); wl_clr_drv_status(cfg, CONNECTING, dev); } + if (!err) + wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_CONNECTING, NULL); #ifdef WLTDLS /* disable TDLS if number of connected interfaces is >= 1 */ @@ -5795,6 +5807,8 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("error (%d)\n", err)); return err; } + wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTING, NULL); wl_cfg80211_wait_for_disconnection(cfg, dev); } } @@ -6155,6 +6169,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, s32 bssidx = 0; struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); s32 mode = wl_get_mode_by_netdev(cfg, dev); + WL_DBG(("key index (%d)\n", key_idx)); RETURN_EIO_IF_NOT_UP(cfg); @@ -6259,6 +6274,8 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("set wsec error (%d)\n", err)); return err; } + wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_ADD_KEY, NULL); return err; } @@ -8052,7 +8069,7 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, dev = ndev_to_wlc_ndev(dev, cfg); _chan = ieee80211_frequency_to_channel(chan->center_freq); #ifdef WL_EXT_IAPSTA - _chan = wl_ext_iapsta_disconnect_sta(dev, _chan); + _chan = wl_ext_iapsta_update_channel(dev, _chan); #endif printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", __FUNCTION__, dev->ifindex, channel_type, _chan); @@ -9164,7 +9181,6 @@ wl_cfg80211_bcn_bringup_ap( WL_ERR(("failed to disable uapsd, error=%d\n", err)); } #endif /* SOFTAP_UAPSD_OFF */ - dhd_conf_set_wme(cfg->pub, 1); err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32)); if (unlikely(err)) { @@ -9200,6 +9216,14 @@ wl_cfg80211_bcn_bringup_ap( WL_ERR(("Could not get wsec %d\n", err)); goto exit; } + if (dhdp->conf->chip == BCM43430_CHIP_ID && bssidx > 0 && wsec >= 2) { + wsec |= 0x8; // terence 20180628: fix me, this is a workaround + err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); + if (err < 0) { + WL_ERR(("wsec error %d\n", err)); + goto exit; + } + } 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, @@ -9244,7 +9268,7 @@ wl_cfg80211_bcn_bringup_ap( /* create softap */ if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params, join_params_size)) != 0) { - WL_ERR(("SoftAP/GO set ssid failed! \n")); + WL_ERR(("SoftAP/GO set ssid failed! %d\n", err)); goto exit; } else { WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID)); @@ -9519,6 +9543,7 @@ wl_cfg80211_del_station( u16 rc = params->reason_code; #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */ #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */ + WL_DBG(("Entry\n")); if (mac_addr == NULL) { WL_DBG(("mac_addr is NULL ignore it\n")); @@ -9536,6 +9561,11 @@ wl_cfg80211_del_station( return -EFAULT; } } + err = wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_DELETE_STA, (void *)mac_addr); + if (err) { + return 0; + } assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV; err = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST, @@ -9947,6 +9977,10 @@ wl_cfg80211_stop_ap( #endif /* ARP_OFFLOAD_SUPPORT */ if (is_rsdb_supported == 0) { + if (dhd_download_fw_on_driverload && bssidx == 0) { + wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32)); + wldev_iovar_setint(dev, "apsta", 1); + } /* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */ err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32)); if (unlikely(err)) { @@ -10908,10 +10942,6 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \ (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)) WL_DBG(("Setting interface combinations for common mode\n")); -#ifndef BCMDBUS - if (dhd->conf->num_different_channels >= 0) - common_iface_combinations[0].num_different_channels = dhd->conf->num_different_channels; -#endif /* !BCMDBUS */ wdev->wiphy->iface_combinations = common_iface_combinations; wdev->wiphy->n_iface_combinations = ARRAY_SIZE(common_iface_combinations); @@ -11169,7 +11199,8 @@ static s32 wl_inform_bss(struct bcm_cfg80211 *cfg) node = node->next; } if (cfg->autochannel) - wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, &cfg->best_2g_ch, &cfg->best_5g_ch); + wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version, + &cfg->best_2g_ch, &cfg->best_5g_ch); #else WL_SCAN(("scanned AP count (%d)\n", bss_list->count)); preempt_disable(); @@ -11181,7 +11212,8 @@ static s32 wl_inform_bss(struct bcm_cfg80211 *cfg) } preempt_enable(); if (cfg->autochannel) - wl_ext_get_best_channel(ndev, bss_list, &cfg->best_2g_ch, &cfg->best_5g_ch); + wl_ext_get_best_channel(ndev, bss_list, ioctl_version, + &cfg->best_2g_ch, &cfg->best_5g_ch); #endif if (cfg->p2p_disconnected > 0) { @@ -11556,9 +11588,7 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, printf("%s: ** AP/GO Link up event **\n", __FUNCTION__); wl_set_drv_status(cfg, AP_CREATED, ndev); wake_up_interruptible(&cfg->netif_change_event); - if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) { - dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_GO, -1); - } + wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_AP_ENABLED, NULL); return 0; } } @@ -11683,13 +11713,19 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, sinfo.assoc_req_ies = data; sinfo.assoc_req_ies_len = len; printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_STA_CONNECTED, NULL); cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); } else if (event == WLC_E_DISASSOC_IND) { printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_STA_DISCONNECTED, NULL); cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); } else if ((event == WLC_E_DEAUTH_IND) || ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) { printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_STA_DISCONNECTED, NULL); cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); } #endif @@ -12194,7 +12230,6 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, vndr_oui_num > 0 ? vndr_oui : ""); wl_bss_connect_done(cfg, ndev, e, data, true); - dhd_conf_set_intiovar(cfg->pub, WLC_SET_VAR, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE); WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID)); @@ -12212,10 +12247,6 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, } wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT); wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID); - dhd_conf_set_wme(cfg->pub, 0); - if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) { - dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1); - } } else if (WL_IS_LINKDOWN(cfg, e, data) || ((event == WLC_E_SET_SSID) && (ntoh32(e->status) != WLC_E_STATUS_SUCCESS) && @@ -12236,6 +12267,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, * the event to avoid pre-empting the current connection */ WL_INFORM(("Nested connection case. Drop event. \n")); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTED, NULL); wl_clr_drv_status(cfg, NESTED_CONNECT, ndev); wl_clr_drv_status(cfg, DISCONNECTING, ndev); /* Not in 'CONNECTED' state, clear it */ @@ -12357,11 +12390,6 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, // terence 20130703: Fix for wrong group_capab (timing issue) cfg->p2p_disconnected = 1; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) - if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) { - CFG80211_DISCONNECTED(ndev, reason, NULL, 0, false, GFP_KERNEL); - } -#endif memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN); wl_clr_drv_status(cfg, CONNECTED, ndev); @@ -12433,6 +12461,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, wl_bss_connect_done(cfg, ndev, e, data, false); } wl_clr_drv_status(cfg, DISCONNECTING, ndev); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTED, NULL); /* if link down, bsscfg is diabled */ if (ndev != bcmcfg_to_prmry_ndev(cfg)) @@ -12446,6 +12476,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, } else if (wl_is_nonetwork(cfg, e)) { printf("connect failed event=%d e->status %d e->reason %d \n", event, (int)ntoh32(e->status), (int)ntoh32(e->reason)); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTED, NULL); #if defined(DHD_ENABLE_BIGDATA_LOGGING) if (event == WLC_E_SET_SSID) { wl_get_connect_failed_status(cfg, e); @@ -13135,7 +13167,7 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, #endif /* WLADPS_SEAK_AP_WAR */ printf("%s succeeded to " MACDBG " (ch:%d)\n", __FUNCTION__, MAC2STRDBG((const u8*)(&e->addr)), *channel); - dhd_conf_set_wme(cfg->pub, 0); + wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) roam_info.channel = notify_channel; @@ -13307,6 +13339,9 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, completed = false; sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE; } + if (completed) { + wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL); + } cfg80211_connect_result(ndev, curbssid, conn_info->req_ie, @@ -13320,9 +13355,11 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, GFP_KERNEL); if (completed) { WL_INFORM(("Report connect result - connection succeeded\n")); - dhd_conf_set_wme(cfg->pub, 0); - } else + } else { WL_ERR(("Report connect result - connection failed\n")); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTED, NULL); + } } #ifdef CONFIG_TCPACK_FASTTX if (wl_get_chan_isvht80(ndev, dhdp)) @@ -15050,6 +15087,7 @@ static s32 wl_escan_without_scan_cache(struct bcm_cfg80211 *cfg, wl_escan_result } #endif /* WL_DRV_AVOID_SCANCACHE */ + static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data) { @@ -15203,7 +15241,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, goto exit; } #ifdef ESCAN_BUF_OVERFLOW_MGMT - WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n", + WL_SCAN(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n", bss->SSID, MAC2STRDBG(bss->BSSID.octet), i, bss->RSSI, list->count)); @@ -15333,7 +15371,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE); cfg->bss_list = wl_escan_get_buf(cfg, FALSE); if (!scan_req_match(cfg)) { - WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n", + WL_SCAN(("SCAN COMPLETED: scanned AP count=%d\n", cfg->bss_list->count)); } wl_inform_bss(cfg); @@ -15605,6 +15643,7 @@ static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_ } return err; } + static s32 wl_init_scan(struct bcm_cfg80211 *cfg) { int err = 0; @@ -15669,6 +15708,7 @@ static s32 wl_init_priv(struct bcm_cfg80211 *cfg) spin_lock_init(&cfg->cfgdrv_lock); mutex_init(&cfg->ioctl_buf_sync); init_waitqueue_head(&cfg->netif_change_event); + init_waitqueue_head(&cfg->wps_done_event); init_completion(&cfg->send_af_done); init_completion(&cfg->iface_disable); mutex_init(&cfg->usr_sync); @@ -15676,6 +15716,7 @@ static s32 wl_init_priv(struct bcm_cfg80211 *cfg) mutex_init(&cfg->scan_complete); mutex_init(&cfg->if_sync); mutex_init(&cfg->pm_sync); + mutex_init(&cfg->in4way_sync); #ifdef WLTDLS mutex_init(&cfg->tdls_sync); #endif /* WLTDLS */ @@ -17008,6 +17049,8 @@ s32 wl_cfg80211_up(struct net_device *net) } ioctl_version = val; WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version)); + wl_cfg80211_check_in4way(cfg, net, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTED, NULL); mutex_lock(&cfg->usr_sync); dhd = (dhd_pub_t *)(cfg->pub); @@ -21676,7 +21719,8 @@ wl_set_rssi_logging(struct net_device *dev, void *param) } #endif /* SUPPORT_RSSI_LOGGING */ -s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len) +s32 +wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len) { struct bcm_cfg80211 *cfg = wl_get_cfg(dev); int ret = 0; @@ -21696,3 +21740,200 @@ s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len return ret; } + +static int +wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, + struct net_device *dev, uint action, enum wl_ext_status status, void *context) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); + struct wl_security *sec; + s32 bssidx = -1; + int ret = 0, cur_eapol_status; + int max_wait_time, max_wait_cnt; + + mutex_lock(&cfg->in4way_sync); + WL_DBG(("status=%d, action=0x%x\n", status, action)); + + cur_eapol_status = dhdp->conf->eapol_status; + switch (status) { + case WL_EXT_STATUS_SCAN: + if (action & NO_SCAN_IN4WAY) { + if (cfg->handshaking > 0 && cfg->handshaking <= 3) { + WL_ERR(("return -EBUSY cnt %d\n", cfg->handshaking)); + cfg->handshaking++; + ret = -EBUSY; + break; + } + } + break; + case WL_EXT_STATUS_DISCONNECTING: + if (cur_eapol_status >= EAPOL_STATUS_WPA_START && + cur_eapol_status < EAPOL_STATUS_WPA_END) { + ANDROID_ERROR(("%s: WPA failed at %d\n", __FUNCTION__, + cur_eapol_status)); + dhdp->conf->eapol_status = EAPOL_STATUS_NONE; + } else if (cur_eapol_status >= EAPOL_STATUS_WPS_WSC_START && + cur_eapol_status < EAPOL_STATUS_WPS_DONE) { + ANDROID_ERROR(("%s: WPS failed at %d\n", __FUNCTION__, + cur_eapol_status)); + dhdp->conf->eapol_status = EAPOL_STATUS_NONE; + } + if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { + if (cfg->handshaking) { + if (action & NO_BTC_IN4WAY) { + WL_TRACE(("status=%d, enable btc_mode\n", status)); + wldev_iovar_setint(dev, "btc_mode", 1); + } + cfg->handshaking = 0; + } + } + if (action & WAIT_DISCONNECTED) { + max_wait_time = 200; + max_wait_cnt = 20; + cfg->disconnected_jiffies = jiffies; + while (!time_after(jiffies, + cfg->disconnected_jiffies + msecs_to_jiffies(max_wait_time)) && + max_wait_cnt) { + WL_TRACE(("status=%d, max_wait_cnt=%d waiting...\n", + status, max_wait_cnt)); + mutex_unlock(&cfg->in4way_sync); + OSL_SLEEP(50); + mutex_lock(&cfg->in4way_sync); + max_wait_cnt--; + } + } + break; + case WL_EXT_STATUS_CONNECTING: + if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { + bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr); + sec = wl_read_prof(cfg, dev, WL_PROF_SEC); + if ((sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) && + bssidx == 0) { + dhdp->conf->eapol_status = EAPOL_STATUS_WPA_START; + cfg->handshaking = 1; + if (action & NO_BTC_IN4WAY) { + WL_TRACE(("status=%d, disable btc_mode\n", status)); + wldev_iovar_setint(dev, "btc_mode", 0); + } + } + } + if (action & WAIT_DISCONNECTED) { + max_wait_time = 200; + max_wait_cnt = 10; + while (!time_after(jiffies, + cfg->disconnected_jiffies + msecs_to_jiffies(max_wait_time)) && + max_wait_cnt) { + WL_TRACE(("status=%d, max_wait_cnt=%d waiting...\n", + status, max_wait_cnt)); + mutex_unlock(&cfg->in4way_sync); + OSL_SLEEP(50); + mutex_lock(&cfg->in4way_sync); + max_wait_cnt--; + } + } + break; + case WL_EXT_STATUS_CONNECTED: + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) { + dhd_conf_set_wme(cfg->pub, 0); + dhd_conf_set_intiovar(cfg->pub, WLC_SET_VAR, "phy_oclscdenable", + cfg->pub->conf->phy_oclscdenable, 0, FALSE); + } + else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) { + dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1); + } + break; + case WL_EXT_STATUS_DISCONNECTED: + if (cur_eapol_status >= EAPOL_STATUS_WPA_START && + cur_eapol_status < EAPOL_STATUS_WPA_END) { + ANDROID_ERROR(("%s: WPA failed at %d\n", __FUNCTION__, cur_eapol_status)); + dhdp->conf->eapol_status = EAPOL_STATUS_NONE; + } else if (cur_eapol_status >= EAPOL_STATUS_WPS_WSC_START && + cur_eapol_status < EAPOL_STATUS_WPS_DONE) { + ANDROID_ERROR(("%s: WPS failed at %d\n", __FUNCTION__, cur_eapol_status)); + dhdp->conf->eapol_status = EAPOL_STATUS_NONE; + } + if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { + if (cfg->handshaking) { + if (action & NO_BTC_IN4WAY) { + WL_TRACE(("status=%d, enable btc_mode\n", status)); + wldev_iovar_setint(dev, "btc_mode", 1); + } + cfg->handshaking = 0; + } + } + if (action & WAIT_DISCONNECTED) { + cfg->disconnected_jiffies = jiffies; + } + break; + case WL_EXT_STATUS_ADD_KEY: + dhdp->conf->eapol_status = EAPOL_STATUS_WPA_END; + if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { + if (cfg->handshaking) { + if (action & NO_BTC_IN4WAY) { + WL_TRACE(("status=%d, enable btc_mode\n", status)); + wldev_iovar_setint(dev, "btc_mode", 1); + } + cfg->handshaking = 0; + } + } + break; + case WL_EXT_STATUS_AP_ENABLED: + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + dhd_conf_set_wme(cfg->pub, 1); + } + else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { + dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_GO, -1); + } + break; + case WL_EXT_STATUS_DELETE_STA: + if ((action & DONT_DELETE_GC_AFTER_WPS) && + (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) { + u8* mac_addr = context; + if (mac_addr && memcmp(ðer_bcast, mac_addr, ETHER_ADDR_LEN) && + cur_eapol_status == EAPOL_STATUS_WPS_DONE) { + u32 timeout; + max_wait_time = dhdp->conf->max_wait_gc_time; + WL_TRACE(("status=%d, wps_done=%d, waiting %dms ...\n", + status, cfg->wps_done, max_wait_time)); + mutex_unlock(&cfg->in4way_sync); + timeout = wait_event_interruptible_timeout(cfg->wps_done_event, + cfg->wps_done, msecs_to_jiffies(max_wait_time)); + mutex_lock(&cfg->in4way_sync); + WL_TRACE(("status=%d, wps_done=%d, timeout=%d\n", + status, cfg->wps_done, timeout)); + if (timeout > 0) { + ret = -1; + break; + } + } else { + WL_TRACE(("status=%d, wps_done=%d => 0\n", status, cfg->wps_done)); + cfg->wps_done = FALSE; + dhdp->conf->eapol_status = EAPOL_STATUS_NONE; + } + } + break; + case WL_EXT_STATUS_STA_DISCONNECTED: + if ((action & DONT_DELETE_GC_AFTER_WPS) && + (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) && + cur_eapol_status == EAPOL_STATUS_WPS_DONE) { + WL_TRACE(("status=%d, wps_done=%d => 0\n", status, cfg->wps_done)); + cfg->wps_done = FALSE; + } + break; + case WL_EXT_STATUS_STA_CONNECTED: + if ((action & DONT_DELETE_GC_AFTER_WPS) && + (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) && + cur_eapol_status == EAPOL_STATUS_WPS_DONE) { + WL_TRACE(("status=%d, wps_done=%d => 1\n", status, cfg->wps_done)); + cfg->wps_done = TRUE; + wake_up_interruptible(&cfg->wps_done_event); + } + break; + default: + WL_ERR(("Unknown action=0x%x, status=%d\n", action, status)); + } + + mutex_unlock(&cfg->in4way_sync); + + return ret; +} diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h index 395dfd5ae7f4..48092808c45f 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h @@ -341,6 +341,20 @@ enum wl_status { WL_STATUS_NESTED_CONNECT }; +enum wl_ext_status { + WL_EXT_STATUS_DISCONNECTING = 0, + WL_EXT_STATUS_DISCONNECTED, + WL_EXT_STATUS_SCAN, + WL_EXT_STATUS_CONNECTING, + WL_EXT_STATUS_CONNECTED, + WL_EXT_STATUS_ADD_KEY, + WL_EXT_STATUS_AP_ENABLED, + WL_EXT_STATUS_DELETE_STA, + WL_EXT_STATUS_STA_DISCONNECTED, + WL_EXT_STATUS_STA_CONNECTED, + WL_EXT_STATUS_AP_DISABLED +}; + /* wi-fi mode */ enum wl_mode { WL_MODE_BSS, @@ -871,6 +885,11 @@ struct bcm_cfg80211 { int autochannel; int best_2g_ch; int best_5g_ch; + uint handshaking; + bool wps_done; + wait_queue_head_t wps_done_event; + struct mutex in4way_sync; + ulong disconnected_jiffies; }; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c index 3778d4977b78..05546127541d 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c @@ -54,6 +54,7 @@ #define dtoh16(i) (i) #define htodchanspec(i) (i) #define dtohchanspec(i) (i) +#define WL_EXTRA_BUF_MAX 2048 #define wl_escan_get_buf(a) ((wl_scan_results_t *) (a)->escan_buf) @@ -71,7 +72,6 @@ typedef struct { } removal_element_t; #endif /* ESCAN_BUF_OVERFLOW_MGMT */ -struct wl_escan_info *g_escan = NULL; /* Return a new chanspec given a legacy chanspec * Returns INVCHANSPEC on error */ @@ -179,9 +179,9 @@ wl_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec) * Returns INVCHANSPEC on error */ static chanspec_t -wl_chspec_host_to_driver(chanspec_t chanspec) +wl_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec) { - if (1) { + if (ioctl_ver == 1) { chanspec = wl_chspec_to_legacy(chanspec); if (chanspec == INVCHANSPEC) { return chanspec; @@ -197,7 +197,7 @@ wl_chspec_host_to_driver(chanspec_t chanspec) * Returns INVCHANSPEC on error */ static chanspec_t -wl_ch_host_to_driver(s32 bssidx, u16 channel) +wl_ch_host_to_driver(int ioctl_ver, s32 bssidx, u16 channel) { chanspec_t chanspec; @@ -212,7 +212,7 @@ wl_ch_host_to_driver(s32 bssidx, u16 channel) chanspec |= WL_CHANSPEC_CTL_SB_NONE; - return wl_chspec_host_to_driver(chanspec); + return wl_chspec_host_to_driver(ioctl_ver, chanspec); } static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) @@ -408,8 +408,9 @@ static s32 wl_escan_event_handler(void *data) void wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data) { + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_escan_info *escan = dhd->escan; u32 event_type = ntoh32(e->event_type); - struct wl_escan_info *escan = g_escan; if (!escan || !escan->dev) { return; @@ -481,10 +482,12 @@ static s32 wl_escan_inform_bss(struct wl_escan_info *escan) wl_delete_dirty_bss_cache(&escan->g_bss_cache_ctrl); wl_reset_bss_cache(&escan->g_bss_cache_ctrl); if (escan->autochannel) - wl_ext_get_best_channel(escan->dev, &escan->g_bss_cache_ctrl, &escan->best_2g_ch, &escan->best_5g_ch); + wl_ext_get_best_channel(escan->dev, &escan->g_bss_cache_ctrl, + escan->ioctl_ver &escan->best_2g_ch, &escan->best_5g_ch); #else if (escan->autochannel) - wl_ext_get_best_channel(escan->dev, bss_list, &escan->best_2g_ch, &escan->best_5g_ch); + wl_ext_get_best_channel(escan->dev, bss_list, escan->ioctl_ver, + &escan->best_2g_ch, &escan->best_5g_ch); #endif ESCAN_TRACE(("scanned AP count (%d)\n", bss_list->count)); @@ -493,7 +496,8 @@ static s32 wl_escan_inform_bss(struct wl_escan_info *escan) } static wl_scan_params_t * -wl_escan_alloc_params(int channel, int nprobes, int *out_params_size) +wl_escan_alloc_params(struct wl_escan_info *escan, int channel, + int nprobes, int *out_params_size) { wl_scan_params_t *params; int params_size; @@ -524,7 +528,7 @@ wl_escan_alloc_params(int channel, int nprobes, int *out_params_size) if (channel == -1) params->channel_list[0] = htodchanspec(channel); else - params->channel_list[0] = wl_ch_host_to_driver(bssidx, channel); + params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, bssidx, channel); /* Our scan params have 1 channel and 0 ssids */ params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) | @@ -541,7 +545,7 @@ static void wl_escan_abort(struct wl_escan_info *escan) s32 err = BCME_OK; if (!in_atomic()) { /* Our scan params only need space for 1 channel and 0 ssids */ - params = wl_escan_alloc_params(-1, 0, ¶ms_size); + params = wl_escan_alloc_params(escan, -1, 0, ¶ms_size); if (params == NULL) { ESCAN_ERROR(("scan params allocation failed \n")); err = -ENOMEM; @@ -942,7 +946,8 @@ wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list, params->channel_list[j] |= chanspec; ESCAN_SCAN(("Chan : %d, Channel spec: %x \n", channel, params->channel_list[j])); - params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]); + params->channel_list[j] = wl_chspec_host_to_driver(escan->ioctl_ver, + params->channel_list[j]); j++; } } else { @@ -1048,12 +1053,13 @@ wl_escan_set_scan( char *extra ) { + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_escan_info *escan = dhd->escan; s32 err = BCME_OK; s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)); wl_escan_params_t *params = NULL; scb_val_t scbval; static int cnt = 0; - struct wl_escan_info *escan = g_escan; wlc_ssid_t ssid; u32 n_channels = 0; wl_uint32_list_t *list; @@ -1144,6 +1150,7 @@ wl_escan_set_scan( err = wldev_iovar_setbuf(dev, "escan", params, params_size, escan->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL); + printf("%s: LEGACY_SCAN\n", __FUNCTION__); if (unlikely(err)) { if (err == BCME_EPERM) /* Scan Not permitted at this point of time */ @@ -1178,25 +1185,133 @@ wl_escan_set_scan( } int -wl_escan_get_scan( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) +wl_escan_merge_scan_results(struct net_device *dev, struct iw_request_info *info, + char *extra, wl_bss_info_t *bi, int *len, int max_size) { + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_escan_info *escan = dhd->escan; s32 err = BCME_OK; struct iw_event iwe; - int i, j; - char *event = extra, *end = extra + dwrq->length, *value; + int j; + char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value; int16 rssi; int channel; + + /* overflow check cover fields before wpa IEs */ + if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + + IW_EV_QUAL_LEN >= end) { + err = -E2BIG; + goto exit; + } + +#if defined(RSSIAVG) + rssi = wl_get_avg_rssi(&escan->g_rssi_cache_ctrl, &bi->BSSID); + if (rssi == RSSI_MINVAL) + rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); +#else + // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS + rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); +#endif + channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); + ESCAN_SCAN(("BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n", + MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID)); + + /* First entry must be the BSSID */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); + event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); + + /* SSID */ + iwe.u.data.length = dtoh32(bi->SSID_len); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); + + /* Mode */ + if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { + iwe.cmd = SIOCGIWMODE; + if (dtoh16(bi->capability) & DOT11_CAP_ESS) + iwe.u.mode = IW_MODE_INFRA; + else + iwe.u.mode = IW_MODE_ADHOC; + event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); + } + + /* Channel */ + iwe.cmd = SIOCGIWFREQ; +#if 1 + iwe.u.freq.m = wf_channel2mhz(channel, channel <= CH_MAX_2G_CHANNEL ? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); +#else + iwe.u.freq.m = wf_channel2mhz(bi->n_cap ? + bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec), + CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); +#endif + iwe.u.freq.e = 6; + event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); + + /* Channel quality */ + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = rssi_to_qual(rssi); + iwe.u.qual.level = 0x100 + rssi; + iwe.u.qual.noise = 0x100 + bi->phy_noise; + event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); + + wl_iw_handle_scanresults_ies(&event, end, info, bi); + + /* Encryption */ + iwe.cmd = SIOCGIWENCODE; + if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); + + /* Rates */ + if (bi->rateset.count <= sizeof(bi->rateset.rates)) { + if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) { + err = -E2BIG; + goto exit; + } + value = event + IW_EV_LCP_LEN; + iwe.cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { + iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; + value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, + IW_EV_PARAM_LEN); + } + event = value; + } + *len = event - extra; + if (*len < 0) + ESCAN_ERROR(("==> Wrong size\n")); + +exit: + return err; +} + +int +wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_escan_info *escan = dhd->escan; + s32 err = BCME_OK; + int i = 0; + int len_prep = 0, len_ret = 0; wl_bss_info_t *bi = NULL; - struct wl_escan_info *escan = g_escan; struct wl_scan_results *bss_list; + __u16 buflen_from_user = dwrq->length; #if defined(BSSCACHE) wl_bss_cache_t *node; #endif + char *buf = NULL; + struct ether_addr cur_bssid; ESCAN_TRACE(("%s: %s SIOCGIWSCAN, len=%d\n", __FUNCTION__, dev->name, dwrq->length)); @@ -1217,6 +1332,31 @@ wl_escan_get_scan( goto exit; } + err = wldev_ioctl(dev, WLC_GET_BSSID, &cur_bssid, sizeof(cur_bssid), false); + if (err != BCME_NOTASSOCIATED && memcmp(ðer_null, &cur_bssid, ETHER_ADDR_LEN)) { + // merge current connected bss + buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_ATOMIC); + if (!buf) { + ESCAN_ERROR(("buffer alloc failed.\n")); + err = BCME_NOMEM; + goto exit; + } + *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX); + err = wldev_ioctl(dev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false); + if (unlikely(err)) { + ESCAN_ERROR(("Could not get bss info %d\n", err)); + goto exit; + } + bi = (struct wl_bss_info *)(buf + 4); + len_prep = 0; + err = wl_escan_merge_scan_results(dev, info, extra+len_ret, bi, + &len_prep, buflen_from_user-len_ret); + len_ret += len_prep; + if (err) + goto exit; + bi = NULL; + } + #if defined(BSSCACHE) bss_list = &escan->g_bss_cache_ctrl.m_cache_head->results; node = escan->g_bss_cache_ctrl.m_cache_head; @@ -1230,112 +1370,40 @@ wl_escan_get_scan( #if defined(BSSCACHE) bi = node->results.bss_info; #endif - /* overflow check cover fields before wpa IEs */ - if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + - IW_EV_QUAL_LEN >= end) { - err = -E2BIG; + if (!memcmp(&bi->BSSID, &cur_bssid, ETHER_ADDR_LEN)) { + ESCAN_SCAN(("skip connected AP %pM\n", &cur_bssid)); +#if defined(BSSCACHE) + node = node->next; +#endif + continue; + } + len_prep = 0; + err = wl_escan_merge_scan_results(dev, info, extra+len_ret, bi, + &len_prep, buflen_from_user-len_ret); + len_ret += len_prep; + if (err) goto exit; - } - -#if defined(RSSIAVG) - rssi = wl_get_avg_rssi(&escan->g_rssi_cache_ctrl, &bi->BSSID); - if (rssi == RSSI_MINVAL) - rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); -#else - // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS - rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); -#endif - channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); - ESCAN_SCAN(("BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n", - MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID)); - - /* First entry must be the BSSID */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); - - /* SSID */ - iwe.u.data.length = dtoh32(bi->SSID_len); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); - - /* Mode */ - if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { - iwe.cmd = SIOCGIWMODE; - if (dtoh16(bi->capability) & DOT11_CAP_ESS) - iwe.u.mode = IW_MODE_INFRA; - else - iwe.u.mode = IW_MODE_ADHOC; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); - } - - /* Channel */ - iwe.cmd = SIOCGIWFREQ; -#if 1 - iwe.u.freq.m = wf_channel2mhz(channel, channel <= CH_MAX_2G_CHANNEL ? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); -#else - iwe.u.freq.m = wf_channel2mhz(bi->n_cap ? - bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec), - CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); -#endif - iwe.u.freq.e = 6; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); - - /* Channel quality */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = rssi_to_qual(rssi); - iwe.u.qual.level = 0x100 + rssi; - iwe.u.qual.noise = 0x100 + bi->phy_noise; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); - - wl_iw_handle_scanresults_ies(&event, end, info, bi); - - /* Encryption */ - iwe.cmd = SIOCGIWENCODE; - if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); - - /* Rates */ - if (bi->rateset.count <= sizeof(bi->rateset.rates)) { - if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) { - err = -E2BIG; - goto exit; - } - value = event + IW_EV_LCP_LEN; - iwe.cmd = SIOCGIWRATE; - /* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { - iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; - value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, - IW_EV_PARAM_LEN); - } - event = value; - } #if defined(BSSCACHE) node = node->next; #endif } - dwrq->length = event - extra; + if ((len_ret + WE_ADD_EVENT_FIX) < dwrq->length) + dwrq->length = len_ret; + dwrq->flags = 0; /* todo */ - ESCAN_SCAN(("scanned AP count (%d)\n", i)); exit: + kfree(buf); + dwrq->length = len_ret; + ESCAN_SCAN(("scanned AP count (%d)\n", i)); mutex_unlock(&escan->usr_sync); return err; } s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len) { - struct wl_escan_info *escan = g_escan; + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_escan_info *escan = dhd->escan; int ret = 0; int bytes_written = -1; @@ -1432,7 +1500,7 @@ static s32 wl_escan_init(struct wl_escan_info *escan) void wl_escan_detach(dhd_pub_t *dhdp) { - struct wl_escan_info *escan = g_escan; + struct wl_escan_info *escan = dhdp->escan; printf("%s: Enter\n", __FUNCTION__); @@ -1448,7 +1516,7 @@ void wl_escan_detach(dhd_pub_t *dhdp) escan->escan_ioctl_buf = NULL; } DHD_OS_PREFREE(dhdp, escan, sizeof(struct wl_escan_info)); - g_escan = NULL; + dhdp->escan = NULL; } int @@ -1463,7 +1531,7 @@ wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp) escan = (wl_escan_info_t *)DHD_OS_PREALLOC(dhdp, DHD_PREALLOC_WL_ESCAN_INFO, sizeof(struct wl_escan_info)); if (!escan) return -ENOMEM; - g_escan = escan; + dhdp->escan = (void *)escan; memset(escan, 0, sizeof(struct wl_escan_info)); /* we only care about main interface so save a global here */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h index 6d84ce56c547..5106069d1dab 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h @@ -27,6 +27,11 @@ struct escan_event_q { s8 edata[1]; }; +struct pmk_list { + pmkid_list_t pmkids; + pmkid_t foo[MAXPMKID - 1]; +}; + /* donlge escan state */ enum escan_state { ESCAN_STATE_IDLE, @@ -66,6 +71,8 @@ typedef struct wl_escan_info { #if defined(BSSCACHE) wl_bss_cache_ctrl_t g_bss_cache_ctrl; #endif + struct pmk_list pmk_list; + wl_conn_info_t conn_info; } wl_escan_info_t; void wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c index 4713882c27ae..fc06441207ac 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c @@ -48,6 +48,7 @@ #ifdef WL_ESCAN #include #endif +#include typedef const struct si_pub si_t; @@ -105,10 +106,6 @@ uint iw_msg_level = WL_ERROR_LEVEL; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) #include #endif -#if defined(SOFTAP) -struct net_device *ap_net_dev = NULL; -tsk_ctl_t ap_eth_ctl; /* apsta AP netdev waiter thread */ -#endif /* SOFTAP */ extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason, char* stringBuf, uint buflen); @@ -133,6 +130,7 @@ extern int dhd_wait_pend8021x(struct net_device *dev); #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) #endif /* WIRELESS_EXT < 19 */ + #ifndef WL_ESCAN #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) #define DAEMONIZE(a) do { \ @@ -163,6 +161,11 @@ typedef struct iscan_buf { char iscan_buf[WLC_IW_ISCAN_MAXLEN]; } iscan_buf_t; +struct pmk_list { + pmkid_list_t pmkids; + pmkid_t foo[MAXPMKID - 1]; +}; + typedef struct iscan_info { struct net_device *dev; struct timer_list timer; @@ -179,11 +182,10 @@ typedef struct iscan_info { long sysioc_pid; struct semaphore sysioc_sem; struct completion sysioc_exited; - - char ioctlbuf[WLC_IOCTL_SMLEN]; + struct pmk_list pmk_list; + wl_conn_info_t conn_info; } iscan_info_t; -iscan_info_t *g_iscan = NULL; static void wl_iw_timerfunc(ulong data); static void wl_iw_set_event_mask(struct net_device *dev); static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action); @@ -471,6 +473,42 @@ wl_iw_set_pm( } #endif /* WIRELESS_EXT > 12 */ +static void +wl_iw_check_handshake(struct net_device *dev, bool set) +{ +#ifndef WL_CFG80211 + struct dhd_pub *dhd = dhd_get_pub(dev); + int cur_eapol_status = 0; + int wpa_auth = 0; + int error = -EINVAL; + + if (dhd && dhd->conf) + cur_eapol_status = dhd->conf->eapol_status; + + if (set) { + if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &wpa_auth))) { + WL_ERROR(("%s: wpa_auth get error %d\n", __FUNCTION__, error)); + return; + } + if (wpa_auth & (WPA_AUTH_PSK|WPA2_AUTH_PSK)) + dhd->conf->eapol_status = EAPOL_STATUS_WPA_START; + else + dhd->conf->eapol_status = EAPOL_STATUS_NONE; + } else { + if (cur_eapol_status >= EAPOL_STATUS_WPA_START && + cur_eapol_status < EAPOL_STATUS_WPA_END) { + WL_ERROR(("%s: WPA failed at %d\n", __FUNCTION__, cur_eapol_status)); + dhd->conf->eapol_status = EAPOL_STATUS_NONE; + } else if (cur_eapol_status >= EAPOL_STATUS_WPS_WSC_START && + cur_eapol_status < EAPOL_STATUS_WPS_DONE) { + WL_ERROR(("%s: WPS failed at %d\n", __FUNCTION__, cur_eapol_status)); + dhd->conf->eapol_status = EAPOL_STATUS_NONE; + } + } +#endif + return; +} + int wl_iw_send_priv_event( struct net_device *dev, @@ -583,6 +621,21 @@ wl_iw_set_freq( { int error, chan; uint sf = 0; + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_conn_info_t *conn_info = NULL; +#ifdef WL_ESCAN + wl_escan_info_t *escan; + if (dhd && dhd->escan) { + escan = (wl_escan_info_t *)dhd->escan; + conn_info = &escan->conn_info; + } +#else + iscan_info_t *iscan; + if (dhd && dhd->iscan) { + iscan = (iscan_info_t *)dhd->iscan; + conn_info = &iscan->conn_info; + } +#endif WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name)); @@ -608,6 +661,8 @@ wl_iw_set_freq( } chan = wf_mhz2channel(fwrq->m, sf); } + if (conn_info) + conn_info->channel = chan; WL_ERROR(("%s: chan=%d\n", __FUNCTION__, chan)); chan = htod32(chan); if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan)))) { @@ -652,8 +707,25 @@ wl_iw_set_mode( ) { int infra = 0, ap = 0, error = 0; + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_conn_info_t *conn_info = NULL; +#ifdef WL_ESCAN + wl_escan_info_t *escan; + if (dhd && dhd->escan) { + escan = (wl_escan_info_t *)dhd->escan; + conn_info = &escan->conn_info; + } +#else + iscan_info_t *iscan; + if (dhd && dhd->iscan) { + iscan = (iscan_info_t *)dhd->iscan; + conn_info = &iscan->conn_info; + } +#endif WL_TRACE(("%s: SIOCSIWMODE\n", dev->name)); + if (conn_info) + memset(conn_info, 0, sizeof(wl_conn_info_t)); switch (*uwrq) { case IW_MODE_MASTER: @@ -997,6 +1069,21 @@ wl_iw_set_wap( ) { int error = -EINVAL; + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_conn_info_t *conn_info = NULL; +#ifdef WL_ESCAN + wl_escan_info_t *escan; + if (dhd && dhd->escan) { + escan = (wl_escan_info_t *)dhd->escan; + conn_info = &escan->conn_info; + } +#else + iscan_info_t *iscan; + if (dhd && dhd->iscan) { + iscan = (iscan_info_t *)dhd->iscan; + conn_info = &iscan->conn_info; + } +#endif WL_TRACE(("%s: SIOCSIWAP\n", dev->name)); @@ -1013,17 +1100,26 @@ wl_iw_set_wap( if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) { WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error)); } + wl_iw_check_handshake(dev, FALSE); return 0; } /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data), * eabuf))); */ /* Reassociate to the specified AP */ - if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) { - WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error)); - return error; + if (conn_info) + memcpy(&conn_info->bssid, awrq->sa_data, ETHER_ADDR_LEN); + if (conn_info && conn_info->ssid.SSID_len) { + if ((error = wl_ext_connect(dev, conn_info))) + return error; + } else { + if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) { + WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error)); + return error; + } + WL_ERROR(("%s: join BSSID="MACSTR"\n", __FUNCTION__, MAC2STR((u8 *)awrq->sa_data))); } - WL_ERROR(("%s: join BSSID="MACSTR"\n", __FUNCTION__, MAC2STR((u8 *)awrq->sa_data))); + wl_iw_check_handshake(dev, TRUE); return 0; } @@ -1084,6 +1180,7 @@ wl_iw_mlme( WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__)); return error; } + wl_iw_check_handshake(dev, FALSE); return error; } @@ -1176,13 +1273,16 @@ wl_iw_iscan_get_aplist( { wl_scan_results_t *list; iscan_buf_t * buf; - iscan_info_t *iscan = g_iscan; + iscan_info_t *iscan; struct sockaddr *addr = (struct sockaddr *) extra; struct iw_quality qual[IW_MAX_AP]; wl_bss_info_t *bi = NULL; int i; int16 rssi; + struct dhd_pub *dhd = dhd_get_pub(dev); + if (dhd && dhd->iscan) + iscan = (iscan_info_t *)dhd->iscan; WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); @@ -1282,7 +1382,10 @@ wl_iw_iscan_set_scan( ) { wlc_ssid_t ssid; - iscan_info_t *iscan = g_iscan; + struct dhd_pub *dhd = dhd_get_pub(dev); + iscan_info_t *iscan; + if (dhd && dhd->iscan) + iscan = (iscan_info_t *)dhd->iscan; WL_TRACE(("%s: SIOCSIWSCAN iscan=%p\n", dev->name, iscan)); @@ -1586,10 +1689,13 @@ wl_iw_iscan_get_scan( int ii, j; int apcnt; char *event = extra, *end = extra + dwrq->length, *value; - iscan_info_t *iscan = g_iscan; iscan_buf_t * p_buf; int16 rssi; int channel; + struct dhd_pub *dhd = dhd_get_pub(dev); + iscan_info_t *iscan; + if (dhd && dhd->iscan) + iscan = (iscan_info_t *)dhd->iscan; WL_TRACE(("%s: %s SIOCGIWSCAN\n", __FUNCTION__, dev->name)); @@ -1722,6 +1828,21 @@ wl_iw_set_essid( { wlc_ssid_t ssid; int error; + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_conn_info_t *conn_info = NULL; +#ifdef WL_ESCAN + wl_escan_info_t *escan; + if (dhd && dhd->escan) { + escan = (wl_escan_info_t *)dhd->escan; + conn_info = &escan->conn_info; + } +#else + iscan_info_t *iscan; + if (dhd && dhd->iscan) { + iscan = (iscan_info_t *)dhd->iscan; + conn_info = &iscan->conn_info; + } +#endif WL_TRACE(("%s: SIOCSIWESSID\n", dev->name)); @@ -1736,11 +1857,21 @@ wl_iw_set_essid( memcpy(ssid.SSID, extra, ssid.SSID_len); ssid.SSID_len = htod32(ssid.SSID_len); - if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)))) { - WL_ERROR(("%s: WLC_SET_SSID failed (%d).\n", __FUNCTION__, error)); - return error; + if (conn_info) { + memcpy(conn_info->ssid.SSID, ssid.SSID, ssid.SSID_len); + conn_info->ssid.SSID_len = ssid.SSID_len; } - WL_ERROR(("%s: join SSID=%s\n", __FUNCTION__, ssid.SSID)); + if (conn_info && memcmp(ðer_null, &conn_info->bssid, ETHER_ADDR_LEN)) { + if ((error = wl_ext_connect(dev, conn_info))) + return error; + } else { + if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)))) { + WL_ERROR(("%s: WLC_SET_SSID failed (%d).\n", __FUNCTION__, error)); + return error; + } + WL_ERROR(("%s: join SSID=%s\n", __FUNCTION__, ssid.SSID)); + } + wl_iw_check_handshake(dev, TRUE); } /* If essid null then it is "iwconfig essid off" command */ else { @@ -1751,6 +1882,7 @@ wl_iw_set_essid( WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error)); return error; } + wl_iw_check_handshake(dev, FALSE); } return 0; } @@ -2410,6 +2542,7 @@ wl_iw_set_encodeext( wl_wsec_key_t key; int error; struct iw_encode_ext *iwe; + struct dhd_pub *dhd = dhd_get_pub(dev); WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name)); @@ -2535,15 +2668,13 @@ wl_iw_set_encodeext( error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); if (error) return error; + if (dhd && dhd->conf) + dhd->conf->eapol_status = EAPOL_STATUS_WPA_END; } return 0; } - -struct { - pmkid_list_t pmkids; - pmkid_t foo[MAXPMKID-1]; -} pmkid_list; +/* wpa2 pmk list */ static int wl_iw_set_pmksa( struct net_device *dev, @@ -2552,17 +2683,34 @@ wl_iw_set_pmksa( char *extra ) { + struct pmk_list *pmk_list = NULL; struct iw_pmksa *iwpmksa; uint i; char eabuf[ETHER_ADDR_STR_LEN]; - pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid; + pmkid_t *pmkid_array = NULL; + struct dhd_pub *dhd = dhd_get_pub(dev); +#ifdef WL_ESCAN + wl_escan_info_t *escan; + if (dhd && dhd->escan) { + escan = (wl_escan_info_t *)dhd->escan; + pmk_list = &escan->pmk_list; + } +#else + iscan_info_t *iscan; + if (dhd && dhd->iscan) { + iscan = (iscan_info_t *)dhd->iscan; + pmk_list = &iscan->pmk_list; + } +#endif WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name)); + if (pmk_list) + pmkid_array = pmk_list->pmkids.pmkid; iwpmksa = (struct iw_pmksa *)extra; bzero((char *)eabuf, ETHER_ADDR_STR_LEN); if (iwpmksa->cmd == IW_PMKSA_FLUSH) { WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n")); - bzero((char *)&pmkid_list, sizeof(pmkid_list)); + bzero((char *)pmk_list, sizeof(struct pmk_list)); } if (iwpmksa->cmd == IW_PMKSA_REMOVE) { pmkid_list_t pmkid, *pmkidptr; @@ -2578,11 +2726,11 @@ wl_iw_set_pmksa( WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j])); WL_TRACE(("\n")); } - for (i = 0; i < pmkid_list.pmkids.npmkid; i++) + for (i = 0; i < pmk_list->pmkids.npmkid; i++) if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID, ETHER_ADDR_LEN)) break; - for (; i < pmkid_list.pmkids.npmkid; i++) { + for (; i < pmk_list->pmkids.npmkid; i++) { bcopy(&pmkid_array[i+1].BSSID, &pmkid_array[i].BSSID, ETHER_ADDR_LEN); @@ -2590,18 +2738,18 @@ wl_iw_set_pmksa( &pmkid_array[i].PMKID, WPA2_PMKID_LEN); } - pmkid_list.pmkids.npmkid--; + pmk_list->pmkids.npmkid--; } if (iwpmksa->cmd == IW_PMKSA_ADD) { bcopy(&iwpmksa->bssid.sa_data[0], - &pmkid_array[pmkid_list.pmkids.npmkid].BSSID, + &pmkid_array[pmk_list->pmkids.npmkid].BSSID, ETHER_ADDR_LEN); - bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmkid_list.pmkids.npmkid].PMKID, + bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmk_list->pmkids.npmkid].PMKID, WPA2_PMKID_LEN); { uint j; uint k; - k = pmkid_list.pmkids.npmkid; + k = pmk_list->pmkids.npmkid; BCM_REFERENCE(k); WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ", bcm_ether_ntoa(&pmkid_array[k].BSSID, @@ -2610,10 +2758,10 @@ wl_iw_set_pmksa( WL_TRACE(("%02x ", pmkid_array[k].PMKID[j])); WL_TRACE(("\n")); } - pmkid_list.pmkids.npmkid++; + pmk_list->pmkids.npmkid++; } - WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid)); - for (i = 0; i < pmkid_list.pmkids.npmkid; i++) { + WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmk_list->pmkids.npmkid)); + for (i = 0; i < pmk_list->pmkids.npmkid; i++) { uint j; WL_TRACE(("PMKID[%d]: %s = ", i, bcm_ether_ntoa(&pmkid_array[i].BSSID, @@ -2623,7 +2771,7 @@ wl_iw_set_pmksa( printf("\n"); } WL_TRACE(("\n")); - dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list)); + dev_wlc_bufvar_set(dev, "pmkid_info", (char *)pmk_list, sizeof(struct pmk_list)); return 0; } @@ -3101,6 +3249,12 @@ wl_iw_ioctl( char *extra = NULL; size_t token_size = 1; int max_tokens = 0, ret = 0; +#ifndef WL_ESCAN + struct dhd_pub *dhd = dhd_get_pub(dev); + iscan_info_t *iscan; + if (dhd && dhd->iscan) + iscan = (iscan_info_t *)dhd->iscan; +#endif if (cmd < SIOCIWFIRST || IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) || @@ -3137,7 +3291,7 @@ wl_iw_ioctl( #if WIRELESS_EXT > 13 case SIOCGIWSCAN: #ifndef WL_ESCAN - if (g_iscan) + if (iscan) max_tokens = wrq->u.data.length; else #endif @@ -3306,6 +3460,12 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) uint32 datalen = ntoh32(e->datalen); uint32 status = ntoh32(e->status); uint32 reason = ntoh32(e->reason); +#ifndef WL_ESCAN + struct dhd_pub *dhd = dhd_get_pub(dev); + iscan_info_t *iscan; + if (dhd && dhd->iscan) + iscan = (iscan_info_t *)dhd->iscan; +#endif memset(&wrqu, 0, sizeof(wrqu)); memset(extra, 0, sizeof(extra)); @@ -3329,16 +3489,17 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) wrqu.data.length = strlen(extra); bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); + wl_iw_check_handshake(dev, FALSE); break; case WLC_E_LINK: cmd = SIOCGIWAP; - wrqu.data.length = strlen(extra); if (!(flags & WLC_EVENT_MSG_LINK)) { printf("%s: Link Down with "MACSTR", reason=%d\n", __FUNCTION__, MAC2STR((u8 *)wrqu.addr.sa_data), reason); bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); + wl_iw_check_handshake(dev, FALSE); } else { printf("%s: Link UP with "MACSTR"\n", __FUNCTION__, MAC2STR((u8 *)wrqu.addr.sa_data)); @@ -3435,9 +3596,9 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) WL_TRACE(("event WLC_E_SCAN_COMPLETE\n")); // terence 20150224: fix "wlan0: (WE) : Wireless Event too big (65306)" memset(&wrqu, 0, sizeof(wrqu)); - if ((g_iscan) && (g_iscan->sysioc_pid >= 0) && - (g_iscan->iscan_state != ISCAN_STATE_IDLE)) - up(&g_iscan->sysioc_sem); + if ((iscan) && (iscan->sysioc_pid >= 0) && + (iscan->iscan_state != ISCAN_STATE_IDLE)) + up(&iscan->sysioc_sem); break; #endif @@ -3449,7 +3610,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) if (cmd) { #ifndef WL_ESCAN if (cmd == SIOCGIWSCAN) { - if ((!g_iscan) || (g_iscan->sysioc_pid < 0)) { + if ((!iscan) || (iscan->sysioc_pid < 0)) { wireless_send_event(dev, cmd, &wrqu, NULL); }; } else @@ -3875,12 +4036,10 @@ _iscan_sysioc_thread(void *data) printf("%s: was terminated\n", __FUNCTION__); complete_and_exit(&iscan->sysioc_exited, 0); } -#endif /* WL_ESCAN */ int -wl_iw_attach(struct net_device *dev, void * dhdp) +wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) { -#ifndef WL_ESCAN iscan_info_t *iscan = NULL; printf("%s: Enter\n", __FUNCTION__); @@ -3891,13 +4050,13 @@ wl_iw_attach(struct net_device *dev, void * dhdp) iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL); if (!iscan) return -ENOMEM; + dhdp->iscan = (void *)iscan; memset(iscan, 0, sizeof(iscan_info_t)); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) iscan->kthread = NULL; #endif iscan->sysioc_pid = -1; /* we only care about main interface so save a global here */ - g_iscan = iscan; iscan->dev = dev; iscan->iscan_state = ISCAN_STATE_IDLE; @@ -3921,15 +4080,13 @@ wl_iw_attach(struct net_device *dev, void * dhdp) #endif if (iscan->sysioc_pid < 0) return -ENOMEM; -#endif /* WL_ESCAN */ return 0; } -void wl_iw_detach(void) +void wl_iw_detach(dhd_pub_t *dhdp) { -#ifndef WL_ESCAN iscan_buf_t *buf; - iscan_info_t *iscan = g_iscan; + iscan_info_t *iscan = dhdp->iscan; if (!iscan) return; if (iscan->sysioc_pid >= 0) { @@ -3943,8 +4100,8 @@ void wl_iw_detach(void) iscan->list_hdr = buf; } kfree(iscan); - g_iscan = NULL; -#endif + dhdp->iscan = NULL; } +#endif /* !WL_ESCAN */ #endif /* USE_IW */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h index 137be566b1f3..0adba1b52b03 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h @@ -35,6 +35,8 @@ #include #include #include +#include +#include #define WL_SCAN_PARAMS_SSID_MAX 10 #define GET_SSID "SSID=" @@ -123,15 +125,15 @@ extern const struct iw_handler_def wl_iw_handler_def; extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data); extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats); -int wl_iw_attach(struct net_device *dev, void * dhdp); int wl_iw_send_priv_event(struct net_device *dev, char *flag); #ifdef WL_ESCAN int wl_iw_handle_scanresults_ies(char **event_p, char *end, struct iw_request_info *info, wl_bss_info_t *bi); +#else +int wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp); +void wl_iw_detach(dhd_pub_t *dhdp); #endif -void wl_iw_detach(void); - #define CSCAN_COMMAND "CSCAN " #define CSCAN_TLV_PREFIX 'S' #define CSCAN_TLV_VERSION 1 diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c index 8be455fc777e..38b7117463ac 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c @@ -499,7 +499,7 @@ int wldev_set_country( cspec.rev = revinfo; memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); - error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec, 0); + error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec); if (error) dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);