From 47fa5ad572febc2cc89c86e6b2264d57842fa906 Mon Sep 17 00:00:00 2001 From: Rongjun Chen Date: Fri, 4 Jan 2019 10:00:48 +0800 Subject: [PATCH] WIFI: fix ap62x8 cts test fail issue [1/5] PD#SWPL-3773 Problem: CtsNetTestCases Module 3 Fails Solution: update driver to fix cts test fail issue Verify: r311 Change-Id: Ibea9da241061f1ce2771ba2c39f78952bd201976 Signed-off-by: Rongjun Chen --- bcmdhd.1.579.77.41.1.cn/dhd_config.c | 2 +- bcmdhd.1.579.77.41.1.cn/dhd_sdio.c | 7 +- bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c | 7 +- bcmdhd.1.579.77.41.1.cn/wl_cfgvendor.c | 1 + bcmdhd.100.10.315.x/Makefile | 2 +- bcmdhd.100.10.315.x/bcmsdh_sdmmc.c | 4 +- bcmdhd.100.10.315.x/dhd_config.c | 209 +++++++++++---- bcmdhd.100.10.315.x/dhd_config.h | 17 +- bcmdhd.100.10.315.x/dhd_linux.c | 63 +++-- bcmdhd.100.10.315.x/dhd_msgbuf.c | 1 + bcmdhd.100.10.315.x/dhd_pcie_linux.c | 6 +- bcmdhd.100.10.315.x/dhd_sdio.c | 12 + bcmdhd.100.10.315.x/dhd_static_buf.c | 8 +- bcmdhd.100.10.315.x/include/epivers.h | 2 +- bcmdhd.100.10.315.x/linux_osl.c | 48 +++- bcmdhd.100.10.315.x/linux_osl_priv.h | 1 + bcmdhd.100.10.315.x/wl_android.c | 2 +- bcmdhd.100.10.315.x/wl_android.h | 22 ++ bcmdhd.100.10.315.x/wl_android_ext.c | 356 ++++++++++++++++++------- bcmdhd.100.10.315.x/wl_cfg80211.c | 82 +++++- bcmdhd.100.10.315.x/wl_escan.c | 51 +++- bcmdhd.100.10.315.x/wl_escan.h | 5 +- bcmdhd.100.10.315.x/wl_iw.c | 99 +++++-- bcmdhd.100.10.315.x/wl_iw.h | 1 + bcmdhd.100.10.315.x/wldev_common.c | 4 +- 25 files changed, 786 insertions(+), 226 deletions(-) diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_config.c b/bcmdhd.1.579.77.41.1.cn/dhd_config.c index 27d0e9d..8aa7a9a 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_config.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_config.c @@ -2740,7 +2740,7 @@ 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 = -1; + conf->txctl_tmo_fix = 300; conf->txglom_mode = SDPCM_TXGLOM_CPY; conf->deferred_tx_len = 0; conf->dhd_txminmax = 1; diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c b/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c index fb6150f..53e9eaf 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c @@ -6610,7 +6610,7 @@ dhdsdio_dpc(dhd_bus_t *bus) goto clkwait; /* Pending interrupt indicates new device status */ - if (bus->ipend || (bus->ctrl_frame_stat && bus->dhd->conf->txctl_tmo_fix)) { + if (bus->ipend) { bus->ipend = FALSE; #if defined(BT_OVER_SDIO) bcmsdh_btsdio_process_f3_intr(); @@ -7552,6 +7552,11 @@ dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen) if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0) goto done; + if (!DATAOK(bus)) { + rv = BCME_NOTREADY; + goto done; + } + /* Bump dongle by sending an empty packet on the event channel. * sdpcm_sendup (RX) checks for virtual console input. */ diff --git a/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c b/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c index 777ac49..34cedee 100644 --- a/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c +++ b/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c @@ -2948,10 +2948,13 @@ wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev, } exit: if (unlikely(err)) { + int suppressed = 0; + wldev_ioctl(dev, WLC_GET_SCANSUPPRESS, &suppressed, sizeof(int), false); /* Don't print Error incase of Scan suppress */ - if ((err == BCME_EPERM) && cfg->scan_suppressed) + if ((err == BCME_EPERM) && (cfg->scan_suppressed || suppressed)) { + cnt = 0; WL_DBG(("Escan failed: Scan Suppressed \n")); - else { + } else { cnt++; WL_ERR(("error (%d), cnt=%d\n", err, cnt)); // terence 20140111: send disassoc to firmware diff --git a/bcmdhd.1.579.77.41.1.cn/wl_cfgvendor.c b/bcmdhd.1.579.77.41.1.cn/wl_cfgvendor.c index c5b4b2b..d0fd9f9 100644 --- a/bcmdhd.1.579.77.41.1.cn/wl_cfgvendor.c +++ b/bcmdhd.1.579.77.41.1.cn/wl_cfgvendor.c @@ -2513,6 +2513,7 @@ wl_cfgvendor_dbg_trigger_mem_dump(struct wiphy *wiphy, if (ret) { WL_ERR(("Vendor Command reply failed ret:%d \n", ret)); } + printk("wl_cfgvendor_dbg_trigger_mem_dump ===================ret : %d\n", ret); exit: return ret; diff --git a/bcmdhd.100.10.315.x/Makefile b/bcmdhd.100.10.315.x/Makefile index 3c964b1..9884970 100644 --- a/bcmdhd.100.10.315.x/Makefile +++ b/bcmdhd.100.10.315.x/Makefile @@ -101,7 +101,7 @@ ifeq ($(CONFIG_VTS_SUPPORT),y) ifneq ($(CONFIG_CFG80211),) DHDCFLAGS += -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG \ -DLINKSTAT_SUPPORT -DDEBUGABILITY -DDBG_PKT_MON -DPKT_FILTER_SUPPORT \ - -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHD_WAKE_STATUS \ + -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHD_WAKE_STATUS \ -DCUSTOM_COUNTRY_CODE -DDHD_FW_COREDUMP -DEXPLICIT_DISCIF_CLEANUP DHDOFILES += dhd_rtt.o bcm_app_utils.o diff --git a/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c b/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c index 04111dc..338ec0e 100644 --- a/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c +++ b/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c @@ -1244,10 +1244,10 @@ sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func goto txglomfail; } } - + bcopy(buf, (localbuf + local_plen), pkt_len); local_plen += pkt_len; - if (PKTNEXT(sd->osh, pnext)) + if (PKTNEXT(sd->osh, pnext)) continue; buf = localbuf; diff --git a/bcmdhd.100.10.315.x/dhd_config.c b/bcmdhd.100.10.315.x/dhd_config.c index eedac09..fed007f 100644 --- a/bcmdhd.100.10.315.x/dhd_config.c +++ b/bcmdhd.100.10.315.x/dhd_config.c @@ -46,6 +46,15 @@ uint config_msg_level = CONFIG_ERROR_LEVEL; #define htodchanspec(i) i #define dtohchanspec(i) i +#define MAX_EVENT_BUF_NUM 16 +typedef struct eventmsg_buf { + u16 num; + struct { + u16 type; + bool set; + } event [MAX_EVENT_BUF_NUM]; +} eventmsg_buf_t; + typedef struct cihp_name_map_t { uint chip; uint chiprev; @@ -792,7 +801,8 @@ dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec) memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t)); printf("%s: set country %s, revision %d\n", __FUNCTION__, cspec->ccode, cspec->rev); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "country", (char *)cspec, sizeof(wl_country_t), FALSE); + bcmerror = dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "country", (char *)cspec, + sizeof(wl_country_t), FALSE); dhd_conf_get_country(dhd, cspec); printf("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev); @@ -887,6 +897,85 @@ dhd_conf_set_roam(dhd_pub_t *dhd) return bcmerror; } +void +dhd_conf_add_to_eventbuffer(struct eventmsg_buf *ev, u16 event, bool set) +{ + if (!ev || (event > WLC_E_LAST)) + return; + + if (ev->num < MAX_EVENT_BUF_NUM) { + ev->event[ev->num].type = event; + ev->event[ev->num].set = set; + ev->num++; + } else { + CONFIG_ERROR(("evenbuffer doesn't support > %u events. Update" + " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM)); + ASSERT(0); + } +} + +s32 +dhd_conf_apply_eventbuffer(dhd_pub_t *dhd, eventmsg_buf_t *ev) +{ + char eventmask[WL_EVENTING_MASK_LEN]; + int i, ret = 0; + + if (!ev || (!ev->num)) + return -EINVAL; + + /* Read event_msgs mask */ + ret = dhd_conf_get_iovar(dhd, WLC_GET_VAR, "event_msgs", eventmask, sizeof(eventmask), 0); + if (unlikely(ret)) { + CONFIG_ERROR(("Get event_msgs error (%d)\n", ret)); + goto exit; + } + + /* apply the set bits */ + for (i = 0; i < ev->num; i++) { + if (ev->event[i].set) + setbit(eventmask, ev->event[i].type); + else + clrbit(eventmask, ev->event[i].type); + } + + /* Write updated Event mask */ + ret = dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "event_msgs", eventmask, + sizeof(eventmask), FALSE); + if (unlikely(ret)) { + CONFIG_ERROR(("Set event_msgs error (%d)\n", ret)); + } + +exit: + return ret; +} + +int +dhd_conf_enable_roam_offload(dhd_pub_t *dhd, int enable) +{ + int err; + eventmsg_buf_t ev_buf; + + if (dhd->conf->roam_off_suspend) + return 0; + + err = dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_offload", enable, 0, FALSE); + if (err) + return err; + + bzero(&ev_buf, sizeof(eventmsg_buf_t)); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable); + err = dhd_conf_apply_eventbuffer(dhd, &ev_buf); + + CONFIG_TRACE(("%s: roam_offload %d\n", __FUNCTION__, enable)); + + return err; +} + void dhd_conf_set_bw_cap(dhd_pub_t *dhd) { @@ -1160,59 +1249,87 @@ dhd_conf_get_pm(dhd_pub_t *dhd) return -1; } -#define AP_IN_SUSPEND 1 -#define AP_DOWN_IN_SUSPEND 2 -int -dhd_conf_get_ap_mode_in_suspend(dhd_pub_t *dhd) +uint +dhd_conf_get_insuspend(dhd_pub_t *dhd) { - int mode = 0; + uint mode = 0; - /* returned ap_in_suspend value: - * 0: nothing - * 1: ap enabled in suspend - * 2: ap enabled, but down in suspend - */ - if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { - mode = dhd->conf->ap_in_suspend; + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + mode = dhd->conf->insuspend & + (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | ROAM_OFFLOAD_IN_SUSPEND); + } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + mode = dhd->conf->insuspend & + (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | AP_DOWN_IN_SUSPEND); } return mode; } int -dhd_conf_set_ap_in_suspend(dhd_pub_t *dhd, int suspend) +dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend) { - int mode = 0; - uint wl_down = 1; + uint mode = 0, wl_down = 1; + struct dhd_conf *conf = dhd->conf; - mode = dhd_conf_get_ap_mode_in_suspend(dhd); + mode = dhd_conf_get_insuspend(dhd); if (mode) - printf("%s: suspend %d, mode %d\n", __FUNCTION__, suspend, mode); + printf("%s: op_mode %d, suspend %d, mode 0x%x\n", __FUNCTION__, + dhd->op_mode, suspend, mode); + if (suspend) { - if (mode == AP_IN_SUSPEND) { + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + if (mode & ROAM_OFFLOAD_IN_SUSPEND) + dhd_conf_enable_roam_offload(dhd, 1); + } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + if (mode & AP_DOWN_IN_SUSPEND) { + dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_down, + sizeof(wl_down), TRUE, 0); + } + } #ifdef SUSPEND_EVENT - if (dhd->conf->suspend_eventmask_enable) { - char *eventmask = dhd->conf->suspend_eventmask; - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "event_msgs", eventmask, sizeof(eventmask), TRUE); + if (mode & NO_EVENT_IN_SUSPEND) { + char suspend_eventmask[WL_EVENTING_MASK_LEN]; + if (!conf->suspended) { + dhd_conf_get_iovar(dhd, WLC_GET_VAR, "event_msgs", + conf->resume_eventmask, sizeof(conf->resume_eventmask), 0); } + memset(suspend_eventmask, 0, sizeof(suspend_eventmask)); + dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "event_msgs", + suspend_eventmask, sizeof(suspend_eventmask), FALSE); + } #endif - } else if (mode == AP_DOWN_IN_SUSPEND) - dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_down, sizeof(wl_down), TRUE, 0); + conf->suspended = TRUE; } else { - if (mode == AP_IN_SUSPEND) { #ifdef SUSPEND_EVENT - if (dhd->conf->suspend_eventmask_enable) { - char *eventmask = dhd->conf->resume_eventmask; - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "event_msgs", eventmask, sizeof(eventmask), TRUE); + if (mode & NO_EVENT_IN_SUSPEND) { + dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "event_msgs", + conf->resume_eventmask, sizeof(conf->resume_eventmask), FALSE); + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + struct ether_addr bssid; + int ret = 0; + ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, + sizeof(struct ether_addr), FALSE, 0); + if (ret != BCME_NOTASSOCIATED && !memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) { + CONFIG_TRACE(("%s: send disassoc\n", __FUNCTION__)); + dhd_conf_set_intiovar(dhd, WLC_DISASSOC, "WLC_DISASSOC", 0, 0, FALSE); + } } + } #endif - } else if (mode == AP_DOWN_IN_SUSPEND) { - wl_down = 0; - dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&wl_down, sizeof(wl_down), TRUE, 0); + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + if (mode & ROAM_OFFLOAD_IN_SUSPEND) + dhd_conf_enable_roam_offload(dhd, 0); + } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + if (mode & AP_DOWN_IN_SUSPEND) { + wl_down = 0; + dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&wl_down, + sizeof(wl_down), TRUE, 0); + } } + conf->suspended = FALSE; } - return mode; + return 0; } #ifdef PROP_TXSTATUS @@ -2099,24 +2216,15 @@ dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param) } else if (!strncmp("xmit_in_suspend=", full_param, len_param)) { if (!strncmp(data, "1", 1)) - conf->xmit_in_suspend = TRUE; + conf->insuspend &= ~NO_TXDATA_IN_SUSPEND; else - conf->xmit_in_suspend = FALSE; - printf("%s: xmit_in_suspend = %d\n", __FUNCTION__, conf->xmit_in_suspend); - } - else if (!strncmp("ap_in_suspend=", full_param, len_param)) { - conf->ap_in_suspend = (int)simple_strtol(data, NULL, 10); - printf("%s: ap_in_suspend = %d\n", __FUNCTION__, conf->ap_in_suspend); + conf->insuspend |= NO_TXDATA_IN_SUSPEND; + printf("%s: insuspend = 0x%x\n", __FUNCTION__, conf->insuspend); } -#ifdef SUSPEND_EVENT - else if (!strncmp("suspend_eventmask_enable=", full_param, len_param)) { - if (!strncmp(data, "1", 1)) - conf->suspend_eventmask_enable = TRUE; - else - conf->suspend_eventmask_enable = FALSE; - printf("%s: suspend_eventmask_enable = %d\n", __FUNCTION__, conf->suspend_eventmask_enable); + else if (!strncmp("insuspend=", full_param, len_param)) { + conf->insuspend = (int)simple_strtol(data, NULL, 0); + printf("%s: insuspend = 0x%x\n", __FUNCTION__, conf->insuspend); } -#endif else return false; @@ -2582,7 +2690,7 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) 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); 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_SRL, "WLC_SET_SRL", conf->srl, 0, FALSE); dhd_conf_set_intiovar(dhd, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE); dhd_conf_set_bw_cap(dhd); dhd_conf_set_roam(dhd); @@ -2728,11 +2836,8 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->pm = -1; conf->pm_in_suspend = -1; conf->suspend_bcn_li_dtim = -1; - conf->xmit_in_suspend = TRUE; - conf->ap_in_suspend = 0; + conf->insuspend = 0; #ifdef SUSPEND_EVENT - conf->suspend_eventmask_enable = FALSE; - memset(&conf->suspend_eventmask, 0, sizeof(conf->suspend_eventmask)); memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask)); #endif #ifdef IDHCP diff --git a/bcmdhd.100.10.315.x/dhd_config.h b/bcmdhd.100.10.315.x/dhd_config.h index d7ad3c8..1830c5f 100644 --- a/bcmdhd.100.10.315.x/dhd_config.h +++ b/bcmdhd.100.10.315.x/dhd_config.h @@ -109,6 +109,13 @@ enum in4way_flags { WAIT_DISCONNECTED = (1 << (3)), }; +enum in_suspend_flags { + NO_EVENT_IN_SUSPEND = (1 << (0)), + NO_TXDATA_IN_SUSPEND = (1 << (1)), + AP_DOWN_IN_SUSPEND = (1 << (2)), + ROAM_OFFLOAD_IN_SUSPEND = (1 << (3)), +}; + enum eapol_status { EAPOL_STATUS_NONE = 0, EAPOL_STATUS_WPS_REQID, @@ -204,11 +211,9 @@ typedef struct dhd_conf { uint8 tcpack_sup_mode; #endif int pktprio8021x; - int xmit_in_suspend; - int ap_in_suspend; + uint insuspend; + bool suspended; #ifdef SUSPEND_EVENT - bool suspend_eventmask_enable; - char suspend_eventmask[WL_EVENTING_MASK_LEN]; char resume_eventmask[WL_EVENTING_MASK_LEN]; #endif #ifdef IDHCP @@ -273,8 +278,8 @@ int dhd_conf_get_pm(dhd_pub_t *dhd); #ifdef PROP_TXSTATUS int dhd_conf_get_disable_proptx(dhd_pub_t *dhd); #endif -int dhd_conf_get_ap_mode_in_suspend(dhd_pub_t *dhd); -int dhd_conf_set_ap_in_suspend(dhd_pub_t *dhd, int suspend); +uint dhd_conf_get_insuspend(dhd_pub_t *dhd); +int dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend); void dhd_conf_postinit_ioctls(dhd_pub_t *dhd); int dhd_conf_preinit(dhd_pub_t *dhd); int dhd_conf_reset(dhd_pub_t *dhd); diff --git a/bcmdhd.100.10.315.x/dhd_linux.c b/bcmdhd.100.10.315.x/dhd_linux.c index e8914db..18a3684 100644 --- a/bcmdhd.100.10.315.x/dhd_linux.c +++ b/bcmdhd.100.10.315.x/dhd_linux.c @@ -3587,7 +3587,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) if (dhd->conf->pm_in_suspend >= 0) power_mode = dhd->conf->pm_in_suspend; dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode), TRUE, 0); + sizeof(power_mode), TRUE, 0); #ifdef PKT_FILTER_SUPPORT /* Enable packet filter, @@ -3768,9 +3768,9 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) } #endif /* CUSTOM_EVENT_PM_WAKE */ #endif /* DHD_USE_EARLYSUSPEND */ - dhd_conf_set_ap_in_suspend(dhd, value); + dhd_conf_set_suspend_resume(dhd, value); } else { - dhd_conf_set_ap_in_suspend(dhd, value); + dhd_conf_set_suspend_resume(dhd, value); #ifdef PKT_FILTER_SUPPORT dhd->early_suspended = 0; #endif // endif @@ -3784,11 +3784,8 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) DHD_ERROR(("failed to set intr_width (%d)\n", ret)); } #endif /* DYNAMIC_SWOOB_DURATION */ -#ifndef SUPPORT_PM2_ONLY - power_mode = PM_FAST; dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode), TRUE, 0); -#endif /* SUPPORT_PM2_ONLY */ + sizeof(power_mode), TRUE, 0); #if defined(WL_CFG80211) && defined(WL_BCNRECV) ret = wl_android_bcnrecv_resume(dhd_linux_get_primary_netdev(dhd)); if (ret != BCME_OK) { @@ -3929,7 +3926,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #endif /* DHD_LB_IRQSET */ /* terence 2017029: Reject in early suspend */ - if (!dhd->conf->xmit_in_suspend) { + if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) { dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); } } @@ -3950,7 +3947,7 @@ static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force) /* Set flag when early suspend was called */ dhdp->in_suspend = val; if ((force || !dhdp->suspend_disable_flag) && - (dhd_support_sta_mode(dhdp) || dhd_conf_get_ap_mode_in_suspend(dhdp))) + (dhd_support_sta_mode(dhdp) || dhd_conf_get_insuspend(dhdp))) { ret = dhd_set_suspend(val, dhdp); } @@ -5271,7 +5268,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) } /* terence 2017029: Reject in early suspend */ - if (!dhd->pub.conf->xmit_in_suspend && dhd->pub.early_suspended) { + if ((dhd->pub.conf->insuspend & NO_TXDATA_IN_SUSPEND) && dhd->pub.early_suspended) { dhd_txflowcontrol(&dhd->pub, ALL_INTERFACES, ON); #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) return -ENODEV; @@ -8549,6 +8546,15 @@ dhd_stop(struct net_device *net) OLD_MOD_DEC_USE_COUNT; exit: +#if defined(WL_WIRELESS_EXT) + if (ifidx == 0) { +#ifdef WL_ESCAN + wl_escan_down(&dhd->pub); +#else + wl_iw_down(&dhd->pub); +#endif /* WL_ESCAN */ + } +#endif /* defined(WL_WIRELESS_EXT) */ if (skip_reset == false) { if (ifidx == 0 && !dhd_download_fw_on_driverload) { #if defined(BT_OVER_SDIO) @@ -8766,14 +8772,6 @@ dhd_open(struct net_device *net) ret = -1; goto exit; } -#if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT) - conf = dhd_get_conf(net); - if (conf) { - wl_android_ext_priv_cmd(net, conf->isam_init, 0, &bytes_written); - wl_android_ext_priv_cmd(net, conf->isam_config, 0, &bytes_written); - wl_android_ext_priv_cmd(net, conf->isam_enable, 0, &bytes_written); - } -#endif } #ifdef SUPPORT_DEEP_SLEEP else { @@ -8924,6 +8922,25 @@ dhd_open(struct net_device *net) dhd_set_scb_probe(&dhd->pub); #endif /* NUM_SCB_MAX_PROBE */ #endif /* WL_CFG80211 */ +#if defined(WL_WIRELESS_EXT) +#ifdef WL_ESCAN + if (unlikely(wl_escan_up(net, &dhd->pub))) { + DHD_ERROR(("%s: failed to bring up escan\n", __FUNCTION__)); + ret = -1; + goto exit; + } +#endif +#endif +#if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT) + if (!dhd_download_fw_on_driverload) { + conf = dhd_get_conf(net); + if (conf) { + wl_android_ext_priv_cmd(net, conf->isam_init, 0, &bytes_written); + wl_android_ext_priv_cmd(net, conf->isam_config, 0, &bytes_written); + wl_android_ext_priv_cmd(net, conf->isam_enable, 0, &bytes_written); + } + } +#endif } /* Allow transmit calls */ @@ -12391,9 +12408,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP); #endif /* defined(BCMPCIE) && defined(EAPOL_PKT_PRIO) */ -#ifdef SUSPEND_EVENT - bcopy(eventmask, dhd->conf->resume_eventmask, WL_EVENTING_MASK_LEN); -#endif /* Write updated Event mask */ ret = dhd_iovar(dhd, 0, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, NULL, 0, TRUE); if (ret < 0) { @@ -13494,6 +13508,11 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) dhd->bus_user_count--; #endif /* BT_OVER_SDIO */ } +#if defined(WL_WIRELESS_EXT) +#ifdef WL_ESCAN + wl_escan_down(&dhd->pub); +#endif /* WL_ESCAN */ +#endif /* defined(WL_WIRELESS_EXT) */ } #endif /* OEM_ANDROID && (BCMPCIE || (BCMLXSDMMC && KERNEL_VERSION >= 2.6.27)) */ return 0; @@ -16656,6 +16675,8 @@ static void dhd_hang_process(void *dhd_info, void *event_info, u8 event) struct net_device *dev; dhd = (dhd_info_t *)dhd_info; + if (!dhd || !dhd->iflist[0]) + return; dev = dhd->iflist[0]->net; if (dev) { diff --git a/bcmdhd.100.10.315.x/dhd_msgbuf.c b/bcmdhd.100.10.315.x/dhd_msgbuf.c index 408cf89..8eb0b8a 100644 --- a/bcmdhd.100.10.315.x/dhd_msgbuf.c +++ b/bcmdhd.100.10.315.x/dhd_msgbuf.c @@ -6834,6 +6834,7 @@ dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) if (intstatus) { DHD_ERROR(("%s: reschedule dhd_dpc, cnt=%d, intstatus=0x%x, intmask=0x%x\n", __FUNCTION__, cnt, intstatus, intmask)); + dhd->bus->intstatus = intstatus; dhd->bus->ipend = TRUE; dhd->bus->dpc_sched = TRUE; dhd_sched_dpc(dhd); diff --git a/bcmdhd.100.10.315.x/dhd_pcie_linux.c b/bcmdhd.100.10.315.x/dhd_pcie_linux.c index 3033dfd..8885b09 100644 --- a/bcmdhd.100.10.315.x/dhd_pcie_linux.c +++ b/bcmdhd.100.10.315.x/dhd_pcie_linux.c @@ -1140,7 +1140,8 @@ dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) { DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__)); - return -ENODEV; + DHD_MUTEX_UNLOCK(); + return -ENODEV; } printf("PCI_PROBE: bus %X, slot %X,vendor %X, device %X" "(good PCI location)\n", pdev->bus->number, @@ -1148,6 +1149,7 @@ dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (dhdpcie_init (pdev)) { DHD_ERROR(("%s: PCIe Enumeration failed\n", __FUNCTION__)); + DHD_MUTEX_UNLOCK(); return -ENODEV; } @@ -1845,7 +1847,7 @@ dhdpcie_enable_irq(dhd_bus_t *bus) int dhdpcie_irq_disabled(dhd_bus_t *bus) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) struct irq_desc *desc = irq_to_desc(bus->dev->irq); /* depth will be zero, if enabled */ return desc->depth; diff --git a/bcmdhd.100.10.315.x/dhd_sdio.c b/bcmdhd.100.10.315.x/dhd_sdio.c index 3c3b3ba..4a52e87 100644 --- a/bcmdhd.100.10.315.x/dhd_sdio.c +++ b/bcmdhd.100.10.315.x/dhd_sdio.c @@ -7829,6 +7829,18 @@ dhd_dump_cis(uint fn, uint8 *cis) static bool dhdsdio_chipmatch(uint16 chipid) { + if (chipid == BCM4330_CHIP_ID) + return TRUE; + if (chipid == BCM43362_CHIP_ID) + return TRUE; + if (chipid == BCM43340_CHIP_ID) + return TRUE; + if (chipid == BCM43341_CHIP_ID) + return TRUE; + if (chipid == BCM4334_CHIP_ID) + return TRUE; + if (chipid == BCM4324_CHIP_ID) + return TRUE; if (chipid == BCM4335_CHIP_ID) return TRUE; if (chipid == BCM4339_CHIP_ID) diff --git a/bcmdhd.100.10.315.x/dhd_static_buf.c b/bcmdhd.100.10.315.x/dhd_static_buf.c index 2e29474..2352ba8 100644 --- a/bcmdhd.100.10.315.x/dhd_static_buf.c +++ b/bcmdhd.100.10.315.x/dhd_static_buf.c @@ -6,7 +6,7 @@ #include #include -#define DHD_STATIC_VERSION_STR "100.10.315.1" +#define DHD_STATIC_VERSION_STR "100.10.315.2" #define BCMDHD_SDIO #define BCMDHD_PCIE @@ -52,7 +52,7 @@ enum dhd_prealloc_index { #define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) #define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024) #define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024) -#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (810 * 1024) +#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024) #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) #define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (66 * 1024) #ifdef CONFIG_64BIT @@ -416,7 +416,7 @@ err_mem_alloc: if (wlan_static_wl_escan_info_buf) kfree(wlan_static_wl_escan_info_buf); - + #ifdef BCMDHD_PCIE if (wlan_static_fw_verbose_ring_buf) kfree(wlan_static_fw_verbose_ring_buf); @@ -512,7 +512,7 @@ dhd_static_buf_exit(void) if (wlan_static_wl_escan_info_buf) kfree(wlan_static_wl_escan_info_buf); - + #ifdef BCMDHD_PCIE if (wlan_static_fw_verbose_ring_buf) kfree(wlan_static_fw_verbose_ring_buf); diff --git a/bcmdhd.100.10.315.x/include/epivers.h b/bcmdhd.100.10.315.x/include/epivers.h index c99ea90..0edcbdd 100644 --- a/bcmdhd.100.10.315.x/include/epivers.h +++ b/bcmdhd.100.10.315.x/include/epivers.h @@ -46,6 +46,6 @@ #define EPI_VERSION_DEV 100.10.315 /* Driver Version String, ASCII, 32 chars max */ -#define EPI_VERSION_STR "100.10.315.2 (r771911)" +#define EPI_VERSION_STR "100.10.315.3 (r771911)" #endif /* _epivers_h_ */ diff --git a/bcmdhd.100.10.315.x/linux_osl.c b/bcmdhd.100.10.315.x/linux_osl.c index 6105a2f..f702c89 100644 --- a/bcmdhd.100.10.315.x/linux_osl.c +++ b/bcmdhd.100.10.315.x/linux_osl.c @@ -115,9 +115,12 @@ static int secdma_found = 0; #endif /* BCM_SECURE_DMA */ #ifdef USE_DMA_LOCK -#define DMA_LOCK(osh) spin_lock_bh(&(osh)->dma_lock) -#define DMA_UNLOCK(osh) spin_unlock_bh(&(osh)->dma_lock) -#define DMA_LOCK_INIT(osh) spin_lock_init(&(osh)->dma_lock) +static void osl_dma_lock(osl_t *osh); +static void osl_dma_unlock(osl_t *osh); +static void osl_dma_lock_init(osl_t *osh); +#define DMA_LOCK(osh) osl_dma_lock(osh) +#define DMA_UNLOCK(osh) osl_dma_unlock(osh) +#define DMA_LOCK_INIT(osh) osl_dma_lock_init(osh); #else #define DMA_LOCK(osh) do { /* noop */ } while(0) #define DMA_UNLOCK(osh) do { /* noop */ } while(0) @@ -1901,3 +1904,42 @@ osl_timer_del(osl_t *osh, osl_timer_t *t) return (TRUE); } #endif + +#ifdef USE_DMA_LOCK +static void +osl_dma_lock(osl_t *osh) +{ + /* XXX: The conditional check is to avoid the scheduling bug. + * If the spin_lock_bh is used under the spin_lock_irqsave, + * Kernel triggered the warning message as the spin_lock_irqsave + * disables the interrupt and the spin_lock_bh doesn't use in case + * interrupt is disabled. + * Please refer to the __local_bh_enable_ip() function + * in kernel/softirq.c to understand the condtion. + */ + if (likely(in_irq() || irqs_disabled())) { + spin_lock(&osh->dma_lock); + } else { + spin_lock_bh(&osh->dma_lock); + osh->dma_lock_bh = TRUE; + } +} + +static void +osl_dma_unlock(osl_t *osh) +{ + if (unlikely(osh->dma_lock_bh)) { + osh->dma_lock_bh = FALSE; + spin_unlock_bh(&osh->dma_lock); + } else { + spin_unlock(&osh->dma_lock); + } +} + +static void +osl_dma_lock_init(osl_t *osh) +{ + spin_lock_init(&osh->dma_lock); + osh->dma_lock_bh = FALSE; +} +#endif /* USE_DMA_LOCK */ \ No newline at end of file diff --git a/bcmdhd.100.10.315.x/linux_osl_priv.h b/bcmdhd.100.10.315.x/linux_osl_priv.h index 0b602cd..7ae18c2 100644 --- a/bcmdhd.100.10.315.x/linux_osl_priv.h +++ b/bcmdhd.100.10.315.x/linux_osl_priv.h @@ -173,6 +173,7 @@ struct osl_info { #endif /* BCM_BACKPLANE_TIMEOUT */ #ifdef USE_DMA_LOCK spinlock_t dma_lock; + bool dma_lock_bh; #endif /* USE_DMA_LOCK */ }; diff --git a/bcmdhd.100.10.315.x/wl_android.c b/bcmdhd.100.10.315.x/wl_android.c index 4e4b927..4fb7ab9 100644 --- a/bcmdhd.100.10.315.x/wl_android.c +++ b/bcmdhd.100.10.315.x/wl_android.c @@ -5256,7 +5256,7 @@ int wl_android_init(void) { int ret = 0; -#ifdef ENABLE_INSMOD_NO_FW_LOAD +#if defined(ENABLE_INSMOD_NO_FW_LOAD) || defined(BUS_POWER_RESTORE) dhd_download_fw_on_driverload = FALSE; #endif /* ENABLE_INSMOD_NO_FW_LOAD */ if (!iface_name[0]) { diff --git a/bcmdhd.100.10.315.x/wl_android.h b/bcmdhd.100.10.315.x/wl_android.h index 4fe94bc..e035aa7 100644 --- a/bcmdhd.100.10.315.x/wl_android.h +++ b/bcmdhd.100.10.315.x/wl_android.h @@ -73,6 +73,13 @@ typedef struct _compat_android_wifi_priv_cmd { #define ANDROID_INFO_LEVEL 0x0004 #define ANDROID_EVENT_LEVEL 0x0008 +#define ANDROID_MSG(x) \ + do { \ + if (android_msg_level & ANDROID_ERROR_LEVEL) { \ + printk(KERN_ERR "ANDROID-MSG) "); \ + printk x; \ + } \ + } while (0) #define ANDROID_ERROR(x) \ do { \ if (android_msg_level & ANDROID_ERROR_LEVEL) { \ @@ -123,8 +130,15 @@ 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); +bool wl_ext_check_mesh_creating(struct net_device *net); extern int op_mode; #endif +typedef struct bcol_gtk_para { + int enable; + int ptk_len; + char ptk[64]; + char replay[8]; +} bcol_gtk_para_t; int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len, int *bytes_written); enum wl_ext_status { @@ -141,12 +155,20 @@ enum wl_ext_status { WL_EXT_STATUS_AP_DISABLED }; typedef struct wl_conn_info { + struct net_device *dev; + dhd_pub_t *dhd; uint8 bssidx; wlc_ssid_t ssid; struct ether_addr bssid; uint16 channel; + struct delayed_work pm_enable_work; + struct mutex pm_sync; } wl_conn_info_t; +#if defined(WL_WIRELESS_EXT) s32 wl_ext_connect(struct net_device *dev, wl_conn_info_t *conn_info); +void wl_ext_pm_work_handler(struct work_struct * work); +void wl_ext_add_remove_pm_enable_work(struct wl_conn_info *conn_info, bool add); +#endif /* defined(WL_WIRELESS_EXT) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) #define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len)) #endif diff --git a/bcmdhd.100.10.315.x/wl_android_ext.c b/bcmdhd.100.10.315.x/wl_android_ext.c index d247d7e..fe00236 100644 --- a/bcmdhd.100.10.315.x/wl_android_ext.c +++ b/bcmdhd.100.10.315.x/wl_android_ext.c @@ -32,6 +32,21 @@ #include #endif +#if defined(WL_WIRELESS_EXT) +#define WL_PM_ENABLE_TIMEOUT 10000 +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ +entry = container_of((ptr), type, member); \ +_Pragma("GCC diagnostic pop") +#else +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +entry = container_of((ptr), type, member); +#endif /* STRICT_GCC_WARNINGS */ +#endif /* defined(WL_WIRELESS_EXT) */ + #ifndef WL_CFG80211 #define htod32(i) i #define htod16(i) i @@ -252,6 +267,7 @@ typedef struct wl_apsta_params { uint csa; apstamode_t apstamode; bool netif_change; + bool mesh_creating; wait_queue_head_t netif_change_event; } wl_apsta_params_t; @@ -487,13 +503,13 @@ set_channel: 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); + ANDROID_MSG(("%s: channel %d\n", __FUNCTION__, _chan)); } else if (err) { ANDROID_ERROR(("%s: failed to set chanspec error %d\n", __FUNCTION__, err)); } else - printf("%s: %s channel %d, 0x%x\n", __FUNCTION__, - dev->name, channel, chspec); + ANDROID_MSG(("%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__)); @@ -572,9 +588,8 @@ wl_ext_channels(struct net_device *dev, char* command, int total_len) for (i = 0; i < dtoh32(list->count); i++) { bytes_written += snprintf(command+bytes_written, total_len, " %d", dtoh32(list->element[i])); - printf("%d ", dtoh32(list->element[i])); } - printf("\n"); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); ret = bytes_written; } @@ -678,23 +693,25 @@ wl_ext_keep_alive(struct net_device *dev, char *command, int total_len) goto exit; } else { mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf; - printf("Id :%d\n" - "Period (msec) :%d\n" - "Length :%d\n" - "Packet :0x", - mkeep_alive_pktp->keep_alive_id, - dtoh32(mkeep_alive_pktp->period_msec), - dtoh16(mkeep_alive_pktp->len_bytes)); - for (i=0; ilen_bytes; i++) { - printf("%02x", mkeep_alive_pktp->data[i]); + if (android_msg_level & ANDROID_INFO_LEVEL) { + printf("Id :%d\n" + "Period (msec) :%d\n" + "Length :%d\n" + "Packet :0x", + mkeep_alive_pktp->keep_alive_id, + dtoh32(mkeep_alive_pktp->period_msec), + dtoh16(mkeep_alive_pktp->len_bytes)); + for (i=0; ilen_bytes; i++) { + printf("%02x", mkeep_alive_pktp->data[i]); + } + printf("\n"); } - printf("\n"); } 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", + bytes_written += snprintf(command+bytes_written, total_len, "%02x", mkeep_alive_pktp->data[i]); } ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); @@ -830,9 +847,9 @@ wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info) 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", + ANDROID_MSG(("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); + ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len)); kfree(ext_join_params); if (err) { @@ -872,6 +889,79 @@ exit: } +#if defined(WL_WIRELESS_EXT) +void wl_ext_pm_work_handler(struct work_struct * work) +{ + struct wl_conn_info *conn_info; + s32 pm = PM_FAST; + dhd_pub_t *dhd; + BCM_SET_CONTAINER_OF(conn_info, work, struct wl_conn_info, pm_enable_work.work); + + ANDROID_TRACE(("%s: Enter\n", __FUNCTION__)); +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#endif + + dhd = (dhd_pub_t *)(conn_info->dhd); + if (!dhd || !conn_info->dhd->up) { + ANDROID_TRACE(("%s: dhd is null or not up\n", __FUNCTION__)); + return; + } + if (dhd_conf_get_pm(dhd) >= 0) + pm = dhd_conf_get_pm(dhd); + wl_ext_ioctl(conn_info->dev, WLC_SET_PM, &pm, sizeof(pm), 1); +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +_Pragma("GCC diagnostic pop") +#endif + DHD_PM_WAKE_UNLOCK(conn_info->dhd); + +} + +void wl_ext_add_remove_pm_enable_work(struct wl_conn_info *conn_info, + bool add) +{ + u16 wq_duration = 0; + s32 pm = PM_OFF; + + if (conn_info == NULL || conn_info->dhd == NULL) + return; + + mutex_lock(&conn_info->pm_sync); + /* + * Make cancel and schedule work part mutually exclusive + * so that while cancelling, we are sure that there is no + * work getting scheduled. + */ + + if (delayed_work_pending(&conn_info->pm_enable_work)) { + cancel_delayed_work_sync(&conn_info->pm_enable_work); + DHD_PM_WAKE_UNLOCK(conn_info->dhd); + } + + if (add) { + wq_duration = (WL_PM_ENABLE_TIMEOUT); + } + + /* It should schedule work item only if driver is up */ + if (wq_duration && conn_info->dhd->up) { + if (dhd_conf_get_pm(conn_info->dhd) >= 0) + pm = dhd_conf_get_pm(conn_info->dhd); + wl_ext_ioctl(conn_info->dev, WLC_SET_PM, &pm, sizeof(pm), 1); + if (schedule_delayed_work(&conn_info->pm_enable_work, + msecs_to_jiffies((const unsigned int)wq_duration))) { + DHD_PM_WAKE_LOCK_TIMEOUT(conn_info->dhd, wq_duration); + } else { + ANDROID_ERROR(("%s: Can't schedule pm work handler\n", __FUNCTION__)); + } + } + mutex_unlock(&conn_info->pm_sync); + +} +#endif /* defined(WL_WIRELESS_EXT) */ + #ifdef WL_EXT_IAPSTA static int wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key) @@ -1299,6 +1389,17 @@ wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params, rtnl_lock(); } +bool +wl_ext_check_mesh_creating(struct net_device *net) +{ + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + + if (apsta_params) + return apsta_params->mesh_creating; + return FALSE; +} + static void wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_params) { @@ -1372,7 +1473,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para 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); + ANDROID_MSG(("%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); @@ -1503,9 +1604,11 @@ 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; + apsta_params->mesh_creating = TRUE; wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); + apsta_params->mesh_creating = FALSE; } else if (apstamode == IMESHAP_MODE) { wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); @@ -1516,11 +1619,13 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para // 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; + iface.flags = WL_INTERFACE_CREATE_STA; apsta_params->netif_change = FALSE; + apsta_params->mesh_creating = TRUE; wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); + apsta_params->mesh_creating = FALSE; } else if (apstamode == IMESHAPSTA_MODE) { wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); @@ -1540,9 +1645,11 @@ 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; + apsta_params->mesh_creating = TRUE; wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL); wl_ext_wait_netif_change(apsta_params, TRUE); + apsta_params->mesh_creating = FALSE; } else if (apstamode == IMESHAPAP_MODE) { wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); @@ -1582,7 +1689,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); apsta_params->init = TRUE; - printf("%s: apstamode=%d\n", __FUNCTION__, apstamode); + ANDROID_MSG(("%s: apstamode=%d\n", __FUNCTION__, apstamode)); } static int @@ -2062,9 +2169,9 @@ wl_mesh_print_peer_info(mesh_peer_info_ext_t *mpi_ext, mpi_ext->rssi); } else { bytes_written += snprintf(command+bytes_written, total_len, - "\n%d: %pM : %6s : %5s : %6s :" + "\n%2d: %pM : %6s : %5s : %6s :" " %5s : %4s : %4s : %11s : %4s", - count, &mpi_ext->ea, " NA ", " NA ", " NA ", + count, &mpi_ext->ea, " NA ", " NA ", " NA ", " NA ", " NA ", " NA ", " TIMEDOUT ", " NA "); } mpi_ext++; @@ -2138,7 +2245,8 @@ wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) } bss_setbuf; apstamode_t apstamode = apsta_params->apstamode; - printf("%s: %s[%c] Turning off\n", __FUNCTION__, cur_if->ifname, cur_if->prefix); + ANDROID_MSG(("%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); @@ -2178,12 +2286,13 @@ wl_ext_if_up(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) } 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); + ANDROID_MSG(("%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); + ANDROID_MSG(("%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); @@ -2256,7 +2365,7 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) return -1; } - printf("%s: %s[%c] Disabling\n", __FUNCTION__, ifname, cur_if->prefix); + ANDROID_MSG(("%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); @@ -2327,7 +2436,7 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) cur_if->ifstate = IF_STATE_DISALBE; - printf("%s: %s[%c] disabled\n", __FUNCTION__, ifname, cur_if->prefix); + ANDROID_MSG(("%s: %s[%c] disabled\n", __FUNCTION__, ifname, cur_if->prefix)); return 0; } @@ -2372,11 +2481,11 @@ wl_ext_triger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_i if (apsta_params->csa & CSA_DRV_BIT && (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) { if (!cur_if->channel) { - printf("%s: %s[%c] skip channel %d\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, cur_if->channel); + ANDROID_MSG(("%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); + ANDROID_MSG(("%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; @@ -2386,14 +2495,14 @@ wl_ext_triger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_i 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); + ANDROID_MSG(("%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__); + ANDROID_ERROR(("%s: fail to get chanspec\n", __FUNCTION__)); } } } @@ -2433,21 +2542,21 @@ wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params, tmp_chan = wl_ext_get_chan(apsta_params, cur_if->dev); if (apsta_params->rsdb && tmp_chan && wl_ext_diff_band(tmp_chan, target_chan)) { - printf("%s: %s[%c] keep on current channel %d\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, tmp_chan); + ANDROID_MSG(("%s: %s[%c] keep on current channel %d\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, tmp_chan)); cur_if->channel = 0; } else { - printf("%s: %s[%c] channel=%d => %s[%c] channel=%d\n", __FUNCTION__, + ANDROID_MSG(("%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); + 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); + ANDROID_MSG(("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, cur_if->channel)); cur_if->channel = 0; } @@ -2483,8 +2592,8 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, } if (target_if) { - printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__, - target_if->ifname, target_chan, cur_if->ifname, cur_if->channel); + ANDROID_MSG(("%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); @@ -2531,9 +2640,8 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) return -1; } - printf("%s: %s[%c] Enabling\n", __FUNCTION__, ifname, cur_if->prefix); - wl_ext_isam_status(cur_if->dev, NULL, 0); + ANDROID_MSG(("%s: %s[%c] Enabling\n", __FUNCTION__, ifname, cur_if->prefix)); wl_ext_move_cur_channel(apsta_params, dev, cur_if); if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) { @@ -2615,8 +2723,8 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) if (cur_if->hidden > 0) { wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1); - printf("%s: Broadcast SSID: %s\n", __FUNCTION__, - cur_if->hidden ? "OFF":"ON"); + ANDROID_MSG(("%s: Broadcast SSID: %s\n", __FUNCTION__, + cur_if->hidden ? "OFF":"ON")); } } @@ -2664,7 +2772,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } 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); + ANDROID_ERROR(("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode)); } #ifdef WLMESH } else if (apstamode == IMESHONLY_MODE || @@ -2684,7 +2792,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) join_params.params.chanspec_num = 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); + ANDROID_ERROR(("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode)); } #endif } @@ -2705,8 +2813,8 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) #endif OSL_SLEEP(500); - printf("%s: %s[%c] enabled with SSID: \"%s\"\n", __FUNCTION__, - ifname, cur_if->prefix, cur_if->ssid); + ANDROID_MSG(("%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; @@ -2824,7 +2932,7 @@ wl_ext_iapsta_alive_postinit(struct net_device *dev) // fix me: how to check it's IAPSTA_MODE or IDUALAP_MODE? wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); - printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode); + ANDROID_MSG(("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode)); return op_mode; } @@ -2957,15 +3065,14 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) #if defined(WL_WIRELESS_EXT) char extra[IW_CUSTOM_MAX]; union iwreq_data wrqu; + uint32 datalen = ntoh32(e->datalen); #endif uint32 event_type = ntoh32(e->event_type); uint32 status = ntoh32(e->status); uint32 reason = ntoh32(e->reason); uint16 flags = ntoh16(e->flags); - uint32 datalen = ntoh32(e->datalen); if (!apsta_params->init) { - ANDROID_TRACE(("%s: please init first\n", __FUNCTION__)); return -1; } @@ -2984,11 +3091,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 %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + ANDROID_MSG(("%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 %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + ANDROID_MSG(("%s: %s[%c] Link UP with %pM\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, &e->addr)); } } } @@ -2996,25 +3103,25 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) if ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) || (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS && reason == WLC_E_REASON_INITIAL_ASSOC)) { - printf("%s: %s[%c] Link up\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix); + ANDROID_MSG(("%s: %s[%c] Link up\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix)); } else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) || (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS && reason == WLC_E_REASON_DEAUTH)) { - printf("%s: %s[%c] Link down\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix); + ANDROID_MSG(("%s: %s[%c] Link down\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix)); } else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) && reason == DOT11_SC_SUCCESS) { - printf("%s: %s[%c] connected device %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + ANDROID_MSG(("%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 %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + ANDROID_MSG(("%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 %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + ANDROID_MSG(("%s: %s[%c] deauthenticated device %pM\n", __FUNCTION__, + cur_if->ifname, cur_if->prefix, &e->addr)); } } @@ -3103,7 +3210,7 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if = NULL, *primary_if; - printf("%s: ifidx=%d, bssidx=%d\n", __FUNCTION__, ifidx, bssidx); + ANDROID_MSG(("%s: ifidx=%d, bssidx=%d\n", __FUNCTION__, ifidx, bssidx)); if (ifidx < MAX_IF_NUM) { cur_if = &apsta_params->if_info[ifidx]; } @@ -3159,7 +3266,7 @@ wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx) if (!apsta_params) return 0; - printf("%s: ifidx=%d\n", __FUNCTION__, ifidx); + ANDROID_MSG(("%s: ifidx=%d\n", __FUNCTION__, ifidx)); if (ifidx < MAX_IF_NUM) { cur_if = &apsta_params->if_info[ifidx]; } @@ -3179,7 +3286,7 @@ int wl_ext_iapsta_attach(dhd_pub_t *pub) iapsta_params = kzalloc(sizeof(struct wl_apsta_params), GFP_KERNEL); if (unlikely(!iapsta_params)) { - printf("%s: Could not allocate apsta_params\n", __FUNCTION__); + ANDROID_ERROR(("%s: Could not allocate apsta_params\n", __FUNCTION__)); return -ENOMEM; } pub->iapsta_params = (void *)iapsta_params; @@ -3296,7 +3403,7 @@ wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command, 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); + ANDROID_MSG(("%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); @@ -3311,9 +3418,41 @@ wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command, return ret; } -#ifdef SENDPROB -int -wl_ext_add_remove_eventmsg(struct net_device *dev, char *data, +static s32 +wl_ext_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) +{ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + s8 eventmask[WL_EVENTING_MASK_LEN]; + s32 err = 0; + + if (!ndev) + return -ENODEV; + + /* Setup event_msgs */ + err = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL); + if (unlikely(err)) { + ANDROID_ERROR(("Get event_msgs error (%d)\n", err)); + goto eventmsg_out; + } + memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); + if (add) { + setbit(eventmask, event); + } else { + clrbit(eventmask, event); + } + err = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, + sizeof(iovbuf), NULL); + if (unlikely(err)) { + ANDROID_ERROR(("Set event_msgs error (%d)\n", err)); + goto eventmsg_out; + } + +eventmsg_out: + return err; +} + +static int +wl_ext_event_msg(struct net_device *dev, char *data, char *command, int total_len) { s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; @@ -3329,7 +3468,8 @@ wl_ext_add_remove_eventmsg(struct net_device *dev, char *data, ANDROID_TRACE(("%s: command = %s\n", __FUNCTION__, data)); sscanf(data, "%d %d", &event, &add); /* Setup event_msgs */ - bytes_written = wldev_iovar_getbuf(dev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL); + bytes_written = wldev_iovar_getbuf(dev, "event_msgs", NULL, 0, iovbuf, + sizeof(iovbuf), NULL); if (unlikely(bytes_written)) { ANDROID_ERROR(("Get event_msgs error (%d)\n", bytes_written)); goto eventmsg_out; @@ -3343,21 +3483,12 @@ wl_ext_add_remove_eventmsg(struct net_device *dev, char *data, ANDROID_INFO(("%s\n", command)); goto eventmsg_out; } - if (add) { - setbit(eventmask, event); - } else { - clrbit(eventmask, event); - } - bytes_written = wl_ext_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, - sizeof(iovbuf), NULL); - if (unlikely(bytes_written)) { - ANDROID_ERROR(("Set event_msgs error (%d)\n", bytes_written)); - goto eventmsg_out; - } + bytes_written = wl_ext_add_remove_eventmsg(dev, event, add); } else { /* Setup event_msgs */ - bytes_written = wldev_iovar_getbuf(dev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL); + bytes_written = wldev_iovar_getbuf(dev, "event_msgs", NULL, 0, iovbuf, + sizeof(iovbuf), NULL); if (bytes_written) { ANDROID_ERROR(("Get event_msgs error (%d)\n", bytes_written)); goto eventmsg_out; @@ -3379,6 +3510,7 @@ eventmsg_out: return bytes_written; } +#ifdef SENDPROB static int wl_ext_send_probresp(struct net_device *dev, char *data, char *command, int total_len) { @@ -3443,6 +3575,47 @@ exit: } #endif +static int +wl_ext_gtk_key_info(struct net_device *dev, char *data, char *command, int total_len) +{ + int err = 0; + char iovar_buf[WLC_IOCTL_SMLEN]="\0"; + gtk_keyinfo_t keyinfo; + bcol_gtk_para_t bcol_keyinfo; + + /* wl gtk_key_info [kck kek replay_ctr] */ + /* wl gtk_key_info 001122..FF001122..FF00000000000001 */ + if (data) { + memset(&keyinfo, 0, sizeof(keyinfo)); + memcpy(&keyinfo, data, RSN_KCK_LENGTH+RSN_KEK_LENGTH+RSN_REPLAY_LEN); + if (android_msg_level & ANDROID_INFO_LEVEL) { + prhex("kck", (uchar *)keyinfo.KCK, RSN_KCK_LENGTH); + prhex("kek", (uchar *)keyinfo.KEK, RSN_KEK_LENGTH); + prhex("replay_ctr", (uchar *)keyinfo.ReplayCounter, RSN_REPLAY_LEN); + } + + memset(&bcol_keyinfo, 0, sizeof(bcol_keyinfo)); + bcol_keyinfo.enable = 1; + bcol_keyinfo.ptk_len = 64; + memcpy(&bcol_keyinfo.ptk, data, RSN_KCK_LENGTH+RSN_KEK_LENGTH); + err = wl_ext_iovar_setbuf(dev, "bcol_gtk_rekey_ptk", &bcol_keyinfo, + sizeof(bcol_keyinfo), iovar_buf, sizeof(iovar_buf), NULL); + if (!err) { + goto exit; + } + + err = wl_ext_iovar_setbuf(dev, "gtk_key_info", &keyinfo, sizeof(keyinfo), + iovar_buf, sizeof(iovar_buf), NULL); + if (err) { + ANDROID_ERROR(("%s: failed to set gtk_key_info\n", __FUNCTION__)); + goto exit; + } + } + +exit: + return err; +} + typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command, int total_len); @@ -3458,10 +3631,11 @@ const wl_ext_iovar_tpl_t wl_ext_iovar_tpl_list[] = { #ifdef WLMESH {WLC_GET_VAR, WLC_SET_VAR, "mesh_peer_status", wl_ext_mesh_peer_status}, #endif + {WLC_GET_VAR, WLC_SET_VAR, "event_msg", wl_ext_event_msg}, #ifdef SENDPROB - {WLC_GET_VAR, WLC_SET_VAR, "event_msg", wl_ext_add_remove_eventmsg}, {WLC_GET_VAR, WLC_SET_VAR, "send_probresp", wl_ext_send_probresp}, #endif + {WLC_GET_VAR, WLC_SET_VAR, "gtk_key_info", wl_ext_gtk_key_info}, }; /* @@ -3796,7 +3970,7 @@ wl_ext_get_best_channel(struct net_device *net, } } - if (android_msg_level&ANDROID_INFO_LEVEL) { + if (android_msg_level & ANDROID_INFO_LEVEL) { printf("%s: b_band: ", __FUNCTION__); for (j=0; jscan_suppressed) + if ((err == BCME_EPERM) && (cfg->scan_suppressed || suppressed)) { + cnt = 0; WL_DBG(("Escan failed: Scan Suppressed \n")); - else { + } else { cnt++; WL_ERR(("error (%d), cnt=%d\n", err, cnt)); // terence 20140111: send disassoc to firmware @@ -4686,6 +4689,13 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev, return NULL; } +#ifdef WL_EXT_IAPSTA + if (wl_ext_check_mesh_creating(ndev)) { + printf("%s: change iface_type to NL80211_IFTYPE_MESH_POINT\n", __FUNCTION__); + iface_type = NL80211_IFTYPE_MESH_POINT; + } +#endif + WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG "\n", addr, name, event->role, iface_type, MAC2STRDBG(event->mac))); if (!name) { @@ -10640,6 +10650,31 @@ wl_cfg80211_parse_ies(const u8 *ptr, u32 len, struct parsed_ies *ies) return err; } + +bool +wl_legacy_chip_check(struct bcm_cfg80211 *cfg) +{ + dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); + uint chip; + + chip = dhd_conf_get_chip(dhd); + + if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID || + chip == BCM43430_CHIP_ID || chip == BCM43012_CHIP_ID || + chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID || + chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID || + chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID || + chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID || + chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID || + chip == BCM4371_CHIP_ID || chip == BCM4359_CHIP_ID || + chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID || + chip == BCM43569_CHIP_ID) { + return true; + } + + return false; +} + static s32 wl_cfg80211_set_ap_role( struct bcm_cfg80211 *cfg, @@ -10651,6 +10686,9 @@ wl_cfg80211_set_ap_role( s32 pm; s32 bssidx; s32 apsta = 0; + bool legacy_chip; + + legacy_chip = wl_legacy_chip_check(cfg); if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) { WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr)); @@ -10659,10 +10697,12 @@ wl_cfg80211_set_ap_role( WL_INFORM_MEM(("[%s] Bringup SoftAP on bssidx:%d \n", dev->name, bssidx)); - if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx, - WL_IF_TYPE_AP, 0, NULL)) < 0) { - WL_ERR(("wl add_del_bss returned error:%d\n", err)); - return err; + if (bssidx != 0 || !legacy_chip) { + if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx, + WL_IF_TYPE_AP, 0, NULL)) < 0) { + WL_ERR(("wl add_del_bss returned error:%d\n", err)); + return err; + } } /* @@ -10710,6 +10750,21 @@ wl_cfg80211_set_ap_role( return err; } } + } else if (bssidx == 0 && legacy_chip) { + err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32)); + if (err < 0) { + WL_ERR(("WLC_DOWN error %d\n", err)); + return err; + } + err = wldev_iovar_setint(dev, "apsta", 0); + if (err < 0) { + WL_ERR(("wl apsta 0 error %d\n", err)); + return err; + } + if ((err = wldev_ioctl_set(dev, WLC_SET_AP, &ap, sizeof(s32))) < 0) { + WL_ERR(("setting AP mode failed %d \n", err)); + return err; + } } if (bssidx == 0) { @@ -10796,7 +10851,7 @@ wl_cfg80211_bcn_bringup_ap( WL_DBG(("Bss is already up\n")); } else if (dev_role == NL80211_IFTYPE_AP) { - if (!wl_get_drv_status(cfg, AP_CREATING, dev)) { + if (!wl_get_drv_status(cfg, AP_CREATED, dev)) { /* Make sure fw is in proper state */ err = wl_cfg80211_set_ap_role(cfg, dev); if (unlikely(err)) { @@ -22109,6 +22164,7 @@ wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); s32 err = 0; gtk_keyinfo_t keyinfo; + bcol_gtk_para_t bcol_keyinfo; WL_DBG(("Enter\n")); if (data == NULL || cfg->p2p_net == dev) { @@ -22123,11 +22179,23 @@ wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, bcopy(data->kek, keyinfo.KEK, RSN_KEK_LENGTH); bcopy(data->replay_ctr, keyinfo.ReplayCounter, RSN_REPLAY_LEN); + memset(&bcol_keyinfo, 0, sizeof(bcol_keyinfo)); + bcol_keyinfo.enable = 1; + bcol_keyinfo.ptk_len = 64; + memcpy(&bcol_keyinfo.ptk[0], data->kck, RSN_KCK_LENGTH); + memcpy(&bcol_keyinfo.ptk[RSN_KCK_LENGTH], data->kek, RSN_KEK_LENGTH); + err = wldev_iovar_setbuf(dev, "bcol_gtk_rekey_ptk", &bcol_keyinfo, + sizeof(bcol_keyinfo), cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync); + if (!err) { + return err; + } + if ((err = wldev_iovar_setbuf(dev, "gtk_key_info", &keyinfo, sizeof(keyinfo), cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync)) < 0) { WL_ERR(("seting gtk_key_info failed code=%d\n", err)); return err; } + WL_DBG(("Exit\n")); return err; } diff --git a/bcmdhd.100.10.315.x/wl_escan.c b/bcmdhd.100.10.315.x/wl_escan.c index ef1dde1..a612957 100644 --- a/bcmdhd.100.10.315.x/wl_escan.c +++ b/bcmdhd.100.10.315.x/wl_escan.c @@ -1072,17 +1072,21 @@ wl_escan_set_scan( ESCAN_ERROR(("device is not ready\n")); return -EIO; } + if (escan->escan_state == ESCAN_STATE_DOWN) { + ESCAN_ERROR(("STATE is down\n")); + return -EIO; + } mutex_lock(&escan->usr_sync); if (!escan->ioctl_ver) { val = 1; if ((err = wldev_ioctl(dev, WLC_GET_VERSION, &val, sizeof(int), false) < 0)) { - ANDROID_ERROR(("WLC_GET_VERSION failed, err=%d\n", err)); + ESCAN_ERROR(("WLC_GET_VERSION failed, err=%d\n", err)); goto exit; } val = dtoh32(val); if (val != WLC_IOCTL_VERSION && val != 1) { - ANDROID_ERROR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n", + ESCAN_ERROR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n", val, WLC_IOCTL_VERSION)); goto exit; } @@ -1415,7 +1419,7 @@ s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len) } else if (escan->autochannel == 2) { bytes_written = snprintf(command, total_len, "2g=%d 5g=%d", escan->best_2g_ch, escan->best_5g_ch); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + ESCAN_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); ret = bytes_written; } @@ -1452,7 +1456,7 @@ static void wl_escan_deinit(struct wl_escan_info *escan) wl_destroy_event_handler(escan); wl_flush_eq(escan); del_timer_sync(&escan->scan_timeout); - escan->escan_state = ESCAN_STATE_IDLE; + escan->escan_state = ESCAN_STATE_DOWN; #if defined(RSSIAVG) wl_free_rssi_cache(&escan->g_rssi_cache_ctrl); @@ -1460,6 +1464,7 @@ static void wl_escan_deinit(struct wl_escan_info *escan) #if defined(BSSCACHE) wl_free_bss_cache(&escan->g_bss_cache_ctrl); #endif + wl_ext_add_remove_pm_enable_work(&escan->conn_info, FALSE); } static s32 wl_escan_init(struct wl_escan_info *escan) @@ -1482,6 +1487,7 @@ static s32 wl_escan_init(struct wl_escan_info *escan) #endif if (wl_create_event_handler(escan)) { + ESCAN_ERROR(("device is not ready\n")); err = -ENOMEM; goto err; } @@ -1490,14 +1496,33 @@ static s32 wl_escan_init(struct wl_escan_info *escan) escan->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler; escan->escan_state = ESCAN_STATE_IDLE; - mutex_init(&escan->usr_sync); - return 0; err: wl_escan_deinit(escan); return err; } +void wl_escan_down(dhd_pub_t *dhdp) +{ + struct wl_escan_info *escan = dhdp->escan; + + wl_escan_deinit(escan); +} + +int wl_escan_up(struct net_device *net, dhd_pub_t *dhdp) +{ + struct wl_escan_info *escan = dhdp->escan; + int err; + + err = wl_escan_init(escan); + if (err) { + ESCAN_ERROR(("wl_escan_init err %d\n", err)); + return err; + } + + return 0; +} + void wl_escan_detach(dhd_pub_t *dhdp) { struct wl_escan_info *escan = dhdp->escan; @@ -1523,6 +1548,7 @@ int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp) { struct wl_escan_info *escan = NULL; + int err = 0; printf("%s: Enter\n", __FUNCTION__); @@ -1537,7 +1563,9 @@ wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp) /* we only care about main interface so save a global here */ escan->dev = dev; escan->pub = dhdp; - escan->escan_state = ESCAN_STATE_IDLE; + escan->conn_info.dev = dev; + escan->conn_info.dhd = dhdp; + escan->escan_state = ESCAN_STATE_DOWN; escan->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); if (unlikely(!escan->escan_ioctl_buf)) { @@ -1545,7 +1573,14 @@ wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp) goto err ; } wl_init_eq(escan); - wl_escan_init(escan); + err = wl_escan_init(escan); + if (err) { + ESCAN_ERROR(("wl_escan_init err %d\n", err)); + return err; + } + mutex_init(&escan->usr_sync); + mutex_init(&escan->conn_info.pm_sync); + INIT_DELAYED_WORK(&escan->conn_info.pm_enable_work, wl_ext_pm_work_handler); return 0; err: diff --git a/bcmdhd.100.10.315.x/wl_escan.h b/bcmdhd.100.10.315.x/wl_escan.h index 1cb7428..86cde62 100644 --- a/bcmdhd.100.10.315.x/wl_escan.h +++ b/bcmdhd.100.10.315.x/wl_escan.h @@ -34,6 +34,7 @@ struct pmk_list { /* donlge escan state */ enum escan_state { + ESCAN_STATE_DOWN, ESCAN_STATE_IDLE, ESCAN_STATE_SCANING }; @@ -47,7 +48,7 @@ typedef struct wl_escan_info { struct net_device *dev; dhd_pub_t *pub; struct timer_list scan_timeout; /* Timer for catch scan event timeout */ - int escan_state; + int escan_state; int ioctl_ver; char ioctlbuf[WLC_IOCTL_SMLEN]; @@ -88,6 +89,8 @@ int wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info, s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len); int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp); void wl_escan_detach(dhd_pub_t *dhdp); +int wl_escan_up(struct net_device *net, dhd_pub_t *dhdp); +void wl_escan_down(dhd_pub_t *dhdp); #endif /* _wl_escan_ */ diff --git a/bcmdhd.100.10.315.x/wl_iw.c b/bcmdhd.100.10.315.x/wl_iw.c index 1556d9c..7859fba 100644 --- a/bcmdhd.100.10.315.x/wl_iw.c +++ b/bcmdhd.100.10.315.x/wl_iw.c @@ -472,18 +472,35 @@ wl_iw_set_pm( #endif /* WIRELESS_EXT > 12 */ static void -wl_iw_check_handshake(struct net_device *dev, bool set) +wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status) { #ifndef WL_CFG80211 struct dhd_pub *dhd = dhd_get_pub(dev); int cur_eapol_status = 0; int wpa_auth = 0; int error = -EINVAL; + 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 + + if (!dhd || !dhd->conf || !conn_info) + return; - if (dhd && dhd->conf) - cur_eapol_status = dhd->conf->eapol_status; + cur_eapol_status = dhd->conf->eapol_status; - if (set) { + if (status == WL_EXT_STATUS_CONNECTING) { + wl_ext_add_remove_pm_enable_work(conn_info, TRUE); if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &wpa_auth))) { WL_ERROR(("%s: wpa_auth get error %d\n", __FUNCTION__, error)); return; @@ -492,7 +509,20 @@ wl_iw_check_handshake(struct net_device *dev, bool set) dhd->conf->eapol_status = EAPOL_STATUS_WPA_START; else dhd->conf->eapol_status = EAPOL_STATUS_NONE; - } else { + } else if (status == WL_EXT_STATUS_ADD_KEY) { + dhd->conf->eapol_status = EAPOL_STATUS_WPA_END; + } else if (status == WL_EXT_STATUS_DISCONNECTING) { + wl_ext_add_remove_pm_enable_work(conn_info, FALSE); + 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; + } + } else if (status == WL_EXT_STATUS_DISCONNECTED) { 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)); @@ -722,8 +752,11 @@ wl_iw_set_mode( #endif WL_TRACE(("%s: SIOCSIWMODE\n", dev->name)); - if (conn_info) - memset(conn_info, 0, sizeof(wl_conn_info_t)); + if (conn_info) { + memset(&conn_info->ssid, 0, sizeof(wlc_ssid_t)); + memset(&conn_info->bssid, 0, sizeof(struct ether_addr)); + conn_info->channel = 0; + } switch (*uwrq) { case IW_MODE_MASTER: @@ -1098,7 +1131,7 @@ 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); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTING); return 0; } /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data), @@ -1117,7 +1150,7 @@ wl_iw_set_wap( } WL_ERROR(("%s: join BSSID="MACSTR"\n", __FUNCTION__, MAC2STR((u8 *)awrq->sa_data))); } - wl_iw_check_handshake(dev, TRUE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_CONNECTING); return 0; } @@ -1178,7 +1211,7 @@ wl_iw_mlme( WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__)); return error; } - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTING); return error; } @@ -1869,7 +1902,7 @@ wl_iw_set_essid( } WL_ERROR(("%s: join SSID=%s\n", __FUNCTION__, ssid.SSID)); } - wl_iw_check_handshake(dev, TRUE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_CONNECTING); } /* If essid null then it is "iwconfig essid off" command */ else { @@ -1880,7 +1913,7 @@ wl_iw_set_essid( WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error)); return error; } - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTING); } return 0; } @@ -2540,7 +2573,6 @@ 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)); @@ -2666,8 +2698,7 @@ 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; + wl_iw_update_connect_status(dev, WL_EXT_STATUS_ADD_KEY); } return 0; } @@ -3458,11 +3489,20 @@ 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); + 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) + if (dhd && dhd->iscan) { iscan = (iscan_info_t *)dhd->iscan; + conn_info = &iscan->conn_info; + } #endif memset(&wrqu, 0, sizeof(wrqu)); @@ -3481,13 +3521,21 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) case WLC_E_REASSOC_IND: cmd = IWEVREGISTERED; break; + case WLC_E_DEAUTH: + case WLC_E_DISASSOC: + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED); + printf("%s: disconnected with "MACSTR", event %d, reason %d\n", + __FUNCTION__, MAC2STR((u8 *)wrqu.addr.sa_data), event_type, reason); + break; case WLC_E_DEAUTH_IND: case WLC_E_DISASSOC_IND: cmd = SIOCGIWAP; wrqu.data.length = strlen(extra); bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED); + printf("%s: disconnected with "MACSTR", event %d, reason %d\n", + __FUNCTION__, MAC2STR((u8 *)wrqu.addr.sa_data), event_type, reason); break; case WLC_E_LINK: @@ -3497,7 +3545,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) 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); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED); } else { printf("%s: Link UP with "MACSTR"\n", __FUNCTION__, MAC2STR((u8 *)wrqu.addr.sa_data)); @@ -4035,6 +4083,14 @@ _iscan_sysioc_thread(void *data) complete_and_exit(&iscan->sysioc_exited, 0); } +void wl_iw_down(dhd_pub_t *dhdp) +{ + iscan_info_t *iscan = dhdp->iscan; + + if (iscan) + wl_ext_add_remove_pm_enable_work(&iscan->conn_info, FALSE); +} + int wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) { @@ -4056,6 +4112,8 @@ wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) iscan->sysioc_pid = -1; /* we only care about main interface so save a global here */ iscan->dev = dev; + iscan->conn_info.dev = dev; + iscan->conn_info.dhd = dhdp; iscan->iscan_state = ISCAN_STATE_IDLE; /* Set up the timer */ @@ -4078,6 +4136,8 @@ wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) #endif if (iscan->sysioc_pid < 0) return -ENOMEM; + mutex_init(&iscan->conn_info.pm_sync); + INIT_DELAYED_WORK(&iscan->conn_info.pm_enable_work, wl_ext_pm_work_handler); return 0; } @@ -4091,6 +4151,7 @@ void wl_iw_detach(dhd_pub_t *dhdp) KILL_PROC(iscan->sysioc_pid, SIGTERM); wait_for_completion(&iscan->sysioc_exited); } + wl_ext_add_remove_pm_enable_work(&iscan->conn_info, FALSE); while (iscan->list_hdr) { buf = iscan->list_hdr->next; diff --git a/bcmdhd.100.10.315.x/wl_iw.h b/bcmdhd.100.10.315.x/wl_iw.h index 0adba1b..b00a489 100644 --- a/bcmdhd.100.10.315.x/wl_iw.h +++ b/bcmdhd.100.10.315.x/wl_iw.h @@ -132,6 +132,7 @@ int wl_iw_handle_scanresults_ies(char **event_p, char *end, #else int wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp); void wl_iw_detach(dhd_pub_t *dhdp); +void wl_iw_down(dhd_pub_t *dhdp); #endif #define CSCAN_COMMAND "CSCAN " diff --git a/bcmdhd.100.10.315.x/wldev_common.c b/bcmdhd.100.10.315.x/wldev_common.c index ac72f96..398c54a 100644 --- a/bcmdhd.100.10.315.x/wldev_common.c +++ b/bcmdhd.100.10.315.x/wldev_common.c @@ -471,7 +471,6 @@ int wldev_set_country( int error = -1; wl_country_t cspec = {{0}, 0, {0}}; scb_val_t scbval; - char smbuf[WLC_IOCTL_SMLEN]; #ifdef WL_CFG80211 struct wireless_dev *wdev = ndev_to_wdev(dev); struct wiphy *wiphy = wdev->wiphy; @@ -518,8 +517,7 @@ int wldev_set_country( error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec); if (error) dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec); - error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), - smbuf, sizeof(smbuf), NULL); + error = dhd_conf_set_country(dhd_get_pub(dev), &cspec); if (error < 0) { WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n", __FUNCTION__, country_code, cspec.ccode, cspec.rev)); -- 2.20.1