summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRongjun Chen <rongjun.chen@amlogic.com>2018-09-25 10:11:59 +0800
committerRongjun Chen <rongjun.chen@amlogic.com>2018-09-30 10:25:03 +0800
commit5011fc31db0edb4c57e72ee04815508804124857 (patch)
tree485389b076fef719b89d67db93f96d1f350a842f
parentd964ce36a41db0ba62704d8d3f4a43e002abd506 (diff)
downloaddhd-driver-5011fc31db0edb4c57e72ee04815508804124857.tar.gz
wifi: fix wifi close 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: Ic7f9b688f56f2c131b12328c30b1d3431c8d157b Signed-off-by: Rongjun Chen <rongjun.chen@amlogic.com>
-rw-r--r--[-rwxr-xr-x]bcmdhd.1.579.77.41.1.cn/Makefile0
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dbus.c2
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dhd_config.c59
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dhd_config.h14
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dhd_gpio.c9
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dhd_ip.c4
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dhd_linux.c73
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dhd_sdio.c35
-rw-r--r--bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c1
-rw-r--r--bcmdhd.1.579.77.41.1.cn/wl_android_ext.c148
-rw-r--r--bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c197
-rw-r--r--bcmdhd.1.579.77.41.1.cn/wl_cfg80211.h15
12 files changed, 366 insertions, 191 deletions
diff --git a/bcmdhd.1.579.77.41.1.cn/Makefile b/bcmdhd.1.579.77.41.1.cn/Makefile
index 5669d5c..5669d5c 100755..100644
--- a/bcmdhd.1.579.77.41.1.cn/Makefile
+++ b/bcmdhd.1.579.77.41.1.cn/Makefile
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..51ea3f6 100644
--- a/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c
+++ b/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c
@@ -112,8 +112,8 @@ dhd_wlan_set_power(int on
}
}
#ifdef CUSTOMER_HW_AMLOGIC
- extern_wifi_set_enable(0);
- mdelay(200);
+// extern_wifi_set_enable(0);
+// mdelay(200);
#endif
}
@@ -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(&ether_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__ == \