From 32c27b7a16bf4c1595862b9a1a3c62c2eca19860 Mon Sep 17 00:00:00 2001 From: Rongjun Chen Date: Mon, 8 Oct 2018 19:47:16 +0800 Subject: [PATCH] wifi: fix wifi close issue and ap62x8 open fail issue PD# 174173 root cause: interrupt not enabled when ctrl cmd comming in some conner case solution: enable the interrupt when ctrl command is comming Change-Id: Ief804d124150cbfe9ec1134c527bdb536b8375a0 Signed-off-by: Rongjun Chen --- bcmdhd.1.579.77.41.1.cn/Makefile | 0 bcmdhd.1.579.77.41.1.cn/dbus.c | 2 +- bcmdhd.1.579.77.41.1.cn/dhd_config.c | 59 ++++++- bcmdhd.1.579.77.41.1.cn/dhd_config.h | 14 +- bcmdhd.1.579.77.41.1.cn/dhd_gpio.c | 5 +- bcmdhd.1.579.77.41.1.cn/dhd_ip.c | 4 +- bcmdhd.1.579.77.41.1.cn/dhd_linux.c | 73 ++------- bcmdhd.1.579.77.41.1.cn/dhd_sdio.c | 35 ++-- bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c | 1 - bcmdhd.1.579.77.41.1.cn/wl_android_ext.c | 148 ++++++++++++----- bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c | 197 ++++++++++++++++------- bcmdhd.1.579.77.41.1.cn/wl_cfg80211.h | 15 ++ 12 files changed, 364 insertions(+), 189 deletions(-) mode change 100755 => 100644 bcmdhd.1.579.77.41.1.cn/Makefile diff --git a/bcmdhd.1.579.77.41.1.cn/Makefile b/bcmdhd.1.579.77.41.1.cn/Makefile old mode 100755 new mode 100644 diff --git a/bcmdhd.1.579.77.41.1.cn/dbus.c b/bcmdhd.1.579.77.41.1.cn/dbus.c index cea6c7f..1f040e7 100644 --- a/bcmdhd.1.579.77.41.1.cn/dbus.c +++ b/bcmdhd.1.579.77.41.1.cn/dbus.c @@ -1442,7 +1442,7 @@ dbus_attach(osl_t *osh, int rxsize, int nrxq, int ntxq, dhd_pub_t *pub, dhd_bus = MALLOC(osh, sizeof(dhd_bus_t)); if (dhd_bus == NULL) { - DBUSERR(("%s: malloc failed %d\n", __FUNCTION__, (int)sizeof(dhd_bus_t))); + DBUSERR(("%s: malloc failed %zu\n", __FUNCTION__, sizeof(dhd_bus_t))); return NULL; } 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 798fc6b..27d0e9d 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_config.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_config.c @@ -1215,6 +1215,39 @@ dhd_conf_set_ap_in_suspend(dhd_pub_t *dhd, int suspend) return mode; } +void +dhd_conf_set_eapol_status(dhd_pub_t *dhd, char *ifname, char *dump_data) +{ + unsigned char type; + int pair, ack, mic, kerr, req, sec, install; + unsigned short us_tmp; + + if (!(dhd->conf->in4way&DONT_DELETE_GC_AFTER_WPS) || strncmp(ifname, "p2p", 3)) { + return; + } + + type = dump_data[15]; + if ((type == 0) && (dump_data[22] == 254) && (dump_data[30] == 5)) { + dhd->conf->eapol_status = EAPOL_STATUS_WPS_DONE; + CONFIG_TRACE(("EAP Packet, WSC Done\n")); + } else if (type == 3 && dump_data[18] == 2) { + us_tmp = (dump_data[19] << 8) | dump_data[20]; + pair = 0 != (us_tmp & 0x08); + ack = 0 != (us_tmp & 0x80); + mic = 0 != (us_tmp & 0x100); + kerr = 0 != (us_tmp & 0x400); + req = 0 != (us_tmp & 0x800); + sec = 0 != (us_tmp & 0x200); + install = 0 != (us_tmp & 0x40); + if (pair && !install && !ack && mic && sec && !req && !kerr) { + dhd->conf->eapol_status = EAPOL_STATUS_M4; + CONFIG_TRACE(("EAPOL Packet, 4-way handshake, M4\n")); + } + } + + return; +} + #ifdef PROP_TXSTATUS int dhd_conf_get_disable_proptx(dhd_pub_t *dhd) @@ -1974,6 +2007,7 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->sd_f2_blocksize = (int)simple_strtol(data, NULL, 10); printf("%s: sd_f2_blocksize = %d\n", __FUNCTION__, conf->sd_f2_blocksize); } +#if defined(HW_OOB) else if (!strncmp("oob_enabled_later=", full_param, len_param)) { if (!strncmp(data, "0", 1)) conf->oob_enabled_later = FALSE; @@ -1981,6 +2015,7 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->oob_enabled_later = TRUE; printf("%s: oob_enabled_later = %d\n", __FUNCTION__, conf->oob_enabled_later); } +#endif else if (!strncmp("dpc_cpucore=", full_param, len_param)) { conf->dpc_cpucore = (int)simple_strtol(data, NULL, 10); printf("%s: dpc_cpucore = %d\n", __FUNCTION__, conf->dpc_cpucore); @@ -2027,7 +2062,7 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len); } else if (!strncmp("txctl_tmo_fix=", full_param, len_param)) { - conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 10); + conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 0); printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix); } else if (!strncmp("tx_max_offset=", full_param, len_param)) { @@ -2268,6 +2303,10 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) conf->in4way = (int)simple_strtol(data, NULL, 0); printf("%s: in4way = 0x%x\n", __FUNCTION__, conf->in4way); } + else if (!strncmp("max_wait_gc_time=", full_param, len_param)) { + conf->max_wait_gc_time = (int)simple_strtol(data, NULL, 0); + printf("%s: max_wait_gc_time = %d\n", __FUNCTION__, conf->max_wait_gc_time); + } else if (!strncmp("wl_preinit=", full_param, len_param)) { if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) { CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); @@ -2530,8 +2569,8 @@ dhd_conf_set_wl_preinit(dhd_pub_t *dhd, char *data) char name[32], *pch, *pick_tmp, *pick_tmp2; /* Process wl_preinit: - * wl_preinit=[cmd]/[val], [cmd]/[val] \ - * Ex: wl_preinit=86/0, mpc/0 + * wl_preinit=[cmd]=[val], [cmd]=[val] + * Ex: wl_preinit=86=0, mpc=0 */ pick_tmp = data; while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) { @@ -2701,13 +2740,15 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->txglom_ext = FALSE; conf->tx_max_offset = 0; conf->txglomsize = SDPCM_DEFGLOM_SIZE; - conf->txctl_tmo_fix = 300; + conf->txctl_tmo_fix = -1; conf->txglom_mode = SDPCM_TXGLOM_CPY; conf->deferred_tx_len = 0; conf->dhd_txminmax = 1; conf->txinrx_thres = -1; conf->sd_f2_blocksize = 0; +#if defined(HW_OOB) conf->oob_enabled_later = FALSE; +#endif conf->orphan_move = 0; #endif #ifdef BCMPCIE @@ -2747,6 +2788,7 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->ctrl_resched = 2; conf->dhd_ioctl_timeout_msec = 0; conf->in4way = NO_SCAN_IN4WAY; + conf->max_wait_gc_time = 300; #ifdef ISAM_PREINIT memset(conf->isam_init, 0, sizeof(conf->isam_init)); memset(conf->isam_config, 0, sizeof(conf->isam_config)); @@ -2758,9 +2800,11 @@ dhd_conf_preinit(dhd_pub_t *dhd) #ifdef CUSTOMER_HW_AMLOGIC dhd_slpauto = FALSE; #endif - if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || - conf->chip == BCM4371_CHIP_ID || conf->chip == BCM43569_CHIP_ID || - conf->chip == BCM4359_CHIP_ID || conf->chip == BCM4362_CHIP_ID) { + if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID || + conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || + conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID || + conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID || + conf->chip == BCM4362_CHIP_ID) { #ifdef DHDTCPACK_SUPPRESS #ifdef BCMSDIO conf->tcpack_sup_mode = TCPACK_SUP_REPLACE; @@ -2776,7 +2820,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->dhd_txminmax = -1; conf->txinrx_thres = 128; conf->sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE; - conf->oob_enabled_later = TRUE; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) conf->orphan_move = 1; #else diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_config.h b/bcmdhd.1.579.77.41.1.cn/dhd_config.h index 8d592ff..ad47271 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_config.h +++ b/bcmdhd.1.579.77.41.1.cn/dhd_config.h @@ -103,7 +103,14 @@ typedef struct mchan_params { enum in4way_flags { NO_SCAN_IN4WAY = (1 << (0)), - NO_BTC_IN4WAY = (1 << (1)) + NO_BTC_IN4WAY = (1 << (1)), + DONT_DELETE_GC_AFTER_WPS = (1 << (2)) +}; + +enum eapol_status { + EAPOL_STATUS_NONE = 0, + EAPOL_STATUS_WPS_DONE, + EAPOL_STATUS_M4 }; typedef struct dhd_conf { @@ -204,7 +211,9 @@ typedef struct dhd_conf { struct mchan_params mchan[MCHAN_MAX_NUM]; char *wl_preinit; int tsq; + uint eapol_status; uint in4way; + uint max_wait_gc_time; } dhd_conf_t; #ifdef BCMSDIO @@ -243,6 +252,9 @@ int dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev); uint dhd_conf_get_chip(void *context); uint dhd_conf_get_chiprev(void *context); int dhd_conf_get_pm(dhd_pub_t *dhd); +void dhd_conf_set_eapol_status(dhd_pub_t *dhd, char *ifname, + char *dump_data); + #ifdef PROP_TXSTATUS int dhd_conf_get_disable_proptx(dhd_pub_t *dhd); #endif diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c b/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c index 525a4b9..d2b53b1 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c @@ -335,9 +335,10 @@ int dhd_wlan_init_gpio(void) dhd_wlan_resources[0].start = dhd_wlan_resources[0].end = host_oob_irq; dhd_wlan_resources[0].flags = host_oob_irq_flags; - printf("%s: WL_REG_ON=%d, WL_HOST_WAKE=%d\n", __FUNCTION__, gpio_wl_reg_on, gpio_wl_host_wake); - printf("%s: oob_irq=%d, oob_irq_flags=0x%x\n", __FUNCTION__, host_oob_irq, host_oob_irq_flags); + printf("%s: WL_HOST_WAKE=%d, oob_irq=%d, oob_irq_flags=0x%x\n", __FUNCTION__, + gpio_wl_host_wake, host_oob_irq, host_oob_irq_flags); #endif /* CUSTOMER_OOB */ + printf("%s: WL_REG_ON=%d\n", __FUNCTION__, gpio_wl_reg_on); return 0; } diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_ip.c b/bcmdhd.1.579.77.41.1.cn/dhd_ip.c index d8be26c..47cfe8a 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_ip.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_ip.c @@ -378,8 +378,8 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) goto exit; } - DHD_TRACE(("%s: TCP ACK Suppress mode %d -> mode %d\n", - __FUNCTION__, dhdp->tcpack_sup_mode, mode)); + printf("%s: TCP ACK Suppress mode %d -> mode %d\n", + __FUNCTION__, dhdp->tcpack_sup_mode, mode); /* Pre-process routines to change a new mode as per previous mode */ switch (prev_mode) { diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_linux.c b/bcmdhd.1.579.77.41.1.cn/dhd_linux.c index cde2666..0264224 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_linux.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_linux.c @@ -4696,38 +4696,25 @@ static const char *_get_packet_type_str(uint16 type) return packet_type_info[n].str; } -#endif /* DHD_RX_DUMP || DHD_TX_DUMP */ -#if defined(DHD_TX_DUMP) void -dhd_tx_dump(struct net_device *ndev, osl_t *osh, void *pkt) +dhd_trx_dump(struct net_device *ndev, uint8 *dump_data, uint datalen, bool tx) { - uint8 *dump_data; uint16 protocol; char *ifname; - dump_data = PKTDATA(osh, pkt); protocol = (dump_data[12] << 8) | dump_data[13]; ifname = ndev ? ndev->name : "N/A"; - DHD_ERROR(("TX DUMP[%s] - %s\n", ifname, _get_packet_type_str(protocol))); - -#if defined(DHD_TX_FULL_DUMP) - { - int i; - uint datalen; - datalen = PKTLEN(osh, pkt); - - for (i = 0; i < datalen; i++) { - printk("%02X ", dump_data[i]); - if ((i & 15) == 15) - printk("\n"); - } - printk("\n"); + if (protocol != ETHER_TYPE_BRCM) { + DHD_ERROR(("%s DUMP[%s] - %s\n", tx?"Tx":"Rx", ifname, + _get_packet_type_str(protocol))); +#if defined(DHD_TX_FULL_DUMP) || defined(DHD_RX_FULL_DUMP) + prhex("Data", dump_data, datalen); +#endif /* DHD_TX_FULL_DUMP || DHD_RX_FULL_DUMP */ } -#endif /* DHD_TX_FULL_DUMP */ } -#endif /* DHD_TX_DUMP */ +#endif /* DHD_TX_DUMP || DHD_RX_DUMP */ /* This routine do not support Packet chain feature, Currently tested for * proxy arp feature @@ -4890,6 +4877,7 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) #if defined(DHD_8021X_DUMP) dhd_dump_eapol_4way_message(dhd_ifname(dhdp, ifidx), pktdata, TRUE); #endif /* DHD_8021X_DUMP */ + dhd_conf_set_eapol_status(dhdp, dhd_ifname(dhdp, ifidx), pktdata); } if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { @@ -4942,7 +4930,8 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) #endif #if defined(DHD_TX_DUMP) - dhd_tx_dump(dhd_idx2net(dhdp, ifidx), dhdp->osh, pktbuf); + dhd_trx_dump(dhd_idx2net(dhdp, ifidx), PKTDATA(dhdp->osh, pktbuf), + PKTLEN(dhdp->osh, pktbuf), TRUE); #endif /* terence 20150901: Micky add to ajust the 802.1X priority */ /* Set the 802.1X packet with the highest priority 7 */ @@ -5717,10 +5706,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) void *skbhead = NULL; void *skbprev = NULL; uint16 protocol; -#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) || defined(DHD_DHCP_DUMP) || \ - defined(DHD_ICMP_DUMP) || defined(DHD_WAKE_STATUS) unsigned char *dump_data; -#endif /* DHD_RX_DUMP || DHD_8021X_DUMP || DHD_DHCP_DUMP || DHD_ICMP_DUMP || DHD_WAKE_STATUS */ #ifdef DHD_MCAST_REGEN uint8 interface_role; if_flow_lkup_t *if_flow_lkup; @@ -5951,10 +5937,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) eth = skb->data; len = skb->len; -#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) || defined(DHD_DHCP_DUMP) || \ - defined(DHD_ICMP_DUMP) || defined(DHD_WAKE_STATUS) dump_data = skb->data; -#endif /* DHD_RX_DUMP || DHD_8021X_DUMP || DHD_DHCP_DUMP || DHD_ICMP_DUMP || DHD_WAKE_STATUS */ protocol = (skb->data[12] << 8) | skb->data[13]; if (protocol == ETHER_TYPE_802_1X) { @@ -5962,6 +5945,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #ifdef DHD_8021X_DUMP dhd_dump_eapol_4way_message(dhd_ifname(dhdp, ifidx), dump_data, FALSE); #endif /* DHD_8021X_DUMP */ + dhd_conf_set_eapol_status(dhdp, dhd_ifname(dhdp, ifidx), dump_data); } if (protocol != ETHER_TYPE_BRCM && protocol == ETHER_TYPE_IP) { @@ -5973,33 +5957,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* DHD_ICMP_DUMP */ } #ifdef DHD_RX_DUMP - DHD_ERROR(("RX DUMP[%s] - %s\n", - dhd_ifname(dhdp, ifidx), _get_packet_type_str(protocol))); - if (protocol != ETHER_TYPE_BRCM) { - if (dump_data[0] == 0xFF) { - DHD_ERROR(("%s: BROADCAST\n", __FUNCTION__)); - - if ((dump_data[12] == 8) && - (dump_data[13] == 6)) { - DHD_ERROR(("%s: ARP %d\n", - __FUNCTION__, dump_data[0x15])); - } - } else if (dump_data[0] & 1) { - DHD_ERROR(("%s: MULTICAST: " MACDBG "\n", - __FUNCTION__, MAC2STRDBG(dump_data))); - } -#ifdef DHD_RX_FULL_DUMP - { - int k; - for (k = 0; k < skb->len; k++) { - printk("%02X ", dump_data[k]); - if ((k & 15) == 15) - printk("\n"); - } - printk("\n"); - } -#endif /* DHD_RX_FULL_DUMP */ - } + dhd_trx_dump(dhd_idx2net(dhdp, ifidx), dump_data, skb->len, FALSE); #endif /* DHD_RX_DUMP */ #if defined(DHD_WAKE_STATUS) && defined(DHD_WAKEPKT_DUMP) if (pkt_wake) { @@ -7791,12 +7749,12 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) goto done; } } - +/* if (!capable(CAP_NET_ADMIN)) { bcmerror = BCME_EPERM; goto done; } - +*/ /* Take backup of ioc.buf and restore later */ ioc_buf_user = ioc.buf; @@ -10996,7 +10954,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_TRACE(("Enter %s\n", __FUNCTION__)); #ifdef DHDTCPACK_SUPPRESS - printf("%s: Set tcpack_sup_mode %d\n", __FUNCTION__, dhd->conf->tcpack_sup_mode); dhd_tcpack_suppress_set(dhd, dhd->conf->tcpack_sup_mode); #endif dhd->op_mode = 0; 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 ea32a6b..fb6150f 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c @@ -437,7 +437,7 @@ typedef struct dhd_bus { #endif /* defined (BT_OVER_SDIO) */ uint txglomframes; /* Number of tx glom frames (superframes) */ uint txglompkts; /* Number of packets from tx glom frames */ - uint8 *membuf; /* Buffer for receiving big glom packet */ + uint8 *membuf; /* Buffer for dhdsdio_membytes */ } dhd_bus_t; @@ -2762,13 +2762,15 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) /* Need to lock here to protect txseq and SDIO tx calls */ + dhd_os_sdlock(bus->dhd); if (bus->dhd->conf->txctl_tmo_fix > 0 && !TXCTLOK(bus)) { bus->ctrl_wait = TRUE; + dhd_os_sdunlock(bus->dhd); wait_event_interruptible_timeout(bus->ctrl_tx_wait, TXCTLOK(bus), msecs_to_jiffies(bus->dhd->conf->txctl_tmo_fix)); + dhd_os_sdlock(bus->dhd); bus->ctrl_wait = FALSE; } - dhd_os_sdlock(bus->dhd); BUS_WAKE(bus); @@ -3361,6 +3363,7 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint s int bcmerror = 0; uint32 sdaddr; uint dsize; + uint8 *pdata; /* In remap mode, adjust address beyond socram and redirect * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize @@ -3377,10 +3380,6 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint s dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); else dsize = size; - if (dsize > MAX_MEM_BUF) { - DHD_ERROR(("%s: dsize %d > %d\n", __FUNCTION__, dsize, MAX_MEM_BUF)); - goto xfer_done; - } /* Set the backplane window to include the start address */ if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { @@ -3393,14 +3392,20 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint s DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n", __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK))); - if (write) - memcpy(bus->membuf, data, dsize); - if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, bus->membuf, dsize))) { + if (dsize <= MAX_MEM_BUF) { + pdata = bus->membuf; + if (write) + memcpy(bus->membuf, data, dsize); + } else { + pdata = data; + } + if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, pdata, dsize))) { DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__)); break; } - if (!write) + if (dsize <= MAX_MEM_BUF && !write) { memcpy(data, bus->membuf, dsize); + } /* Adjust for next transfer (if any) */ if ((size -= dsize)) { @@ -6605,7 +6610,7 @@ dhdsdio_dpc(dhd_bus_t *bus) goto clkwait; /* Pending interrupt indicates new device status */ - if (bus->ipend) { + if (bus->ipend || (bus->ctrl_frame_stat && bus->dhd->conf->txctl_tmo_fix)) { bus->ipend = FALSE; #if defined(BT_OVER_SDIO) bcmsdh_btsdio_process_f3_intr(); @@ -6728,7 +6733,8 @@ clkwait: * or clock availability. (Allows tx loop to check ipend if desired.) * (Unless register access seems hosed, as we may not be able to ACK...) */ - if (!bus->dhd->conf->oob_enabled_later && bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) { + if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) && + !(bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) { DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n", __FUNCTION__, rxdone, framecnt)); bus->intdis = FALSE; @@ -6786,7 +6792,7 @@ clkwait: } /* Resched the DPC if ctrl cmd is pending on bus credit */ if (bus->ctrl_frame_stat) { - if (bus->dhd->conf->txctl_tmo_fix > 0) { + if (bus->dhd->conf->txctl_tmo_fix) { set_current_state(TASK_INTERRUPTIBLE); if (!kthread_should_stop()) schedule_timeout(1); @@ -6834,7 +6840,8 @@ exit: * or clock availability. (Allows tx loop to check ipend if desired.) * (Unless register access seems hosed, as we may not be able to ACK...) */ - if (bus->dhd->conf->oob_enabled_later && bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) { + if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) && + (bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) { DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n", __FUNCTION__, rxdone, framecnt)); bus->intdis = FALSE; diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c b/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c index 2bf784c..a0f0a2a 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c @@ -272,7 +272,6 @@ int bcmdhd_init_wlan_mem(void) { int i; int j; - printk(KERN_ERR "%s(): %s\n", __func__, DHD_STATIC_VERSION_STR); for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) { diff --git a/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c b/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c index bf901ea..3159d4c 100644 --- a/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c +++ b/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c @@ -3020,66 +3020,126 @@ wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len) } #endif +static int +wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command, + int total_len) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wl_config_t rsdb_mode_cfg = {1, 0}, *rsdb_p; + int ret = 0; + + ANDROID_TRACE(("%s: Enter\n", __FUNCTION__)); + + if (data) { + rsdb_mode_cfg.config = (int)simple_strtol(data, NULL, 0); + ret = wl_ext_iovar_setbuf(dev, "rsdb_mode", (char *)&rsdb_mode_cfg, + sizeof(rsdb_mode_cfg), iovar_buf, WLC_IOCTL_SMLEN, NULL); + printf("%s: rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config); + } else { + ret = wl_ext_iovar_getbuf(dev, "rsdb_mode", NULL, 0, + iovar_buf, WLC_IOCTL_SMLEN, NULL); + if (!ret) { + rsdb_p = (wl_config_t *) iovar_buf; + ret = snprintf(command, total_len, "%d", rsdb_p->config); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, + command)); + } + } + + return ret; +} + +typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command, + int total_len); + +typedef struct wl_ext_iovar_tpl_t { + int get; + int set; + char *name; + wl_ext_tpl_parse_t *parse; +} wl_ext_iovar_tpl_t; + +const wl_ext_iovar_tpl_t wl_ext_iovar_tpl_list[] = { + {WLC_GET_VAR, WLC_SET_VAR, "rsdb_mode", wl_ext_rsdb_mode}, +}; + /* -dhd_priv dhd [string] ==> Not ready -1. Get dhd val: - Ex: dhd_priv dhd bussleep -2. Set dhd val: - Ex: dhd_priv dhd bussleep 1 - -dhd_priv wl [WLC_GET_PM] ==> Ready to get int val -dhd_priv wl [WLC_SET_PM] [int] ==> Ready to set int val -dhd_priv wl [string] ==> Ready to get int val -dhd_priv wl [string] [int] ==> Ready to set int val -Ex: get/set WLC_PM +Ex: dhd_priv wl [cmd] [val] dhd_priv wl 85 dhd_priv wl 86 1 -Ex: get/set mpc dhd_priv wl mpc dhd_priv wl mpc 1 */ int -wl_ext_iovar(struct net_device *dev, char *command, int total_len) +wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len) { - int ret = 0; - char wl[3]="\0", arg[20]="\0", cmd_str[20]="\0", val_str[20]="\0"; - int cmd=-1, val=0; + int cmd, val, ret = -1, i; + char name[32], *pch, *pick_tmp, *data; int bytes_written=-1; + const wl_ext_iovar_tpl_t *tpl = wl_ext_iovar_tpl_list; + int tpl_count = ARRAY_SIZE(wl_ext_iovar_tpl_list); ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + pick_tmp = command; - sscanf(command, "%s %d %s", wl, &cmd, arg); - if (cmd < 0) - sscanf(command, "%s %s %s", wl, cmd_str, val_str); - - if (!strcmp(wl, "wl")) { - if (cmd>=0 && cmd!=WLC_GET_VAR && cmd!=WLC_SET_VAR) { - ret = sscanf(arg, "%d", &val); - if (ret > 0) { // set - ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), TRUE); - } else { // get - ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), FALSE); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } + pch = bcmstrtok(&pick_tmp, " ", 0); // pick wl + if (!pch || strncmp(pch, "wl", 2)) + goto exit; + + pch = bcmstrtok(&pick_tmp, " ", 0); // pick cmd + if (!pch) + goto exit; + + memset(name, 0 , sizeof (name)); + cmd = (int)simple_strtol(pch, NULL, 0); + if (cmd == 0) { + strcpy(name, pch); + } + data = bcmstrtok(&pick_tmp, " ", 0); // pick data + if (data && cmd == 0) { + cmd = WLC_SET_VAR; + } else if (cmd == 0) { + cmd = WLC_GET_VAR; + } + + /* look for a matching code in the table */ + for (i = 0; i < tpl_count; i++, tpl++) { + if ((tpl->get == cmd || tpl->set == cmd) && !strcmp(tpl->name, name)) + break; + } + if (i < tpl_count && tpl->parse) { + ret = tpl->parse(dev, data, command, total_len); + } else { + if (cmd == WLC_SET_VAR) { + val = (int)simple_strtol(data, NULL, 0); + ANDROID_TRACE(("%s: set %s %d\n", __FUNCTION__, name, val)); + ret = wl_ext_iovar_setint(dev, name, val); + } else if (cmd == WLC_GET_VAR) { + ANDROID_TRACE(("%s: get %s\n", __FUNCTION__, name)); + ret = wl_ext_iovar_getint(dev, name, &val); + if (!ret) { + bytes_written = snprintf(command, total_len, "%d", val); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, + command)); + ret = bytes_written; } - } else if (strlen(cmd_str)) { - ret = sscanf(val_str, "%d", &val); - if (ret > 0) { // set - ret = wl_ext_iovar_setint(dev, cmd_str, val); - } else { // get - ret = wl_ext_iovar_getint(dev, cmd_str, &val); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } + } else if (data) { + val = (int)simple_strtol(data, NULL, 0); + ANDROID_TRACE(("%s: set %d %d\n", __FUNCTION__, cmd, val)); + ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), TRUE); + } else { + ANDROID_TRACE(("%s: get %d\n", __FUNCTION__, cmd)); + ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), FALSE); + if (!ret) { + bytes_written = snprintf(command, total_len, "%d", val); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, + command)); + ret = bytes_written; } } } +exit: return ret; } @@ -3159,7 +3219,7 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, } #endif else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) { - *bytes_written = wl_ext_iovar(net, command, total_len); + *bytes_written = wl_ext_wl_iovar(net, command, total_len); } else ret = -1; 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 eb4e338..777ac49 100644 --- a/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c +++ b/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c @@ -912,6 +912,8 @@ extern int dhd_wait_pend8021x(struct net_device *dev); #ifdef PROP_TXSTATUS_VSDB extern int disable_proptx; #endif /* PROP_TXSTATUS_VSDB */ +static int wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, + struct net_device *dev, uint action, enum wl_ext_status status, void *context); extern int passive_channel_skip; @@ -3323,53 +3325,6 @@ scan_out: return err; } -void -wl_cfg80211_4way_start(struct bcm_cfg80211 *cfg, struct net_device *dev) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); - struct wl_security *sec; - s32 bssidx = -1; - - bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr); - - sec = wl_read_prof(cfg, dev, WL_PROF_SEC); - if ((sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) && - bssidx == 0 && dhdp->conf->in4way) { - WL_DBG(("Enter in4way=0x%x\n", dhdp->conf->in4way)); - cfg->handshaking = 1; - if (dhdp->conf->in4way & NO_BTC_IN4WAY) - wldev_iovar_setint(dev, "btc_mode", 0); - } -} - -void -wl_cfg80211_4way_exit(struct bcm_cfg80211 *cfg, struct net_device *dev) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); - - if (cfg->handshaking) { - WL_DBG(("Enter in4way=0x%x\n", dhdp->conf->in4way)); - if (dhdp->conf->in4way & NO_BTC_IN4WAY) - wldev_iovar_setint(dev, "btc_mode", 1); - cfg->handshaking = 0; - } -} - -s32 -wl_cfg80211_4way_check(struct bcm_cfg80211 *cfg, uint mode) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); - - if (cfg->handshaking && (dhdp->conf->in4way & mode)) { - if (mode & NO_SCAN_IN4WAY && cfg->handshaking <= 3) { - WL_ERR(("%s: return -EBUSY cnt %d\n", __FUNCTION__, cfg->handshaking)); - cfg->handshaking++; - return -EBUSY; - } - } - return 0; -} - static s32 #if defined(WL_CFG80211_P2P_DEV_IF) wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) @@ -3401,7 +3356,8 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, return -ENODEV; } } - err = wl_cfg80211_4way_check(cfg, NO_SCAN_IN4WAY); + err = wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_SCAN, NULL); if (err) return err; @@ -5763,7 +5719,8 @@ exit: wl_clr_drv_status(cfg, CONNECTING, dev); } if (!err) - wl_cfg80211_4way_start(cfg, dev); + wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_CONNECTING, NULL); #ifdef WLTDLS /* disable TDLS if number of connected interfaces is >= 1 */ @@ -6216,7 +6173,8 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr)); return BCME_ERROR; } - wl_cfg80211_4way_exit(cfg, dev); + wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_4WAY_DONE, NULL); if (mac_addr && ((params->cipher != WLAN_CIPHER_SUITE_WEP40) && @@ -9574,6 +9532,7 @@ wl_cfg80211_del_station( u16 rc = params->reason_code; #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */ #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */ + WL_DBG(("Entry\n")); if (mac_addr == NULL) { WL_DBG(("mac_addr is NULL ignore it\n")); @@ -9591,6 +9550,11 @@ wl_cfg80211_del_station( return -EFAULT; } } + err = wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_DELETE_GC, (void *)mac_addr); + if (err) { + return 0; + } assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV; err = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST, @@ -11740,13 +11704,19 @@ exit: sinfo.assoc_req_ies = data; sinfo.assoc_req_ies_len = len; printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_GC_CONNECTED, NULL); cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); } else if (event == WLC_E_DISASSOC_IND) { printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_GC_DISCONNECTED, NULL); cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); } else if ((event == WLC_E_DEAUTH_IND) || ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) { printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, + WL_EXT_STATUS_GC_DISCONNECTED, NULL); cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); } #endif @@ -12367,7 +12337,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, "event : %d, reason=%d from " MACDBG "\n", ndev->name, event, ntoh32(e->reason), MAC2STRDBG((const u8*)(&e->addr))); - wl_cfg80211_4way_exit(cfg, ndev); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_DISCONNECTED, NULL); /* roam offload does not sync BSSID always, get it from dongle */ if (cfg->roam_offload) { @@ -12474,7 +12445,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, } else if (wl_get_drv_status(cfg, CONNECTING, ndev)) { printf("link down, during connecting\n"); - wl_cfg80211_4way_exit(cfg, ndev); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_DISCONNECTED, NULL); /* Issue WLC_DISASSOC to prevent FW roam attempts */ err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0); if (err < 0) { @@ -12505,7 +12477,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, } else if (wl_is_nonetwork(cfg, e)) { printf("connect failed event=%d e->status %d e->reason %d \n", event, (int)ntoh32(e->status), (int)ntoh32(e->reason)); - wl_cfg80211_4way_exit(cfg, ndev); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_DISCONNECTED, NULL); #if defined(DHD_ENABLE_BIGDATA_LOGGING) if (event == WLC_E_SET_SSID) { wl_get_connect_failed_status(cfg, e); @@ -13383,7 +13356,8 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, dhd_conf_set_wme(cfg->pub, 0); } else { WL_ERR(("Report connect result - connection failed\n")); - wl_cfg80211_4way_exit(cfg, ndev); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_DISCONNECTED, NULL); } } #ifdef CONFIG_TCPACK_FASTTX @@ -15122,6 +15096,7 @@ exit: } #endif /* WL_DRV_AVOID_SCANCACHE */ + static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data) { @@ -15275,7 +15250,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, goto exit; } #ifdef ESCAN_BUF_OVERFLOW_MGMT - WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n", + WL_SCAN(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n", bss->SSID, MAC2STRDBG(bss->BSSID.octet), i, bss->RSSI, list->count)); @@ -15405,7 +15380,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE); cfg->bss_list = wl_escan_get_buf(cfg, FALSE); if (!scan_req_match(cfg)) { - WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n", + WL_SCAN(("SCAN COMPLETED: scanned AP count=%d\n", cfg->bss_list->count)); } wl_inform_bss(cfg); @@ -15742,6 +15717,7 @@ static s32 wl_init_priv(struct bcm_cfg80211 *cfg) spin_lock_init(&cfg->cfgdrv_lock); mutex_init(&cfg->ioctl_buf_sync); init_waitqueue_head(&cfg->netif_change_event); + init_waitqueue_head(&cfg->wps_done_event); init_completion(&cfg->send_af_done); init_completion(&cfg->iface_disable); mutex_init(&cfg->usr_sync); @@ -15749,6 +15725,7 @@ static s32 wl_init_priv(struct bcm_cfg80211 *cfg) mutex_init(&cfg->scan_complete); mutex_init(&cfg->if_sync); mutex_init(&cfg->pm_sync); + mutex_init(&cfg->in4way_sync); #ifdef WLTDLS mutex_init(&cfg->tdls_sync); #endif /* WLTDLS */ @@ -17083,7 +17060,8 @@ s32 wl_cfg80211_up(struct net_device *net) return BCME_VERSION; } ioctl_version = val; - wl_cfg80211_4way_exit(cfg, net); + wl_cfg80211_check_in4way(cfg, net, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, + WL_EXT_STATUS_DISCONNECTED, NULL); WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version)); mutex_lock(&cfg->usr_sync); @@ -21753,7 +21731,8 @@ wl_set_rssi_logging(struct net_device *dev, void *param) } #endif /* SUPPORT_RSSI_LOGGING */ -s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len) +s32 +wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len) { struct bcm_cfg80211 *cfg = wl_get_cfg(dev); int ret = 0; @@ -21773,3 +21752,105 @@ s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len return ret; } + +static int +wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, + struct net_device *dev, uint action, enum wl_ext_status status, void *context) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); + struct wl_security *sec; + s32 bssidx = -1; + int ret = 0; + int max_wait_gc_time = dhdp->conf->max_wait_gc_time; + + if (!(dhdp->conf->in4way & action)) + return 0; + + mutex_lock(&cfg->in4way_sync); + WL_DBG(("status=%d, action=0x%x\n", status, action)); + + switch (status) { + case WL_EXT_STATUS_SCAN: + if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { + if (cfg->handshaking > 0 && cfg->handshaking <= 3) { + WL_ERR(("%s: return -EBUSY cnt %d\n", + __FUNCTION__, cfg->handshaking)); + cfg->handshaking++; + ret = -EBUSY; + break; + } + } + break; + case WL_EXT_STATUS_CONNECTING: + if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { + bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr); + sec = wl_read_prof(cfg, dev, WL_PROF_SEC); + if ((sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) && + bssidx == 0) { + cfg->handshaking = 1; + if (action & NO_BTC_IN4WAY) + wldev_iovar_setint(dev, "btc_mode", 0); + } + } + break; + case WL_EXT_STATUS_DELETE_GC: + if ((action & DONT_DELETE_GC_AFTER_WPS) && + (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) { + u8* mac_addr = context; + if (memcmp(ðer_bcast, mac_addr, ETHER_ADDR_LEN) && + dhdp->conf->eapol_status == EAPOL_STATUS_WPS_DONE) { + u32 timeout; + WL_TRACE(("status=%d, wps_done=%d, waiting %dms ...\n", + status, cfg->wps_done, max_wait_gc_time)); + mutex_unlock(&cfg->in4way_sync); + timeout = wait_event_interruptible_timeout(cfg->wps_done_event, + cfg->wps_done, msecs_to_jiffies(max_wait_gc_time)); + mutex_lock(&cfg->in4way_sync); + WL_TRACE(("status=%d, wps_done=%d, timeout=%d\n", + status, cfg->wps_done, timeout)); + if (timeout > 0) { + ret = -1; + break; + } + } else { + WL_TRACE(("status=%d, wps_done=%d => 0\n", status, cfg->wps_done)); + cfg->wps_done = FALSE; + dhdp->conf->eapol_status = EAPOL_STATUS_NONE; + } + } + break; + case WL_EXT_STATUS_GC_DISCONNECTED: + if ((action & DONT_DELETE_GC_AFTER_WPS) && + (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) && + dhdp->conf->eapol_status == EAPOL_STATUS_WPS_DONE) { + WL_TRACE(("status=%d, wps_done=%d => 0\n", status, cfg->wps_done)); + cfg->wps_done = FALSE; + } + break; + case WL_EXT_STATUS_GC_CONNECTED: + if ((action & DONT_DELETE_GC_AFTER_WPS) && + (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) && + dhdp->conf->eapol_status == EAPOL_STATUS_WPS_DONE) { + WL_TRACE(("status=%d, wps_done=%d => 1\n", status, cfg->wps_done)); + cfg->wps_done = TRUE; + wake_up_interruptible(&cfg->wps_done_event); + } + break; + case WL_EXT_STATUS_DISCONNECTED: + case WL_EXT_STATUS_4WAY_DONE: + if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { + if (cfg->handshaking) { + if (action & NO_BTC_IN4WAY) + wldev_iovar_setint(dev, "btc_mode", 1); + cfg->handshaking = 0; + } + } + break; + default: + WL_ERR(("Unknown action=0x%x, status=%d\n", action, status)); + } + + mutex_unlock(&cfg->in4way_sync); + + return ret; +} \ No newline at end of file diff --git a/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.h b/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.h index cf9b3fb..6a6300c 100644 --- a/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.h +++ b/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.h @@ -341,6 +341,18 @@ enum wl_status { WL_STATUS_NESTED_CONNECT }; +enum wl_ext_status { + WL_EXT_STATUS_DISCONNECTED = 0, + WL_EXT_STATUS_SCAN, + WL_EXT_STATUS_CONNECTING, + WL_EXT_STATUS_CONNECTED, + WL_EXT_STATUS_DELETE_GC, + WL_EXT_STATUS_GC_DISCONNECTED, + WL_EXT_STATUS_GC_CONNECTED, + WL_EXT_STATUS_4WAY_START, + WL_EXT_STATUS_4WAY_DONE +}; + /* wi-fi mode */ enum wl_mode { WL_MODE_BSS, @@ -872,6 +884,9 @@ struct bcm_cfg80211 { int best_2g_ch; int best_5g_ch; uint handshaking; + bool wps_done; + wait_queue_head_t wps_done_event; + struct mutex in4way_sync; }; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ -- 2.20.1