diff options
author | Dennis Jeon <dennis.jeon@broadcom.corp-partner.google.com> | 2023-08-31 09:06:28 -0400 |
---|---|---|
committer | kensun <kensun@google.com> | 2023-09-05 12:06:56 +0000 |
commit | 97a64ddb9c18696ce5f9f5af9438db6d0a89ab04 (patch) | |
tree | 47216415d64ecd5f41b7f48c06789d29cc33489f | |
parent | 395ec6912866550c43e22aee9aff60b6f6fe5e92 (diff) | |
download | bcm4398-97a64ddb9c18696ce5f9f5af9438db6d0a89ab04.tar.gz |
DHD QPR release for bcm4398, 2023.8.31 Version : 103.10.243.18
b/294772744 - crash_reason: BY_LIVELOCK (pa/2602203)
b/296057838 - KP: softlockup: hung tasks [kernel panic, softlockup: hung tasks, logspam (pa/2587356)
b/295208412 - KP: BRK handler: Fatal exception: comm:kworker/7:2 PC:dhdpcie_dump_oobr (pa/2602779)
b/289901429 - cellular coex feature problem - why the unsafe list includes the 5GHz channel 32/68 (pa/2557682)
b/291825549 - "Fixed the code by removing unintended write from DHD to chip which was causing chip to hang and requires a SSR to recover" (pa/2550480)
b/291518630 - Avoid scan busy calling log dump (pa/2552825)
b/292450431 - Unable to handle kernel paging request, PC is at wl_cfg80211_wbtext_update_rcc (pa/2561053)
b/295911312 - logspam from dhd driver (pa/2588678)
b/294830926 - Fatal exception: comm:init PC:wl_cfg80211_stop_pno+0x5c/0x284
b/290691662 - Cannot turn on/off hotspot
b/291738207 - Cannot turn on/off hotspot
Bug: 298295660
Test: SVT test cycle
Change-Id: Ia6e9de5fc985b8b42a7c9611da5fb698bd83460b
Signed-off-by: Dennis Jeon <dennis.jeon@broadcom.corp-partner.google.com>
-rw-r--r-- | Kbuild | 2 | ||||
-rw-r--r-- | dhd_custom_cis.c | 253 | ||||
-rw-r--r-- | dhd_custom_google.c | 23 | ||||
-rw-r--r-- | dhd_debug.c | 2 | ||||
-rw-r--r-- | dhd_linux.c | 19 | ||||
-rw-r--r-- | dhd_linux_lb.c | 5 | ||||
-rw-r--r-- | dhd_linux_platdev.c | 2 | ||||
-rw-r--r-- | dhd_msgbuf.c | 39 | ||||
-rw-r--r-- | dhd_pcie.c | 39 | ||||
-rw-r--r-- | dhd_pno.c | 1 | ||||
-rw-r--r-- | include/epivers.h | 12 | ||||
-rw-r--r-- | wl_android.c | 2 | ||||
-rw-r--r-- | wl_cfg80211.c | 93 | ||||
-rw-r--r-- | wl_cfg80211.h | 6 | ||||
-rw-r--r-- | wl_cfg_cellavoid.c | 2 | ||||
-rw-r--r-- | wl_cfgscan.c | 70 |
16 files changed, 325 insertions, 245 deletions
@@ -349,7 +349,7 @@ ifneq ($(CONFIG_SOC_GOOGLE),) # Recover timeouts DHDCFLAGS += -DDHD_RECOVER_TIMEOUT # PCIE CPL TIMEOUT WAR - #DHDCFLAGS += -DDHD_TREAT_D3ACKTO_AS_LINKDWN + # DHDCFLAGS += -DDHD_TREAT_D3ACKTO_AS_LINKDWN # Skip coredump for certain health check traps DHDCFLAGS += -DDHD_SKIP_COREDUMP_ON_HC # Skip coredump for older chip revs diff --git a/dhd_custom_cis.c b/dhd_custom_cis.c index 9c1dbf9..eda0ceb 100644 --- a/dhd_custom_cis.c +++ b/dhd_custom_cis.c @@ -343,11 +343,85 @@ typedef struct otp_access { uint32 bpdata[2]; } otp_access_t; -otp_access_t otp_info[] = { -/* {chipid, {OTPCtrl1 addr, PMU minrsrcmask addr}, {OTPCtrl1 val, PMU minrsrcmask val} */ - {0x4389, {0x18010324, 0x18012618}, {0x00fa0000, 0x0e4fffff}}, - {0x4398, {0x18010324, 0x1801F618}, {0x0, 0xE4FF9DF}} -}; +#ifdef DHD_USE_CISINFO +/* File Location to keep each information */ +#ifdef OEM_ANDROID +#define MACINFO "/data/.mac.info" +#define MACINFO_EFS "/efs/wifi/.mac.info" +#define CIDINFO PLATFORM_PATH".cid.info" +#define CIDINFO_DATA "/data/.cid.info" +#elif defined(PLATFORM_SLP) +#define CIDINFO "/opt/etc/.cid.info" +#define MACINFO "/opt/etc/.mac.info" +#define MACINFO_EFS "/csa/.mac.info" +#else +#define MACINFO "/opt/.mac.info" +#define MACINFO_EFS "/opt/.efs.mac.info" +#define CIDINFO "/opt/.cid.info" +#endif /* OEM_ANDROID */ + +/* Definitions for MAC address */ +#define MAC_BUF_SIZE 20 +#define MAC_CUSTOM_FORMAT "%02X:%02X:%02X:%02X:%02X:%02X" + +#define CIS_BUF_SIZE 1280 +#define DUMP_CIS_SIZE 48 + +#define CIS_TUPLE_TAG_START 0x80 +#define CIS_TUPLE_TAG_VENDOR 0x81 +#define CIS_TUPLE_TAG_MACADDR 0x19 +#define CIS_TUPLE_TAG_BOARDTYPE 0x1b +#define CIS_TUPLE_LEN_MACADDR 7 +#define CIS_DUMP_END 0xff +#define CIS_TUPLE_NULL 0X00 + +#ifdef CONFIG_BCMDHD_PCIE +#if defined(BCM4361_CHIP) || defined(BCM4375_CHIP) +#define OTP_OFFSET 208 +#elif defined(BCM4389_CHIP_DEF) || defined(BCM4398_CHIP_DEF) +#define OTP_OFFSET 0 +#else +#define OTP_OFFSET 128 +#endif /* BCM4361 | BCM4375 = 208, BCM4389 = 0, Others = 128 */ +#else /* CONFIG_BCMDHD_PCIE */ +#define OTP_OFFSET 12 /* SDIO */ +#endif /* CONFIG_BCMDHD_PCIE */ + +unsigned char *g_cis_buf = NULL; + +/* Definitions for common interface */ +typedef struct tuple_entry { + struct list_head list; /* head of the list */ + uint32 cis_idx; /* index of each tuples */ +} tuple_entry_t; + +extern int _dhd_set_mac_address(struct dhd_info *dhd, int ifidx, struct ether_addr *addr); +#if defined(GET_MAC_FROM_OTP) || defined(USE_CID_CHECK) +static tuple_entry_t *dhd_alloc_tuple_entry(dhd_pub_t *dhdp, const int idx); +static void dhd_free_tuple_entry(dhd_pub_t *dhdp, struct list_head *head); +static int dhd_find_tuple_list_from_otp(dhd_pub_t *dhdp, int req_tup, + unsigned char* req_tup_len, struct list_head *head); +#endif /* GET_MAC_FROM_OTP || USE_CID_CHECK */ + +/* otp region read/write information */ +typedef struct otp_rgn_rw_info { + uint8 rgnid; + uint8 preview; + uint8 integrity_chk; + uint16 rgnsize; + uint16 datasize; + uint8 *data; +} otp_rgn_rw_info_t; + +/* otp region status information */ +typedef struct otp_rgn_stat_info { + uint8 rgnid; + uint16 rgnstart; + uint16 rgnsize; +} otp_rgn_stat_info_t; + +typedef int (pack_handler_t)(void *ctx, uint8 *buf, uint16 *buflen); +#endif /* DHD_USE_CISINFO */ static INLINE int get_cis_tuple_chipidx(uint chipid) @@ -362,25 +436,11 @@ get_cis_tuple_chipidx(uint chipid) return -1; } -static INLINE int -get_otp_chipidx(uint chipid) -{ - int i = 0; - for (i = 0; i < ARRAYSIZE(otp_info); ++i) { - if (otp_info[i].chipid == chipid) { - return i; - } - } - - return -1; -} - static int read_otp_from_bp(dhd_bus_t *bus, uint32 *data_buf) { - int int_val = 0, i = 0, bp_idx = 0; - uint32 org_boardtype_backplane_data[] = {0, 0}; - int chipidx = 0, otpidx = 0; + int i = 0; + int chipidx = 0; uint chipid = si_chipid(bus->sih); uint32 cis_start_addr = 0; @@ -392,38 +452,6 @@ read_otp_from_bp(dhd_bus_t *bus, uint32 *data_buf) } cis_start_addr = CIS_TUPLE_START_ADDR(chipidx); - otpidx = get_otp_chipidx(chipid); - if (otpidx < 0) { - DHD_ERROR(("%s: unable to find otp info for chipid 0x%x !\n", - __FUNCTION__, chipid)); - return BCME_NOTFOUND; - } - - for (bp_idx = 0; bp_idx < ARRAYSIZE(otp_info[otpidx].bpaddr); bp_idx++) { - /* Read OTP Control 1 and PMU min_rsrc_mask before writing */ - if (si_backplane_access(bus->sih, otp_info[otpidx].bpaddr[bp_idx], sizeof(int), - &org_boardtype_backplane_data[bp_idx], TRUE) != BCME_OK) { - DHD_ERROR(("invalid size/addr combination\n")); - return BCME_ERROR; - } - - /* Write new OTP and PMU configuration */ - if (si_backplane_access(bus->sih, otp_info[otpidx].bpaddr[bp_idx], sizeof(int), - &otp_info[otpidx].bpdata[bp_idx], FALSE) != BCME_OK) { - DHD_ERROR(("invalid size/addr combination\n")); - return BCME_ERROR; - } - - if (si_backplane_access(bus->sih, otp_info[otpidx].bpaddr[bp_idx], sizeof(int), - &int_val, TRUE) != BCME_OK) { - DHD_ERROR(("invalid size/addr combination\n")); - return BCME_ERROR; - } - - DHD_INFO(("%s: boardtype_backplane_addr 0x%08x rdata 0x%04x\n", - __FUNCTION__, otp_info[otpidx].bpaddr[bp_idx], int_val)); - } - /* read tuple raw data */ for (i = 0; i < CIS_TUPLE_MAX_CNT(chipidx); i++) { if (si_backplane_access(bus->sih, cis_start_addr + i * sizeof(uint32), @@ -433,31 +461,12 @@ read_otp_from_bp(dhd_bus_t *bus, uint32 *data_buf) DHD_INFO(("%s: tuple index %d, raw data 0x%08x\n", __FUNCTION__, i, data_buf[i])); } - for (bp_idx = 0; bp_idx < ARRAYSIZE(otp_info[otpidx].bpaddr); bp_idx++) { - /* Write original OTP and PMU configuration */ - if (si_backplane_access(bus->sih, otp_info[otpidx].bpaddr[bp_idx], sizeof(int), - &org_boardtype_backplane_data[bp_idx], FALSE) != BCME_OK) { - DHD_ERROR(("invalid size/addr combination\n")); - return BCME_ERROR; - } - - if (si_backplane_access(bus->sih, otp_info[otpidx].bpaddr[bp_idx], sizeof(int), - &int_val, TRUE) != BCME_OK) { - DHD_ERROR(("invalid size/addr combination\n")); - return BCME_ERROR; - } - - DHD_INFO(("%s: boardtype_backplane_addr 0x%08x rdata 0x%04x\n", - __FUNCTION__, otp_info[otpidx].bpaddr[bp_idx], int_val)); - } - - return i * sizeof(uint32); } static int dhd_parse_board_information_bcm(dhd_bus_t *bus, int *boardtype, - unsigned char *vid, int *vid_length) + unsigned char *vid, int *vid_length, bool store_otp) { int totlen, len; uint32 *raw_data = NULL; @@ -467,6 +476,12 @@ dhd_parse_board_information_bcm(dhd_bus_t *bus, int *boardtype, int ret = 0; uint otp_cis_sz = 0; + int cis_offset = OTP_OFFSET + sizeof(cis_rw_t); +#if defined(BCM4389_CHIP_DEF) || defined(BCM4398_CHIP_DEF) + /* override OTP_OFFSET for 4389 */ + cis_offset = OTP_OFFSET; +#endif /* BCM4389_CHIP_DEF || BCM4398_CHIP_DEF */ + chipidx = get_cis_tuple_chipidx(chipid); if (chipidx < 0) { DHD_ERROR(("%s: unable to find CIS tuple addr for chipid 0x%x !\n", @@ -490,6 +505,13 @@ dhd_parse_board_information_bcm(dhd_bus_t *bus, int *boardtype, goto exit; } + if (store_otp && g_cis_buf) { + if (memcpy_s(g_cis_buf + cis_offset, CIS_BUF_SIZE, raw_data, totlen) != 0) { + DHD_ERROR(("%s : memcpy of otp data to local cis buf failed !\n", + __FUNCTION__)); + } + } + tuple = (cis_tuple_format_t *)raw_data; /* check the first tuple has tag 'start' */ @@ -882,7 +904,7 @@ dhd_get_fw_nvram_names(dhd_pub_t *dhdp, uint chipid, uint chiprev, } /* read Vendor ID (VID) from dongle OTP */ - if (dhd_parse_board_information_bcm(bus, &board_type, vid, &vid_length) + if (dhd_parse_board_information_bcm(bus, &board_type, vid, &vid_length, TRUE) != BCME_OK) { DHD_ERROR(("%s:failed to parse board information\n", __FUNCTION__)); /* If OTP is not programmed with vendor tuple, @@ -1000,7 +1022,7 @@ dhd_find_naming_info_by_chip_rev(dhd_pub_t *dhdp, bool *is_murata_fem) chip_rev = bus->sih->chiprev; - if (dhd_parse_board_information_bcm(bus, &board_type, vid, &vid_length) + if (dhd_parse_board_information_bcm(bus, &board_type, vid, &vid_length, FALSE) != BCME_OK) { DHD_ERROR(("%s:failed to parse board information\n", __FUNCTION__)); return NULL; @@ -1059,7 +1081,7 @@ concate_nvram_by_vid(dhd_pub_t *dhdp, char *nv_path, char *chipstr) return BCME_ERROR; } bus = dhdp->bus; - if (dhd_parse_board_information_bcm(bus, &board_type, vid, &vid_length) + if (dhd_parse_board_information_bcm(bus, &board_type, vid, &vid_length, FALSE) != BCME_OK) { DHD_ERROR(("%s:failed to parse board information\n", __FUNCTION__)); return BCME_ERROR; @@ -1080,85 +1102,6 @@ concate_nvram_by_vid(dhd_pub_t *dhdp, char *nv_path, char *chipstr) #endif /* DHD_USE_CISINFO_FROM_OTP */ #ifdef DHD_USE_CISINFO - -/* File Location to keep each information */ -#ifdef OEM_ANDROID -#define MACINFO "/data/.mac.info" -#define MACINFO_EFS "/efs/wifi/.mac.info" -#define CIDINFO PLATFORM_PATH".cid.info" -#define CIDINFO_DATA "/data/.cid.info" -#elif defined(PLATFORM_SLP) -#define CIDINFO "/opt/etc/.cid.info" -#define MACINFO "/opt/etc/.mac.info" -#define MACINFO_EFS "/csa/.mac.info" -#else -#define MACINFO "/opt/.mac.info" -#define MACINFO_EFS "/opt/.efs.mac.info" -#define CIDINFO "/opt/.cid.info" -#endif /* OEM_ANDROID */ - -/* Definitions for MAC address */ -#define MAC_BUF_SIZE 20 -#define MAC_CUSTOM_FORMAT "%02X:%02X:%02X:%02X:%02X:%02X" - -#define CIS_BUF_SIZE 1280 -#define DUMP_CIS_SIZE 48 - -#define CIS_TUPLE_TAG_START 0x80 -#define CIS_TUPLE_TAG_VENDOR 0x81 -#define CIS_TUPLE_TAG_MACADDR 0x19 -#define CIS_TUPLE_TAG_BOARDTYPE 0x1b -#define CIS_TUPLE_LEN_MACADDR 7 -#define CIS_DUMP_END 0xff -#define CIS_TUPLE_NULL 0X00 - -#ifdef CONFIG_BCMDHD_PCIE -#if defined(BCM4361_CHIP) || defined(BCM4375_CHIP) -#define OTP_OFFSET 208 -#elif defined(BCM4389_CHIP_DEF) || defined(BCM4398_CHIP_DEF) -#define OTP_OFFSET 0 -#else -#define OTP_OFFSET 128 -#endif /* BCM4361 | BCM4375 = 208, BCM4389 = 0, Others = 128 */ -#else /* CONFIG_BCMDHD_PCIE */ -#define OTP_OFFSET 12 /* SDIO */ -#endif /* CONFIG_BCMDHD_PCIE */ - -unsigned char *g_cis_buf = NULL; - -/* Definitions for common interface */ -typedef struct tuple_entry { - struct list_head list; /* head of the list */ - uint32 cis_idx; /* index of each tuples */ -} tuple_entry_t; - -extern int _dhd_set_mac_address(struct dhd_info *dhd, int ifidx, struct ether_addr *addr); -#if defined(GET_MAC_FROM_OTP) || defined(USE_CID_CHECK) -static tuple_entry_t *dhd_alloc_tuple_entry(dhd_pub_t *dhdp, const int idx); -static void dhd_free_tuple_entry(dhd_pub_t *dhdp, struct list_head *head); -static int dhd_find_tuple_list_from_otp(dhd_pub_t *dhdp, int req_tup, - unsigned char* req_tup_len, struct list_head *head); -#endif /* GET_MAC_FROM_OTP || USE_CID_CHECK */ - -/* otp region read/write information */ -typedef struct otp_rgn_rw_info { - uint8 rgnid; - uint8 preview; - uint8 integrity_chk; - uint16 rgnsize; - uint16 datasize; - uint8 *data; -} otp_rgn_rw_info_t; - -/* otp region status information */ -typedef struct otp_rgn_stat_info { - uint8 rgnid; - uint16 rgnstart; - uint16 rgnsize; -} otp_rgn_stat_info_t; - -typedef int (pack_handler_t)(void *ctx, uint8 *buf, uint16 *buflen); - /* Common Interface Functions */ int dhd_alloc_cis(dhd_pub_t *dhdp) diff --git a/dhd_custom_google.c b/dhd_custom_google.c index 3e0438c..6902b27 100644 --- a/dhd_custom_google.c +++ b/dhd_custom_google.c @@ -399,10 +399,12 @@ dhd_get_platform_naming_for_nvram_clmblob_file(download_type_t component, char * DHD_ERROR(("ext_name is not composed.\n")); return BCME_ERROR; } + if(hw_stage_val < EVT) { DHD_ERROR(("No multi-NVRAM/CLM support on Proto/Dev device\n")); return BCME_ERROR; } + if (component == NVRAM) { #ifdef DHD_LINUX_STD_FW_API nvram_clmblob_file = DHD_NVRAM_NAME; @@ -786,12 +788,12 @@ irq_affinity_hysteresis_control(struct pci_dev *pdev, int resched_streak_max, } } if (is_plat_pcie_resume || - (is_irq_on_big_core && (resched_streak_max <= RESCHED_STREAK_MAX_LOW) && - !has_recent_affinity_update)) { + (is_irq_on_big_core && (resched_streak_max <= RESCHED_STREAK_MAX_LOW) && + !has_recent_affinity_update)) { err = set_affinity(pdev->irq, cpumask_of(IRQ_AFFINITY_SMALL_CORE)); if (!err) { is_irq_on_big_core = FALSE; - is_plat_pcie_resume = FALSE; + is_plat_pcie_resume = FALSE; last_affinity_update_time_ns = curr_time_ns; DHD_INFO(("%s switches to all cores successfully\n", __FUNCTION__)); } else { @@ -814,8 +816,9 @@ void dhd_plat_report_bh_sched(void *plat_info, int resched) if (resched > 0) { resched_streak++; - if (resched_streak <= RESCHED_STREAK_MAX_HIGH) + if (resched_streak <= RESCHED_STREAK_MAX_HIGH) { return; + } } if (resched_streak > resched_streak_max) { @@ -982,8 +985,8 @@ int dhd_plat_pcie_resume(void *plat_info) { int ret = 0; ret = exynos_pcie_pm_resume(pcie_ch_num); - is_plat_pcie_resume = TRUE; - return ret; + is_plat_pcie_resume = TRUE; + return ret; } void dhd_plat_pin_dbg_show(void *plat_info) @@ -1036,10 +1039,12 @@ void dhd_plat_pcie_skip_config_set(bool val) exynos_pcie_set_skip_config(pcie_ch_num, val); #endif /* DHD_TREAT_D3ACKTO_AS_LINKDWN */ } - bool dhd_plat_pcie_enable_big_core(void) - { + +bool dhd_plat_pcie_enable_big_core(void) +{ return is_irq_on_big_core; - } +} + #ifndef BCMDHD_MODULAR /* Required only for Built-in DHD */ device_initcall(dhd_wlan_init); diff --git a/dhd_debug.c b/dhd_debug.c index 281bc4d..f7e981d 100644 --- a/dhd_debug.c +++ b/dhd_debug.c @@ -401,7 +401,7 @@ dhd_dbg_msgtrace_seqchk(uint32 *prev, uint32 cur) DHD_EVENT(("%s duplicate trace\n", __FUNCTION__)); return -1; } else if (cur > *prev) { - DHD_EVENT(("%s lost %d packets\n", __FUNCTION__, cur - *prev)); + DHD_INFO(("%s lost %d packets\n", __FUNCTION__, cur - *prev)); } else { DHD_EVENT(("%s seq out of order, dhd %d, dongle %d\n", __FUNCTION__, *prev, cur)); diff --git a/dhd_linux.c b/dhd_linux.c index b5fd2c6..1b27e8e 100644 --- a/dhd_linux.c +++ b/dhd_linux.c @@ -2272,12 +2272,7 @@ int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx) int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost) { uint chipid = dhd_bus_chip_id(dhdp); - int ret = BCME_OK; if (prepost) { /* pre process */ - ret = dhd_alloc_cis(dhdp); - if (ret != BCME_OK) { - return ret; - } switch (chipid) { #ifndef DHD_READ_CIS_FROM_BP case BCM4389_CHIP_GRPID: @@ -2286,7 +2281,11 @@ int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost) break; #endif /* !DHD_READ_CIS_FROM_BP */ default: - dhd_read_cis(dhdp); + /* cis information is filled in + * dhd_parse_board_information much before + * fw download, so no need to read cis from otp + * here again + */ break; } dhd_check_module_cid(dhdp); @@ -2294,7 +2293,6 @@ int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost) dhd_set_macaddr_from_file(dhdp); } else { /* post process */ dhd_write_macaddr(&dhdp->mac); - dhd_clear_cis(dhdp); } return BCME_OK; @@ -9435,6 +9433,11 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd_rx_pktpool_init(dhd); #endif /* RX_PKT_POOL */ + if (dhd_alloc_cis(&dhd->pub) != BCME_OK) { + DHD_ERROR(("%s: alloc CIS buf failed!\n", __FUNCTION__)); + goto fail; + } + #ifdef WL_CFGVENDOR_SEND_HANG_EVENT dhd->pub.hang_info = MALLOCZ(osh, VENDOR_SEND_HANG_EXT_INFO_LEN); if (dhd->pub.hang_info == NULL) { @@ -15016,6 +15019,8 @@ void dhd_detach(dhd_pub_t *dhdp) #ifdef RX_PKT_POOL dhd_rx_pktpool_deinit(dhd); #endif + dhd_clear_cis(dhdp); + /* Free the memory alloc'd for socram */ if (dhd->pub.soc_ram) { #if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) diff --git a/dhd_linux_lb.c b/dhd_linux_lb.c index c237e19..f234c8a 100644 --- a/dhd_linux_lb.c +++ b/dhd_linux_lb.c @@ -225,10 +225,11 @@ void dhd_select_cpu_candidacy(dhd_info_t *dhd) cpumask_clear_cpu(net_tx_cpu, dhd->cpumask_set4_new); cpumask_clear_cpu(net_tx_cpu, dhd->cpumask_set0_new); - if (use_big_core) + if (use_big_core) { set8_available_cpus = cpumask_weight(dhd->cpumask_set8_new); - else + } else { set8_available_cpus = 0; + } set4_available_cpus = cpumask_weight(dhd->cpumask_set4_new); DHD_INFO(("%s select cpu from set4/8\n", __FUNCTION__)); diff --git a/dhd_linux_platdev.c b/dhd_linux_platdev.c index b087e64..41c92d5 100644 --- a/dhd_linux_platdev.c +++ b/dhd_linux_platdev.c @@ -1111,10 +1111,12 @@ void __attribute__ ((weak)) dhd_plat_pcie_skip_config_set(bool val) { return; } + bool __attribute__ ((weak)) dhd_plat_pcie_enable_big_core(void) { return false; } + int __attribute__ ((weak)) dhd_get_platform_naming_for_nvram_clmblob_file(download_type_t component, char *file_name) diff --git a/dhd_msgbuf.c b/dhd_msgbuf.c index db7f0e6..dfb17c5 100644 --- a/dhd_msgbuf.c +++ b/dhd_msgbuf.c @@ -1883,7 +1883,7 @@ BCMFASTPATH(dhd_prot_d2h_sync_edl)(dhd_pub_t *dhd, msgbuf_ring_t *ring, { uint32 tries; int msglen = 0, len = 0; - uint32 ring_seqnum = ring->seqnum % D2H_EPOCH_MODULO; + uint32 ring_seqnum; dhd_prot_t *prot = dhd->prot; uint32 step = 0; uint32 delay = PCIE_D2H_SYNC_DELAY; @@ -1920,6 +1920,7 @@ BCMFASTPATH(dhd_prot_d2h_sync_edl)(dhd_pub_t *dhd, msgbuf_ring_t *ring, * that the complete message has arrived. */ valid_msg = FALSE; + ring_seqnum = ring->seqnum % D2H_EPOCH_MODULO; if (msg->epoch == ring_seqnum && msg->msg_type == MSG_TYPE_INFO_PYLD && msg->request_id > 0 && @@ -1974,19 +1975,19 @@ BCMFASTPATH(dhd_prot_d2h_sync_edl)(dhd_pub_t *dhd, msgbuf_ring_t *ring, } /* for PCIE_D2H_SYNC_NUM_OF_STEPS */ DHD_ERROR(("%s: EDL header check fails !\n", __FUNCTION__)); - DHD_ERROR(("%s: header: seqnum=%u; expected-seqnum=%u" + DHD_ERROR(("%s: header: dongle-seqnum=%u; host-expected-seqnum=%u:%u" " msgtype=0x%x; expected-msgtype=0x%x" " length=%u; expected-max-length=%u", __FUNCTION__, - msg->epoch, ring_seqnum, msg->msg_type, MSG_TYPE_INFO_PYLD, + msg->epoch, ring->seqnum, ring_seqnum, msg->msg_type, MSG_TYPE_INFO_PYLD, msg->request_id, ring->item_len)); dhd_prhex("msg header bytes: ", (volatile uchar *)msg, sizeof(*msg), DHD_ERROR_VAL); if (trailer && msglen > 0 && (msglen + sizeof(cmn_msg_hdr_t)) <= ring->item_len) { - DHD_ERROR(("%s: trailer: seqnum=%u; expected-seqnum=%u" + DHD_ERROR(("%s: trailer: dongle-seqnum=%u; host-expected-seqnum=%u:%u" " msgtype=0x%x; expected-msgtype=0x%x" " length=%u; expected-length=%u", __FUNCTION__, - trailer->epoch, ring_seqnum, trailer->msg_type, MSG_TYPE_INFO_PYLD, - trailer->request_id, msg->request_id)); + trailer->epoch, ring->seqnum, ring_seqnum, trailer->msg_type, + MSG_TYPE_INFO_PYLD, trailer->request_id, msg->request_id)); dhd_prhex("msg trailer bytes: ", (volatile uchar *)trailer, sizeof(*trailer), DHD_ERROR_VAL); } @@ -6059,17 +6060,19 @@ dhd_prot_init_edl_rings(dhd_pub_t *dhd) return ret; } + prot->d2hring_edl->seqnum = D2H_EPOCH_INIT_VAL; + prot->d2hring_edl->current_phase = BCMPCIE_CMNHDR_PHASE_BIT_INIT; + OSL_SMP_WMB(); + DHD_ERROR_MEM(("trying to send create d2h edl ring: idx %d\n", prot->d2hring_edl->idx)); ret = dhd_send_d2h_ringcreate(dhd, prot->d2hring_edl, BCMPCIE_D2H_RING_TYPE_EDL, DHD_D2H_DBGRING_REQ_PKTID); - if (ret != BCME_OK) + if (ret != BCME_OK) { return ret; - - prot->d2hring_edl->seqnum = D2H_EPOCH_INIT_VAL; - prot->d2hring_edl->current_phase = BCMPCIE_CMNHDR_PHASE_BIT_INIT; + } return BCME_OK; -} /* dhd_prot_init_btlog_rings */ +} /* dhd_prot_init_edl_rings */ static void dhd_prot_detach_edl_rings(dhd_pub_t *dhd) @@ -7821,14 +7824,12 @@ dhd_prot_process_edl_complete(dhd_pub_t *dhd, void *evt_decode_data) ring->curr_rd += 1; } - if (err != BCME_OK) { - return 0; - } - - /* process the edl work item, i.e, the event log */ - err = dhd_event_logtrace_process_edl(dhd, msg_addr, evt_decode_data); - if (err == BCME_NOTUP) { - return 0; + if (err == BCME_OK) { + /* process the edl work item, i.e. the event log */ + err = dhd_event_logtrace_process_edl(dhd, msg_addr, evt_decode_data); + if (err == BCME_NOTUP) { + return 0; + } } /* Dummy sleep so that scheduler kicks in after processing any logprints */ @@ -11347,7 +11347,7 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) #if defined(PCIE_OOB) || defined(PCIE_INB_DW) DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - DHD_PRINT(("%s: Before DW_ASSERT inband_dw_state:%d\n", + DHD_RPM(("%s: Before DW_ASSERT inband_dw_state:%d\n", __FUNCTION__, dhdpcie_bus_get_pcie_inband_dw_state(bus))); if (dhdpcie_bus_get_pcie_inband_dw_state(bus) == DW_DEVICE_DS_DISABLED_WAIT) { @@ -11359,7 +11359,7 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); dhd_bus_set_device_wake(bus, TRUE, __FUNCTION__); DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - DHD_PRINT(("%s: After DW_ASSERT inband_dw_state:%d\n", + DHD_RPM(("%s: After DW_ASSERT inband_dw_state:%d\n", __FUNCTION__, dhdpcie_bus_get_pcie_inband_dw_state(bus))); DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); #endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ @@ -11395,10 +11395,10 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) #ifdef PCIE_INB_DW if (INBAND_DW_ENAB(bus)) { DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - DHD_PRINT(("%s: Before D3_INFORM inband_dw_state:%d\n", + DHD_RPM(("%s: Before D3_INFORM inband_dw_state:%d\n", __FUNCTION__, dhdpcie_bus_get_pcie_inband_dw_state(bus))); dhdpcie_send_mb_data(bus, H2D_HOST_D3_INFORM, __FUNCTION__); - DHD_PRINT(("%s: After D3_INFORM inband_dw_state:%d\n", + DHD_RPM(("%s: After D3_INFORM inband_dw_state:%d\n", __FUNCTION__, dhdpcie_bus_get_pcie_inband_dw_state(bus))); DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); } else @@ -14785,7 +14785,7 @@ dhd_bus_ringbell_2(struct dhd_bus *bus, uint32 value, bool devwake) /* makesure we are on PCIE */ /* Skip once bus enters low power state (D3_INFORM/D3_ACK) */ if (__DHD_CHK_BUS_IN_LPS(bus)) { - DHD_PRINT(("%s: trying to ring the doorbell after D3 inform %d\n", + DHD_RPM(("%s: trying to ring the doorbell after D3 inform %d\n", __FUNCTION__, bus->bus_low_power_state)); return; } @@ -14809,7 +14809,7 @@ dhdpcie_bus_ringbell_fast(struct dhd_bus *bus, uint32 value) { /* Skip once bus enters low power state (D3_INFORM/D3_ACK) */ if (__DHD_CHK_BUS_IN_LPS(bus)) { - DHD_PRINT(("%s: trying to ring the doorbell after D3 inform %d\n", + DHD_RPM(("%s: trying to ring the doorbell after D3 inform %d\n", __FUNCTION__, bus->bus_low_power_state)); return; } @@ -14854,7 +14854,7 @@ dhdpcie_bus_ringbell_2_fast(struct dhd_bus *bus, uint32 value, bool devwake) { /* Skip once bus enters low power state (D3_INFORM/D3_ACK) */ if (__DHD_CHK_BUS_IN_LPS(bus)) { - DHD_PRINT(("%s: trying to ring the doorbell after D3 inform %d\n", + DHD_RPM(("%s: trying to ring the doorbell after D3 inform %d\n", __FUNCTION__, bus->bus_low_power_state)); return; } @@ -14890,7 +14890,7 @@ dhd_bus_ringbell_oldpcie(struct dhd_bus *bus, uint32 value) uint32 w; /* Skip once bus enters low power state (D3_INFORM/D3_ACK) */ if (__DHD_CHK_BUS_IN_LPS(bus)) { - DHD_PRINT(("%s: trying to ring the doorbell after D3 inform %d\n", + DHD_RPM(("%s: trying to ring the doorbell after D3 inform %d\n", __FUNCTION__, bus->bus_low_power_state)); return; } @@ -20547,7 +20547,7 @@ dhdpcie_validate_gci_chip_intstatus(dhd_pub_t *dhd) #define OOBR_CAP2_NUMTOPEXTRSRC_MASK 0x1Fu #define OOBR_CAP2_NUMTOPEXTRSRC_SHIFT 4u /* Bits 8:4 */ -static void +static int dhdpcie_dump_oobr(dhd_pub_t *dhd, uint core_bmap, uint coreunit_bmap) { si_t *sih = dhd->bus->sih; @@ -20558,7 +20558,12 @@ dhdpcie_dump_oobr(dhd_pub_t *dhd, uint core_bmap, uint coreunit_bmap) uint val = 0, idx = 0; if (CHIPTYPE(sih->socitype) != SOCI_NCI) { - return; + return BCME_UNSUPPORTED; + } + + if (dhd->bus->is_linkdown) { + DHD_ERROR(("%s: PCIe link is down\n", __FUNCTION__)); + return BCME_NOTUP; } curcore = si_coreid(dhd->bus->sih); @@ -20567,6 +20572,12 @@ dhdpcie_dump_oobr(dhd_pub_t *dhd, uint core_bmap, uint coreunit_bmap) uint corecap2 = R_REG(dhd->osh, ®->capability2); uint numtopextrsrc = (corecap2 >> OOBR_CAP2_NUMTOPEXTRSRC_SHIFT) & OOBR_CAP2_NUMTOPEXTRSRC_MASK; + if (corecap2 == (uint)-1) { + DHD_ERROR(("%s:corecap2=0x%x ! Bad value, set linkdown\n", + __FUNCTION__, corecap2)); + dhd->bus->is_linkdown = TRUE; + return BCME_NOTUP; + } /* * Convert the value (8:4) to a loop count to dump topextrsrcmap. * TopRsrcDestSel0 is accessible if NUM_TOP_EXT_RSRC > 0 @@ -20609,6 +20620,7 @@ dhdpcie_dump_oobr(dhd_pub_t *dhd, uint core_bmap, uint coreunit_bmap) } si_setcore(sih, curcore, 0); + return BCME_OK; } bool @@ -20779,7 +20791,12 @@ dhdpcie_sssr_dump(dhd_pub_t *dhd) } if (core_bmap) { - dhdpcie_dump_oobr(dhd, core_bmap, coreunit_bmap); + ret = dhdpcie_dump_oobr(dhd, core_bmap, coreunit_bmap); + if (ret == BCME_NOTUP) { + DHD_ERROR(("%s: dhdpcie_dump_oobr fails due to linkdown !\n", + __FUNCTION__)); + goto exit; + } } dhd_bus_pcie_pwr_req_wl_domain(dhd->bus, CC_REG_OFF(PowerControl), TRUE); @@ -1163,6 +1163,7 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd) _pno_state = PNO_GET_PNOSTATE(dhd); if (!(_pno_state->pno_mode & DHD_PNO_LEGACY_MODE)) { DHD_ERROR(("%s : LEGACY PNO MODE is not enabled\n", __FUNCTION__)); + err = BCME_UNSUPPORTED; goto exit; } DHD_PNO(("%s enter\n", __FUNCTION__)); diff --git a/include/epivers.h b/include/epivers.h index dc9e37e..1bea059 100644 --- a/include/epivers.h +++ b/include/epivers.h @@ -29,25 +29,25 @@ #define EPI_RC_NUMBER 243 -#define EPI_INCREMENTAL_NUMBER 7 +#define EPI_INCREMENTAL_NUMBER 18 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 103, 10, 243, 7 +#define EPI_VERSION 103, 10, 243, 18 -#define EPI_VERSION_NUM 0x670af307 +#define EPI_VERSION_NUM 0x670af312 #define EPI_VERSION_DEV 103.10.243 /* Driver Version String, ASCII, 32 chars max */ #if defined (WLTEST) -#define EPI_VERSION_STR "103.10.243.7 (wlan=r1028253 WLTEST)" +#define EPI_VERSION_STR "103.10.243.18 (wlan=r1034304 WLTEST)" #elif (defined (BCMDBG_ASSERT) && \ !defined (BCMDBG_ASSERT_DISABLED) && \ !defined (ASSERT_FP_DISABLE)) -#define EPI_VERSION_STR "103.10.243.7 (wlan=r1028253 ASSRT)" +#define EPI_VERSION_STR "103.10.243.18 (wlan=r1034304 ASSRT)" #else -#define EPI_VERSION_STR "103.10.243.7 (wlan=r1028253)" +#define EPI_VERSION_STR "103.10.243.18 (wlan=r1034304)" #endif /* BCMINTERNAL */ #endif /* _epivers_h_ */ diff --git a/wl_android.c b/wl_android.c index 6b5c4db..fcf8c6c 100644 --- a/wl_android.c +++ b/wl_android.c @@ -5358,10 +5358,10 @@ int wl_android_wifi_on(struct net_device *dev) __FUNCTION__, retry)); /* Set big hammer flag */ dhdp->do_chip_bighammer = TRUE; - /* * If failed to power up wifi chip, dhd_open() which invoked this function * will invoke dhd_stop. As part of dhd_stop this clean-up will be handled. + * */ if (retry != 0) { #ifdef BCMPCIE diff --git a/wl_cfg80211.c b/wl_cfg80211.c index c92fbb9..20520c8 100644 --- a/wl_cfg80211.c +++ b/wl_cfg80211.c @@ -432,6 +432,8 @@ static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211 *cfg, struct n struct wl_profile *profile); static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211 *cfg, struct net_device *dev); static int wl_cfg80211_recv_nbr_resp(struct net_device *dev, uint8 *body, uint body_len); +static s32 wl_wbtext_init(struct bcm_cfg80211 *cfg); +static void wl_wbtext_deinit(struct bcm_cfg80211 *cfg); #endif /* WBTEXT */ #ifdef RTT_SUPPORT @@ -7246,18 +7248,17 @@ wl_cfg80211_config_rsnxe_ie(struct bcm_cfg80211 *cfg, struct net_device *dev, WL_ERR(("set wsec_info_sae_pwe failed %d\n", err)); return err; } - } else { - err = wldev_iovar_setbuf(dev, "rsnxe", ie, ie_len, - smbuf, sizeof(smbuf), NULL); - if (!err) { - WL_DBG(("Configured RSNXE IE\n")); - } else if (err == BCME_UNSUPPORTED) { - WL_DBG(("FW does not support rsnxe iovar\n")); - err = BCME_OK; - } else { - WL_ERR(("rsnxe set error (%d)\n", err)); - } + } + err = wldev_iovar_setbuf(dev, "rsnxe", ie, ie_len, + smbuf, sizeof(smbuf), NULL); + if (!err) { + WL_DBG(("Configured RSNXE IE\n")); + } else if (err == BCME_UNSUPPORTED) { + WL_DBG(("FW does not support rsnxe iovar\n")); + err = BCME_OK; + } else { + WL_ERR(("rsnxe set error (%d)\n", err)); } return err; } @@ -12495,7 +12496,7 @@ wl_cfg80211_cleanup_connection(struct net_device *net, bool user_enforced) wl_cfg80211_disassoc(iter->ndev, WLAN_REASON_DEAUTH_LEAVING); } else { WL_INFORM(("Disconnected state. Interface clean " - "up skipped for ifname:%s", iter->ndev->name)); + "up skipped for ifname:%s \n", iter->ndev->name)); } } } @@ -14728,10 +14729,10 @@ wl_handle_link_down(struct bcm_cfg80211 *cfg, wl_assoc_status_t *as) CFG80211_DISCONNECTED(ndev, reason, ie_ptr, ie_len, loc_gen, GFP_KERNEL); - WL_INFORM_MEM(("[%s] Disconnect event sent to upper layer" - "event:%d e->reason=%d reason=%d ie_len=%d loc_gen=%d" + WL_INFORM_MEM(("[%s] Disconnect event sent to upper layer " + "event:%d e->reason=%d loc_reason=%d ie_len=%d loc_gen=%d " "from " MACDBG "\n", - ndev->name, event, ntoh32(as->reason), reason, ie_len, + ndev->name, event, dtoh32(as->reason), reason, ie_len, loc_gen, MAC2STRDBG((const u8*)(&as->addr)))); /* clear connected state */ @@ -16173,7 +16174,7 @@ static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, } bi = (wl_bss_info_v109_t *)(buf + 4); chspec = wl_chspec_driver_to_host(bi->chanspec); - WL_INFORM_MEM(("chanspec:0x%x\n band:%d chan:%d", chspec, CHSPEC_BAND(chspec), + WL_INFORM_MEM(("chanspec:0x%x band:0x%x chan:%d\n", chspec, CHSPEC_BAND(chspec), wf_chspec_ctlchan(wl_chspec_driver_to_host(chspec)))); /* chanspec queried for ASSOCIATED BSSID needs to be valid */ if (!(target_bssid) && !wf_chspec_valid(chspec)) { @@ -18589,6 +18590,13 @@ static s32 wl_init_priv(struct bcm_cfg80211 *cfg) wl_cellavoid_init(cfg); #endif /* WL_CELLULAR_CHAN_AVOID */ +#ifdef WBTEXT + err = wl_wbtext_init(cfg); + if (err) { + return err; + } +#endif /* WBTEXT */ + #ifdef CONFIG_SLEEP_MONITOR sleep_monitor_register_ops(cfg, &wlan_sleep_monitor_ops, SLEEP_MONITOR_WIFI); @@ -18612,6 +18620,11 @@ static void wl_deinit_priv(struct bcm_cfg80211 *cfg) #ifdef WL_CELLULAR_CHAN_AVOID wl_cellavoid_deinit(cfg); #endif /* WL_CELLULAR_CHAN_AVOID */ + +#ifdef WBTEXT + wl_wbtext_deinit(cfg); +#endif /* WBTEXT */ + wl_deinit_priv_mem(cfg); if (wl_cfg80211_netdev_notifier_registered) { wl_cfg80211_netdev_notifier_registered = FALSE; @@ -21322,7 +21335,7 @@ wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, } else { bzero(profile->bssid, ETHER_ADDR_LEN); } - WL_INFORM_MEM(("prof_bssid:"MACDBG"\n", MAC2STRDBG(profile->latest_bssid))); + WL_INFORM_MEM(("prof_bssid: "MACDBG"\n", MAC2STRDBG(profile->latest_bssid))); break; case WL_PROF_SEC: memcpy(&profile->sec, data, sizeof(profile->sec)); @@ -23715,14 +23728,19 @@ wl_get_netdev_by_name(struct bcm_cfg80211 *cfg, char *ifname) static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea) { wl_wbtext_bssid_t *bssid = NULL; + unsigned long flags; + + WL_CFG_WBTEXT_BSSID_LIST_SYNC_LOCK(cfg->wbtext_bssid_list_sync, flags); GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); /* check duplicate */ list_for_each_entry(bssid, &cfg->wbtext_bssid_list, list) { GCC_DIAGNOSTIC_POP(); if (!memcmp(bssid->ea.octet, ea, ETHER_ADDR_LEN)) { + WL_CFG_WBTEXT_BSSID_LIST_SYNC_UNLOCK(cfg->wbtext_bssid_list_sync, flags); return FALSE; } } + WL_CFG_WBTEXT_BSSID_LIST_SYNC_UNLOCK(cfg->wbtext_bssid_list_sync, flags); return TRUE; } @@ -23731,6 +23749,7 @@ static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211 *cfg, struct e { wl_wbtext_bssid_t *bssid = NULL; char eabuf[ETHER_ADDR_STR_LEN]; + unsigned long flags; bssid = (wl_wbtext_bssid_t *)MALLOC(cfg->osh, sizeof(wl_wbtext_bssid_t)); if (bssid == NULL) { @@ -23741,7 +23760,10 @@ static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211 *cfg, struct e memcpy(bssid->ea.octet, ea, ETHER_ADDR_LEN); INIT_LIST_HEAD(&bssid->list); + + WL_CFG_WBTEXT_BSSID_LIST_SYNC_LOCK(cfg->wbtext_bssid_list_sync, flags); list_add_tail(&bssid->list, &cfg->wbtext_bssid_list); + WL_CFG_WBTEXT_BSSID_LIST_SYNC_UNLOCK(cfg->wbtext_bssid_list_sync, flags); WL_DBG(("add wbtext bssid : %s\n", bcm_ether_ntoa(ea, eabuf))); @@ -23752,7 +23774,9 @@ static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211 *cfg) { wl_wbtext_bssid_t *bssid = NULL, *tmp = NULL; char eabuf[ETHER_ADDR_STR_LEN]; + unsigned long flags; + WL_CFG_WBTEXT_BSSID_LIST_SYNC_LOCK(cfg->wbtext_bssid_list_sync, flags); GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); list_for_each_entry_safe(bssid, tmp, &cfg->wbtext_bssid_list, list) { GCC_DIAGNOSTIC_POP(); @@ -23760,6 +23784,7 @@ static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211 *cfg) list_del(&bssid->list); MFREE(cfg->osh, bssid, sizeof(wl_wbtext_bssid_t)); } + WL_CFG_WBTEXT_BSSID_LIST_SYNC_UNLOCK(cfg->wbtext_bssid_list_sync, flags); } static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211 *cfg, struct net_device *dev) @@ -24006,6 +24031,40 @@ wl_cfg80211_recv_nbr_resp(struct net_device *dev, uint8 *body, uint body_len) return BCME_OK; } + +static s32 +wl_wbtext_init(struct bcm_cfg80211 *cfg) +{ + if (!cfg) { + WL_ERR(("cfg is NULL\n")); + return BCME_ERROR; + } + + /* Allocate spinlock for protecting wbtext_bssid_list */ + cfg->wbtext_bssid_list_sync = (void *)WL_CFG_WBTEXT_BSSID_LIST_SYNC_INIT(cfg->osh); + + if (!cfg->wbtext_bssid_list_sync) { + WL_ERR(("Failed to alloc spinlock\n")); + return BCME_ERROR; + } + return BCME_OK; +} + +static void +wl_wbtext_deinit(struct bcm_cfg80211 *cfg) +{ + if (!cfg) { + WL_ERR(("cfg is NULL\n")); + return; + } + + /* If there are still entries in the list, clean them up */ + wl_cfg80211_wbtext_clear_bssid_list(cfg); + + /* Free spinlock allocated in attach */ + WL_CFG_WBTEXT_BSSID_LIST_SYNC_DEINIT(cfg->osh, cfg->wbtext_bssid_list_sync); + cfg->wbtext_bssid_list_sync = NULL; +} #endif /* WBTEXT */ #ifdef SUPPORT_SET_CAC diff --git a/wl_cfg80211.h b/wl_cfg80211.h index af2b471..f8ea094 100644 --- a/wl_cfg80211.h +++ b/wl_cfg80211.h @@ -66,6 +66,11 @@ #define WL_CFG_VNDR_OUI_SYNC_LOCK(lock, flags) (flags) = osl_spin_lock(lock) #define WL_CFG_VNDR_OUI_SYNC_UNLOCK(lock, flags) osl_spin_unlock((lock), (flags)) +#define WL_CFG_WBTEXT_BSSID_LIST_SYNC_INIT(osh) osl_spin_lock_init(osh) +#define WL_CFG_WBTEXT_BSSID_LIST_SYNC_DEINIT(osh, lock) osl_spin_lock_deinit(osh, lock) +#define WL_CFG_WBTEXT_BSSID_LIST_SYNC_LOCK(lock, flags) (flags) = osl_spin_lock(lock) +#define WL_CFG_WBTEXT_BSSID_LIST_SYNC_UNLOCK(lock, flags) osl_spin_unlock((lock), (flags)) + #include <wifi_stats.h> #include <wl_cfgp2p.h> #ifdef WL_NAN @@ -2285,6 +2290,7 @@ struct bcm_cfg80211 { uint8 vif_count; /* Virtual Interface count */ #ifdef WBTEXT struct list_head wbtext_bssid_list; + void *wbtext_bssid_list_sync; #endif /* WBTEXT */ #ifdef SUPPORT_AP_RADIO_PWRSAVE ap_rps_info_t ap_rps_info; diff --git a/wl_cfg_cellavoid.c b/wl_cfg_cellavoid.c index c162fe5..445eaee 100644 --- a/wl_cfg_cellavoid.c +++ b/wl_cfg_cellavoid.c @@ -1577,8 +1577,6 @@ wl_cellavoid_validate_param(struct bcm_cfg80211 *cfg, wl_cellavoid_param_t *para WL_ERR(("Not supported band %d, channel %d, pwrcap %d\n", param->chan_param[i].band, param->chan_param[i].center_channel, param->chan_param[i].pwr_cap)); - ret = -EINVAL; - goto exit; } param->chan_param[i].chspec_bw = bw; diff --git a/wl_cfgscan.c b/wl_cfgscan.c index 99bdefe..6b32834 100644 --- a/wl_cfgscan.c +++ b/wl_cfgscan.c @@ -2840,9 +2840,9 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, #if defined(WL_CFG80211_P2P_DEV_IF) struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg); #endif /* WL_CFG80211_P2P_DEV_IF */ -#ifdef WL_CFGVENDOR_SEND_ALERT_EVENT +#if defined(WL_CFGVENDOR_SEND_ALERT_EVENT) && defined(WL_SCAN_ERR_ALERT) dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); -#endif /* WL_CFGVENDOR_SEND_ALERT_EVENT */ +#endif /* WL_CFGVENDOR_SEND_ALERT_EVENT && WL_SCAN_ERR_ALERT */ WL_DBG(("Enter\n")); RETURN_EIO_IF_NOT_UP(cfg); @@ -2865,14 +2865,14 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); if (unlikely(err)) { WL_ERR(("scan error (%d)\n", err)); -#ifdef WL_CFGVENDOR_SEND_ALERT_EVENT +#if defined(WL_CFGVENDOR_SEND_ALERT_EVENT) && defined(WL_SCAN_ERR_ALERT) if (err == -EBUSY) { dhdp->alert_reason = ALERT_SCAN_BUSY; } else { dhdp->alert_reason = ALERT_SCAN_ERR; } dhd_os_send_alert_message(dhdp); -#endif /* WL_CFGVENDOR_SEND_ALERT_EVENT */ +#endif /* WL_CFGVENDOR_SEND_ALERT_EVENT && WL_SCAN_ERR_ALERT */ } #ifdef WL_DRV_AVOID_SCANCACHE /* Reset roam cache after successful scan request */ @@ -3863,7 +3863,7 @@ int wl_cfg80211_scan_mac_config(struct net_device *dev, uint8 *rand_mac, uint8 * /* Disable scan mac for clean-up */ return err; } - WL_INFORM_MEM(("scanmac configured")); + WL_INFORM_MEM(("scanmac configured\n")); cfg->scanmac_config = true; return err; @@ -6125,6 +6125,18 @@ wl_cfgscan_get_band_freq_list(struct bcm_cfg80211 *cfg, struct wireless_dev *wde #define SEC_FREQ_HT40_OFFSET 20 static acs_delay_work_t delay_work_acs = { .init_flag = 0 }; +static bool wl_is_chan_info_restricted(u32 chan_info_bitmap, chanspec_t chspec) +{ + if (chan_info_bitmap & (WL_CHAN_RADAR | WL_CHAN_PASSIVE | WL_CHAN_RESTRICTED | + WL_CHAN_CLM_RESTRICTED | WL_CHAN_P2P_PROHIBITED | WL_CHAN_INDOOR_ONLY)) { + WL_DBG_MEM(("Restricted chan_info:0x%x for chspec:0x%x\n", chan_info_bitmap, + chspec)); + return TRUE; + } + + return FALSE; +} + static int wl_cfgscan_acs_parse_result(acs_selected_channels_t *pResult, chanspec_t ch_chosen, drv_acs_params_t *pParameter) { @@ -6393,9 +6405,11 @@ static int wl_cfgscan_acs_parse_parameter(struct bcm_cfg80211 *cfg, chspec = wf_create_chspec_from_primary(channel, WL_CHANSPEC_BW_80, chspec_band, 0); #ifdef WL_CELLULAR_CHAN_AVOID + wl_cellavoid_sync_lock(cfg); if (!wl_cellavoid_is_safe_overlap(cfg->cellavoid_info, chspec)) { chspec = INVCHANSPEC; } + wl_cellavoid_sync_unlock(cfg); #endif /* WL_CELLULAR_CHAN_AVOID */ if (chspec != INVCHANSPEC) { WL_INFORM_MEM(("set %d/80 (0x%x)\n", channel, chspec)); @@ -6412,9 +6426,11 @@ static int wl_cfgscan_acs_parse_parameter(struct bcm_cfg80211 *cfg, chspec = wf_create_chspec_from_primary(channel, WL_CHANSPEC_BW_40, chspec_band, 0); #ifdef WL_CELLULAR_CHAN_AVOID + wl_cellavoid_sync_lock(cfg); if (!wl_cellavoid_is_safe_overlap(cfg->cellavoid_info, chspec)) { chspec = INVCHANSPEC; } + wl_cellavoid_sync_unlock(cfg); #endif /* WL_CELLULAR_CHAN_AVOID */ if (chspec != INVCHANSPEC) { WL_INFORM_MEM(("set %d/40 (0x%x)\n", channel, chspec)); @@ -6431,9 +6447,11 @@ static int wl_cfgscan_acs_parse_parameter(struct bcm_cfg80211 *cfg, chspec = wf_create_chspec_from_primary(channel, WL_CHANSPEC_BW_20, chspec_band, 0); #ifdef WL_CELLULAR_CHAN_AVOID + wl_cellavoid_sync_lock(cfg); if (!wl_cellavoid_is_safe_overlap(cfg->cellavoid_info, chspec)) { chspec = INVCHANSPEC; } + wl_cellavoid_sync_unlock(cfg); #endif /* WL_CELLULAR_CHAN_AVOID */ if (chspec != INVCHANSPEC) { WL_INFORM_MEM(("set %d/20 (0x%x)\n", channel, chspec)); @@ -6702,6 +6720,7 @@ wl_convert_freqlist_to_chspeclist(struct bcm_cfg80211 *cfg, u32 *chspeclist = NULL; u32 *p_chspec_list = NULL; char chanspec_str[CHANSPEC_STR_LEN]; + u32 chan_info; #ifdef WL_CELLULAR_CHAN_AVOID int safe_chspec_cnt = 0; u32 *safe_chspeclist = NULL; @@ -6735,27 +6754,48 @@ wl_convert_freqlist_to_chspeclist(struct bcm_cfg80211 *cfg, for (i = 0, j = 0; i < freq_list_len; i++) { chspeclist[j] = wl_freq_to_chanspec(pElem_freq[i]); - if (CHSPEC_IS6G(chspeclist[j]) && !CHSPEC_IS_6G_PSC(chspeclist[j])) { - /* Skip non PSC channels */ - WL_DBG(("Skipping 6G non PSC channel\n")); - continue; + if (CHSPEC_IS6G(chspeclist[j])) { + if ((wl_cfgscan_get_chan_info(cfg, + &chan_info, chspeclist[j]) == BCME_OK) && + (!(chan_info & WL_CHAN_BAND_6G_PSC) || + !(chan_info & WL_CHAN_BAND_6G_VLP))) { + /* Skip non PSC channels */ + WL_DBG(("Skipping 6G non-PSC/non-VLP chanspec 0x%x\n", + chspeclist[j])); + continue; + } } #ifdef WL_UNII4_CHAN /* Skip UNII-4 frequencies */ - if (CHSPEC_IS5G(chspeclist[j]) && - IS_UNII4_CHANNEL(wf_chspec_center_channel(chspeclist[j]))) { - WL_DBG(("Skipped UNII-4 chanspec 0x%x\n", chspeclist[j])); - continue; + if (CHSPEC_IS5G(chspeclist[j])) { + if (IS_UNII4_CHANNEL(wf_chspec_center_channel(chspeclist[j])) || + ((wl_cfgscan_get_chan_info(cfg, + &chan_info, chspeclist[j]) == BCME_OK) && + wl_is_chan_info_restricted(chan_info, chspeclist[j]))) { + WL_DBG_MEM(("Skipped UNII-4/restricted chanspec 0x%x\n", + chspeclist[j])); + continue; + } } #endif /* WL_UNII4_CHAN */ + if (CHSPEC_IS2G(chspeclist[j])) { + if ((wl_cfgscan_get_chan_info(cfg, + &chan_info, chspeclist[j]) == BCME_OK) && + wl_is_chan_info_restricted(chan_info, chspeclist[j])) { + WL_DBG_MEM(("Skipped restricted chanspec 0x%x\n", + chspeclist[j])); + continue; + } + } + #ifdef WL_CELLULAR_CHAN_AVOID if (wl_cellavoid_is_safe(cfg->cellavoid_info, chspeclist[j])) { safe_chspeclist[safe_chspec_cnt++] = chspeclist[j]; safe_param.freq_bands |= CHSPEC_TO_WLC_BAND(CHSPEC_BAND(chspeclist[j])); wf_chspec_ntoa(chspeclist[j], chanspec_str); - WL_INFORM_MEM(("Adding %s (0x%x) to the safe list\n", + WL_DBG_MEM(("Adding %s (0x%x) to the safe list\n", chanspec_str, chspeclist[j])); } #endif /* WL_CELLULAR_CHAN_AVOID */ @@ -7240,8 +7280,10 @@ wl_acs_check_scc(struct bcm_cfg80211 *cfg, drv_acs_params_t *parameter, if (scc == FALSE && CHSPEC_IS2G(sta_chanspec)) { #ifdef WL_CELLULAR_CHAN_AVOID if (!wl_is_chanspec_restricted(cfg, sta_chanspec)) { + wl_cellavoid_sync_lock(cfg); scc = wl_cellavoid_operation_allowed(cfg->cellavoid_info, sta_chanspec, NL80211_IFTYPE_AP); + wl_cellavoid_sync_unlock(cfg); if (scc == FALSE) { WL_INFORM_MEM(("Not allow unsafe channel and" " mandatory chspec:0x%x\n", sta_chanspec)); |