config BCMDHD_PCIE
bool "PCIe bus interface support"
depends on BCMDHD && PCI
+config BCMDHD_USB
+ bool "USB bus interface support"
+ depends on BCMDHD && USB
endchoice
choice
$(info bcm SDIO driver configured)
CONFIG_DHD_USE_STATIC_BUF :=y
endif
-#CONFIG_BCMDHD_SDIOO := y
+
+#CONFIG_BCMDHD_SDIO := y
#CONFIG_BCMDHD_PCIE := y
#CONFIG_BCMDHD_USB := y
+
+#CONFIG_BCMDHD_CUSB := y
CONFIG_BCMDHD_PROPTXSTATUS := y
CONFIG_MACH_PLATFORM := y
export CONFIG_BCMDHD_OOB = y
export CONFIG_VTS_SUPPORT = y
-DHDCFLAGS = -Wall -Wstrict-prototypes -Wno-maybe-uninitialized \
- -Dlinux -DBCMDRIVER \
+DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \
+ -Wno-maybe-uninitialized \
-DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \
-DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DBCMDBG -DGET_OTP_MAC_ENABLE \
-DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \
-DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DPNO_SUPPORT -DDHDTCPACK_SUPPRESS \
- -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD \
- -DTSQ_MULTIPLIER -DMFP \
+ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT \
+ -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP \
-DWL_EXT_IAPSTA \
+ -DENABLE_INSMOD_NO_FW_LOAD \
-I$(src) -I$(src)/include
DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \
dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o \
dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o \
bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \
+ dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o \
hnd_pktq.o hnd_pktpool.o dhd_config.o wl_android_ext.o
-ifeq ($(BCM_USB_COMPOSITE),true)
-DHDCFLAGS += -DBCMUSBDEV_COMPOSITE
-endif
-
+#BCMDHD_SDIO
ifneq ($(CONFIG_BCMDHD_SDIO),)
-DHDCFLAGS += \
- -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \
+DHDCFLAGS += -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \
-DSDTEST -DBDC -DDHD_USE_IDLECOUNT -DCUSTOM_SDIO_F2_BLKSIZE=256 \
- -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT
-DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD
-
-DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \
- dhd_sdio.o dhd_cdc.o dhd_wlfc.o
-
+ -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DRXFRAME_THREAD
ifeq ($(CONFIG_BCMDHD_OOB),y)
DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB
ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y)
else
DHDCFLAGS += -DSDIO_ISR_THREAD
endif
+
+DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \
+ dhd_sdio.o dhd_cdc.o dhd_wlfc.o
endif
+#BCMDHD_PCIE
ifneq ($(CONFIG_BCMDHD_PCIE),)
-DHDCFLAGS += \
- -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1 \
+DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1 \
-DDONGLE_ENABLE_ISOLATION
-DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD
+ifneq ($(CONFIG_PCI_MSI),)
+ DHDCFLAGS += -DDHD_USE_MSI
+endif
DHDCFLAGS += -DDHD_PCIE_BAR1_WIN_BASE_FIX=0x200000
DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \
dhd_msgbuf.o
-
-ifneq ($(CONFIG_PCI_MSI),)
- DHDCFLAGS += -DDHD_USE_MSI
-endif
-ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y)
- DHDCFLAGS += -DDHD_USE_STATIC_CTRLBUF
-endif
endif
+#BCMDHD_USB
ifneq ($(CONFIG_BCMDHD_USB),)
DHDCFLAGS += -DUSBOS_TX_THREAD -DBCMDBUS -DBCMTRXV2 -DDBUS_USB_LOOPBACK \
-DBDC
+DHDCFLAGS += -DBCM_REQUEST_FW -DEXTERNAL_FW_PATH
+#DHDCFLAGS :=$(filter-out -DENABLE_INSMOD_NO_FW_LOAD,$(DHDCFLAGS))
+ifneq ($(CONFIG_BCMDHD_CUSB),)
+ DHDCFLAGS += -DBCMUSBDEV_COMPOSITE
+ DHDCFLAGS :=$(filter-out -DENABLE_INSMOD_NO_FW_LOAD,$(DHDCFLAGS))
+endif
DHDOFILES += dbus.o dbus_usb.o dbus_usb_linux.o dhd_cdc.o dhd_wlfc.o
endif
+#PROPTXSTATUS
ifeq ($(CONFIG_BCMDHD_PROPTXSTATUS),y)
ifneq ($(CONFIG_BCMDHD_USB),)
DHDCFLAGS += -DPROP_TXSTATUS
endif
endif
+#VTS_SUPPORT
ifeq ($(CONFIG_VTS_SUPPORT),y)
-DHDCFLAGS += \
- -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG \
+ifneq ($(CONFIG_CFG80211),)
+DHDCFLAGS += -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG \
-DLINKSTAT_SUPPORT -DDEBUGABILITY -DDBG_PKT_MON -DPKT_FILTER_SUPPORT \
-DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHD_WAKE_STATUS \
-DCUSTOM_COUNTRY_CODE -DDHD_FW_COREDUMP -DEXPLICIT_DISCIF_CLEANUP
-DHDOFILES += dhd_debug_linux.o dhd_debug.o bcmxtlv.o dhd_rtt.o \
- bcm_app_utils.o
+DHDOFILES += bcmxtlv.o dhd_rtt.o bcm_app_utils.o
+endif
endif
# MESH support for kernel 3.10 later
DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS))
DHDCFLAGS :=$(filter-out -DSET_RANDOM_MAC_SOFTAP,$(DHDCFLAGS))
endif
+
ifeq ($(CONFIG_BCMDHD_SDIO),y)
obj-$(CONFIG_BCMDHD) += dhd.o
dhd-objs += $(DHDOFILES)
endif
ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y)
+# obj-m += dhd_static_buf.o
DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF
DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -DCONFIG_DHD_USE_STATIC_BUF
endif
endif
EXTRA_CFLAGS = $(DHDCFLAGS)
ifeq ($(CONFIG_BCMDHD),m)
- DHDCFLAGS += -DMULTIPLE_SUPPLICANT
EXTRA_LDFLAGS += --strip-debug
-else
- DHDCFLAGS += -DBUILD_IN_KERNEL
endif
ARCH ?= arm64
#include "osl.h"
#include "dbus.h"
#include <bcmutils.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_proto.h>
+#ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */
+#include <dhd_wlfc.h>
+#endif
+#include <dhd_config.h>
#if defined(BCM_REQUEST_FW)
#include <bcmsrom_fmt.h>
} dbus_irbq_t;
/**
- * This private structure dbus_info_t is also declared in dbus_usb_linux.c.
+ * This private structure dhd_bus_t is also declared in dbus_usb_linux.c.
* All the fields must be consistent in both declarations.
*/
-typedef struct dbus_info {
+typedef struct dhd_bus {
dbus_pub_t pub; /* MUST BE FIRST */
+ dhd_pub_t *dhd;
void *cbarg;
dbus_callbacks_t *cbs; /* callbacks to higher level, e.g. dhd_linux.c */
void *firmware;
void *nvfile;
#endif
-} dbus_info_t;
+ char *fw_path; /* module_param: path to firmware image */
+ char *nv_path; /* module_param: path to nvram vars file */
+} dhd_bus_t;
struct exec_parms {
union {
};
#define EXEC_RXLOCK(info, fn, a) \
- info->drvintf->exec_rxlock(dbus_info->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
+ info->drvintf->exec_rxlock(dhd_bus->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
#define EXEC_TXLOCK(info, fn, a) \
- info->drvintf->exec_txlock(dbus_info->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
+ info->drvintf->exec_txlock(dhd_bus->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
/*
* Callbacks common for all BUS
static struct dbus_irb *dbus_if_getirb(void *cbarg, bool send);
static void dbus_if_rxerr_indicate(void *handle, bool on);
+void * dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype,
+ uint16 bus_no, uint16 slot, uint32 hdrlen);
+void dhd_dbus_disconnect_cb(void *arg);
+void dbus_detach(dhd_bus_t *pub);
+
/** functions in this file that are called by lower DBUS levels, e.g. dbus_usb.c */
static dbus_intf_callbacks_t dbus_intf_cbs = {
dbus_if_send_irb_timeout,
static void* q_enq_exec(struct exec_parms *args);
static dbus_irb_t*q_deq(dbus_irbq_t *q);
static void* q_deq_exec(struct exec_parms *args);
-static int dbus_tx_timer_init(dbus_info_t *dbus_info);
-static int dbus_tx_timer_start(dbus_info_t *dbus_info, uint timeout);
-static int dbus_tx_timer_stop(dbus_info_t *dbus_info);
-static int dbus_irbq_init(dbus_info_t *dbus_info, dbus_irbq_t *q, int nq, int size_irb);
-static int dbus_irbq_deinit(dbus_info_t *dbus_info, dbus_irbq_t *q, int size_irb);
-static int dbus_rxirbs_fill(dbus_info_t *dbus_info);
+static int dbus_tx_timer_init(dhd_bus_t *dhd_bus);
+static int dbus_tx_timer_start(dhd_bus_t *dhd_bus, uint timeout);
+static int dbus_tx_timer_stop(dhd_bus_t *dhd_bus);
+static int dbus_irbq_init(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int nq, int size_irb);
+static int dbus_irbq_deinit(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int size_irb);
+static int dbus_rxirbs_fill(dhd_bus_t *dhd_bus);
static int dbus_send_irb(dbus_pub_t *pub, uint8 *buf, int len, void *pkt, void *info);
static void dbus_disconnect(void *handle);
-static void *dbus_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
+static void *dbus_probe(void *arg, const char *desc, uint32 bustype,
+ uint16 bus_no, uint16 slot, uint32 hdrlen);
-#if defined(BCM_REQUEST_FW)
#if defined(BCM_REQUEST_FW)
extern char * dngl_firmware;
extern unsigned int dngl_fwlen;
-#endif /* #if defined(BCM_REQUEST_FW) */
-static int dbus_get_nvram(dbus_info_t *dbus_info);
-static int dbus_jumbo_nvram(dbus_info_t *dbus_info);
-static int dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev);
-static int dbus_select_nvram(dbus_info_t *dbus_info, int8 *jumbonvram, int jumbolen,
+#ifndef EXTERNAL_FW_PATH
+static int dbus_get_nvram(dhd_bus_t *dhd_bus);
+static int dbus_jumbo_nvram(dhd_bus_t *dhd_bus);
+static int dbus_otp(dhd_bus_t *dhd_bus, uint16 *boardtype, uint16 *boardrev);
+static int dbus_select_nvram(dhd_bus_t *dhd_bus, int8 *jumbonvram, int jumbolen,
uint16 boardtype, uint16 boardrev, int8 **nvram, int *nvram_len);
-#ifndef BCM_REQUEST_FW
-static int dbus_zlib_decomp(dbus_info_t *dbus_info);
+#endif /* !EXTERNAL_FW_PATH */
+extern int dbus_zlib_decomp(dhd_bus_t *dhd_bus);
extern void *dbus_zlib_calloc(int num, int size);
extern void dbus_zlib_free(void *ptr);
#endif
-#endif
/* function */
void
dbus_flowctrl_tx(void *dbi, bool on)
{
- dbus_info_t *dbus_info = dbi;
+ dhd_bus_t *dhd_bus = dbi;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return;
DBUSTRACE(("%s on %d\n", __FUNCTION__, on));
- if (dbus_info->txoff == on)
+ if (dhd_bus->txoff == on)
return;
- dbus_info->txoff = on;
+ dhd_bus->txoff = on;
- if (dbus_info->cbs && dbus_info->cbs->txflowcontrol)
- dbus_info->cbs->txflowcontrol(dbus_info->cbarg, on);
+ if (dhd_bus->cbs && dhd_bus->cbs->txflowcontrol)
+ dhd_bus->cbs->txflowcontrol(dhd_bus->cbarg, on);
}
/**
static void
dbus_if_rxerr_indicate(void *handle, bool on)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
DBUSTRACE(("%s, on %d\n", __FUNCTION__, on));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return;
- if (dbus_info->txoverride == on)
+ if (dhd_bus->txoverride == on)
return;
- dbus_info->txoverride = on; /* flow control */
+ dhd_bus->txoverride = on; /* flow control */
if (!on)
- dbus_rxirbs_fill(dbus_info);
+ dbus_rxirbs_fill(dhd_bus);
}
/**
* called during attach phase. Status @ Dec 2012: this function does nothing since for all of the
- * lower DBUS levels dbus_info->drvintf->tx_timer_init is NULL.
+ * lower DBUS levels dhd_bus->drvintf->tx_timer_init is NULL.
*/
static int
-dbus_tx_timer_init(dbus_info_t *dbus_info)
+dbus_tx_timer_init(dhd_bus_t *dhd_bus)
{
- if (dbus_info && dbus_info->drvintf && dbus_info->drvintf->tx_timer_init)
- return dbus_info->drvintf->tx_timer_init(dbus_info->bus_info);
+ if (dhd_bus && dhd_bus->drvintf && dhd_bus->drvintf->tx_timer_init)
+ return dhd_bus->drvintf->tx_timer_init(dhd_bus->bus_info);
else
return DBUS_ERR;
}
static int
-dbus_tx_timer_start(dbus_info_t *dbus_info, uint timeout)
+dbus_tx_timer_start(dhd_bus_t *dhd_bus, uint timeout)
{
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- if (dbus_info->tx_timer_ticking)
+ if (dhd_bus->tx_timer_ticking)
return DBUS_OK;
- if (dbus_info->drvintf && dbus_info->drvintf->tx_timer_start) {
- if (dbus_info->drvintf->tx_timer_start(dbus_info->bus_info, timeout) == DBUS_OK) {
- dbus_info->tx_timer_ticking = TRUE;
+ if (dhd_bus->drvintf && dhd_bus->drvintf->tx_timer_start) {
+ if (dhd_bus->drvintf->tx_timer_start(dhd_bus->bus_info, timeout) == DBUS_OK) {
+ dhd_bus->tx_timer_ticking = TRUE;
return DBUS_OK;
}
}
}
static int
-dbus_tx_timer_stop(dbus_info_t *dbus_info)
+dbus_tx_timer_stop(dhd_bus_t *dhd_bus)
{
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- if (!dbus_info->tx_timer_ticking)
+ if (!dhd_bus->tx_timer_ticking)
return DBUS_OK;
- if (dbus_info->drvintf && dbus_info->drvintf->tx_timer_stop) {
- if (dbus_info->drvintf->tx_timer_stop(dbus_info->bus_info) == DBUS_OK) {
- dbus_info->tx_timer_ticking = FALSE;
+ if (dhd_bus->drvintf && dhd_bus->drvintf->tx_timer_stop) {
+ if (dhd_bus->drvintf->tx_timer_stop(dhd_bus->bus_info) == DBUS_OK) {
+ dhd_bus->tx_timer_ticking = FALSE;
return DBUS_OK;
}
}
/** called during attach phase. */
static int
-dbus_irbq_init(dbus_info_t *dbus_info, dbus_irbq_t *q, int nq, int size_irb)
+dbus_irbq_init(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int nq, int size_irb)
{
int i;
dbus_irb_t *irb;
ASSERT(q);
- ASSERT(dbus_info);
+ ASSERT(dhd_bus);
for (i = 0; i < nq; i++) {
/* MALLOC dbus_irb_tx or dbus_irb_rx, but cast to simple dbus_irb_t linkedlist */
- irb = (dbus_irb_t *) MALLOC(dbus_info->pub.osh, size_irb);
+ irb = (dbus_irb_t *) MALLOC(dhd_bus->pub.osh, size_irb);
if (irb == NULL) {
ASSERT(irb);
return DBUS_ERR;
/** called during detach phase or when attach failed */
static int
-dbus_irbq_deinit(dbus_info_t *dbus_info, dbus_irbq_t *q, int size_irb)
+dbus_irbq_deinit(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int size_irb)
{
dbus_irb_t *irb;
ASSERT(q);
- ASSERT(dbus_info);
+ ASSERT(dhd_bus);
/* q_deq() does not need to go through EXEC_xxLOCK()
* during deinit(); all callbacks are stopped by this time
*/
while ((irb = q_deq(q)) != NULL) {
- MFREE(dbus_info->pub.osh, irb, size_irb);
+ MFREE(dhd_bus->pub.osh, irb, size_irb);
}
if (q->cnt)
/** multiple code paths require the rx queue to be filled with more free IRBs */
static int
-dbus_rxirbs_fill(dbus_info_t *dbus_info)
+dbus_rxirbs_fill(dhd_bus_t *dhd_bus)
{
int err = DBUS_OK;
dbus_irb_rx_t *rxirb;
struct exec_parms args;
- ASSERT(dbus_info);
- if (dbus_info->pub.busstate != DBUS_STATE_UP) {
+ ASSERT(dhd_bus);
+ if (dhd_bus->pub.busstate != DBUS_STATE_UP) {
DBUSERR(("dbus_rxirbs_fill: DBUS not up \n"));
return DBUS_ERR;
- } else if (!dbus_info->drvintf || (dbus_info->drvintf->recv_irb == NULL)) {
+ } else if (!dhd_bus->drvintf || (dhd_bus->drvintf->recv_irb == NULL)) {
/* Lower edge bus interface does not support recv_irb().
* No need to pre-submit IRBs in this case.
*/
* refill) can run in parallel. While the rxoff condition is triggered outside,
* below while loop has to check and abort posting more to avoid RPC rxq overflow.
*/
- args.qdeq.q = dbus_info->rx_q;
- while ((!dbus_info->rxoff) &&
- (rxirb = (EXEC_RXLOCK(dbus_info, q_deq_exec, &args))) != NULL) {
- err = dbus_info->drvintf->recv_irb(dbus_info->bus_info, rxirb);
+ args.qdeq.q = dhd_bus->rx_q;
+ while ((!dhd_bus->rxoff) &&
+ (rxirb = (EXEC_RXLOCK(dhd_bus, q_deq_exec, &args))) != NULL) {
+ err = dhd_bus->drvintf->recv_irb(dhd_bus->bus_info, rxirb);
if (err == DBUS_ERR_RXDROP || err == DBUS_ERR_RXFAIL) {
/* Add the the free rxirb back to the queue
* and wait till later
*/
bzero(rxirb, sizeof(dbus_irb_rx_t));
- args.qenq.q = dbus_info->rx_q;
+ args.qenq.q = dhd_bus->rx_q;
args.qenq.b = (dbus_irb_t *) rxirb;
- EXEC_RXLOCK(dbus_info, q_enq_exec, &args);
+ EXEC_RXLOCK(dhd_bus, q_enq_exec, &args);
break;
} else if (err != DBUS_OK) {
int i = 0;
void
dbus_flowctrl_rx(dbus_pub_t *pub, bool on)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info->rxoff == on)
+ if (dhd_bus->rxoff == on)
return;
- dbus_info->rxoff = on;
+ dhd_bus->rxoff = on;
- if (dbus_info->pub.busstate == DBUS_STATE_UP) {
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
if (!on) {
/* post more irbs, resume rx if necessary */
- dbus_rxirbs_fill(dbus_info);
- if (dbus_info && dbus_info->drvintf->recv_resume) {
- dbus_info->drvintf->recv_resume(dbus_info->bus_info);
+ dbus_rxirbs_fill(dhd_bus);
+ if (dhd_bus && dhd_bus->drvintf->recv_resume) {
+ dhd_bus->drvintf->recv_resume(dhd_bus->bus_info);
}
} else {
/* ??? cancell posted irbs first */
- if (dbus_info && dbus_info->drvintf->recv_stop) {
- dbus_info->drvintf->recv_stop(dbus_info->bus_info);
+ if (dhd_bus && dhd_bus->drvintf->recv_stop) {
+ dhd_bus->drvintf->recv_stop(dhd_bus->bus_info);
}
}
}
static int
dbus_send_irb(dbus_pub_t *pub, uint8 *buf, int len, void *pkt, void *info)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_OK;
dbus_irb_tx_t *txirb = NULL;
int txirb_pending;
struct exec_parms args;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info->pub.busstate == DBUS_STATE_UP ||
- dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
- args.qdeq.q = dbus_info->tx_q;
- if (dbus_info->drvintf)
- txirb = EXEC_TXLOCK(dbus_info, q_deq_exec, &args);
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+ dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+ args.qdeq.q = dhd_bus->tx_q;
+ if (dhd_bus->drvintf)
+ txirb = EXEC_TXLOCK(dhd_bus, q_deq_exec, &args);
if (txirb == NULL) {
DBUSERR(("Out of tx dbus_bufs\n"));
txirb->arg = NULL;
txirb->retry_count = 0;
- if (dbus_info->drvintf && dbus_info->drvintf->send_irb) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->send_irb) {
/* call lower DBUS level send_irb function */
- err = dbus_info->drvintf->send_irb(dbus_info->bus_info, txirb);
+ err = dhd_bus->drvintf->send_irb(dhd_bus->bus_info, txirb);
if (err == DBUS_ERR_TXDROP) {
/* tx fail and no completion routine to clean up, reclaim irb NOW */
DBUSERR(("%s: send_irb failed, status = %d\n", __FUNCTION__, err));
bzero(txirb, sizeof(dbus_irb_tx_t));
- args.qenq.q = dbus_info->tx_q;
+ args.qenq.q = dhd_bus->tx_q;
args.qenq.b = (dbus_irb_t *) txirb;
- EXEC_TXLOCK(dbus_info, q_enq_exec, &args);
+ EXEC_TXLOCK(dhd_bus, q_enq_exec, &args);
} else {
- dbus_tx_timer_start(dbus_info, DBUS_TX_TIMEOUT_INTERVAL);
- txirb_pending = dbus_info->pub.ntxq - dbus_info->tx_q->cnt;
- if (txirb_pending > (dbus_info->tx_low_watermark * 3)) {
- dbus_flowctrl_tx(dbus_info, TRUE);
+ dbus_tx_timer_start(dhd_bus, DBUS_TX_TIMEOUT_INTERVAL);
+ txirb_pending = dhd_bus->pub.ntxq - dhd_bus->tx_q->cnt;
+ if (txirb_pending > (dhd_bus->tx_low_watermark * 3)) {
+ dbus_flowctrl_tx(dhd_bus, TRUE);
}
}
}
return -1;
}
+#ifdef EXTERNAL_FW_PATH
+static int
+dbus_get_fw_nvram(dhd_bus_t *dhd_bus, char *pfw_path, char *pnv_path)
+{
+ int bcmerror = -1, i;
+ uint len, total_len;
+ void *nv_image = NULL, *fw_image = NULL;
+ char *nv_memblock = NULL, *fw_memblock = NULL;
+ char *bufp;
+ bool file_exists;
+ uint8 nvram_words_pad = 0;
+ uint memblock_size = 2048;
+ uint8 *memptr;
+ int actual_fwlen;
+ struct trx_header *hdr;
+ uint32 img_offset = 0;
+ int offset = 0;
+
+ /* For Get nvram */
+ file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
+ if (file_exists) {
+ nv_image = dhd_os_open_image(pnv_path);
+ if (nv_image == NULL) {
+ printf("%s: Open nvram file failed %s\n", __FUNCTION__, pnv_path);
+ goto err;
+ }
+ }
+ nv_memblock = MALLOC(dhd_bus->pub.osh, MAX_NVRAMBUF_SIZE);
+ if (nv_memblock == NULL) {
+ DBUSERR(("%s: Failed to allocate memory %d bytes\n",
+ __FUNCTION__, MAX_NVRAMBUF_SIZE));
+ goto err;
+ }
+ len = dhd_os_get_image_block(nv_memblock, MAX_NVRAMBUF_SIZE, nv_image);
+ if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
+ bufp = (char *)nv_memblock;
+ bufp[len] = 0;
+ dhd_bus->nvram_len = process_nvram_vars(bufp, len);
+ if (dhd_bus->nvram_len % 4)
+ nvram_words_pad = 4 - dhd_bus->nvram_len % 4;
+ } else {
+ DBUSERR(("%s: error reading nvram file: %d\n", __FUNCTION__, len));
+ bcmerror = DBUS_ERR_NVRAM;
+ goto err;
+ }
+ if (nv_image)
+ dhd_os_close_image(nv_image);
+
+ /* For Get first block of fw to calculate total_len */
+ file_exists = ((pfw_path != NULL) && (pfw_path[0] != '\0'));
+ if (file_exists) {
+ fw_image = dhd_os_open_image(pfw_path);
+ if (fw_image == NULL) {
+ printf("%s: Open fw file failed %s\n", __FUNCTION__, pfw_path);
+ goto err;
+ }
+ }
+ memptr = fw_memblock = MALLOC(dhd_bus->pub.osh, memblock_size);
+ if (fw_memblock == NULL) {
+ DBUSERR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
+ memblock_size));
+ goto err;
+ }
+ len = dhd_os_get_image_block((char*)memptr, memblock_size, fw_image);
+ if ((actual_fwlen = check_file(dhd_bus->pub.osh, memptr)) <= 0) {
+ DBUSERR(("%s: bad firmware format!\n", __FUNCTION__));
+ goto err;
+ }
+
+ total_len = actual_fwlen + dhd_bus->nvram_len + nvram_words_pad;
+ dhd_bus->image = MALLOC(dhd_bus->pub.osh, total_len);
+ dhd_bus->image_len = total_len;
+ if (dhd_bus->image == NULL) {
+ DBUSERR(("%s: malloc failed!\n", __FUNCTION__));
+ goto err;
+ }
+
+ /* Step1: Copy trx header + firmwre */
+ memptr = fw_memblock;
+ do {
+ if (len < 0) {
+ DBUSERR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
+ bcmerror = BCME_ERROR;
+ goto err;
+ }
+ bcopy(memptr, dhd_bus->image+offset, len);
+ offset += len;
+ } while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, fw_image)));
+ /* Step2: Copy NVRAM + pad */
+ hdr = (struct trx_header *)dhd_bus->image;
+ img_offset = SIZEOF_TRX(hdr) + hdr->offsets[TRX_OFFSETS_DLFWLEN_IDX];
+ bcopy(nv_memblock, (uint8 *)(dhd_bus->image + img_offset),
+ dhd_bus->nvram_len);
+ img_offset += dhd_bus->nvram_len;
+ if (nvram_words_pad) {
+ bzero(&dhd_bus->image[img_offset], nvram_words_pad);
+ img_offset += nvram_words_pad;
+ }
+#ifdef BCMTRXV2
+ /* Step3: Copy DSG/CFG for V2 */
+ if (ISTRX_V2(hdr) &&
+ (hdr->offsets[TRX_OFFSETS_DSG_LEN_IDX] ||
+ hdr->offsets[TRX_OFFSETS_CFG_LEN_IDX])) {
+ DBUSERR(("%s: fix me\n", __FUNCTION__));
+ }
+#endif /* BCMTRXV2 */
+ /* Step4: update TRX header for nvram size */
+ hdr = (struct trx_header *)dhd_bus->image;
+ hdr->len = htol32(total_len);
+ /* Pass the actual fw len */
+ hdr->offsets[TRX_OFFSETS_NVM_LEN_IDX] =
+ htol32(dhd_bus->nvram_len + nvram_words_pad);
+ /* Calculate CRC over header */
+ hdr->crc32 = hndcrc32((uint8 *)&hdr->flag_version,
+ SIZEOF_TRX(hdr) - OFFSETOF(struct trx_header, flag_version),
+ CRC32_INIT_VALUE);
+
+ /* Calculate CRC over data */
+ for (i = SIZEOF_TRX(hdr); i < total_len; ++i)
+ hdr->crc32 = hndcrc32((uint8 *)&dhd_bus->image[i], 1, hdr->crc32);
+ hdr->crc32 = htol32(hdr->crc32);
+
+ bcmerror = DBUS_OK;
+
+err:
+ if (fw_memblock)
+ MFREE(dhd_bus->pub.osh, fw_memblock, MAX_NVRAMBUF_SIZE);
+ if (fw_image)
+ dhd_os_close_image(fw_image);
+ if (nv_memblock)
+ MFREE(dhd_bus->pub.osh, nv_memblock, MAX_NVRAMBUF_SIZE);
+ if (nv_image)
+ dhd_os_close_image(nv_image);
+
+ return bcmerror;
+}
+
+/**
+ * during driver initialization ('attach') or after PnP 'resume', firmware needs to be loaded into
+ * the dongle
+ */
+static int
+dbus_do_download(dhd_bus_t *dhd_bus, char *pfw_path, char *pnv_path)
+{
+ int err = DBUS_OK;
+
+ err = dbus_get_fw_nvram(dhd_bus, pfw_path, pnv_path);
+ if (err) {
+ DBUSERR(("dbus_do_download: fail to get nvram %d\n", err));
+ return err;
+ }
+
+ if (dhd_bus->drvintf->dlstart && dhd_bus->drvintf->dlrun) {
+ err = dhd_bus->drvintf->dlstart(dhd_bus->bus_info,
+ dhd_bus->image, dhd_bus->image_len);
+ if (err == DBUS_OK) {
+ err = dhd_bus->drvintf->dlrun(dhd_bus->bus_info);
+ }
+ } else
+ err = DBUS_ERR;
+
+ if (dhd_bus->image) {
+ MFREE(dhd_bus->pub.osh, dhd_bus->image, dhd_bus->image_len);
+ dhd_bus->image = NULL;
+ dhd_bus->image_len = 0;
+ }
+
+ return err;
+} /* dbus_do_download */
+#else
+
/**
* It is easy for the user to pass one jumbo nvram file to the driver than a set of smaller files.
* The 'jumbo nvram' file format is essentially a set of nvram files. Before commencing firmware
* file is selected.
*/
static int
-dbus_jumbo_nvram(dbus_info_t *dbus_info)
+dbus_jumbo_nvram(dhd_bus_t *dhd_bus)
{
int8 *nvram = NULL;
int nvram_len = 0;
* if boardtype/rev are present in otp
* select nvram data for that boardtype/rev
*/
- dbus_otp(dbus_info, &boardtype, &boardrev);
+ dbus_otp(dhd_bus, &boardtype, &boardrev);
- ret = dbus_select_nvram(dbus_info, dbus_info->extdl.vars, dbus_info->extdl.varslen,
+ ret = dbus_select_nvram(dhd_bus, dhd_bus->extdl.vars, dhd_bus->extdl.varslen,
boardtype, boardrev, &nvram, &nvram_len);
if (ret == DBUS_JUMBO_BAD_FORMAT)
boardtype, boardrev));
return DBUS_ERR_NVRAM;
}
- dbus_info->nvram = nvram;
- dbus_info->nvram_len = nvram_len;
+ dhd_bus->nvram = nvram;
+ dhd_bus->nvram_len = nvram_len;
return DBUS_OK;
}
/** before commencing fw download, the correct NVRAM image to download has to be picked */
static int
-dbus_get_nvram(dbus_info_t *dbus_info)
+dbus_get_nvram(dhd_bus_t *dhd_bus)
{
int len, i;
struct trx_header *hdr;
int actual_fwlen;
uint32 img_offset = 0;
- dbus_info->nvram_len = 0;
- if (dbus_info->extdl.varslen) {
- if (DBUS_OK != dbus_jumbo_nvram(dbus_info))
+ dhd_bus->nvram_len = 0;
+ if (dhd_bus->extdl.varslen) {
+ if (DBUS_OK != dbus_jumbo_nvram(dhd_bus))
return DBUS_ERR_NVRAM;
- DBUSERR(("NVRAM %d bytes downloaded\n", dbus_info->nvram_len));
+ DBUSERR(("NVRAM %d bytes downloaded\n", dhd_bus->nvram_len));
}
#if defined(BCM_REQUEST_FW)
else if (nonfwnvram) {
- dbus_info->nvram = nonfwnvram;
- dbus_info->nvram_len = nonfwnvramlen;
- DBUSERR(("NVRAM %d bytes downloaded\n", dbus_info->nvram_len));
+ dhd_bus->nvram = nonfwnvram;
+ dhd_bus->nvram_len = nonfwnvramlen;
+ DBUSERR(("NVRAM %d bytes downloaded\n", dhd_bus->nvram_len));
}
#endif
- if (dbus_info->nvram) {
+ if (dhd_bus->nvram) {
uint8 nvram_words_pad = 0;
/* Validate the format/length etc of the file */
- if ((actual_fwlen = check_file(dbus_info->pub.osh, dbus_info->fw)) <= 0) {
+ if ((actual_fwlen = check_file(dhd_bus->pub.osh, dhd_bus->fw)) <= 0) {
DBUSERR(("%s: bad firmware format!\n", __FUNCTION__));
return DBUS_ERR_NVRAM;
}
- if (!dbus_info->nvram_nontxt) {
+ if (!dhd_bus->nvram_nontxt) {
/* host supplied nvram could be in .txt format
* with all the comments etc...
*/
- dbus_info->nvram_len = process_nvram_vars(dbus_info->nvram,
- dbus_info->nvram_len);
+ dhd_bus->nvram_len = process_nvram_vars(dhd_bus->nvram,
+ dhd_bus->nvram_len);
}
- if (dbus_info->nvram_len % 4)
- nvram_words_pad = 4 - dbus_info->nvram_len % 4;
+ if (dhd_bus->nvram_len % 4)
+ nvram_words_pad = 4 - dhd_bus->nvram_len % 4;
- len = actual_fwlen + dbus_info->nvram_len + nvram_words_pad;
- dbus_info->image = MALLOC(dbus_info->pub.osh, len);
- dbus_info->image_len = len;
- if (dbus_info->image == NULL) {
+ len = actual_fwlen + dhd_bus->nvram_len + nvram_words_pad;
+ dhd_bus->image = MALLOC(dhd_bus->pub.osh, len);
+ dhd_bus->image_len = len;
+ if (dhd_bus->image == NULL) {
DBUSERR(("%s: malloc failed!\n", __FUNCTION__));
return DBUS_ERR_NVRAM;
}
- hdr = (struct trx_header *)dbus_info->fw;
+ hdr = (struct trx_header *)dhd_bus->fw;
/* Step1: Copy trx header + firmwre */
img_offset = SIZEOF_TRX(hdr) + hdr->offsets[TRX_OFFSETS_DLFWLEN_IDX];
- bcopy(dbus_info->fw, dbus_info->image, img_offset);
+ bcopy(dhd_bus->fw, dhd_bus->image, img_offset);
/* Step2: Copy NVRAM + pad */
- bcopy(dbus_info->nvram, (uint8 *)(dbus_info->image + img_offset),
- dbus_info->nvram_len);
- img_offset += dbus_info->nvram_len;
+ bcopy(dhd_bus->nvram, (uint8 *)(dhd_bus->image + img_offset),
+ dhd_bus->nvram_len);
+ img_offset += dhd_bus->nvram_len;
if (nvram_words_pad) {
- bzero(&dbus_info->image[img_offset],
+ bzero(&dhd_bus->image[img_offset],
nvram_words_pad);
img_offset += nvram_words_pad;
}
(hdr->offsets[TRX_OFFSETS_DSG_LEN_IDX] ||
hdr->offsets[TRX_OFFSETS_CFG_LEN_IDX])) {
- bcopy(dbus_info->fw + SIZEOF_TRX(hdr) +
+ bcopy(dhd_bus->fw + SIZEOF_TRX(hdr) +
hdr->offsets[TRX_OFFSETS_DLFWLEN_IDX] +
hdr->offsets[TRX_OFFSETS_NVM_LEN_IDX],
- dbus_info->image + img_offset,
+ dhd_bus->image + img_offset,
hdr->offsets[TRX_OFFSETS_DSG_LEN_IDX] +
hdr->offsets[TRX_OFFSETS_CFG_LEN_IDX]);
}
#endif /* BCMTRXV2 */
/* Step4: update TRX header for nvram size */
- hdr = (struct trx_header *)dbus_info->image;
+ hdr = (struct trx_header *)dhd_bus->image;
hdr->len = htol32(len);
/* Pass the actual fw len */
hdr->offsets[TRX_OFFSETS_NVM_LEN_IDX] =
- htol32(dbus_info->nvram_len + nvram_words_pad);
+ htol32(dhd_bus->nvram_len + nvram_words_pad);
/* Calculate CRC over header */
hdr->crc32 = hndcrc32((uint8 *)&hdr->flag_version,
SIZEOF_TRX(hdr) - OFFSETOF(struct trx_header, flag_version),
/* Calculate CRC over data */
for (i = SIZEOF_TRX(hdr); i < len; ++i)
- hdr->crc32 = hndcrc32((uint8 *)&dbus_info->image[i], 1, hdr->crc32);
+ hdr->crc32 = hndcrc32((uint8 *)&dhd_bus->image[i], 1, hdr->crc32);
hdr->crc32 = htol32(hdr->crc32);
} else {
- dbus_info->image = dbus_info->fw;
- dbus_info->image_len = (uint32)dbus_info->fwlen;
+ dhd_bus->image = dhd_bus->fw;
+ dhd_bus->image_len = (uint32)dhd_bus->fwlen;
}
return DBUS_OK;
* the dongle
*/
static int
-dbus_do_download(dbus_info_t *dbus_info)
+dbus_do_download(dhd_bus_t *dhd_bus)
{
int err = DBUS_OK;
#ifndef BCM_REQUEST_FW
#endif
#if defined(BCM_REQUEST_FW)
- dbus_info->firmware = dbus_get_fw_nvfile(dbus_info->pub.attrib.devid,
- dbus_info->pub.attrib.chiprev, &dbus_info->fw, &dbus_info->fwlen,
+ dhd_bus->firmware = dbus_get_fw_nvfile(dhd_bus->pub.attrib.devid,
+ dhd_bus->pub.attrib.chiprev, &dhd_bus->fw, &dhd_bus->fwlen,
DBUS_FIRMWARE, 0, 0);
- if (!dbus_info->firmware)
+ if (!dhd_bus->firmware)
return DBUS_ERR;
#endif
- dbus_info->image = dbus_info->fw;
- dbus_info->image_len = (uint32)dbus_info->fwlen;
+ dhd_bus->image = dhd_bus->fw;
+ dhd_bus->image_len = (uint32)dhd_bus->fwlen;
#ifndef BCM_REQUEST_FW
- if (UNZIP_ENAB(dbus_info) && !decomp_override) {
- err = dbus_zlib_decomp(dbus_info);
+ if (UNZIP_ENAB(dhd_bus) && !decomp_override) {
+ err = dbus_zlib_decomp(dhd_bus);
if (err) {
DBUSERR(("dbus_attach: fw decompress fail %d\n", err));
return err;
#if defined(BCM_REQUEST_FW)
/* check if firmware is appended with nvram file */
- err = dbus_otp(dbus_info, &boardtype, &boardrev);
+ err = dbus_otp(dhd_bus, &boardtype, &boardrev);
/* check if nvram is provided as separte file */
nonfwnvram = NULL;
nonfwnvramlen = 0;
- dbus_info->nvfile = dbus_get_fw_nvfile(dbus_info->pub.attrib.devid,
- dbus_info->pub.attrib.chiprev, (void *)&temp_nvram, &temp_len,
+ dhd_bus->nvfile = dbus_get_fw_nvfile(dhd_bus->pub.attrib.devid,
+ dhd_bus->pub.attrib.chiprev, (void *)&temp_nvram, &temp_len,
DBUS_NVFILE, boardtype, boardrev);
- if (dbus_info->nvfile) {
- int8 *tmp = MALLOC(dbus_info->pub.osh, temp_len);
+ if (dhd_bus->nvfile) {
+ int8 *tmp = MALLOC(dhd_bus->pub.osh, temp_len);
if (tmp) {
bcopy(temp_nvram, tmp, temp_len);
nonfwnvram = tmp;
}
#endif /* defined(BCM_REQUEST_FW) */
- err = dbus_get_nvram(dbus_info);
+ err = dbus_get_nvram(dhd_bus);
if (err) {
DBUSERR(("dbus_do_download: fail to get nvram %d\n", err));
return err;
}
- if (dbus_info->drvintf->dlstart && dbus_info->drvintf->dlrun) {
- err = dbus_info->drvintf->dlstart(dbus_info->bus_info,
- dbus_info->image, dbus_info->image_len);
+ if (dhd_bus->drvintf->dlstart && dhd_bus->drvintf->dlrun) {
+ err = dhd_bus->drvintf->dlstart(dhd_bus->bus_info,
+ dhd_bus->image, dhd_bus->image_len);
if (err == DBUS_OK)
- err = dbus_info->drvintf->dlrun(dbus_info->bus_info);
+ err = dhd_bus->drvintf->dlrun(dhd_bus->bus_info);
} else
err = DBUS_ERR;
- if (dbus_info->nvram) {
- MFREE(dbus_info->pub.osh, dbus_info->image, dbus_info->image_len);
- dbus_info->image = dbus_info->fw;
- dbus_info->image_len = (uint32)dbus_info->fwlen;
+ if (dhd_bus->nvram) {
+ MFREE(dhd_bus->pub.osh, dhd_bus->image, dhd_bus->image_len);
+ dhd_bus->image = dhd_bus->fw;
+ dhd_bus->image_len = (uint32)dhd_bus->fwlen;
}
#ifndef BCM_REQUEST_FW
- if (UNZIP_ENAB(dbus_info) && (!decomp_override) && dbus_info->orig_fw) {
- MFREE(dbus_info->pub.osh, dbus_info->fw, dbus_info->decomp_memsize);
- dbus_info->image = dbus_info->fw = dbus_info->orig_fw;
- dbus_info->image_len = dbus_info->fwlen = dbus_info->origfw_len;
+ if (UNZIP_ENAB(dhd_bus) && (!decomp_override) && dhd_bus->orig_fw) {
+ MFREE(dhd_bus->pub.osh, dhd_bus->fw, dhd_bus->decomp_memsize);
+ dhd_bus->image = dhd_bus->fw = dhd_bus->orig_fw;
+ dhd_bus->image_len = dhd_bus->fwlen = dhd_bus->origfw_len;
}
#endif
#if defined(BCM_REQUEST_FW)
fail:
- if (dbus_info->firmware) {
- dbus_release_fw_nvfile(dbus_info->firmware);
- dbus_info->firmware = NULL;
+ if (dhd_bus->firmware) {
+ dbus_release_fw_nvfile(dhd_bus->firmware);
+ dhd_bus->firmware = NULL;
}
- if (dbus_info->nvfile) {
- dbus_release_fw_nvfile(dbus_info->nvfile);
- dbus_info->nvfile = NULL;
+ if (dhd_bus->nvfile) {
+ dbus_release_fw_nvfile(dhd_bus->nvfile);
+ dhd_bus->nvfile = NULL;
}
if (nonfwnvram) {
- MFREE(dbus_info->pub.osh, nonfwnvram, nonfwnvramlen);
+ MFREE(dhd_bus->pub.osh, nonfwnvram, nonfwnvramlen);
nonfwnvram = NULL;
nonfwnvramlen = 0;
}
#endif
return err;
} /* dbus_do_download */
-
-#endif
+#endif /* EXTERNAL_FW_PATH */
+#endif
/** required for DBUS deregistration */
static void
static void
dbus_if_send_irb_timeout(void *handle, dbus_irb_tx_t *txirb)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
- if ((dbus_info == NULL) || (dbus_info->drvintf == NULL) || (txirb == NULL)) {
+ if ((dhd_bus == NULL) || (dhd_bus->drvintf == NULL) || (txirb == NULL)) {
return;
}
static void BCMFASTPATH
dbus_if_send_irb_complete(void *handle, dbus_irb_tx_t *txirb, int status)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
int txirb_pending;
struct exec_parms args;
void *pktinfo;
- if ((dbus_info == NULL) || (txirb == NULL)) {
+ if ((dhd_bus == NULL) || (txirb == NULL)) {
return;
}
DBUSTRACE(("%s: status = %d\n", __FUNCTION__, status));
- dbus_tx_timer_stop(dbus_info);
+ dbus_tx_timer_stop(dhd_bus);
/* re-queue BEFORE calling send_complete which will assume that this irb
is now available.
*/
pktinfo = txirb->info;
bzero(txirb, sizeof(dbus_irb_tx_t));
- args.qenq.q = dbus_info->tx_q;
+ args.qenq.q = dhd_bus->tx_q;
args.qenq.b = (dbus_irb_t *) txirb;
- EXEC_TXLOCK(dbus_info, q_enq_exec, &args);
+ EXEC_TXLOCK(dhd_bus, q_enq_exec, &args);
- if (dbus_info->pub.busstate != DBUS_STATE_DOWN) {
+ if (dhd_bus->pub.busstate != DBUS_STATE_DOWN) {
if ((status == DBUS_OK) || (status == DBUS_ERR_NODEVICE)) {
- if (dbus_info->cbs && dbus_info->cbs->send_complete)
- dbus_info->cbs->send_complete(dbus_info->cbarg, pktinfo,
+ if (dhd_bus->cbs && dhd_bus->cbs->send_complete)
+ dhd_bus->cbs->send_complete(dhd_bus->cbarg, pktinfo,
status);
if (status == DBUS_OK) {
- txirb_pending = dbus_info->pub.ntxq - dbus_info->tx_q->cnt;
+ txirb_pending = dhd_bus->pub.ntxq - dhd_bus->tx_q->cnt;
if (txirb_pending)
- dbus_tx_timer_start(dbus_info, DBUS_TX_TIMEOUT_INTERVAL);
- if ((txirb_pending < dbus_info->tx_low_watermark) &&
- dbus_info->txoff && !dbus_info->txoverride) {
- dbus_flowctrl_tx(dbus_info, OFF);
+ dbus_tx_timer_start(dhd_bus, DBUS_TX_TIMEOUT_INTERVAL);
+ if ((txirb_pending < dhd_bus->tx_low_watermark) &&
+ dhd_bus->txoff && !dhd_bus->txoverride) {
+ dbus_flowctrl_tx(dhd_bus, OFF);
}
}
} else {
pktinfo));
#if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) || defined(BCM_RPC_TOC)
if (pktinfo)
- if (dbus_info->cbs && dbus_info->cbs->send_complete)
- dbus_info->cbs->send_complete(dbus_info->cbarg, pktinfo,
+ if (dhd_bus->cbs && dhd_bus->cbs->send_complete)
+ dhd_bus->cbs->send_complete(dhd_bus->cbarg, pktinfo,
status);
#else
- dbus_if_pktfree(dbus_info, (void*)pktinfo, TRUE);
+ dbus_if_pktfree(dhd_bus, (void*)pktinfo, TRUE);
#endif /* defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) || defined(BCM_RPC_TOC) */
}
} else {
pktinfo));
#if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) || defined(BCM_RPC_TOC)
if (pktinfo)
- if (dbus_info->cbs && dbus_info->cbs->send_complete)
- dbus_info->cbs->send_complete(dbus_info->cbarg, pktinfo,
+ if (dhd_bus->cbs && dhd_bus->cbs->send_complete)
+ dhd_bus->cbs->send_complete(dhd_bus->cbarg, pktinfo,
status);
#else
- dbus_if_pktfree(dbus_info, (void*)pktinfo, TRUE);
+ dbus_if_pktfree(dhd_bus, (void*)pktinfo, TRUE);
#endif /* defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) defined(BCM_RPC_TOC) */
}
} /* dbus_if_send_irb_complete */
static void BCMFASTPATH
dbus_if_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
int rxirb_pending;
struct exec_parms args;
- if ((dbus_info == NULL) || (rxirb == NULL)) {
+ if ((dhd_bus == NULL) || (rxirb == NULL)) {
return;
}
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info->pub.busstate != DBUS_STATE_DOWN &&
- dbus_info->pub.busstate != DBUS_STATE_SLEEP) {
+ if (dhd_bus->pub.busstate != DBUS_STATE_DOWN &&
+ dhd_bus->pub.busstate != DBUS_STATE_SLEEP) {
if (status == DBUS_OK) {
if ((rxirb->buf != NULL) && (rxirb->actual_len > 0)) {
#ifdef DBUS_USB_LOOPBACK
matches_loopback_pkt(rxirb->buf);
} else
#endif
- if (dbus_info->cbs && dbus_info->cbs->recv_buf) {
- dbus_info->cbs->recv_buf(dbus_info->cbarg, rxirb->buf,
+ if (dhd_bus->cbs && dhd_bus->cbs->recv_buf) {
+ dhd_bus->cbs->recv_buf(dhd_bus->cbarg, rxirb->buf,
rxirb->actual_len);
}
} else if (rxirb->pkt != NULL) {
- if (dbus_info->cbs && dbus_info->cbs->recv_pkt)
- dbus_info->cbs->recv_pkt(dbus_info->cbarg, rxirb->pkt);
+ if (dhd_bus->cbs && dhd_bus->cbs->recv_pkt)
+ dhd_bus->cbs->recv_pkt(dhd_bus->cbarg, rxirb->pkt);
} else {
ASSERT(0); /* Should not happen */
}
- rxirb_pending = dbus_info->pub.nrxq - dbus_info->rx_q->cnt - 1;
- if ((rxirb_pending <= dbus_info->rx_low_watermark) &&
- !dbus_info->rxoff) {
+ rxirb_pending = dhd_bus->pub.nrxq - dhd_bus->rx_q->cnt - 1;
+ if ((rxirb_pending <= dhd_bus->rx_low_watermark) &&
+ !dhd_bus->rxoff) {
DBUSTRACE(("Low watermark so submit more %d <= %d \n",
- dbus_info->rx_low_watermark, rxirb_pending));
- dbus_rxirbs_fill(dbus_info);
- } else if (dbus_info->rxoff)
+ dhd_bus->rx_low_watermark, rxirb_pending));
+ dbus_rxirbs_fill(dhd_bus);
+ } else if (dhd_bus->rxoff)
DBUSTRACE(("rx flow controlled. not filling more. cut_rxq=%d\n",
- dbus_info->rx_q->cnt));
+ dhd_bus->rx_q->cnt));
} else if (status == DBUS_ERR_NODEVICE) {
DBUSERR(("%s: %d status = %d, buf %p\n", __FUNCTION__, __LINE__, status,
rxirb->buf));
#if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
if (rxirb->buf) {
- PKTFRMNATIVE(dbus_info->pub.osh, rxirb->buf);
- PKTFREE(dbus_info->pub.osh, rxirb->buf, FALSE);
+ PKTFRMNATIVE(dhd_bus->pub.osh, rxirb->buf);
+ PKTFREE(dhd_bus->pub.osh, rxirb->buf, FALSE);
}
#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY || BCM_RPC_TOC */
} else {
status, rxirb->buf));
#if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
if (rxirb->buf) {
- PKTFRMNATIVE(dbus_info->pub.osh, rxirb->buf);
- PKTFREE(dbus_info->pub.osh, rxirb->buf, FALSE);
+ PKTFRMNATIVE(dhd_bus->pub.osh, rxirb->buf);
+ PKTFREE(dhd_bus->pub.osh, rxirb->buf, FALSE);
}
#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY || BCM_RPC_TOC */
}
rxirb->buf));
#if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
if (rxirb->buf) {
- PKTFRMNATIVE(dbus_info->pub.osh, rxirb->buf);
- PKTFREE(dbus_info->pub.osh, rxirb->buf, FALSE);
+ PKTFRMNATIVE(dhd_bus->pub.osh, rxirb->buf);
+ PKTFREE(dhd_bus->pub.osh, rxirb->buf, FALSE);
}
#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY || BCM_RPC_TOC */
}
- if (dbus_info->rx_q != NULL) {
+ if (dhd_bus->rx_q != NULL) {
bzero(rxirb, sizeof(dbus_irb_rx_t));
- args.qenq.q = dbus_info->rx_q;
+ args.qenq.q = dhd_bus->rx_q;
args.qenq.b = (dbus_irb_t *) rxirb;
- EXEC_RXLOCK(dbus_info, q_enq_exec, &args);
+ EXEC_RXLOCK(dhd_bus, q_enq_exec, &args);
} else
- MFREE(dbus_info->pub.osh, rxirb, sizeof(dbus_irb_tx_t));
+ MFREE(dhd_bus->pub.osh, rxirb, sizeof(dbus_irb_tx_t));
} /* dbus_if_recv_irb_complete */
/**
static void
dbus_if_errhandler(void *handle, int err)
{
- dbus_info_t *dbus_info = handle;
+ dhd_bus_t *dhd_bus = handle;
uint32 mask = 0;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return;
switch (err) {
case DBUS_ERR_TXFAIL:
- dbus_info->pub.stats.tx_errors++;
+ dhd_bus->pub.stats.tx_errors++;
mask |= ERR_CBMASK_TXFAIL;
break;
case DBUS_ERR_TXDROP:
- dbus_info->pub.stats.tx_dropped++;
+ dhd_bus->pub.stats.tx_dropped++;
mask |= ERR_CBMASK_TXFAIL;
break;
case DBUS_ERR_RXFAIL:
- dbus_info->pub.stats.rx_errors++;
+ dhd_bus->pub.stats.rx_errors++;
mask |= ERR_CBMASK_RXFAIL;
break;
case DBUS_ERR_RXDROP:
- dbus_info->pub.stats.rx_dropped++;
+ dhd_bus->pub.stats.rx_dropped++;
mask |= ERR_CBMASK_RXFAIL;
break;
default:
break;
}
- if (dbus_info->cbs && dbus_info->cbs->errhandler && (dbus_info->errmask & mask))
- dbus_info->cbs->errhandler(dbus_info->cbarg, err);
+ if (dhd_bus->cbs && dhd_bus->cbs->errhandler && (dhd_bus->errmask & mask))
+ dhd_bus->cbs->errhandler(dhd_bus->cbarg, err);
}
/**
static void
dbus_if_ctl_complete(void *handle, int type, int status)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL) {
- DBUSERR(("%s: dbus_info is NULL\n", __FUNCTION__));
+ if (dhd_bus == NULL) {
+ DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
return;
}
- if (dbus_info->pub.busstate != DBUS_STATE_DOWN) {
- if (dbus_info->cbs && dbus_info->cbs->ctl_complete)
- dbus_info->cbs->ctl_complete(dbus_info->cbarg, type, status);
+ if (dhd_bus->pub.busstate != DBUS_STATE_DOWN) {
+ if (dhd_bus->cbs && dhd_bus->cbs->ctl_complete)
+ dhd_bus->cbs->ctl_complete(dhd_bus->cbarg, type, status);
}
}
static void
dbus_if_state_change(void *handle, int state)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
int old_state;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return;
- if (dbus_info->pub.busstate == state)
+ if (dhd_bus->pub.busstate == state)
return;
- old_state = dbus_info->pub.busstate;
+ old_state = dhd_bus->pub.busstate;
if (state == DBUS_STATE_DISCONNECT) {
DBUSERR(("DBUS disconnected\n"));
}
/* Don't update state if it's PnP firmware re-download */
if (state != DBUS_STATE_PNP_FWDL)
- dbus_info->pub.busstate = state;
+ dhd_bus->pub.busstate = state;
else
dbus_flowctrl_rx(handle, FALSE);
if (state == DBUS_STATE_SLEEP)
dbus_flowctrl_rx(handle, TRUE);
if (state == DBUS_STATE_UP) {
- dbus_rxirbs_fill(dbus_info);
+ dbus_rxirbs_fill(dhd_bus);
dbus_flowctrl_rx(handle, FALSE);
}
- if (dbus_info->cbs && dbus_info->cbs->state_change)
- dbus_info->cbs->state_change(dbus_info->cbarg, state);
+ if (dhd_bus->cbs && dhd_bus->cbs->state_change)
+ dhd_bus->cbs->state_change(dhd_bus->cbarg, state);
}
/** Forward request for packet from lower DBUS layer to higher layer (e.g. dhd_linux.c) */
static void *
dbus_if_pktget(void *handle, uint len, bool send)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
void *p = NULL;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return NULL;
- if (dbus_info->cbs && dbus_info->cbs->pktget)
- p = dbus_info->cbs->pktget(dbus_info->cbarg, len, send);
+ if (dhd_bus->cbs && dhd_bus->cbs->pktget)
+ p = dhd_bus->cbs->pktget(dhd_bus->cbarg, len, send);
else
ASSERT(0);
static void
dbus_if_pktfree(void *handle, void *p, bool send)
{
- dbus_info_t *dbus_info = (dbus_info_t *) handle;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return;
- if (dbus_info->cbs && dbus_info->cbs->pktfree)
- dbus_info->cbs->pktfree(dbus_info->cbarg, p, send);
+ if (dhd_bus->cbs && dhd_bus->cbs->pktfree)
+ dhd_bus->cbs->pktfree(dhd_bus->cbarg, p, send);
else
ASSERT(0);
}
static struct dbus_irb*
dbus_if_getirb(void *cbarg, bool send)
{
- dbus_info_t *dbus_info = (dbus_info_t *) cbarg;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) cbarg;
struct exec_parms args;
struct dbus_irb *irb;
- if ((dbus_info == NULL) || (dbus_info->pub.busstate != DBUS_STATE_UP))
+ if ((dhd_bus == NULL) || (dhd_bus->pub.busstate != DBUS_STATE_UP))
return NULL;
if (send == TRUE) {
- args.qdeq.q = dbus_info->tx_q;
- irb = EXEC_TXLOCK(dbus_info, q_deq_exec, &args);
+ args.qdeq.q = dhd_bus->tx_q;
+ irb = EXEC_TXLOCK(dhd_bus, q_deq_exec, &args);
} else {
- args.qdeq.q = dbus_info->rx_q;
- irb = EXEC_RXLOCK(dbus_info, q_deq_exec, &args);
+ args.qdeq.q = dhd_bus->rx_q;
+ irb = EXEC_RXLOCK(dhd_bus, q_deq_exec, &args);
}
return irb;
* function.
*/
static void *
-dbus_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
+dbus_probe(void *arg, const char *desc, uint32 bustype, uint16 bus_no,
+ uint16 slot, uint32 hdrlen)
{
DBUSTRACE(("%s\n", __FUNCTION__));
if (probe_cb) {
- disc_arg = probe_cb(probe_arg, desc, bustype, hdrlen);
+ disc_arg = probe_cb(probe_arg, desc, bustype, bus_no, slot, hdrlen);
return disc_arg;
}
* action.
*/
int
-dbus_register(int vid, int pid, probe_cb_t prcb,
- disconnect_cb_t discb, void *prarg, void *param1, void *param2)
+dhd_bus_register(void)
{
int err;
- DBUSTRACE(("%s\n", __FUNCTION__));
+ DBUSTRACE(("%s: Enter\n", __FUNCTION__));
- probe_cb = prcb;
- disconnect_cb = discb;
- probe_arg = prarg;
+ probe_cb = dhd_dbus_probe_cb;
+ disconnect_cb = dhd_dbus_disconnect_cb;
+ probe_arg = NULL;
+
+ err = dbus_bus_register(0xa5c, 0x48f, dbus_probe, /* call lower DBUS level register function */
+ dbus_disconnect, NULL, &g_busintf, NULL, NULL);
- err = dbus_bus_register(vid, pid, dbus_probe, /* call lower DBUS level register function */
- dbus_disconnect, NULL, &g_busintf, param1, param2);
+ /* Device not detected */
+ if (err == DBUS_ERR_NODEVICE)
+ err = DBUS_OK;
return err;
}
-int
-dbus_deregister()
+dhd_pub_t *g_pub = NULL;
+void
+dhd_bus_unregister(void)
{
int ret;
DBUSTRACE(("%s\n", __FUNCTION__));
+ DHD_MUTEX_LOCK();
+ if (g_pub) {
+ g_pub->dhd_remove = TRUE;
+ if (!g_pub->bus) {
+ dhd_dbus_disconnect_cb(g_pub->bus);
+ }
+ }
probe_cb = NULL;
+ DHD_MUTEX_UNLOCK();
ret = dbus_bus_deregister();
disconnect_cb = NULL;
probe_arg = NULL;
-
- return ret;
-
}
/** As part of initialization, data structures have to be allocated and initialized */
-dbus_pub_t *
-dbus_attach(osl_t *osh, int rxsize, int nrxq, int ntxq, void *cbarg,
+dhd_bus_t *
+dbus_attach(osl_t *osh, int rxsize, int nrxq, int ntxq, dhd_pub_t *pub,
dbus_callbacks_t *cbs, dbus_extdl_t *extdl, struct shared_info *sh)
{
- dbus_info_t *dbus_info;
+ dhd_bus_t *dhd_bus;
int err;
if ((g_busintf == NULL) || (g_busintf->attach == NULL) || (cbs == NULL))
if ((nrxq <= 0) || (ntxq <= 0))
return NULL;
- dbus_info = MALLOC(osh, sizeof(dbus_info_t));
- if (dbus_info == NULL)
+ dhd_bus = MALLOC(osh, sizeof(dhd_bus_t));
+ if (dhd_bus == NULL) {
+ DBUSERR(("%s: malloc failed %d\n", __FUNCTION__, (int)sizeof(dhd_bus_t)));
return NULL;
+ }
- bzero(dbus_info, sizeof(dbus_info_t));
+ bzero(dhd_bus, sizeof(dhd_bus_t));
/* BUS-specific driver interface (at a lower DBUS level) */
- dbus_info->drvintf = g_busintf;
- dbus_info->cbarg = cbarg;
- dbus_info->cbs = cbs;
-
- dbus_info->pub.sh = sh;
- dbus_info->pub.osh = osh;
- dbus_info->pub.rxsize = rxsize;
+ dhd_bus->drvintf = g_busintf;
+ dhd_bus->cbarg = pub;
+ dhd_bus->cbs = cbs;
+ dhd_bus->pub.sh = sh;
+ dhd_bus->pub.osh = osh;
+ dhd_bus->pub.rxsize = rxsize;
- dbus_info->pub.nrxq = nrxq;
- dbus_info->rx_low_watermark = nrxq / 2; /* keep enough posted rx urbs */
- dbus_info->pub.ntxq = ntxq;
- dbus_info->tx_low_watermark = ntxq / 4; /* flow control when too many tx urbs posted */
+ dhd_bus->pub.nrxq = nrxq;
+ dhd_bus->rx_low_watermark = nrxq / 2; /* keep enough posted rx urbs */
+ dhd_bus->pub.ntxq = ntxq;
+ dhd_bus->tx_low_watermark = ntxq / 4; /* flow control when too many tx urbs posted */
- dbus_info->tx_q = MALLOC(osh, sizeof(dbus_irbq_t));
- if (dbus_info->tx_q == NULL)
+ dhd_bus->tx_q = MALLOC(osh, sizeof(dbus_irbq_t));
+ if (dhd_bus->tx_q == NULL)
goto error;
else {
- bzero(dbus_info->tx_q, sizeof(dbus_irbq_t));
- err = dbus_irbq_init(dbus_info, dbus_info->tx_q, ntxq, sizeof(dbus_irb_tx_t));
+ bzero(dhd_bus->tx_q, sizeof(dbus_irbq_t));
+ err = dbus_irbq_init(dhd_bus, dhd_bus->tx_q, ntxq, sizeof(dbus_irb_tx_t));
if (err != DBUS_OK)
goto error;
}
- dbus_info->rx_q = MALLOC(osh, sizeof(dbus_irbq_t));
- if (dbus_info->rx_q == NULL)
+ dhd_bus->rx_q = MALLOC(osh, sizeof(dbus_irbq_t));
+ if (dhd_bus->rx_q == NULL)
goto error;
else {
- bzero(dbus_info->rx_q, sizeof(dbus_irbq_t));
- err = dbus_irbq_init(dbus_info, dbus_info->rx_q, nrxq, sizeof(dbus_irb_rx_t));
+ bzero(dhd_bus->rx_q, sizeof(dbus_irbq_t));
+ err = dbus_irbq_init(dhd_bus, dhd_bus->rx_q, nrxq, sizeof(dbus_irb_rx_t));
if (err != DBUS_OK)
goto error;
}
- dbus_info->bus_info = (void *)g_busintf->attach(&dbus_info->pub,
- dbus_info, &dbus_intf_cbs);
- if (dbus_info->bus_info == NULL)
+ dhd_bus->bus_info = (void *)g_busintf->attach(&dhd_bus->pub,
+ dhd_bus, &dbus_intf_cbs);
+ if (dhd_bus->bus_info == NULL)
goto error;
- dbus_tx_timer_init(dbus_info);
+ dbus_tx_timer_init(dhd_bus);
#if defined(BCM_REQUEST_FW)
/* Need to copy external image for re-download */
if (extdl && extdl->fw && (extdl->fwlen > 0)) {
- dbus_info->extdl.fw = MALLOC(osh, extdl->fwlen);
- if (dbus_info->extdl.fw) {
- bcopy(extdl->fw, dbus_info->extdl.fw, extdl->fwlen);
- dbus_info->extdl.fwlen = extdl->fwlen;
+ dhd_bus->extdl.fw = MALLOC(osh, extdl->fwlen);
+ if (dhd_bus->extdl.fw) {
+ bcopy(extdl->fw, dhd_bus->extdl.fw, extdl->fwlen);
+ dhd_bus->extdl.fwlen = extdl->fwlen;
}
}
if (extdl && extdl->vars && (extdl->varslen > 0)) {
- dbus_info->extdl.vars = MALLOC(osh, extdl->varslen);
- if (dbus_info->extdl.vars) {
- bcopy(extdl->vars, dbus_info->extdl.vars, extdl->varslen);
- dbus_info->extdl.varslen = extdl->varslen;
+ dhd_bus->extdl.vars = MALLOC(osh, extdl->varslen);
+ if (dhd_bus->extdl.vars) {
+ bcopy(extdl->vars, dhd_bus->extdl.vars, extdl->varslen);
+ dhd_bus->extdl.varslen = extdl->varslen;
}
}
-
- if (dbus_download_firmware(&dbus_info->pub) != DBUS_OK)
- goto error;
#endif
- return (dbus_pub_t *)dbus_info;
+ return (dhd_bus_t *)dhd_bus;
error:
- dbus_detach((dbus_pub_t *)dbus_info);
+ DBUSERR(("%s: Failed\n", __FUNCTION__));
+ dbus_detach(dhd_bus);
return NULL;
} /* dbus_attach */
void
-dbus_detach(dbus_pub_t *pub)
+dbus_detach(dhd_bus_t *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
osl_t *osh;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return;
- dbus_tx_timer_stop(dbus_info);
+ dbus_tx_timer_stop(dhd_bus);
- osh = pub->osh;
+ osh = pub->pub.osh;
- if (dbus_info->drvintf && dbus_info->drvintf->detach)
- dbus_info->drvintf->detach((dbus_pub_t *)dbus_info, dbus_info->bus_info);
+ if (dhd_bus->drvintf && dhd_bus->drvintf->detach)
+ dhd_bus->drvintf->detach((dbus_pub_t *)dhd_bus, dhd_bus->bus_info);
- if (dbus_info->tx_q) {
- dbus_irbq_deinit(dbus_info, dbus_info->tx_q, sizeof(dbus_irb_tx_t));
- MFREE(osh, dbus_info->tx_q, sizeof(dbus_irbq_t));
- dbus_info->tx_q = NULL;
+ if (dhd_bus->tx_q) {
+ dbus_irbq_deinit(dhd_bus, dhd_bus->tx_q, sizeof(dbus_irb_tx_t));
+ MFREE(osh, dhd_bus->tx_q, sizeof(dbus_irbq_t));
+ dhd_bus->tx_q = NULL;
}
- if (dbus_info->rx_q) {
- dbus_irbq_deinit(dbus_info, dbus_info->rx_q, sizeof(dbus_irb_rx_t));
- MFREE(osh, dbus_info->rx_q, sizeof(dbus_irbq_t));
- dbus_info->rx_q = NULL;
+ if (dhd_bus->rx_q) {
+ dbus_irbq_deinit(dhd_bus, dhd_bus->rx_q, sizeof(dbus_irb_rx_t));
+ MFREE(osh, dhd_bus->rx_q, sizeof(dbus_irbq_t));
+ dhd_bus->rx_q = NULL;
}
- if (dbus_info->extdl.fw && (dbus_info->extdl.fwlen > 0)) {
- MFREE(osh, dbus_info->extdl.fw, dbus_info->extdl.fwlen);
- dbus_info->extdl.fw = NULL;
- dbus_info->extdl.fwlen = 0;
+ if (dhd_bus->extdl.fw && (dhd_bus->extdl.fwlen > 0)) {
+ MFREE(osh, dhd_bus->extdl.fw, dhd_bus->extdl.fwlen);
+ dhd_bus->extdl.fw = NULL;
+ dhd_bus->extdl.fwlen = 0;
}
- if (dbus_info->extdl.vars && (dbus_info->extdl.varslen > 0)) {
- MFREE(osh, dbus_info->extdl.vars, dbus_info->extdl.varslen);
- dbus_info->extdl.vars = NULL;
- dbus_info->extdl.varslen = 0;
+ if (dhd_bus->extdl.vars && (dhd_bus->extdl.varslen > 0)) {
+ MFREE(osh, dhd_bus->extdl.vars, dhd_bus->extdl.varslen);
+ dhd_bus->extdl.vars = NULL;
+ dhd_bus->extdl.varslen = 0;
}
- MFREE(osh, dbus_info, sizeof(dbus_info_t));
+ MFREE(osh, dhd_bus, sizeof(dhd_bus_t));
} /* dbus_detach */
-#if defined(BCM_REQUEST_FW)
+int dbus_dlneeded(dhd_bus_t *pub)
+{
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
+ int dlneeded = DBUS_ERR;
-int dbus_download_firmware(dbus_pub_t *pub)
+ if (!dhd_bus) {
+ DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
+ return DBUS_ERR;
+ }
+
+ DBUSTRACE(("%s: state %d\n", __FUNCTION__, dhd_bus->pub.busstate));
+
+ if (dhd_bus->drvintf->dlneeded) {
+ dlneeded = dhd_bus->drvintf->dlneeded(dhd_bus->bus_info);
+ }
+ printf("%s: dlneeded=%d\n", __FUNCTION__, dlneeded);
+
+ /* dlneeded > 0: need to download
+ * dlneeded = 0: downloaded
+ * dlneeded < 0: bus error*/
+ return dlneeded;
+}
+
+#if defined(BCM_REQUEST_FW)
+int dbus_download_firmware(dhd_bus_t *pub, char *pfw_path, char *pnv_path)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_OK;
- DBUSTRACE(("%s: state %d\n", __FUNCTION__, dbus_info->pub.busstate));
+ if (!dhd_bus) {
+ DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
+ return DBUS_ERR;
+ }
+
+ DBUSTRACE(("%s: state %d\n", __FUNCTION__, dhd_bus->pub.busstate));
- if (dbus_info->drvintf->dlneeded) {
- if (dbus_info->drvintf->dlneeded(dbus_info->bus_info)) {
- dbus_info->pub.busstate = DBUS_STATE_DL_PENDING;
- err = dbus_do_download(dbus_info);
- if (err == DBUS_OK) {
- dbus_info->pub.busstate = DBUS_STATE_DL_DONE;
- } else {
- DBUSERR(("%s: download failed (%d)\n", __FUNCTION__, err));
- }
- }
+ dhd_bus->pub.busstate = DBUS_STATE_DL_PENDING;
+#ifdef EXTERNAL_FW_PATH
+ err = dbus_do_download(dhd_bus, pfw_path, pnv_path);
+#else
+ err = dbus_do_download(dhd_bus);
+#endif /* EXTERNAL_FW_PATH */
+ if (err == DBUS_OK) {
+ dhd_bus->pub.busstate = DBUS_STATE_DL_DONE;
+ } else {
+ DBUSERR(("%s: download failed (%d)\n", __FUNCTION__, err));
}
return err;
}
-
#endif
/**
* bootloader) must be active in the dongle.
*/
int
-dbus_up(dbus_pub_t *pub)
+dbus_up(struct dhd_bus *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_OK;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL) {
+ DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
return DBUS_ERR;
+ }
- if ((dbus_info->pub.busstate == DBUS_STATE_DL_DONE) ||
- (dbus_info->pub.busstate == DBUS_STATE_DOWN) ||
- (dbus_info->pub.busstate == DBUS_STATE_SLEEP)) {
- if (dbus_info->drvintf && dbus_info->drvintf->up) {
- err = dbus_info->drvintf->up(dbus_info->bus_info);
+ if ((dhd_bus->pub.busstate == DBUS_STATE_DL_DONE) ||
+ (dhd_bus->pub.busstate == DBUS_STATE_DOWN) ||
+ (dhd_bus->pub.busstate == DBUS_STATE_SLEEP)) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->up) {
+ err = dhd_bus->drvintf->up(dhd_bus->bus_info);
if (err == DBUS_OK) {
- dbus_rxirbs_fill(dbus_info);
+ dbus_rxirbs_fill(dhd_bus);
}
}
} else
int
dbus_down(dbus_pub_t *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- dbus_tx_timer_stop(dbus_info);
+ dbus_tx_timer_stop(dhd_bus);
- if (dbus_info->pub.busstate == DBUS_STATE_UP ||
- dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
- if (dbus_info->drvintf && dbus_info->drvintf->down)
- return dbus_info->drvintf->down(dbus_info->bus_info);
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+ dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->down)
+ return dhd_bus->drvintf->down(dhd_bus->bus_info);
}
return DBUS_ERR;
int
dbus_shutdown(dbus_pub_t *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- if (dbus_info->drvintf && dbus_info->drvintf->shutdown)
- return dbus_info->drvintf->shutdown(dbus_info->bus_info);
+ if (dhd_bus->drvintf && dhd_bus->drvintf->shutdown)
+ return dhd_bus->drvintf->shutdown(dhd_bus->bus_info);
return DBUS_OK;
}
int
-dbus_stop(dbus_pub_t *pub)
+dbus_stop(struct dhd_bus *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- if (dbus_info->pub.busstate == DBUS_STATE_UP ||
- dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
- if (dbus_info->drvintf && dbus_info->drvintf->stop)
- return dbus_info->drvintf->stop(dbus_info->bus_info);
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+ dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->stop)
+ return dhd_bus->drvintf->stop(dhd_bus->bus_info);
}
return DBUS_ERR;
}
int
-dbus_send_ctl(dbus_pub_t *pub, uint8 *buf, int len)
+dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL) {
+ DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
return DBUS_ERR;
+ }
- if (dbus_info->pub.busstate == DBUS_STATE_UP ||
- dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
- if (dbus_info->drvintf && dbus_info->drvintf->send_ctl)
- return dbus_info->drvintf->send_ctl(dbus_info->bus_info, buf, len);
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+ dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->send_ctl)
+ return dhd_bus->drvintf->send_ctl(dhd_bus->bus_info, buf, len);
+ } else {
+ DBUSERR(("%s: bustate=%d\n", __FUNCTION__, dhd_bus->pub.busstate));
}
return DBUS_ERR;
}
int
-dbus_recv_ctl(dbus_pub_t *pub, uint8 *buf, int len)
+dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
- if ((dbus_info == NULL) || (buf == NULL))
+ if ((dhd_bus == NULL) || (buf == NULL))
return DBUS_ERR;
- if (dbus_info->pub.busstate == DBUS_STATE_UP ||
- dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
- if (dbus_info->drvintf && dbus_info->drvintf->recv_ctl)
- return dbus_info->drvintf->recv_ctl(dbus_info->bus_info, buf, len);
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+ dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->recv_ctl)
+ return dhd_bus->drvintf->recv_ctl(dhd_bus->bus_info, buf, len);
}
return DBUS_ERR;
int
dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
dbus_irb_rx_t *rxirb;
struct exec_parms args;
int status;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- args.qdeq.q = dbus_info->rx_q;
- if (dbus_info->pub.busstate == DBUS_STATE_UP) {
- if (dbus_info->drvintf && dbus_info->drvintf->recv_irb_from_ep) {
- if ((rxirb = (EXEC_RXLOCK(dbus_info, q_deq_exec, &args))) != NULL) {
- status = dbus_info->drvintf->recv_irb_from_ep(dbus_info->bus_info,
+ args.qdeq.q = dhd_bus->rx_q;
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->recv_irb_from_ep) {
+ if ((rxirb = (EXEC_RXLOCK(dhd_bus, q_deq_exec, &args))) != NULL) {
+ status = dhd_bus->drvintf->recv_irb_from_ep(dhd_bus->bus_info,
rxirb, ep_idx);
if (status == DBUS_ERR_RXDROP) {
bzero(rxirb, sizeof(dbus_irb_rx_t));
- args.qenq.q = dbus_info->rx_q;
+ args.qenq.q = dhd_bus->rx_q;
args.qenq.b = (dbus_irb_t *) rxirb;
- EXEC_RXLOCK(dbus_info, q_enq_exec, &args);
+ EXEC_RXLOCK(dhd_bus, q_enq_exec, &args);
}
}
}
int
dbus_poll_intr(dbus_pub_t *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int status = DBUS_ERR;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- if (dbus_info->pub.busstate == DBUS_STATE_UP) {
- if (dbus_info->drvintf && dbus_info->drvintf->recv_irb_from_ep) {
- status = dbus_info->drvintf->recv_irb_from_ep(dbus_info->bus_info,
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
+ if (dhd_bus->drvintf && dhd_bus->drvintf->recv_irb_from_ep) {
+ status = dhd_bus->drvintf->recv_irb_from_ep(dhd_bus->bus_info,
NULL, 0xff);
}
}
void *
dbus_pktget(dbus_pub_t *pub, int len)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
- if ((dbus_info == NULL) || (len < 0))
+ if ((dhd_bus == NULL) || (len < 0))
return NULL;
- return PKTGET(dbus_info->pub.osh, len, TRUE);
+ return PKTGET(dhd_bus->pub.osh, len, TRUE);
}
/** called by nobody (Dec 2012) */
void
dbus_pktfree(dbus_pub_t *pub, void* pkt)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
- if ((dbus_info == NULL) || (pkt == NULL))
+ if ((dhd_bus == NULL) || (pkt == NULL))
return;
- PKTFREE(dbus_info->pub.osh, pkt, TRUE);
+ PKTFREE(dhd_bus->pub.osh, pkt, TRUE);
}
/** called by nobody (Dec 2012) */
int
dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
- if ((dbus_info == NULL) || (stats == NULL))
+ if ((dhd_bus == NULL) || (stats == NULL))
return DBUS_ERR;
- bcopy(&dbus_info->pub.stats, stats, sizeof(dbus_stats_t));
+ bcopy(&dhd_bus->pub.stats, stats, sizeof(dbus_stats_t));
return DBUS_OK;
}
int
-dbus_get_attrib(dbus_pub_t *pub, dbus_attrib_t *attrib)
+dbus_get_attrib(dhd_bus_t *pub, dbus_attrib_t *attrib)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_ERR;
- if ((dbus_info == NULL) || (attrib == NULL))
+ if ((dhd_bus == NULL) || (attrib == NULL))
return DBUS_ERR;
- if (dbus_info->drvintf && dbus_info->drvintf->get_attrib) {
- err = dbus_info->drvintf->get_attrib(dbus_info->bus_info,
- &dbus_info->pub.attrib);
+ if (dhd_bus->drvintf && dhd_bus->drvintf->get_attrib) {
+ err = dhd_bus->drvintf->get_attrib(dhd_bus->bus_info,
+ &dhd_bus->pub.attrib);
}
- bcopy(&dbus_info->pub.attrib, attrib, sizeof(dbus_attrib_t));
+ bcopy(&dhd_bus->pub.attrib, attrib, sizeof(dbus_attrib_t));
return err;
}
int
dbus_get_device_speed(dbus_pub_t *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return INVALID_SPEED;
- return (dbus_info->pub.device_speed);
+ return (dhd_bus->pub.device_speed);
}
int
dbus_set_config(dbus_pub_t *pub, dbus_config_t *config)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_ERR;
- if ((dbus_info == NULL) || (config == NULL))
+ if ((dhd_bus == NULL) || (config == NULL))
return DBUS_ERR;
- if (dbus_info->drvintf && dbus_info->drvintf->set_config) {
- err = dbus_info->drvintf->set_config(dbus_info->bus_info,
+ if (dhd_bus->drvintf && dhd_bus->drvintf->set_config) {
+ err = dhd_bus->drvintf->set_config(dhd_bus->bus_info,
config);
if ((config->config_id == DBUS_CONFIG_ID_AGGR_LIMIT) &&
(!err) &&
- (dbus_info->pub.busstate == DBUS_STATE_UP)) {
- dbus_rxirbs_fill(dbus_info);
+ (dhd_bus->pub.busstate == DBUS_STATE_UP)) {
+ dbus_rxirbs_fill(dhd_bus);
}
}
int
dbus_get_config(dbus_pub_t *pub, dbus_config_t *config)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_ERR;
- if ((dbus_info == NULL) || (config == NULL))
+ if ((dhd_bus == NULL) || (config == NULL))
return DBUS_ERR;
- if (dbus_info->drvintf && dbus_info->drvintf->get_config) {
- err = dbus_info->drvintf->get_config(dbus_info->bus_info,
+ if (dhd_bus->drvintf && dhd_bus->drvintf->get_config) {
+ err = dhd_bus->drvintf->get_config(dhd_bus->bus_info,
config);
}
int
dbus_set_errmask(dbus_pub_t *pub, uint32 mask)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_OK;
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- dbus_info->errmask = mask;
+ dhd_bus->errmask = mask;
return err;
}
int
dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_ERR;
bool fwdl = FALSE;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- if (dbus_info->pub.busstate == DBUS_STATE_UP) {
+ if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
return DBUS_OK;
}
- if (dbus_info->drvintf->pnp) {
- err = dbus_info->drvintf->pnp(dbus_info->bus_info,
+ if (dhd_bus->drvintf->pnp) {
+ err = dhd_bus->drvintf->pnp(dhd_bus->bus_info,
DBUS_PNP_RESUME);
}
- if (dbus_info->drvintf->recv_needed) {
- if (dbus_info->drvintf->recv_needed(dbus_info->bus_info)) {
+ if (dhd_bus->drvintf->recv_needed) {
+ if (dhd_bus->drvintf->recv_needed(dhd_bus->bus_info)) {
/* Refill after sleep/hibernate */
- dbus_rxirbs_fill(dbus_info);
+ dbus_rxirbs_fill(dhd_bus);
}
}
int
dbus_pnp_sleep(dbus_pub_t *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_ERR;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- dbus_tx_timer_stop(dbus_info);
+ dbus_tx_timer_stop(dhd_bus);
- if (dbus_info->drvintf && dbus_info->drvintf->pnp) {
- err = dbus_info->drvintf->pnp(dbus_info->bus_info,
+ if (dhd_bus->drvintf && dhd_bus->drvintf->pnp) {
+ err = dhd_bus->drvintf->pnp(dhd_bus->bus_info,
DBUS_PNP_SLEEP);
}
int
dbus_pnp_disconnect(dbus_pub_t *pub)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
int err = DBUS_ERR;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- dbus_tx_timer_stop(dbus_info);
+ dbus_tx_timer_stop(dhd_bus);
- if (dbus_info->drvintf && dbus_info->drvintf->pnp) {
- err = dbus_info->drvintf->pnp(dbus_info->bus_info,
+ if (dhd_bus->drvintf && dhd_bus->drvintf->pnp) {
+ err = dhd_bus->drvintf->pnp(dhd_bus->bus_info,
DBUS_PNP_DISCONNECT);
}
}
int
-dbus_iovar_op(dbus_pub_t *pub, const char *name,
+dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
void *params, int plen, void *arg, int len, bool set)
{
- dbus_info_t *dbus_info = (dbus_info_t *) pub;
+ dhd_bus_t *dhd_bus = (dhd_bus_t *) dhdp->bus;
int err = DBUS_ERR;
DBUSTRACE(("%s\n", __FUNCTION__));
- if (dbus_info == NULL)
+ if (dhd_bus == NULL)
return DBUS_ERR;
- if (dbus_info->drvintf && dbus_info->drvintf->iovar_op) {
- err = dbus_info->drvintf->iovar_op(dbus_info->bus_info,
+ if (dhd_bus->drvintf && dhd_bus->drvintf->iovar_op) {
+ err = dhd_bus->drvintf->iovar_op(dhd_bus->bus_info,
name, params, plen, arg, len, set);
}
return pub->dev_info;
}
-#if defined(BCM_REQUEST_FW)
-
+#if defined(BCM_REQUEST_FW) && !defined(EXTERNAL_FW_PATH)
static int
-dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev)
+dbus_otp(dhd_bus_t *dhd_bus, uint16 *boardtype, uint16 *boardrev)
{
uint32 value = 0;
uint8 *cis;
uint16 brev = 0;
uint32 otp_size = 0, otp_addr = 0, otp_sw_rgn = 0;
- if (dbus_info == NULL || dbus_info->drvintf == NULL ||
- dbus_info->drvintf->readreg == NULL)
+ if (dhd_bus == NULL || dhd_bus->drvintf == NULL ||
+ dhd_bus->drvintf->readreg == NULL)
return DBUS_ERR;
- devid = dbus_info->pub.attrib.devid;
+ devid = dhd_bus->pub.attrib.devid;
if ((devid == BCM43234_CHIP_ID) || (devid == BCM43235_CHIP_ID) ||
(devid == BCM43236_CHIP_ID)) {
return DBUS_ERR_NVRAM;
}
- cis = MALLOC(dbus_info->pub.osh, otp_size * 2);
+ cis = MALLOC(dhd_bus->pub.osh, otp_size * 2);
if (cis == NULL)
return DBUS_ERR;
for (i = 0; i < otp_size; i++) {
- ret = dbus_info->drvintf->readreg(dbus_info->bus_info,
+ ret = dhd_bus->drvintf->readreg(dhd_bus->bus_info,
otp_addr + ((otp_sw_rgn + i) << 1), 2, &value);
if (ret != DBUS_OK) {
- MFREE(dbus_info->pub.osh, cis, otp_size * 2);
+ MFREE(dhd_bus->pub.osh, cis, otp_size * 2);
return ret;
}
otpinfo[i] = (uint16) value;
i += tlen;
}
- MFREE(dbus_info->pub.osh, cis, otp_size * 2);
+ MFREE(dhd_bus->pub.osh, cis, otp_size * 2);
if (btype_present == TRUE && brev_present == TRUE) {
*boardtype = btype;
} /* dbus_otp */
static int
-dbus_select_nvram(dbus_info_t *dbus_info, int8 *jumbonvram, int jumbolen,
+dbus_select_nvram(dhd_bus_t *dhd_bus, int8 *jumbonvram, int jumbolen,
uint16 boardtype, uint16 boardrev, int8 **nvram, int *nvram_len)
{
/* Multi board nvram file format is contenation of nvram info with \r
return DBUS_JUMBO_BAD_FORMAT;
}
- dbus_info->nvram_nontxt = DBUS_NVRAM_NONTXT;
+ dhd_bus->nvram_nontxt = DBUS_NVRAM_NONTXT;
nvram_start = jumbonvram;
#endif
+#define DBUS_NRXQ 50
+#define DBUS_NTXQ 100
+
+static void
+dhd_dbus_send_complete(void *handle, void *info, int status)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+ void *pkt = info;
+
+ if ((dhd == NULL) || (pkt == NULL)) {
+ DBUSERR(("dhd or pkt is NULL\n"));
+ return;
+ }
+
+ if (status == DBUS_OK) {
+ dhd->dstats.tx_packets++;
+ } else {
+ DBUSERR(("TX error=%d\n", status));
+ dhd->dstats.tx_errors++;
+ }
+#ifdef PROP_TXSTATUS
+ if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) &&
+ (dhd_wlfc_txcomplete(dhd, pkt, status == 0) != WLFC_UNSUPPORTED)) {
+ return;
+ }
+#endif /* PROP_TXSTATUS */
+ PKTFREE(dhd->osh, pkt, TRUE);
+}
+
+static void
+dhd_dbus_recv_pkt(void *handle, void *pkt)
+{
+ uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
+ uint reorder_info_len;
+ uint pkt_count;
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+ int ifidx = 0;
+
+ if (dhd == NULL) {
+ DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+ return;
+ }
+
+ /* If the protocol uses a data header, check and remove it */
+ if (dhd_prot_hdrpull(dhd, &ifidx, pkt, reorder_info_buf,
+ &reorder_info_len) != 0) {
+ DBUSERR(("rx protocol error\n"));
+ PKTFREE(dhd->osh, pkt, FALSE);
+ dhd->rx_errors++;
+ return;
+ }
+
+ if (reorder_info_len) {
+ /* Reordering info from the firmware */
+ dhd_process_pkt_reorder_info(dhd, reorder_info_buf, reorder_info_len,
+ &pkt, &pkt_count);
+ if (pkt_count == 0)
+ return;
+ }
+ else {
+ pkt_count = 1;
+ }
+ dhd_rx_frame(dhd, ifidx, pkt, pkt_count, 0);
+}
+
+static void
+dhd_dbus_recv_buf(void *handle, uint8 *buf, int len)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+ void *pkt;
+
+ if (dhd == NULL) {
+ DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+ return;
+ }
+
+ if ((pkt = PKTGET(dhd->osh, len, FALSE)) == NULL) {
+ DBUSERR(("PKTGET (rx) failed=%d\n", len));
+ return;
+ }
+
+ bcopy(buf, PKTDATA(dhd->osh, pkt), len);
+ dhd_dbus_recv_pkt(dhd, pkt);
+}
+
+static void
+dhd_dbus_txflowcontrol(void *handle, bool onoff)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+ bool wlfc_enabled = FALSE;
+
+ if (dhd == NULL) {
+ DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+ return;
+ }
+
+#ifdef PROP_TXSTATUS
+ wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, onoff, !onoff) != WLFC_UNSUPPORTED);
+#endif
+
+ if (!wlfc_enabled) {
+ dhd_txflowcontrol(dhd, ALL_INTERFACES, onoff);
+ }
+}
+
+static void
+dhd_dbus_errhandler(void *handle, int err)
+{
+}
+
+static void
+dhd_dbus_ctl_complete(void *handle, int type, int status)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+
+ if (dhd == NULL) {
+ DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+ return;
+ }
+
+ if (type == DBUS_CBCTL_READ) {
+ if (status == DBUS_OK)
+ dhd->rx_ctlpkts++;
+ else
+ dhd->rx_ctlerrs++;
+ } else if (type == DBUS_CBCTL_WRITE) {
+ if (status == DBUS_OK)
+ dhd->tx_ctlpkts++;
+ else
+ dhd->tx_ctlerrs++;
+ }
+
+ dhd_prot_ctl_complete(dhd);
+}
+
+static void
+dhd_dbus_state_change(void *handle, int state)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+
+ if (dhd == NULL) {
+ DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+ return;
+ }
+
+ switch (state) {
+
+ case DBUS_STATE_DL_NEEDED:
+ DBUSERR(("%s: firmware request cannot be handled\n", __FUNCTION__));
+ break;
+ case DBUS_STATE_DOWN:
+ DBUSTRACE(("%s: DBUS is down\n", __FUNCTION__));
+ dhd->busstate = DHD_BUS_DOWN;
+ break;
+ case DBUS_STATE_UP:
+ DBUSTRACE(("%s: DBUS is up\n", __FUNCTION__));
+ dhd->busstate = DHD_BUS_DATA;
+ break;
+ default:
+ break;
+ }
+
+ DBUSERR(("%s: DBUS current state=%d\n", __FUNCTION__, state));
+}
+
+static void *
+dhd_dbus_pktget(void *handle, uint len, bool send)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+ void *p = NULL;
+
+ if (dhd == NULL) {
+ DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+ return NULL;
+ }
+
+ if (send == TRUE) {
+ dhd_os_sdlock_txq(dhd);
+ p = PKTGET(dhd->osh, len, TRUE);
+ dhd_os_sdunlock_txq(dhd);
+ } else {
+ dhd_os_sdlock_rxq(dhd);
+ p = PKTGET(dhd->osh, len, FALSE);
+ dhd_os_sdunlock_rxq(dhd);
+ }
+
+ return p;
+}
+
+static void
+dhd_dbus_pktfree(void *handle, void *p, bool send)
+{
+ dhd_pub_t *dhd = (dhd_pub_t *)handle;
+
+ if (dhd == NULL) {
+ DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+ return;
+ }
+
+ if (send == TRUE) {
+#ifdef PROP_TXSTATUS
+ if (DHD_PKTTAG_WLFCPKT(PKTTAG(p)) &&
+ (dhd_wlfc_txcomplete(dhd, p, FALSE) != WLFC_UNSUPPORTED)) {
+ return;
+ }
+#endif /* PROP_TXSTATUS */
+
+ dhd_os_sdlock_txq(dhd);
+ PKTFREE(dhd->osh, p, TRUE);
+ dhd_os_sdunlock_txq(dhd);
+ } else {
+ dhd_os_sdlock_rxq(dhd);
+ PKTFREE(dhd->osh, p, FALSE);
+ dhd_os_sdunlock_rxq(dhd);
+ }
+}
+
+
+static dbus_callbacks_t dhd_dbus_cbs = {
+ dhd_dbus_send_complete,
+ dhd_dbus_recv_buf,
+ dhd_dbus_recv_pkt,
+ dhd_dbus_txflowcontrol,
+ dhd_dbus_errhandler,
+ dhd_dbus_ctl_complete,
+ dhd_dbus_state_change,
+ dhd_dbus_pktget,
+ dhd_dbus_pktfree
+};
+
+uint
+dhd_bus_chip(struct dhd_bus *bus)
+{
+ ASSERT(bus != NULL);
+ return bus->pub.attrib.devid;
+}
+
+uint
+dhd_bus_chiprev(struct dhd_bus *bus)
+{
+ ASSERT(bus);
+ ASSERT(bus != NULL);
+ return bus->pub.attrib.chiprev;
+}
+
+void
+dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+{
+ bcm_bprintf(strbuf, "Bus USB\n");
+}
+
+void
+dhd_bus_clearcounts(dhd_pub_t *dhdp)
+{
+}
+
+int
+dhd_bus_txdata(struct dhd_bus *bus, void *pktbuf)
+{
+ DBUSTRACE(("%s\n", __FUNCTION__));
+ if (bus->txoff) {
+ DBUSTRACE(("txoff\n"));
+ return BCME_EPERM;
+ }
+ return dbus_send_txdata(&bus->pub, pktbuf);
+}
+
+static void
+dhd_dbus_advertise_bus_cleanup(dhd_pub_t *dhdp)
+{
+ unsigned long flags;
+ int timeleft;
+
+ DHD_LINUX_GENERAL_LOCK(dhdp, flags);
+ dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS;
+ DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
+
+ timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
+ if ((timeleft == 0) || (timeleft == 1)) {
+ DBUSERR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
+ __FUNCTION__, dhdp->dhd_bus_busy_state));
+ ASSERT(0);
+ }
+
+ return;
+}
+
+static void
+dhd_dbus_advertise_bus_remove(dhd_pub_t *dhdp)
+{
+ unsigned long flags;
+ int timeleft;
+
+ DHD_LINUX_GENERAL_LOCK(dhdp, flags);
+ dhdp->busstate = DHD_BUS_REMOVE;
+ DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
+
+ timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
+ if ((timeleft == 0) || (timeleft == 1)) {
+ DBUSERR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
+ __FUNCTION__, dhdp->dhd_bus_busy_state));
+ ASSERT(0);
+ }
+
+ return;
+}
+
+int
+dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
+{
+ int bcmerror = 0;
+ unsigned long flags;
+ wifi_adapter_info_t *adapter = (wifi_adapter_info_t *)dhdp->adapter;
+
+ if (flag == TRUE) {
+ if (!dhdp->dongle_reset) {
+ DBUSERR(("%s: == Power OFF ==\n", __FUNCTION__));
+ dhd_dbus_advertise_bus_cleanup(dhdp);
+ dhd_os_wd_timer(dhdp, 0);
+#if !defined(IGNORE_ETH0_DOWN)
+ /* Force flow control as protection when stop come before ifconfig_down */
+ dhd_txflowcontrol(dhdp, ALL_INTERFACES, ON);
+#endif /* !defined(IGNORE_ETH0_DOWN) */
+ dbus_stop(dhdp->bus);
+
+ dhdp->dongle_reset = TRUE;
+ dhdp->up = FALSE;
+
+ DHD_LINUX_GENERAL_LOCK(dhdp, flags);
+ dhdp->busstate = DHD_BUS_DOWN;
+ DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
+ wifi_clr_adapter_status(adapter, WIFI_STATUS_FW_READY);
+
+ printf("%s: WLAN OFF DONE\n", __FUNCTION__);
+ /* App can now remove power from device */
+ } else
+ bcmerror = BCME_ERROR;
+ } else {
+ /* App must have restored power to device before calling */
+ printf("\n\n%s: == WLAN ON ==\n", __FUNCTION__);
+ if (dhdp->dongle_reset) {
+ /* Turn on WLAN */
+ DHD_MUTEX_UNLOCK();
+ wait_event_interruptible_timeout(adapter->status_event,
+ wifi_get_adapter_status(adapter, WIFI_STATUS_FW_READY),
+ msecs_to_jiffies(DHD_FW_READY_TIMEOUT));
+ DHD_MUTEX_LOCK();
+ bcmerror = dbus_up(dhdp->bus);
+ if (bcmerror == BCME_OK) {
+ dhdp->dongle_reset = FALSE;
+ dhdp->up = TRUE;
+#if !defined(IGNORE_ETH0_DOWN)
+ /* Restore flow control */
+ dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
+#endif
+ dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
+
+ DBUSTRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
+ } else {
+ DBUSERR(("%s: failed to dbus_up with code %d\n", __FUNCTION__, bcmerror));
+ }
+ }
+ }
+
+#ifdef PKT_STATICS
+ memset((uint8*) &tx_statics, 0, sizeof(pkt_statics_t));
+#endif
+ return bcmerror;
+}
+
+void
+dhd_set_path_params(struct dhd_bus *bus)
+{
+ /* External conf takes precedence if specified */
+ dhd_conf_preinit(bus->dhd);
+
+ if (bus->dhd->conf_path[0] == '\0') {
+ dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_path);
+ }
+ if (bus->dhd->clm_path[0] == '\0') {
+ dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path);
+ }
+#ifdef CONFIG_PATH_AUTO_SELECT
+ dhd_conf_set_conf_name_by_chip(bus->dhd, bus->dhd->conf_path);
+#endif
+
+ dhd_conf_read_config(bus->dhd, bus->dhd->conf_path);
+
+ dhd_conf_set_fw_name_by_chip(bus->dhd, bus->fw_path);
+ dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path);
+ dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path);
+
+ printf("Final fw_path=%s\n", bus->fw_path);
+ printf("Final nv_path=%s\n", bus->nv_path);
+ printf("Final clm_path=%s\n", bus->dhd->clm_path);
+ printf("Final conf_path=%s\n", bus->dhd->conf_path);
+
+}
+
+void
+dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path,
+ char *pnv_path, char *pclm_path, char *pconf_path)
+{
+ DBUSTRACE(("%s\n", __FUNCTION__));
+
+ if (bus == NULL) {
+ DBUSERR(("%s: bus is NULL\n", __FUNCTION__));
+ return;
+ }
+
+ bus->fw_path = pfw_path;
+ bus->nv_path = pnv_path;
+ bus->dhd->clm_path = pclm_path;
+ bus->dhd->conf_path = pconf_path;
+
+ dhd_set_path_params(bus);
+
+}
+
+/*
+ * hdrlen is space to reserve in pkt headroom for DBUS
+ */
+void *
+dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype,
+ uint16 bus_no, uint16 slot, uint32 hdrlen)
+{
+ osl_t *osh = NULL;
+ dhd_bus_t *bus = NULL;
+ dhd_pub_t *pub = NULL;
+ uint rxsz;
+ int dlneeded = 0;
+ wifi_adapter_info_t *adapter = NULL;
+
+ DBUSTRACE(("%s: Enter\n", __FUNCTION__));
+
+ adapter = dhd_wifi_platform_get_adapter(bustype, bus_no, slot);
+
+ if (!g_pub) {
+ /* Ask the OS interface part for an OSL handle */
+ if (!(osh = osl_attach(NULL, bustype, TRUE))) {
+ DBUSERR(("%s: OSL attach failed\n", __FUNCTION__));
+ goto fail;
+ }
+
+ /* Attach to the dhd/OS interface */
+ if (!(pub = dhd_attach(osh, bus, hdrlen, adapter))) {
+ DBUSERR(("%s: dhd_attach failed\n", __FUNCTION__));
+ goto fail;
+ }
+ } else {
+ pub = g_pub;
+ }
+
+ if (pub->bus) {
+ DBUSERR(("%s: wrong probe\n", __FUNCTION__));
+ goto fail;
+ }
+
+ rxsz = dhd_get_rxsz(pub);
+ bus = dbus_attach(osh, rxsz, DBUS_NRXQ, DBUS_NTXQ, pub, &dhd_dbus_cbs, NULL, NULL);
+ if (bus) {
+ pub->bus = bus;
+ bus->dhd = pub;
+
+ dlneeded = dbus_dlneeded(bus);
+ if (dlneeded >= 0) {
+ if (!g_pub) {
+ dhd_conf_reset(pub);
+ dhd_conf_set_chiprev(pub, bus->pub.attrib.devid, bus->pub.attrib.chiprev);
+ dhd_conf_preinit(pub);
+ }
+ }
+
+ if (g_pub || dhd_download_fw_on_driverload) {
+ if (dlneeded == 0) {
+ wifi_set_adapter_status(adapter, WIFI_STATUS_FW_READY);
+#ifdef BCM_REQUEST_FW
+ } else if (dlneeded > 0) {
+ dhd_set_path(bus->dhd);
+ if (dbus_download_firmware(bus, bus->fw_path, bus->nv_path) != DBUS_OK)
+ goto fail;
+#endif
+ }
+ }
+ } else {
+ DBUSERR(("%s: dbus_attach failed\n", __FUNCTION__));
+ }
+
+ if (!g_pub) {
+ /* Ok, finish the attach to the OS network interface */
+ if (dhd_register_if(pub, 0, TRUE) != 0) {
+ DBUSERR(("%s: dhd_register_if failed\n", __FUNCTION__));
+ goto fail;
+ }
+ pub->hang_report = TRUE;
+#if defined(MULTIPLE_SUPPLICANT)
+ wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
+#endif
+ g_pub = pub;
+ }
+
+ DBUSTRACE(("%s: Exit\n", __FUNCTION__));
+ wifi_clr_adapter_status(adapter, WIFI_STATUS_DETTACH);
+ wifi_set_adapter_status(adapter, WIFI_STATUS_ATTACH);
+ wake_up_interruptible(&adapter->status_event);
+ /* This is passed to dhd_dbus_disconnect_cb */
+ return bus;
+
+fail:
+ if (pub && pub->bus) {
+ dbus_detach(pub->bus);
+ pub->bus = NULL;
+ }
+ /* Release resources in reverse order */
+ if (!g_pub) {
+ if (pub) {
+ dhd_detach(pub);
+ dhd_free(pub);
+ }
+ if (osh) {
+ osl_detach(osh);
+ }
+ }
+
+ printf("%s: Failed\n", __FUNCTION__);
+ return NULL;
+}
+
+void
+dhd_dbus_disconnect_cb(void *arg)
+{
+ dhd_bus_t *bus = (dhd_bus_t *)arg;
+ dhd_pub_t *pub = g_pub;
+ osl_t *osh;
+ wifi_adapter_info_t *adapter = NULL;
+
+ adapter = (wifi_adapter_info_t *)pub->adapter;
+
+ if (pub && !pub->dhd_remove && bus == NULL) {
+ DBUSERR(("%s: bus is NULL\n", __FUNCTION__));
+ return;
+ }
+ if (!adapter) {
+ DBUSERR(("%s: adapter is NULL\n", __FUNCTION__));
+ return;
+ }
+
+ printf("%s: Enter dhd_remove=%d on %s\n", __FUNCTION__,
+ pub->dhd_remove, adapter->name);
+ if (!pub->dhd_remove) {
+ /* Advertise bus remove during rmmod */
+ dhd_dbus_advertise_bus_remove(bus->dhd);
+ dbus_detach(pub->bus);
+ pub->bus = NULL;
+ wifi_clr_adapter_status(adapter, WIFI_STATUS_ATTACH);
+ wifi_set_adapter_status(adapter, WIFI_STATUS_DETTACH);
+ wake_up_interruptible(&adapter->status_event);
+ } else {
+ osh = pub->osh;
+ dhd_detach(pub);
+ if (pub->bus) {
+ dbus_detach(pub->bus);
+ pub->bus = NULL;
+ }
+ dhd_free(pub);
+ g_pub = NULL;
+ if (MALLOCED(osh)) {
+ DBUSERR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh)));
+ }
+ osl_detach(osh);
+ }
+
+ DBUSTRACE(("%s: Exit\n", __FUNCTION__));
+}
#ifdef LINUX_EXTERNAL_MODULE_DBUS
}
EXPORT_SYMBOL(dbus_pnp_sleep);
-EXPORT_SYMBOL(dbus_register);
EXPORT_SYMBOL(dbus_get_devinfo);
EXPORT_SYMBOL(dbus_detach);
EXPORT_SYMBOL(dbus_get_attrib);
EXPORT_SYMBOL(dbus_send_pkt);
EXPORT_SYMBOL(dbus_recv_ctl);
EXPORT_SYMBOL(dbus_attach);
-EXPORT_SYMBOL(dbus_deregister);
MODULE_LICENSE("GPL");
static void dbus_usb_state_change(void *handle, int state);
static struct dbus_irb* dbus_usb_getirb(void *handle, bool send);
static void dbus_usb_rxerr_indicate(void *handle, bool on);
+#if !defined(BCM_REQUEST_FW)
static int dbus_usb_resetcfg(usb_info_t *usbinfo);
+#endif
static int dbus_usb_iovar_op(void *bus, const char *name,
void *params, int plen, void *arg, int len, bool set);
static int dbus_iovar_process(usb_info_t* usbinfo, const char *name,
static int dbus_usb_dl_writeimage(usb_info_t *usbinfo, uint8 *fw, int fwlen);
static int dbus_usb_dlstart(void *bus, uint8 *fw, int len);
-static bool dbus_usb_dlneeded(void *bus);
+static int dbus_usb_dlneeded(void *bus);
static int dbus_usb_dlrun(void *bus);
static int dbus_usb_rdl_dwnld_state(usb_info_t *usbinfo);
*/
static void *dbus_usb_attach(dbus_pub_t *pub, void *cbarg, dbus_intf_callbacks_t *cbs);
static void dbus_usb_detach(dbus_pub_t *pub, void *info);
-static void * dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
+static void * dbus_usb_probe(void *arg, const char *desc, uint32 bustype,
+ uint16 bus_no, uint16 slot, uint32 hdrlen);
/* functions */
* lower level DBUS functions to call (in both dbus_usb.c and dbus_usb_os.c).
*/
static void *
-dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
+dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint16 bus_no,
+ uint16 slot, uint32 hdrlen)
{
DBUSTRACE(("%s(): \n", __FUNCTION__));
if (probe_cb) {
dbus_usb_intf.dlrun = dbus_usb_dlrun;
}
- disc_arg = probe_cb(probe_arg, "DBUS USB", USB_BUS, hdrlen);
+ disc_arg = probe_cb(probe_arg, "DBUS USB", USB_BUS, bus_no, slot, hdrlen);
return disc_arg;
}
usb_info->drvintf = g_dbusintf;
pub->bus = usb_info;
-#if !defined(BCM_REQUEST_FW)
-
+#if !defined(BCM_REQUEST_FW)
if (!dbus_usb_resetcfg(usb_info)) {
- usb_info->pub->busstate = DBUS_STATE_DL_DONE;
+ usb_info->pub->busstate = DBUS_STATE_DL_DONE;
}
#endif
/* Return Lower layer info */
return bcmerror;
} /* dbus_usb_doiovar */
+#if !defined(BCM_REQUEST_FW)
/**
* After downloading firmware into dongle and starting it, we need to know if the firmware is
* indeed up and running.
return DBUS_OK;
}
+#endif
/** before firmware download, the dongle has to be prepared to receive the fw image */
static int
err = dbus_usb_rdl_dwnld_state(usbinfo);
if (DBUS_OK == err) {
- err = dbus_usb_dl_writeimage(usbinfo, fw, len);
- if (err == DBUS_OK)
- usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
- else
- usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
+ err = dbus_usb_dl_writeimage(usbinfo, fw, len);
+ if (err == DBUS_OK)
+ usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
+ else
+ usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
} else
usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
} /* dbus_usb_update_chipinfo */
/** higher DBUS level (dbus.c) wants to know if firmware download is required. */
-static bool
+static int
dbus_usb_dlneeded(void *bus)
{
usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
void *osinfo;
bootrom_id_t id;
- bool dl_needed = TRUE;
+ int dl_needed = 1;
DBUSTRACE(("%s\n", __FUNCTION__));
if (usbinfo == NULL)
- return FALSE;
+ return DBUS_ERR;
osinfo = usbinfo->usbosl_info;
ASSERT(osinfo);
id.chiprev = ltoh32(id.chiprev);
if (FALSE == dbus_usb_update_chipinfo(usbinfo, id.chip)) {
- dl_needed = FALSE;
+ dl_needed = DBUS_ERR;
goto exit;
}
DBUSERR(("%s: Firmware already downloaded\n", __FUNCTION__));
dbus_usbos_dl_cmd(osinfo, DL_RESETCFG, &id, sizeof(bootrom_id_t));
- dl_needed = FALSE;
+ dl_needed = DBUS_OK;
if (usbinfo->pub->busstate == DBUS_STATE_DL_PENDING)
usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
} else {
if (usbinfo->pub->attrib.devid == TEST_CHIP)
dbus_usbos_wait(osinfo, USB_DLGO_SPINWAIT);
- dbus_usb_resetcfg(usbinfo);
+// dbus_usb_resetcfg(usbinfo);
/* The Donlge may go for re-enumeration. */
} else {
DBUSERR(("%s: Dongle not runnable\n", __FUNCTION__));
#include <linux/usb.h>
#include <usbrdl.h>
#include <linux/firmware.h>
+#include <dngl_stats.h>
+#include <dhd.h>
#if defined(USBOS_THREAD) || defined(USBOS_TX_THREAD)
int wlan_if = -1;
bool intr_ep = FALSE;
#endif /* BCMUSBDEV_COMPOSITE */
+ wifi_adapter_info_t *adapter;
- printf("%s: Enter\n", __FUNCTION__);
+ DHD_MUTEX_LOCK();
+
+ DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
+ usb->bus->busnum, usb->portnum));
+ adapter = dhd_wifi_platform_attach_adapter(USB_BUS, usb->bus->busnum,
+ usb->portnum, WIFI_STATUS_POWER_ON);
+ if (adapter == NULL) {
+ DBUSERR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
+ goto fail;
+ }
#ifdef BCMUSBDEV_COMPOSITE
wlan_if = dbus_usbos_intf_wlan(usb);
DBUSERR(("full speed device detected\n"));
}
if (g_probe_info.dereged == FALSE && probe_cb) {
- disc_arg = probe_cb(probe_arg, "", USB_BUS, 0);
+ disc_arg = probe_cb(probe_arg, "", USB_BUS, usb->bus->busnum, usb->portnum, 0);
}
g_probe_info.disc_cb_done = FALSE;
#ifdef KERNEL26
intf->needs_remote_wakeup = 1;
#endif /* KERNEL26 */
- printf("%s: Exit ret=%d\n", __FUNCTION__, ret);
+ DHD_MUTEX_UNLOCK();
/* Success */
#ifdef KERNEL26
#endif /* BCMUSBDEV_COMPOSITE */
#endif /* !KERNEL26 */
+ DHD_MUTEX_UNLOCK();
#ifdef KERNEL26
usb_set_intfdata(intf, NULL);
return ret;
#endif
usbos_info_t *usbos_info;
- printf("%s: Enter\n", __FUNCTION__);
+ DHD_MUTEX_LOCK();
+
+ DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
+ usb->bus->busnum, usb->portnum));
if (probe_usb_init_data) {
usbos_info = (usbos_info_t *) probe_usb_init_data->usbos_info;
usb_dec_dev_use(usb);
#endif /* !KERNEL26 */
}
- printf("%s: Exit\n", __FUNCTION__);
+ DHD_MUTEX_UNLOCK();
} /* dbus_usbos_disconnect */
#define LOOPBACK_PKT_START 0xBABE1234
{
g_probe_info.dereged = TRUE;
+ DHD_MUTEX_LOCK();
if (disconnect_cb && disc_arg && (g_probe_info.disc_cb_done == FALSE)) {
disconnect_cb(disc_arg);
disc_arg = NULL;
}
+ DHD_MUTEX_UNLOCK();
USB_DEREGISTER();
#if defined(STAT_REPORT)
void *stat_report_info;
#endif
- char *clm_path; /* module_param: path to clm vars file */
- char *conf_path; /* module_param: path to config vars file */
+ char *clm_path; /* module_param: path to clm vars file */
+ char *conf_path; /* module_param: path to config vars file */
struct dhd_conf *conf; /* Bus module handle */
+ void *adapter; /* adapter information, interrupt, fw path etc. */
+#ifdef BCMDBUS
+ bool dhd_remove;
+#endif /* BCMDBUS */
} dhd_pub_t;
typedef struct {
*/
void dhd_net_if_lock(struct net_device *dev);
void dhd_net_if_unlock(struct net_device *dev);
-
#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
-extern struct mutex _dhd_sdio_mutex_lock_;
+extern void wl_android_post_init(void); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && defined(MULTIPLE_SUPPLICANT)
+extern struct mutex _dhd_mutex_lock_;
+#define DHD_MUTEX_IS_LOCK_RETURN() \
+ if (mutex_is_locked(&_dhd_mutex_lock_) != 0) { \
+ printf("%s : probe is already running! return.\n", __FUNCTION__); \
+ return 0; \
+ }
+#define DHD_MUTEX_LOCK() \
+ do { \
+ if (mutex_is_locked(&_dhd_mutex_lock_) == 0) { \
+ printf("%s : no mutex held. set lock\n", __FUNCTION__); \
+ } else { \
+ printf("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__); \
+ } \
+ mutex_lock(&_dhd_mutex_lock_); \
+ } while (0)
+#define DHD_MUTEX_UNLOCK() \
+ do { \
+ mutex_unlock(&_dhd_mutex_lock_); \
+ printf("%s : the lock is released.\n", __FUNCTION__); \
+ } while (0)
+#else
+#define DHD_MUTEX_IS_LOCK_RETURN(a) do {} while (0)
+#define DHD_MUTEX_LOCK(a) do {} while (0)
+#define DHD_MUTEX_UNLOCK(a) do {} while (0)
#endif
-#endif /* MULTIPLE_SUPPLICANT */
typedef enum dhd_attach_states
{
* Returned structure should have bus and prot pointers filled in.
* bus_hdrlen specifies required headroom for bus module header.
*/
-extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen);
+extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen
+#ifdef BCMDBUS
+ , void *adapter
+#endif
+);
#if defined(WLP2P) && defined(WL_CFG80211)
/* To allow attach/detach calls corresponding to p2p0 interface */
extern int dhd_attach_p2p(dhd_pub_t *);
extern void dhd_dump_to_kernelog(dhd_pub_t *dhdp);
#ifdef BCMDBUS
+extern uint dhd_get_rxsz(dhd_pub_t *pub);
+extern void dhd_set_path(dhd_pub_t *pub);
extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
#endif /* BCMDBUS */
#ifndef _dhd_bus_h_
#define _dhd_bus_h_
+extern int dbus_up(struct dhd_bus *pub);
+extern int dbus_stop(struct dhd_bus *pub);
+extern int dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len);
+extern int dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len);
/*
* Exported from dhd bus module (dhd_usb, dhd_sdio)
*/
#include <dngl_stats.h>
#include <dhd.h>
#include <dhd_proto.h>
-#ifdef BCMDBUS
-#include <dbus.h>
-#else
#include <dhd_bus.h>
-#endif /* BCMDBUS */
#include <dhd_dbg.h>
#include <wlfc_proto.h>
#include <dhd_wlfc.h>
#endif
+#ifdef BCMDBUS
+#include <dhd_config.h>
+#endif /* BCMDBUS */
#ifdef DHD_ULP
#include <dhd_ulp.h>
unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
} dhd_prot_t;
-#if defined(BCMDBUS)
-extern int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf);
-#endif /* BCMDBUS */
-
static int
dhdcdc_msg(dhd_pub_t *dhd)
{
#ifdef BCMDBUS
DHD_OS_IOCTL_RESP_LOCK(dhd);
prot->ctl_completed = FALSE;
- err = dbus_send_ctl(dhd->dbus, (void *)&prot->msg, len);
+ err = dbus_send_ctl(dhd->bus, (void *)&prot->msg, len);
if (err) {
- DHD_ERROR(("dbus_send_ctl error=0x%x\n", err));
+ DHD_ERROR(("dbus_send_ctl error=%d\n", err));
DHD_OS_IOCTL_RESP_UNLOCK(dhd);
DHD_OS_WAKE_UNLOCK(dhd);
return err;
#ifdef BCMDBUS
DHD_OS_IOCTL_RESP_LOCK(dhd);
prot->ctl_completed = FALSE;
- ret = dbus_recv_ctl(dhd->dbus, (uchar*)&prot->msg, cdc_len);
+ ret = dbus_recv_ctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
if (ret) {
DHD_ERROR(("dbus_recv_ctl error=0x%x(%d)\n", ret, ret));
DHD_OS_IOCTL_RESP_UNLOCK(dhd);
#ifdef BCMDBUS
#ifndef DHD_WLFC_THREAD
dhd_wlfc_commit_packets(dhd,
- (f_commitpkt_t)dhd_dbus_txdata, (void *)dhd, NULL, FALSE);
+ (f_commitpkt_t)dhd_bus_txdata, dhd->bus, NULL, FALSE);
#endif /* DHD_WLFC_THREAD */
#endif /* BCMDBUS */
}
ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
if (ret < 0)
goto done;
+#if defined(BCMDBUS)
+ if (dhd_download_fw_on_driverload) {
+ dhd_conf_reset(dhd);
+ dhd_conf_set_chiprev(dhd, revinfo.chipnum, revinfo.chiprev);
+ dhd_conf_preinit(dhd);
+ dhd_conf_read_config(dhd, dhd->conf_path);
+ }
+#endif /* BCMDBUS */
DHD_SSSR_DUMP_INIT(dhd);
#include <dhd_flowring.h>
#endif
-#ifdef BCMDBUS
-#include <dbus.h>
-#else
#include <dhd_bus.h>
-#endif /* BCMDBUS */
#include <dhd_proto.h>
#include <dhd_config.h>
#include <bcmsdbus.h>
/* if still not found, try bus module */
if (ioc->cmd == DHD_GET_VAR) {
-#ifdef BCMDBUS
- bcmerror = dbus_iovar_op(dhd_pub->dbus, buf,
- arg, arglen, buf, buflen, IOV_GET);
-#else
bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
arg, arglen, buf, buflen, IOV_GET);
-#endif /* BCMDBUS */
} else {
-#ifdef BCMDBUS
- bcmerror = dbus_iovar_op(dhd_pub->dbus, buf,
- NULL, 0, arg, arglen, IOV_SET);
-#else
bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
NULL, 0, arg, arglen, IOV_SET);
-#endif /* BCMDBUS */
}
if (bcmerror != BCME_UNSUPPORTED) {
goto unlock_exit;
htod16(WL_PKT_FILTER_MFLAG_NEG);
(argv[i])++;
}
- if (argv[i] == '\0') {
+ if (*argv[i] == '\0') {
printf("Pattern not provided\n");
goto fail;
}
char iovbuf[WLC_IOCTL_SMLEN] = {0};
int status = FALSE;
- if (clm_path[0] != '\0') {
+ if (clm_path && clm_path[0] != '\0') {
if (strlen(clm_path) > MOD_PARAM_PATHLEN) {
DHD_ERROR(("clm path exceeds max len\n"));
return BCME_ERROR;
{BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "bcm40181a2", ""},\r
{BCM4330_CHIP_ID, 4, FW_TYPE_G, FALSE, "bcm40183b2", ""},\r
{BCM4330_CHIP_ID, 4, FW_TYPE_AG, FALSE, "bcm40183b2_ag", ""},\r
- {BCM43430_CHIP_ID, 0, DONT_CARE, FALSE, "bcm43438a0", "nvram_ap6212.txt"},\r
- {BCM43430_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43438a1", "nvram_ap6212a.txt"},\r
- {BCM43430_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43436b0", "nvram_ap6236.txt"},\r
+ {BCM43430_CHIP_ID, 0, DONT_CARE, FALSE, "bcm43438a0", "ap6212"},\r
+ {BCM43430_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43438a1", "ap6212a"},\r
+ {BCM43430_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43436b0", "ap6236"},\r
{BCM43012_CHIP_ID, 1, DONT_CARE, TRUE, "bcm43013b0", ""},\r
{BCM4334_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4334b1_ag", ""},\r
{BCM43340_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""},\r
{BCM43341_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""},\r
{BCM4324_CHIP_ID, 5, DONT_CARE, FALSE, "bcm43241b4_ag", ""},\r
{BCM4335_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4339a0_ag", ""},\r
- {BCM4339_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4339a0_ag", "nvram_ap6335.txt"},\r
- {BCM4345_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", "nvram_ap6255.txt"},\r
+ {BCM4339_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4339a0_ag", "ap6335"},\r
+ {BCM4345_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", "ap6255"},\r
{BCM43454_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", ""},\r
- {BCM4345_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", "nvram_ap6256.txt"},\r
- {BCM43454_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43455c5_ag", ""},\r
+ {BCM4345_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", "ap6256"},\r
+ {BCM43454_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", ""},\r
{BCM4354_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4354a1_ag", ""},\r
- {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "nvram_ap6356.txt"},\r
+ {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "ap6356"},\r
{BCM4356_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", ""},\r
{BCM4371_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", ""},\r
{BCM43569_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4358a3_ag", ""},\r
{BCM4359_CHIP_ID, 5, DONT_CARE, FALSE, "bcm4359b1_ag", ""},\r
- {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_ag", "nvram_ap6398.txt"},\r
+ {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_ag", "ap6398s"},\r
{BCM4362_CHIP_ID, 0, DONT_CARE, TRUE, "bcm43752a0_ag", ""},\r
#endif\r
#ifdef BCMPCIE\r
{BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_pcie_ag", ""},\r
{BCM4362_CHIP_ID, 0, DONT_CARE, TRUE, "bcm43752a0_pcie_ag", ""},\r
#endif\r
+#ifdef BCMDBUS\r
+ {BCM43143_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43143b0", ""},\r
+ {BCM43242_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43242a1_ag", ""},\r
+ {BCM43569_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4358u_ag", "ap62x8"},\r
+#endif\r
};\r
\r
#ifdef BCMSDIO\r
(row->ag_type == ag_type || row->ag_type == DONT_CARE)) {\r
strcpy(name_ptr, "fw_");\r
strcat(fw_path, row->chip_name);\r
+#ifdef BCMUSBDEV_COMPOSITE\r
+ strcat(fw_path, "_cusb");\r
+#endif\r
if (fw_type == FW_TYPE_APSTA)\r
strcat(fw_path, "_apsta.bin");\r
else if (fw_type == FW_TYPE_P2P)\r
for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {\r
const cihp_name_map_t* row = &chip_name_map[i];\r
if (row->chip == chip && row->chiprev == chiprev && strlen(row->module_name)) {\r
- strcpy(name_ptr, row->module_name);\r
+ strcpy(name_ptr, "nvram_");\r
+ strcat(name_ptr, row->module_name);\r
+#ifdef BCMUSBDEV_COMPOSITE\r
+ strcat(name_ptr, "_cusb");\r
+#endif\r
+ strcat(name_ptr, ".txt");\r
}\r
}\r
\r
}\r
\r
int\r
-dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec, int nodfs)\r
+dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)\r
{\r
int bcmerror = -1, i;\r
struct dhd_conf *conf = dhd->conf;\r
- conf_country_list_t *country_list;\r
-\r
- if ((nodfs > 0 || dhd->op_mode & DHD_FLAG_HOSTAP_MODE) &&\r
- conf->country_list_nodfs.count > 0) {\r
- country_list = &conf->country_list_nodfs;\r
- } else {\r
- country_list = &conf->country_list;\r
- }\r
+ conf_country_list_t *country_list = &conf->country_list;\r
\r
for (i = 0; i < country_list->count; i++) {\r
if (!strncmp(cspec->country_abbrev, country_list->cspec[i]->country_abbrev, 2)) {\r
memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ);\r
cspec->rev = country_list->cspec[i]->rev;\r
- printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev);\r
- return 0;\r
+ bcmerror = 0;\r
}\r
}\r
\r
+ if (!bcmerror)\r
+ printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev);\r
+\r
return bcmerror;\r
}\r
\r
dtoh32(list->count)<11)) {\r
CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n",\r
__FUNCTION__, bcmerror, dtoh32(list->count)));\r
- dhd_conf_map_country_list(dhd, &dhd->conf->cspec, 0);\r
+ dhd_conf_map_country_list(dhd, &dhd->conf->cspec);\r
if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) {\r
strcpy(cspec.country_abbrev, "US");\r
cspec.rev = 0;\r
strcpy(cspec.ccode, "US");\r
- dhd_conf_map_country_list(dhd, &cspec, 0);\r
+ dhd_conf_map_country_list(dhd, &cspec);\r
dhd_conf_set_country(dhd, &cspec);\r
}\r
}\r
u32 bw_cap;\r
} param = {0, 0};\r
\r
- if (dhd->conf->bw_cap_2g >= 0) {\r
+ if (dhd->conf->bw_cap[0] >= 0) {\r
+ memset(¶m, 0, sizeof(param));\r
param.band = WLC_BAND_2G;\r
- param.bw_cap = (uint)dhd->conf->bw_cap_2g;\r
- printf("%s: set bw_cap 2g %d\n", __FUNCTION__, param.bw_cap);\r
+ param.bw_cap = (uint)dhd->conf->bw_cap[0];\r
+ printf("%s: set bw_cap 2g 0x%x\n", __FUNCTION__, param.bw_cap);\r
dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "bw_cap", (char *)¶m, sizeof(param), TRUE);\r
}\r
\r
- if (dhd->conf->bw_cap_5g >= 0) {\r
+ if (dhd->conf->bw_cap[1] >= 0) {\r
+ memset(¶m, 0, sizeof(param));\r
param.band = WLC_BAND_5G;\r
- param.bw_cap = (uint)dhd->conf->bw_cap_5g;\r
- printf("%s: set bw_cap 5g %d\n", __FUNCTION__, param.bw_cap);\r
+ param.bw_cap = (uint)dhd->conf->bw_cap[1];\r
+ printf("%s: set bw_cap 5g 0x%x\n", __FUNCTION__, param.bw_cap);\r
dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "bw_cap", (char *)¶m, sizeof(param), TRUE);\r
}\r
}\r
dhd_conf_get_pm(dhd_pub_t *dhd)\r
{\r
if (dhd && dhd->conf) {\r
- if (dhd->conf->fw_type == FW_TYPE_MESH)\r
- return PM_OFF;\r
- else\r
- return dhd->conf->pm;\r
+ return dhd->conf->pm;\r
}\r
return -1;\r
}\r
if (pick) {\r
if (varbuf[n] == 0x9)\r
continue;\r
- if (pick_column>0 && pickbuf[pick_column-1]==' ' && varbuf[n]==' ')\r
- continue;\r
pickbuf[pick_column] = varbuf[n];\r
pick_column++;\r
}\r
*/\r
if (!strncmp("country_list=", full_param, len_param)) {\r
country_list = &dhd->conf->country_list;\r
- } else if (!strncmp("country_list_nodfs=", full_param, len_param)) {\r
- country_list = &dhd->conf->country_list_nodfs;\r
}\r
if (country_list) {\r
pick_tmp = data;\r
}\r
if (!strncmp("country_list=", full_param, len_param)) {\r
printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count);\r
- } else if (!strncmp("country_list_nodfs=", full_param, len_param)) {\r
- printf("%s: %d nodfs country in list\n", __FUNCTION__, conf->country_list.count);\r
}\r
}\r
else\r
}\r
#endif\r
\r
-#ifdef IAPSTA_PREINIT\r
+#ifdef ISAM_PREINIT\r
/*\r
- * iapsta_init=mode [sta|ap|apsta|dualap] vifname [wlan1]\r
- * iapsta_config=ifname [wlan0|wlan1] ssid [xxx] chan [x]\r
+ * isam_init=mode [sta|ap|apsta|dualap] vifname [wlan1]\r
+ * isam_config=ifname [wlan0|wlan1] ssid [xxx] chan [x]\r
hidden [y|n] maxassoc [x]\r
amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\r
emode [none|wep|tkip|aes|tkipaes]\r
key [xxxxx]\r
- * iapsta_enable=ifname [wlan0|wlan1]\r
+ * isam_enable=ifname [wlan0|wlan1]\r
*/\r
bool\r
-dhd_conf_read_iapsta(dhd_pub_t *dhd, char *full_param, uint len_param)\r
+dhd_conf_read_isam(dhd_pub_t *dhd, char *full_param, uint len_param)\r
{\r
struct dhd_conf *conf = dhd->conf;\r
char *data = full_param+len_param;\r
\r
- if (!strncmp("iapsta_init=", full_param, len_param)) {\r
- sprintf(conf->iapsta_init, "iapsta_init %s", data);\r
- printf("%s: iapsta_init=%s\n", __FUNCTION__, conf->iapsta_init);\r
+ if (!strncmp("isam_init=", full_param, len_param)) {\r
+ sprintf(conf->isam_init, "isam_init %s", data);\r
+ printf("%s: isam_init=%s\n", __FUNCTION__, conf->isam_init);\r
}\r
- else if (!strncmp("iapsta_config=", full_param, len_param)) {\r
- sprintf(conf->iapsta_config, "iapsta_config %s", data);\r
- printf("%s: iapsta_config=%s\n", __FUNCTION__, conf->iapsta_config);\r
+ else if (!strncmp("isam_config=", full_param, len_param)) {\r
+ sprintf(conf->isam_config, "isam_config %s", data);\r
+ printf("%s: isam_config=%s\n", __FUNCTION__, conf->isam_config);\r
}\r
- else if (!strncmp("iapsta_enable=", full_param, len_param)) {\r
- sprintf(conf->iapsta_enable, "iapsta_enable %s", data);\r
- printf("%s: iapsta_enable=%s\n", __FUNCTION__, conf->iapsta_enable);\r
+ else if (!strncmp("isam_enable=", full_param, len_param)) {\r
+ sprintf(conf->isam_enable, "isam_enable %s", data);\r
+ printf("%s: isam_enable=%s\n", __FUNCTION__, conf->isam_enable);\r
}\r
else\r
return false;\r
conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 10);\r
printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix);\r
}\r
- else if (!strncmp("tx_in_rx=", full_param, len_param)) {\r
- if (!strncmp(data, "0", 1))\r
- conf->tx_in_rx = FALSE;\r
- else\r
- conf->tx_in_rx = TRUE;\r
- printf("%s: tx_in_rx = %d\n", __FUNCTION__, conf->tx_in_rx);\r
- }\r
else if (!strncmp("tx_max_offset=", full_param, len_param)) {\r
conf->tx_max_offset = (int)simple_strtol(data, NULL, 10);\r
printf("%s: tx_max_offset = %d\n", __FUNCTION__, conf->tx_max_offset);\r
printf("%s: band = %d\n", __FUNCTION__, conf->band);\r
}\r
else if (!strncmp("bw_cap_2g=", full_param, len_param)) {\r
- conf->bw_cap_2g = (uint)simple_strtol(data, NULL, 0);\r
- printf("%s: bw_cap_2g = %d\n", __FUNCTION__, conf->bw_cap_2g);\r
+ conf->bw_cap[0] = (uint)simple_strtol(data, NULL, 0);\r
+ printf("%s: bw_cap_2g = %d\n", __FUNCTION__, conf->bw_cap[0]);\r
}\r
else if (!strncmp("bw_cap_5g=", full_param, len_param)) {\r
- conf->bw_cap_5g = (uint)simple_strtol(data, NULL, 0);\r
- printf("%s: bw_cap_5g = %d\n", __FUNCTION__, conf->bw_cap_5g);\r
+ conf->bw_cap[1] = (uint)simple_strtol(data, NULL, 0);\r
+ printf("%s: bw_cap_5g = %d\n", __FUNCTION__, conf->bw_cap[1]);\r
+ }\r
+ else if (!strncmp("bw_cap=", full_param, len_param)) {\r
+ pick_tmp = data;\r
+ pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
+ if (pch != NULL) {\r
+ conf->bw_cap[0] = (uint32)simple_strtol(pch, NULL, 0);\r
+ printf("%s: bw_cap 2g = %d\n", __FUNCTION__, conf->bw_cap[0]);\r
+ }\r
+ pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
+ if (pch != NULL) {\r
+ conf->bw_cap[1] = (uint32)simple_strtol(pch, NULL, 0);\r
+ printf("%s: bw_cap 5g = %d\n", __FUNCTION__, conf->bw_cap[1]);\r
+ }\r
}\r
else if (!strncmp("ccode=", full_param, len_param)) {\r
memset(&conf->cspec, 0, sizeof(wl_country_t));\r
printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound);\r
}\r
#endif\r
- else if (!strncmp("num_different_channels=", full_param, len_param)) {\r
- conf->num_different_channels = (int)simple_strtol(data, NULL, 10);\r
- printf("%s: num_different_channels = %d\n", __FUNCTION__, conf->num_different_channels);\r
- }\r
else if (!strncmp("tsq=", full_param, len_param)) {\r
conf->tsq = (int)simple_strtol(data, NULL, 10);\r
printf("%s: tsq = %d\n", __FUNCTION__, conf->tsq);\r
conf->dhd_ioctl_timeout_msec = (int)simple_strtol(data, NULL, 10);\r
printf("%s: dhd_ioctl_timeout_msec = %d\n", __FUNCTION__, conf->dhd_ioctl_timeout_msec);\r
}\r
+ else if (!strncmp("in4way=", 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("wl_preinit=", full_param, len_param)) {\r
- if (!(conf->wl_preinit = kmalloc(len_param, GFP_KERNEL))) {\r
+ if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) {\r
CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
} else {\r
- memset(conf->wl_preinit, 0, len_param);\r
+ memset(conf->wl_preinit, 0, len_param+1);\r
strcpy(conf->wl_preinit, data);\r
printf("%s: wl_preinit = %s\n", __FUNCTION__, conf->wl_preinit);\r
}\r
else if (dhd_conf_read_pkt_filter(dhd, pick, len_param))\r
continue;\r
#endif /* PKT_FILTER_SUPPORT */\r
-#ifdef IAPSTA_PREINIT\r
- else if (dhd_conf_read_iapsta(dhd, pick, len_param))\r
+#ifdef ISAM_PREINIT\r
+ else if (dhd_conf_read_isam(dhd, pick, len_param))\r
continue;\r
-#endif /* IAPSTA_PREINIT */\r
+#endif /* ISAM_PREINIT */\r
#ifdef IDHCP\r
else if (dhd_conf_read_dhcp_params(dhd, pick, len_param))\r
continue;\r
if (conf->txglom_ext)\r
printf("%s: txglom_ext=%d, txglom_bucket_size=%d\n", __FUNCTION__,\r
conf->txglom_ext, conf->txglom_bucket_size);\r
- printf("%s: txglom_mode=%s, use_rxchain=%d\n", __FUNCTION__,\r
- conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy", conf->use_rxchain);\r
+ printf("%s: txglom_mode=%s\n", __FUNCTION__,\r
+ conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy");\r
printf("%s: txglomsize=%d, deferred_tx_len=%d\n", __FUNCTION__,\r
conf->txglomsize, conf->deferred_tx_len);\r
- printf("%s: tx_in_rx=%d, txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__,\r
- conf->tx_in_rx, conf->txinrx_thres, conf->dhd_txminmax);\r
+ printf("%s: txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__,\r
+ conf->txinrx_thres, conf->dhd_txminmax);\r
printf("%s: tx_max_offset=%d, txctl_tmo_fix=%d\n", __FUNCTION__,\r
conf->tx_max_offset, conf->txctl_tmo_fix);\r
\r
}\r
#endif\r
\r
+static int\r
+dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf)\r
+{\r
+ char *pch;\r
+ wl_config_t rsdb_mode_cfg = {1, 0};\r
+\r
+ pch = buf;\r
+ rsdb_mode_cfg.config = (int)simple_strtol(pch, NULL, 0);\r
+\r
+ if (pch) {\r
+ dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg,\r
+ sizeof(rsdb_mode_cfg), TRUE);\r
+ printf("%s: rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf);\r
+\r
+typedef struct iovar_tpl_t {\r
+ int cmd;\r
+ char *name;\r
+ tpl_parse_t *parse;\r
+} iovar_tpl_t;\r
+\r
+const iovar_tpl_t iovar_tpl_list[] = {\r
+ {WLC_SET_VAR, "rsdb_mode", dhd_conf_rsdb_mode},\r
+};\r
+\r
+static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,\r
+ dhd_pub_t *dhd, int cmd, char *name, char *buf)\r
+{\r
+ int i, ret = 0;\r
+\r
+ /* look for a matching code in the table */\r
+ for (i = 0; i < tpl_count; i++, tpl++) {\r
+ if (tpl->cmd == cmd && !strcmp(tpl->name, name))\r
+ break;\r
+ }\r
+ if (i < tpl_count && tpl->parse) {\r
+ ret = tpl->parse(dhd, buf);\r
+ } else {\r
+ ret = -1;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
bool\r
dhd_conf_set_wl_preinit(dhd_pub_t *dhd, char *data)\r
{\r
- int cmd, val;\r
- char name[50], *pch, *pick_tmp, *pick_tmp2;\r
+ int cmd, val, ret = 0;\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=85/0, mpc/0\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
+ while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {\r
pch = bcmstrtok(&pick_tmp2, "=", 0);\r
if (!pch)\r
break;\r
+ if (*pch == ' ') {\r
+ pch++;\r
+ }\r
memset(name, 0 , sizeof (name));\r
cmd = (int)simple_strtol(pch, NULL, 0);\r
if (cmd == 0) {\r
cmd = WLC_SET_VAR;\r
strcpy(name, pch);\r
}\r
- pch = bcmstrtok(&pick_tmp2, ", ", 0);\r
+ pch = bcmstrtok(&pick_tmp2, ",", 0);\r
if (!pch) {\r
break;\r
}\r
- val = (int)simple_strtol(pch, NULL, 0);\r
- dhd_conf_set_intiovar(dhd, cmd, name, val, -1, TRUE);\r
+ ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list),\r
+ dhd, cmd, name, pch);\r
+ if (ret) {\r
+ val = (int)simple_strtol(pch, NULL, 0);\r
+ dhd_conf_set_intiovar(dhd, cmd, name, val, -1, TRUE);\r
+ }\r
}\r
\r
return true;\r
struct dhd_conf *conf = dhd->conf;\r
\r
dhd_conf_set_intiovar(dhd, WLC_UP, "up", 0, 0, FALSE);\r
- dhd_conf_map_country_list(dhd, &conf->cspec, 0);\r
+ dhd_conf_map_country_list(dhd, &conf->cspec);\r
dhd_conf_set_country(dhd, &conf->cspec);\r
dhd_conf_fix_country(dhd);\r
dhd_conf_get_country(dhd, &dhd->dhd_cspec);\r
dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
#endif\r
dhd_conf_free_country_list(&conf->country_list);\r
- dhd_conf_free_country_list(&conf->country_list_nodfs);\r
- if (conf->magic_pkt_filter_add)\r
+ if (conf->magic_pkt_filter_add) {\r
kfree(conf->magic_pkt_filter_add);\r
- if (conf->wl_preinit)\r
+ conf->magic_pkt_filter_add = NULL;\r
+ }\r
+ if (conf->wl_preinit) {\r
kfree(conf->wl_preinit);\r
+ conf->wl_preinit = NULL;\r
+ }\r
memset(&conf->country_list, 0, sizeof(conf_country_list_t));\r
conf->band = -1;\r
- conf->bw_cap_2g = -1;\r
- conf->bw_cap_5g = -1;\r
+ memset(&conf->bw_cap, -1, sizeof(conf->bw_cap));\r
if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {\r
strcpy(conf->cspec.country_abbrev, "ALL");\r
strcpy(conf->cspec.ccode, "ALL");\r
conf->tx_max_offset = 0;\r
conf->txglomsize = SDPCM_DEFGLOM_SIZE;\r
conf->txctl_tmo_fix = 300;\r
- conf->tx_in_rx = TRUE;\r
conf->txglom_mode = SDPCM_TXGLOM_CPY;\r
conf->deferred_tx_len = 0;\r
conf->dhd_txminmax = 1;\r
conf->pm = -1;\r
conf->pm_in_suspend = -1;\r
conf->suspend_bcn_li_dtim = -1;\r
- conf->num_different_channels = -1;\r
conf->xmit_in_suspend = TRUE;\r
conf->ap_in_suspend = 0;\r
#ifdef SUSPEND_EVENT\r
conf->tsq = 0;\r
#endif\r
#ifdef DHDTCPACK_SUPPRESS\r
-#ifdef BCMSDIO\r
- conf->tcpack_sup_mode = TCPACK_SUP_OFF;\r
-#elif defined(BCMPCIE)\r
+#ifdef BCMPCIE\r
conf->tcpack_sup_mode = TCPACK_SUP_DEFAULT;\r
+#else\r
+ conf->tcpack_sup_mode = TCPACK_SUP_OFF;\r
#endif\r
#endif\r
conf->pktprio8021x = -1;\r
conf->ctrl_resched = 2;\r
conf->dhd_ioctl_timeout_msec = 0;\r
-#ifdef IAPSTA_PREINIT\r
- memset(conf->iapsta_init, 0, sizeof(conf->iapsta_init));\r
- memset(conf->iapsta_config, 0, sizeof(conf->iapsta_config));\r
- memset(conf->iapsta_enable, 0, sizeof(conf->iapsta_enable));\r
+ conf->in4way = NO_SCAN_IN4WAY;\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
+ memset(conf->isam_enable, 0, sizeof(conf->isam_enable));\r
#endif\r
for (i=0; i<MCHAN_MAX_NUM; i++) {\r
memset(&conf->mchan[i], -1, sizeof(mchan_params_t));\r
dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
#endif\r
dhd_conf_free_country_list(&dhd->conf->country_list);\r
- dhd_conf_free_country_list(&dhd->conf->country_list_nodfs);\r
- if (dhd->conf->magic_pkt_filter_add)\r
+ if (dhd->conf->magic_pkt_filter_add) {\r
kfree(dhd->conf->magic_pkt_filter_add);\r
- if (dhd->conf->wl_preinit)\r
+ dhd->conf->magic_pkt_filter_add = NULL;\r
+ }\r
+ if (dhd->conf->wl_preinit) {\r
kfree(dhd->conf->wl_preinit);\r
+ dhd->conf->wl_preinit = NULL;\r
+ }\r
memset(dhd->conf, 0, sizeof(dhd_conf_t));\r
return 0;\r
}\r
dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
#endif\r
dhd_conf_free_country_list(&dhd->conf->country_list);\r
- dhd_conf_free_country_list(&dhd->conf->country_list_nodfs);\r
- if (dhd->conf->magic_pkt_filter_add)\r
+ if (dhd->conf->magic_pkt_filter_add) {\r
kfree(dhd->conf->magic_pkt_filter_add);\r
- if (dhd->conf->wl_preinit)\r
+ dhd->conf->magic_pkt_filter_add = NULL;\r
+ }\r
+ if (dhd->conf->wl_preinit) {\r
kfree(dhd->conf->wl_preinit);\r
+ dhd->conf->wl_preinit = NULL;\r
+ }\r
MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));\r
}\r
dhd->conf = NULL;\r
int miracast_mode;
} mchan_params_t;
+enum in4way_flags {
+ NO_SCAN_IN4WAY = (1 << (0)),
+ NO_BTC_IN4WAY = (1 << (1))
+};
+
typedef struct dhd_conf {
uint chip;
uint chiprev;
wl_mac_list_ctrl_t nv_by_mac;
wl_chip_nv_path_list_ctrl_t nv_by_chip;
conf_country_list_t country_list;
- conf_country_list_t country_list_nodfs;
int band;
- int bw_cap_2g;
- int bw_cap_5g;
+ int bw_cap[2];
wl_country_t cspec;
wl_channel_list_t channels;
uint roam_off;
int tx_max_offset;
uint txglomsize;
int txctl_tmo_fix;
- bool tx_in_rx;
bool txglom_mode;
uint deferred_tx_len;
/*txglom_bucket_size:
uint8 tcpack_sup_mode;
#endif
int pktprio8021x;
- int num_different_channels;
int xmit_in_suspend;
int ap_in_suspend;
#ifdef SUSPEND_EVENT
struct ipv4_addr dhcpd_ip_start;
struct ipv4_addr dhcpd_ip_end;
#endif
-#ifdef IAPSTA_PREINIT
- char iapsta_init[50];
- char iapsta_config[300];
- char iapsta_enable[50];
+#ifdef ISAM_PREINIT
+ char isam_init[50];
+ char isam_config[300];
+ char isam_enable[50];
#endif
int ctrl_resched;
int dhd_ioctl_timeout_msec;
struct mchan_params mchan[MCHAN_MAX_NUM];
char *wl_preinit;
int tsq;
+ uint in4way;
} dhd_conf_t;
#ifdef BCMSDIO
uint dhd_conf_get_band(dhd_pub_t *dhd);
int dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec);
int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec);
-int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec, int nodfs);
+int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec);
int dhd_conf_fix_country(dhd_pub_t *dhd);
bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel);
void dhd_conf_set_wme(dhd_pub_t *dhd, int mode);
}
}
#ifdef CUSTOMER_HW_AMLOGIC
-// extern_wifi_set_enable(0);
-// mdelay(200);
+ extern_wifi_set_enable(0);
+ mdelay(200);
#endif
}
return;
}
-static void dhd_tcpack_send(ulong data)
+static void dhd_tcpack_send(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ ulong data
+#endif
+)
{
tcpack_sup_module_t *tcpack_sup_mod;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ tcpack_info_t *cur_tbl = from_timer(cur_tbl, t, timer);
+#else
tcpack_info_t *cur_tbl = (tcpack_info_t *)data;
+#endif
dhd_pub_t *dhdp;
int ifidx;
void* pkt;
tcpack_info_t *tcpack_info_tbl =
&tcpack_sup_module->tcpack_info_tbl[i];
tcpack_info_tbl->dhdp = dhdp;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&tcpack_info_tbl->timer, dhd_tcpack_send, 0);
+#else
init_timer(&tcpack_info_tbl->timer);
tcpack_info_tbl->timer.data = (ulong)tcpack_info_tbl;
tcpack_info_tbl->timer.function = dhd_tcpack_send;
+#endif
}
break;
}
#if defined(MULTIPLE_SUPPLICANT)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-DEFINE_MUTEX(_dhd_sdio_mutex_lock_);
+DEFINE_MUTEX(_dhd_mutex_lock_);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
#endif
#define MAX_CONSECUTIVE_HANG_COUNTS 5
#endif /* CONFIG_BCM_DETECT_CONSECUTIVE_HANG */
-#ifdef BCMDBUS
-#include <dbus.h>
-#else
#include <dhd_bus.h>
-#endif /* BCMDBUS */
#ifdef DHD_ULP
#include <dhd_ulp.h>
dhd_pub_t pub;
dhd_if_t *iflist[DHD_MAX_IFS]; /* for supporting multiple interfaces */
- void *adapter; /* adapter information, interrupt, fw path etc. */
+ wifi_adapter_info_t *adapter; /* adapter information, interrupt, fw path etc. */
char fw_path[PATH_MAX]; /* path to firmware image */
char nv_path[PATH_MAX]; /* path to nvram vars file */
char clm_path[PATH_MAX]; /* path to clm vars file */
int disable_proptx = 0;
module_param(op_mode, int, 0644);
extern int wl_control_wl_start(struct net_device *dev);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (defined(BCMLXSDMMC) || defined(BCMDBUS))
struct semaphore dhd_registration_sem;
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol);
static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol);
#endif /* TOE */
-#ifdef BCMDBUS
-int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf);
-#endif /* BCMDBUS */
static int dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen,
wl_event_msg_t *event_ptr, void **data_ptr);
}
// terence 20160615: fix building error if ARP_OFFLOAD_SUPPORT removed
-#if defined(PKT_FILTER_SUPPORT) && defined(ARP_OFFLOAD_SUPPORT)
-#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER
+#if defined(PKT_FILTER_SUPPORT)
+#if defined(ARP_OFFLOAD_SUPPORT) && !defined(GAN_LITE_NAT_KEEPALIVE_FILTER)
static bool
_turn_on_arp_filter(dhd_pub_t *dhd, int op_mode_param)
{
return NULL;
}
-#ifdef BCMDBUS
-#define DBUS_NRXQ 50
-#define DBUS_NTXQ 100
-
-static void
-dhd_dbus_send_complete(void *handle, void *info, int status)
-{
- dhd_info_t *dhd = (dhd_info_t *)handle;
- void *pkt = info;
-
- if ((dhd == NULL) || (pkt == NULL))
- return;
-
- if (status == DBUS_OK) {
- dhd->pub.dstats.tx_packets++;
- } else {
- DHD_ERROR(("TX error=%d\n", status));
- dhd->pub.dstats.tx_errors++;
- }
-#ifdef PROP_TXSTATUS
- if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) &&
- (dhd_wlfc_txcomplete(&dhd->pub, pkt, status == 0) != WLFC_UNSUPPORTED)) {
- return;
- }
-#endif /* PROP_TXSTATUS */
- PKTFREE(dhd->pub.osh, pkt, TRUE);
-}
-
-static void
-dhd_dbus_recv_pkt(void *handle, void *pkt)
-{
- uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
- uint reorder_info_len;
- uint pkt_count;
- dhd_info_t *dhd = (dhd_info_t *)handle;
- int ifidx = 0;
-
- if (dhd == NULL)
- return;
-
- /* If the protocol uses a data header, check and remove it */
- if (dhd_prot_hdrpull(&dhd->pub, &ifidx, pkt, reorder_info_buf,
- &reorder_info_len) != 0) {
- DHD_ERROR(("rx protocol error\n"));
- PKTFREE(dhd->pub.osh, pkt, FALSE);
- dhd->pub.rx_errors++;
- return;
- }
-
- if (reorder_info_len) {
- /* Reordering info from the firmware */
- dhd_process_pkt_reorder_info(&dhd->pub, reorder_info_buf, reorder_info_len,
- &pkt, &pkt_count);
- if (pkt_count == 0)
- return;
- }
- else {
- pkt_count = 1;
- }
- dhd_rx_frame(&dhd->pub, ifidx, pkt, pkt_count, 0);
-}
-
-static void
-dhd_dbus_recv_buf(void *handle, uint8 *buf, int len)
-{
- dhd_info_t *dhd = (dhd_info_t *)handle;
- void *pkt;
-
- if (dhd == NULL)
- return;
-
- if ((pkt = PKTGET(dhd->pub.osh, len, FALSE)) == NULL) {
- DHD_ERROR(("PKTGET (rx) failed=%d\n", len));
- return;
- }
-
- bcopy(buf, PKTDATA(dhd->pub.osh, pkt), len);
- dhd_dbus_recv_pkt(dhd, pkt);
-}
-
-static void
-dhd_dbus_txflowcontrol(void *handle, bool onoff)
-{
- dhd_info_t *dhd = (dhd_info_t *)handle;
- bool wlfc_enabled = FALSE;
-
- if (dhd == NULL)
- return;
-
-#ifdef PROP_TXSTATUS
- wlfc_enabled = (dhd_wlfc_flowcontrol(&dhd->pub, onoff, !onoff) != WLFC_UNSUPPORTED);
-#endif
-
- if (!wlfc_enabled) {
- dhd_txflowcontrol(&dhd->pub, ALL_INTERFACES, onoff);
- }
-}
-
-static void
-dhd_dbus_errhandler(void *handle, int err)
-{
-}
-
-static void
-dhd_dbus_ctl_complete(void *handle, int type, int status)
-{
- dhd_info_t *dhd = (dhd_info_t *)handle;
-
- if (dhd == NULL)
- return;
-
- if (type == DBUS_CBCTL_READ) {
- if (status == DBUS_OK)
- dhd->pub.rx_ctlpkts++;
- else
- dhd->pub.rx_ctlerrs++;
- } else if (type == DBUS_CBCTL_WRITE) {
- if (status == DBUS_OK)
- dhd->pub.tx_ctlpkts++;
- else
- dhd->pub.tx_ctlerrs++;
- }
-
- dhd_prot_ctl_complete(&dhd->pub);
-}
-
-static void
-dhd_dbus_state_change(void *handle, int state)
-{
- dhd_info_t *dhd = (dhd_info_t *)handle;
-
- if (dhd == NULL)
- return;
-
- switch (state) {
-
- case DBUS_STATE_DL_NEEDED:
-#if defined(BCM_REQUEST_FW)
-#if defined(BCMDBUS)
- DHD_TRACE(("%s: firmware request\n", __FUNCTION__));
- up(&dhd->fw_download_lock);
-#endif /* BCMDBUS */
-#else
- DHD_ERROR(("%s: firmware request cannot be handled\n", __FUNCTION__));
-#endif
- break;
- case DBUS_STATE_DOWN:
- DHD_TRACE(("%s: DBUS is down\n", __FUNCTION__));
- dhd->pub.busstate = DHD_BUS_DOWN;
- break;
- case DBUS_STATE_UP:
- DHD_TRACE(("%s: DBUS is up\n", __FUNCTION__));
- dhd->pub.busstate = DHD_BUS_DATA;
- break;
- default:
- break;
- }
-
- printf("%s: DBUS current state=%d\n", __FUNCTION__, state);
-}
-
-static void *
-dhd_dbus_pktget(void *handle, uint len, bool send)
-{
- dhd_info_t *dhd = (dhd_info_t *)handle;
- void *p = NULL;
-
- if (dhd == NULL)
- return NULL;
-
- if (send == TRUE) {
- dhd_os_sdlock_txq(&dhd->pub);
- p = PKTGET(dhd->pub.osh, len, TRUE);
- dhd_os_sdunlock_txq(&dhd->pub);
- } else {
- dhd_os_sdlock_rxq(&dhd->pub);
- p = PKTGET(dhd->pub.osh, len, FALSE);
- dhd_os_sdunlock_rxq(&dhd->pub);
- }
-
- return p;
-}
-
-static void
-dhd_dbus_pktfree(void *handle, void *p, bool send)
-{
- dhd_info_t *dhd = (dhd_info_t *)handle;
-
- if (dhd == NULL)
- return;
-
- if (send == TRUE) {
-#ifdef PROP_TXSTATUS
- if (DHD_PKTTAG_WLFCPKT(PKTTAG(p)) &&
- (dhd_wlfc_txcomplete(&dhd->pub, p, FALSE) != WLFC_UNSUPPORTED)) {
- return;
- }
-#endif /* PROP_TXSTATUS */
-
- dhd_os_sdlock_txq(&dhd->pub);
- PKTFREE(dhd->pub.osh, p, TRUE);
- dhd_os_sdunlock_txq(&dhd->pub);
- } else {
- dhd_os_sdlock_rxq(&dhd->pub);
- PKTFREE(dhd->pub.osh, p, FALSE);
- dhd_os_sdunlock_rxq(&dhd->pub);
- }
-}
-
-
-static dbus_callbacks_t dhd_dbus_cbs = {
- dhd_dbus_send_complete,
- dhd_dbus_recv_buf,
- dhd_dbus_recv_pkt,
- dhd_dbus_txflowcontrol,
- dhd_dbus_errhandler,
- dhd_dbus_ctl_complete,
- dhd_dbus_state_change,
- dhd_dbus_pktget,
- dhd_dbus_pktfree
-};
-
-void
-dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
-{
- bcm_bprintf(strbuf, "Bus USB\n");
-}
-
-void
-dhd_bus_clearcounts(dhd_pub_t *dhdp)
-{
-}
-
-bool
-dhd_bus_dpc(struct dhd_bus *bus)
-{
- return FALSE;
-}
-
-int
-dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf)
-{
-
- if (dhdp->txoff)
- return BCME_EPERM;
- return dbus_send_txdata(dhdp->dbus, pktbuf);
-}
-
-#endif /* BCMDBUS */
static void
_dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
DHD_ERROR(("TX DUMP[%s] - %s\n", ifname, _get_packet_type_str(protocol)));
- if (protocol == ETHER_TYPE_802_1X) {
- dhd_dump_eapol_4way_message(ifname, dump_data, TRUE);
- }
-
#if defined(DHD_TX_FULL_DUMP)
{
int i;
#endif
#if defined(DHD_TX_DUMP)
- ndev = dhd_idx2net(dhdp, ifidx);
- dhd_tx_dump(ndev, dhdp->osh, pktbuf);
+ dhd_tx_dump(dhd_idx2net(dhdp, ifidx), dhdp->osh, pktbuf);
#endif
/* terence 20150901: Micky add to ajust the 802.1X priority */
/* Set the 802.1X packet with the highest priority 7 */
#ifdef WLMEDIA_HTSF
dhd_htsf_addtxts(dhdp, pktbuf);
#endif
-
-#ifdef BCMDBUS
-#ifdef PROP_TXSTATUS
- if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_dbus_txdata,
- dhdp, pktbuf, TRUE) == WLFC_UNSUPPORTED) {
- /* non-proptxstatus way */
- ret = dhd_dbus_txdata(dhdp, pktbuf);
- }
-#else
- ret = dhd_dbus_txdata(dhdp, pktbuf);
-#endif /* PROP_TXSTATUS */
- if (ret)
- PKTCFREE(dhdp->osh, pktbuf, TRUE);
-#else
#ifdef PROP_TXSTATUS
{
if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_bus_txdata,
ret = dhd_bus_txdata(dhdp->bus, pktbuf);
#endif /* BCMPCIE */
#endif /* PROP_TXSTATUS */
-
+#ifdef BCMDBUS
+ if (ret)
+ PKTCFREE(dhdp->osh, pktbuf, TRUE);
#endif /* BCMDBUS */
+
return ret;
}
#endif /* DHD_PCIE_RUNTIMEPM */
DHD_GENERAL_LOCK(&dhd->pub, flags);
+#ifdef BCMPCIE
if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(&dhd->pub)) {
- // DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n",
- // __FUNCTION__, dhd->pub.busstate, dhd->pub.dhd_bus_busy_state));
+ DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n",
+ __FUNCTION__, dhd->pub.busstate, dhd->pub.dhd_bus_busy_state));
DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub);
#ifdef PCIE_FULL_DONGLE
/* Stop tx queues if suspend is in progress */
return NETDEV_TX_BUSY;
#endif
}
+#else
+ if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(&dhd->pub)) {
+ DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n",
+ __FUNCTION__, dhd->pub.busstate, dhd->pub.dhd_bus_busy_state));
+ }
+#endif
DHD_OS_WAKE_LOCK(&dhd->pub);
DHD_PERIM_LOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
complete_and_exit(&tsk->completed, 0);
}
-static void dhd_watchdog(ulong data)
+static void dhd_watchdog(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ ulong data
+#endif
+)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ dhd_info_t *dhd = from_timer(dhd, t, timer);
+#else
dhd_info_t *dhd = (dhd_info_t *)data;
+#endif
unsigned long flags;
if (dhd->pub.dongle_reset) {
complete_and_exit(&tsk->completed, 0);
}
-static void dhd_runtimepm(ulong data)
+static void dhd_runtimepm(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ ulong data
+#endif
+)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ dhd_info_t *dhd = from_timer(dhd, t, rpm_timer);
+#else
dhd_info_t *dhd = (dhd_info_t *)data;
+#endif
if (dhd->pub.dongle_reset) {
return;
return 0;
}
#endif /* DEBUG_CPU_FREQ */
+
static int
dhd_dpc_thread(void *data)
{
uint32 slot_num = -1;
wifi_adapter_info_t *adapter = NULL;
#endif
-#if defined(WL_EXT_IAPSTA) && defined(IAPSTA_PREINIT)
+#if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT)
int bytes_written = 0;
struct dhd_conf *conf;
#endif
}
printf("%s: Enter %p\n", __FUNCTION__, net);
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) {
- DHD_ERROR(("%s : dhd_open: call dev open before insmod complete!\n", __FUNCTION__));
- }
- mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif
-#endif /* MULTIPLE_SUPPLICANT */
+ DHD_MUTEX_LOCK();
/* Init wakelock */
if (!dhd_download_fw_on_driverload) {
if (!(dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) {
if (ifidx == 0) {
atomic_set(&dhd->pend_8021x_cnt, 0);
-#ifdef BCMDBUS
- dhd_update_fw_nv_path(dhd); // terence 20140807: fix for op_mode issue
- dhd_conf_read_config(&dhd->pub, dhd->pub.conf_path);
-#endif /* BCMDBUS */
if (!dhd_download_fw_on_driverload) {
DHD_ERROR(("\n%s\n", dhd_version));
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_attach_netdev(net, ifidx);
+ wl_ext_iapsta_attach_netdev(net, ifidx, dhd->iflist[ifidx]->bssidx);
#endif
#if defined(USE_INITIAL_SHORT_DWELL_TIME)
g_first_broadcast_scan = TRUE;
ret = -1;
goto exit;
}
-#if defined(WL_EXT_IAPSTA) && defined(IAPSTA_PREINIT)
+#if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT)
conf = dhd_get_conf(net);
if (conf) {
- wl_android_ext_priv_cmd(net, conf->iapsta_init, 0, &bytes_written);
- wl_android_ext_priv_cmd(net, conf->iapsta_config, 0, &bytes_written);
- wl_android_ext_priv_cmd(net, conf->iapsta_enable, 0, &bytes_written);
+ wl_android_ext_priv_cmd(net, conf->isam_init, 0, &bytes_written);
+ wl_android_ext_priv_cmd(net, conf->isam_config, 0, &bytes_written);
+ wl_android_ext_priv_cmd(net, conf->isam_enable, 0, &bytes_written);
}
#endif
}
#endif
if (dhd->pub.busstate != DHD_BUS_DATA) {
-
-#ifndef BCMDBUS
- /* try to bring up bus */
- DHD_PERIM_UNLOCK(&dhd->pub);
- ret = dhd_bus_start(&dhd->pub);
- DHD_PERIM_LOCK(&dhd->pub);
- if (ret) {
- DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
- ret = -1;
- goto exit;
- }
-#else
- if ((ret = dbus_up(dhd->pub.dbus)) != 0) {
+#ifdef BCMDBUS
+ dhd_set_path(&dhd->pub);
+ DHD_MUTEX_UNLOCK();
+ wait_event_interruptible_timeout(dhd->adapter->status_event,
+ wifi_get_adapter_status(dhd->adapter, WIFI_STATUS_FW_READY),
+ msecs_to_jiffies(DHD_FW_READY_TIMEOUT));
+ DHD_MUTEX_LOCK();
+ if ((ret = dbus_up(dhd->pub.bus)) != 0) {
DHD_ERROR(("%s: failed to dbus_up with code %d\n", __FUNCTION__, ret));
goto exit;
} else {
dhd->pub.busstate = DHD_BUS_DATA;
}
-
if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0) {
DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
goto exit;
}
+#else
+ /* try to bring up bus */
+ DHD_PERIM_UNLOCK(&dhd->pub);
+ ret = dhd_bus_start(&dhd->pub);
+ DHD_PERIM_LOCK(&dhd->pub);
+ if (ret) {
+ DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
+ ret = -1;
+ goto exit;
+ }
#endif /* !BCMDBUS */
}
+#ifdef WL_EXT_IAPSTA
+ wl_ext_iapsta_attach_name(net, ifidx);
+#endif
if (dhd_download_fw_on_driverload) {
if (dhd->pub.conf->deepsleep)
dhd_deepsleep(dhd, 0);
DHD_PERIM_UNLOCK(&dhd->pub);
DHD_OS_WAKE_UNLOCK(&dhd->pub);
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
- mutex_unlock(&_dhd_sdio_mutex_lock_);
-#endif
-#endif /* MULTIPLE_SUPPLICANT */
+ DHD_MUTEX_UNLOCK();
printf("%s: Exit ret=%d\n", __FUNCTION__, ret);
return ret;
return -EINVAL;
}
-#ifdef MULTIPLE_SUPPLICANT
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && defined(BCMSDIO)
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) {
- DHD_ERROR(("%s : dhdsdio_probe is already running!\n", __FUNCTION__));
- return 0;
- }
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* MULTIPLE_SUPPLICANT */
+ DHD_MUTEX_IS_LOCK_RETURN();
/* && defined(OEM_ANDROID) && defined(BCMSDIO) */
dhd = DHD_DEV_INFO(net);
#endif /* SHOW_LOGTRACE */
+#ifdef BCMDBUS
+uint
+dhd_get_rxsz(dhd_pub_t *pub)
+{
+ struct net_device *net = NULL;
+ dhd_info_t *dhd = NULL;
+ uint rxsz;
+
+ /* Assign rxsz for dbus_attach */
+ dhd = pub->info;
+ net = dhd->iflist[0]->net;
+ net->hard_header_len = ETH_HLEN + pub->hdrlen;
+ rxsz = DBUS_RX_BUFFER_SIZE_DHD(net);
+
+ return rxsz;
+}
+
+void
+dhd_set_path(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = NULL;
+
+ dhd = pub->info;
+
+ /* try to download image and nvram to the dongle */
+ if (dhd_update_fw_nv_path(dhd) && dhd->pub.bus) {
+ DHD_INFO(("%s: fw %s, nv %s, conf %s\n",
+ __FUNCTION__, dhd->fw_path, dhd->nv_path, dhd->conf_path));
+ dhd_bus_update_fw_nv_path(dhd->pub.bus,
+ dhd->fw_path, dhd->nv_path, dhd->clm_path, dhd->conf_path);
+ }
+}
+#endif
dhd_pub_t *
-dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
+dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen
+#ifdef BCMDBUS
+ , void *data
+#endif
+)
{
dhd_info_t *dhd = NULL;
struct net_device *net = NULL;
char if_name[IFNAMSIZ] = {'\0'};
- uint32 bus_type = -1;
- uint32 bus_num = -1;
- uint32 slot_num = -1;
#ifdef SHOW_LOGTRACE
int ret;
#endif /* SHOW_LOGTRACE */
+#if defined(BCMSDIO) || defined(BCMPCIE)
+ uint32 bus_type = -1;
+ uint32 bus_num = -1;
+ uint32 slot_num = -1;
wifi_adapter_info_t *adapter = NULL;
+#elif defined(BCMDBUS)
+ wifi_adapter_info_t *adapter = data;
+#endif
+#ifdef GET_CUSTOM_MAC_ENABLE
+ char hw_ether[62];
+#endif /* GET_CUSTOM_MAC_ENABLE */
dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
#if defined(BCMSDIO)
dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num);
#endif
+#if defined(BCMSDIO) || defined(BCMPCIE)
adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
+#endif
/* Allocate primary dhd_info */
dhd = wifi_platform_prealloc(adapter, DHD_PREALLOC_DHD_INFO, sizeof(dhd_info_t));
dll_init(&(dhd->pub.dump_iovlist_head));
#endif /* DUMP_IOCTL_IOV_LIST */
dhd->adapter = adapter;
+ dhd->pub.adapter = (void *)adapter;
#ifdef DHD_DEBUG
dll_init(&(dhd->pub.mw_list_head));
#endif /* DHD_DEBUG */
#endif /* BT_OVER_SDIO */
#ifdef GET_CUSTOM_MAC_ENABLE
- wifi_platform_get_mac_addr(dhd->adapter, dhd->pub.mac.octet);
+ wifi_platform_get_mac_addr(dhd->adapter, hw_ether);
+ bcopy(hw_ether, dhd->pub.mac.octet, sizeof(struct ether_addr));
#endif /* GET_CUSTOM_MAC_ENABLE */
#ifdef CUSTOM_FORCE_NODFS_FLAG
dhd->pub.dhd_cflags |= WLAN_PLAT_NODFS_FLAG;
dhd->pub.bus = bus;
dhd->pub.hdrlen = bus_hdrlen;
-#ifndef BCMDBUS
/* dhd_conf must be attached after linking dhd to dhd->pub.info,
* because dhd_detech will check .info is NULL or not.
*/
DHD_ERROR(("dhd_conf_attach failed\n"));
goto fail;
}
+#ifndef BCMDBUS
dhd_conf_reset(&dhd->pub);
dhd_conf_set_chiprev(&dhd->pub, dhd_bus_chip(bus), dhd_bus_chiprev(bus));
dhd_conf_preinit(&dhd->pub);
#ifndef BCMDBUS
/* Set up the watchdog timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&dhd->timer, dhd_watchdog, 0);
+#else
init_timer(&dhd->timer);
dhd->timer.data = (ulong)dhd;
dhd->timer.function = dhd_watchdog;
+#endif
dhd->default_wd_interval = dhd_watchdog_ms;
if (dhd_watchdog_prio >= 0) {
#ifdef DHD_PCIE_RUNTIMEPM
/* Setup up the runtime PM Idlecount timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&dhd->rpm_timer, dhd_runtimepm, 0);
+#else
init_timer(&dhd->rpm_timer);
dhd->rpm_timer.data = (ulong)dhd;
dhd->rpm_timer.function = dhd_runtimepm;
+#endif
dhd->rpm_timer_valid = FALSE;
dhd->thr_rpm_ctl.thr_pid = DHD_PID_KT_INVALID;
#ifdef DEBUGGER
debugger_init((void *) bus);
#endif
-#ifdef SHOW_LOGTRACE
- skb_queue_head_init(&dhd->evt_trace_queue);
-#endif /* SHOW_LOGTRACE */
/* Set up the bottom half handler */
if (dhd_dpc_prio >= 0) {
}
}
#endif /* !BCMDBUS */
+#ifdef SHOW_LOGTRACE
+ skb_queue_head_init(&dhd->evt_trace_queue);
+#endif /* SHOW_LOGTRACE */
dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED;
return FALSE;
}
#endif /* BCMEMBEDIMAGE */
-#ifdef BCMDBUS
- if (dhdinfo->conf_path[0] == '\0') {
- dhd_conf_set_path(&dhdinfo->pub, "config.txt", dhdinfo->conf_path, dhdinfo->fw_path);
- } else {
- dhdinfo->pub.conf_path = dhdinfo->conf_path;
- printf("%s: conf_path=%s\n", __FUNCTION__, dhdinfo->conf_path);
- }
- if (dhdinfo->clm_path[0] == '\0') {
- dhd_conf_set_path(&dhdinfo->pub, "clm.blob", dhdinfo->clm_path, dhdinfo->fw_path);
- } else {
- dhdinfo->pub.clm_path= dhdinfo->clm_path;
- printf("%s: clm_path=%s\n", __FUNCTION__, dhdinfo->clm_path);
- }
-#endif /* BCMDBUS */
return TRUE;
}
} else if (ret >= 1) {
disable_proptx = 1;
wlfc_enable = FALSE;
- /* terence 20161229: we should set ampdu_hostreorder=0 when disalbe_proptx=1 */
+ /* terence 20161229: we should set ampdu_hostreorder=0 when disable_proptx=1 */
hostreorder = 0;
}
printf("%s\n", dhd_version);
#ifdef WL_EXT_IAPSTA
else
- wl_ext_iapsta_attach_netdev(net, ifidx);
+ wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
#endif
-#ifdef WLMESH
- if (ifidx != 0 && dhdp->conf->fw_type == FW_TYPE_MESH) {
- if (_dhd_set_mac_address(dhd, ifidx, temp_addr) == 0)
+ if (ifidx != 0) {
+ if (_dhd_set_mac_address(dhd, ifidx, net->dev_addr) == 0)
DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__));
else
DHD_ERROR(("%s: _dhd_set_mac_address() failed\n", __FUNCTION__));
}
-#endif
if (need_rtnl_lock)
err = register_netdev(net);
}
#ifdef WL_EXT_IAPSTA
if (ifidx == 0)
- wl_ext_iapsta_attach_netdev(net, ifidx);
+ wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
wl_ext_iapsta_attach_name(net, ifidx);
#endif
#endif
#if (defined(BCMPCIE) || (defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= \
- KERNEL_VERSION(2, 6, 27))))
+ KERNEL_VERSION(2, 6, 27))) || defined(BCMDBUS))
if (ifidx == 0) {
#if defined(BCMLXSDMMC) && !defined(DHD_PRELOAD)
up(&dhd_registration_sem);
if (dhd_wl_ioctl_cmd(dhdp, WLC_TERMINATED, NULL, 0, TRUE, 0) < 0)
DHD_ERROR(("%s Setting WLC_TERMINATED failed\n",
__FUNCTION__));
- dbus_stop(dhd->pub.dbus);
+ dbus_stop(dhd->pub.bus);
dhd->pub.busstate = DHD_BUS_DOWN;
#else
dhd_bus_stop(dhd->pub.bus, TRUE);
ASSERT(ifp);
ASSERT(ifp->net);
if (ifp && ifp->net) {
-
-
-
#ifdef WL_CFG80211
cfg = wl_get_cfg(ifp->net);
#endif
{
printf("%s: Enter\n", __FUNCTION__);
-#ifdef BCMDBUS
- dbus_deregister();
-#else
dhd_bus_unregister();
-#endif /* BCMDBUS */
wl_android_exit();
dhd_wifi_platform_unregister_drv();
-
#ifdef CUSTOMER_HW_AMLOGIC
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
wifi_teardown_dt();
return NOTIFY_DONE;
}
-#ifdef BCMDBUS
-/*
- * hdrlen is space to reserve in pkt headroom for DBUS
- */
-void *
-dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
-{
- osl_t *osh = NULL;
- int ret = 0;
- dbus_attrib_t attrib;
- dhd_pub_t *pub = NULL;
-
- printf("%s: Enter\n", __FUNCTION__);
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
- DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
- }
- else {
- DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
- }
- mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif
-
- /* Ask the OS interface part for an OSL handle */
- if (!(osh = osl_attach(NULL, bustype, TRUE))) {
- DHD_ERROR(("%s: OSL attach failed\n", __FUNCTION__));
- ret = -ENOMEM;
- goto fail;
- }
-
- /* Attach to the dhd/OS interface */
- if (!(pub = dhd_attach(osh, NULL /* bus */, hdrlen))) {
- DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
- ret = -ENXIO;
- goto fail;
- }
-
- /* Ok, finish the attach to the OS network interface */
- if (dhd_register_if(pub, 0, TRUE) != 0) {
- DHD_ERROR(("%s: dhd_register_if failed\n", __FUNCTION__));
- ret = -ENXIO;
- goto fail;
- }
-
- pub->dbus = dbus_attach(pub->osh, pub->rxsz, DBUS_NRXQ, DBUS_NTXQ,
- pub->info, &dhd_dbus_cbs, NULL, NULL);
- if (pub->dbus) {
- dbus_get_attrib(pub->dbus, &attrib);
- DHD_ERROR(("DBUS: vid=0x%x pid=0x%x devid=0x%x bustype=0x%x mtu=%d rev=%d\n",
- attrib.vid, attrib.pid, attrib.devid, attrib.bustype, attrib.mtu, attrib.chiprev));
- } else {
- ret = -ENXIO;
- goto fail;
- }
-
- /* dhd_conf must be attached after linking dhd to dhd->dbus,
- * because dhd_detech will check .info is NULL or not.
- */
- if (dhd_conf_attach(pub) != 0) {
- DHD_ERROR(("dhd_conf_attach failed\n"));
- goto fail;
- }
- dhd_conf_reset(pub);
- dhd_conf_set_chiprev(pub, attrib.devid, attrib.chiprev);
- dhd_conf_preinit(pub);
-
- /* Some DHD modules (e.g. cfg80211) configures operation mode based on firmware name.
- * This is indeed a hack but we have to make it work properly before we have a better
- * solution
- */
- dhd_update_fw_nv_path(pub->info);
-
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif
-
- printf("%s: Exit\n", __FUNCTION__);
- /* This is passed to dhd_dbus_disconnect_cb */
- return pub->info;
-fail:
- /* Release resources in reverse order */
- if (pub) {
- if (pub->dbus) {
- dbus_detach(pub->dbus);
- pub->dbus = NULL;
- }
- dhd_detach(pub);
- dhd_free(pub);
- }
- if (osh) {
- osl_detach(osh);
- }
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif
-
- BCM_REFERENCE(ret);
- printf("%s: Exit\n", __FUNCTION__);
- return NULL;
-}
-
-void
-dhd_dbus_disconnect_cb(void *arg)
-{
- dhd_info_t *dhd = (dhd_info_t *)arg;
- dhd_pub_t *pub;
- osl_t *osh;
-
- printf("%s: Enter\n", __FUNCTION__);
- if (dhd == NULL)
- return;
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
- DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
- }
- else {
- DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
- }
- mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif
-
- pub = &dhd->pub;
- osh = pub->osh;
- dhd_detach(pub);
- if (pub->dbus) {
- dbus_detach(pub->dbus);
- pub->dbus = NULL;
- }
- dhd_free(pub);
-
- if (MALLOCED(osh)) {
- DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh)));
- }
- osl_detach(osh);
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* LINUX */
- printf("%s: Exit\n", __FUNCTION__);
-}
-#endif /* BCMDBUS */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
#if defined(CONFIG_DEFERRED_INITCALLS) && !defined(EXYNOS_PCIE_MODULE_PATCH)
dhd = (dhd_info_t *)(pub->info);
-#ifndef BCMDBUS
+#ifdef BCMDBUS
+ spin_lock_bh(&dhd->sdlock);
+#else
if (dhd_dpc_prio >= 0)
down(&dhd->sdsem);
else
spin_lock_bh(&dhd->sdlock);
-#else
- spin_lock_bh(&dhd->sdlock);
#endif /* !BCMDBUS */
}
dhd = (dhd_info_t *)(pub->info);
-#ifndef BCMDBUS
+#ifdef BCMDBUS
+ spin_unlock_bh(&dhd->sdlock);
+#else
if (dhd_dpc_prio >= 0)
up(&dhd->sdsem);
else
spin_unlock_bh(&dhd->sdlock);
-#else
- spin_unlock_bh(&dhd->sdlock);
#endif /* !BCMDBUS */
}
return;
}
-#if defined(BCMSDIO) || defined(BCMPCIE)
+#if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMDBUS)
int
dhd_net_bus_devreset(struct net_device *dev, uint8 flag)
{
}
#endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMPCIE */
+#endif /* BCMSDIO || BCMPCIE || BCMDBUS */
int net_os_set_suspend_disable(struct net_device *dev, int val)
{
DHD_ERROR(("%s(): dhd is NULL \r\n", __FUNCTION__));
return;
}
+
/* Releae the kobject */
- if (dhd->dhd_kobj.state_initialized)
+ if (dhd->dhd_kobj.state_initialized)
kobject_put(&dhd->dhd_kobj);
}
#include <linux/earlysuspend.h>
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */
+/* dongle status */
+enum wifi_adapter_status {
+ WIFI_STATUS_POWER_ON = 0,
+ WIFI_STATUS_ATTACH,
+ WIFI_STATUS_FW_READY,
+ WIFI_STATUS_DETTACH
+};
+#define wifi_chk_adapter_status(adapter, stat) (test_bit(stat, &(adapter)->status))
+#define wifi_get_adapter_status(adapter, stat) (test_bit(stat, &(adapter)->status))
+#define wifi_set_adapter_status(adapter, stat) (set_bit(stat, &(adapter)->status))
+#define wifi_clr_adapter_status(adapter, stat) (clear_bit(stat, &(adapter)->status))
+#define wifi_chg_adapter_status(adapter, stat) (change_bit(stat, &(adapter)->status))
+
#define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */
+#define DHD_FW_READY_TIMEOUT 5000 /* msec : allowed time to finished fw download */
typedef struct wifi_adapter_info {
const char *name;
uint bus_type;
uint bus_num;
uint slot_num;
+ wait_queue_head_t status_event;
+ unsigned long status;
#if defined(BT_OVER_SDIO)
const char *btfw_path;
#endif /* defined (BT_OVER_SDIO) */
int dhd_wifi_platform_register_drv(void);
void dhd_wifi_platform_unregister_drv(void);
+wifi_adapter_info_t* dhd_wifi_platform_attach_adapter(uint32 bus_type,
+ uint32 bus_num, uint32 slot_num, unsigned long status);
wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num,
uint32 slot_num);
int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec);
#if defined(CONFIG_WIFI_CONTROL_FUNC)
#include <linux/wlan_plat.h>
#endif
-#ifdef BCMDBUS
-#include <dbus.h>
-#endif /* BCMDBUS */
#ifdef CONFIG_DTS
#include<linux/regulator/consumer.h>
#include<linux/of_gpio.h>
static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24; /* cookie is "WiFi" */
#endif /* ENABLE_4335BT_WAR */
+wifi_adapter_info_t* dhd_wifi_platform_attach_adapter(uint32 bus_type,
+ uint32 bus_num, uint32 slot_num, unsigned long status)
+{
+ int i;
+
+ if (dhd_wifi_platdata == NULL)
+ return NULL;
+
+ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+ wifi_adapter_info_t *adapter = &dhd_wifi_platdata->adapters[i];
+ if ((adapter->bus_type == -1 || adapter->bus_type == bus_type) &&
+ (adapter->bus_num == -1 || adapter->bus_num == bus_num) &&
+ (adapter->slot_num == -1 || adapter->slot_num == slot_num)
+#if defined(ENABLE_INSMOD_NO_FW_LOAD)
+ && (wifi_chk_adapter_status(adapter, status))
+#endif
+ ) {
+ DHD_ERROR(("attach adapter info '%s'\n", adapter->name));
+ return adapter;
+ }
+ }
+ return NULL;
+}
+
wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num, uint32 slot_num)
{
int i;
return -EINVAL;
}
#endif /* BT_OVER_SDIO */
+ if (on) {
+ wifi_set_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+ } else {
+ wifi_clr_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+ }
#ifdef CONFIG_DTS
if (on) {
printf("======== PULL WL_REG_ON HIGH! ========\n");
err = regulator_disable(wifi_regulator);
is_power_on = FALSE;
}
- if (err < 0)
+ if (err < 0) {
DHD_ERROR(("%s: regulator enable/disable failed", __FUNCTION__));
+ goto fail;
+ }
#else
- if (!adapter || !adapter->wifi_plat_data)
- return -EINVAL;
+ if (!adapter || !adapter->wifi_plat_data) {
+ err = -EINVAL;
+ goto fail;
+ }
plat_data = adapter->wifi_plat_data;
DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
#endif /* CONFIG_DTS */
+ return err;
+fail:
+ if (on) {
+ wifi_clr_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+ } else {
+ wifi_set_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+ }
return err;
}
dhd_wifi_platdata = kzalloc(sizeof(bcmdhd_wifi_platdata_t), GFP_KERNEL);
dhd_wifi_platdata->num_adapters = 1;
dhd_wifi_platdata->adapters = adapter;
+ init_waitqueue_head(&adapter->status_event);
#ifndef CUSTOMER_HW
if (dev1) {
extern int dhd_watchdog_prio;
extern int dhd_dpc_prio;
extern uint dhd_deferred_tx;
-#if defined(BCMLXSDMMC)
+#if defined(BCMLXSDMMC) || defined(BCMDBUS)
extern struct semaphore dhd_registration_sem;
#endif
#endif /* BCMSDIO */
#ifdef BCMDBUS
-/* User-specified vid/pid */
-int dhd_vid = 0xa5c;
-int dhd_pid = 0x48f;
-module_param(dhd_vid, int, 0);
-module_param(dhd_pid, int, 0);
-void *dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
-void dhd_dbus_disconnect_cb(void *arg);
-
static int dhd_wifi_platform_load_usb(void)
{
+ wifi_adapter_info_t *adapter;
+ s32 timeout = -1;
+ int i;
int err = 0;
+ enum wifi_adapter_status wait_status;
- if (dhd_vid < 0 || dhd_vid > 0xffff) {
- DHD_ERROR(("%s: invalid dhd_vid 0x%x\n", __FUNCTION__, dhd_vid));
- return -EINVAL;
+ err = dhd_bus_register();
+ if (err) {
+ DHD_ERROR(("%s: usb_register failed\n", __FUNCTION__));
+ goto exit;
}
- if (dhd_pid < 0 || dhd_pid > 0xffff) {
- DHD_ERROR(("%s: invalid dhd_pid 0x%x\n", __FUNCTION__, dhd_pid));
- return -EINVAL;
+
+ /* power up all adapters */
+ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+ adapter = &dhd_wifi_platdata->adapters[i];
+ DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));
+ DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
+ adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path));
+ DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
+ adapter->bus_type, adapter->bus_num, adapter->slot_num));
+ err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);
+ if (err) {
+ DHD_ERROR(("failed to wifi_platform_set_power on %s\n", adapter->name));
+ goto fail;
+ }
+ if (dhd_download_fw_on_driverload)
+ wait_status = WIFI_STATUS_ATTACH;
+ else
+ wait_status = WIFI_STATUS_DETTACH;
+ timeout = wait_event_interruptible_timeout(adapter->status_event,
+ wifi_get_adapter_status(adapter, wait_status),
+ msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));
+ if (timeout <= 0) {
+ err = -1;
+ DHD_ERROR(("%s: usb_register_driver timeout\n", __FUNCTION__));
+ goto fail;
+ }
}
- err = dbus_register(dhd_vid, dhd_pid, dhd_dbus_probe_cb, dhd_dbus_disconnect_cb,
- NULL, NULL, NULL);
+exit:
+ return err;
- /* Device not detected */
- if (err == DBUS_ERR_NODEVICE)
- err = DBUS_OK;
+fail:
+ dhd_bus_unregister();
+ /* power down all adapters */
+ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+ adapter = &dhd_wifi_platdata->adapters[i];
+ wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+ }
return err;
}
int __devinit
dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
-#ifdef BUS_POWER_RESTORE
- wifi_adapter_info_t *adapter = NULL;
-#endif
+ DHD_MUTEX_LOCK();
if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) {
DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__));
device_disable_async_suspend(&pdev->dev);
#endif /* BCMPCIE_DISABLE_ASYNC_SUSPEND */
-#ifdef BUS_POWER_RESTORE
- adapter = dhd_wifi_platform_get_adapter(PCI_BUS, pdev->bus->number,
- PCI_SLOT(pdev->devfn));
-
- if (adapter != NULL)
- adapter->pci_dev = pdev;
-#endif
-
DHD_TRACE(("%s: PCIe Enumeration done!!\n", __FUNCTION__));
+ DHD_MUTEX_UNLOCK();
return 0;
}
DHD_TRACE(("%s Enter\n", __FUNCTION__));
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
- DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
- }
- else {
- DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
- }
- mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif
+ DHD_MUTEX_LOCK();
pch = pci_get_drvdata(pdev);
bus = pch->bus;
dhdpcie_init_succeeded = FALSE;
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* LINUX */
+ DHD_MUTEX_UNLOCK();
DHD_TRACE(("%s Exit\n", __FUNCTION__));
*/
#endif /* SUPPORT_LINKDOWN_RECOVERY */
-#if defined(MULTIPLE_SUPPLICANT)
-extern void wl_android_post_init(void); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#endif
-
int dhdpcie_init(struct pci_dev *pdev)
{
dhdpcie_smmu_info_t *dhdpcie_smmu_info = NULL;
#endif /* USE_SMMU_ARCH_MSM */
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
- DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
- }
- else {
- DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
- }
- mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif
-
do {
/* osl attach */
if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
/* initialize static buffer */
adapter = dhd_wifi_platform_get_adapter(PCI_BUS, pdev->bus->number,
PCI_SLOT(pdev->devfn));
- if (adapter != NULL)
+ if (adapter != NULL) {
DHD_ERROR(("%s: found adapter info '%s'\n", __FUNCTION__, adapter->name));
- else
+#ifdef BUS_POWER_RESTORE
+ adapter->pci_dev = pdev;
+#endif
+ } else
DHD_ERROR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
osl_static_mem_init(osh, adapter);
#if defined(MULTIPLE_SUPPLICANT)
wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif
+#endif /* MULTIPLE_SUPPLICANT */
DHD_TRACE(("%s:Exit - SUCCESS \n", __FUNCTION__));
return 0; /* return SUCCESS */
osl_detach(osh);
dhdpcie_init_succeeded = FALSE;
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif
DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
return bus->runtime_resume_done;
}
#endif /* DHD_PCIE_RUNTIMEPM */
+
struct device * dhd_bus_to_dev(dhd_bus_t *bus)
{
struct pci_dev *pdev;
else
return NULL;
}
+
#ifdef HOFFLOAD_MODULES
void
dhd_free_module_memory(struct dhd_bus *bus, struct module_metadata *hmem)
dhdsdio_sendpendctl(bus);
} else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
!bus->fcstate && DATAOK(bus) &&
- (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres) &&
- bus->dhd->conf->tx_in_rx) {
+ (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
dhdsdio_sendfromq(bus, dhd_txbound);
#ifdef DHDTCPACK_SUPPRESS
/* In TCPACK_SUP_DELAYTX mode, do txinrx only if
return FALSE;
}
-#if defined(MULTIPLE_SUPPLICANT)
-extern void wl_android_post_init(void); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#endif
-
static void *
dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
struct ether_addr ea_addr;
#endif
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
- DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
- }
- else {
- DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
- }
- mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif
+ DHD_MUTEX_LOCK();
/* Init global variables at run-time, not as part of the declaration.
* This is required to support init/de-init of the driver. Initialization
#if defined(MULTIPLE_SUPPLICANT)
wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif
+#endif /* MULTIPLE_SUPPLICANT */
+ DHD_MUTEX_UNLOCK();
return bus;
dhdsdio_release(bus, osh);
forcereturn:
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif
+ DHD_MUTEX_UNLOCK();
return NULL;
}
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
- DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
- }
- else {
- DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
- }
- mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif
-
-
+ DHD_MUTEX_LOCK();
if (bus) {
ASSERT(bus->dhd);
/* Advertise bus remove during rmmod */
dhdsdio_advertise_bus_remove(bus->dhd);
dhdsdio_release(bus, bus->dhd->osh);
}
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
- mutex_unlock(&_dhd_sdio_mutex_lock_);
- DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* LINUX */
-
+ DHD_MUTEX_UNLOCK();
DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
}
#include <linux/wlan_plat.h>\r
#include <linux/amlogic/dhd_buf.h>\r
\r
-#define DHD_STATIC_VERSION_STR "1.579.77.41.1"\r
+#define DHD_STATIC_VERSION_STR "1.579.77.41.9"\r
\r
#define BCMDHD_SDIO\r
#define BCMDHD_PCIE\r
#define DHD_PREALLOC_DATABUF_SIZE (64 * 1024)\r
#define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)\r
#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)\r
-#define DHD_PREALLOC_DHD_INFO_SIZE (30 * 1024)\r
+#define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024)\r
#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (810 * 1024)\r
#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024)\r
#define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (66 * 1024)\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
wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);\r
if (!wlan_static_skb[i]) {\r
wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);\r
if (!wlan_static_if_flow_lkup)\r
goto err_mem_alloc;\r
+ pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+ DHD_PREALLOC_IF_FLOW_LKUP, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);\r
#endif /* BCMDHD_PCIE */\r
\r
wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL);\r
- if (!wlan_static_dhd_memdump_ram_buf) \r
+ if (!wlan_static_dhd_memdump_ram_buf)\r
goto err_mem_alloc;\r
pr_err("%s: sectoin %d, size=%d\n", __func__,\r
DHD_PREALLOC_MEMDUMP_RAM, DHD_PREALLOC_MEMDUMP_RAM_SIZE);\r
pr_err("%s: sectoin %d, size=%d\n", __func__,\r
DHD_PREALLOC_WL_ESCAN_INFO, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
\r
- wlan_static_fw_verbose_ring_buf = kmalloc(\r
- DHD_PREALLOC_WIPHY_ESCAN0_SIZE,\r
- GFP_KERNEL);\r
+ wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL);\r
if (!wlan_static_fw_verbose_ring_buf)\r
goto err_mem_alloc;\r
pr_err("%s: sectoin %d, size=%d\n", __func__,\r
- DHD_PREALLOC_FW_VERBOSE_RING, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+ DHD_PREALLOC_FW_VERBOSE_RING, FW_VERBOSE_RING_SIZE);\r
\r
- wlan_static_fw_event_ring_buf = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\r
+ wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL);\r
if (!wlan_static_fw_event_ring_buf)\r
goto err_mem_alloc;\r
pr_err("%s: sectoin %d, size=%d\n", __func__,\r
- DHD_PREALLOC_FW_EVENT_RING, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+ DHD_PREALLOC_FW_EVENT_RING, FW_EVENT_RING_SIZE);\r
\r
- wlan_static_dhd_event_ring_buf = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\r
+ wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL);\r
if (!wlan_static_dhd_event_ring_buf)\r
goto err_mem_alloc;\r
pr_err("%s: sectoin %d, size=%d\n", __func__,\r
- DHD_PREALLOC_DHD_EVENT_RING, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+ DHD_PREALLOC_DHD_EVENT_RING, DHD_EVENT_RING_SIZE);\r
\r
- wlan_static_nan_event_ring_buf = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\r
+ wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL);\r
if (!wlan_static_nan_event_ring_buf)\r
goto err_mem_alloc;\r
pr_err("%s: sectoin %d, size=%d\n", __func__,\r
- DHD_PREALLOC_NAN_EVENT_RING, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+ DHD_PREALLOC_NAN_EVENT_RING, NAN_EVENT_RING_SIZE);\r
\r
return 0;\r
\r
#include <dngl_stats.h>
#include <dhd.h>
-#ifdef BCMDBUS /* an abstraction layer that hides details of the underlying bus, eg \
- Linux USB */
-#include <dbus.h>
-#else
#include <dhd_bus.h>
-#endif /* BCMDBUS */
#include <dhd_dbg.h>
#include <dhd_config.h>
#define WLFC_THREAD_RETRY_WAIT_MS 10000 /* 10 sec */
#endif /* defined (DHD_WLFC_THREAD) */
-#if defined(BCMDBUS)
-extern int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf);
-#endif
#ifdef PROP_TXSTATUS
#if defined(BCMPCIE)
rc = dhd_bus_txdata(dhdp->bus, p, ctx->host_ifidx);
-#elif defined(BCMDBUS)
- rc = dhd_dbus_txdata(dhdp, p);
#else
rc = dhd_bus_txdata(dhdp->bus, p);
#endif
#define __DBUS_H__
#include "typedefs.h"
+#include <dhd_linux.h>
extern uint dbus_msglevel;
#define DBUS_ERROR_VAL 0x0001
struct dbus_callbacks;
struct exec_parms;
-typedef void *(*probe_cb_t)(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
+typedef void *(*probe_cb_t)(void *arg, const char *desc, uint32 bustype,
+ uint16 bus_no, uint16 slot, uint32 hdrlen);
typedef void (*disconnect_cb_t)(void *arg);
typedef void *(*exec_cb_t)(struct exec_parms *args);
int (*get_config)(void *bus, dbus_config_t *config);
bool (*device_exists)(void *bus);
- bool (*dlneeded)(void *bus);
+ int (*dlneeded)(void *bus);
int (*dlstart)(void *bus, uint8 *fw, int len);
int (*dlrun)(void *bus);
bool (*recv_needed)(void *bus);
void *param1, void *param2);
extern int dbus_deregister(void);
-extern dbus_pub_t *dbus_attach(struct osl_info *osh, int rxsize, int nrxq, int ntxq,
- void *cbarg, dbus_callbacks_t *cbs, dbus_extdl_t *extdl, struct shared_info *sh);
-extern void dbus_detach(dbus_pub_t *pub);
-
-extern int dbus_download_firmware(dbus_pub_t *pub);
-extern int dbus_up(dbus_pub_t *pub);
+//extern int dbus_download_firmware(dbus_pub_t *pub);
+//extern int dbus_up(struct dhd_bus *pub);
extern int dbus_down(dbus_pub_t *pub);
-extern int dbus_stop(dbus_pub_t *pub);
+//extern int dbus_stop(struct dhd_bus *pub);
extern int dbus_shutdown(dbus_pub_t *pub);
extern void dbus_flowctrl_rx(dbus_pub_t *pub, bool on);
extern int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf);
extern int dbus_send_buf(dbus_pub_t *pub, uint8 *buf, int len, void *info);
extern int dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info);
-extern int dbus_send_ctl(dbus_pub_t *pub, uint8 *buf, int len);
-extern int dbus_recv_ctl(dbus_pub_t *pub, uint8 *buf, int len);
+//extern int dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len);
+//extern int dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len);
extern int dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx);
extern int dbus_poll_intr(dbus_pub_t *pub);
extern int dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats);
-extern int dbus_get_attrib(dbus_pub_t *pub, dbus_attrib_t *attrib);
extern int dbus_get_device_speed(dbus_pub_t *pub);
extern int dbus_set_config(dbus_pub_t *pub, dbus_config_t *config);
extern int dbus_get_config(dbus_pub_t *pub, dbus_config_t *config);
extern int dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload);
extern int dbus_pnp_disconnect(dbus_pub_t *pub);
-extern int dbus_iovar_op(dbus_pub_t *pub, const char *name,
- void *params, int plen, void *arg, int len, bool set);
+//extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+// void *params, int plen, void *arg, int len, bool set);
extern void *dhd_dbus_txq(const dbus_pub_t *pub);
extern uint dhd_dbus_hdrlen(const dbus_pub_t *pub);
#define EPI_VERSION_DEV 1.579.77.41
/* Driver Version String, ASCII, 32 chars max */
-#define EPI_VERSION_STR "1.579.77.41.5 (r)"
+#define EPI_VERSION_STR "1.579.77.41.10 (r)"
#endif /* _epivers_h_ */
#define PKTLIST_UNLINK(x, y) skb_unlink((struct sk_buff *)(y), (struct sk_buff_head *)(x))
#define PKTLIST_FINI(x) skb_queue_purge((struct sk_buff_head *)(x))
+#ifdef REPORT_FATAL_TIMEOUTS
typedef struct osl_timer {
struct timer_list *timer;
bool set;
extern void osl_timer_add(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic);
extern void osl_timer_update(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic);
extern bool osl_timer_del(osl_t *osh, osl_timer_t *t);
+#endif
#endif /* _linux_osl_h_ */
/* timer apis */
/* Note: All timer api's are thread unsafe and should be protected with locks by caller */
+#ifdef REPORT_FATAL_TIMEOUTS
osl_timer_t *
osl_timer_init(osl_t *osh, const char *name, void (*fn)(void *arg), void *arg)
{
}
return (TRUE);
}
+#endif
sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
-#if defined(HW_OOB) || defined(FORCE_WOWLAN)
+#if defined(BCMSDIO) && (defined(HW_OOB) || defined(FORCE_WOWLAN))
dhd_conf_set_hw_oob_intr(sdh, sih->chip);
#endif
error:
return bytes_written;
}
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
+#endif
#ifdef WBTEXT
static int wl_android_wbtext(struct net_device *dev, char *command, int total_len)
ANDROID_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n"));
goto exit;
}
-#ifdef BCMSDIO
+#if defined(BCMSDIO) || defined(BCMDBUS)
ret = dhd_net_bus_devreset(dev, FALSE);
if (ret)
goto err;
+#ifdef BCMSDIO
dhd_net_bus_resume(dev, 1);
#endif /* BCMSDIO */
-
-#ifndef BCMPCIE
+#endif /* BCMSDIO || BCMDBUS */
+#if defined(BCMSDIO) || defined(BCMDBUS)
if (!ret) {
if (dhd_dev_init_ioctl(dev) < 0) {
ret = -EFAULT;
goto err;
}
}
-#endif /* !BCMPCIE */
+#endif /* BCMSDIO || BCMDBUS */
g_wifi_on = TRUE;
}
dhd_net_if_unlock(dev);
return ret;
-#ifndef BCMPCIE
+#if defined(BCMSDIO) || defined(BCMDBUS)
err:
-#ifdef BCMSDIO
dhd_net_bus_devreset(dev, TRUE);
+#ifdef BCMSDIO
dhd_net_bus_suspend(dev);
+#endif /* BCMSDIO */
dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
-#endif
printf("%s: Failed\n", __FUNCTION__);
dhd_net_if_unlock(dev);
return ret;
-#endif
+#endif /* BCMSDIO || BCMDBUS */
}
int wl_android_wifi_off(struct net_device *dev, bool on_failure)
dhd_net_if_lock(dev);
printf("%s in 2: g_wifi_on=%d, on_failure=%d\n", __FUNCTION__, g_wifi_on, on_failure);
if (g_wifi_on || on_failure) {
-#if defined(BCMSDIO) || defined(BCMPCIE)
+#if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMDBUS)
ret = dhd_net_bus_devreset(dev, TRUE);
#if defined(BCMSDIO)
dhd_net_bus_suspend(dev);
#endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMPCIE */
+#endif /* BCMSDIO || BCMPCIE || BCMDBUS */
dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
g_wifi_on = FALSE;
}
uint32 band = WLC_BAND_2G;
uint32 buf_size;
char *pos = command;
+ int band_new, band_cur;
if (cmd_str) {
ANDROID_INFO(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str)));
(channel == APCS_BAND_2G_LEGACY2)) {
band = WLC_BAND_2G;
} else {
- ANDROID_ERROR(("Invalid argument\n"));
+ ANDROID_ERROR(("%s: Invalid argument\n", __FUNCTION__));
return -EINVAL;
}
}
} else {
/* If no argument is provided, default to 2G */
- ANDROID_ERROR(("No argument given default to 2.4G scan\n"));
+ ANDROID_ERROR(("%s: No argument given default to 2.4G scan\n", __FUNCTION__));
band = WLC_BAND_2G;
}
- ANDROID_INFO(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band));
+ ANDROID_INFO(("%s : HAPD_AUTO_CHANNEL = %d, band=%d \n", __FUNCTION__, channel, band));
+
+ ret = wldev_ioctl_set(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur));
if ((ret =
wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect))) < 0) {
- ANDROID_ERROR(("ACS: error getting the spect\n"));
+ ANDROID_ERROR(("%s: ACS: error getting the spect\n", __FUNCTION__));
goto done;
}
reqbuf = kzalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
if (reqbuf == NULL) {
- ANDROID_ERROR(("failed to allocate chanspec buffer\n"));
+ ANDROID_ERROR(("%s: failed to allocate chanspec buffer\n", __FUNCTION__));
return -ENOMEM;
}
if (band == WLC_BAND_AUTO) {
- ANDROID_INFO(("ACS full channel scan \n"));
+ ANDROID_INFO(("%s: ACS full channel scan \n", __func__));
reqbuf[0] = htod32(0);
} else if (band == WLC_BAND_5G) {
- ANDROID_INFO(("ACS 5G band scan \n"));
+ band_new = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
+ ret = wldev_ioctl_set(dev, WLC_SET_BAND, &band_new, sizeof(band_new));
+ if (ret < 0)
+ WL_ERR(("WLC_SET_BAND error %d\n", ret));
+ ANDROID_INFO(("%s: ACS 5G band scan \n", __func__));
if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
ANDROID_ERROR(("ACS 5g chanspec retreival failed! \n"));
goto done;
* If channel argument is not provided/ argument 20 is provided,
* Restrict channel to 2GHz, 20MHz BW, No SB
*/
- ANDROID_INFO(("ACS 2G band scan \n"));
+ ANDROID_INFO(("%s: ACS 2G band scan \n", __func__));
if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
ANDROID_ERROR(("ACS 2g chanspec retreival failed! \n"));
goto done;
goto done2;
}
- buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
+ buf_size = CHANSPEC_BUF_SIZE;
ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
buf_size);
if (ret < 0) {
- ANDROID_ERROR(("can't start auto channel scan, err = %d\n", ret));
+ ANDROID_ERROR(("%s: can't start auto channel scan, err = %d\n",
+ __FUNCTION__, ret));
channel = 0;
goto done;
}
chosen = dtoh32(chosen);
}
+ if ((ret == 0) && (dtoh32(chosen) != 0)) {
+ uint chip;
+ chip = dhd_conf_get_chip(dhd_get_pub(dev));
+ if (chip != BCM43143_CHIP_ID) {
+ u32 chanspec = 0;
+ chanspec = wl_chspec_driver_to_host(chosen);
+ ANDROID_INFO(("%s: selected chanspec = 0x%x\n", __FUNCTION__, chanspec));
+ chosen = wf_chspec_ctlchan(chanspec);
+ ANDROID_INFO(("%s: selected chosen = 0x%x\n", __FUNCTION__, chosen));
+ }
+ }
+
if (chosen) {
int chosen_band;
int apcs_band;
#endif /* D11AC_IOTYPES */
apcs_band = (band == WLC_BAND_AUTO) ? WLC_BAND_2G : band;
chosen_band = (channel <= CH_MAX_2G_CHANNEL) ? WLC_BAND_2G : WLC_BAND_5G;
- if (apcs_band == chosen_band) {
+ if (band == WLC_BAND_AUTO) {
+ printf("%s: selected channel = %d\n", __FUNCTION__, channel);
+ break;
+ } else if (apcs_band == chosen_band) {
printf("%s: selected channel = %d\n", __FUNCTION__, channel);
break;
}
}
- ANDROID_INFO(("%d tried, ret = %d, chosen = 0x%x\n",
+ ANDROID_INFO(("%s: %d tried, ret = %d, chosen = 0x%x\n", __FUNCTION__,
(APCS_MAX_RETRY - retry), ret, chosen));
OSL_SLEEP(250);
}
} else {
channel = APCS_DEFAULT_2G_CH;
}
- ANDROID_ERROR(("ACS failed. Fall back to default channel (%d) \n", channel));
+ ANDROID_ERROR(("%s: ACS failed."
+ " Fall back to default channel (%d) \n", __FUNCTION__, channel));
}
done2:
+ ret = wldev_ioctl_set(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur));
+ if (ret < 0)
+ WL_ERR(("WLC_SET_BAND error %d\n", ret));
if (spect > 0) {
if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) {
- ANDROID_ERROR(("ACS: error while setting spect\n"));
+ ANDROID_ERROR(("%s: ACS: error while setting spect\n", __FUNCTION__));
}
}
else
pos += snprintf(pos, total_len, "5g=");
pos += snprintf(pos, total_len, "%d", channel);
- ANDROID_INFO(("command result is %s \n", command));
+ ANDROID_INFO(("%s: command result is %s \n", __FUNCTION__, command));
return strlen(command);
} else {
return ret;
}
#endif /* P2P_LISTEN_OFFLOADING */
-#ifdef WL_CFG80211
-#ifdef BCM4359_CHIP
+#if defined(BCM4359_CHIP) && defined(WL_CFG80211)
int
wl_android_murx_bfe_cap(struct net_device *dev, int val)
{
return err;
}
#endif /* BCM4359_CHIP */
-#endif
#ifdef SUPPORT_AP_HIGHER_BEACONRATE
int
}
#endif /* DHD_HANG_SEND_UP_TEST */
+#ifdef WL_CFG80211
#ifdef WLMESH
static int
wl_android_set_rsdb_mode(struct net_device *dev, char *command, int total_len)
return ret;
}
#endif /* WLMESH */
+#endif /* WL_CFG80211 */
#ifdef SUPPORT_LQCM
static int
bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
}
#ifdef WL_CFG80211
+ else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
+ bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
+ } else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
+ bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
+ } else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
+ bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
+ }
+#endif /* WL_CFG80211 */
/* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
/*
#endif /* FCC_PWR_LIMIT_2G */
#endif /* CUSTOMER_HW4_PRIVATE_CMD */
}
- else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
- bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
- } else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
- bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
- } else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
- bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
- }
-#endif /* WL_CFG80211 */
else if (strnicmp(command, CMD_DATARATE, strlen(CMD_DATARATE)) == 0) {
bytes_written = wl_android_get_datarate(net, command, priv_cmd.total_len);
} else if (strnicmp(command, CMD_ASSOC_CLIENTS, strlen(CMD_ASSOC_CLIENTS)) == 0) {
else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
}
+#ifdef WL_CFG80211
#ifdef WLMESH
else if (strnicmp(command, CMD_SAE_SET_PASSWORD, strlen(CMD_SAE_SET_PASSWORD)) == 0) {
int skip = strlen(CMD_SAE_SET_PASSWORD) + 1;
bytes_written = wl_android_set_rsdb_mode(net, command, priv_cmd.total_len);
}
#endif
+#endif /* WL_CFG80211 */
else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
int skip = strlen(CMD_P2P_SET_NOA) + 1;
bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
bytes_written = wl_cfg80211_get_sta_info(net, command, priv_cmd.total_len);
}
#endif /* CUSTOMER_HW4_PRIVATE_CMD */
-#ifdef WL_CFG80211
else if (strnicmp(command, CMD_MURX_BFE_CAP,
strlen(CMD_MURX_BFE_CAP)) == 0) {
-#ifdef BCM4359_CHIP
+#if defined(BCM4359_CHIP) && defined(WL_CFG80211)
uint val = *(command + strlen(CMD_MURX_BFE_CAP) + 1) - '0';
bytes_written = wl_android_murx_bfe_cap(net, val);
#else
return BCME_UNSUPPORTED;
#endif /* BCM4359_CHIP */
}
-#endif
#ifdef SUPPORT_AP_HIGHER_BEACONRATE
else if (strnicmp(command, CMD_GET_AP_BASICRATE, strlen(CMD_GET_AP_BASICRATE)) == 0) {
bytes_written = wl_android_get_ap_basicrate(net, command, priv_cmd.total_len);
s32 wl_netlink_send_msg(int pid, int type, int seq, const void *data, size_t size);
#ifdef WL_EXT_IAPSTA
-int wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx);
-int wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx);
+int wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx);
+int wl_ext_iapsta_attach_name(struct net_device *net, int ifidx);
int wl_ext_iapsta_dettach_netdev(void);
-void wl_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel);
+u32 wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel);
int wl_ext_iapsta_alive_preinit(struct net_device *dev);
int wl_ext_iapsta_alive_postinit(struct net_device *dev);
int wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data);
#define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len))
#endif
-typedef enum IF_STATE {
- IF_STATE_INIT = 1,
- IF_STATE_DISALBE,
- IF_STATE_ENABLE
-} if_state_t;
-
-typedef enum APSTAMODE {
- ISTAONLY_MODE = 1,
- IAPONLY_MODE,
- IAPSTA_MODE,
- IDUALAP_MODE,
- IMESHONLY_MODE,
- IMESHSTA_MODE,
- IMESHAP_MODE,
- IMESHAPSTA_MODE,
- IMESHAPAP_MODE,
- IGOSTA_MODE
-} apstamode_t;
-
-typedef enum IFMODE {
- ISTA_MODE = 1,
- IAP_MODE,
- IMESH_MODE
-} ifmode_t;
-
-typedef enum BGNMODE {
- IEEE80211B = 1,
- IEEE80211G,
- IEEE80211BG,
- IEEE80211BGN,
- IEEE80211BGNAC
-} bgnmode_t;
-
-typedef enum AUTHMODE {
- AUTH_OPEN,
- AUTH_SHARED,
- AUTH_WPAPSK,
- AUTH_WPA2PSK,
- AUTH_WPAWPA2PSK
-} authmode_t;
-
-typedef enum ENCMODE {
- ENC_NONE,
- ENC_WEP,
- ENC_TKIP,
- ENC_AES,
- ENC_TKIPAES
-} encmode_t;
-
-enum wl_if_list {
- IF_PIF,
- IF_VIF,
- IF_VIF2,
- MAX_IF_NUM
-};
-
-/* i/f query */
-typedef struct wl_if_info {
- struct net_device *dev;
- if_state_t ifstate;
- ifmode_t ifmode;
- uint bssidx;
- char ifname[IFNAMSIZ+1];
- char ssid[DOT11_MAX_SSID_LEN];
- struct ether_addr bssid;
- bgnmode_t bgnmode;
- int hidden;
- int maxassoc;
- uint16 channel;
- authmode_t amode;
- encmode_t emode;
- char key[100];
-} wl_if_info_t;
-
-typedef struct wl_apsta_params {
- struct wl_if_info if_info[MAX_IF_NUM]; // primary device
- int ioctl_ver;
- bool init;
- bool vsdb;
- apstamode_t apstamode;
- bool netif_change;
- wait_queue_head_t netif_change_event;
-} wl_apsta_params_t;
-
/* hostap mac mode */
#define MACLIST_MODE_DISABLED 0
#define MACLIST_MODE_DENY 1
#define REPEATED_SCAN_RESULT_CNT 1
#endif
+#if defined(RSSIAVG) || defined(RSSIOFFSET)
+extern int g_wifi_on;
+#endif
+
#if defined(RSSIAVG)
#define RSSIAVG_LEN (4*REPEATED_SCAN_RESULT_CNT)
#define RSSICACHE_TIMEOUT 15
wl_scan_results_t *ss_list);
void wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl);
#endif
+int wl_ext_get_best_channel(struct net_device *net,
+#if defined(BSSCACHE)
+ wl_bss_cache_ctrl_t *bss_cache_ctrl,
+#else
+ struct wl_scan_results *bss_list,
+#endif
+ int ioctl_ver, int *best_2g_ch, int *best_5g_ch
+);
#endif /* _wl_android_ */
-
#include <linux/module.h>
#include <linux/netdevice.h>
#include <net/netlink.h>
#include <linux/if_arp.h>
#include <asm/uaccess.h>
#include <linux/wireless.h>
+#if defined(WL_WIRELESS_EXT)
#include <wl_iw.h>
+#endif
#include <wldev_common.h>
#include <wlioctl.h>
#include <bcmutils.h>
#ifdef WL_CFG80211
#include <wl_cfg80211.h>
#endif
+#ifdef WL_ESCAN
+#include <wl_escan.h>
+#endif
#ifndef WL_CFG80211
#define htod32(i) i
#define CMD_SET_SUSPEND_BCN_LI_DTIM "SET_SUSPEND_BCN_LI_DTIM"
#ifdef WL_EXT_IAPSTA
+#include <net/rtnetlink.h>
#define CMD_IAPSTA_INIT "IAPSTA_INIT"
#define CMD_IAPSTA_CONFIG "IAPSTA_CONFIG"
#define CMD_IAPSTA_ENABLE "IAPSTA_ENABLE"
#define CMD_ISAM_CONFIG "ISAM_CONFIG"
#define CMD_ISAM_ENABLE "ISAM_ENABLE"
#define CMD_ISAM_DISABLE "ISAM_DISABLE"
+#define CMD_ISAM_STATUS "ISAM_STATUS"
#ifdef PROP_TXSTATUS
#ifdef PROP_TXSTATUS_VSDB
#include <dhd_wlfc.h>
#define CMD_DHCPC_ENABLE "DHCPC_ENABLE"
#define CMD_DHCPC_DUMP "DHCPC_DUMP"
#endif
+#define CMD_AUTOCHANNEL "AUTOCHANNEL"
#define CMD_WL "WL"
int wl_ext_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
}
#ifdef WL_EXT_IAPSTA
-static int wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len);
+typedef enum IF_STATE {
+ IF_STATE_INIT = 1,
+ IF_STATE_DISALBE,
+ IF_STATE_ENABLE
+} if_state_t;
+
+typedef enum APSTAMODE {
+ ISTAONLY_MODE = 1,
+ IAPONLY_MODE,
+ IAPSTA_MODE,
+ IDUALAP_MODE,
+ ISTAAPAP_MODE,
+ IMESHONLY_MODE,
+ IMESHSTA_MODE,
+ IMESHAP_MODE,
+ IMESHAPSTA_MODE,
+ IMESHAPAP_MODE,
+ IGOSTA_MODE
+} apstamode_t;
+
+typedef enum IFMODE {
+ ISTA_MODE = 1,
+ IAP_MODE,
+ IMESH_MODE
+} ifmode_t;
+
+typedef enum BGNMODE {
+ IEEE80211B = 1,
+ IEEE80211G,
+ IEEE80211BG,
+ IEEE80211BGN,
+ IEEE80211BGNAC
+} bgnmode_t;
+
+typedef enum AUTHMODE {
+ AUTH_OPEN,
+ AUTH_SHARED,
+ AUTH_WPAPSK,
+ AUTH_WPA2PSK,
+ AUTH_WPAWPA2PSK,
+ AUTH_SAE
+} authmode_t;
+
+typedef enum ENCMODE {
+ ENC_NONE,
+ ENC_WEP,
+ ENC_TKIP,
+ ENC_AES,
+ ENC_TKIPAES
+} encmode_t;
+
+enum wl_if_list {
+ IF_PIF,
+ IF_VIF,
+ IF_VIF2,
+ MAX_IF_NUM
+};
+
+typedef enum WL_PRIO {
+ PRIO_AP,
+ PRIO_MESH,
+ PRIO_STA
+}wl_prio_t;
+
+typedef struct wl_if_info {
+ struct net_device *dev;
+ if_state_t ifstate;
+ ifmode_t ifmode;
+ char prefix;
+ wl_prio_t prio;
+ int ifidx;
+ uint8 bssidx;
+ char ifname[IFNAMSIZ+1];
+ char ssid[DOT11_MAX_SSID_LEN];
+ struct ether_addr bssid;
+ bgnmode_t bgnmode;
+ int hidden;
+ int maxassoc;
+ uint16 channel;
+ authmode_t amode;
+ encmode_t emode;
+ char key[100];
+} wl_if_info_t;
+
+#define CSA_FW_BIT (1<<0)
+#define CSA_DRV_BIT (1<<1)
+
+typedef struct wl_apsta_params {
+ struct wl_if_info if_info[MAX_IF_NUM];
+ int ioctl_ver;
+ bool init;
+ bool rsdb;
+ bool vsdb;
+ uint csa;
+ apstamode_t apstamode;
+ bool netif_change;
+ wait_queue_head_t netif_change_event;
+} wl_apsta_params_t;
+
+static int wl_ext_enable_iface(struct net_device *dev, char *ifname);
int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
- void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx,
+ struct mutex* buf_sync)
{
int ret;
return ret;
}
-
-int wl_ext_iovar_getbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
- void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
-{
- int ret;
-
- ret = wldev_iovar_getbuf_bsscfg(dev, iovar_name, param, paramlen,
- buf, buflen, bsscfg_idx, buf_sync);
- if (ret < 0)
- ANDROID_ERROR(("%s: iovar_name=%s ret=%d\n", __FUNCTION__, iovar_name, ret));
-
- return ret;
-}
#endif
/* Return a legacy chanspec given a new chanspec
return chanspec;
}
+#if defined(WL_EXT_IAPSTA) || defined(WL_CFG80211) || defined(WL_ESCAN)
+static chanspec_t
+wl_ext_chspec_from_legacy(chanspec_t legacy_chspec)
+{
+ chanspec_t chspec;
+
+ /* get the channel number */
+ chspec = LCHSPEC_CHANNEL(legacy_chspec);
+
+ /* convert the band */
+ if (LCHSPEC_IS2G(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BAND_2G;
+ } else {
+ chspec |= WL_CHANSPEC_BAND_5G;
+ }
+
+ /* convert the bw and sideband */
+ if (LCHSPEC_IS20(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BW_20;
+ } else {
+ chspec |= WL_CHANSPEC_BW_40;
+ if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
+ chspec |= WL_CHANSPEC_CTL_SB_L;
+ } else {
+ chspec |= WL_CHANSPEC_CTL_SB_U;
+ }
+ }
+
+ if (wf_chspec_malformed(chspec)) {
+ ANDROID_ERROR(("wl_ext_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
+ chspec));
+ return INVCHANSPEC;
+ }
+
+ return chspec;
+}
+
+static chanspec_t
+wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
+{
+ chanspec = dtohchanspec(chanspec);
+ if (ioctl_ver == 1) {
+ chanspec = wl_ext_chspec_from_legacy(chanspec);
+ }
+
+ return chanspec;
+}
+#endif
+
static int
wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
{
}
static int
-wl_ext_set_chanspec(struct net_device *dev, uint16 channel, chanspec_t *ret_chspec)
+wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver,
+ uint16 channel, chanspec_t *ret_chspec)
{
s32 _chan = channel;
chanspec_t chspec = 0;
u32 bw_cap;
} param = {0, 0};
uint band;
- int ioctl_ver = 0;
if (_chan <= CH_MAX_2G_CHANNEL)
band = IEEE80211_BAND_2GHZ;
else
band = IEEE80211_BAND_5GHZ;
- wl_ext_get_ioctl_ver(dev, &ioctl_ver);
if (band == IEEE80211_BAND_5GHZ) {
param.band = WLC_BAND_5G;
wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
printf("%s: channel %d\n", __FUNCTION__, _chan);
} else if (err) {
- ANDROID_ERROR(("%s: failed to set chanspec error %d\n", __FUNCTION__, err));
+ ANDROID_ERROR(("%s: failed to set chanspec error %d\n",
+ __FUNCTION__, err));
} else
- printf("%s: channel %d, 0x%x\n", __FUNCTION__, channel, chspec);
+ printf("%s: %s channel %d, 0x%x\n", __FUNCTION__,
+ dev->name, channel, chspec);
} else {
- ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", __FUNCTION__));
+ ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n",
+ __FUNCTION__));
err = BCME_ERROR;
}
} else {
channel_info_t ci;
int bytes_written = 0;
chanspec_t fw_chspec;
+ int ioctl_ver = 0;
ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command));
sscanf(command, "%*s %d", &channel);
if (channel > 0) {
- ret = wl_ext_set_chanspec(dev, channel, &fw_chspec);
+ wl_ext_get_ioctl_ver(dev, &ioctl_ver);
+ ret = wl_ext_set_chanspec(dev, ioctl_ver, channel, &fw_chspec);
} else {
- if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) {
+ if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci,
+ sizeof(channel_info_t), FALSE))) {
ANDROID_TRACE(("hw_channel %d\n", ci.hw_channel));
ANDROID_TRACE(("target_channel %d\n", ci.target_channel));
ANDROID_TRACE(("scan_channel %d\n", ci.scan_channel));
- bytes_written = snprintf(command, sizeof(channel_info_t)+2, "channel %d", ci.hw_channel);
+ bytes_written = snprintf(command, sizeof(channel_info_t)+2,
+ "channel %d", ci.hw_channel);
ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
ret = bytes_written;
}
memset(valid_chan_list, 0, sizeof(valid_chan_list));
list = (wl_uint32_list_t *)(void *) valid_chan_list;
list->count = htod32(WL_NUMCHANNELS);
- ret = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), 0);
+ ret = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
+ sizeof(valid_chan_list), 0);
if (ret<0) {
ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret));
} else {
bytes_written = snprintf(command, total_len, "channels");
for (i = 0; i < dtoh32(list->count); i++) {
- bytes_written += snprintf(command+bytes_written, total_len, " %d", dtoh32(list->element[i]));
+ bytes_written += snprintf(command+bytes_written, total_len, " %d",
+ dtoh32(list->element[i]));
printf("%d ", dtoh32(list->element[i]));
}
printf("\n");
if (roam_trigger[0]) {
roam_trigger[1] = WLC_BAND_ALL;
- ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 1);
+ ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), 1);
if (ret)
- ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+ ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n",
+ roam_trigger[0], ret));
} else {
roam_trigger[1] = WLC_BAND_2G;
- ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
+ ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), 0);
if (!ret)
trigger[0] = roam_trigger[0];
else
- ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+ ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n",
+ roam_trigger[0], ret));
roam_trigger[1] = WLC_BAND_5G;
- ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
+ ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), 0);
if (!ret)
trigger[1] = roam_trigger[0];
else
- ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+ ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n",
+ roam_trigger[0], ret));
ANDROID_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1]));
bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]);
} else {
if (id < 0)
id = 0;
- ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, sizeof(buf), NULL);
+ ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf,
+ sizeof(buf), NULL);
if (ret) {
goto exit;
} else {
}
printf("\n");
}
- bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ", dtoh32(mkeep_alive_pktp->period_msec));
+ bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ",
+ dtoh32(mkeep_alive_pktp->period_msec));
bytes_written += snprintf(command+bytes_written, total_len, "0x");
for (i=0; i<mkeep_alive_pktp->len_bytes; i++) {
- bytes_written += snprintf(command+bytes_written, total_len, "%x", mkeep_alive_pktp->data[i]);
+ bytes_written += snprintf(command+bytes_written, total_len, "%x",
+ mkeep_alive_pktp->data[i]);
}
ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
ret = bytes_written;
return 0;
}
+static void
+wl_ext_get_amode(struct wl_if_info *cur_if, char *amode)
+{
+ struct net_device *dev = cur_if->dev;
+ int auth=-1, wpa_auth=-1;
+
+ wl_ext_iovar_getint(dev, "auth", &auth);
+ wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
+
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (auth == 0 && wpa_auth == 0) {
+ strcpy(amode, "open");
+ } else if (auth == 0 && wpa_auth == 128) {
+ strcpy(amode, "sae");
+ }
+ } else if (auth == 0 && wpa_auth == 0) {
+ strcpy(amode, "open");
+ } else if (auth == 1 && wpa_auth == 0) {
+ strcpy(amode, "shared");
+ } else if (auth == 0 && wpa_auth == 4) {
+ strcpy(amode, "wpapsk");
+ } else if (auth == 0 && wpa_auth == 128) {
+ strcpy(amode, "wpa2psk");
+ } else if (auth == 0 && wpa_auth == 132) {
+ strcpy(amode, "wpawpa2psk");
+ }
+}
+
+static void
+wl_ext_get_emode(struct wl_if_info *cur_if, char *emode)
+{
+ struct net_device *dev = cur_if->dev;
+ int wsec=0;
+
+ wl_ext_iovar_getint(dev, "wsec", &wsec);
+
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (wsec == 0) {
+ strcpy(emode, "none");
+ } else {
+ strcpy(emode, "sae");
+ }
+ } else if (wsec == 0) {
+ strcpy(emode, "none");
+ } else if (wsec == 1) {
+ strcpy(emode, "wep");
+ } else if (wsec == 2 || wsec == 10) {
+ strcpy(emode, "tkip");
+ } else if (wsec == 4 || wsec == 12) {
+ strcpy(emode, "aes");
+ } else if (wsec == 6 || wsec == 14) {
+ strcpy(emode, "tkipaes");
+ }
+}
+
static int
-wl_ext_set_amode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params)
+wl_ext_set_amode(struct wl_if_info *cur_if)
{
struct net_device *dev = cur_if->dev;
authmode_t amode = cur_if->amode;
int auth=0, wpa_auth=0;
- if (amode == AUTH_OPEN) {
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (amode == AUTH_SAE) {
+ auth = 0;
+ wpa_auth = 128;
+ ANDROID_INFO(("%s: Authentication: SAE\n", __FUNCTION__));
+ } else {
+ auth = 0;
+ wpa_auth = 0;
+ ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__));
+ }
+ } else if (amode == AUTH_OPEN) {
auth = 0;
wpa_auth = 0;
- ANDROID_TRACE(("%s: Authentication: Open System\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__));
} else if (amode == AUTH_SHARED) {
auth = 1;
wpa_auth = 0;
- ANDROID_TRACE(("%s: Authentication: Shared Key\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: Shared Key\n", __FUNCTION__));
} else if (amode == AUTH_WPAPSK) {
auth = 0;
wpa_auth = 4;
- ANDROID_TRACE(("%s: Authentication: WPA-PSK\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: WPA-PSK\n", __FUNCTION__));
} else if (amode == AUTH_WPA2PSK) {
auth = 0;
wpa_auth = 128;
- ANDROID_TRACE(("%s: Authentication: WPA2-PSK\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: WPA2-PSK\n", __FUNCTION__));
} else if (amode == AUTH_WPAWPA2PSK) {
auth = 0;
wpa_auth = 132;
- ANDROID_TRACE(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__));
}
if (cur_if->ifmode == IMESH_MODE) {
s32 val = WL_BSSTYPE_MESH;
encmode_t emode = cur_if->emode;
char *key = cur_if->key;
s8 iovar_buf[WLC_IOCTL_SMLEN];
+ struct dhd_pub *dhd = dhd_get_pub(dev);
memset(&wsec_key, 0, sizeof(wsec_key));
memset(&psk, 0, sizeof(psk));
- if (emode == ENC_NONE) {
+
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (amode == AUTH_SAE) {
+ wsec = 4;
+ ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__));
+ } else {
+ wsec = 0;
+ ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__));
+ }
+ } else if (emode == ENC_NONE) {
wsec = 0;
- ANDROID_TRACE(("%s: Encryption: No securiy\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__));
} else if (emode == ENC_WEP) {
wsec = 1;
wl_ext_parse_wep(key, &wsec_key);
- ANDROID_TRACE(("%s: Encryption: WEP\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, wsec_key.data));
+ ANDROID_INFO(("%s: Encryption: WEP\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, wsec_key.data));
} else if (emode == ENC_TKIP) {
wsec = 2;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
- ANDROID_TRACE(("%s: Encryption: TKIP\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
- } else if (emode == ENC_AES) {
+ ANDROID_INFO(("%s: Encryption: TKIP\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ } else if (emode == ENC_AES || amode == AUTH_SAE) {
wsec = 4;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
- ANDROID_TRACE(("%s: Encryption: AES\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
} else if (emode == ENC_TKIPAES) {
wsec = 6;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
- ANDROID_TRACE(("%s: Encryption: TKIP/AES\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ ANDROID_INFO(("%s: Encryption: TKIP/AES\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ }
+ if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 &&
+ apsta_params->apstamode == IAPSTA_MODE) {
+ wsec |= 0x8; // terence 20180628: fix me, this is a workaround
}
wl_ext_iovar_setint(dev, "wsec", wsec);
if (cur_if->ifmode == IMESH_MODE) {
- if (amode == AUTH_WPA2PSK && emode == ENC_AES) {
+ if (amode == AUTH_SAE) {
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, key));
wl_ext_iovar_setint(dev, "mesh_auth_proto", 1);
wl_ext_iovar_setint(dev, "mfp", WL_MFP_REQUIRED);
wl_ext_iovar_setbuf(dev, "sae_password", key, strlen(key),
return 0;
}
+static uint16
+wl_ext_get_chan(struct net_device *dev)
+{
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ int ret = 0;
+ uint16 chan = 0, ctl_chan;
+ struct ether_addr bssid;
+ u32 chanspec = 0;
+
+ ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
+ if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
+ if (wldev_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
+ chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
+ ctl_chan = wf_chspec_ctlchan(chanspec);
+ chan = (u16)(ctl_chan & 0x00FF);
+ ANDROID_INFO(("%s: cur_chan=%d(0x%x)\n", __FUNCTION__,
+ chan, chanspec));
+ return chan;
+ }
+ }
+
+ return 0;
+}
+
+static chanspec_t
+wl_ext_get_chanspec(struct wl_apsta_params *apsta_params,
+ struct net_device *dev, uint16 channel)
+{
+ s32 _chan = channel;
+ chanspec_t chspec = 0;
+ chanspec_t fw_chspec = 0;
+ u32 bw = WL_CHANSPEC_BW_20;
+ s32 err = BCME_OK;
+ s32 bw_cap = 0;
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ struct {
+ u32 band;
+ u32 bw_cap;
+ } param = {0, 0};
+ uint band;
+
+ if (_chan <= CH_MAX_2G_CHANNEL)
+ band = IEEE80211_BAND_2GHZ;
+ else
+ band = IEEE80211_BAND_5GHZ;
+
+ if (band == IEEE80211_BAND_5GHZ) {
+ param.band = WLC_BAND_5G;
+ err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ if (err) {
+ if (err != BCME_UNSUPPORTED) {
+ ANDROID_ERROR(("bw_cap failed, %d\n", err));
+ return err;
+ } else {
+ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+ if (err) {
+ ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err));
+ }
+ if (bw_cap != WLC_N_BW_20ALL)
+ bw = WL_CHANSPEC_BW_40;
+ }
+ } else {
+ if (WL_BW_CAP_80MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_80;
+ else if (WL_BW_CAP_40MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_40;
+ else
+ bw = WL_CHANSPEC_BW_20;
+ }
+ }
+ else if (band == IEEE80211_BAND_2GHZ)
+ bw = WL_CHANSPEC_BW_20;
+
+set_channel:
+ chspec = wf_channel2chspec(_chan, bw);
+ if (wf_chspec_valid(chspec)) {
+ fw_chspec = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, chspec);
+ if (fw_chspec == INVCHANSPEC) {
+ ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n",
+ __FUNCTION__));
+ fw_chspec = 0;
+ }
+ } else {
+ if (bw == WL_CHANSPEC_BW_80)
+ bw = WL_CHANSPEC_BW_40;
+ else if (bw == WL_CHANSPEC_BW_40)
+ bw = WL_CHANSPEC_BW_20;
+ else
+ bw = 0;
+ if (bw)
+ goto set_channel;
+ ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec));
+ err = BCME_ERROR;
+ }
+
+ return fw_chspec;
+}
+
static void
wl_ext_ch_to_chanspec(int ch, struct wl_join_params *join_params,
size_t *join_params_size)
}
}
-static chanspec_t
-wl_ext_chspec_from_legacy(chanspec_t legacy_chspec)
-{
- chanspec_t chspec;
-
- /* get the channel number */
- chspec = LCHSPEC_CHANNEL(legacy_chspec);
-
- /* convert the band */
- if (LCHSPEC_IS2G(legacy_chspec)) {
- chspec |= WL_CHANSPEC_BAND_2G;
- } else {
- chspec |= WL_CHANSPEC_BAND_5G;
- }
-
- /* convert the bw and sideband */
- if (LCHSPEC_IS20(legacy_chspec)) {
- chspec |= WL_CHANSPEC_BW_20;
- } else {
- chspec |= WL_CHANSPEC_BW_40;
- if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
- chspec |= WL_CHANSPEC_CTL_SB_L;
- } else {
- chspec |= WL_CHANSPEC_CTL_SB_U;
- }
- }
-
- if (wf_chspec_malformed(chspec)) {
- ANDROID_ERROR(("wl_ext_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
- chspec));
- return INVCHANSPEC;
- }
-
- return chspec;
-}
-
-static chanspec_t
-wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
-{
- chanspec = dtohchanspec(chanspec);
- if (ioctl_ver == 1) {
- chanspec = wl_ext_chspec_from_legacy(chanspec);
- }
-
- return chanspec;
-}
-
static s32
wl_ext_connect(struct wl_if_info *cur_if)
{
err = -ENOMEM;
goto exit;
}
- ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), strlen(cur_if->ssid));
+ ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID),
+ strlen(cur_if->ssid));
memcpy(&ext_join_params->ssid.SSID, cur_if->ssid, ext_join_params->ssid.SSID_len);
ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
/* increate dwell time to receive probe response or detect Beacon
ext_join_params->ssid.SSID_len));
}
- err = wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "join", ext_join_params, join_params_size,
- iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
+ err = wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "join", ext_join_params,
+ join_params_size, iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
printf("Connecting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), cur_if->channel,
}
+static void
+wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params,
+ bool need_rtnl_unlock)
+{
+ if (need_rtnl_unlock)
+ rtnl_unlock();
+ wait_event_interruptible_timeout(apsta_params->netif_change_event,
+ apsta_params->netif_change, msecs_to_jiffies(1500));
+ if (need_rtnl_unlock)
+ rtnl_lock();
+}
+
static void
wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_params)
{
struct dhd_pub *dhd;
+ apstamode_t apstamode = apsta_params->apstamode;
wl_interface_create_t iface;
struct wl_if_info *cur_if;
wlc_ssid_t ssid = { 0, {0} };
wl_country_t cspec = {{0}, 0, {0}};
wl_p2p_if_t ifreq;
s32 val = 0;
- int i, dfs = 1;
+ int i, dfs = 1, pm = 0;
dhd = dhd_get_pub(dev);
- if (!strlen(apsta_params->if_info[IF_VIF].ifname))
- strcpy(apsta_params->if_info[IF_VIF].ifname, "wlan1");
- if (!strlen(apsta_params->if_info[IF_VIF2].ifname))
- strcpy(apsta_params->if_info[IF_VIF2].ifname, "wlan2");
-
for (i=0; i<MAX_IF_NUM; i++) {
cur_if = &apsta_params->if_info[i];
+ if (i == 1 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan1");
+ if (i == 2 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan2");
if (cur_if->ifmode == ISTA_MODE) {
cur_if->channel = 0;
cur_if->maxassoc = -1;
cur_if->ifstate = IF_STATE_INIT;
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_sta", i);
+ cur_if->prio = PRIO_STA;
+ cur_if->prefix = 'S';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
} else if (cur_if->ifmode == IAP_MODE) {
cur_if->channel = 1;
cur_if->maxassoc = -1;
cur_if->ifstate = IF_STATE_INIT;
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_ap", i);
+ cur_if->prio = PRIO_AP;
+ cur_if->prefix = 'A';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
dfs = 0;
} else if (cur_if->ifmode == IMESH_MODE) {
cur_if->channel = 1;
cur_if->maxassoc = -1;
cur_if->ifstate = IF_STATE_INIT;
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_mesh", i);
+ cur_if->prio = PRIO_MESH;
+ cur_if->prefix = 'M';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
dfs = 0;
}
}
- if (dfs == 0) {
+
+ if (!dfs && !apsta_params->vsdb) {
dhd_conf_get_country(dhd, &cspec);
- if (!dhd_conf_map_country_list(dhd, &cspec, 1)) {
+ if (!dhd_conf_map_country_list(dhd, &cspec)) {
dhd_conf_set_country(dhd, &cspec);
dhd_bus_country_set(dev, &cspec, TRUE);
}
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setint(dev, "dfs_chan_disable", 1);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ }
+
+ if (FW_SUPPORTED(dhd, rsdb)) {
+ if (apstamode == IDUALAP_MODE)
+ apsta_params->rsdb = TRUE;
+ else if (apstamode == ISTAAPAP_MODE)
+ apsta_params->rsdb = FALSE;
+ if (apstamode == IDUALAP_MODE || apstamode == ISTAAPAP_MODE ||
+ apstamode == IMESHONLY_MODE || apstamode == IMESHSTA_MODE ||
+ apstamode == IMESHAP_MODE || apstamode == IMESHAPSTA_MODE ||
+ apstamode == IMESHAPAP_MODE) {
+ wl_config_t rsdb_mode_cfg = {0, 0};
+ if (apsta_params->rsdb)
+ rsdb_mode_cfg.config = 1;
+ printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
+ sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ }
+ } else {
+ apsta_params->rsdb = FALSE;
}
- if (apsta_params->apstamode == ISTAONLY_MODE) {
+ if (apstamode == ISTAONLY_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
- } else if (apsta_params->apstamode == IAPONLY_MODE) {
+ } else if (apstamode == IAPONLY_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is enabled, disable arpoe */
#endif
#endif /* PROP_TXSTATUS_VSDB */
}
- else if (apsta_params->apstamode == IAPSTA_MODE) {
+ else if (apstamode == IAPSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ apsta_params->netif_change = FALSE;
if (FW_SUPPORTED(dhd, rsdb)) {
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface,
+ sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL);
} else {
- wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), iovar_buf,
- WLC_IOCTL_SMLEN, 1, NULL);
+ wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid),
+ iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
}
- apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IDUALAP_MODE) {
+ else if (apstamode == IDUALAP_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
/* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */
#ifdef ARP_OFFLOAD_SUPPORT
dhd_arp_offload_enable(dhd, FALSE);
#endif /* ARP_OFFLOAD_SUPPORT */
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 0);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
val = 1;
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IMESHONLY_MODE) {
+ else if (apstamode == ISTAAPAP_MODE) {
+ u8 rand_bytes[2] = {0, };
+ get_random_bytes(&rand_bytes, sizeof(rand_bytes));
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbss", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
- // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
- }
- else if (apsta_params->apstamode == IMESHSTA_MODE) {
- wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
- wl_ext_iovar_setint(dev, "mpc", 0);
- wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
- iface.flags = WL_INTERFACE_CREATE_STA;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
+ iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE;
+ memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+ iface.mac_addr.octet[0] |= 0x02;
+ iface.mac_addr.octet[5] += 0x01;
+ memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
- }
- else if (apsta_params->apstamode == IMESHAP_MODE) {
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
+ bzero(&iface, sizeof(wl_interface_create_t));
+ iface.ver = WL_INTERFACE_CREATE_VER;
+ iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE;
+ memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+ iface.mac_addr.octet[0] |= 0x02;
+ iface.mac_addr.octet[5] += 0x02;
+ memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
+ apsta_params->netif_change = FALSE;
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
+ }
+ else if (apstamode == IMESHONLY_MODE) {
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
+ }
+ else if (apstamode == IMESHSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
+ wl_ext_iovar_setint(dev, "apsta", 1);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ bzero(&iface, sizeof(wl_interface_create_t));
+ iface.ver = WL_INTERFACE_CREATE_VER;
+ iface.flags = WL_INTERFACE_CREATE_STA;
+ apsta_params->netif_change = FALSE;
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
+ }
+ else if (apstamode == IMESHAP_MODE) {
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IMESHAPSTA_MODE) {
+ else if (apstamode == IMESHAPSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_STA;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IMESHAPAP_MODE) {
+ else if (apstamode == IMESHAPAP_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IGOSTA_MODE) {
+ else if (apstamode == IGOSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
bzero(&ifreq, sizeof(wl_p2p_if_t));
ifreq.type = htod32(WL_P2P_IF_GO);
+ apsta_params->netif_change = FALSE;
wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
- apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
apsta_params->init = TRUE;
- printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode);
+
+ printf("%s: apstamode=%d\n", __FUNCTION__, apstamode);
}
static int
apsta_params->apstamode = IAPSTA_MODE;
} else if (!strcmp(pick_tmp2, "ap-ap")) {
apsta_params->apstamode = IDUALAP_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-ap-ap")) {
+ apsta_params->apstamode = ISTAAPAP_MODE;
} else if (!strcmp(pick_tmp2, "mesh")) {
apsta_params->apstamode = IMESHONLY_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-sta")) {
+ } else if (!strcmp(pick_tmp2, "mesh-sta") ||
+ !strcmp(pick_tmp2, "sta-mesh")) {
apsta_params->apstamode = IMESHSTA_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap")) {
+ } else if (!strcmp(pick_tmp2, "mesh-ap") ||
+ !strcmp(pick_tmp2, "ap-mesh")) {
apsta_params->apstamode = IMESHAP_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap-sta")) {
+ } else if (!strcmp(pick_tmp2, "mesh-ap-sta") ||
+ !strcmp(pick_tmp2, "sta-ap-mesh") ||
+ !strcmp(pick_tmp2, "sta-mesh-ap")) {
apsta_params->apstamode = IMESHAPSTA_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) {
+ } else if (!strcmp(pick_tmp2, "mesh-ap-ap") ||
+ !strcmp(pick_tmp2, "ap-ap-mesh")) {
apsta_params->apstamode = IMESHAPAP_MODE;
} else if (!strcmp(pick_tmp2, "apsta")) {
apsta_params->apstamode = IAPSTA_MODE;
apsta_params->if_info[i].ifmode = ISTA_MODE;
else if (!strcmp(pch, "ap"))
apsta_params->if_info[i].ifmode = IAP_MODE;
- else if (!strcmp(pch, "mesh"))
+ else if (!strcmp(pch, "mesh")) {
+ if (dhd->conf->fw_type != FW_TYPE_MESH) {
+ ANDROID_ERROR(("%s: wrong fw type\n", __FUNCTION__));
+ return -1;
+ }
apsta_params->if_info[i].ifmode = IMESH_MODE;
+ }
pch = bcmstrtok(&pick_tmp2, " -", 0);
}
}
+ }
+ else if (!strcmp(param, "rsdb")) {
+ pch = bcmstrtok(&pick_tmp, " ", 0);
+ if (pch) {
+ if (!strcmp(pch, "y")) {
+ apsta_params->rsdb = TRUE;
+ } else if (!strcmp(pch, "n")) {
+ apsta_params->rsdb = FALSE;
+ } else {
+ ANDROID_ERROR(("%s: rsdb [y|n]\n", __FUNCTION__));
+ return -1;
+ }
+ }
} else if (!strcmp(param, "vsdb")) {
pch = bcmstrtok(&pick_tmp, " ", 0);
if (pch) {
return -1;
}
}
+ } else if (!strcmp(param, "csa")) {
+ pch = bcmstrtok(&pick_tmp, " ", 0);
+ if (pch) {
+ apsta_params->csa = (int)simple_strtol(pch, NULL, 0);
+ }
} else if (!strcmp(param, "ifname")) {
pch = NULL;
pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
{
char *pch, *pick_tmp;
char name[20], data[100];
- int i, j;
+ int i, j, len;
char *ifname_head = NULL;
typedef struct config_map_t {
char *head;
char *tail;
} config_map_t;
-
+
config_map_t config_map [] = {
{" ifname ", NULL, NULL},
{" ssid ", NULL, NULL},
pick_tmp = command;
// reset head and tail
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
row->head = NULL;
row->tail = pick_tmp + strlen(pick_tmp);
}
// pick head
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
pch = strstr(pick_tmp, row->name);
if (pch) {
}
// sort by head
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
row_prev = &config_map[i];
- for (j = i+1; j < sizeof(config_map)/sizeof(config_map[0]); j++) {
+ for (j = i+1; j < sizeof(config_map)/sizeof(config_map[0]); j++) {
row = &config_map[j];
if (row->head < row_prev->head) {
strcpy(name, row_prev->name);
}
// pick tail
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
row_prev = &config_map[i];
row = &config_map[i+1];
if (row_prev->head) {
}
// remove name from head
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
if (row->head) {
if (!strcmp(row->name, " ifname ")) {
}
}
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
if (row->head) {
memset(data, 0, sizeof(data));
- if (row->tail) {
+ if (row->tail && row->tail > row->head) {
strncpy(data, row->head, row->tail-row->head);
} else {
strcpy(data, row->head);
if (!strcmp(row->name, " ifname ")) {
break;
} else if (!strcmp(row->name, " ssid ")) {
- strcpy(cur_if->ssid, pick_tmp);
+ len = strlen(pick_tmp);
+ memset(cur_if->ssid, 0, sizeof(cur_if->ssid));
+ if (pick_tmp[0] == '"' && pick_tmp[len-1] == '"')
+ strncpy(cur_if->ssid, &pick_tmp[1], len-2);
+ else
+ strcpy(cur_if->ssid, pick_tmp);
} else if (!strcmp(row->name, " bssid ")) {
pch = bcmstrtok(&pick_tmp, ": ", 0);
for (j=0; j<6 && pch; j++) {
cur_if->amode = AUTH_WPA2PSK;
else if (!strcmp(pick_tmp, "wpawpa2psk"))
cur_if->amode = AUTH_WPAWPA2PSK;
+ else if (!strcmp(pick_tmp, "sae"))
+ cur_if->amode = AUTH_SAE;
else {
ANDROID_ERROR(("%s: amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\n",
__FUNCTION__));
return -1;
}
} else if (!strcmp(row->name, " key ")) {
- strcpy(cur_if->key, pick_tmp);
+ len = strlen(pick_tmp);
+ memset(cur_if->key, 0, sizeof(cur_if->key));
+ if (pick_tmp[0] == '"' && pick_tmp[len-1] == '"')
+ strncpy(cur_if->key, &pick_tmp[1], len-2);
+ else
+ strcpy(cur_if->key, pick_tmp);
}
}
}
static int
wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len)
{
- int ret=0;
+ int ret=0, i;
char *pch, *pch2, *pick_tmp, *pick_next=NULL, *param;
struct wl_apsta_params *apsta_params = &g_apsta_params;
char ifname[IFNAMSIZ+1];
- struct wl_if_info *cur_if = &apsta_params->if_info[IF_PIF];
+ struct wl_if_info *cur_if = NULL;
if (!apsta_params->init) {
ANDROID_ERROR(("%s: please init first\n", __FUNCTION__));
ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__));
return -1;
}
- if (!strcmp(apsta_params->if_info[IF_PIF].dev->name, ifname)) {
- cur_if = &apsta_params->if_info[IF_PIF];
- } else if (!strcmp(apsta_params->if_info[IF_VIF].ifname, ifname)) {
- cur_if = &apsta_params->if_info[IF_VIF];
- } else if (!strcmp(apsta_params->if_info[IF_VIF2].ifname, ifname)) {
- cur_if = &apsta_params->if_info[IF_VIF2];
- } else {
- ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n", __FUNCTION__,
- ifname, apsta_params->apstamode));
+ for (i=0; i<MAX_IF_NUM; i++) {
+ if (apsta_params->if_info[i].dev &&
+ !strcmp(apsta_params->if_info[i].dev->name, ifname)) {
+ cur_if = &apsta_params->if_info[i];
+ break;
+ }
+ }
+ if (!cur_if) {
+ ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n",
+ __FUNCTION__, ifname, apsta_params->apstamode));
return -1;
}
ret = wl_ext_parse_config(cur_if, pick_tmp, &pick_next);
return 0;
}
+static int
+wl_ext_isam_status(struct net_device *dev)
+{
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ int i;
+ bool now_if;
+ struct wl_if_info *tmp_if;
+ uint16 chan = 0;
+ wlc_ssid_t ssid = { 0, {0} };
+ char amode[16], emode[16];
+
+ if (apsta_params->init == FALSE) {
+ return 0;
+ }
+
+ printf("****************************\n");
+ printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode);
+ for (i=0; i<MAX_IF_NUM; i++) {
+ now_if = FALSE;
+ memset(&ssid, 0, sizeof(ssid));
+ memset(amode, 0, sizeof(amode));
+ memset(emode, 0, sizeof(emode));
+ tmp_if = &apsta_params->if_info[i];
+ if (dev == tmp_if->dev)
+ now_if = TRUE;
+ if (tmp_if->dev) {
+ chan = wl_ext_get_chan(tmp_if->dev);
+ if (chan) {
+ wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
+ wl_ext_get_amode(tmp_if, amode);
+ wl_ext_get_emode(tmp_if, emode);
+ }
+ if (chan) {
+ printf("%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n",
+ tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
+ now_if?"*":" ", chan, amode, emode, ssid.SSID);
+ } else {
+ printf("%s[%c-%c%s]:\n",
+ tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
+ now_if?"*":" ");
+ }
+ }
+ }
+ printf("****************************\n");
+
+ return 0;
+}
+
+static int
+wl_ext_if_down(struct wl_if_info *cur_if)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ scb_val_t scbval;
+ struct {
+ s32 cfg;
+ s32 val;
+ } bss_setbuf;
+ apstamode_t apstamode = g_apsta_params.apstamode;
+
+ printf("%s: %s[%c] Turning off\n", __FUNCTION__, cur_if->ifname, cur_if->prefix);
+
+ if (cur_if->ifmode == ISTA_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
+ } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+ // deauthenticate all STA first
+ memcpy(scbval.ea.octet, ðer_bcast, ETHER_ADDR_LEN);
+ wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1);
+ }
+
+ if (apstamode == IAPONLY_MODE || apstamode == IMESHONLY_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_DOWN, NULL, 0, 1);
+ } else {
+ bss_setbuf.cfg = 0xffffffff;
+ bss_setbuf.val = htod32(0);
+ wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ }
+
+ return 0;
+}
+
+static int
+wl_ext_if_up(struct wl_if_info *cur_if)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ struct {
+ s32 cfg;
+ s32 val;
+ } bss_setbuf;
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ apstamode_t apstamode = apsta_params->apstamode;
+ chanspec_t fw_chspec;
+
+ if (cur_if->ifmode != IAP_MODE) {
+ ANDROID_ERROR(("%s: Wrong ifmode on %s[%c]\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix));
+ return 0;
+ }
+
+ if (cur_if->channel >= 52 && cur_if->channel <= 148) {
+ printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ return 0;
+ }
+
+ printf("%s: %s[%c] Turning on\n", __FUNCTION__, cur_if->ifname, cur_if->prefix);
+ wl_ext_isam_status(cur_if->dev);
+
+ wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
+ &fw_chspec);
+
+ if (apstamode == IAPONLY_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_UP, NULL, 0, 1);
+ } else {
+ bss_setbuf.cfg = 0xffffffff;
+ bss_setbuf.val = htod32(1);
+ wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf,
+ sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ }
+
+ OSL_SLEEP(500);
+
+ return 0;
+}
+
static int
wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
{
wlc_ssid_t ssid = { 0, {0} };
scb_val_t scbval;
struct {
- s32 tmp;
s32 cfg;
s32 val;
} bss_setbuf;
return -1;
}
+ printf("%s: %s[%c] Disabling\n", __FUNCTION__, ifname, cur_if->prefix);
+
if (cur_if->ifmode == ISTA_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
} else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
wl_ext_iovar_setint(dev, "mpc", 1);
} else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) &&
cur_if->ifmode == IAP_MODE) {
- // if_info[IF_VIF] is AP mode
- bss_setbuf.tmp = 0xffffffff;
- bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+ bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
#endif
#endif /* PROP_TXSTATUS_VSDB */
- } else if (apstamode == IDUALAP_MODE) {
- bss_setbuf.tmp = 0xffffffff;
- bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+ }
+ else if (apstamode == IDUALAP_MODE) {
+ bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
} else if (apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
- apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) {
- bss_setbuf.tmp = 0xffffffff;
- bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+ apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE ||
+ apstamode == ISTAAPAP_MODE) {
+ bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
cur_if->ifstate = IF_STATE_DISALBE;
- printf("%s: ifname=%s, mode=%d\n", __FUNCTION__, ifname, cur_if->ifmode);
+ printf("%s: %s[%c] disabled\n", __FUNCTION__, ifname, cur_if->prefix);
return 0;
}
-static bool
-wl_ext_iapsta_diff_band(uint16 channel1, uint16 channel2)
-{
- ANDROID_TRACE(("%s: cur_chan=%d, channel=%d\n", __FUNCTION__, channel1, channel2));
- if ((channel1 <= CH_MAX_2G_CHANNEL && channel2 > CH_MAX_2G_CHANNEL) ||
- (channel1 > CH_MAX_2G_CHANNEL && channel2 <= CH_MAX_2G_CHANNEL)) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
static uint16
-wl_ext_iapsta_is_vsdb(struct net_device *dev,
- struct wl_if_info *cur_if, struct wl_if_info *another_if)
+wl_ext_get_vsdb_chan(struct net_device *dev,
+ struct wl_if_info *cur_if, struct wl_if_info *target_if)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- int ret = 0, cur_chan = 0;
- uint16 another_chan = 0, ctl_chan;
+ uint16 target_chan = 0, cur_chan = cur_if->channel;
struct dhd_pub *dhd;
- struct ether_addr bssid;
- u32 chanspec = 0;
dhd = dhd_get_pub(dev);
-
- ret = wldev_ioctl(another_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
- if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
- if (wldev_iovar_getint(another_if->dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
- ANDROID_TRACE(("%s: chanspec=0x%x\n", __FUNCTION__, chanspec));
- chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
- ctl_chan = wf_chspec_ctlchan(chanspec);
- another_chan = (u16)(ctl_chan & 0x00FF);
- cur_chan = cur_if->channel;
- if (wl_ext_iapsta_diff_band(another_chan, cur_chan)) {
- // different band
- if (!FW_SUPPORTED(dhd, rsdb))
- return another_chan;
- } else {
- // same band
- if (another_chan != cur_chan)
- return another_chan;
- }
+
+ target_chan = wl_ext_get_chan(target_if->dev);
+ if (target_chan) {
+ ANDROID_INFO(("%s: cur_chan=%d, target_chan=%d\n", __FUNCTION__,
+ cur_chan, target_chan));
+ if ((cur_chan <= CH_MAX_2G_CHANNEL && target_chan > CH_MAX_2G_CHANNEL) ||
+ (cur_chan > CH_MAX_2G_CHANNEL && target_chan <= CH_MAX_2G_CHANNEL)) {
+ // different band
+ if (!FW_SUPPORTED(dhd, rsdb) || !apsta_params->rsdb)
+ return target_chan;
+ } else {
+ // same band
+ if (target_chan != cur_chan)
+ return target_chan;
}
}
return 0;
}
-static void
-wl_ext_iapsta_change_channel(struct wl_if_info *cur_if, uint16 chan)
+static int
+wl_ext_triger_csa(struct wl_if_info *cur_if)
{
- if (chan) {
- char cmd[50] = "";
- printf("%s: deauthenticate all STA and move to chan=%d on %s\n",
- __FUNCTION__, chan, cur_if->ifname);
- snprintf(cmd, 50, "%s %s", "isam_disable ifname", cur_if->ifname);
- wl_ext_iapsta_disable(cur_if->dev, cmd, strlen(cmd));
- cur_if->channel = chan;
- snprintf(cmd, 50, "%s %s", "isam_enable ifname", cur_if->ifname);
- wl_ext_iapsta_enable(cur_if->dev, cmd, strlen(cmd));
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+ if (apsta_params->csa & CSA_DRV_BIT &&
+ (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) {
+ if (!cur_if->channel) {
+ printf("%s: %s[%c] skip channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ } else if (cur_if->channel >= 52 && cur_if->channel <= 148) {
+ printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ wl_ext_if_down(cur_if);
+ } else {
+ wl_chan_switch_t csa_arg;
+ memset(&csa_arg, 0, sizeof(csa_arg));
+ csa_arg.mode = 1;
+ csa_arg.count = 3;
+ csa_arg.chspec = wl_ext_get_chanspec(apsta_params, cur_if->dev,
+ cur_if->channel);
+ if (csa_arg.chspec) {
+ printf("%s: Trigger CSA to channel %d(0x%x)\n", __FUNCTION__,
+ cur_if->channel, csa_arg.chspec);
+ wl_ext_iovar_setbuf(cur_if->dev, "csa", &csa_arg, sizeof(csa_arg),
+ iovar_buf, sizeof(iovar_buf), NULL);
+ OSL_SLEEP(500);
+ wl_ext_isam_status(cur_if->dev);
+ } else {
+ printf("%s: fail to get chanspec\n", __FUNCTION__);
+ }
+ }
}
+
+ return 0;
}
-static void
-wl_ext_iapsta_change_cur_iface_channel(struct net_device *dev,
+static uint16
+wl_ext_move_cur_channel(struct net_device *dev,
struct wl_if_info *cur_if)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- struct wl_if_info *another_if, *final_if = NULL;
- uint16 new_chan = 0;
+ struct wl_if_info *tmp_if, *target_if = NULL;
+ uint16 tmp_chan, target_chan = 0;
+ wl_prio_t max_prio;
int i;
- if (cur_if->ifmode == IAP_MODE) {
- for (i=MAX_IF_NUM-1; i>=0; i--) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == ISTA_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan) {
- final_if = another_if;
- break;
- }
- }
- }
- } else if (cur_if->ifmode == IMESH_MODE) {
- for (i=MAX_IF_NUM-1; i>=0; i--) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == ISTA_MODE || another_if->ifmode == IAP_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan) {
- final_if = another_if;
- break;
- }
+ if (apsta_params->vsdb) {
+ target_chan = cur_if->channel;
+ goto exit;
+ }
+
+ // find the max prio
+ max_prio = cur_if->prio;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if &&
+ tmp_if->prio > max_prio) {
+ tmp_chan = wl_ext_get_vsdb_chan(dev, cur_if, tmp_if);
+ if (tmp_chan) {
+ target_if = tmp_if;
+ target_chan = tmp_chan;
+ max_prio = tmp_if->prio;
}
}
}
- if (new_chan && !apsta_params->vsdb) {
- cur_if->channel = new_chan;
- printf("%s: %s ifmode=%d, %s ifmode=%d, channel=%d\n", __FUNCTION__,
- cur_if->ifname, cur_if->ifmode, final_if->ifname, final_if->ifmode,
- cur_if->channel);
+
+ if (target_chan) {
+ printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->channel, target_if->ifname, target_chan);
+ cur_if->channel = target_chan;
+ }
+exit:
+ if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) &&
+ (cur_if->channel >= 52 && cur_if->channel <= 148)) {
+ printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ cur_if->channel = 0;
}
+ return cur_if->channel;
}
static void
-wl_ext_iapsta_change_other_iface_channel(struct net_device *dev,
+wl_ext_move_other_channel(struct net_device *dev,
struct wl_if_info *cur_if)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- struct wl_if_info *another_if;
- uint16 new_chan = 0;
+ struct wl_if_info *tmp_if, *target_if=NULL;
+ uint16 tmp_chan, target_chan = 0;
+ wl_prio_t max_prio = 0, cur_prio;
int i;
- if (cur_if->ifmode == ISTA_MODE) {
- for (i=MAX_IF_NUM-1; i>=0; i--) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == IAP_MODE || another_if->ifmode == IMESH_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan && !apsta_params->vsdb) {
- wl_ext_iapsta_change_channel(another_if, cur_if->channel);
- }
+ if (apsta_params->vsdb || !cur_if->channel) {
+ return;
+ }
+
+ // find the max prio, but lower than cur_if
+ cur_prio = cur_if->prio;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if &&
+ tmp_if->prio >= max_prio && tmp_if->prio <= cur_prio) {
+ tmp_chan = wl_ext_get_vsdb_chan(dev, cur_if, tmp_if);
+ if (tmp_chan) {
+ target_if = tmp_if;
+ target_chan = tmp_chan;
+ max_prio = tmp_if->prio;
}
}
- } else if (cur_if->ifmode == IAP_MODE) {
- for (i=0; i<MAX_IF_NUM; i++) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == IMESH_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan && !apsta_params->vsdb) {
- wl_ext_iapsta_change_channel(another_if, cur_if->channel);
- }
+ }
+
+ if (target_if) {
+ printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__,
+ target_if->ifname, target_chan, cur_if->ifname, cur_if->channel);
+ target_if->channel = cur_if->channel;
+ if (apsta_params->csa == 0) {
+ wl_ext_if_down(target_if);
+ wl_ext_move_other_channel(dev, target_if);
+ if (target_if->ifmode == ISTA_MODE || target_if->ifmode == IMESH_MODE) {
+ wl_ext_enable_iface(target_if->dev, target_if->ifname);
+ } else if (target_if->ifmode == IAP_MODE) {
+ wl_ext_if_up(target_if);
}
+ } else {
+ wl_ext_triger_csa(target_if);
}
}
}
static int
-wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
+wl_ext_enable_iface(struct net_device *dev, char *ifname)
{
- int ret = 0, i;
- char *pick_tmp, *param;
+ int i;
s8 iovar_buf[WLC_IOCTL_SMLEN];
wlc_ssid_t ssid = { 0, {0} };
chanspec_t fw_chspec;
struct wl_apsta_params *apsta_params = &g_apsta_params;
apstamode_t apstamode = apsta_params->apstamode;
struct wl_if_info *cur_if = NULL;
- char cmd[128];
struct dhd_pub *dhd;
- struct ether_addr bssid;
uint16 cur_chan;
dhd = dhd_get_pub(dev);
return -1;
}
- wl_ext_iapsta_change_cur_iface_channel(dev, cur_if);
+ printf("%s: %s[%c] Enabling\n", __FUNCTION__, ifname, cur_if->prefix);
- if ((apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
- apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) &&
- cur_if == &apsta_params->if_info[IF_PIF] &&
- cur_if->ifstate == IF_STATE_INIT &&
- FW_SUPPORTED(dhd, rsdb)) {
- wl_config_t rsdb_mode_cfg = {1, 0};
- // mesh-ap must set rsdb_mode=1 in same channel or AP mode not easy to be found
- printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);
- wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
- sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL);
- }
+ wl_ext_isam_status(cur_if->dev);
- ret = wldev_ioctl(cur_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
- if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
- ANDROID_INFO(("%s: Associated! ret %d\n", __FUNCTION__, ret));
+ wl_ext_move_cur_channel(dev, cur_if);
+ if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) {
return 0;
}
- ssid.SSID_len = strlen(cur_if->ssid);
- memcpy(ssid.SSID, cur_if->ssid, ssid.SSID_len);
- ANDROID_TRACE(("%s: apstamode=%d, bssidx=%d\n", __FUNCTION__, apstamode, cur_if->bssidx));
+ cur_chan = wl_ext_get_chan(cur_if->dev);
+ if (cur_chan) {
+ ANDROID_INFO(("%s: Associated!\n", __FUNCTION__));
+ if (cur_chan != cur_if->channel) {
+ wl_ext_triger_csa(cur_if);
+ }
+ return 0;
+ }
- wl_ext_iapsta_change_other_iface_channel(dev, cur_if);
+ wl_ext_move_other_channel(dev, cur_if);
- if (cur_if == &apsta_params->if_info[IF_VIF] || cur_if == &apsta_params->if_info[IF_VIF2]) {
+ if (cur_if->ifidx > 0) {
wl_ext_iovar_setbuf(cur_if->dev, "cur_etheraddr", (u8 *)cur_if->dev->dev_addr,
ETHER_ADDR_LEN, iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
// set ssid for AP
+ ssid.SSID_len = strlen(cur_if->ssid);
+ memcpy(ssid.SSID, cur_if->ssid, ssid.SSID_len);
if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
wl_ext_iovar_setint(dev, "mpc", 0);
if (apstamode == IAPONLY_MODE) {
if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
wl_ext_set_bgnmode(cur_if);
- cur_chan = cur_if->channel;
- if (!cur_chan) {
- cur_chan = 1;
+ if (!cur_if->channel) {
#ifdef WL_CFG80211
+ char *pick_tmp, *param;
+ char cmd[128];
+ uint16 cur_chan;
+ cur_chan = 1;
snprintf(cmd, 128, "get_best_channels");
wl_cfg80211_get_best_channels(dev, cmd, strlen(cmd));
pick_tmp = cmd;
}
param = bcmstrtok(&pick_tmp, " ", 0);
}
+ cur_if->channel = cur_chan;
+#else
+ cur_if->channel = 1;
#endif
}
- wl_ext_set_chanspec(cur_if->dev, cur_chan, &fw_chspec);
+ wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
+ &fw_chspec);
}
- wl_ext_set_amode(cur_if, apsta_params);
+ wl_ext_set_amode(cur_if);
wl_ext_set_emode(cur_if, apsta_params);
if (cur_if->ifmode == IAP_MODE) {
wl_ext_iovar_setint(dev, "maxassoc", cur_if->maxassoc);
// terence: fix me, hidden does not work in dualAP mode
if (cur_if->hidden > 0) {
- wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1);
- printf("%s: Broadcast SSID: %s\n", __FUNCTION__, cur_if->hidden ? "OFF":"ON");
+ wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden,
+ sizeof(cur_if->hidden), 1);
+ printf("%s: Broadcast SSID: %s\n", __FUNCTION__,
+ cur_if->hidden ? "OFF":"ON");
}
}
} else {
bss_setbuf.cfg = htod32(cur_if->bssidx);
bss_setbuf.val = htod32(1);
- wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
- iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf,
+ sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is enabled, disable arpoe */
}
else if (apstamode == IDUALAP_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
+ } else if (apstamode == ISTAAPAP_MODE) {
+ if (cur_if->ifmode == ISTA_MODE) {
+ wl_ext_connect(cur_if);
+ } else if (cur_if->ifmode == IAP_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
+ } else {
+ printf("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode);
+ }
} else if (apstamode == IMESHONLY_MODE ||
apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
} else if (cur_if->ifmode == IMESH_MODE) {
// need to up before setting ssid
- wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
memset(&join_params, 0, sizeof(join_params));
join_params.ssid.SSID_len = strlen(cur_if->ssid);
- memcpy((void *)join_params.ssid.SSID, cur_if->ssid, ssid.SSID_len);
+ memcpy((void *)join_params.ssid.SSID, cur_if->ssid, strlen(cur_if->ssid));
join_params.params.chanspec_list[0] = fw_chspec;
join_params.params.chanspec_num = 1;
join_params_size = sizeof(join_params);
}
}
- printf("%s: ifname=%s, mode=%d, SSID: \"%s\"\n", __FUNCTION__,
- ifname, cur_if->ifmode, cur_if->ssid);
+ OSL_SLEEP(500);
+ printf("%s: %s[%c] enabled with SSID: \"%s\"\n", __FUNCTION__,
+ ifname, cur_if->prefix, cur_if->ssid);
+ wl_ext_isam_status(cur_if->dev);
cur_if->ifstate = IF_STATE_ENABLE;
pch = bcmstrtok(&pick_tmp, " ", 0);
if (pch) {
strcpy(ifname, pch);
- ret = wl_ext_iapsta_enable_iface(dev, ifname);
+ ret = wl_ext_enable_iface(dev, ifname);
if (ret)
return ret;
- else
- OSL_SLEEP(1000);
} else {
ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__));
return -1;
wl_ext_iapsta_alive_preinit(struct net_device *dev)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
+ struct wl_if_info *cur_if;
+ int i;
if (apsta_params->init == TRUE) {
ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__));
ANDROID_TRACE(("%s: Enter\n", __FUNCTION__));
- strcpy(apsta_params->if_info[IF_PIF].ssid, "tttp");
- apsta_params->if_info[IF_PIF].maxassoc = -1;
- apsta_params->if_info[IF_PIF].channel = 1;
-
- if (!strlen(apsta_params->if_info[IF_VIF].ifname))
- strcpy(apsta_params->if_info[IF_VIF].ifname, "wlan1");
- strcpy(apsta_params->if_info[IF_VIF].ssid, "tttv");
- apsta_params->if_info[IF_VIF].maxassoc = -1;
- apsta_params->if_info[IF_VIF].channel = 1;
-
- if (!strlen(apsta_params->if_info[IF_VIF2].ifname))
- strcpy(apsta_params->if_info[IF_VIF2].ifname, "wlan2");
- strcpy(apsta_params->if_info[IF_VIF2].ssid, "tttv2");
- apsta_params->if_info[IF_VIF2].maxassoc = -1;
- apsta_params->if_info[IF_VIF2].channel = 161;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[i];
+ if (i == 1 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan1");
+ if (i == 2 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan2");
+ if (cur_if->ifmode == ISTA_MODE) {
+ cur_if->channel = 0;
+ cur_if->maxassoc = -1;
+ cur_if->ifstate = IF_STATE_INIT;
+ cur_if->prio = PRIO_STA;
+ cur_if->prefix = 'S';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
+ } else if (cur_if->ifmode == IAP_MODE) {
+ cur_if->channel = 1;
+ cur_if->maxassoc = -1;
+ cur_if->ifstate = IF_STATE_INIT;
+ cur_if->prio = PRIO_AP;
+ cur_if->prefix = 'A';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
+ } else if (cur_if->ifmode == IMESH_MODE) {
+ cur_if->channel = 1;
+ cur_if->maxassoc = -1;
+ cur_if->ifstate = IF_STATE_INIT;
+ cur_if->prio = PRIO_MESH;
+ cur_if->prefix = 'M';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
+ }
+ }
apsta_params->init = TRUE;
return op_mode;
}
+#if defined(WL_WIRELESS_EXT)
static bool
wl_ext_conn_status_str(uint32 event_type,
uint32 status, uint32 reason, char* stringBuf, uint buflen)
return FALSE;
}
+#endif /* WL_WIRELESS_EXT */
int
wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
struct wl_if_info *cur_if = NULL;
- char extra[IW_CUSTOM_MAX + 1];
int i;
#if defined(WL_WIRELESS_EXT)
+ char extra[IW_CUSTOM_MAX + 1];
union iwreq_data wrqu;
- int cmd = 0;
#endif
uint32 event_type = ntoh32(e->event_type);
uint32 status = ntoh32(e->status);
}
for (i=0; i<MAX_IF_NUM; i++) {
- if (apsta_params->if_info[i].bssidx == e->ifidx) {
+ if (apsta_params->if_info[i].ifidx == e->ifidx) {
cur_if = &apsta_params->if_info[i];
break;
}
return -1;
}
- memset(extra, 0, sizeof(extra));
-#if defined(WL_WIRELESS_EXT)
- memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
- wrqu.addr.sa_family = ARPHRD_ETHER;
-#endif
-
if (cur_if->ifmode == ISTA_MODE) {
- switch (event_type) {
- case WLC_E_LINK:
- if (!(flags & WLC_EVENT_MSG_LINK)) {
- printf("%s: %s Link Down with BSSID="MACSTR"\n", __FUNCTION__,
- cur_if->ifname, MAC2STR((u8 *)&e->addr));
- } else {
- printf("%s: %s Link UP with BSSID="MACSTR"\n", __FUNCTION__,
- cur_if->ifname, MAC2STR((u8 *)&e->addr));
- }
- break;
- default:
- /* Cannot translate event */
- break;
+ if (event_type == WLC_E_LINK) {
+ if (!(flags & WLC_EVENT_MSG_LINK)) {
+ printf("%s: %s[%c] Link Down with %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
+ } else {
+ printf("%s: %s[%c] Link UP with %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
+ }
}
- } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
- if (((event_type == WLC_E_ASSOC_IND) || (event_type == WLC_E_REASSOC_IND)) &&
- reason == DOT11_SC_SUCCESS) {
- printf("%s: %s connected device "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, MAC2STRDBG(e->addr.octet));
+ }
+ else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+ if ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
+ (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_INITIAL_ASSOC)) {
+ printf("%s: %s[%c] Link up\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix);
+ } else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
+ (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_DEAUTH)) {
+ printf("%s: %s[%c] Link down\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix);
+ }
+ else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
+ reason == DOT11_SC_SUCCESS) {
+ printf("%s: %s[%c] connected device %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
} else if (event_type == WLC_E_DISASSOC_IND) {
- printf("%s: %s disassociated device "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, MAC2STRDBG(e->addr.octet));
- } else if ((event_type == WLC_E_DEAUTH_IND) ||
- ((event_type == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) {
- printf("%s: %s deauthenticated device "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, MAC2STRDBG(e->addr.octet));
- } else {
- ANDROID_TRACE(("%s: %s event %d "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, event_type, MAC2STRDBG(e->addr.octet)));
+ printf("%s: %s[%c] disassociated device %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
+ } else if (event_type == WLC_E_DEAUTH_IND ||
+ (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
+ printf("%s: %s[%c] deauthenticated device %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
}
}
- if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) {
#if defined(WL_WIRELESS_EXT)
- cmd = IWEVCUSTOM;
+ memset(extra, 0, sizeof(extra));
+ memset(&wrqu, 0, sizeof(wrqu));
+ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) {
wrqu.data.length = strlen(extra);
- wireless_send_event(cur_if->dev, cmd, &wrqu, extra);
+ wireless_send_event(cur_if->dev, IWEVCUSTOM, &wrqu, extra);
+ ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d sent up\n",
+ __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status,
+ reason, flags));
+ } else
#endif /* WL_WIRELESS_EXT */
- ANDROID_TRACE(("%s: %s event=%d, status=%d, reason=%d sent up\n", __FUNCTION__,
- cur_if->ifname, event_type, status, reason));
- } else {
- ANDROID_TRACE(("%s: %s event=%d, status=%d, reason=%d\n", __FUNCTION__,
- cur_if->ifname, event_type, status, reason));
+ {
+ ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d\n",
+ __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status,
+ reason, flags));
}
return 0;
}
-void
-wl_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel)
+u32
+wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- struct wl_if_info *cur_if = NULL;
+ struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
int i;
for (i=0; i<MAX_IF_NUM; i++) {
- if (apsta_params->if_info[i].dev == dev) {
- cur_if = &apsta_params->if_info[i];
- cur_if->channel = channel;
- wl_ext_iapsta_change_other_iface_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->dev && tmp_if->dev == dev) {
+ cur_if = tmp_if;
+ break;
}
}
+ if (cur_if) {
+ wl_ext_isam_status(cur_if->dev);
+ cur_if->channel = channel;
+ channel = wl_ext_move_cur_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+ if (channel)
+ wl_ext_move_other_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+ }
+
+ return channel;
}
int
-wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx)
+wl_ext_iapsta_attach_name(struct net_device *net, int ifidx)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
+ struct dhd_pub *dhd;
+ struct wl_if_info *cur_if = NULL;
- ANDROID_TRACE(("%s: bssidx=%d, %s\n", __FUNCTION__, bssidx, net->name));
- if (bssidx == 1 && apsta_params->if_info[IF_VIF].ifstate == IF_STATE_INIT) {
- strcpy(apsta_params->if_info[IF_VIF].ifname, net->name);
- } else if (bssidx == 2 && apsta_params->if_info[IF_VIF2].ifstate == IF_STATE_INIT) {
- strcpy(apsta_params->if_info[IF_VIF2].ifname, net->name);
+ dhd = dhd_get_pub(net);
+
+ ANDROID_TRACE(("%s: ifidx=%d, %s\n", __FUNCTION__, ifidx, net->name));
+ if (ifidx < MAX_IF_NUM) {
+ cur_if = &apsta_params->if_info[ifidx];
+ }
+ if (ifidx == 0) {
+ if (dhd->conf->fw_type == FW_TYPE_MESH) {
+ apsta_params->rsdb = TRUE;
+ apsta_params->csa = CSA_FW_BIT | CSA_DRV_BIT;
+ }
+ strcpy(cur_if->ifname, net->name);
+ } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) {
+ strcpy(cur_if->ifname, net->name);
+ apsta_params->netif_change = TRUE;
+ wake_up_interruptible(&apsta_params->netif_change_event);
}
return 0;
}
int
-wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx)
+wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
+ struct dhd_pub *dhd;
+ struct wl_if_info *cur_if = NULL, *primary_if;
- printf("%s: bssidx=%d\n", __FUNCTION__, bssidx);
- if (bssidx == 0) {
+ dhd = dhd_get_pub(net);
+
+ printf("%s: ifidx=%d, bssidx=%d\n", __FUNCTION__, ifidx, bssidx);
+ if (ifidx < MAX_IF_NUM) {
+ cur_if = &apsta_params->if_info[ifidx];
+ }
+ if (ifidx == 0) {
memset(apsta_params, 0, sizeof(struct wl_apsta_params));
apsta_params->vsdb = FALSE;
- apsta_params->if_info[IF_PIF].dev = net;
- apsta_params->if_info[IF_PIF].bssidx = bssidx;
- strcpy(apsta_params->if_info[IF_PIF].ifname, net->name);
+ cur_if->dev = net;
+ cur_if->ifidx = ifidx;
+ cur_if->bssidx = bssidx;
+ strcpy(cur_if->ifname, net->name);
init_waitqueue_head(&apsta_params->netif_change_event);
- } else if (bssidx == 1 && apsta_params->if_info[IF_VIF].ifstate == IF_STATE_INIT) {
- apsta_params->if_info[IF_VIF].dev = net;
- apsta_params->if_info[IF_VIF].bssidx = bssidx;
- if (strlen(apsta_params->if_info[IF_VIF].ifname)) {
+ } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) {
+ primary_if = &apsta_params->if_info[IF_PIF];
+ cur_if->dev = net;
+ cur_if->ifidx = ifidx;
+ cur_if->bssidx = bssidx;
+ if (strlen(cur_if->ifname)) {
memset(net->name, 0, sizeof(IFNAMSIZ));
- strcpy(net->name, apsta_params->if_info[IF_VIF].ifname);
+ strcpy(net->name, cur_if->ifname);
net->name[IFNAMSIZ-1] = '\0';
}
- if (apsta_params->if_info[IF_PIF].dev) {
- memcpy(net->dev_addr, apsta_params->if_info[IF_PIF].dev->dev_addr, ETHER_ADDR_LEN);
+ if (apsta_params->apstamode != ISTAAPAP_MODE) {
+ memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN);
net->dev_addr[0] |= 0x02;
+ if (ifidx >= 2) {
+ net->dev_addr[4] ^= 0x80;
+ net->dev_addr[4] += ifidx;
+ net->dev_addr[5] += (ifidx-1);
+ }
}
- apsta_params->netif_change = TRUE;
- wake_up_interruptible(&apsta_params->netif_change_event);
- } else if (bssidx == 2 && apsta_params->if_info[IF_VIF2].ifstate == IF_STATE_INIT) {
- apsta_params->if_info[IF_VIF2].dev = net;
- apsta_params->if_info[IF_VIF2].bssidx = bssidx;
- if (strlen(apsta_params->if_info[IF_VIF2].ifname)) {
- memset(net->name, 0, sizeof(IFNAMSIZ));
- strcpy(net->name, apsta_params->if_info[IF_VIF2].ifname);
- net->name[IFNAMSIZ-1] = '\0';
- }
- if (apsta_params->if_info[IF_PIF].dev) {
- memcpy(net->dev_addr, apsta_params->if_info[IF_PIF].dev->dev_addr, ETHER_ADDR_LEN);
- net->dev_addr[0] |= 0x02;
- net->dev_addr[4] ^= 0x80;
- net->dev_addr[4] += bssidx;
- net->dev_addr[5] += bssidx;
+ if (cur_if->ifmode == ISTA_MODE) {
+ wl_ext_iovar_setint(net, "roam_off", dhd->conf->roam_off);
+ wl_ext_iovar_setint(net, "bcn_timeout", dhd->conf->bcn_timeout);
+ } else if (cur_if->ifmode == IMESH_MODE) {
+ int pm = 0;
+ wl_ext_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), 1);
}
- apsta_params->netif_change = TRUE;
- wake_up_interruptible(&apsta_params->netif_change_event);
}
return 0;
int
wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len)
{
-
int ret = 0;
int bytes_written = 0;
uint32 ip_addr;
return ret;
}
-int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len,
- int *bytes_written)
+int wl_android_ext_priv_cmd(struct net_device *net, char *command,
+ int total_len, int *bytes_written)
{
int ret = 0;
else if (strnicmp(command, CMD_ISAM_DISABLE, strlen(CMD_ISAM_DISABLE)) == 0) {
*bytes_written = wl_ext_iapsta_disable(net, command, total_len);
}
+ else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) {
+ *bytes_written = wl_ext_isam_status(net);
+ }
#endif
#ifdef IDHCP
else if (strnicmp(command, CMD_DHCPC_ENABLE, strlen(CMD_DHCPC_ENABLE)) == 0) {
else if (strnicmp(command, CMD_DHCPC_DUMP, strlen(CMD_DHCPC_DUMP)) == 0) {
*bytes_written = wl_ext_dhcpc_dump(net, command, total_len);
}
+#endif
+#ifdef WL_CFG80211
+ else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
+ *bytes_written = wl_cfg80211_autochannel(net, command, total_len);
+ }
+#endif
+#ifdef WL_ESCAN
+ else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
+ *bytes_written = wl_escan_autochannel(net, command, total_len);
+ }
#endif
else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) {
*bytes_written = wl_ext_iovar(net, command, total_len);
return ret;
}
+#if defined(WL_CFG80211) || defined(WL_ESCAN)
+int
+wl_ext_get_distance(struct net_device *net, u32 band)
+{
+ u32 bw = WL_CHANSPEC_BW_20;
+ s32 bw_cap = 0, distance = 0;
+ struct {
+ u32 band;
+ u32 bw_cap;
+ } param = {0, 0};
+ char buf[WLC_IOCTL_SMLEN]="\0";
+ s32 err = BCME_OK;
+
+ param.band = band;
+ err = wldev_iovar_getbuf(net, "bw_cap", ¶m, sizeof(param), buf,
+ sizeof(buf), NULL);
+ if (err) {
+ if (err != BCME_UNSUPPORTED) {
+ ANDROID_ERROR(("bw_cap failed, %d\n", err));
+ return err;
+ } else {
+ err = wl_ext_iovar_getint(net, "mimo_bw_cap", &bw_cap);
+ if (err) {
+ ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err));
+ }
+ if (bw_cap != WLC_N_BW_20ALL)
+ bw = WL_CHANSPEC_BW_40;
+ }
+ } else {
+ if (WL_BW_CAP_80MHZ(buf[0]))
+ bw = WL_CHANSPEC_BW_80;
+ else if (WL_BW_CAP_40MHZ(buf[0]))
+ bw = WL_CHANSPEC_BW_40;
+ else
+ bw = WL_CHANSPEC_BW_20;
+ }
+
+ if (bw == WL_CHANSPEC_BW_20)
+ distance = 2;
+ else if (bw == WL_CHANSPEC_BW_40)
+ distance = 4;
+ else if (bw == WL_CHANSPEC_BW_80)
+ distance = 8;
+ else
+ distance = 16;
+ ANDROID_INFO(("%s: bw=0x%x, distance=%d\n", __FUNCTION__, bw, distance));
+
+ return distance;
+}
+
+int
+wl_ext_get_best_channel(struct net_device *net,
+#if defined(BSSCACHE)
+ wl_bss_cache_ctrl_t *bss_cache_ctrl,
+#else
+ struct wl_scan_results *bss_list,
+#endif
+ int ioctl_ver, int *best_2g_ch, int *best_5g_ch
+)
+{
+ struct wl_bss_info *bi = NULL; /* must be initialized */
+ s32 i, j;
+#if defined(BSSCACHE)
+ wl_bss_cache_t *node;
+#endif
+ int b_band[CH_MAX_2G_CHANNEL]={0}, a_band1[4]={0}, a_band4[5]={0};
+ s32 cen_ch, distance, distance_2g, distance_5g, ch, min_ap=999;
+ u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+ wl_uint32_list_t *list;
+ int ret;
+ chanspec_t chanspec;
+
+ memset(b_band, -1, sizeof(b_band));
+ memset(a_band1, -1, sizeof(a_band1));
+ memset(a_band4, -1, sizeof(a_band4));
+
+ memset(valid_chan_list, 0, sizeof(valid_chan_list));
+ list = (wl_uint32_list_t *)(void *) valid_chan_list;
+ list->count = htod32(WL_NUMCHANNELS);
+ ret = wldev_ioctl(net, WLC_GET_VALID_CHANNELS, valid_chan_list,
+ sizeof(valid_chan_list), 0);
+ if (ret<0) {
+ ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret));
+ return 0;
+ } else {
+ for (i = 0; i < dtoh32(list->count); i++) {
+ ch = dtoh32(list->element[i]);
+ if (ch < CH_MAX_2G_CHANNEL)
+ b_band[ch-1] = 0;
+ else if (ch <= 48)
+ a_band1[(ch-36)/4] = 0;
+ else if (ch >= 149 && ch <= 161)
+ a_band4[(ch-149)/4] = 0;
+ }
+ }
+
+ distance_2g = wl_ext_get_distance(net, WLC_BAND_2G);
+ distance_5g = wl_ext_get_distance(net, WLC_BAND_5G);
+
+#if defined(BSSCACHE)
+ node = bss_cache_ctrl->m_cache_head;
+ for (i=0; node && i<256; i++)
+#else
+ for (i=0; i < bss_list->count; i++)
+#endif
+ {
+#if defined(BSSCACHE)
+ bi = node->results.bss_info;
+#else
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : bss_list->bss_info;
+#endif
+ chanspec = wl_ext_chspec_driver_to_host(ioctl_ver, bi->chanspec);
+ cen_ch = CHSPEC_CHANNEL(bi->chanspec);
+ distance = 0;
+ if (CHSPEC_IS20(chanspec))
+ distance += 2;
+ else if (CHSPEC_IS40(chanspec))
+ distance += 4;
+ else if (CHSPEC_IS80(chanspec))
+ distance += 8;
+ else
+ distance += 16;
+
+ if (CHSPEC_IS2G(chanspec)) {
+ distance += distance_2g;
+ for (j=0; j<ARRAYSIZE(b_band); j++) {
+ if (b_band[j] >= 0 && abs(cen_ch-(1+j)) <= distance)
+ b_band[j] += 1;
+ }
+ } else {
+ distance += distance_5g;
+ if (cen_ch <= 48) {
+ for (j=0; j<ARRAYSIZE(a_band1); j++) {
+ if (a_band1[j] >= 0 && abs(cen_ch-(36+j*4)) <= distance)
+ a_band1[j] += 1;
+ }
+ } else if (cen_ch >= 149) {
+ for (j=0; j<ARRAYSIZE(a_band4); j++) {
+ if (a_band4[j] >= 0 && abs(cen_ch-(149+j*4)) <= distance)
+ a_band4[j] += 1;
+ }
+ }
+ }
+#if defined(BSSCACHE)
+ node = node->next;
+#endif
+ }
+
+ *best_2g_ch = 0;
+ min_ap = 999;
+ for (i=0; i<CH_MAX_2G_CHANNEL; i++) {
+ if(b_band[i] < min_ap && b_band[i] >= 0) {
+ min_ap = b_band[i];
+ *best_2g_ch = i+1;
+ }
+ }
+ *best_5g_ch = 0;
+ min_ap = 999;
+ for (i=0; i<ARRAYSIZE(a_band1); i++) {
+ if(a_band1[i] < min_ap && a_band1[i] >= 0) {
+ min_ap = a_band1[i];
+ *best_5g_ch = i*4 + 36;
+ }
+ }
+ for (i=0; i<ARRAYSIZE(a_band4); i++) {
+ if(a_band4[i] < min_ap && a_band4[i] >= 0) {
+ min_ap = a_band4[i];
+ *best_5g_ch = i*4 + 149;
+ }
+ }
+
+ if (android_msg_level&ANDROID_INFO_LEVEL) {
+ printf("%s: b_band: ", __FUNCTION__);
+ for (j=0; j<ARRAYSIZE(b_band); j++)
+ printf("%d, ", b_band[j]);
+ printf("\n");
+ printf("%s: a_band1: ", __FUNCTION__);
+ for (j=0; j<ARRAYSIZE(a_band1); j++)
+ printf("%d, ", a_band1[j]);
+ printf("\n");
+ printf("%s: a_band4: ", __FUNCTION__);
+ for (j=0; j<ARRAYSIZE(a_band4); j++)
+ printf("%d, ", a_band4[j]);
+ printf("\n");
+ printf("%s: best_2g_ch=%d, best_5g_ch=%d\n", __FUNCTION__,
+ *best_2g_ch, *best_5g_ch);
+ }
+
+ return 0;
+}
+#endif
+
#if defined(RSSIAVG)
void
wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
}
void
-wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, u8 *bssid)
+wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+ u8 *bssid)
{
wl_rssi_cache_t *node, *prev, **rssi_head;
int i = -1, tmp = 0;
}
int
-wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg)
+wl_update_connected_rssi_cache(struct net_device *net,
+ wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg)
{
wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
int j, k=0;
int rssi, error=0;
struct ether_addr bssid;
struct timeval now, timeout;
+ scb_val_t scbval;
if (!g_wifi_on)
return 0;
if (error) {
ANDROID_ERROR(("Could not get bssid (%d)\n", error));
}
- error = wldev_get_rssi(net, &rssi);
+ error = wldev_get_rssi(net, &scbval);
if (error) {
ANDROID_ERROR(("Could not get rssi (%d)\n", error));
return error;
}
+ rssi = scbval.val;
do_gettimeofday(&now);
timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT;
}
void
-wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list)
+wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+ wl_scan_results_t *ss_list)
{
wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
wl_bss_info_t *bi = NULL;
}
void
-wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, u8 *bssid)
+wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
+ u8 *bssid)
{
wl_bss_cache_t *node, *prev, **bss_head;
int i = -1, tmp = 0;
rssi = dtoh16(node->results.bss_info->RSSI);
#endif
ANDROID_TRACE(("%s: dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
- __FUNCTION__, k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID));
+ __FUNCTION__, k, &node->results.bss_info->BSSID, rssi,
+ node->results.bss_info->SSID));
k++;
node = node->next;
}
#endif
for (;node;) {
#if defined(RSSIAVG)
- rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
+ rssi_node = wl_get_avg_rssi(rssi_cache_ctrl,
+ &node->results.bss_info->BSSID);
#else
rssi_node = dtoh16(node->results.bss_info->RSSI);
#endif
#else
#define NUM_DIFF_CHANNELS 2
#endif
-static struct ieee80211_iface_combination
+static const struct ieee80211_iface_combination
common_iface_combinations[] = {
{
.num_different_channels = NUM_DIFF_CHANNELS,
* requests.
*/
if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
- WL_ERR(("Fw doesnot support multiple Go"));
+ WL_ERR(("Fw does not support multiple Go\n"));
err = -ENOTSUPP;
goto fail;
}
cfg_type = wl_cfgp2p_get_conn_idx(cfg);
if (cfg_type == BCME_ERROR) {
wl_clr_p2p_status(cfg, IF_ADDING);
- WL_ERR(("Failed to get connection idx for p2p interface"));
+ WL_ERR(("Failed to get connection idx for p2p interface\n"));
err = -ENOTSUPP;
goto fail;
}
*/
if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS);
- WL_ERR(("Fw doesnot support multiple GO "));
+ WL_ERR(("Fw does not support multiple GO\n"));
err = BCME_ERROR;
goto error;
}
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);
+ if (err)
+ return err;
mutex_lock(&cfg->usr_sync);
err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
chipnum = revinfo.chipnum;
if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) ||
- (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID)) {
+ (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID) ||
+ (chipnum == BCM43362_CHIP_ID)) {
/* WAR required */
return true;
}
wl_bss_iovar_war(struct bcm_cfg80211 *cfg,
struct net_device *ndev, s32 *val)
{
- if (wl_customer6_legacy_chip_check(cfg, ndev)) {
+ u32 chipnum;
+ wlc_rev_info_t revinfo;
+ int ret;
+ bool need_war = false;
+
+ /* Get the device rev info */
+ memset(&revinfo, 0, sizeof(revinfo));
+ ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+ if (ret < 0) {
+ WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
+ } else {
+ WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
+ dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
+ chipnum = revinfo.chipnum;
+ if ((chipnum == BCM4359_CHIP_ID) || (chipnum == BCM43596_CHIP_ID)) {
+ /* WAR required */
+ need_war = true;
+ }
+ }
+
+ if (wl_customer6_legacy_chip_check(cfg, ndev) || need_war) {
/* Few firmware branches have issues in bss iovar handling and
* that can't be changed since they are in production.
*/
addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
event->bssidx, &cfg->ioctl_buf_sync);
if (unlikely(ret)) {
- WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
- goto fail;
+ WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
+ goto fail;
}
memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
WL_ERR(("Applying updated mac address to firmware\n"));
DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
#endif /* BCMDONGLEHOST && CUSTOMER_HW2 */
#ifdef WL_EXT_IAPSTA
- wl_ext_iapsta_disconnect_sta(dev, cfg->channel);
+ wl_ext_iapsta_update_channel(dev, cfg->channel);
#endif
err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
WL_ERR(("error (%d)\n", err));
wl_clr_drv_status(cfg, CONNECTING, dev);
}
+ if (!err)
+ wl_cfg80211_4way_start(cfg, dev);
#ifdef WLTDLS
/* disable TDLS if number of connected interfaces is >= 1 */
{
struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
bcm_struct_cfgdev *new_cfgdev;
-#ifdef WLMESH
char ifname[IFNAMSIZ];
char iftype[IFNAMSIZ];
enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
if (strnicmp(iftype, "AP", strlen("AP")) == 0) {
iface_type = NL80211_IFTYPE_AP;
}
-#endif
new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
-#ifdef WLMESH
iface_type, NULL, ifname);
-#else
- NL80211_IFTYPE_STATION, NULL, name);
-#endif
if (!new_cfgdev) {
return BCME_ERROR;
}
s32 bssidx = 0;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
s32 mode = wl_get_mode_by_netdev(cfg, dev);
+
WL_DBG(("key index (%d)\n", key_idx));
RETURN_EIO_IF_NOT_UP(cfg);
WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
return BCME_ERROR;
}
+ wl_cfg80211_4way_exit(cfg, dev);
if (mac_addr &&
((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
#endif /* MFP */
}
-#if defined(RSSIAVG)
-static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
-static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
-#endif
-#if defined(BSSCACHE)
-static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
-#endif
-
static s32
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
}
rssi = dtoh32(scb_val.val);
#if defined(RSSIAVG)
- err = wl_update_connected_rssi_cache(dev, &g_connected_rssi_cache_ctrl, &rssi);
+ err = wl_update_connected_rssi_cache(dev, &cfg->g_connected_rssi_cache_ctrl, &rssi);
if (err) {
WL_ERR(("Could not get rssi (%d)\n", err));
goto get_station_err;
}
- wl_delete_dirty_rssi_cache(&g_connected_rssi_cache_ctrl);
- wl_reset_rssi_cache(&g_connected_rssi_cache_ctrl);
+ wl_delete_dirty_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
+ wl_reset_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
#endif
#if defined(RSSIOFFSET)
rssi = wl_update_rssi_offset(dev, rssi);
dev = ndev_to_wlc_ndev(dev, cfg);
_chan = ieee80211_frequency_to_channel(chan->center_freq);
+#ifdef WL_EXT_IAPSTA
+ _chan = wl_ext_iapsta_update_channel(dev, _chan);
+#endif
printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
__FUNCTION__, dev->ifindex, channel_type, _chan);
/* create softap */
if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
join_params_size)) != 0) {
- WL_ERR(("SoftAP/GO set ssid failed! \n"));
+ WL_ERR(("SoftAP/GO set ssid failed! %d\n", err));
goto exit;
} else {
WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
} else {
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
#endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
-// dhd_wait_pend8021x(dev);
+#ifndef BCMDBUS
+ dhd_wait_pend8021x(dev);
+#endif /* !BCMDBUS */
scb_val.val = DOT11_RC_DEAUTH_LEAVING;
err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
sizeof(scb_val_t));
#endif /* ARP_OFFLOAD_SUPPORT */
if (is_rsdb_supported == 0) {
+ if (dhd_download_fw_on_driverload && bssidx == 0) {
+ wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
+ wldev_iovar_setint(dev, "apsta", 1);
+ }
/* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
if (unlikely(err)) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
(defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
WL_DBG(("Setting interface combinations for common mode\n"));
-#ifndef BCMDBUS
- if (dhd->conf->num_different_channels >= 0)
- common_iface_combinations[0].num_different_channels = dhd->conf->num_different_channels;
-#endif /* !BCMDBUS */
wdev->wiphy->iface_combinations = common_iface_combinations;
wdev->wiphy->n_iface_combinations =
ARRAY_SIZE(common_iface_combinations);
struct wl_bss_info *bi = NULL; /* must be initialized */
s32 err = 0;
s32 i;
-#if defined(RSSIAVG)
struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+#if defined(RSSIAVG)
int rssi;
#endif
#if defined(BSSCACHE)
/* Free cache in p2p scanning*/
if (p2p_is_on(cfg) && p2p_scan(cfg)) {
#if defined(RSSIAVG)
- wl_free_rssi_cache(&g_rssi_cache_ctrl);
+ wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
#endif
#if defined(BSSCACHE)
- wl_free_bss_cache(&g_bss_cache_ctrl);
+ wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
#endif
}
/* Delete disconnected cache */
#if defined(BSSCACHE)
- wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+ wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
#if defined(RSSIAVG)
- wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+ wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
#endif
if (cfg->p2p_disconnected == 0)
memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
/* Update cache */
#if defined(RSSIAVG)
- wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
+ wl_update_rssi_cache(&cfg->g_rssi_cache_ctrl, bss_list);
if (!in_atomic())
- wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
+ wl_update_connected_rssi_cache(ndev, &cfg->g_rssi_cache_ctrl, &rssi);
#endif
#if defined(BSSCACHE)
- wl_update_bss_cache(&g_bss_cache_ctrl,
+ wl_update_bss_cache(&cfg->g_bss_cache_ctrl,
#if defined(RSSIAVG)
- &g_rssi_cache_ctrl,
+ &cfg->g_rssi_cache_ctrl,
#endif
bss_list);
#endif
/* delete dirty cache */
#if defined(RSSIAVG)
- wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
- wl_reset_rssi_cache(&g_rssi_cache_ctrl);
+ wl_delete_dirty_rssi_cache(&cfg->g_rssi_cache_ctrl);
+ wl_reset_rssi_cache(&cfg->g_rssi_cache_ctrl);
#endif
#if defined(BSSCACHE)
- wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
- wl_reset_bss_cache(&g_bss_cache_ctrl);
+ wl_delete_dirty_bss_cache(&cfg->g_bss_cache_ctrl);
+ wl_reset_bss_cache(&cfg->g_bss_cache_ctrl);
#endif
#if defined(BSSCACHE)
if (cfg->p2p_disconnected > 0) {
// terence 20130703: Fix for wrong group_capab (timing issue)
- wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+ wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
#if defined(RSSIAVG)
- wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+ wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
#endif
}
WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
- node = g_bss_cache_ctrl.m_cache_head;
+ node = cfg->g_bss_cache_ctrl.m_cache_head;
for (i=0; node && i<WL_AP_MAX; i++) {
bi = node->results.bss_info;
err = wl_inform_single_bss(cfg, bi, false);
node = node->next;
}
+ if (cfg->autochannel)
+ wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version,
+ &cfg->best_2g_ch, &cfg->best_5g_ch);
#else
WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
preempt_disable();
err = wl_inform_single_bss(cfg, bi, false);
}
preempt_enable();
+ if (cfg->autochannel)
+ wl_ext_get_best_channel(ndev, bss_list, ioctl_version,
+ &cfg->best_2g_ch, &cfg->best_5g_ch);
#endif
if (cfg->p2p_disconnected > 0) {
u32 freq;
s32 err = 0;
gfp_t aflags;
+ chanspec_t chanspec;
if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
WL_DBG(("Beacon is larger than buffer. Discarding\n"));
return -ENOMEM;
}
mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
- notif_bss_info->channel =
- wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
+ chanspec = wl_chspec_driver_to_host(bi->chanspec);
+ notif_bss_info->channel = wf_chspec_ctlchan(chanspec);
if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
}
notif_bss_info->rssi = dtoh16(bi->RSSI);
#if defined(RSSIAVG)
- notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
+ notif_bss_info->rssi = wl_get_avg_rssi(&cfg->g_rssi_cache_ctrl, &bi->BSSID);
if (notif_bss_info->rssi == RSSI_MINVAL)
notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
#endif
return -EINVAL;
}
channel = ieee80211_get_channel(wiphy, freq);
- WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
- "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
+ WL_SCAN(("BSSID %pM, channel %2d(%2d %sMHz), rssi %3d, capa 0x04%x, mgmt_type %d, "
+ "frame_len %d, SSID \"%s\"\n",
+ &bi->BSSID, notif_bss_info->channel, CHSPEC_CHANNEL(chanspec),
+ CHSPEC_IS20(chanspec)?"20":
+ CHSPEC_IS40(chanspec)?"40":
+ CHSPEC_IS80(chanspec)?"80":"160",
notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
notif_bss_info->frame_len, bi->SSID));
if (unlikely(!channel)) {
"event : %d, reason=%d from " MACDBG "\n",
ndev->name, event, ntoh32(e->reason),
MAC2STRDBG((const u8*)(&e->addr)));
+ wl_cfg80211_4way_exit(cfg, ndev);
/* 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);
/* 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);
#if defined(DHD_ENABLE_BIGDATA_LOGGING)
if (event == WLC_E_SET_SSID) {
wl_get_connect_failed_status(cfg, e);
}
DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
}
- else {
- WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
+ else {
+ printf("wl_notify_connect_status : Invalid %s mode %d event %d status %d\n",
+ ndev->name, wl_get_mode_by_netdev(cfg, ndev), ntoh32(e->event_type),
+ ntoh32(e->status));
}
return err;
}
if (completed) {
WL_INFORM(("Report connect result - connection succeeded\n"));
dhd_conf_set_wme(cfg->pub, 0);
- } else
+ } else {
WL_ERR(("Report connect result - connection failed\n"));
+ wl_cfg80211_4way_exit(cfg, ndev);
+ }
}
#ifdef CONFIG_TCPACK_FASTTX
if (wl_get_chan_isvht80(ndev, dhdp))
}
}
-static void wl_scan_timeout(unsigned long data)
+static void wl_scan_timeout(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ unsigned long data
+#endif
+)
{
wl_event_msg_t msg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct bcm_cfg80211 *cfg = from_timer(cfg, t, scan_timeout);
+#else
struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
+#endif
struct wireless_dev *wdev = NULL;
struct net_device *ndev = NULL;
struct wl_scan_results *bss_list;
}
-static void wl_roam_timeout(unsigned long data)
+static void wl_roam_timeout(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ unsigned long data
+#endif
+)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct bcm_cfg80211 *cfg = from_timer(cfg, t, roam_timeout);
+#else
struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
+#endif
dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
WL_ERR(("roam timer expired\n"));
}
return err;
}
+
static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
{
int err = 0;
wl_escan_init_sync_id(cfg);
/* Init scan_timeout timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&cfg->scan_timeout, wl_scan_timeout, 0);
+#else
init_timer(&cfg->scan_timeout);
cfg->scan_timeout.data = (unsigned long) cfg;
cfg->scan_timeout.function = wl_scan_timeout;
+#endif
return err;
}
int err = 0;
/* Init roam timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&cfg->roam_timeout, wl_roam_timeout, 0);
+#else
init_timer(&cfg->roam_timeout);
cfg->roam_timeout.data = (unsigned long) cfg;
cfg->roam_timeout.function = wl_roam_timeout;
+#endif
return err;
}
wl_cfg80211_clear_mgmt_vndr_ies(cfg);
wl_deinit_priv(cfg);
wl_cfg80211_clear_parent_dev();
- wl_free_wdev(cfg);
#if defined(RSSIAVG)
- wl_free_rssi_cache(&g_rssi_cache_ctrl);
- wl_free_rssi_cache(&g_connected_rssi_cache_ctrl);
+ wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
+ wl_free_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
#endif
#if defined(BSSCACHE)
- wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
+ wl_release_bss_cache_ctrl(&cfg->g_bss_cache_ctrl);
#endif
+ wl_free_wdev(cfg);
/* PLEASE do NOT call any function after wl_free_wdev, the driver's private
* structure "cfg", which is the private part of wiphy, has been freed in
* wl_free_wdev !!!!!!!!!!!
}
wl_flush_eq(cfg);
-
if (cfg->link_up) { //army fix wifi stop call trace issue
- CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
- wl_link_down(cfg);
- }
+ CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
+ wl_link_down(cfg);
+ }
if (cfg->p2p_supported) {
if (timer_pending(&cfg->p2p->listen_timer))
del_timer_sync(&cfg->p2p->listen_timer);
return BCME_VERSION;
}
ioctl_version = val;
+ wl_cfg80211_4way_exit(cfg, net);
WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
mutex_lock(&cfg->usr_sync);
CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
}
#if defined(RSSIAVG)
- wl_free_rssi_cache(&g_rssi_cache_ctrl);
+ wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
#endif
#if defined(BSSCACHE)
- wl_free_bss_cache(&g_bss_cache_ctrl);
+ wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
#endif
if (cfg != NULL) {
wl_link_down(cfg);
return err;
mutex_lock(&cfg->usr_sync);
#if defined(RSSIAVG)
- wl_free_rssi_cache(&g_rssi_cache_ctrl);
+ wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
#endif
#if defined(BSSCACHE)
- wl_free_bss_cache(&g_bss_cache_ctrl);
+ wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
#endif
err = __wl_cfg80211_down(cfg);
mutex_unlock(&cfg->usr_sync);
// terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
- if (ret < 0)
+ if (ret < 0) {
WL_ERR(("WLC_SET_BAND error %d\n", ret));
+ goto done;
+ }
/* Best channel selection in 5GHz band. */
ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
return err;
}
#endif /* SUPPORT_RSSI_LOGGING */
+
+s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len)
+{
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+ int ret = 0;
+ int bytes_written = -1;
+
+ sscanf(command, "%*s %d", &cfg->autochannel);
+
+ if (cfg->autochannel == 0) {
+ cfg->best_2g_ch = 0;
+ cfg->best_5g_ch = 0;
+ } else if (cfg->autochannel == 2) {
+ bytes_written = snprintf(command, total_len, "2g=%d 5g=%d",
+ cfg->best_2g_ch, cfg->best_5g_ch);
+ ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
+ ret = bytes_written;
+ }
+
+ return ret;
+}
#include <dngl_stats.h>
#include <dhd.h>
#include <wl_cfgp2p.h>
+#include <wl_android.h>
struct wl_conf;
struct wl_iface;
struct bcm_cfg80211;
char sae_password[SAE_MAX_PASSWD_LEN];
uint sae_password_len;
#endif /* WLMESH */
+#if defined(RSSIAVG)
+ wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
+ wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
+#endif
+#if defined(BSSCACHE)
+ wl_bss_cache_ctrl_t g_bss_cache_ctrl;
+#endif
int p2p_disconnected; // terence 20130703: Fix for wrong group_capab (timing issue)
struct ether_addr disconnected_bssid;
+ int autochannel;
+ int best_2g_ch;
+ int best_5g_ch;
+ uint handshaking;
};
#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
struct net_device* wl_get_ap_netdev(struct bcm_cfg80211 *cfg, char *ifname);
struct net_device* wl_get_netdev_by_name(struct bcm_cfg80211 *cfg, char *ifname);
int wl_cfg80211_get_vndr_ouilist(struct bcm_cfg80211 *cfg, uint8 *buf, int max_cnt);
+s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len);
#endif /* _wl_cfg80211_h_ */
#endif
}
-static void wl_cfg80211_bt_timerfunc(ulong data)
+static void wl_cfg80211_bt_timerfunc(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ unsigned long data
+#endif
+)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct btcoex_info *bt_local = from_timer(bt_local, t, timer);
+#else
struct btcoex_info *bt_local = (struct btcoex_info *)data;
+#endif
WL_TRACE(("Enter\n"));
bt_local->timer_on = 0;
schedule_work(&bt_local->work);
btco_inf->ts_dhcp_ok = 0;
/* Set up timer for BT */
btco_inf->timer_ms = 10;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&btco_inf->timer, wl_cfg80211_bt_timerfunc, 0);
+#else
init_timer(&btco_inf->timer);
btco_inf->timer.data = (ulong)btco_inf;
btco_inf->timer.function = wl_cfg80211_bt_timerfunc;
+#endif
btco_inf->dev = ndev;
return -ENOMEM;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ cfg->p2p->cfg = cfg;
+#endif
wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg);
wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0;
wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
* so lets do it from thread context.
*/
void
-wl_cfgp2p_listen_expired(unsigned long data)
+wl_cfgp2p_listen_expired(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ ulong data
+#endif
+)
{
wl_event_msg_t msg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct p2p_info *p2p = from_timer(p2p, t, listen_timer);
+ struct bcm_cfg80211 *cfg = p2p->cfg;
+#else
struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
+#endif
struct net_device *ndev;
CFGP2P_DBG((" Enter\n"));
};
struct p2p_info {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct bcm_cfg80211 *cfg;
+#endif
bool on; /**< p2p on/off switch */
bool scan;
int16 search_state;
printk args; \
} \
} while (0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+#define INIT_TIMER(timer, func, duration, extra_delay) \
+ do { \
+ timer_setup(timer, func, 0); \
+ timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \
+ add_timer(timer); \
+ } while (0);
+#else
#define INIT_TIMER(timer, func, duration, extra_delay) \
do { \
init_timer(timer); \
timer->data = (unsigned long) cfg; \
add_timer(timer); \
} while (0);
+#endif
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 8))
#ifdef WL_SUPPORT_BACKPORTED_KPATCHES
#define P2P_ECSA_CNT 50
extern void
-wl_cfgp2p_listen_expired(unsigned long data);
+wl_cfgp2p_listen_expired(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ ulong data
+#endif
+);
extern bool
wl_cfgp2p_is_pub_action(void *frame, u32 frame_len);
extern bool
((wl_cnt_info_t *)iovar_buf)->datalen,
WL_CNT_XTLV_CNTV_LE10_UCODE, NULL,
BCM_XTLV_OPTION_ALIGN32)) == NULL) {
- macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
+ if ((macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
((wl_cnt_info_t *)iovar_buf)->datalen,
WL_CNT_XTLV_GE40_UCODE_V1, NULL,
+ BCM_XTLV_OPTION_ALIGN32)) == NULL) {
+ macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
+ ((wl_cnt_info_t *)iovar_buf)->datalen,
+ WL_CNT_XTLV_LT40_UCODE_V1, NULL,
BCM_XTLV_OPTION_ALIGN32);
+ }
}
if (macstat_cnt == NULL) {
#define ESCAN_ERROR(x) \
do { \
if (iw_msg_level & ESCAN_ERROR_LEVEL) { \
- printf(KERN_ERR "ESCAN-ERROR) "); \
+ printf(KERN_ERR "ESCAN-ERROR) %s : ", __func__); \
printf x; \
} \
} while (0)
#define ESCAN_SCAN(x) \
do { \
if (iw_msg_level & ESCAN_SCAN_LEVEL) { \
- printf(KERN_ERR "ESCAN-SCAN) "); \
+ printf(KERN_ERR "ESCAN-SCAN) %s : ", __func__); \
printf x; \
} \
} while (0)
#define ESCAN_TRACE(x) \
do { \
if (iw_msg_level & ESCAN_TRACE_LEVEL) { \
- printf(KERN_ERR "ESCAN-TRACE) "); \
+ printf(KERN_ERR "ESCAN-TRACE) %s : ", __func__); \
printf x; \
} \
} while (0)
#endif /* ESCAN_BUF_OVERFLOW_MGMT */
struct wl_escan_info *g_escan = NULL;
-
-#if defined(RSSIAVG)
-static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
-static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
-#endif
-#if defined(BSSCACHE)
-static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
-#endif
-
/* Return a new chanspec given a legacy chanspec
* Returns INVCHANSPEC on error
*/
* Returns INVCHANSPEC on error
*/
static chanspec_t
-wl_chspec_host_to_driver(chanspec_t chanspec)
+wl_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec)
{
- if (1) {
+ if (ioctl_ver == 1) {
chanspec = wl_chspec_to_legacy(chanspec);
if (chanspec == INVCHANSPEC) {
return chanspec;
* Returns INVCHANSPEC on error
*/
static chanspec_t
-wl_ch_host_to_driver(s32 bssidx, u16 channel)
+wl_ch_host_to_driver(int ioctl_ver, s32 bssidx, u16 channel)
{
chanspec_t chanspec;
chanspec |= WL_CHANSPEC_CTL_SB_NONE;
- return wl_chspec_host_to_driver(chanspec);
+ return wl_chspec_host_to_driver(ioctl_ver, chanspec);
}
static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
}
void
-wl_escan_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data)
{
u32 event_type = ntoh32(e->event_type);
struct wl_escan_info *escan = g_escan;
}
DHD_EVENT_WAKE_LOCK(escan->pub);
- if (likely(!wl_enq_event(escan, ndev, event_type, e, data))) {
+ if (likely(!wl_enq_event(escan, dev, event_type, e, data))) {
wl_wakeup_event(escan);
} else {
DHD_EVENT_WAKE_UNLOCK(escan->pub);
/* Delete disconnected cache */
#if defined(BSSCACHE)
- wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&escan->disconnected_bssid);
+ wl_delete_disconnected_bss_cache(&escan->g_bss_cache_ctrl, (u8*)&escan->disconnected_bssid);
#if defined(RSSIAVG)
- wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&escan->disconnected_bssid);
+ wl_delete_disconnected_rssi_cache(&escan->g_rssi_cache_ctrl, (u8*)&escan->disconnected_bssid);
#endif
#endif
/* Update cache */
#if defined(RSSIAVG)
- wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
+ wl_update_rssi_cache(&escan->g_rssi_cache_ctrl, bss_list);
if (!in_atomic())
- wl_update_connected_rssi_cache(escan->dev, &g_rssi_cache_ctrl, &rssi);
+ wl_update_connected_rssi_cache(escan->dev, &escan->g_rssi_cache_ctrl, &rssi);
#endif
#if defined(BSSCACHE)
- wl_update_bss_cache(&g_bss_cache_ctrl,
+ wl_update_bss_cache(&escan->g_bss_cache_ctrl,
#if defined(RSSIAVG)
- &g_rssi_cache_ctrl,
+ &escan->g_rssi_cache_ctrl,
#endif
bss_list);
#endif
/* delete dirty cache */
#if defined(RSSIAVG)
- wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
- wl_reset_rssi_cache(&g_rssi_cache_ctrl);
+ wl_delete_dirty_rssi_cache(&escan->g_rssi_cache_ctrl);
+ wl_reset_rssi_cache(&escan->g_rssi_cache_ctrl);
#endif
#if defined(BSSCACHE)
- wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
- wl_reset_bss_cache(&g_bss_cache_ctrl);
+ wl_delete_dirty_bss_cache(&escan->g_bss_cache_ctrl);
+ wl_reset_bss_cache(&escan->g_bss_cache_ctrl);
+ if (escan->autochannel)
+ wl_ext_get_best_channel(escan->dev, &escan->g_bss_cache_ctrl,
+ escan->ioctl_ver &escan->best_2g_ch, &escan->best_5g_ch);
+#else
+ if (escan->autochannel)
+ wl_ext_get_best_channel(escan->dev, bss_list, escan->ioctl_ver,
+ &escan->best_2g_ch, &escan->best_5g_ch);
#endif
ESCAN_TRACE(("scanned AP count (%d)\n", bss_list->count));
}
static wl_scan_params_t *
-wl_escan_alloc_params(int channel, int nprobes, int *out_params_size)
+wl_escan_alloc_params(struct wl_escan_info *escan, int channel,
+ int nprobes, int *out_params_size)
{
wl_scan_params_t *params;
int params_size;
if (channel == -1)
params->channel_list[0] = htodchanspec(channel);
else
- params->channel_list[0] = wl_ch_host_to_driver(bssidx, channel);
+ params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, bssidx, channel);
/* Our scan params have 1 channel and 0 ssids */
params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
s32 err = BCME_OK;
if (!in_atomic()) {
/* Our scan params only need space for 1 channel and 0 ssids */
- params = wl_escan_alloc_params(-1, 0, ¶ms_size);
+ params = wl_escan_alloc_params(escan, -1, 0, ¶ms_size);
if (params == NULL) {
ESCAN_ERROR(("scan params allocation failed \n"));
err = -ENOMEM;
}
else if (status == WLC_E_STATUS_SUCCESS) {
escan->escan_state = ESCAN_STATE_IDLE;
-
- ESCAN_TRACE(("ESCAN COMPLETED\n"));
- escan->bss_list = wl_escan_get_buf(escan);
- ESCAN_TRACE(("SCAN COMPLETED: scanned AP count=%d\n",
- escan->bss_list->count));
- wl_escan_inform_bss(escan);
- wl_notify_escan_complete(escan, false);
-
+ ESCAN_TRACE(("ESCAN COMPLETED\n"));
+ escan->bss_list = wl_escan_get_buf(escan);
+ ESCAN_TRACE(("SCAN COMPLETED: scanned AP count=%d\n",
+ escan->bss_list->count));
+ wl_escan_inform_bss(escan);
+ wl_notify_escan_complete(escan, false);
} else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
(status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
(status == WLC_E_STATUS_NEWASSOC)) {
/* Handle all cases of scan abort */
escan->escan_state = ESCAN_STATE_IDLE;
ESCAN_TRACE(("ESCAN ABORT reason: %d\n", status));
+ escan->bss_list = wl_escan_get_buf(escan);
+ ESCAN_TRACE(("SCAN ABORT: scanned AP count=%d\n",
+ escan->bss_list->count));
wl_escan_inform_bss(escan);
wl_notify_escan_complete(escan, false);
} else if (status == WLC_E_STATUS_TIMEOUT) {
if (e->reason == 0xFFFFFFFF) {
wl_notify_escan_complete(escan, true);
}
+ escan->escan_state = ESCAN_STATE_IDLE;
} else {
ESCAN_ERROR(("unexpected Escan Event %d : abort\n", status));
escan->escan_state = ESCAN_STATE_IDLE;
params->channel_list[j] |= chanspec;
ESCAN_SCAN(("Chan : %d, Channel spec: %x \n",
channel, params->channel_list[j]));
- params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
+ params->channel_list[j] = wl_chspec_host_to_driver(escan->ioctl_ver,
+ params->channel_list[j]);
j++;
}
} else {
return err;
}
-static int wl_escan_reset(void) {
- struct wl_escan_info *escan = g_escan;
-
+static int wl_escan_reset(struct wl_escan_info *escan)
+{
if (timer_pending(&escan->scan_timeout))
del_timer_sync(&escan->scan_timeout);
escan->escan_state = ESCAN_STATE_IDLE;
return 0;
}
-static void wl_escan_timeout(unsigned long data)
+static void wl_escan_timeout(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ unsigned long data
+#endif
+)
{
wl_event_msg_t msg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct wl_escan_info *escan = from_timer(escan, t, scan_timeout);
+#else
struct wl_escan_info *escan = (struct wl_escan_info *)data;
+#endif
struct wl_scan_results *bss_list;
struct wl_bss_info *bi = NULL;
s32 i;
wl_escan_params_t *params = NULL;
scb_val_t scbval;
static int cnt = 0;
- struct wl_escan_info *escan = NULL;
+ struct wl_escan_info *escan = g_escan;
wlc_ssid_t ssid;
u32 n_channels = 0;
wl_uint32_list_t *list;
ESCAN_TRACE(("Enter \n"));
- escan = g_escan;
if (!escan) {
- ESCAN_ERROR(("device is not ready\n")); \
+ ESCAN_ERROR(("device is not ready\n"));
return -EIO;
}
mutex_lock(&escan->usr_sync);
ESCAN_TRACE(("Escan not permitted at this time (%d)\n", err));
else
ESCAN_ERROR(("Escan set error (%d)\n", err));
- wl_escan_reset();
+ wl_escan_reset(escan);
}
kfree(params);
err = -EAGAIN;
goto exit;
}
+ if (!escan->bss_list) {
+ ESCAN_ERROR(("%s: scan not ready\n", dev->name));
+ err = -EAGAIN;
+ goto exit;
+ }
#if defined(BSSCACHE)
- bss_list = &g_bss_cache_ctrl.m_cache_head->results;
- node = g_bss_cache_ctrl.m_cache_head;
+ bss_list = &escan->g_bss_cache_ctrl.m_cache_head->results;
+ node = escan->g_bss_cache_ctrl.m_cache_head;
for (i=0; node && i<IW_MAX_AP; i++)
#else
bss_list = escan->bss_list;
}
#if defined(RSSIAVG)
- rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
+ rssi = wl_get_avg_rssi(&escan->g_rssi_cache_ctrl, &bi->BSSID);
if (rssi == RSSI_MINVAL)
rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
#else
rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
#endif
channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
- ESCAN_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n",
- __FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
+ ESCAN_SCAN(("BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n",
+ MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
/* First entry must be the BSSID */
iwe.cmd = SIOCGIWAP;
return err;
}
+s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len)
+{
+ struct wl_escan_info *escan = g_escan;
+ int ret = 0;
+ int bytes_written = -1;
+
+ sscanf(command, "%*s %d", &escan->autochannel);
+
+ if (escan->autochannel == 0) {
+ escan->best_2g_ch = 0;
+ escan->best_5g_ch = 0;
+ } else if (escan->autochannel == 2) {
+ bytes_written = snprintf(command, total_len, "2g=%d 5g=%d",
+ escan->best_2g_ch, escan->best_5g_ch);
+ ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
+ ret = bytes_written;
+ }
+
+ return ret;
+}
+
static s32 wl_create_event_handler(struct wl_escan_info *escan)
{
int ret = 0;
PROC_STOP(&escan->event_tsk);
}
-static void wl_escan_deinit(void)
+static void wl_escan_deinit(struct wl_escan_info *escan)
{
- struct wl_escan_info *escan = g_escan;
-
printf("%s: Enter\n", __FUNCTION__);
if (!escan) {
- ESCAN_ERROR(("device is not ready\n")); \
+ ESCAN_ERROR(("device is not ready\n"));
return;
}
wl_destroy_event_handler(escan);
wl_flush_eq(escan);
del_timer_sync(&escan->scan_timeout);
+ escan->escan_state = ESCAN_STATE_IDLE;
#if defined(RSSIAVG)
- wl_free_rssi_cache(&g_rssi_cache_ctrl);
+ wl_free_rssi_cache(&escan->g_rssi_cache_ctrl);
#endif
#if defined(BSSCACHE)
- wl_free_bss_cache(&g_bss_cache_ctrl);
+ wl_free_bss_cache(&escan->g_bss_cache_ctrl);
#endif
}
-static s32 wl_escan_init(void)
+static s32 wl_escan_init(struct wl_escan_info *escan)
{
- struct wl_escan_info *escan = g_escan;
int err = 0;
printf("%s: Enter\n", __FUNCTION__);
if (!escan) {
- ESCAN_ERROR(("device is not ready\n")); \
+ ESCAN_ERROR(("device is not ready\n"));
return -EIO;
}
/* Init scan_timeout timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&escan->scan_timeout, wl_escan_timeout, 0);
+#else
init_timer(&escan->scan_timeout);
escan->scan_timeout.data = (unsigned long) escan;
escan->scan_timeout.function = wl_escan_timeout;
+#endif
if (wl_create_event_handler(escan)) {
err = -ENOMEM;
return 0;
err:
- wl_escan_deinit();
+ wl_escan_deinit(escan);
return err;
}
printf("%s: Enter\n", __FUNCTION__);
if (!escan) {
- ESCAN_ERROR(("device is not ready\n")); \
+ ESCAN_ERROR(("device is not ready\n"));
return;
}
- wl_escan_deinit();
+ wl_escan_deinit(escan);
if (escan->escan_ioctl_buf) {
kfree(escan->escan_ioctl_buf);
escan = (wl_escan_info_t *)DHD_OS_PREALLOC(dhdp, DHD_PREALLOC_WL_ESCAN_INFO, sizeof(struct wl_escan_info));
if (!escan)
return -ENOMEM;
+ g_escan = escan;
memset(escan, 0, sizeof(struct wl_escan_info));
/* we only care about main interface so save a global here */
- g_escan = escan;
escan->dev = dev;
escan->pub = dhdp;
escan->escan_state = ESCAN_STATE_IDLE;
goto err ;
}
wl_init_eq(escan);
-#ifdef WL_ESCAN
- wl_escan_init();
-#endif
+ wl_escan_init(escan);
return 0;
err:
tsk_ctl_t event_tsk; /* task of main event handler thread */\r
ESCAN_EVENT_HANDLER evt_handler[WLC_E_LAST];\r
struct mutex usr_sync; /* maily for up/down synchronization */\r
+ int autochannel;\r
+ int best_2g_ch;\r
+ int best_5g_ch;\r
+#if defined(RSSIAVG)\r
+ wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;\r
+ wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;\r
+#endif\r
+#if defined(BSSCACHE)\r
+ wl_bss_cache_ctrl_t g_bss_cache_ctrl;\r
+#endif\r
} wl_escan_info_t;\r
\r
-void wl_escan_event(struct net_device *ndev, const wl_event_msg_t * e, void *data);\r
+void wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data);\r
\r
int wl_escan_set_scan(\r
struct net_device *dev,\r
);\r
int wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info,\r
struct iw_point *dwrq, char *extra);\r
+s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len);\r
int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp);\r
void wl_escan_detach(dhd_pub_t *dhdp);\r
\r
char *extra
)
{
- channel_info_t ci;
int error;
+ u32 chanspec = 0;
+ int ctl_chan;
WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
- if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+ if ((error = dev_wlc_intvar_get(dev, "chanspec", &chanspec)))
return error;
+ ctl_chan = wf_chspec_ctlchan(chanspec);
/* Return radio channel in channel form */
- fwrq->m = dtoh32(ci.hw_channel);
+ fwrq->m = ctl_chan;
fwrq->e = dtoh32(0);
return 0;
}
dwrq->length = sizeof(struct iw_range);
memset(range, 0, sizeof(*range));
- memset(channels, 0, sizeof(channels));
+
/* We don't use nwids */
range->min_nwid = range->max_nwid = 0;
#endif /* WIRELESS_EXT > 11 */
phy_noise = 0;
- if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) {
+ WL_ERROR(("%s: WLC_GET_PHY_NOISE error=%d\n", __FUNCTION__, res));
goto done;
+ }
phy_noise = dtoh32(phy_noise);
WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise));
- scb_val.val = 0;
- if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
+ memset(&scb_val, 0, sizeof(scb_val));
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) {
+ WL_ERROR(("%s: WLC_GET_RSSI error=%d\n", __FUNCTION__, res));
goto done;
+ }
rssi = dtoh32(scb_val.val);
rssi = MIN(rssi, RSSI_MAXVAL);
#ifndef WL_ESCAN
static void
-wl_iw_timerfunc(ulong data)
+wl_iw_timerfunc(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ struct timer_list *t
+#else
+ unsigned long data
+#endif
+)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ iscan_info_t *iscan = from_timer(iscan, t, timer);
+#else
iscan_info_t *iscan = (iscan_info_t *)data;
+#endif
iscan->timer_on = 0;
if (iscan->iscan_state != ISCAN_STATE_IDLE) {
WL_TRACE(("timer trigger\n"));
/* Set up the timer */
iscan->timer_ms = 2000;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ timer_setup(&iscan->timer, wl_iw_timerfunc, 0);
+#else
init_timer(&iscan->timer);
iscan->timer.data = (ulong)iscan;
iscan->timer.function = wl_iw_timerfunc;
+#endif
sema_init(&iscan->sysioc_sem, 0);
init_completion(&iscan->sysioc_exited);
#include <wldev_common.h>
#include <bcmutils.h>
+#ifdef WL_CFG80211
#include <wl_cfg80211.h>
+#endif
#include <dhd_config.h>
#define htod32(i) (i)
wl_country_t cur_cspec = {{0}, 0, {0}}; /* current ccode */
scb_val_t scbval;
char smbuf[WLC_IOCTL_SMLEN];
+#ifdef WL_CFG80211
struct wireless_dev *wdev = ndev_to_wdev(dev);
struct wiphy *wiphy = wdev->wiphy;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+#endif
if (!country_code)
return error;
cspec.rev = revinfo;
memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
- error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec, 0);
+ error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec);
if (error)
dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);
dhd_force_country_change(dev) ||
(strncmp(cspec.ccode, cur_cspec.ccode, WLC_CNTRY_BUF_SZ) != 0)) {
- if ((user_enforced) && (wl_get_drv_status(cfg, CONNECTED, dev))) {
+ if ((user_enforced)
+#ifdef WL_CFG80211
+ && (wl_get_drv_status(cfg, CONNECTED, dev))
+#endif
+ ) {
bzero(&scbval, sizeof(scb_val_t));
error = wldev_ioctl_set(dev, WLC_DISASSOC,
&scbval, sizeof(scb_val_t));