summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Jeon <dennis.jeon@broadcom.corp-partner.google.com>2023-08-31 09:06:28 -0400
committerkensun <kensun@google.com>2023-09-05 12:06:56 +0000
commit97a64ddb9c18696ce5f9f5af9438db6d0a89ab04 (patch)
tree47216415d64ecd5f41b7f48c06789d29cc33489f
parent395ec6912866550c43e22aee9aff60b6f6fe5e92 (diff)
downloadbcm4398-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--Kbuild2
-rw-r--r--dhd_custom_cis.c253
-rw-r--r--dhd_custom_google.c23
-rw-r--r--dhd_debug.c2
-rw-r--r--dhd_linux.c19
-rw-r--r--dhd_linux_lb.c5
-rw-r--r--dhd_linux_platdev.c2
-rw-r--r--dhd_msgbuf.c39
-rw-r--r--dhd_pcie.c39
-rw-r--r--dhd_pno.c1
-rw-r--r--include/epivers.h12
-rw-r--r--wl_android.c2
-rw-r--r--wl_cfg80211.c93
-rw-r--r--wl_cfg80211.h6
-rw-r--r--wl_cfg_cellavoid.c2
-rw-r--r--wl_cfgscan.c70
16 files changed, 325 insertions, 245 deletions
diff --git a/Kbuild b/Kbuild
index 1c32cc2..c751fda 100644
--- a/Kbuild
+++ b/Kbuild
@@ -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 */
diff --git a/dhd_pcie.c b/dhd_pcie.c
index 44474ce..99fc548 100644
--- a/dhd_pcie.c
+++ b/dhd_pcie.c
@@ -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, &reg->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);
diff --git a/dhd_pno.c b/dhd_pno.c
index 0ce0a42..7c09d06 100644
--- a/dhd_pno.c
+++ b/dhd_pno.c
@@ -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));