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;
}
return mode;\r
}\r
\r
+void\r
+dhd_conf_set_eapol_status(dhd_pub_t *dhd, char *ifname, char *dump_data)\r
+{\r
+ unsigned char type;\r
+ int pair, ack, mic, kerr, req, sec, install;\r
+ unsigned short us_tmp;\r
+\r
+ if (!(dhd->conf->in4way&DONT_DELETE_GC_AFTER_WPS) || strncmp(ifname, "p2p", 3)) {\r
+ return;\r
+ }\r
+\r
+ type = dump_data[15];\r
+ if ((type == 0) && (dump_data[22] == 254) && (dump_data[30] == 5)) {\r
+ dhd->conf->eapol_status = EAPOL_STATUS_WPS_DONE;\r
+ CONFIG_TRACE(("EAP Packet, WSC Done\n"));\r
+ } else if (type == 3 && dump_data[18] == 2) {\r
+ us_tmp = (dump_data[19] << 8) | dump_data[20];\r
+ pair = 0 != (us_tmp & 0x08);\r
+ ack = 0 != (us_tmp & 0x80);\r
+ mic = 0 != (us_tmp & 0x100);\r
+ kerr = 0 != (us_tmp & 0x400);\r
+ req = 0 != (us_tmp & 0x800);\r
+ sec = 0 != (us_tmp & 0x200);\r
+ install = 0 != (us_tmp & 0x40);\r
+ if (pair && !install && !ack && mic && sec && !req && !kerr) {\r
+ dhd->conf->eapol_status = EAPOL_STATUS_M4;\r
+ CONFIG_TRACE(("EAPOL Packet, 4-way handshake, M4\n"));\r
+ }\r
+ }\r
+\r
+ return;\r
+}\r
+\r
#ifdef PROP_TXSTATUS\r
int\r
dhd_conf_get_disable_proptx(dhd_pub_t *dhd)\r
conf->sd_f2_blocksize = (int)simple_strtol(data, NULL, 10);\r
printf("%s: sd_f2_blocksize = %d\n", __FUNCTION__, conf->sd_f2_blocksize);\r
}\r
+#if defined(HW_OOB)\r
else if (!strncmp("oob_enabled_later=", full_param, len_param)) {\r
if (!strncmp(data, "0", 1))\r
conf->oob_enabled_later = FALSE;\r
conf->oob_enabled_later = TRUE;\r
printf("%s: oob_enabled_later = %d\n", __FUNCTION__, conf->oob_enabled_later);\r
}\r
+#endif\r
else if (!strncmp("dpc_cpucore=", full_param, len_param)) {\r
conf->dpc_cpucore = (int)simple_strtol(data, NULL, 10);\r
printf("%s: dpc_cpucore = %d\n", __FUNCTION__, conf->dpc_cpucore);\r
printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len);\r
}\r
else if (!strncmp("txctl_tmo_fix=", full_param, len_param)) {\r
- conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 10);\r
+ conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 0);\r
printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix);\r
}\r
else if (!strncmp("tx_max_offset=", full_param, len_param)) {\r
conf->in4way = (int)simple_strtol(data, NULL, 0);\r
printf("%s: in4way = 0x%x\n", __FUNCTION__, conf->in4way);\r
}\r
+ else if (!strncmp("max_wait_gc_time=", full_param, len_param)) {\r
+ conf->max_wait_gc_time = (int)simple_strtol(data, NULL, 0);\r
+ printf("%s: max_wait_gc_time = %d\n", __FUNCTION__, conf->max_wait_gc_time);\r
+ }\r
else if (!strncmp("wl_preinit=", full_param, len_param)) {\r
if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) {\r
CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
char name[32], *pch, *pick_tmp, *pick_tmp2;\r
\r
/* Process wl_preinit:\r
- * wl_preinit=[cmd]/[val], [cmd]/[val] \\r
- * Ex: wl_preinit=86/0, mpc/0\r
+ * wl_preinit=[cmd]=[val], [cmd]=[val]\r
+ * Ex: wl_preinit=86=0, mpc=0\r
*/\r
pick_tmp = data;\r
while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {\r
conf->txglom_ext = FALSE;\r
conf->tx_max_offset = 0;\r
conf->txglomsize = SDPCM_DEFGLOM_SIZE;\r
- conf->txctl_tmo_fix = 300;\r
+ conf->txctl_tmo_fix = -1;\r
conf->txglom_mode = SDPCM_TXGLOM_CPY;\r
conf->deferred_tx_len = 0;\r
conf->dhd_txminmax = 1;\r
conf->txinrx_thres = -1;\r
conf->sd_f2_blocksize = 0;\r
+#if defined(HW_OOB)\r
conf->oob_enabled_later = FALSE;\r
+#endif\r
conf->orphan_move = 0;\r
#endif\r
#ifdef BCMPCIE\r
conf->ctrl_resched = 2;\r
conf->dhd_ioctl_timeout_msec = 0;\r
conf->in4way = NO_SCAN_IN4WAY;\r
+ conf->max_wait_gc_time = 300;\r
#ifdef ISAM_PREINIT\r
memset(conf->isam_init, 0, sizeof(conf->isam_init));\r
memset(conf->isam_config, 0, sizeof(conf->isam_config));\r
#ifdef CUSTOMER_HW_AMLOGIC\r
dhd_slpauto = FALSE;\r
#endif\r
- if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
- conf->chip == BCM4371_CHIP_ID || conf->chip == BCM43569_CHIP_ID ||\r
- conf->chip == BCM4359_CHIP_ID || conf->chip == BCM4362_CHIP_ID) {\r
+ if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||\r
+ conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
+ conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||\r
+ conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||\r
+ conf->chip == BCM4362_CHIP_ID) {\r
#ifdef DHDTCPACK_SUPPRESS\r
#ifdef BCMSDIO\r
conf->tcpack_sup_mode = TCPACK_SUP_REPLACE;\r
conf->dhd_txminmax = -1;\r
conf->txinrx_thres = 128;\r
conf->sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE;\r
- conf->oob_enabled_later = TRUE;\r
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))\r
conf->orphan_move = 1;\r
#else\r
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 {
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
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
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;
}
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) {
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
#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) {
#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 */
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;
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) {
#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) {
#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) {
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;
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;
#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;
/* 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);
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
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))) {
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)) {
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();
* 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;
}
/* 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);
* 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;
{\r
int i;\r
int j;\r
-\r
printk(KERN_ERR "%s(): %s\n", __func__, DHD_STATIC_VERSION_STR);\r
\r
for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {\r
}
#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;
}
}
#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;
#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;
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)
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;
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 */
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) &&
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"));
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,
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
"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) {
}
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) {
} 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);
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
}
#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)
{
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));
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);
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);
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 */
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);
}
#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;
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
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,
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__ == \