update rkwifi bcmdhd to version 1.201.34.1

Conflicts:
	drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile
This commit is contained in:
hwg 2015-02-12 15:21:52 +08:00
parent 43faede2e2
commit d41ea47068
150 changed files with 54566 additions and 21730 deletions

View File

@ -1,9 +1,8 @@
config BCMDHD
tristate "Broadcom 4329/30 wireless cards support"
depends on MMC
tristate "Broadcom FullMAC wireless cards support"
---help---
This module adds support for wireless adapters based on
Broadcom 4329/30 chipset.
Broadcom FullMAC chipset.
config BCMDHD_FW_PATH
depends on BCMDHD
@ -35,17 +34,20 @@ config BCMDHD_WEXT
Enables WEXT support
choice
depends on BCMDHD
prompt "Interrupt type"
depends on BCMDHD
prompt "Interrupt type"
---help---
Interrupt type
config BCMDHD_OOB
depends on BCMDHD
bool "Out-of-Band Interrupt"
default y
---help---
Interrupt from WL_HOST_WAKE.
Interrupt from WL_HOST_WAKE.
config BCMDHD_SDIO_IRQ
depends on BCMDHD
depends on BCMDHD
bool "In-Band Interrupt"
---help---
Interrupt from SDIO DAT[1]
Interrupt from SDIO DAT[1]
endchoice

View File

@ -1,64 +1,70 @@
# bcmdhd
# 1. WL_ENABLE_P2P_IF must be removed if kernel version is 3.8 later, otherwise please remove it.
# 2. WL_IFACE_COMB_NUM_CHANNELS must be added if Android version is 4.4 with Kernel version 3.0~3.4,
# 1. WL_IFACE_COMB_NUM_CHANNELS must be added if Android version is 4.4 with Kernel version 3.0~3.4,
# otherwise please remove it.
MODULE_NAME = bcmdhd
#CONFIG_RKWIFI = m
CONFIG_CFG80211 = y
CONFIG_BCMDHD_OOB = y
#CONFIG_BCMDHD_POWER_OFF_IN_SUSPEND = y
DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \
-DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DWLBTAMP -DBCMFILEIMAGE \
-DDHDTHREAD -DDHD_DEBUG -DSDTEST -DBDC -DTOE \
-DDHD_BCMEVENTS -DSHOW_EVENTS -DBCMDBG \
-DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DBCMPLATFORM_BUS \
DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \
-DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \
-DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DBCMDBG \
-DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \
-DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DGET_CUSTOM_MAC_ENABLE \
-DEMBEDDED_PLATFORM -DPNO_SUPPORT -DENABLE_INSMOD_NO_FW_LOAD \
-DKEEP_ALIVE -DPKT_FILTER_SUPPORT \
-DEMBEDDED_PLATFORM -DENABLE_INSMOD_NO_FW_LOAD -DPNO_SUPPORT \
-DDHD_USE_IDLECOUNT -DSET_RANDOM_MAC_SOFTAP -DVSDB \
-DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST -DSDIO_CRC_ERROR_FIX \
-DESCAN_RESULT_PATCH -DHT40_GO -DPASS_ARP_PACKET -DSUPPORT_PM2_ONLY \
-DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DAMPDU_HOSTREORDER \
-DCUSTOM_SDIO_F2_BLKSIZE=128 -DWL_SDO -DWLTDLS \
-DWL_SUPPORT_BACKPORTED_KPATCHES \
-Idrivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd \
-Idrivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include
-DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST \
-DESCAN_RESULT_PATCH -DSUPPORT_PM2_ONLY -DWLTDLS \
-DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD \
-DMIRACAST_AMPDU_SIZE=8 \
-DSDTEST -DBDC -DDHD_BCMEVENTS -DPROP_TXSTATUS -DPROP_TXSTATUS_VSDB \
-DWL_SUPPORT_BACKPORTED_KPATCHES -DDHDTCPACK_SUPPRESS \
-Idrivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd \
-Idrivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include
DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \
dhd_linux_sched.o bcmwifi_channels.o dhd_sdio.o bcmevent.o dhd_bta.o hndpmu.o \
bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o dhd_wlfc.o dhd_ip.o linux_osl.o \
bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o \
dhd_pno.o dhd_config.o dhd_gpio.o
DHDCFLAGS += \
-DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DSDIO_CRC_ERROR_FIX \
-DCUSTOM_SDIO_F2_BLKSIZE=128 -DUSE_SDIOFIFO_IOVAR
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 \
hnd_pktq.o hnd_pktpool.o dhd_config.o
DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \
dhd_sdio.o dhd_cdc.o dhd_wlfc.o
$(MODULE_NAME)-y += $(DHDOFILES)
DHDCFLAGS += -DCUSTOMER_HW
#DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DCONFIG_DHD_USE_STATIC_BUF -DENHANCED_STATIC_BUF
DHDOFILES += dhd_gpio.o
DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT
#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI
ifeq ($(CONFIG_BCMDHD_OOB),y)
DHDCFLAGS += -DOOB_INTR_ONLY -DHW_OOB -DCUSTOMER_OOB
ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y)
DHDCFLAGS += -DDISABLE_WOWLAN
endif
else
DHDCFLAGS += -DSDIO_ISR_THREAD
endif
ifeq ($(CONFIG_BCMDHD_POWER_OFF_IN_SUSPEND),y)
DHDCFLAGS += -DPOWER_OFF_IN_SUSPEND
endif
#ifeq ($(CONFIG_BCMDHD_AG),y)
DHDCFLAGS += -DBAND_AG
#endif
ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y)
DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT
endif
ifneq ($(CONFIG_WIRELESS_EXT),)
$(MODULE_NAME)-y += wl_iw.o
bcmdhd-objs += wl_iw.o
DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW
endif
ifeq ($(CONFIG_CFG80211),y)
$(MODULE_NAME)-y += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o dhd_cfg80211.o
DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT
ifneq ($(CONFIG_CFG80211),)
bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o dhd_cfg80211.o wl_cfg_btcoex.o
#DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF
#DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT
DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65
DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15
DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000

View File

@ -4,7 +4,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: aiutils.c 385510 2013-02-15 21:02:07Z $
* $Id: aiutils.c 467150 2014-04-02 17:30:43Z $
*/
#include <bcm_cfg.h>
#include <typedefs.h>
@ -21,19 +21,19 @@
#define BCM47162_DMP() (0)
#define BCM5357_DMP() (0)
#define BCM4707_DMP() (0)
#define PMU_DMP() (0)
#define remap_coreid(sih, coreid) (coreid)
#define remap_corerev(sih, corerev) (corerev)
/* EROM parsing */
static uint32
get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match)
{
uint32 ent = 0;
uint32 ent;
uint inv = 0, nom = 0;
uint retry = 20;
while (retry--) {
while (TRUE) {
ent = R_REG(si_osh(sih), *eromptr);
(*eromptr)++;
@ -53,8 +53,6 @@ get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match)
nom++;
}
if (!retry)
SI_ERROR(("%s: WiFi read register fail, retry = %d.\n", __FUNCTION__, retry));
SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent));
if (inv + nom) {
@ -73,7 +71,7 @@ get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, u
if (((asd & ER_TAG1) != ER_ADD) ||
(((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
((asd & AD_ST_MASK) != st)) {
/* This is not what we want, "push" it back */
(*eromptr)--;
return 0;
}
@ -104,11 +102,12 @@ ai_hwfixup(si_info_t *sii)
}
/* parse the enumeration rom to identify all cores */
void
ai_scan(si_t *sih, void *regs, uint devid)
{
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
chipcregs_t *cc = (chipcregs_t *)regs;
uint32 erombase, *eromptr, *eromlim;
@ -120,18 +119,20 @@ ai_scan(si_t *sih, void *regs, uint devid)
break;
case PCI_BUS:
/* Set wrappers address */
sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE);
/* Now point the window at the erom */
OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase);
eromptr = regs;
break;
#ifdef BCMSDIO
case SPI_BUS:
case SDIO_BUS:
eromptr = (uint32 *)(uintptr)erombase;
break;
#endif /* BCMSDIO */
case PCMCIA_BUS:
default:
@ -151,7 +152,7 @@ ai_scan(si_t *sih, void *regs, uint devid)
br = FALSE;
/* Grok a component */
cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
if (cia == (ER_END | ER_VALID)) {
SI_VMSG(("Found END of erom after %d cores\n", sii->numcores));
@ -185,7 +186,7 @@ ai_scan(si_t *sih, void *regs, uint devid)
if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
continue;
if ((nmw + nsw == 0)) {
/* A component which is not a core */
if (cid == OOB_ROUTER_CORE_ID) {
asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
&addrl, &addrh, &sizel, &sizeh);
@ -193,15 +194,16 @@ ai_scan(si_t *sih, void *regs, uint devid)
sii->oob_router = addrl;
}
}
if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID)
if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID &&
cid != PMU_CORE_ID && cid != GCI_CORE_ID)
continue;
}
idx = sii->numcores;
sii->cia[idx] = cia;
sii->cib[idx] = cib;
sii->coreid[idx] = remap_coreid(sih, cid);
cores_info->cia[idx] = cia;
cores_info->cib[idx] = cib;
cores_info->coreid[idx] = remap_coreid(sih, cid);
for (i = 0; i < nmp; i++) {
mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
@ -214,11 +216,13 @@ ai_scan(si_t *sih, void *regs, uint devid)
(mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
}
/* First Slave Address Descriptor should be port 0:
* the main register space for the core
*/
asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
if (asd == 0) {
do {
/* Try again to see if it is a bridge */
asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
&sizel, &sizeh);
if (asd != 0)
@ -239,21 +243,21 @@ ai_scan(si_t *sih, void *regs, uint devid)
}
} while (1);
}
sii->coresba[idx] = addrl;
sii->coresba_size[idx] = sizel;
cores_info->coresba[idx] = addrl;
cores_info->coresba_size[idx] = sizel;
/* Get any more ASDs in port 0 */
j = 1;
do {
asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
&sizel, &sizeh);
if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) {
sii->coresba2[idx] = addrl;
sii->coresba2_size[idx] = sizel;
cores_info->coresba2[idx] = addrl;
cores_info->coresba2_size[idx] = sizel;
}
j++;
} while (asd != 0);
/* Go through the ASDs for other slave ports */
for (i = 1; i < nsp; i++) {
j = 0;
do {
@ -270,7 +274,7 @@ ai_scan(si_t *sih, void *regs, uint devid)
}
}
/* Now get master wrappers */
for (i = 0; i < nmw; i++) {
asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
&sizel, &sizeh);
@ -283,10 +287,10 @@ ai_scan(si_t *sih, void *regs, uint devid)
goto error;
}
if (i == 0)
sii->wrapba[idx] = addrl;
cores_info->wrapba[idx] = addrl;
}
/* And finally slave wrappers */
for (i = 0; i < nsw; i++) {
uint fwp = (nsp == 1) ? 0 : 1;
asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh,
@ -300,15 +304,15 @@ ai_scan(si_t *sih, void *regs, uint devid)
goto error;
}
if ((nmw == 0) && (i == 0))
sii->wrapba[idx] = addrl;
cores_info->wrapba[idx] = addrl;
}
/* Don't record bridges */
if (br)
continue;
/* Done with core */
sii->numcores++;
}
@ -319,44 +323,66 @@ ai_scan(si_t *sih, void *regs, uint devid)
return;
}
#define AI_SETCOREIDX_MAPSIZE(coreid) \
(((coreid) == NS_CCB_CORE_ID) ? 15 * SI_CORE_SIZE : SI_CORE_SIZE)
/* This function changes the logical "focus" to the indicated core.
* Return the current core's virtual address.
*/
void *
ai_setcoreidx(si_t *sih, uint coreidx)
{
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint32 addr, wrap;
void *regs;
if (coreidx >= MIN(sii->numcores, SI_MAXCORES))
return (NULL);
addr = sii->coresba[coreidx];
wrap = sii->wrapba[coreidx];
addr = cores_info->coresba[coreidx];
wrap = cores_info->wrapba[coreidx];
/*
* If the user has provided an interrupt mask enabled function,
* then assert interrupts are disabled before switching the core.
*/
ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
switch (BUSTYPE(sih->bustype)) {
case SI_BUS:
if (!sii->regs[coreidx]) {
sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
ASSERT(GOODREGS(sii->regs[coreidx]));
/* map new one */
if (!cores_info->regs[coreidx]) {
cores_info->regs[coreidx] = REG_MAP(addr,
AI_SETCOREIDX_MAPSIZE(cores_info->coreid[coreidx]));
ASSERT(GOODREGS(cores_info->regs[coreidx]));
}
sii->curmap = regs = sii->regs[coreidx];
if (!sii->wrappers[coreidx] && (wrap != 0)) {
sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
ASSERT(GOODREGS(sii->wrappers[coreidx]));
sii->curmap = regs = cores_info->regs[coreidx];
if (!cores_info->wrappers[coreidx] && (wrap != 0)) {
cores_info->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
ASSERT(GOODREGS(cores_info->wrappers[coreidx]));
}
sii->curwrap = sii->wrappers[coreidx];
sii->curwrap = cores_info->wrappers[coreidx];
break;
case PCI_BUS:
/* point bar0 window */
OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, addr);
regs = sii->curmap;
/* point bar0 2nd 4KB window to the primary wrapper */
if (PCIE_GEN2(sii))
OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap);
else
OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, wrap);
break;
#ifdef BCMSDIO
case SPI_BUS:
case SDIO_BUS:
sii->curmap = regs = (void *)((uintptr)addr);
sii->curwrap = (void *)((uintptr)wrap);
break;
#endif /* BCMSDIO */
case PCMCIA_BUS:
default:
@ -371,10 +397,12 @@ ai_setcoreidx(si_t *sih, uint coreidx)
return regs;
}
void
ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
{
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
chipcregs_t *cc = NULL;
uint32 erombase, *eromptr, *eromlim;
uint i, j, cidx;
@ -382,8 +410,8 @@ ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
uint32 asd, addrl, addrh, sizel, sizeh;
for (i = 0; i < sii->numcores; i++) {
if (sii->coreid[i] == CC_CORE_ID) {
cc = (chipcregs_t *)sii->regs[i];
if (cores_info->coreid[i] == CC_CORE_ID) {
cc = (chipcregs_t *)cores_info->regs[i];
break;
}
}
@ -395,13 +423,13 @@ ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
cidx = sii->curidx;
cia = sii->cia[cidx];
cib = sii->cib[cidx];
cia = cores_info->cia[cidx];
cib = cores_info->cib[cidx];
nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
/* scan for cores */
while (eromptr < eromlim) {
if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) &&
(get_erom_ent(sih, &eromptr, 0, 0) == cib)) {
@ -409,14 +437,14 @@ ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
}
}
/* skip master ports */
for (i = 0; i < nmp; i++)
get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
/* Skip ASDs in port 0 */
asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
if (asd == 0) {
/* Try again to see if it is a bridge */
asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
&sizel, &sizeh);
}
@ -428,7 +456,7 @@ ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
j++;
} while (asd != 0);
/* Go through the ASDs for other slave ports */
for (i = 1; i < nsp; i++) {
j = 0;
do {
@ -456,27 +484,27 @@ ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
return;
}
/* Return the number of address spaces in current core */
int
ai_numaddrspaces(si_t *sih)
{
return 2;
}
/* Return the address of the nth address space in the current core */
uint32
ai_addrspace(si_t *sih, uint asidx)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint cidx;
sii = SI_INFO(sih);
cidx = sii->curidx;
if (asidx == 0)
return sii->coresba[cidx];
return cores_info->coresba[cidx];
else if (asidx == 1)
return sii->coresba2[cidx];
return cores_info->coresba2[cidx];
else {
SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
__FUNCTION__, asidx));
@ -484,20 +512,20 @@ ai_addrspace(si_t *sih, uint asidx)
}
}
/* Return the size of the nth address space in the current core */
uint32
ai_addrspacesize(si_t *sih, uint asidx)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint cidx;
sii = SI_INFO(sih);
cidx = sii->curidx;
if (asidx == 0)
return sii->coresba_size[cidx];
return cores_info->coresba_size[cidx];
else if (asidx == 1)
return sii->coresba2_size[cidx];
return cores_info->coresba2_size[cidx];
else {
SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
__FUNCTION__, asidx));
@ -508,10 +536,9 @@ ai_addrspacesize(si_t *sih, uint asidx)
uint
ai_flag(si_t *sih)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
aidmp_t *ai;
sii = SI_INFO(sih);
if (BCM47162_DMP()) {
SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
return sii->curidx;
@ -525,7 +552,17 @@ ai_flag(si_t *sih)
__FUNCTION__));
return sii->curidx;
}
#ifdef REROUTE_OOBINT
if (PMU_DMP()) {
SI_ERROR(("%s: Attempting to read PMU DMP registers\n",
__FUNCTION__));
return PMU_OOB_BIT;
}
#endif /* REROUTE_OOBINT */
ai = sii->curwrap;
ASSERT(ai != NULL);
return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f);
}
@ -533,10 +570,9 @@ ai_flag(si_t *sih)
uint
ai_flag_alt(si_t *sih)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
aidmp_t *ai;
sii = SI_INFO(sih);
if (BCM47162_DMP()) {
SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
return sii->curidx;
@ -550,6 +586,14 @@ ai_flag_alt(si_t *sih)
__FUNCTION__));
return sii->curidx;
}
#ifdef REROUTE_OOBINT
if (PMU_DMP()) {
SI_ERROR(("%s: Attempting to read PMU DMP registers\n",
__FUNCTION__));
return PMU_OOB_BIT;
}
#endif /* REROUTE_OOBINT */
ai = sii->curwrap;
return ((R_REG(sii->osh, &ai->oobselouta30) >> AI_OOBSEL_1_SHIFT) & AI_OOBSEL_MASK);
@ -570,7 +614,7 @@ ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
uint32 w = R_REG(sii->osh, map+(offset/4));
w &= ~mask;
w |= val;
W_REG(sii->osh, map+(offset/4), val);
W_REG(sii->osh, map+(offset/4), w);
}
return (R_REG(sii->osh, map+(offset/4)));
@ -579,39 +623,47 @@ ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
uint
ai_corevendor(si_t *sih)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint32 cia;
sii = SI_INFO(sih);
cia = sii->cia[sii->curidx];
cia = cores_info->cia[sii->curidx];
return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT);
}
uint
ai_corerev(si_t *sih)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint32 cib;
sii = SI_INFO(sih);
cib = sii->cib[sii->curidx];
cib = cores_info->cib[sii->curidx];
return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT);
}
bool
ai_iscoreup(si_t *sih)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
aidmp_t *ai;
sii = SI_INFO(sih);
ai = sii->curwrap;
return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) &&
((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0));
}
/*
* Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
* switch back to the original core, and return the new value.
*
* When using the silicon backplane, no fiddling with interrupts or core switches is needed.
*
* Also, when using pci/pcie, we can optimize away the core switching for pci registers
* and (on newer pci cores) chipcommon registers.
*/
uint
ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
{
@ -620,9 +672,9 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
uint w;
uint intr_val = 0;
bool fast = FALSE;
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
sii = SI_INFO(sih);
ASSERT(GOODIDX(coreidx));
ASSERT(regoff < SI_CORE_SIZE);
@ -632,25 +684,27 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
return 0;
if (BUSTYPE(sih->bustype) == SI_BUS) {
/* If internal bus, we can always get at everything */
fast = TRUE;
if (!sii->regs[coreidx]) {
sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx],
/* map if does not exist */
if (!cores_info->regs[coreidx]) {
cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
SI_CORE_SIZE);
ASSERT(GOODREGS(sii->regs[coreidx]));
ASSERT(GOODREGS(cores_info->regs[coreidx]));
}
r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff);
r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
} else if (BUSTYPE(sih->bustype) == PCI_BUS) {
/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
/* Chipc registers are mapped at 12KB */
fast = TRUE;
r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
} else if (sii->pub.buscoreidx == coreidx) {
/* pci registers are at either in the last 2KB of an 8KB window
* or, in pcie and pci rev 13 at 8KB
*/
fast = TRUE;
if (SI_FAST(sii))
r = (uint32 *)((char *)sii->curmap +
@ -666,25 +720,25 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
if (!fast) {
INTR_OFF(sii, intr_val);
/* save current core index */
origidx = si_coreidx(&sii->pub);
/* switch core */
r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff);
}
ASSERT(r != NULL);
/* mask and set */
if (mask || val) {
w = (R_REG(sii->osh, r) & ~mask) | val;
W_REG(sii->osh, r, w);
}
/* readback */
w = R_REG(sii->osh, r);
if (!fast) {
/* restore core index */
if (origidx != coreidx)
ai_setcoreidx(&sii->pub, origidx);
@ -694,33 +748,96 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
return (w);
}
/*
* If there is no need for fiddling with interrupts or core switches (typically silicon
* back plane registers, pci registers and chipcommon registers), this function
* returns the register offset on this core to a mapped address. This address can
* be used for W_REG/R_REG directly.
*
* For accessing registers that would need a core switch, this function will return
* NULL.
*/
uint32 *
ai_corereg_addr(si_t *sih, uint coreidx, uint regoff)
{
uint32 *r = NULL;
bool fast = FALSE;
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
ASSERT(GOODIDX(coreidx));
ASSERT(regoff < SI_CORE_SIZE);
if (coreidx >= SI_MAXCORES)
return 0;
if (BUSTYPE(sih->bustype) == SI_BUS) {
/* If internal bus, we can always get at everything */
fast = TRUE;
/* map if does not exist */
if (!cores_info->regs[coreidx]) {
cores_info->regs[coreidx] = REG_MAP(cores_info->coresba[coreidx],
SI_CORE_SIZE);
ASSERT(GOODREGS(cores_info->regs[coreidx]));
}
r = (uint32 *)((uchar *)cores_info->regs[coreidx] + regoff);
} else if (BUSTYPE(sih->bustype) == PCI_BUS) {
/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
if ((cores_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
/* Chipc registers are mapped at 12KB */
fast = TRUE;
r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
} else if (sii->pub.buscoreidx == coreidx) {
/* pci registers are at either in the last 2KB of an 8KB window
* or, in pcie and pci rev 13 at 8KB
*/
fast = TRUE;
if (SI_FAST(sii))
r = (uint32 *)((char *)sii->curmap +
PCI_16KB0_PCIREGS_OFFSET + regoff);
else
r = (uint32 *)((char *)sii->curmap +
((regoff >= SBCONFIGOFF) ?
PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
regoff);
}
}
if (!fast)
return 0;
return (r);
}
void
ai_core_disable(si_t *sih, uint32 bits)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
volatile uint32 dummy;
uint32 status;
aidmp_t *ai;
sii = SI_INFO(sih);
ASSERT(GOODREGS(sii->curwrap));
ai = sii->curwrap;
/* if core is already in reset, just return */
if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET)
return;
/* ensure there are no pending backplane operations */
SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
/* if pending backplane ops still, try waiting longer */
if (status != 0) {
/* 300usecs was sufficient to allow backplane ops to clear for big hammer */
/* during driver load we may need more time */
SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000);
/* if still pending ops, continue on and try disable anyway */
/* this is in big hammer path, so don't call wl_reinit in this case... */
}
W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
@ -734,30 +851,53 @@ ai_core_disable(si_t *sih, uint32 bits)
OSL_DELAY(10);
}
/* reset and re-enable a core
* inputs:
* bits - core specific bits that are set during and after reset sequence
* resetbits - core specific bits that are set only during reset sequence
*/
void
ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
aidmp_t *ai;
volatile uint32 dummy;
uint loop_counter = 10;
sii = SI_INFO(sih);
ASSERT(GOODREGS(sii->curwrap));
ai = sii->curwrap;
ai_core_disable(sih, (bits | resetbits));
/* ensure there are no pending backplane operations */
SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
/* put core into reset state */
W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
OSL_DELAY(10);
/* ensure there are no pending backplane operations */
SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300);
W_REG(sii->osh, &ai->ioctrl, (bits | resetbits | SICF_FGC | SICF_CLOCK_EN));
dummy = R_REG(sii->osh, &ai->ioctrl);
BCM_REFERENCE(dummy);
W_REG(sii->osh, &ai->resetctrl, 0);
dummy = R_REG(sii->osh, &ai->resetctrl);
BCM_REFERENCE(dummy);
OSL_DELAY(1);
/* ensure there are no pending backplane operations */
SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
while (R_REG(sii->osh, &ai->resetctrl) != 0 && --loop_counter != 0) {
/* ensure there are no pending backplane operations */
SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
/* take core out of reset */
W_REG(sii->osh, &ai->resetctrl, 0);
/* ensure there are no pending backplane operations */
SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300);
}
W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN));
dummy = R_REG(sii->osh, &ai->ioctrl);
@ -768,11 +908,10 @@ ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
void
ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
aidmp_t *ai;
uint32 w;
sii = SI_INFO(sih);
if (BCM47162_DMP()) {
SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
@ -789,6 +928,11 @@ ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
__FUNCTION__));
return;
}
if (PMU_DMP()) {
SI_ERROR(("%s: Accessing PMU DMP register (ioctrl)\n",
__FUNCTION__));
return;
}
ASSERT(GOODREGS(sii->curwrap));
ai = sii->curwrap;
@ -804,11 +948,10 @@ ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
uint32
ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
aidmp_t *ai;
uint32 w;
sii = SI_INFO(sih);
if (BCM47162_DMP()) {
SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
__FUNCTION__));
@ -825,6 +968,11 @@ ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
return 0;
}
if (PMU_DMP()) {
SI_ERROR(("%s: Accessing PMU DMP register (ioctrl)\n",
__FUNCTION__));
return 0;
}
ASSERT(GOODREGS(sii->curwrap));
ai = sii->curwrap;
@ -841,11 +989,10 @@ ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
uint32
ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
{
si_info_t *sii;
si_info_t *sii = SI_INFO(sih);
aidmp_t *ai;
uint32 w;
sii = SI_INFO(sih);
if (BCM47162_DMP()) {
SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0",
__FUNCTION__));
@ -861,6 +1008,11 @@ ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
__FUNCTION__));
return 0;
}
if (PMU_DMP()) {
SI_ERROR(("%s: Accessing PMU DMP register (ioctrl)\n",
__FUNCTION__));
return 0;
}
ASSERT(GOODREGS(sii->curwrap));
ai = sii->curwrap;
@ -875,3 +1027,71 @@ ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
return R_REG(sii->osh, &ai->iostatus);
}
#if defined(BCMDBG_PHYDUMP)
/* print interesting aidmp registers */
void
ai_dumpregs(si_t *sih, struct bcmstrbuf *b)
{
si_info_t *sii = SI_INFO(sih);
si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
osl_t *osh;
aidmp_t *ai;
uint i;
osh = sii->osh;
for (i = 0; i < sii->numcores; i++) {
si_setcoreidx(&sii->pub, i);
ai = sii->curwrap;
bcm_bprintf(b, "core 0x%x: \n", cores_info->coreid[i]);
if (BCM47162_DMP()) {
bcm_bprintf(b, "Skipping mips74k in 47162a0\n");
continue;
}
if (BCM5357_DMP()) {
bcm_bprintf(b, "Skipping usb20h in 5357\n");
continue;
}
if (BCM4707_DMP()) {
bcm_bprintf(b, "Skipping chipcommonb in 4707\n");
continue;
}
if (PMU_DMP()) {
bcm_bprintf(b, "Skipping pmu core\n");
continue;
}
bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x"
"ioctrlwidth 0x%x iostatuswidth 0x%x\n"
"resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n"
"errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x"
"errlogaddrlo 0x%x errlogaddrhi 0x%x\n"
"errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n"
"intstatus 0x%x config 0x%x itcr 0x%x\n",
R_REG(osh, &ai->ioctrlset),
R_REG(osh, &ai->ioctrlclear),
R_REG(osh, &ai->ioctrl),
R_REG(osh, &ai->iostatus),
R_REG(osh, &ai->ioctrlwidth),
R_REG(osh, &ai->iostatuswidth),
R_REG(osh, &ai->resetctrl),
R_REG(osh, &ai->resetstatus),
R_REG(osh, &ai->resetreadid),
R_REG(osh, &ai->resetwriteid),
R_REG(osh, &ai->errlogctrl),
R_REG(osh, &ai->errlogdone),
R_REG(osh, &ai->errlogstatus),
R_REG(osh, &ai->errlogaddrlo),
R_REG(osh, &ai->errlogaddrhi),
R_REG(osh, &ai->errlogid),
R_REG(osh, &ai->errloguser),
R_REG(osh, &ai->errlogflags),
R_REG(osh, &ai->intstatus),
R_REG(osh, &ai->config),
R_REG(osh, &ai->itcr));
}
}
#endif

View File

@ -2,7 +2,7 @@
* bcmevent read-only data shared by kernel or app layers
*
* $Copyright Open Broadcom Corporation$
* $Id: bcmevent.c 389384 2013-03-06 12:20:17Z $
* $Id: bcmevent.c 487838 2014-06-27 05:51:44Z $
*/
#include <typedefs.h>
@ -11,141 +11,188 @@
#include <proto/bcmeth.h>
#include <proto/bcmevent.h>
#if WLC_E_LAST != 125
#error "You need to add an entry to bcmevent_names[] for the new event"
#endif
const bcmevent_name_t bcmevent_names[] = {
{ WLC_E_SET_SSID, "SET_SSID" },
{ WLC_E_JOIN, "JOIN" },
{ WLC_E_START, "START" },
{ WLC_E_AUTH, "AUTH" },
{ WLC_E_AUTH_IND, "AUTH_IND" },
{ WLC_E_DEAUTH, "DEAUTH" },
{ WLC_E_DEAUTH_IND, "DEAUTH_IND" },
{ WLC_E_ASSOC, "ASSOC" },
{ WLC_E_ASSOC_IND, "ASSOC_IND" },
{ WLC_E_REASSOC, "REASSOC" },
{ WLC_E_REASSOC_IND, "REASSOC_IND" },
{ WLC_E_DISASSOC, "DISASSOC" },
{ WLC_E_DISASSOC_IND, "DISASSOC_IND" },
{ WLC_E_QUIET_START, "START_QUIET" },
{ WLC_E_QUIET_END, "END_QUIET" },
{ WLC_E_BEACON_RX, "BEACON_RX" },
{ WLC_E_LINK, "LINK" },
{ WLC_E_MIC_ERROR, "MIC_ERROR" },
{ WLC_E_NDIS_LINK, "NDIS_LINK" },
{ WLC_E_ROAM, "ROAM" },
{ WLC_E_TXFAIL, "TXFAIL" },
{ WLC_E_PMKID_CACHE, "PMKID_CACHE" },
{ WLC_E_RETROGRADE_TSF, "RETROGRADE_TSF" },
{ WLC_E_PRUNE, "PRUNE" },
{ WLC_E_AUTOAUTH, "AUTOAUTH" },
{ WLC_E_EAPOL_MSG, "EAPOL_MSG" },
{ WLC_E_SCAN_COMPLETE, "SCAN_COMPLETE" },
{ WLC_E_ADDTS_IND, "ADDTS_IND" },
{ WLC_E_DELTS_IND, "DELTS_IND" },
{ WLC_E_BCNSENT_IND, "BCNSENT_IND" },
{ WLC_E_BCNRX_MSG, "BCNRX_MSG" },
{ WLC_E_BCNLOST_MSG, "BCNLOST_IND" },
{ WLC_E_ROAM_PREP, "ROAM_PREP" },
{ WLC_E_PFN_NET_FOUND, "PFNFOUND_IND" },
{ WLC_E_PFN_NET_LOST, "PFNLOST_IND" },
/* Table of event name strings for UIs and debugging dumps */
typedef struct {
uint event;
const char *name;
} bcmevent_name_str_t;
/* Use the actual name for event tracing */
#define BCMEVENT_NAME(_event) {(_event), #_event}
static const bcmevent_name_str_t bcmevent_names[] = {
BCMEVENT_NAME(WLC_E_SET_SSID),
BCMEVENT_NAME(WLC_E_JOIN),
BCMEVENT_NAME(WLC_E_START),
BCMEVENT_NAME(WLC_E_AUTH),
BCMEVENT_NAME(WLC_E_AUTH_IND),
BCMEVENT_NAME(WLC_E_DEAUTH),
BCMEVENT_NAME(WLC_E_DEAUTH_IND),
BCMEVENT_NAME(WLC_E_ASSOC),
BCMEVENT_NAME(WLC_E_ASSOC_IND),
BCMEVENT_NAME(WLC_E_REASSOC),
BCMEVENT_NAME(WLC_E_REASSOC_IND),
BCMEVENT_NAME(WLC_E_DISASSOC),
BCMEVENT_NAME(WLC_E_DISASSOC_IND),
BCMEVENT_NAME(WLC_E_QUIET_START),
BCMEVENT_NAME(WLC_E_QUIET_END),
BCMEVENT_NAME(WLC_E_BEACON_RX),
BCMEVENT_NAME(WLC_E_LINK),
BCMEVENT_NAME(WLC_E_MIC_ERROR),
BCMEVENT_NAME(WLC_E_NDIS_LINK),
BCMEVENT_NAME(WLC_E_ROAM),
BCMEVENT_NAME(WLC_E_TXFAIL),
BCMEVENT_NAME(WLC_E_PMKID_CACHE),
BCMEVENT_NAME(WLC_E_RETROGRADE_TSF),
BCMEVENT_NAME(WLC_E_PRUNE),
BCMEVENT_NAME(WLC_E_AUTOAUTH),
BCMEVENT_NAME(WLC_E_EAPOL_MSG),
BCMEVENT_NAME(WLC_E_SCAN_COMPLETE),
BCMEVENT_NAME(WLC_E_ADDTS_IND),
BCMEVENT_NAME(WLC_E_DELTS_IND),
BCMEVENT_NAME(WLC_E_BCNSENT_IND),
BCMEVENT_NAME(WLC_E_BCNRX_MSG),
BCMEVENT_NAME(WLC_E_BCNLOST_MSG),
BCMEVENT_NAME(WLC_E_ROAM_PREP),
BCMEVENT_NAME(WLC_E_PFN_NET_FOUND),
BCMEVENT_NAME(WLC_E_PFN_NET_LOST),
#if defined(IBSS_PEER_DISCOVERY_EVENT)
{ WLC_E_IBSS_ASSOC, "IBSS_ASSOC" },
BCMEVENT_NAME(WLC_E_IBSS_ASSOC),
#endif /* defined(IBSS_PEER_DISCOVERY_EVENT) */
{ WLC_E_RADIO, "RADIO" },
{ WLC_E_PSM_WATCHDOG, "PSM_WATCHDOG" },
BCMEVENT_NAME(WLC_E_RADIO),
BCMEVENT_NAME(WLC_E_PSM_WATCHDOG),
#if defined(BCMCCX) && defined(CCX_SDK)
{ WLC_E_CCX_ASSOC_START, "CCX_ASSOC_START" },
{ WLC_E_CCX_ASSOC_ABORT, "CCX_ASSOC_ABORT" },
BCMEVENT_NAME(WLC_E_CCX_ASSOC_START),
BCMEVENT_NAME(WLC_E_CCX_ASSOC_ABORT),
#endif /* BCMCCX && CCX_SDK */
{ WLC_E_PROBREQ_MSG, "PROBE_REQ_MSG" },
{ WLC_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND" },
{ WLC_E_PSK_SUP, "PSK_SUP" },
{ WLC_E_COUNTRY_CODE_CHANGED, "CNTRYCODE_IND" },
{ WLC_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME" },
{ WLC_E_ICV_ERROR, "ICV_ERROR" },
{ WLC_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR" },
{ WLC_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR" },
{ WLC_E_TRACE, "TRACE" },
BCMEVENT_NAME(WLC_E_PROBREQ_MSG),
BCMEVENT_NAME(WLC_E_SCAN_CONFIRM_IND),
BCMEVENT_NAME(WLC_E_PSK_SUP),
BCMEVENT_NAME(WLC_E_COUNTRY_CODE_CHANGED),
BCMEVENT_NAME(WLC_E_EXCEEDED_MEDIUM_TIME),
BCMEVENT_NAME(WLC_E_ICV_ERROR),
BCMEVENT_NAME(WLC_E_UNICAST_DECODE_ERROR),
BCMEVENT_NAME(WLC_E_MULTICAST_DECODE_ERROR),
BCMEVENT_NAME(WLC_E_TRACE),
#ifdef WLBTAMP
{ WLC_E_BTA_HCI_EVENT, "BTA_HCI_EVENT" },
BCMEVENT_NAME(WLC_E_BTA_HCI_EVENT),
#endif
{ WLC_E_IF, "IF" },
BCMEVENT_NAME(WLC_E_IF),
#ifdef WLP2P
{ WLC_E_P2P_DISC_LISTEN_COMPLETE, "WLC_E_P2P_DISC_LISTEN_COMPLETE" },
BCMEVENT_NAME(WLC_E_P2P_DISC_LISTEN_COMPLETE),
#endif
{ WLC_E_RSSI, "RSSI" },
{ WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE" },
{ WLC_E_EXTLOG_MSG, "EXTERNAL LOG MESSAGE" },
BCMEVENT_NAME(WLC_E_RSSI),
BCMEVENT_NAME(WLC_E_PFN_SCAN_COMPLETE),
BCMEVENT_NAME(WLC_E_EXTLOG_MSG),
#ifdef WIFI_ACT_FRAME
{ WLC_E_ACTION_FRAME, "ACTION_FRAME" },
{ WLC_E_ACTION_FRAME_RX, "ACTION_FRAME_RX" },
{ WLC_E_ACTION_FRAME_COMPLETE, "ACTION_FRAME_COMPLETE" },
BCMEVENT_NAME(WLC_E_ACTION_FRAME),
BCMEVENT_NAME(WLC_E_ACTION_FRAME_RX),
BCMEVENT_NAME(WLC_E_ACTION_FRAME_COMPLETE),
#endif
#if 0 && (NDISVER >= 0x0620)
{ WLC_E_PRE_ASSOC_IND, "ASSOC_RECV" },
{ WLC_E_PRE_REASSOC_IND, "REASSOC_RECV" },
{ WLC_E_CHANNEL_ADOPTED, "CHANNEL_ADOPTED" },
{ WLC_E_AP_STARTED, "AP_STARTED" },
{ WLC_E_DFS_AP_STOP, "DFS_AP_STOP" },
{ WLC_E_DFS_AP_RESUME, "DFS_AP_RESUME" },
{ WLC_E_ASSOC_IND_NDIS, "ASSOC_IND_NDIS"},
{ WLC_E_REASSOC_IND_NDIS, "REASSOC_IND_NDIS"},
{ WLC_E_ACTION_FRAME_RX_NDIS, "WLC_E_ACTION_FRAME_RX_NDIS" },
{ WLC_E_AUTH_REQ, "WLC_E_AUTH_REQ" },
{ WLC_E_IBSS_COALESCE, "IBSS COALESCE" },
BCMEVENT_NAME(WLC_E_PRE_ASSOC_IND),
BCMEVENT_NAME(WLC_E_PRE_REASSOC_IND),
BCMEVENT_NAME(WLC_E_CHANNEL_ADOPTED),
BCMEVENT_NAME(WLC_E_AP_STARTED),
BCMEVENT_NAME(WLC_E_DFS_AP_STOP),
BCMEVENT_NAME(WLC_E_DFS_AP_RESUME),
BCMEVENT_NAME(WLC_E_ASSOC_IND_NDIS),
BCMEVENT_NAME(WLC_E_REASSOC_IND_NDIS),
BCMEVENT_NAME(WLC_E_ACTION_FRAME_RX_NDIS),
BCMEVENT_NAME(WLC_E_AUTH_REQ),
BCMEVENT_NAME(WLC_E_IBSS_COALESCE),
#endif
#ifdef BCMWAPI_WAI
{ WLC_E_WAI_STA_EVENT, "WAI_STA_EVENT" },
{ WLC_E_WAI_MSG, "WAI_MSG" },
BCMEVENT_NAME(WLC_E_WAI_STA_EVENT),
BCMEVENT_NAME(WLC_E_WAI_MSG),
#endif /* BCMWAPI_WAI */
{ WLC_E_ESCAN_RESULT, "WLC_E_ESCAN_RESULT" },
{ WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "WLC_E_AF_OFF_CHAN_COMPLETE" },
BCMEVENT_NAME(WLC_E_ESCAN_RESULT),
BCMEVENT_NAME(WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE),
#ifdef WLP2P
{ WLC_E_PROBRESP_MSG, "PROBE_RESP_MSG" },
{ WLC_E_P2P_PROBREQ_MSG, "P2P PROBE_REQ_MSG" },
BCMEVENT_NAME(WLC_E_PROBRESP_MSG),
BCMEVENT_NAME(WLC_E_P2P_PROBREQ_MSG),
#endif
#ifdef PROP_TXSTATUS
{ WLC_E_FIFO_CREDIT_MAP, "FIFO_CREDIT_MAP" },
BCMEVENT_NAME(WLC_E_FIFO_CREDIT_MAP),
#endif
{ WLC_E_WAKE_EVENT, "WAKE_EVENT" },
{ WLC_E_DCS_REQUEST, "DCS_REQUEST" },
{ WLC_E_RM_COMPLETE, "RM_COMPLETE" },
BCMEVENT_NAME(WLC_E_WAKE_EVENT),
BCMEVENT_NAME(WLC_E_DCS_REQUEST),
BCMEVENT_NAME(WLC_E_RM_COMPLETE),
#ifdef WLMEDIA_HTSF
{ WLC_E_HTSFSYNC, "HTSF_SYNC_EVENT" },
BCMEVENT_NAME(WLC_E_HTSFSYNC),
#endif
{ WLC_E_OVERLAY_REQ, "OVERLAY_REQ_EVENT" },
{ WLC_E_CSA_COMPLETE_IND, "WLC_E_CSA_COMPLETE_IND"},
{ WLC_E_EXCESS_PM_WAKE_EVENT, "EXCESS_PM_WAKE_EVENT" },
{ WLC_E_PFN_SCAN_NONE, "PFN_SCAN_NONE" },
{ WLC_E_PFN_SCAN_ALLGONE, "PFN_SCAN_ALLGONE" },
BCMEVENT_NAME(WLC_E_OVERLAY_REQ),
BCMEVENT_NAME(WLC_E_CSA_COMPLETE_IND),
BCMEVENT_NAME(WLC_E_EXCESS_PM_WAKE_EVENT),
BCMEVENT_NAME(WLC_E_PFN_SCAN_NONE),
BCMEVENT_NAME(WLC_E_PFN_SCAN_ALLGONE),
#ifdef SOFTAP
{ WLC_E_GTK_PLUMBED, "GTK_PLUMBED" },
BCMEVENT_NAME(WLC_E_GTK_PLUMBED),
#endif
{ WLC_E_ASSOC_REQ_IE, "ASSOC_REQ_IE" },
{ WLC_E_ASSOC_RESP_IE, "ASSOC_RESP_IE" },
{ WLC_E_ACTION_FRAME_RX_NDIS, "WLC_E_ACTION_FRAME_RX_NDIS" },
BCMEVENT_NAME(WLC_E_ASSOC_REQ_IE),
BCMEVENT_NAME(WLC_E_ASSOC_RESP_IE),
BCMEVENT_NAME(WLC_E_BEACON_FRAME_RX),
#ifdef WLTDLS
{ WLC_E_TDLS_PEER_EVENT, "TDLS_PEER_EVENT" },
BCMEVENT_NAME(WLC_E_TDLS_PEER_EVENT),
#endif /* WLTDLS */
{ WLC_E_NATIVE, "NATIVE" },
BCMEVENT_NAME(WLC_E_NATIVE),
#ifdef WLPKTDLYSTAT
{ WLC_E_PKTDELAY_IND, "PKTDELAY_IND" },
BCMEVENT_NAME(WLC_E_PKTDELAY_IND),
#endif /* WLPKTDLYSTAT */
{ WLC_E_SERVICE_FOUND, "SERVICE_FOUND" },
{ WLC_E_GAS_FRAGMENT_RX, "GAS_FRAGMENT_RX" },
{ WLC_E_GAS_COMPLETE, "GAS_COMPLETE" },
{ WLC_E_P2PO_ADD_DEVICE, "P2PO_DEV_FOUND" },
{ WLC_E_P2PO_DEL_DEVICE, "P2PO_DEV_LOST" },
BCMEVENT_NAME(WLC_E_SERVICE_FOUND),
BCMEVENT_NAME(WLC_E_GAS_FRAGMENT_RX),
BCMEVENT_NAME(WLC_E_GAS_COMPLETE),
BCMEVENT_NAME(WLC_E_P2PO_ADD_DEVICE),
BCMEVENT_NAME(WLC_E_P2PO_DEL_DEVICE),
#ifdef WLWNM
{ WLC_E_WNM_STA_SLEEP, "WMM_STA_SLEEP" },
BCMEVENT_NAME(WLC_E_WNM_STA_SLEEP),
#endif /* WLWNM */
#if defined(WL_PROXDETECT)
{ WLC_E_PROXD, "WLC_E_PROXD" },
BCMEVENT_NAME(WLC_E_PROXD),
#endif
{ WLC_E_CCA_CHAN_QUAL, "CCA_BASED_CHANNEL_QUALITY" },
BCMEVENT_NAME(WLC_E_CCA_CHAN_QUAL),
BCMEVENT_NAME(WLC_E_BSSID),
#ifdef PROP_TXSTATUS
BCMEVENT_NAME(WLC_E_BCMC_CREDIT_SUPPORT),
#endif
BCMEVENT_NAME(WLC_E_TXFAIL_THRESH),
#ifdef WLAIBSS
BCMEVENT_NAME(WLC_E_AIBSS_TXFAIL),
#endif /* WLAIBSS */
#ifdef WLBSSLOAD_REPORT
BCMEVENT_NAME(WLC_E_BSS_LOAD),
#endif
#if defined(BT_WIFI_HANDOVER) || defined(WL_TBOW)
BCMEVENT_NAME(WLC_E_BT_WIFI_HANDOVER_REQ),
#endif
#ifdef WLFBT
BCMEVENT_NAME(WLC_E_FBT_AUTH_REQ_IND),
#endif /* WLFBT */
BCMEVENT_NAME(WLC_E_RMC_EVENT),
};
const int bcmevent_names_size = ARRAYSIZE(bcmevent_names);
const char *bcmevent_get_name(uint event_type)
{
/* note: first coded this as a static const but some
* ROMs already have something called event_name so
* changed it so we don't have a variable for the
* 'unknown string
*/
const char *event_name = NULL;
uint idx;
for (idx = 0; idx < (uint)ARRAYSIZE(bcmevent_names); idx++) {
if (bcmevent_names[idx].event == event_type) {
event_name = bcmevent_names[idx].name;
break;
}
}
/* if we find an event name in the array, return it.
* otherwise return unknown string.
*/
return ((event_name) ? event_name : "Unknown Event");
}

View File

@ -4,7 +4,7 @@
*
* $ Copyright Open Broadcom Corporation $
*
* $Id: bcmsdh.c 373331 2012-12-07 04:46:22Z $
* $Id: bcmsdh.c 450676 2014-01-22 22:45:13Z $
*/
/**
@ -24,27 +24,18 @@
#include <bcmsdh.h> /* BRCM API for SDIO clients (such as wl, dhd) */
#include <bcmsdbus.h> /* common SDIO/controller interface */
#include <sbsdio.h> /* SDIO device core hardware definitions. */
#include <sdio.h> /* SDIO Device and Protocol Specs */
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
/**
* BCMSDH API context
*/
struct bcmsdh_info
{
bool init_success; /* underlying driver successfully attached */
void *sdioh; /* handler for sdioh */
uint32 vendevid; /* Target Vendor and Device ID on SD bus */
osl_t *osh;
bool regfail; /* Save status of last reg_read/reg_write call */
uint32 sbwad; /* Save backplane window address */
};
/* local copy of bcm sd handler */
bcmsdh_info_t * l_bcmsdh = NULL;
#if 0 && (NDISVER < 0x0630)
extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd);
#endif
#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
extern int
sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
@ -66,7 +57,7 @@ bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
* @return bcmsdh_info_t Handle to BCMSDH context.
*/
bcmsdh_info_t *
bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq)
bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva)
{
bcmsdh_info_t *bcmsdh;
@ -75,22 +66,17 @@ bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq)
return NULL;
}
bzero((char *)bcmsdh, sizeof(bcmsdh_info_t));
bcmsdh->sdioh = sdioh;
bcmsdh->osh = osh;
bcmsdh->init_success = TRUE;
*regsva = SI_ENUM_BASE;
/* Report the BAR, to fix if needed */
bcmsdh->sbwad = SI_ENUM_BASE;
/* save the handler locally */
l_bcmsdh = bcmsdh;
if (!(bcmsdh->sdioh = sdioh_attach(osh, cfghdl, irq))) {
bcmsdh_detach(osh, bcmsdh);
return NULL;
}
bcmsdh->osh = osh;
bcmsdh->init_success = TRUE;
*regsva = (uint32 *)SI_ENUM_BASE;
/* Report the BAR, to fix if needed */
bcmsdh->sbwad = SI_ENUM_BASE;
return bcmsdh;
}
@ -100,14 +86,15 @@ bcmsdh_detach(osl_t *osh, void *sdh)
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
if (bcmsdh != NULL) {
if (bcmsdh->sdioh) {
#if 0 && (NDISVER < 0x0630)
if (bcmsdh->sdioh)
sdioh_detach(osh, bcmsdh->sdioh);
bcmsdh->sdioh = NULL;
}
#endif
MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t));
}
l_bcmsdh = NULL;
return 0;
}
@ -599,8 +586,6 @@ int
bcmsdh_waitlockfree(void *sdh)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
if (!bcmsdh)
bcmsdh = l_bcmsdh;
return sdioh_waitlockfree(bcmsdh->sdioh);
}
@ -711,32 +696,3 @@ bcmsdh_gpioout(void *sdh, uint32 gpio, bool enab)
return sdioh_gpioout(sd, gpio, enab);
}
#ifdef BCMSDIOH_TXGLOM
void
bcmsdh_glom_post(void *sdh, uint8 *frame, void *pkt, uint len)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
sdioh_glom_post(bcmsdh->sdioh, frame, pkt, len);
}
void
bcmsdh_glom_clear(void *sdh)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
sdioh_glom_clear(bcmsdh->sdioh);
}
uint
bcmsdh_set_mode(void *sdh, uint mode)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
return (sdioh_set_mode(bcmsdh->sdioh, mode));
}
bool
bcmsdh_glom_enabled(void)
{
return (sdioh_glom_enabled());
}
#endif /* BCMSDIOH_TXGLOM */

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: bcmsdh_linux.c 414953 2013-07-26 17:36:27Z $
* $Id: bcmsdh_linux.c 461444 2014-03-12 02:55:28Z $
*/
/**
@ -14,7 +14,6 @@
#include <typedefs.h>
#include <linuxver.h>
#include <linux/pci.h>
#include <linux/completion.h>
@ -22,43 +21,46 @@
#include <pcicfg.h>
#include <bcmdefs.h>
#include <bcmdevs.h>
#if defined(OOB_INTR_ONLY)
#include <linux/irq.h>
extern void dhdsdio_isr(void * args);
#include <bcmutils.h>
#include <dngl_stats.h>
#include <dhd.h>
#endif
/**
* SDIO Host Controller info
*/
typedef struct bcmsdh_hc bcmsdh_hc_t;
struct bcmsdh_hc {
bcmsdh_hc_t *next;
#ifdef BCMPLATFORM_BUS
struct device *dev; /* platform device handle */
#else
struct pci_dev *dev; /* pci device handle */
#endif /* BCMPLATFORM_BUS */
osl_t *osh;
void *regs; /* SDIO Host Controller address */
bcmsdh_info_t *sdh; /* SDIO Host Controller handle */
void *ch;
unsigned int oob_irq;
unsigned long oob_flags; /* OOB Host specifiction as edge and etc */
bool oob_irq_registered;
bool oob_irq_enable_flag;
#if defined(OOB_INTR_ONLY)
spinlock_t irq_lock;
#endif
};
static bcmsdh_hc_t *sdhcinfo = NULL;
#if defined(CONFIG_ARCH_ODIN)
#include <linux/platform_data/gpio-odin.h>
#endif /* defined(CONFIG_ARCH_ODIN) */
#include <dhd_linux.h>
/* driver info, initialized when bcmsdh_register is called */
static bcmsdh_driver_t drvinfo = {NULL, NULL};
static bcmsdh_driver_t drvinfo = {NULL, NULL, NULL, NULL};
typedef enum {
DHD_INTR_INVALID = 0,
DHD_INTR_INBAND,
DHD_INTR_HWOOB,
DHD_INTR_SWOOB
} DHD_HOST_INTR_TYPE;
/* the BCMSDH module comprises the generic part (bcmsdh.c) and OS specific layer (e.g.
* bcmsdh_linux.c). Put all OS specific variables (e.g. irq number and flags) here rather
* than in the common structure bcmsdh_info. bcmsdh_info only keeps a handle (os_ctx) to this
* structure.
*/
typedef struct bcmsdh_os_info {
DHD_HOST_INTR_TYPE intr_type;
int oob_irq_num; /* valid when hardware or software oob in use */
unsigned long oob_irq_flags; /* valid when hardware or software oob in use */
bool oob_irq_registered;
bool oob_irq_enabled;
bool oob_irq_wake_enabled;
spinlock_t oob_irq_spinlock;
bcmsdh_cb_fn_t oob_irq_handler;
void *oob_irq_handler_context;
void *context; /* context returned from upper layer */
void *sdioh; /* handle to lower layer (sdioh) */
void *dev; /* handle to the underlying device */
bool dev_wake_enabled;
} bcmsdh_os_info_t;
/* debugging macros */
#define SDLX_MSG(x) printf x
@ -113,391 +115,104 @@ bcmsdh_chipmatch(uint16 vendor, uint16 device)
return (FALSE);
}
#if defined(BCMPLATFORM_BUS)
#if defined(BCMLXSDMMC)
/* forward declarations */
int bcmsdh_probe(struct device *dev);
int bcmsdh_remove(struct device *dev);
EXPORT_SYMBOL(bcmsdh_probe);
EXPORT_SYMBOL(bcmsdh_remove);
#else
/* forward declarations */
static int __devinit bcmsdh_probe(struct device *dev);
static int __devexit bcmsdh_remove(struct device *dev);
#endif
#if !defined(BCMLXSDMMC)
static
#endif
int bcmsdh_probe(struct device *dev)
void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bus_type,
uint bus_num, uint slot_num)
{
osl_t *osh = NULL;
bcmsdh_hc_t *sdhc = NULL;
ulong regs = 0;
bcmsdh_info_t *sdh = NULL;
#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
struct platform_device *pdev;
struct resource *r;
#endif
int irq = 0;
ulong regs;
bcmsdh_info_t *bcmsdh;
uint32 vendevid;
unsigned long irq_flags = 0;
bcmsdh_os_info_t *bcmsdh_osinfo = NULL;
#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
pdev = to_platform_device(dev);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
if (!r || irq < 0)
return -ENXIO;
#endif
bcmsdh = bcmsdh_attach(osh, sdioh, &regs);
if (bcmsdh == NULL) {
SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
goto err;
}
bcmsdh_osinfo = MALLOC(osh, sizeof(bcmsdh_os_info_t));
if (bcmsdh_osinfo == NULL) {
SDLX_MSG(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__));
goto err;
}
bzero((char *)bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
bcmsdh->os_cxt = bcmsdh_osinfo;
bcmsdh_osinfo->sdioh = sdioh;
bcmsdh_osinfo->dev = dev;
osl_set_bus_handle(osh, bcmsdh);
#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
if (dev && device_init_wakeup(dev, true) == 0)
bcmsdh_osinfo->dev_wake_enabled = TRUE;
#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
#if defined(OOB_INTR_ONLY)
#ifdef HW_OOB
irq_flags =
IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
#else
irq_flags = IRQF_TRIGGER_FALLING;
#endif /* HW_OOB */
spin_lock_init(&bcmsdh_osinfo->oob_irq_spinlock);
/* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */
irq = dhd_customer_oob_irq_map(&irq_flags);
if (irq < 0) {
SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__));
bcmsdh_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter_info,
&bcmsdh_osinfo->oob_irq_flags);
if (bcmsdh_osinfo->oob_irq_num < 0) {
SDLX_MSG(("%s: Host OOB irq is not defined\n", __FUNCTION__));
goto err;
}
#endif
/* allocate SDIO Host Controller state info */
if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) {
SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
goto err;
}
if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) {
SDLX_MSG(("%s: out of memory, allocated %d bytes\n",
__FUNCTION__,
MALLOCED(osh)));
goto err;
}
bzero(sdhc, sizeof(bcmsdh_hc_t));
sdhc->osh = osh;
sdhc->dev = (void *)dev;
#if defined(BCMLXSDMMC)
if (!(sdh = bcmsdh_attach(osh, (void *)0,
(void **)&regs, irq))) {
SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
goto err;
}
#else
if (!(sdh = bcmsdh_attach(osh, (void *)r->start,
(void **)&regs, irq))) {
SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
goto err;
}
#endif
sdhc->sdh = sdh;
sdhc->oob_irq = irq;
sdhc->oob_flags = irq_flags;
sdhc->oob_irq_registered = FALSE; /* to make sure.. */
sdhc->oob_irq_enable_flag = FALSE;
#if defined(OOB_INTR_ONLY)
spin_lock_init(&sdhc->irq_lock);
#endif
/* chain SDIO Host Controller info together */
sdhc->next = sdhcinfo;
sdhcinfo = sdhc;
#endif /* defined(BCMLXSDMMC) */
/* Read the vendor/device ID from the CIS */
vendevid = bcmsdh_query_device(sdh);
vendevid = bcmsdh_query_device(bcmsdh);
/* try to attach to the target device */
if (!(sdhc->ch = drvinfo.attach((vendevid >> 16),
(vendevid & 0xFFFF), 0, 0, 0, 0,
(void *)regs, NULL, sdh))) {
bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num,
slot_num, 0, bus_type, (void *)regs, osh, bcmsdh);
if (bcmsdh_osinfo->context == NULL) {
SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
goto err;
}
return 0;
return bcmsdh;
/* error handling */
err:
if (sdhc) {
if (sdhc->sdh)
bcmsdh_detach(sdhc->osh, sdhc->sdh);
MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
}
if (osh)
osl_detach(osh);
return -ENODEV;
if (bcmsdh != NULL)
bcmsdh_detach(osh, bcmsdh);
if (bcmsdh_osinfo != NULL)
MFREE(osh, bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
return NULL;
}
#if !defined(BCMLXSDMMC)
static
#endif
int bcmsdh_remove(struct device *dev)
int bcmsdh_remove(bcmsdh_info_t *bcmsdh)
{
bcmsdh_hc_t *sdhc, *prev;
osl_t *osh;
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
sdhc = sdhcinfo;
drvinfo.detach(sdhc->ch);
bcmsdh_detach(sdhc->osh, sdhc->sdh);
#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
if (bcmsdh_osinfo->dev)
device_init_wakeup(bcmsdh_osinfo->dev, false);
bcmsdh_osinfo->dev_wake_enabled = FALSE;
#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
/* find the SDIO Host Controller state for this pdev and take it out from the list */
for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
if (sdhc->dev == (void *)dev) {
if (prev)
prev->next = sdhc->next;
else
sdhcinfo = NULL;
break;
}
prev = sdhc;
}
if (!sdhc) {
SDLX_MSG(("%s: failed\n", __FUNCTION__));
return 0;
}
/* release SDIO Host Controller info */
osh = sdhc->osh;
MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
osl_detach(osh);
#if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY)
dev_set_drvdata(dev, NULL);
#endif
drvinfo.remove(bcmsdh_osinfo->context);
MFREE(bcmsdh->osh, bcmsdh->os_cxt, sizeof(bcmsdh_os_info_t));
bcmsdh_detach(bcmsdh->osh, bcmsdh);
return 0;
}
#else /* BCMPLATFORM_BUS */
#if !defined(BCMLXSDMMC)
/* forward declarations for PCI probe and remove functions. */
static int __devinit bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void __devexit bcmsdh_pci_remove(struct pci_dev *pdev);
/**
* pci id table
*/
static struct pci_device_id bcmsdh_pci_devid[] __devinitdata = {
{ vendor: PCI_ANY_ID,
device: PCI_ANY_ID,
subvendor: PCI_ANY_ID,
subdevice: PCI_ANY_ID,
class: 0,
class_mask: 0,
driver_data: 0,
},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, bcmsdh_pci_devid);
/**
* SDIO Host Controller pci driver info
*/
static struct pci_driver bcmsdh_pci_driver = {
node: {},
name: "bcmsdh",
id_table: bcmsdh_pci_devid,
probe: bcmsdh_pci_probe,
remove: bcmsdh_pci_remove,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
save_state: NULL,
#endif
suspend: NULL,
resume: NULL,
};
extern uint sd_pci_slot; /* Force detection to a particular PCI */
/* slot only . Allows for having multiple */
/* WL devices at once in a PC */
/* Only one instance of dhd will be */
/* usable at a time */
/* Upper word is bus number, */
/* lower word is slot number */
/* Default value of 0xffffffff turns this */
/* off */
module_param(sd_pci_slot, uint, 0);
/**
* Detect supported SDIO Host Controller and attach if found.
*
* Determine if the device described by pdev is a supported SDIO Host
* Controller. If so, attach to it and attach to the target device.
*/
static int __devinit
bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int bcmsdh_suspend(bcmsdh_info_t *bcmsdh)
{
osl_t *osh = NULL;
bcmsdh_hc_t *sdhc = NULL;
ulong regs;
bcmsdh_info_t *sdh = NULL;
int rc;
if (sd_pci_slot != 0xFFFFffff) {
if (pdev->bus->number != (sd_pci_slot>>16) ||
PCI_SLOT(pdev->devfn) != (sd_pci_slot&0xffff)) {
SDLX_MSG(("%s: %s: bus %X, slot %X, vend %X, dev %X\n",
__FUNCTION__,
bcmsdh_chipmatch(pdev->vendor, pdev->device)
?"Found compatible SDIOHC"
:"Probing unknown device",
pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor,
pdev->device));
return -ENODEV;
}
SDLX_MSG(("%s: %s: bus %X, slot %X, vendor %X, device %X (good PCI location)\n",
__FUNCTION__,
bcmsdh_chipmatch(pdev->vendor, pdev->device)
?"Using compatible SDIOHC"
:"WARNING, forced use of unkown device",
pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device));
}
if ((pdev->vendor == VENDOR_TI) && ((pdev->device == PCIXX21_FLASHMEDIA_ID) ||
(pdev->device == PCIXX21_FLASHMEDIA0_ID))) {
uint32 config_reg;
SDLX_MSG(("%s: Disabling TI FlashMedia Controller.\n", __FUNCTION__));
if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
goto err;
}
config_reg = OSL_PCI_READ_CONFIG(osh, 0x4c, 4);
/*
* Set MMC_SD_DIS bit in FlashMedia Controller.
* Disbling the SD/MMC Controller in the FlashMedia Controller
* allows the Standard SD Host Controller to take over control
* of the SD Slot.
*/
config_reg |= 0x02;
OSL_PCI_WRITE_CONFIG(osh, 0x4c, 4, config_reg);
osl_detach(osh);
}
/* match this pci device with what we support */
/* we can't solely rely on this to believe it is our SDIO Host Controller! */
if (!bcmsdh_chipmatch(pdev->vendor, pdev->device)) {
if (pdev->vendor == VENDOR_BROADCOM) {
SDLX_MSG(("%s: Unknown Broadcom device (vendor: %#x, device: %#x).\n",
__FUNCTION__, pdev->vendor, pdev->device));
}
return -ENODEV;
}
/* this is a pci device we might support */
SDLX_MSG(("%s: Found possible SDIO Host Controller: bus %d slot %d func %d irq %d\n",
__FUNCTION__,
pdev->bus->number, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn), pdev->irq));
/* use bcmsdh_query_device() to get the vendor ID of the target device so
* it will eventually appear in the Broadcom string on the console
*/
/* allocate SDIO Host Controller state info */
if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
goto err;
}
if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) {
SDLX_MSG(("%s: out of memory, allocated %d bytes\n",
__FUNCTION__,
MALLOCED(osh)));
goto err;
}
bzero(sdhc, sizeof(bcmsdh_hc_t));
sdhc->osh = osh;
sdhc->dev = pdev;
/* map to address where host can access */
pci_set_master(pdev);
rc = pci_enable_device(pdev);
if (rc) {
SDLX_MSG(("%s: Cannot enable PCI device\n", __FUNCTION__));
goto err;
}
if (!(sdh = bcmsdh_attach(osh, (void *)(uintptr)pci_resource_start(pdev, 0),
(void **)&regs, pdev->irq))) {
SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
goto err;
}
sdhc->sdh = sdh;
/* try to attach to the target device */
if (!(sdhc->ch = drvinfo.attach(VENDOR_BROADCOM, /* pdev->vendor, */
bcmsdh_query_device(sdh) & 0xFFFF, 0, 0, 0, 0,
(void *)regs, NULL, sdh))) {
SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
goto err;
}
/* chain SDIO Host Controller info together */
sdhc->next = sdhcinfo;
sdhcinfo = sdhc;
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
if (drvinfo.suspend && drvinfo.suspend(bcmsdh_osinfo->context))
return -EBUSY;
return 0;
/* error handling */
err:
if (sdhc) {
if (sdhc->sdh)
bcmsdh_detach(sdhc->osh, sdhc->sdh);
MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
}
if (osh)
osl_detach(osh);
return -ENODEV;
}
/**
* Detach from target devices and SDIO Host Controller
*/
static void __devexit
bcmsdh_pci_remove(struct pci_dev *pdev)
int bcmsdh_resume(bcmsdh_info_t *bcmsdh)
{
bcmsdh_hc_t *sdhc, *prev;
osl_t *osh;
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
/* find the SDIO Host Controller state for this pdev and take it out from the list */
for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
if (sdhc->dev == pdev) {
if (prev)
prev->next = sdhc->next;
else
sdhcinfo = NULL;
break;
}
prev = sdhc;
}
if (!sdhc)
return;
drvinfo.detach(sdhc->ch);
bcmsdh_detach(sdhc->osh, sdhc->sdh);
/* release SDIO Host Controller info */
osh = sdhc->osh;
MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
osl_detach(osh);
if (drvinfo.resume)
return drvinfo.resume(bcmsdh_osinfo->context);
return 0;
}
#endif /* BCMLXSDMMC */
#endif /* BCMPLATFORM_BUS */
extern int sdio_function_init(void);
extern int bcmsdh_register_client_driver(void);
extern void bcmsdh_unregister_client_driver(void);
extern int sdio_func_reg_notify(void* semaphore);
extern void sdio_func_unreg_notify(void);
@ -519,176 +234,151 @@ bcmsdh_register(bcmsdh_driver_t *driver)
int error = 0;
drvinfo = *driver;
#if defined(BCMPLATFORM_BUS)
SDLX_MSG(("%s: Linux Kernel SDIO/MMC Driver\n", __FUNCTION__));
error = sdio_function_init();
return error;
#endif /* defined(BCMPLATFORM_BUS) */
#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
if (!(error = pci_module_init(&bcmsdh_pci_driver)))
return 0;
#else
if (!(error = pci_register_driver(&bcmsdh_pci_driver)))
return 0;
#endif
SDLX_MSG(("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error));
#endif /* BCMPLATFORM_BUS */
SDLX_MSG(("%s: register client driver\n", __FUNCTION__));
error = bcmsdh_register_client_driver();
if (error)
SDLX_MSG(("%s: failed %d\n", __FUNCTION__, error));
return error;
}
extern void sdio_function_cleanup(void);
void
bcmsdh_unregister(void)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
if (bcmsdh_pci_driver.node.next)
if (bcmsdh_pci_driver.node.next == NULL)
return;
#endif
#if defined(BCMLXSDMMC)
sdio_function_cleanup();
#endif /* BCMLXSDMMC */
#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
pci_unregister_driver(&bcmsdh_pci_driver);
#endif /* BCMPLATFORM_BUS */
bcmsdh_unregister_client_driver();
}
int bcmsdh_set_drvdata(void * dhdp)
void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *bcmsdh)
{
SDLX_MSG(("%s: Enter\n", __FUNCTION__));
#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
pm_stay_awake(bcmsdh_osinfo->dev);
#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
}
dev_set_drvdata(sdhcinfo->dev, dhdp);
void bcmsdh_dev_relax(bcmsdh_info_t *bcmsdh)
{
#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
pm_relax(bcmsdh_osinfo->dev);
#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */
}
return 0;
bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *bcmsdh)
{
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
return bcmsdh_osinfo->dev_wake_enabled;
}
#if defined(OOB_INTR_ONLY)
void bcmsdh_oob_intr_set(bool enable)
void bcmsdh_oob_intr_set(bcmsdh_info_t *bcmsdh, bool enable)
{
static bool curstate = 1;
unsigned long flags;
bcmsdh_os_info_t *bcmsdh_osinfo;
spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
if (curstate != enable) {
if (!bcmsdh)
return;
bcmsdh_osinfo = bcmsdh->os_cxt;
spin_lock_irqsave(&bcmsdh_osinfo->oob_irq_spinlock, flags);
if (bcmsdh_osinfo->oob_irq_enabled != enable) {
if (enable)
enable_irq(sdhcinfo->oob_irq);
enable_irq(bcmsdh_osinfo->oob_irq_num);
else
disable_irq_nosync(sdhcinfo->oob_irq);
curstate = enable;
disable_irq_nosync(bcmsdh_osinfo->oob_irq_num);
bcmsdh_osinfo->oob_irq_enabled = enable;
}
spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
spin_unlock_irqrestore(&bcmsdh_osinfo->oob_irq_spinlock, flags);
}
static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
{
dhd_pub_t *dhdp;
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)dev_id;
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
dhdp = (dhd_pub_t *)dev_get_drvdata(sdhcinfo->dev);
bcmsdh_oob_intr_set(0);
if (dhdp == NULL) {
SDLX_MSG(("%s: Out of band GPIO interrupt fired way too early\n",
__FUNCTION__));
return IRQ_HANDLED;
}
dhdsdio_isr((void *)dhdp->bus);
bcmsdh_oob_intr_set(bcmsdh, FALSE);
bcmsdh_osinfo->oob_irq_handler(bcmsdh_osinfo->oob_irq_handler_context);
return IRQ_HANDLED;
}
int bcmsdh_register_oob_intr(void * dhdp)
int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler,
void* oob_irq_handler_context)
{
int error = 0;
int err = 0;
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
SDLX_MSG(("%s: Enter \n", __FUNCTION__));
/* IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; */
dev_set_drvdata(sdhcinfo->dev, dhdp);
if (!sdhcinfo->oob_irq_registered) {
SDLX_MSG(("%s: IRQ=%d Type=%X \n", __FUNCTION__,
(int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags));
/* Refer to customer Host IRQ docs about proper irqflags definition */
error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, sdhcinfo->oob_flags,
"bcmsdh_sdmmc", NULL);
if (error)
return -ENODEV;
#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI)
if (device_may_wakeup(sdhcinfo->dev)) {
#endif
error = enable_irq_wake(sdhcinfo->oob_irq);
#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI)
}
#endif
if (error)
SDLX_MSG(("%s: enable_irq_wake error=%d \n", __FUNCTION__, error));
sdhcinfo->oob_irq_registered = TRUE;
sdhcinfo->oob_irq_enable_flag = TRUE;
}
return 0;
}
void bcmsdh_set_irq(int flag)
{
if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) {
SDLX_MSG(("%s: Flag = %d\n", __FUNCTION__, flag));
sdhcinfo->oob_irq_enable_flag = flag;
if (flag) {
enable_irq(sdhcinfo->oob_irq);
#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI)
if (device_may_wakeup(sdhcinfo->dev))
#endif
enable_irq_wake(sdhcinfo->oob_irq);
} else {
#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI)
if (device_may_wakeup(sdhcinfo->dev))
#endif
disable_irq_wake(sdhcinfo->oob_irq);
disable_irq(sdhcinfo->oob_irq);
}
}
}
void bcmsdh_unregister_oob_intr(void)
{
SDLX_MSG(("%s: Enter\n", __FUNCTION__));
if (sdhcinfo->oob_irq_registered == TRUE) {
bcmsdh_set_irq(FALSE);
free_irq(sdhcinfo->oob_irq, NULL);
sdhcinfo->oob_irq_registered = FALSE;
if (bcmsdh_osinfo->oob_irq_registered) {
SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__));
return -EBUSY;
}
SDLX_MSG(("%s OOB irq=%d flags=%X\n", __FUNCTION__,
(int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
bcmsdh_osinfo->oob_irq_handler = oob_irq_handler;
bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context;
#if defined(CONFIG_ARCH_ODIN)
err = odin_gpio_sms_request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
#else
err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
#endif /* defined(CONFIG_ARCH_ODIN) */
if (err) {
SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err));
return err;
}
#if defined(DISABLE_WOWLAN)
SDLX_MSG(("%s: disable_irq_wake\n", __FUNCTION__));
err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num);
if (err)
SDLX_MSG(("%s: disable_irq_wake failed with %d\n", __FUNCTION__, err));
else
bcmsdh_osinfo->oob_irq_wake_enabled = FALSE;
#else
SDLX_MSG(("%s: enable_irq_wake\n", __FUNCTION__));
err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num);
if (err)
SDLX_MSG(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err));
else
bcmsdh_osinfo->oob_irq_wake_enabled = TRUE;
#endif
bcmsdh_osinfo->oob_irq_enabled = TRUE;
bcmsdh_osinfo->oob_irq_registered = TRUE;
return err;
}
bool bcmsdh_is_oob_intr_registered(void)
void bcmsdh_oob_intr_unregister(bcmsdh_info_t *bcmsdh)
{
if (sdhcinfo)
return sdhcinfo->oob_irq_registered;
else
return FALSE;
int err = 0;
bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
SDLX_MSG(("%s: Enter\n", __FUNCTION__));
if (!bcmsdh_osinfo->oob_irq_registered) {
SDLX_MSG(("%s: irq is not registered\n", __FUNCTION__));
return;
}
if (bcmsdh_osinfo->oob_irq_wake_enabled) {
err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num);
if (!err)
bcmsdh_osinfo->oob_irq_wake_enabled = FALSE;
}
if (bcmsdh_osinfo->oob_irq_enabled) {
disable_irq(bcmsdh_osinfo->oob_irq_num);
bcmsdh_osinfo->oob_irq_enabled = FALSE;
}
free_irq(bcmsdh_osinfo->oob_irq_num, bcmsdh);
bcmsdh_osinfo->oob_irq_registered = FALSE;
}
#endif
#if defined(BCMLXSDMMC)
void *bcmsdh_get_drvdata(void)
{
if (!sdhcinfo)
return NULL;
return dev_get_drvdata(sdhcinfo->dev);
}
#endif
/* Module parameters specific to each host-controller driver */
extern uint sd_msglevel; /* Debug message level */
@ -719,11 +409,11 @@ extern uint sd_tuning_period;
module_param(sd_tuning_period, uint, 0);
extern int sd_delay_value;
module_param(sd_delay_value, uint, 0);
#endif
#ifdef BCMSDIOH_TXGLOM
extern uint sd_txglom;
module_param(sd_txglom, uint, 0);
/* SDIO Drive Strength for UHSI mode specific to SDIO3.0 */
extern char dhd_sdiod_uhsi_ds_override[2];
module_param_string(dhd_sdiod_uhsi_ds_override, dhd_sdiod_uhsi_ds_override, 2, 0);
#endif
#ifdef BCMSDH_MODULE

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
*
* Copyright (C) 1999-2013, Broadcom Corporation
* Copyright (C) 1999-2014, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
* $Id: bcmsdh_sdmmc_linux.c 404103 2013-05-23 20:07:27Z $
* $Id: bcmsdh_sdmmc_linux.c 434777 2013-11-07 09:30:27Z $
*/
#include <typedefs.h>
@ -34,9 +34,12 @@
#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <dhd_config.h>
#include <dhd_linux.h>
#include <bcmsdh_sdmmc.h>
#include <dhd_dbg.h>
#if !defined(SDIO_VENDOR_ID_BROADCOM)
#define SDIO_VENDOR_ID_BROADCOM 0x02d0
@ -69,20 +72,12 @@
#define SDIO_DEVICE_ID_BROADCOM_43239 43239
#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_43239) */
#include <bcmsdh_sdmmc.h>
#include <dhd_dbg.h>
#ifdef WL_CFG80211
extern void wl_cfg80211_set_parent_dev(void *dev);
#endif
extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
extern int dhd_os_check_wakelock(void *dhdp);
extern int dhd_os_check_if_up(void *dhdp);
extern void *bcmsdh_get_drvdata(void);
extern void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bus_type,
uint bus_num, uint slot_num);
extern int bcmsdh_remove(bcmsdh_info_t *bcmsdh);
int sdio_function_init(void);
void sdio_function_cleanup(void);
@ -101,82 +96,111 @@ PBCMSDH_SDMMC_INSTANCE gInstance;
/* Maximum number of bcmsdh_sdmmc devices supported by driver */
#define BCMSDH_SDMMC_MAX_DEVICES 1
extern int bcmsdh_probe(struct device *dev);
extern int bcmsdh_remove(struct device *dev);
extern volatile bool dhd_mmc_suspend;
static int sdioh_probe(struct sdio_func *func)
{
int host_idx = func->card->host->index;
uint32 rca = func->card->rca;
wifi_adapter_info_t *adapter;
osl_t *osh = NULL;
sdioh_info_t *sdioh = NULL;
sd_err(("bus num (host idx)=%d, slot num (rca)=%d\n", host_idx, rca));
adapter = dhd_wifi_platform_get_adapter(SDIO_BUS, host_idx, rca);
if (adapter != NULL)
sd_err(("found adapter info '%s'\n", adapter->name));
else
sd_err(("can't find adapter info for this chip\n"));
#ifdef WL_CFG80211
wl_cfg80211_set_parent_dev(&func->dev);
#endif
/* allocate SDIO Host Controller state info */
osh = osl_attach(&func->dev, SDIO_BUS, TRUE);
if (osh == NULL) {
sd_err(("%s: osl_attach failed\n", __FUNCTION__));
goto fail;
}
osl_static_mem_init(osh, adapter);
sdioh = sdioh_attach(osh, func);
if (sdioh == NULL) {
sd_err(("%s: sdioh_attach failed\n", __FUNCTION__));
goto fail;
}
sdioh->bcmsdh = bcmsdh_probe(osh, &func->dev, sdioh, adapter, SDIO_BUS, host_idx, rca);
if (sdioh->bcmsdh == NULL) {
sd_err(("%s: bcmsdh_probe failed\n", __FUNCTION__));
goto fail;
}
sdio_set_drvdata(func, sdioh);
return 0;
fail:
if (sdioh != NULL)
sdioh_detach(osh, sdioh);
if (osh != NULL)
osl_detach(osh);
return -ENOMEM;
}
static void sdioh_remove(struct sdio_func *func)
{
sdioh_info_t *sdioh;
osl_t *osh;
sdioh = sdio_get_drvdata(func);
if (sdioh == NULL) {
sd_err(("%s: error, no sdioh handler found\n", __FUNCTION__));
return;
}
osh = sdioh->osh;
bcmsdh_remove(sdioh->bcmsdh);
sdioh_detach(osh, sdioh);
osl_detach(osh);
}
static int bcmsdh_sdmmc_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
int ret = 0;
static struct sdio_func sdio_func_0;
if (!gInstance)
if (func == NULL)
return -EINVAL;
if (func) {
sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class));
sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
sd_trace(("sdio_device: 0x%04x\n", func->device));
sd_trace(("Function#: 0x%04x\n", func->num));
sd_err(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
sd_info(("sdio_device: 0x%04x\n", func->device));
sd_info(("Function#: 0x%04x\n", func->num));
if (func->num == 1) {
sdio_func_0.num = 0;
sdio_func_0.card = func->card;
gInstance->func[0] = &sdio_func_0;
if(func->device == 0x4) { /* 4318 */
gInstance->func[2] = NULL;
sd_trace(("NIC found, calling bcmsdh_probe...\n"));
ret = bcmsdh_probe(&func->dev);
}
}
gInstance->func[func->num] = func;
gInstance->func[func->num] = func;
if (func->num == 2) {
#ifdef WL_CFG80211
wl_cfg80211_set_parent_dev(&func->dev);
#endif
sd_trace(("F2 found, calling bcmsdh_probe...\n"));
ret = bcmsdh_probe(&func->dev);
if (ret < 0)
gInstance->func[2] = NULL;
}
} else {
ret = -ENODEV;
}
#ifdef POWER_OFF_IN_SUSPEND
dhd_conf_register_wifi_suspend(func);
#endif
/* 4318 doesn't have function 2 */
if ((func->num == 2) || (func->num == 1 && func->device == 0x4))
ret = sdioh_probe(func);
return ret;
}
static void bcmsdh_sdmmc_remove(struct sdio_func *func)
{
if (func) {
sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
sd_info(("sdio_device: 0x%04x\n", func->device));
sd_info(("Function#: 0x%04x\n", func->num));
#ifdef POWER_OFF_IN_SUSPEND
dhd_conf_unregister_wifi_suspend(func);
#endif
if (gInstance->func[2]) {
sd_trace(("F2 found, calling bcmsdh_remove...\n"));
bcmsdh_remove(&func->dev);
gInstance->func[2] = NULL;
}
if (func->num == 1) {
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
gInstance->func[1] = NULL;
}
if (func == NULL) {
sd_err(("%s is called with NULL SDIO function pointer\n", __FUNCTION__));
return;
}
sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
sd_info(("sdio_device: 0x%04x\n", func->device));
sd_info(("Function#: 0x%04x\n", func->num));
if ((func->num == 2) || (func->num == 1 && func->device == 0x4))
sdioh_remove(func);
}
/* devices we support, null terminated */
@ -199,62 +223,63 @@ MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM)
static int bcmsdh_sdmmc_suspend(struct device *pdev)
{
int err;
sdioh_info_t *sdioh;
struct sdio_func *func = dev_to_sdio_func(pdev);
#ifndef POWER_OFF_IN_SUSPEND
mmc_pm_flag_t sdio_flags;
int ret;
#endif
printk("%s Enter\n", __FUNCTION__);
if (func->num != 2)
return 0;
sd_trace(("%s Enter\n", __FUNCTION__));
if (dhd_os_check_wakelock(bcmsdh_get_drvdata()))
return -EBUSY;
sdioh = sdio_get_drvdata(func);
err = bcmsdh_suspend(sdioh->bcmsdh);
if (err) {
printk("%s bcmsdh_suspend err=%d\n", __FUNCTION__, err);
return err;
}
#ifdef POWER_OFF_IN_SUSPEND
dhd_conf_wifi_suspend(func);
#else
sdio_flags = sdio_get_host_pm_caps(func);
if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
sd_err(("%s: can't keep power while host is suspended\n", __FUNCTION__));
return -EINVAL;
}
/* keep power while host suspended */
ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
if (ret) {
err = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
if (err) {
sd_err(("%s: error while trying to keep power\n", __FUNCTION__));
return ret;
return err;
}
#if defined(OOB_INTR_ONLY)
bcmsdh_oob_intr_set(0);
#endif
bcmsdh_oob_intr_set(sdioh->bcmsdh, FALSE);
#endif
dhd_mmc_suspend = TRUE;
smp_mb();
printk("%s Exit\n", __FUNCTION__);
return 0;
}
static int bcmsdh_sdmmc_resume(struct device *pdev)
{
#if defined(OOB_INTR_ONLY) || defined(POWER_OFF_IN_SUSPEND)
struct sdio_func *func = dev_to_sdio_func(pdev);
#endif
sd_trace(("%s Enter\n", __FUNCTION__));
dhd_mmc_suspend = FALSE;
#ifdef POWER_OFF_IN_SUSPEND
gInstance->func[func->num] = func;
#else
#if defined(OOB_INTR_ONLY)
if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata()))
bcmsdh_oob_intr_set(1);
#endif
sdioh_info_t *sdioh;
#endif
struct sdio_func *func = dev_to_sdio_func(pdev);
printk("%s Enter\n", __FUNCTION__);
if (func->num != 2)
return 0;
dhd_mmc_suspend = FALSE;
#if defined(OOB_INTR_ONLY)
sdioh = sdio_get_drvdata(func);
bcmsdh_resume(sdioh->bcmsdh);
#endif
smp_mb();
printk("%s Exit\n", __FUNCTION__);
return 0;
}
@ -266,10 +291,14 @@ static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = {
#if defined(BCMLXSDMMC)
static struct semaphore *notify_semaphore = NULL;
/*
static int dummy_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
if (func && (func->num != 2)) {
return 0;
}
if (notify_semaphore)
up(notify_semaphore);
return 0;
@ -285,19 +314,17 @@ static struct sdio_driver dummy_sdmmc_driver = {
.name = "dummy_sdmmc",
.id_table = bcmsdh_sdmmc_ids,
};
*/
int sdio_func_reg_notify(void* semaphore)
{
notify_semaphore = semaphore;
if (notify_semaphore)
up(notify_semaphore);
return 0;
//return sdio_register_driver(&dummy_sdmmc_driver);
return sdio_register_driver(&dummy_sdmmc_driver);
}
void sdio_func_unreg_notify(void)
{
//sdio_unregister_driver(&dummy_sdmmc_driver);
OSL_SLEEP(15);
sdio_unregister_driver(&dummy_sdmmc_driver);
}
#endif /* defined(BCMLXSDMMC) */
@ -319,73 +346,17 @@ struct sdos_info {
spinlock_t lock;
};
int
sdioh_sdmmc_osinit(sdioh_info_t *sd)
{
struct sdos_info *sdos;
if (!sd)
return BCME_BADARG;
sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info));
sd->sdos_info = (void*)sdos;
if (sdos == NULL)
return BCME_NOMEM;
sdos->sd = sd;
spin_lock_init(&sdos->lock);
return BCME_OK;
}
void
sdioh_sdmmc_osfree(sdioh_info_t *sd)
{
struct sdos_info *sdos;
ASSERT(sd && sd->sdos_info);
sdos = (struct sdos_info *)sd->sdos_info;
MFREE(sd->osh, sdos, sizeof(struct sdos_info));
}
/* Interrupt enable/disable */
SDIOH_API_RC
sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
{
ulong flags;
struct sdos_info *sdos;
if (!sd)
return BCME_BADARG;
sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling"));
sdos = (struct sdos_info *)sd->sdos_info;
ASSERT(sdos);
#if !defined(OOB_INTR_ONLY)
if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__));
return SDIOH_API_RC_FAIL;
}
#endif /* !defined(OOB_INTR_ONLY) */
/* Ensure atomicity for enable/disable calls */
spin_lock_irqsave(&sdos->lock, flags);
sd->client_intr_enabled = enable;
if (enable) {
sdioh_sdmmc_devintr_on(sd);
} else {
sdioh_sdmmc_devintr_off(sd);
}
spin_unlock_irqrestore(&sdos->lock, flags);
return SDIOH_API_RC_SUCCESS;
}
#ifdef BCMSDH_MODULE
static int __init
bcmsdh_module_init(void)
@ -412,37 +383,21 @@ MODULE_AUTHOR(AUTHOR);
/*
* module init
*/
int sdio_function_init(void)
int bcmsdh_register_client_driver(void)
{
int error = 0;
sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
gInstance = kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL);
if (!gInstance)
return -ENOMEM;
error = sdio_register_driver(&bcmsdh_sdmmc_driver);
if (error) {
kfree(gInstance);
gInstance = NULL;
}
return error;
return sdio_register_driver(&bcmsdh_sdmmc_driver);
}
/*
* module cleanup
*/
extern int bcmsdh_remove(struct device *dev);
void sdio_function_cleanup(void)
void bcmsdh_unregister_client_driver(void)
{
sd_trace(("%s Enter\n", __FUNCTION__));
sdio_unregister_driver(&bcmsdh_sdmmc_driver);
if (gInstance) {
if (gInstance)
kfree(gInstance);
gInstance = NULL;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,324 @@
/** @file circularbuf.c
*
* PCIe host driver and dongle firmware need to communicate with each other. The mechanism consists
* of multiple circular buffers located in (DMA'able) host memory. A circular buffer is either used
* for host -> dongle (h2d) or dongle -> host communication. Both host driver and firmware make use
* of this source file. This source file contains functions to manage such a set of circular
* buffers, but does not contain the code to read or write the data itself into the buffers. It
* leaves that up to the software layer that uses this file, which can be implemented either using
* pio or DMA transfers. It also leaves the format of the data that is written and read to a higher
* layer. Typically the data is in the form of so-called 'message buffers'.
*
* $Copyright Open Broadcom Corporation$
*
* $Id: circularbuf.c 467150 2014-04-02 17:30:43Z $
*/
#include <circularbuf.h>
#include <bcmmsgbuf.h>
#include <osl.h>
#define CIRCULARBUF_READ_SPACE_AT_END(x) \
((x->w_ptr >= x->rp_ptr) ? (x->w_ptr - x->rp_ptr) : (x->e_ptr - x->rp_ptr))
#define CIRCULARBUF_READ_SPACE_AVAIL(x) \
(((CIRCULARBUF_READ_SPACE_AT_END(x) == 0) && (x->w_ptr < x->rp_ptr)) ? \
x->w_ptr : CIRCULARBUF_READ_SPACE_AT_END(x))
int cbuf_msg_level = CBUF_ERROR_VAL | CBUF_TRACE_VAL | CBUF_INFORM_VAL;
/* #define CBUF_DEBUG */
#ifdef CBUF_DEBUG
#define CBUF_DEBUG_CHECK(x) x
#else
#define CBUF_DEBUG_CHECK(x)
#endif /* CBUF_DEBUG */
/**
* -----------------------------------------------------------------------------
* Function : circularbuf_init
* Description:
*
*
* Input Args : buf_base_addr: address of DMA'able host memory provided by caller
*
*
* Return Values :
*
* -----------------------------------------------------------------------------
*/
void
circularbuf_init(circularbuf_t *handle, void *buf_base_addr, uint16 total_buf_len)
{
handle->buf_addr = buf_base_addr;
handle->depth = handle->e_ptr = HTOL32(total_buf_len);
/* Initialize Read and Write pointers */
handle->w_ptr = handle->r_ptr = handle->wp_ptr = handle->rp_ptr = HTOL32(0);
handle->mb_ring_bell = NULL;
handle->mb_ctx = NULL;
return;
}
/**
* When an item is added to the circular buffer by the producing party, the consuming party has to
* be notified by means of a 'door bell' or 'ring'. This function allows the caller to register a
* 'ring' function that will be called when a 'write complete' occurs.
*/
void
circularbuf_register_cb(circularbuf_t *handle, mb_ring_t mb_ring_func, void *ctx)
{
handle->mb_ring_bell = mb_ring_func;
handle->mb_ctx = ctx;
}
#ifdef CBUF_DEBUG
static void
circularbuf_check_sanity(circularbuf_t *handle)
{
if ((handle->e_ptr > handle->depth) ||
(handle->r_ptr > handle->e_ptr) ||
(handle->rp_ptr > handle->e_ptr) ||
(handle->w_ptr > handle->e_ptr))
{
printf("%s:%d: Pointers are corrupted.\n", __FUNCTION__, __LINE__);
circularbuf_debug_print(handle);
ASSERT(0);
}
return;
}
#endif /* CBUF_DEBUG */
/**
* -----------------------------------------------------------------------------
* Function : circularbuf_reserve_for_write
*
* Description:
* This function reserves N bytes for write in the circular buffer. The circularbuf
* implementation will only reserve space in the circular buffer and return
* the pointer to the address where the new data can be written.
* The actual write implementation (bcopy/dma) is outside the scope of
* circularbuf implementation.
*
* Input Args :
* size - No. of bytes to reserve for write
*
* Return Values :
* void * : Pointer to the reserved location. This is the address
* that will be used for write (dma/bcopy)
*
* -----------------------------------------------------------------------------
*/
void * BCMFASTPATH
circularbuf_reserve_for_write(circularbuf_t *handle, uint16 size)
{
int16 avail_space;
void *ret_ptr = NULL;
CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
ASSERT(size < handle->depth);
if (handle->wp_ptr >= handle->r_ptr)
avail_space = handle->depth - handle->wp_ptr;
else
avail_space = handle->r_ptr - handle->wp_ptr;
ASSERT(avail_space <= handle->depth);
if (avail_space > size)
{
/* Great. We have enough space. */
ret_ptr = CIRCULARBUF_START(handle) + handle->wp_ptr;
/*
* We need to update the wp_ptr for the next guy to write.
*
* Please Note : We are not updating the write pointer here. This can be
* done only after write is complete (In case of DMA, we can only schedule
* the DMA. Actual completion will be known only on DMA complete interrupt).
*/
handle->wp_ptr += size;
return ret_ptr;
}
/*
* If there is no available space, we should check if there is some space left
* in the beginning of the circular buffer. Wrap-around case, where there is
* not enough space in the end of the circular buffer. But, there might be
* room in the beginning of the buffer.
*/
if (handle->wp_ptr >= handle->r_ptr)
{
avail_space = handle->r_ptr;
if (avail_space > size)
{
/* OK. There is room in the beginning. Let's go ahead and use that.
* But, before that, we have left a hole at the end of the circular
* buffer as that was not sufficient to accomodate the requested
* size. Let's make sure this is updated in the circularbuf structure
* so that consumer does not use the hole.
*/
handle->e_ptr = handle->wp_ptr;
handle->wp_ptr = size;
return CIRCULARBUF_START(handle);
}
}
/* We have tried enough to accomodate the new packet. There is no room for now. */
return NULL;
}
/**
* -----------------------------------------------------------------------------
* Function : circularbuf_write_complete
*
* Description:
* This function has to be called by the producer end of circularbuf to indicate to
* the circularbuf layer that data has been written and the write pointer can be
* updated. In the process, if there was a doorbell callback registered, that
* function would also be invoked as to notify the consuming party.
*
* Input Args :
* dest_addr : Address where the data was written. This would be the
* same address that was reserved earlier.
* bytes_written : Length of data written
*
* -----------------------------------------------------------------------------
*/
void BCMFASTPATH
circularbuf_write_complete(circularbuf_t *handle, uint16 bytes_written)
{
CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
/* Update the write pointer */
if ((handle->w_ptr + bytes_written) >= handle->depth) {
OSL_CACHE_FLUSH((void *) CIRCULARBUF_START(handle), bytes_written);
handle->w_ptr = bytes_written;
} else {
OSL_CACHE_FLUSH((void *) (CIRCULARBUF_START(handle) + handle->w_ptr),
bytes_written);
handle->w_ptr += bytes_written;
}
/* And ring the door bell (mail box interrupt) to indicate to the peer that
* message is available for consumption.
*/
if (handle->mb_ring_bell)
handle->mb_ring_bell(handle->mb_ctx);
}
/**
* -----------------------------------------------------------------------------
* Function : circularbuf_get_read_ptr
*
* Description:
* This function will be called by the consumer of circularbuf for reading data from
* the circular buffer. This will typically be invoked when the consumer gets a
* doorbell interrupt.
* Please note that the function only returns the pointer (and length) from
* where the data can be read. Actual read implementation is up to the
* consumer. It could be a bcopy or dma.
*
* Input Args :
* void * : Address from where the data can be read.
* available_len : Length of data available for read.
*
* -----------------------------------------------------------------------------
*/
void * BCMFASTPATH
circularbuf_get_read_ptr(circularbuf_t *handle, uint16 *available_len)
{
uint8 *ret_addr;
CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
/* First check if there is any data available in the circular buffer */
*available_len = CIRCULARBUF_READ_SPACE_AVAIL(handle);
if (*available_len == 0)
return NULL;
/*
* Although there might be data in the circular buffer for read, in
* cases of write wrap-around and read still in the end of the circular
* buffer, we might have to wrap around the read pending pointer also.
*/
if (CIRCULARBUF_READ_SPACE_AT_END(handle) == 0)
handle->rp_ptr = 0;
ret_addr = CIRCULARBUF_START(handle) + handle->rp_ptr;
/*
* Please note that we do not update the read pointer here. Only
* read pending pointer is updated, so that next reader knows where
* to read data from.
* read pointer can only be updated when the read is complete.
*/
handle->rp_ptr = (uint16)(ret_addr - CIRCULARBUF_START(handle) + *available_len);
ASSERT(*available_len <= handle->depth);
OSL_CACHE_INV((void *) ret_addr, *available_len);
return ret_addr;
}
/**
* -----------------------------------------------------------------------------
* Function : circularbuf_read_complete
* Description:
* This function has to be called by the consumer end of circularbuf to indicate
* that data has been consumed and the read pointer can be updated, so the producing side
* can can use the freed space for new entries.
*
*
* Input Args :
* bytes_read : No. of bytes consumed by the consumer. This has to match
* the length returned by circularbuf_get_read_ptr
*
* Return Values :
* CIRCULARBUF_SUCCESS : Otherwise
*
* -----------------------------------------------------------------------------
*/
circularbuf_ret_t BCMFASTPATH
circularbuf_read_complete(circularbuf_t *handle, uint16 bytes_read)
{
CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
ASSERT(bytes_read < handle->depth);
/* Update the read pointer */
if ((handle->w_ptr < handle->e_ptr) && (handle->r_ptr + bytes_read) > handle->e_ptr)
handle->r_ptr = bytes_read;
else
handle->r_ptr += bytes_read;
return CIRCULARBUF_SUCCESS;
}
/**
* -----------------------------------------------------------------------------
* Function : circularbuf_revert_rp_ptr
*
* Description:
* The rp_ptr update during circularbuf_get_read_ptr() is done to reflect the amount of data
* that is sent out to be read by the consumer. But the consumer may not always read the
* entire data. In such a case, the rp_ptr needs to be reverted back by 'left' bytes, where
* 'left' is the no. of bytes left unread.
*
* Input args:
* bytes : The no. of bytes left unread by the consumer
*
* -----------------------------------------------------------------------------
*/
circularbuf_ret_t
circularbuf_revert_rp_ptr(circularbuf_t *handle, uint16 bytes)
{
CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle));
ASSERT(bytes < handle->depth);
handle->rp_ptr -= bytes;
return CIRCULARBUF_SUCCESS;
}

View File

@ -6,7 +6,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd.h 419132 2013-08-19 21:33:05Z $
* $Id: dhd.h 491170 2014-07-15 06:23:58Z $
*/
/****************
@ -25,7 +25,6 @@
#include <linux/random.h>
#include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
@ -35,16 +34,22 @@
struct task_struct;
struct sched_param;
int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
int get_scheduler_policy(struct task_struct *p);
#define MAX_EVENT 16
#define ALL_INTERFACES 0xff
#include <wlioctl.h>
#include <wlfc_proto.h>
#if defined(NDISVER) && (NDISVER >= 0x0600)
#if defined(BCMWDF)
#include <wdf.h>
#include <WdfMiniport.h>
#endif /* (NDISVER >= 0x0600) */
#endif /* (BCMWDF) */
#if defined(WL11U) && !defined(MFP)
#define MFP /* Applying interaction with MFP by spec HS2.0 REL2 */
#endif /* WL11U */
#if defined(KEEP_ALIVE)
/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
@ -56,13 +61,13 @@ struct dhd_bus;
struct dhd_prot;
struct dhd_info;
struct dhd_ioctl;
struct dhd_cmn;
/* The level of bus communication with the dongle */
enum dhd_bus_state {
DHD_BUS_DOWN, /* Not ready for frame transfers */
DHD_BUS_LOAD, /* Download access only (CPU reset) */
DHD_BUS_DATA /* Ready for frame transfers */
DHD_BUS_DATA, /* Ready for frame transfers */
DHD_BUS_SUSPEND, /* Bus has been suspended */
};
#if defined(NDISVER) && (NDISVER >= 0x0600)
@ -76,6 +81,11 @@ enum dhd_bus_state {
#define CONCURENT_MASK 0x00F0
#endif /* (NDISVER >= 0x0600) */
/* For supporting multiple interfaces */
#define DHD_MAX_IFS 16
#define DHD_DEL_IF -0xE
#define DHD_BAD_IF -0xF
enum dhd_op_flags {
/* Firmware requested operation mode */
DHD_FLAG_STA_MODE = (1 << (0)), /* STA only */
@ -88,11 +98,10 @@ enum dhd_op_flags {
DHD_FLAG_P2P_GC_MODE = (1 << (5)),
DHD_FLAG_P2P_GO_MODE = (1 << (6)),
DHD_FLAG_MBSS_MODE = (1 << (7)), /* MBSS in future */
DHD_FLAG_IBSS_MODE = (1 << (8))
DHD_FLAG_IBSS_MODE = (1 << (8)),
DHD_FLAG_MFG_MODE = (1 << (9))
};
#define MANUFACTRING_FW "WLTEST"
/* Max sequential TX/RX Control timeouts to set HANG event */
#ifndef MAX_CNTL_TX_TIMEOUT
#define MAX_CNTL_TX_TIMEOUT 2
@ -109,7 +118,7 @@ enum dhd_op_flags {
#define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */
#endif
#ifndef POWERUP_WAIT_MS
#define POWERUP_WAIT_MS 5000 /* ms: time out in waiting wifi to come up */
#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */
#endif
enum dhd_bus_wake_state {
@ -139,36 +148,6 @@ enum dhd_prealloc_index {
DHD_PREALLOC_DHD_INFO = 7
};
typedef enum {
DHD_IF_NONE = 0,
DHD_IF_ADD,
DHD_IF_DEL,
DHD_IF_CHANGE,
DHD_IF_DELETING
} dhd_if_state_t;
typedef enum {
DHD_IPV6_ADDR_NONE = 0,
DHD_IPV6_ADDR_ADD,
DHD_IPV6_ADDR_DELETE
} dhd_ipv6_op_t;
#if defined(CONFIG_DHD_USE_STATIC_BUF)
uint8* dhd_os_prealloc(void *osh, int section, uint size);
void dhd_os_prefree(void *osh, void *addr, uint size);
#define DHD_OS_PREALLOC(osh, section, size) dhd_os_prealloc(osh, section, size)
#define DHD_OS_PREFREE(osh, addr, size) dhd_os_prefree(osh, addr, size)
#else
#define DHD_OS_PREALLOC(osh, section, size) MALLOC(osh, size)
#define DHD_OS_PREFREE(osh, addr, size) MFREE(osh, addr, size)
#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */
/* Packet alignment for most efficient SDIO (can change based on platform) */
#ifndef DHD_SDALIGN
#define DHD_SDALIGN 32
@ -186,18 +165,44 @@ typedef struct reorder_info {
} reorder_info_t;
#ifdef DHDTCPACK_SUPPRESS
#define MAXTCPSTREAMS 4 /* Keep this to be power of 2 */
typedef struct tcp_ack_info {
void *p_tcpackinqueue;
uint32 tcpack_number;
uint ip_tcp_ttllen;
uint8 ipaddrs[8]; /* Each 4bytes src and dst IP addrs */
uint8 tcpports[4]; /* Each 2bytes src and dst port number */
} tcp_ack_info_t;
void dhd_onoff_tcpack_sup(void *pub, bool on);
enum {
/* TCPACK suppress off */
TCPACK_SUP_OFF,
/* Replace TCPACK in txq when new coming one has higher ACK number. */
TCPACK_SUP_REPLACE,
/* TCPACK_SUP_REPLACE + delayed TCPACK TX unless ACK to PSH DATA.
* This will give benefits to Half-Duplex bus interface(e.g. SDIO) that
* 1. we are able to read TCP DATA packets first from the bus
* 2. TCPACKs that don't need to hurry delivered remains longer in TXQ so can be suppressed.
*/
TCPACK_SUP_DELAYTX,
TCPACK_SUP_LAST_MODE
};
#endif /* DHDTCPACK_SUPPRESS */
/* DMA'ing r/w indices for rings supported */
#ifdef BCM_INDX_TCM /* FW gets r/w indices in TCM */
#define DMA_INDX_ENAB(dma_indxsup) 0
#elif defined BCM_INDX_DMA /* FW gets r/w indices from Host memory */
#define DMA_INDX_ENAB(dma_indxsup) 1
#else /* r/w indices in TCM or host memory based on FW/Host agreement */
#define DMA_INDX_ENAB(dma_indxsup) dma_indxsup
#endif /* BCM_INDX_TCM */
#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE)
struct tdls_peer_node {
uint8 addr[ETHER_ADDR_LEN];
struct tdls_peer_node *next;
};
typedef struct tdls_peer_node tdls_peer_node_t;
typedef struct {
tdls_peer_node_t *node;
uint8 tdls_peer_count;
} tdls_peer_tbl_t;
#endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */
/* Common structure for module and instance linkage */
typedef struct dhd_pub {
/* Linkage ponters */
@ -205,7 +210,11 @@ typedef struct dhd_pub {
struct dhd_bus *bus; /* Bus module handle */
struct dhd_prot *prot; /* Protocol module handle */
struct dhd_info *info; /* Info module handle */
struct dhd_cmn *cmn; /* dhd_common module handle */
/* to NDIS developer, the structure dhd_common is redundant,
* please do NOT merge it back from other branches !!!
*/
/* Internal dhd items */
bool up; /* Driver up/down (to OS) */
@ -225,6 +234,7 @@ typedef struct dhd_pub {
/* Additional stats for the bus level */
ulong tx_packets; /* Data packets sent to dongle */
ulong tx_dropped; /* Data packets dropped in dhd */
ulong tx_multicast; /* Multicast data packets sent to dongle */
ulong tx_errors; /* Errors in sending data to dongle */
ulong tx_ctlpkts; /* Control packets sent to dongle */
@ -254,6 +264,10 @@ typedef struct dhd_pub {
/* Suspend disable flag and "in suspend" flag */
int suspend_disable_flag; /* "1" to disable all extra powersaving during suspend */
int in_suspend; /* flag set to 1 when early suspend called */
#ifdef PNO_SUPPORT
int pno_enable; /* pno status : "1" is pno enable */
int pno_suspend; /* pno suspend status : "1" is pno suspended */
#endif /* PNO_SUPPORT */
/* DTIM skip value, default 0(or 1) means wake each DTIM
* 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3)
*/
@ -286,20 +300,33 @@ typedef struct dhd_pub {
uint16 maxdatablks;
#endif /* WLBTAMP */
#ifdef PROP_TXSTATUS
int wlfc_enabled;
bool wlfc_enabled;
int wlfc_mode;
void* wlfc_state;
int ptx_opt_enabled;
bool pending_tx_pkts;
/*
Mode in which the dhd flow control shall operate. Must be set before
traffic starts to the device.
0 - Do not do any proptxtstatus flow control
1 - Use implied credit from a packet status
2 - Use explicit credit
3 - Only AMPDU hostreorder used. no wlfc.
*/
uint8 proptxstatus_mode;
bool proptxstatus_txoff;
bool proptxstatus_module_ignore;
bool proptxstatus_credit_ignore;
bool proptxstatus_txstatus_ignore;
bool wlfc_rxpkt_chk;
/*
* implement below functions in each platform if needed.
*/
/* platform specific function whether to skip flow control */
bool (*skip_fc)(void);
/* platform specific function for wlfc_enable and wlfc_deinit */
void (*plat_enable)(void *dhd);
void (*plat_init)(void *dhd);
void (*plat_deinit)(void *dhd);
#endif
#endif /* PROP_TXSTATUS */
#ifdef PNO_SUPPORT
void *pno_state;
#endif
@ -317,28 +344,68 @@ typedef struct dhd_pub {
#endif
struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS];
char fw_capabilities[WLC_IOCTL_SMLEN];
#ifdef RXFRAME_THREAD
#define MAXSKBPEND 1024
#define MAXSKBPEND 1024
void *skbbuf[MAXSKBPEND];
uint32 store_idx;
uint32 sent_idx;
#endif /* RXFRAME_THREAD */
#ifdef DHDTCPACK_SUPPRESS
int tcp_ack_info_cnt;
tcp_ack_info_t tcp_ack_info_tbl[MAXTCPSTREAMS];
uint8 tcpack_sup_mode; /* TCPACK suppress mode */
void *tcpack_sup_module; /* TCPACK suppress module */
#endif /* DHDTCPACK_SUPPRESS */
#if defined(ARP_OFFLOAD_SUPPORT)
uint32 arp_version;
#endif
#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X)
bool fw_4way_handshake; /* Whether firmware will to do the 4way handshake. */
#endif
#ifdef CUSTOM_SET_CPUCORE
struct task_struct * current_dpc;
struct task_struct * current_rxf;
int chan_isvht80;
#endif /* CUSTOM_SET_CPUCORE */
void *sta_pool; /* pre-allocated pool of sta objects */
void *staid_allocator; /* allocator of sta indexes */
void *flowid_allocator; /* unique flowid allocator */
void *flow_ring_table; /* flow ring table, include prot and bus info */
void *if_flow_lkup; /* per interface flowid lkup hash table */
uint32 num_flow_rings;
uint8 flow_prio_map[NUMPRIO];
uint8 flow_prio_map_type;
char enable_log[MAX_EVENT];
bool dma_d2h_ring_upd_support;
bool dma_h2d_ring_upd_support;
#ifdef DHD_WMF
bool wmf_ucast_igmp;
#ifdef DHD_IGMP_UCQUERY
bool wmf_ucast_igmp_query;
#endif
#ifdef DHD_UCAST_UPNP
bool wmf_ucast_upnp;
#endif
#endif /* DHD_WMF */
#ifdef DHD_UNICAST_DHCP
bool dhcp_unicast;
#endif /* DHD_UNICAST_DHCP */
#ifdef DHD_L2_FILTER
bool block_ping;
#endif
#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE)
tdls_peer_tbl_t peer_tbl;
#endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */
char *conf_path; /* module_param: path to config vars file */
struct dhd_conf *conf; /* Bus module handle */
} dhd_pub_t;
typedef struct dhd_cmn {
osl_t *osh; /* OSL handle */
dhd_pub_t *dhd;
} dhd_cmn_t;
#if defined(BCMWDF)
typedef struct {
dhd_pub_t *dhd_pub;
} dhd_workitem_context_t;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(dhd_workitem_context_t, dhd_get_dhd_workitem_context)
#endif /* (BCMWDF) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
@ -353,7 +420,18 @@ typedef struct dhd_cmn {
} while (0)
#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200)
#define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
#define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0)
#ifdef CUSTOMER_HW4
#define DHD_PM_RESUME_RETURN_ERROR(a) do { \
if (dhd_mmc_suspend) { \
printf("%s[%d]: mmc is still in suspend state!!!\n", \
__FUNCTION__, __LINE__); \
return a; \
} \
} while (0)
#else
#define DHD_PM_RESUME_RETURN_ERROR(a) do { \
if (dhd_mmc_suspend) return a; } while (0)
#endif
#define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0)
#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
@ -383,10 +461,6 @@ typedef struct dhd_cmn {
} while (0)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
#ifndef DHDTHREAD
#undef SPINWAIT_SLEEP
#define SPINWAIT_SLEEP(a, exp, us) SPINWAIT(exp, us)
#endif /* DHDTHREAD */
#ifndef OSL_SLEEP
#define OSL_SLEEP(ms) OSL_DELAY(ms*1000)
@ -394,17 +468,23 @@ typedef struct dhd_cmn {
#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
unsigned long dhd_os_spin_lock(dhd_pub_t *pub);
void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags);
/* Wakelock Functions */
#ifdef PNO_SUPPORT
int dhd_pno_clean(dhd_pub_t *dhd);
#endif /* PNO_SUPPORT */
/*
* Wake locks are an Android power management concept. They are used by applications and services
* to request CPU resources.
*/
extern int dhd_os_wake_lock(dhd_pub_t *pub);
extern int dhd_os_wake_unlock(dhd_pub_t *pub);
extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub);
extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val);
extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val);
extern int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub);
extern int dhd_os_wd_wake_lock(dhd_pub_t *pub);
extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub);
extern int dhd_os_wake_lock_waive(dhd_pub_t *pub);
extern int dhd_os_wake_lock_restore(dhd_pub_t *pub);
inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp)
{
@ -429,16 +509,22 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub)
#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub)
#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub)
#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub)
#define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub)
#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \
dhd_os_wake_lock_rx_timeout_enable(pub, val)
#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \
dhd_os_wake_lock_ctrl_timeout_enable(pub, val)
#define DHD_PACKET_TIMEOUT_MS 1000
#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \
dhd_os_wake_lock_ctrl_timeout_cancel(pub)
#define DHD_OS_WAKE_LOCK_WAIVE(pub) dhd_os_wake_lock_waive(pub)
#define DHD_OS_WAKE_LOCK_RESTORE(pub) dhd_os_wake_lock_restore(pub)
#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub)
#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub)
#define DHD_PACKET_TIMEOUT_MS 500
#define DHD_EVENT_TIMEOUT_MS 1500
/* interface operations (register, remove) should be atomic, use this lock to prevent race
* condition among wifi on/off and interface operation functions
*/
@ -446,19 +532,11 @@ 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 && 1
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && defined(BCMSDIO)
extern struct mutex _dhd_sdio_mutex_lock_;
#endif
#endif /* MULTIPLE_SUPPLICANT */
typedef struct dhd_if_event {
uint8 ifidx;
uint8 action;
uint8 flags;
uint8 bssidx;
uint8 is_AP;
} dhd_if_event_t;
typedef enum dhd_attach_states
{
DHD_ATTACH_STATE_INIT = 0x0,
@ -483,10 +561,6 @@ typedef enum dhd_attach_states
* Exported from dhd OS modules (dhd_linux/dhd_ndis)
*/
/* To allow osl_attach/detach calls from os-independent modules */
osl_t *dhd_osl_attach(void *pdev, uint bustype);
void dhd_osl_detach(osl_t *osh);
/* Indication from bus module regarding presence/insertion of dongle.
* Return dhd_pub_t pointer, used as handle to OS module in later calls.
* Returned structure should have bus and prot pointers filled in.
@ -498,7 +572,7 @@ extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen);
extern int dhd_attach_p2p(dhd_pub_t *);
extern int dhd_detach_p2p(dhd_pub_t *);
#endif /* WLP2P && WL_CFG80211 */
extern int dhd_net_attach(dhd_pub_t *dhdp, int idx);
extern int dhd_register_if(dhd_pub_t *dhdp, int idx, bool need_rtnl_lock);
/* Indication from bus module regarding removal/absence of dongle */
extern void dhd_detach(dhd_pub_t *dhdp);
@ -531,8 +605,14 @@ extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool * pend
extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub);
extern unsigned int dhd_os_get_ioctl_resp_timeout(void);
extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
extern void * dhd_os_open_image(char * filename);
#if 0 && (NDISVER >= 0x0600)
#define dhd_os_open_image(a) wl_os_open_image(a)
#define dhd_os_close_image(a) wl_os_close_image(a)
#define dhd_os_get_image_block(a, b, c) wl_os_get_image_block(a, b, c)
#endif /* (NDISVER >= 0x0600) */
extern int dhd_os_get_image_block(char * buf, int len, void * image);
extern void * dhd_os_open_image(char * filename);
extern void dhd_os_close_image(void * image);
extern void dhd_os_wd_timer(void *bus, uint wdtick);
extern void dhd_os_sdlock(dhd_pub_t * pub);
@ -547,14 +627,22 @@ extern void dhd_os_tcpacklock(dhd_pub_t *pub);
extern void dhd_os_tcpackunlock(dhd_pub_t *pub);
#endif /* DHDTCPACK_SUPPRESS */
extern void dhd_customer_gpio_wlan_ctrl(int onoff);
extern int dhd_custom_get_mac_address(unsigned char *buf);
extern int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr);
extern int dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff);
extern int dhd_custom_get_mac_address(void *adapter, unsigned char *buf);
extern void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec);
extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret);
extern int dhd_os_send_hang_message(dhd_pub_t *dhdp);
extern void dhd_set_version_info(dhd_pub_t *pub, char *fw);
extern bool dhd_os_check_if_up(dhd_pub_t *pub);
extern int dhd_os_check_wakelock(dhd_pub_t *pub);
extern int dhd_get_instance(dhd_pub_t *pub);
#ifdef CUSTOM_SET_CPUCORE
extern void dhd_set_cpucore(dhd_pub_t *dhd, int set);
#endif /* CUSTOM_SET_CPUCORE */
#if defined(KEEP_ALIVE)
extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
@ -580,11 +668,6 @@ extern bool dhd_support_sta_mode(dhd_pub_t *dhd);
#ifdef DHD_DEBUG
extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size);
#endif /* DHD_DEBUG */
#if defined(OOB_INTR_ONLY)
extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
#endif
extern void dhd_os_sdtxlock(dhd_pub_t * pub);
extern void dhd_os_sdtxunlock(dhd_pub_t * pub);
typedef struct {
uint32 limit; /* Expiration time (usec) */
@ -593,35 +676,44 @@ typedef struct {
uint32 tick; /* O/S tick time (usec) */
} dhd_timeout_t;
#ifdef SHOW_LOGTRACE
typedef struct {
int num_fmts;
char **fmts;
char *raw_fmts;
} dhd_event_log_t;
#endif /* SHOW_LOGTRACE */
extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
extern int dhd_timeout_expired(dhd_timeout_t *tmo);
extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
extern int dhd_ifidx2hostidx(struct dhd_info *dhd, int ifidx);
extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net);
extern struct net_device * dhd_idx2net(void *pub, int ifidx);
extern int net_os_send_hang_message(struct net_device *dev);
extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata,
wl_event_msg_t *, void **data_ptr);
wl_event_msg_t *, void **data_ptr, void *);
extern void wl_event_to_host_order(wl_event_msg_t * evt);
extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len);
extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set,
int ifindex);
extern void dhd_common_init(osl_t *osh);
extern void dhd_common_deinit(dhd_pub_t *dhd_pub, dhd_cmn_t *sa_cmn);
extern int dhd_do_driver_init(struct net_device *net);
extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle,
char *name, uint8 *mac_addr, uint32 flags, uint8 bssidx);
extern void dhd_del_if(struct dhd_info *dhd, int ifidx);
extern int dhd_event_ifadd(struct dhd_info *dhd, struct wl_event_data_if *ifevent,
char *name, uint8 *mac);
extern int dhd_event_ifdel(struct dhd_info *dhd, struct wl_event_data_if *ifevent,
char *name, uint8 *mac);
extern struct net_device* dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name,
uint8 *mac, uint8 bssidx, bool need_rtnl_lock);
extern int dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock);
extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name);
extern void dhd_vif_del(struct dhd_info *dhd, int ifidx);
extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx);
extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len);
/* Send packet to dongle via data channel */
extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt);
@ -629,20 +721,44 @@ extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt);
extern void dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data);
/* Send event to host */
extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data);
#ifdef LOG_INTO_TCPDUMP
extern void dhd_sendup_log(dhd_pub_t *dhdp, void *data, int len);
#endif /* LOG_INTO_TCPDUMP */
extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag);
extern uint dhd_bus_status(dhd_pub_t *dhdp);
extern int dhd_bus_start(dhd_pub_t *dhdp);
extern int dhd_bus_suspend(dhd_pub_t *dhdpub);
extern int dhd_bus_resume(dhd_pub_t *dhdpub, int stage);
extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval);
#if defined(BCMSDIO) || defined(BCMPCIE)
extern uint dhd_bus_chip_id(dhd_pub_t *dhdp);
extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp);
extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp);
#endif /* defined(BCMSDIO) || defined(BCMPCIE) */
#if defined(KEEP_ALIVE)
extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
#endif /* KEEP_ALIVE */
/* OS spin lock API */
extern void *dhd_os_spin_lock_init(osl_t *osh);
extern void dhd_os_spin_lock_deinit(osl_t *osh, void *lock);
extern unsigned long dhd_os_spin_lock(void *lock);
void dhd_os_spin_unlock(void *lock, unsigned long flags);
/*
* Manage sta objects in an interface. Interface is identified by an ifindex and
* sta(s) within an interfaces are managed using a MacAddress of the sta.
*/
struct dhd_sta;
extern struct dhd_sta *dhd_findadd_sta(void *pub, int ifidx, void *ea);
extern void dhd_del_sta(void *pub, int ifidx, void *ea);
extern int dhd_get_ap_isolate(dhd_pub_t *dhdp, uint32 idx);
extern int dhd_set_ap_isolate(dhd_pub_t *dhdp, uint32 idx, int val);
extern int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx);
extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd);
extern int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set);
typedef enum cust_gpio_modes {
@ -667,12 +783,14 @@ extern uint dhd_console_ms;
#endif /* defined(DHD_DEBUG) */
extern uint android_msg_level;
extern uint config_msg_level;
extern uint sd_msglevel;
#ifdef WL_WIRELESS_EXT
extern uint iw_msg_level;
#endif
#ifdef WL_CFG80211
extern uint wl_dbg_level;
#endif
extern uint dhd_slpauto;
/* Use interrupts */
@ -750,7 +868,6 @@ extern uint dhd_force_tx_queueing;
#ifndef CUSTOM_PNO_EVENT_LOCK_xTIME
#define CUSTOM_PNO_EVENT_LOCK_xTIME DEFAULT_PNO_EVENT_LOCK_xTIME
#endif
/* hooks for custom dhd_dpc_prio setting option via Makefile */
#define DEFAULT_DHP_DPC_PRIO 1
#ifndef CUSTOM_DPC_PRIO_SETTING
@ -766,16 +883,24 @@ extern uint dhd_force_tx_queueing;
#define CUSTOM_SUSPEND_BCN_LI_DTIM DEFAULT_SUSPEND_BCN_LI_DTIM
#endif
#define DEFAULT_WIFI_TURNOFF_DELAY 0
#ifndef CUSTOM_RXF_PRIO_SETTING
#define CUSTOM_RXF_PRIO_SETTING MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1)
#endif
#define DEFAULT_WIFI_TURNOFF_DELAY 0
#ifndef WIFI_TURNOFF_DELAY
#define WIFI_TURNOFF_DELAY DEFAULT_WIFI_TURNOFF_DELAY
#endif /* WIFI_TURNOFF_DELAY */
#ifdef RXFRAME_THREAD
#ifndef CUSTOM_RXF_PRIO_SETTING
#define CUSTOM_RXF_PRIO_SETTING MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1)
#endif
#endif /* RXFRAME_THREAD */
#define DEFAULT_WIFI_TURNON_DELAY 200
#ifndef WIFI_TURNON_DELAY
#define WIFI_TURNON_DELAY DEFAULT_WIFI_TURNON_DELAY
#endif /* WIFI_TURNON_DELAY */
#define DEFAULT_DHD_WATCHDOG_INTERVAL_MS 10 /* msec */
#ifndef CUSTOM_DHD_WATCHDOG_MS
#define CUSTOM_DHD_WATCHDOG_MS DEFAULT_DHD_WATCHDOG_INTERVAL_MS
#endif /* DEFAULT_DHD_WATCHDOG_INTERVAL_MS */
#ifdef WLTDLS
#ifndef CUSTOM_TDLS_IDLE_MODE_SETTING
@ -790,8 +915,11 @@ extern uint dhd_force_tx_queueing;
#endif /* WLTDLS */
#define MAX_DTIM_SKIP_BEACON_ITERVAL 100 /* max allowed associated AP beacon for dtim skip */
#define MAX_DTIM_SKIP_BEACON_INTERVAL 100 /* max allowed associated AP beacon for DTIM skip */
#ifndef MAX_DTIM_ALLOWED_INTERVAL
#define MAX_DTIM_ALLOWED_INTERVAL 600 /* max allowed total beacon interval for DTIM skip */
#endif
#define NO_DTIM_SKIP 1
#ifdef SDTEST
/* Echo packet generator (SDIO), pkts/s */
extern uint dhd_pktgen;
@ -804,11 +932,8 @@ extern uint dhd_pktgen_len;
/* optionally set by a module_param_string() */
#define MOD_PARAM_PATHLEN 2048
extern char fw_path[MOD_PARAM_PATHLEN];
extern char nv_path[MOD_PARAM_PATHLEN];
extern char conf_path[MOD_PARAM_PATHLEN];
#define MOD_PARAM_INFOLEN 512
#ifdef SOFTAP
extern char fw_path2[MOD_PARAM_PATHLEN];
#endif
@ -817,159 +942,6 @@ extern char fw_path2[MOD_PARAM_PATHLEN];
extern uint dhd_download_fw_on_driverload;
/* For supporting multiple interfaces */
#define DHD_MAX_IFS 16
#define DHD_DEL_IF -0xe
#define DHD_BAD_IF -0xf
#ifdef PROP_TXSTATUS
/* Please be mindful that total pkttag space is 32 octets only */
typedef struct dhd_pkttag {
/*
b[14:13] - encryption exemption
b[12 ] - 1 = event channel
b[11 ] - 1 = this packet was sent in response to one time packet request,
do not increment credit on status for this one. [WLFC_CTL_TYPE_MAC_REQUEST_PACKET].
b[10 ] - 1 = signal-only-packet to firmware [i.e. nothing to piggyback on]
b[9 ] - 1 = packet is host->firmware (transmit direction)
- 0 = packet received from firmware (firmware->host)
b[8 ] - 1 = packet was sent due to credit_request (pspoll),
packet does not count against FIFO credit.
- 0 = normal transaction, packet counts against FIFO credit
b[7 ] - 1 = AP, 0 = STA
b[6:4] - AC FIFO number
b[3:0] - interface index
*/
uint16 if_flags;
/* destination MAC address for this packet so that not every
module needs to open the packet to find this
*/
uint8 dstn_ether[ETHER_ADDR_LEN];
/*
This 32-bit goes from host to device for every packet.
*/
uint32 htod_tag;
/* bus specific stuff */
union {
struct {
void* stuff;
uint32 thing1;
uint32 thing2;
} sd;
struct {
void* bus;
void* urb;
} usb;
} bus_specific;
} dhd_pkttag_t;
#define DHD_PKTTAG_SET_H2DTAG(tag, h2dvalue) ((dhd_pkttag_t*)(tag))->htod_tag = (h2dvalue)
#define DHD_PKTTAG_H2DTAG(tag) (((dhd_pkttag_t*)(tag))->htod_tag)
#define DHD_PKTTAG_IFMASK 0xf
#define DHD_PKTTAG_IFTYPE_MASK 0x1
#define DHD_PKTTAG_IFTYPE_SHIFT 7
#define DHD_PKTTAG_FIFO_MASK 0x7
#define DHD_PKTTAG_FIFO_SHIFT 4
#define DHD_PKTTAG_SIGNALONLY_MASK 0x1
#define DHD_PKTTAG_SIGNALONLY_SHIFT 10
#define DHD_PKTTAG_ONETIMEPKTRQST_MASK 0x1
#define DHD_PKTTAG_ONETIMEPKTRQST_SHIFT 11
#define DHD_PKTTAG_EVENT_MASK 0x1
#define DHD_PKTTAG_EVENT_SHIFT 12
#define DHD_PKTTAG_EXEMPT_MASK 0x3
#define DHD_PKTTAG_EXEMPT_SHIFT 13
#define DHD_PKTTAG_PKTDIR_MASK 0x1
#define DHD_PKTTAG_PKTDIR_SHIFT 9
#define DHD_PKTTAG_CREDITCHECK_MASK 0x1
#define DHD_PKTTAG_CREDITCHECK_SHIFT 8
#define DHD_PKTTAG_INVALID_FIFOID 0x7
#define DHD_PKTTAG_SETFIFO(tag, fifo) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_FIFO_MASK << DHD_PKTTAG_FIFO_SHIFT)) | \
(((fifo) & DHD_PKTTAG_FIFO_MASK) << DHD_PKTTAG_FIFO_SHIFT)
#define DHD_PKTTAG_FIFO(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_FIFO_SHIFT) & DHD_PKTTAG_FIFO_MASK)
#define DHD_PKTTAG_SETIF(tag, if) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & ~DHD_PKTTAG_IFMASK) | ((if) & DHD_PKTTAG_IFMASK)
#define DHD_PKTTAG_IF(tag) (((dhd_pkttag_t*)(tag))->if_flags & DHD_PKTTAG_IFMASK)
#define DHD_PKTTAG_SETIFTYPE(tag, isAP) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_IFTYPE_MASK << DHD_PKTTAG_IFTYPE_SHIFT)) | \
(((isAP) & DHD_PKTTAG_IFTYPE_MASK) << DHD_PKTTAG_IFTYPE_SHIFT)
#define DHD_PKTTAG_IFTYPE(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_IFTYPE_SHIFT) & DHD_PKTTAG_IFTYPE_MASK)
#define DHD_PKTTAG_SETCREDITCHECK(tag, check) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_CREDITCHECK_MASK << DHD_PKTTAG_CREDITCHECK_SHIFT)) | \
(((check) & DHD_PKTTAG_CREDITCHECK_MASK) << DHD_PKTTAG_CREDITCHECK_SHIFT)
#define DHD_PKTTAG_CREDITCHECK(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_CREDITCHECK_SHIFT) & DHD_PKTTAG_CREDITCHECK_MASK)
#define DHD_PKTTAG_SETPKTDIR(tag, dir) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_PKTDIR_MASK << DHD_PKTTAG_PKTDIR_SHIFT)) | \
(((dir) & DHD_PKTTAG_PKTDIR_MASK) << DHD_PKTTAG_PKTDIR_SHIFT)
#define DHD_PKTTAG_PKTDIR(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_PKTDIR_SHIFT) & DHD_PKTTAG_PKTDIR_MASK)
#define DHD_PKTTAG_SETSIGNALONLY(tag, signalonly) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_SIGNALONLY_MASK << DHD_PKTTAG_SIGNALONLY_SHIFT)) | \
(((signalonly) & DHD_PKTTAG_SIGNALONLY_MASK) << DHD_PKTTAG_SIGNALONLY_SHIFT)
#define DHD_PKTTAG_SIGNALONLY(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_SIGNALONLY_SHIFT) & DHD_PKTTAG_SIGNALONLY_MASK)
#define DHD_PKTTAG_SETONETIMEPKTRQST(tag) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_ONETIMEPKTRQST_MASK << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)) | \
(1 << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)
#define DHD_PKTTAG_ONETIMEPKTRQST(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) & DHD_PKTTAG_ONETIMEPKTRQST_MASK)
#define DHD_PKTTAG_SETEVENT(tag, event) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_EVENT_MASK << DHD_PKTTAG_EVENT_SHIFT)) | \
(((event) & DHD_PKTTAG_EVENT_MASK) << DHD_PKTTAG_EVENT_SHIFT)
#define DHD_PKTTAG_EVENT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_EVENT_SHIFT) & DHD_PKTTAG_EVENT_MASK)
#define DHD_PKTTAG_EXEMPT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_EXEMPT_MASK << DHD_PKTTAG_EXEMPT_SHIFT)) | \
(((value) & DHD_PKTTAG_EXEMPT_MASK) << DHD_PKTTAG_EXEMPT_SHIFT)
#define DHD_PKTTAG_EXEMPT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_EXEMPT_SHIFT) & DHD_PKTTAG_EXEMPT_MASK)
#define DHD_PKTTAG_SETDSTN(tag, dstn_MAC_ea) memcpy(((dhd_pkttag_t*)((tag)))->dstn_ether, \
(dstn_MAC_ea), ETHER_ADDR_LEN)
#define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether
typedef int (*f_commitpkt_t)(void* ctx, void* p);
int dhd_os_wlfc_block(dhd_pub_t *pub);
int dhd_os_wlfc_unblock(dhd_pub_t *pub);
void dhd_schedule_tx(struct dhd_info *dhd);
#ifdef PROP_TXSTATUS_DEBUG
#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0)
#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do { (entry)->opened_ct++; } while (0)
#else
#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do {} while (0)
#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do {} while (0)
#endif
#endif /* PROP_TXSTATUS */
extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
@ -991,18 +963,78 @@ int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx)
void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx);
#endif /* ARP_OFFLOAD_SUPPORT */
#ifdef WLTDLS
int dhd_tdls_enable_disable(dhd_pub_t *dhd, bool flag);
#endif
int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac);
#ifdef PCIE_FULL_DONGLE
void dhd_tdls_update_peer_info(struct net_device *dev, bool connect_disconnect, uint8 *addr);
#endif /* PCIE_FULL_DONGLE */
#endif /* WLTDLS */
/* Neighbor Discovery Offload Support */
int dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable);
int dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipaddr, int idx);
int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx);
/* ioctl processing for nl80211 */
int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc);
int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc, void *data_buf);
void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pconf_path);
void dhd_set_bus_state(void *bus, uint32 state);
/* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */
extern bool dhd_prec_drop_pkts(osl_t *osh, struct pktq *pq, int prec);
typedef int (*f_droppkt_t)(dhd_pub_t *dhdp, int prec, void* p, bool bPktInQ);
extern bool dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn);
#ifdef PROP_TXSTATUS
int dhd_os_wlfc_block(dhd_pub_t *pub);
int dhd_os_wlfc_unblock(dhd_pub_t *pub);
extern const uint8 prio2fifo[];
#endif /* PROP_TXSTATUS */
uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail);
void dhd_os_prefree(dhd_pub_t *dhdpub, void *addr, uint size);
int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost);
#if defined(CONFIG_DHD_USE_STATIC_BUF)
#define DHD_OS_PREALLOC(dhdpub, section, size) dhd_os_prealloc(dhdpub, section, size, FALSE)
#define DHD_OS_PREFREE(dhdpub, addr, size) dhd_os_prefree(dhdpub, addr, size)
#else
#define DHD_OS_PREALLOC(dhdpub, section, size) MALLOC(dhdpub->osh, size)
#define DHD_OS_PREFREE(dhdpub, addr, size) MFREE(dhdpub->osh, addr, size)
#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */
#define dhd_add_flowid(pub, ifidx, ac_prio, ea, flowid) do {} while (0)
#define dhd_del_flowid(pub, ifidx, flowid) do {} while (0)
extern unsigned long dhd_os_general_spin_lock(dhd_pub_t *pub);
extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags);
/** Miscellaenous DHD Spin Locks */
/* Disable router 3GMAC bypass path perimeter lock */
#define DHD_PERIM_LOCK(dhdp) do {} while (0)
#define DHD_PERIM_UNLOCK(dhdp) do {} while (0)
/* Enable DHD general spin lock/unlock */
#define DHD_GENERAL_LOCK(dhdp, flags) \
(flags) = dhd_os_general_spin_lock(dhdp)
#define DHD_GENERAL_UNLOCK(dhdp, flags) \
dhd_os_general_spin_unlock((dhdp), (flags))
/* Enable DHD flowring queue spin lock/unlock */
#define DHD_QUEUE_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock)
#define DHD_QUEUE_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags))
typedef struct wl_io_pport {
dhd_pub_t *dhd_pub;
uint ifidx;
} wl_io_pport_t;
extern void *dhd_pub_wlinfo(dhd_pub_t *dhd_pub);
#ifdef EXYNOS5433_PCIE_WAR
extern void exynos_pcie_set_l1_exit(void);
extern void exynos_pcie_clear_l1_exit(void);
extern int enum_wifi;
#endif /* EXYNOS5433_PCIE_WAR */
#endif /* _dhd_h_ */

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_bta.c 379512 2013-01-17 22:49:08Z $
* $Id: dhd_bta.c 434434 2013-11-06 07:16:02Z $
*/
#ifndef WLBTAMP
#error "WLBTAMP is not defined"
@ -83,7 +83,6 @@ dhd_bta_flush_hcidata(dhd_pub_t *pub, uint16 llh)
void *pkt = pktq_pdeq(q, prec);
int ifidx;
PKTPULL(pub->osh, pkt, dhd_bus_hdrlen(pub->bus));
dhd_prot_hdrpull(pub, &ifidx, pkt, NULL, NULL);
if (PKTLEN(pub->osh, pkt) >= RFC1042_HDR_LEN) {
@ -111,7 +110,6 @@ dhd_bta_flush_hcidata(dhd_pub_t *pub, uint16 llh)
}
dhd_prot_hdrpush(pub, ifidx, pkt);
PKTPUSH(pub->osh, pkt, dhd_bus_hdrlen(pub->bus));
if (head_pkt == NULL)
head_pkt = pkt;

View File

View File

@ -6,7 +6,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_bus.h 335569 2012-05-29 12:04:43Z $
* $Id: dhd_bus.h 491657 2014-07-17 06:29:40Z $
*/
#ifndef _dhd_bus_h_
@ -21,7 +21,7 @@ extern int dhd_bus_register(void);
extern void dhd_bus_unregister(void);
/* Download firmware image and nvram image */
extern bool dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
extern int dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
char *fw_path, char *nv_path, char *conf_path);
/* Stop bus module: clear pending frames, disable data flow */
@ -37,7 +37,12 @@ extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime);
extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time);
/* Send a data frame to the dongle. Callee disposes of txp. */
#ifdef BCMPCIE
extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp, uint8 ifidx);
#else
extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp);
#endif
/* Send/receive a control message to/from the dongle.
* Expects caller to enforce a single outstanding transaction.
@ -47,7 +52,13 @@ extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen);
/* Watchdog timer function */
extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
extern void dhd_disable_intr(dhd_pub_t *dhd);
extern int dhd_bus_oob_intr_register(dhd_pub_t *dhdp);
extern void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp);
extern void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable);
extern void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub);
extern void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub);
extern bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub);
#if defined(DHD_DEBUG)
/* Device console input function */
@ -72,13 +83,21 @@ extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
/* return the dongle chipid */
extern uint dhd_bus_chip(struct dhd_bus *bus);
/* return the dongle chiprev */
extern uint dhd_bus_chiprev(struct dhd_bus *bus);
/* Set user-specified nvram parameters. */
extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params);
extern void *dhd_bus_pub(struct dhd_bus *bus);
extern void *dhd_bus_txq(struct dhd_bus *bus);
extern void *dhd_bus_sih(struct dhd_bus *bus);
extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
#ifdef BCMSDIO
extern void dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val);
#else
#define dhd_bus_set_dotxinrx(a, b) do {} while (0)
#endif
#define DHD_SET_BUS_STATE_DOWN(_bus) do { \
(_bus)->dhd->busstate = DHD_BUS_DOWN; \
@ -87,7 +106,68 @@ extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
/* Register a dummy SDIO client driver in order to be notified of new SDIO device */
extern int dhd_bus_reg_sdio_notify(void* semaphore);
extern void dhd_bus_unreg_sdio_notify(void);
extern void dhd_txglom_enable(dhd_pub_t *dhdp, bool enable);
extern int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num,
uint32 *slot_num);
#ifdef BCMPCIE
enum {
DNGL_TO_HOST_BUF_IOCT,
DNGL_TO_HOST_DMA_SCRATCH_BUFFER,
DNGL_TO_HOST_DMA_SCRATCH_BUFFER_LEN,
HOST_TO_DNGL_DMA_WRITEINDX_BUFFER,
HOST_TO_DNGL_DMA_READINDX_BUFFER,
DNGL_TO_HOST_DMA_WRITEINDX_BUFFER,
DNGL_TO_HOST_DMA_READINDX_BUFFER,
TOTAL_LFRAG_PACKET_CNT,
HTOD_MB_DATA,
DTOH_MB_DATA,
RING_BUF_ADDR,
H2D_DMA_WRITEINDX,
H2D_DMA_READINDX,
D2H_DMA_WRITEINDX,
D2H_DMA_READINDX,
RING_READ_PTR,
RING_WRITE_PTR,
RING_LEN_ITEMS,
RING_MAX_ITEM,
MAX_HOST_RXBUFS
};
typedef void (*dhd_mb_ring_t) (struct dhd_bus *, uint32);
extern void dhd_bus_cmn_writeshared(struct dhd_bus *bus, void * data, uint32 len, uint8 type,
uint16 ringid);
extern void dhd_bus_ringbell(struct dhd_bus *bus, uint32 value);
extern void dhd_bus_cmn_readshared(struct dhd_bus *bus, void* data, uint8 type, uint16 ringid);
extern uint32 dhd_bus_get_sharedflags(struct dhd_bus *bus);
extern void dhd_bus_rx_frame(struct dhd_bus *bus, void* pkt, int ifidx, uint pkt_count);
extern void dhd_bus_start_queue(struct dhd_bus *bus);
extern void dhd_bus_stop_queue(struct dhd_bus *bus);
extern void dhd_bus_update_retlen(struct dhd_bus *bus, uint32 retlen, uint32 cmd_id, uint16 status,
uint32 resp_len);
extern dhd_mb_ring_t dhd_bus_get_mbintr_fn(struct dhd_bus *bus);
extern void dhd_bus_write_flow_ring_states(struct dhd_bus *bus,
void * data, uint16 flowid);
extern void dhd_bus_read_flow_ring_states(struct dhd_bus *bus,
void * data, uint8 flowid);
extern int dhd_bus_flow_ring_create_request(struct dhd_bus *bus, void *flow_ring_node);
extern void dhd_bus_clean_flow_ring(struct dhd_bus *bus, uint16 flowid);
extern void dhd_bus_flow_ring_create_response(struct dhd_bus *bus, uint16 flow_id, int32 status);
extern int dhd_bus_flow_ring_delete_request(struct dhd_bus *bus, void *flow_ring_node);
extern void dhd_bus_flow_ring_delete_response(struct dhd_bus *bus, uint16 flowid, uint32 status);
extern int dhd_bus_flow_ring_flush_request(struct dhd_bus *bus, void *flow_ring_node);
extern void dhd_bus_flow_ring_flush_response(struct dhd_bus *bus, uint16 flowid, uint32 status);
extern uint8 dhd_bus_is_txmode_push(struct dhd_bus *bus);
extern uint32 dhd_bus_max_h2d_queues(struct dhd_bus *bus, uint8 *txpush);
extern int dhd_bus_schedule_queue(struct dhd_bus *bus, uint16 flow_id, bool txs);
extern int dhdpcie_bus_clock_start(struct dhd_bus *bus);
extern int dhdpcie_bus_clock_stop(struct dhd_bus *bus);
extern int dhdpcie_bus_enable_device(struct dhd_bus *bus);
extern int dhdpcie_bus_disable_device(struct dhd_bus *bus);
extern int dhdpcie_bus_alloc_resource(struct dhd_bus *bus);
extern void dhdpcie_bus_free_resource(struct dhd_bus *bus);
extern bool dhdpcie_bus_dongle_attach(struct dhd_bus *bus);
extern int dhd_bus_release_dongle(struct dhd_bus *bus);
#endif /* BCMPCIE */
#endif /* _dhd_bus_h_ */

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_cdc.c 416698 2013-08-06 07:53:34Z $
* $Id: dhd_cdc.c 472193 2014-04-23 06:27:38Z $
*
* BDC is like CDC, except it includes a header for data packets to convey
* packet priority over the bus, and flags (e.g. to indicate checksum status
@ -202,7 +202,6 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8
return -EIO;
}
memset(msg, 0, sizeof(cdc_ioctl_t));
msg->cmd = htol32(cmd);
@ -333,8 +332,7 @@ dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
{
bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
#ifdef PROP_TXSTATUS
if (dhdp->wlfc_state)
dhd_wlfc_dump(dhdp, strbuf);
dhd_wlfc_dump(dhdp, strbuf);
#endif
}
@ -371,6 +369,17 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF)
}
#undef PKTBUF /* Only defined in the above routine */
uint
dhd_prot_hdrlen(dhd_pub_t *dhd, void *PKTBUF)
{
uint hdrlen = 0;
#ifdef BDC
/* Length of BDC(+WLFC) headers pushed */
hdrlen = BDC_HEADER_LEN + (((struct bdc_header *)PKTBUF)->dataOffset * 4);
#endif
return hdrlen;
}
int
dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_info,
uint *reorder_info_len)
@ -428,54 +437,40 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in
PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
#endif /* BDC */
#if defined(NDISVER) && (NDISVER < 0x0630)
if (PKTLEN(dhd->osh, pktbuf) < (uint32) (data_offset << 2)) {
DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__,
PKTLEN(dhd->osh, pktbuf), (data_offset * 4)));
return BCME_ERROR;
}
#endif /* (NDISVER < 0x0630) */
#ifdef PROP_TXSTATUS
dhd_os_wlfc_block(dhd);
if (dhd->wlfc_state &&
((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode
!= WLFC_FCMODE_NONE &&
(!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf)))) {
if (!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf))) {
/*
- parse txstatus only for packets that came from the firmware
*/
dhd_wlfc_parse_header_info(dhd, pktbuf, (data_offset << 2),
reorder_buf_info, reorder_info_len);
((athost_wl_status_info_t*)dhd->wlfc_state)->stats.dhd_hdrpulls++;
}
dhd_os_wlfc_unblock(dhd);
#endif /* PROP_TXSTATUS */
exit:
PKTPULL(dhd->osh, pktbuf, (data_offset << 2));
PKTPULL(dhd->osh, pktbuf, (data_offset << 2));
return 0;
}
#if defined(PROP_TXSTATUS)
void
dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd)
{
dhd_os_wlfc_block(dhd);
if (dhd->wlfc_state &&
(((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode
!= WLFC_FCMODE_NONE)) {
dhd_wlfc_commit_packets(dhd->wlfc_state, (f_commitpkt_t)dhd_bus_txdata,
(void *)dhd->bus, NULL);
}
dhd_os_wlfc_unblock(dhd);
}
#endif
int
dhd_prot_attach(dhd_pub_t *dhd)
{
dhd_prot_t *cdc;
if (!(cdc = (dhd_prot_t *)DHD_OS_PREALLOC(dhd->osh, DHD_PREALLOC_PROT,
sizeof(dhd_prot_t)))) {
DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
goto fail;
}
if (!(cdc = (dhd_prot_t *)DHD_OS_PREALLOC(dhd, DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) {
DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
goto fail;
}
memset(cdc, 0, sizeof(dhd_prot_t));
/* ensure that the msg buf directly follows the cdc msg struct */
@ -492,10 +487,8 @@ dhd_prot_attach(dhd_pub_t *dhd)
return 0;
fail:
#ifndef CONFIG_DHD_USE_STATIC_BUF
if (cdc != NULL)
MFREE(dhd->osh, cdc, sizeof(dhd_prot_t));
#endif /* CONFIG_DHD_USE_STATIC_BUF */
DHD_OS_PREFREE(dhd, cdc, sizeof(dhd_prot_t));
return BCME_NOMEM;
}
@ -505,19 +498,16 @@ dhd_prot_detach(dhd_pub_t *dhd)
{
#ifdef PROP_TXSTATUS
dhd_wlfc_deinit(dhd);
if (dhd->plat_deinit)
dhd->plat_deinit((void *)dhd);
#endif
#ifndef CONFIG_DHD_USE_STATIC_BUF
MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t));
#endif /* CONFIG_DHD_USE_STATIC_BUF */
DHD_OS_PREFREE(dhd, dhd->prot, sizeof(dhd_prot_t));
dhd->prot = NULL;
}
void
dhd_prot_dstats(dhd_pub_t *dhd)
{
/* No stats from dongle added yet, copy bus stats */
/* copy bus stats */
dhd->dstats.tx_packets = dhd->tx_packets;
dhd->dstats.tx_errors = dhd->tx_errors;
dhd->dstats.rx_packets = dhd->rx_packets;
@ -528,7 +518,7 @@ dhd_prot_dstats(dhd_pub_t *dhd)
}
int
dhd_prot_init(dhd_pub_t *dhd)
dhd_sync_with_dongle(dhd_pub_t *dhd)
{
int ret = 0;
wlc_rev_info_t revinfo;
@ -542,10 +532,13 @@ dhd_prot_init(dhd_pub_t *dhd)
goto done;
#if defined(WL_CFG80211)
if (dhd_download_fw_on_driverload)
#endif /* defined(WL_CFG80211) */
ret = dhd_preinit_ioctls(dhd);
dhd_process_cid_mac(dhd, TRUE);
ret = dhd_preinit_ioctls(dhd);
if (!ret)
dhd_process_cid_mac(dhd, FALSE);
/* Always assumes wl for now */
dhd->iswl = TRUE;
@ -553,10 +546,15 @@ dhd_prot_init(dhd_pub_t *dhd)
return ret;
}
int dhd_prot_init(dhd_pub_t *dhd)
{
return TRUE;
}
void
dhd_prot_stop(dhd_pub_t *dhd)
{
/* Nothing to do for CDC */
/* Nothing to do for CDC */
}
@ -564,7 +562,6 @@ static void
dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt,
uint32 *pkt_count, void **pplast, uint8 start, uint8 end)
{
uint i;
void *plast = NULL, *p;
uint32 pkt_cnt = 0;
@ -575,15 +572,7 @@ dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt,
*pkt = NULL;
return;
}
if (start == end)
i = ptr->max_idx + 1;
else {
if (start > end)
i = ((ptr->max_idx + 1) - start) + end;
else
i = end - start;
}
while (i) {
do {
p = (void *)(ptr->p[start]);
ptr->p[start] = NULL;
@ -596,12 +585,13 @@ dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt,
plast = p;
pkt_cnt++;
}
i--;
if (start++ == ptr->max_idx)
start++;
if (start > ptr->max_idx)
start = 0;
}
} while (start != end);
*pplast = plast;
*pkt_count = (uint32)pkt_cnt;
*pkt_count = pkt_cnt;
ptr->pend_pkts -= (uint8)pkt_cnt;
}
int
@ -749,7 +739,6 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord
dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast,
cur_idx, exp_idx);
ptr->pend_pkts -= (uint8)cnt;
*pkt_count = cnt;
DHD_REORDER(("%s: freeing up buffers %d, still pending %d\n",
__FUNCTION__, cnt, ptr->pend_pkts));
@ -806,7 +795,6 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord
end_idx = exp_idx;
dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ptr->exp_idx, end_idx);
ptr->pend_pkts -= (uint8)cnt;
if (plast)
PKTSETNEXT(dhd->osh, plast, cur_pkt);
else

View File

@ -6,6 +6,7 @@
* $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $
*/
#include <linux/vmalloc.h>
#include <net/rtnetlink.h>
#include <bcmutils.h>
@ -18,7 +19,7 @@
#include <dhd.h>
#endif
extern struct wl_priv *wlcfg_drv_priv;
extern struct bcm_cfg80211 *g_bcm_cfg;
#ifdef PKT_FILTER_SUPPORT
extern uint dhd_pkt_filter_enable;
@ -32,35 +33,48 @@ static int dhd_dongle_up = FALSE;
#include <dhd.h>
#include <dhdioctl.h>
#include <wlioctl.h>
#include <brcm_nl80211.h>
#include <dhd_cfg80211.h>
static s32 wl_dongle_up(struct net_device *ndev, u32 up);
static s32 wl_dongle_up(struct net_device *ndev);
static s32 wl_dongle_down(struct net_device *ndev);
/**
* Function implementations
*/
s32 dhd_cfg80211_init(struct wl_priv *wl)
s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg)
{
dhd_dongle_up = FALSE;
return 0;
}
s32 dhd_cfg80211_deinit(struct wl_priv *wl)
s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg)
{
dhd_dongle_up = FALSE;
return 0;
}
s32 dhd_cfg80211_down(struct wl_priv *wl)
s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg)
{
struct net_device *ndev;
s32 err = 0;
WL_TRACE(("In\n"));
if (!dhd_dongle_up) {
WL_ERR(("Dongle is already down\n"));
return err;
}
ndev = bcmcfg_to_prmry_ndev(cfg);
wl_dongle_down(ndev);
dhd_dongle_up = FALSE;
return 0;
}
s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val)
{
dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
dhd->op_mode |= val;
WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode));
#ifdef ARP_OFFLOAD_SUPPORT
@ -74,9 +88,9 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
return 0;
}
s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg)
{
dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE);
WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode));
@ -91,9 +105,50 @@ s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
return 0;
}
static s32 wl_dongle_up(struct net_device *ndev, u32 up)
struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
uint8 *mac, uint8 bssidx)
{
return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE);
}
int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
{
return dhd_register_if(cfg->pub, ifidx, FALSE);
}
int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
{
return dhd_remove_if(cfg->pub, ifidx, FALSE);
}
struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev)
{
if (ndev) {
if (ndev->ieee80211_ptr) {
kfree(ndev->ieee80211_ptr);
ndev->ieee80211_ptr = NULL;
}
free_netdev(ndev);
return NULL;
}
return ndev;
}
void dhd_netdev_free(struct net_device *ndev)
{
#ifdef WL_CFG80211
ndev = dhd_cfg80211_netdev_free(ndev);
#endif
if (ndev)
free_netdev(ndev);
}
static s32
wl_dongle_up(struct net_device *ndev)
{
s32 err = 0;
u32 up = 0;
err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true);
if (unlikely(err)) {
@ -101,7 +156,22 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up)
}
return err;
}
s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
static s32
wl_dongle_down(struct net_device *ndev)
{
s32 err = 0;
u32 down = 0;
err = wldev_ioctl(ndev, WLC_DOWN, &down, sizeof(down), true);
if (unlikely(err)) {
WL_ERR(("WLC_DOWN error (%d)\n", err));
}
return err;
}
s32 dhd_config_dongle(struct bcm_cfg80211 *cfg)
{
#ifndef DHD_SDALIGN
#define DHD_SDALIGN 32
@ -115,12 +185,9 @@ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
return err;
}
ndev = wl_to_prmry_ndev(wl);
ndev = bcmcfg_to_prmry_ndev(cfg);
if (need_lock)
rtnl_lock();
err = wl_dongle_up(ndev, 0);
err = wl_dongle_up(ndev);
if (unlikely(err)) {
WL_ERR(("wl_dongle_up failed\n"));
goto default_conf_out;
@ -128,561 +195,7 @@ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
dhd_dongle_up = true;
default_conf_out:
if (need_lock)
rtnl_unlock();
return err;
}
#ifdef CONFIG_NL80211_TESTMODE
int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
{
struct sk_buff *reply;
struct wl_priv *wl;
dhd_pub_t *dhd;
dhd_ioctl_t *ioc = data;
int err = 0;
WL_TRACE(("entry: cmd = %d\n", ioc->cmd));
wl = wiphy_priv(wiphy);
dhd = wl->pub;
DHD_OS_WAKE_LOCK(dhd);
/* send to dongle only if we are not waiting for reload already */
if (dhd->hang_was_sent) {
WL_ERR(("HANG was sent up earlier\n"));
DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
DHD_OS_WAKE_UNLOCK(dhd);
return OSL_ERROR(BCME_DONGLE_DOWN);
}
/* currently there is only one wiphy for ifidx 0 */
err = dhd_ioctl_process(dhd, 0, ioc);
if (err)
goto done;
/* response data is in ioc->buf so return ioc here */
reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*ioc));
nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc);
err = cfg80211_testmode_reply(reply);
done:
DHD_OS_WAKE_UNLOCK(dhd);
return err;
}
#endif /* CONFIG_NL80211_TESTMODE */
/* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */
#define COEX_DHCP
#if defined(COEX_DHCP)
/* use New SCO/eSCO smart YG suppression */
#define BT_DHCP_eSCO_FIX
/* this flag boost wifi pkt priority to max, caution: -not fair to sco */
#define BT_DHCP_USE_FLAGS
/* T1 start SCO/ESCo priority suppression */
#define BT_DHCP_OPPR_WIN_TIME 2500
/* T2 turn off SCO/SCO supperesion is (timeout) */
#define BT_DHCP_FLAG_FORCE_TIME 5500
enum wl_cfg80211_btcoex_status {
BT_DHCP_IDLE,
BT_DHCP_START,
BT_DHCP_OPPR_WIN,
BT_DHCP_FLAG_FORCE_TIMEOUT
};
/*
* get named driver variable to uint register value and return error indication
* calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, &reg_value)
*/
static int
dev_wlc_intvar_get_reg(struct net_device *dev, char *name,
uint reg, int *retval)
{
union {
char buf[WLC_IOCTL_SMLEN];
int val;
} var;
int error;
bcm_mkiovar(name, (char *)(&reg), sizeof(reg),
(char *)(&var), sizeof(var.buf));
error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false);
*retval = dtoh32(var.val);
return (error);
}
static int
dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
char ioctlbuf_local[1024];
#else
static char ioctlbuf_local[1024];
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local));
return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf_local, sizeof(ioctlbuf_local), true));
}
/*
get named driver variable to uint register value and return error indication
calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value)
*/
static int
dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val)
{
char reg_addr[8];
memset(reg_addr, 0, sizeof(reg_addr));
memcpy((char *)&reg_addr[0], (char *)addr, 4);
memcpy((char *)&reg_addr[4], (char *)val, 4);
return (dev_wlc_bufvar_set(dev, name, (char *)&reg_addr[0], sizeof(reg_addr)));
}
static bool btcoex_is_sco_active(struct net_device *dev)
{
int ioc_res = 0;
bool res = FALSE;
int sco_id_cnt = 0;
int param27;
int i;
for (i = 0; i < 12; i++) {
ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, &param27);
WL_TRACE(("sample[%d], btc params: 27:%x\n", i, param27));
if (ioc_res < 0) {
WL_ERR(("ioc read btc params error\n"));
break;
}
if ((param27 & 0x6) == 2) { /* count both sco & esco */
sco_id_cnt++;
}
if (sco_id_cnt > 2) {
WL_TRACE(("sco/esco detected, pkt id_cnt:%d samples:%d\n",
sco_id_cnt, i));
res = TRUE;
break;
}
OSL_SLEEP(5);
}
return res;
}
#if defined(BT_DHCP_eSCO_FIX)
/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */
static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
{
static bool saved_status = FALSE;
char buf_reg50va_dhcp_on[8] =
{ 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
char buf_reg51va_dhcp_on[8] =
{ 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
char buf_reg64va_dhcp_on[8] =
{ 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
char buf_reg65va_dhcp_on[8] =
{ 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
char buf_reg71va_dhcp_on[8] =
{ 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
uint32 regaddr;
static uint32 saved_reg50;
static uint32 saved_reg51;
static uint32 saved_reg64;
static uint32 saved_reg65;
static uint32 saved_reg71;
if (trump_sco) {
/* this should reduce eSCO agressive retransmit
* w/o breaking it
*/
/* 1st save current */
WL_TRACE(("Do new SCO/eSCO coex algo {save &"
"override}\n"));
if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
saved_status = TRUE;
WL_TRACE(("saved bt_params[50,51,64,65,71]:"
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
saved_reg50, saved_reg51,
saved_reg64, saved_reg65, saved_reg71));
} else {
WL_ERR((":%s: save btc_params failed\n",
__FUNCTION__));
saved_status = FALSE;
return -1;
}
WL_TRACE(("override with [50,51,64,65,71]:"
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
*(u32 *)(buf_reg50va_dhcp_on+4),
*(u32 *)(buf_reg51va_dhcp_on+4),
*(u32 *)(buf_reg64va_dhcp_on+4),
*(u32 *)(buf_reg65va_dhcp_on+4),
*(u32 *)(buf_reg71va_dhcp_on+4)));
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg50va_dhcp_on[0], 8);
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg51va_dhcp_on[0], 8);
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg64va_dhcp_on[0], 8);
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg65va_dhcp_on[0], 8);
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg71va_dhcp_on[0], 8);
saved_status = TRUE;
} else if (saved_status) {
/* restore previously saved bt params */
WL_TRACE(("Do new SCO/eSCO coex algo {save &"
"override}\n"));
regaddr = 50;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg50);
regaddr = 51;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg51);
regaddr = 64;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg64);
regaddr = 65;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg65);
regaddr = 71;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg71);
WL_TRACE(("restore bt_params[50,51,64,65,71]:"
"0x%x 0x%x 0x%x 0x%x 0x%x\n",
saved_reg50, saved_reg51, saved_reg64,
saved_reg65, saved_reg71));
saved_status = FALSE;
} else {
WL_ERR((":%s att to restore not saved BTCOEX params\n",
__FUNCTION__));
return -1;
}
return 0;
}
#endif /* BT_DHCP_eSCO_FIX */
static void
wl_cfg80211_bt_setflag(struct net_device *dev, bool set)
{
#if defined(BT_DHCP_USE_FLAGS)
char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
#endif
#if defined(BT_DHCP_eSCO_FIX)
/* set = 1, save & turn on 0 - off & restore prev settings */
set_btc_esco_params(dev, set);
#endif
#if defined(BT_DHCP_USE_FLAGS)
WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set));
if (set == TRUE)
/* Forcing bt_flag7 */
dev_wlc_bufvar_set(dev, "btc_flags",
(char *)&buf_flag7_dhcp_on[0],
sizeof(buf_flag7_dhcp_on));
else
/* Restoring default bt flag7 */
dev_wlc_bufvar_set(dev, "btc_flags",
(char *)&buf_flag7_default[0],
sizeof(buf_flag7_default));
#endif
}
static void wl_cfg80211_bt_timerfunc(ulong data)
{
struct btcoex_info *bt_local = (struct btcoex_info *)data;
WL_TRACE(("Enter\n"));
bt_local->timer_on = 0;
schedule_work(&bt_local->work);
}
static void wl_cfg80211_bt_handler(struct work_struct *work)
{
struct btcoex_info *btcx_inf;
btcx_inf = container_of(work, struct btcoex_info, work);
if (btcx_inf->timer_on) {
btcx_inf->timer_on = 0;
del_timer_sync(&btcx_inf->timer);
}
switch (btcx_inf->bt_state) {
case BT_DHCP_START:
/* DHCP started
* provide OPPORTUNITY window to get DHCP address
*/
WL_TRACE(("bt_dhcp stm: started \n"));
btcx_inf->bt_state = BT_DHCP_OPPR_WIN;
mod_timer(&btcx_inf->timer,
jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME));
btcx_inf->timer_on = 1;
break;
case BT_DHCP_OPPR_WIN:
if (btcx_inf->dhcp_done) {
WL_TRACE(("DHCP Done before T1 expiration\n"));
goto btc_coex_idle;
}
/* DHCP is not over yet, start lowering BT priority
* enforce btc_params + flags if necessary
*/
WL_TRACE(("DHCP T1:%d expired\n", BT_DHCP_OPPR_WIN_TIME));
if (btcx_inf->dev)
wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE);
btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
mod_timer(&btcx_inf->timer,
jiffies + msecs_to_jiffies(BT_DHCP_FLAG_FORCE_TIME));
btcx_inf->timer_on = 1;
break;
case BT_DHCP_FLAG_FORCE_TIMEOUT:
if (btcx_inf->dhcp_done) {
WL_TRACE(("DHCP Done before T2 expiration\n"));
} else {
/* Noo dhcp during T1+T2, restore BT priority */
WL_TRACE(("DHCP wait interval T2:%d msec expired\n",
BT_DHCP_FLAG_FORCE_TIME));
}
/* Restoring default bt priority */
if (btcx_inf->dev)
wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
btc_coex_idle:
btcx_inf->bt_state = BT_DHCP_IDLE;
btcx_inf->timer_on = 0;
break;
default:
WL_ERR(("error g_status=%d !!!\n", btcx_inf->bt_state));
if (btcx_inf->dev)
wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
btcx_inf->bt_state = BT_DHCP_IDLE;
btcx_inf->timer_on = 0;
break;
}
net_os_wake_unlock(btcx_inf->dev);
}
int wl_cfg80211_btcoex_init(struct wl_priv *wl)
{
struct btcoex_info *btco_inf = NULL;
btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL);
if (!btco_inf)
return -ENOMEM;
btco_inf->bt_state = BT_DHCP_IDLE;
btco_inf->ts_dhcp_start = 0;
btco_inf->ts_dhcp_ok = 0;
/* Set up timer for BT */
btco_inf->timer_ms = 10;
init_timer(&btco_inf->timer);
btco_inf->timer.data = (ulong)btco_inf;
btco_inf->timer.function = wl_cfg80211_bt_timerfunc;
btco_inf->dev = wl->wdev->netdev;
INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler);
wl->btcoex_info = btco_inf;
return 0;
}
void wl_cfg80211_btcoex_deinit(struct wl_priv *wl)
{
if (!wl->btcoex_info)
return;
if (wl->btcoex_info->timer_on) {
wl->btcoex_info->timer_on = 0;
del_timer_sync(&wl->btcoex_info->timer);
}
cancel_work_sync(&wl->btcoex_info->work);
kfree(wl->btcoex_info);
wl->btcoex_info = NULL;
}
int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
{
struct wl_priv *wl = wlcfg_drv_priv;
char powermode_val = 0;
char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
uint32 regaddr;
static uint32 saved_reg66;
static uint32 saved_reg41;
static uint32 saved_reg68;
static bool saved_status = FALSE;
#ifdef COEX_DHCP
char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
struct btcoex_info *btco_inf = wl->btcoex_info;
#endif /* COEX_DHCP */
#ifdef PKT_FILTER_SUPPORT
dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
#endif
/* Figure out powermode 1 or o command */
strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1);
if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
WL_TRACE_HW4(("DHCP session starts\n"));
#if defined(DHCP_SCAN_SUPPRESS)
/* Suppress scan during the DHCP */
wl_cfg80211_scan_suppress(dev, 1);
#endif /* OEM_ANDROID */
#ifdef PKT_FILTER_SUPPORT
dhd->dhcp_in_progress = 1;
if (dhd->early_suspended) {
WL_TRACE_HW4(("DHCP in progressing , disable packet filter!!!\n"));
dhd_enable_packet_filter(0, dhd);
}
#endif
/* Retrieve and saved orig regs value */
if ((saved_status == FALSE) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
(!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
saved_status = TRUE;
WL_TRACE(("Saved 0x%x 0x%x 0x%x\n",
saved_reg66, saved_reg41, saved_reg68));
/* Disable PM mode during dhpc session */
/* Disable PM mode during dhpc session */
#ifdef COEX_DHCP
/* Start BT timer only for SCO connection */
if (btcoex_is_sco_active(dev)) {
/* btc_params 66 */
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg66va_dhcp_on[0],
sizeof(buf_reg66va_dhcp_on));
/* btc_params 41 0x33 */
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg41va_dhcp_on[0],
sizeof(buf_reg41va_dhcp_on));
/* btc_params 68 0x190 */
dev_wlc_bufvar_set(dev, "btc_params",
(char *)&buf_reg68va_dhcp_on[0],
sizeof(buf_reg68va_dhcp_on));
saved_status = TRUE;
btco_inf->bt_state = BT_DHCP_START;
btco_inf->timer_on = 1;
mod_timer(&btco_inf->timer, btco_inf->timer.expires);
WL_TRACE(("enable BT DHCP Timer\n"));
}
#endif /* COEX_DHCP */
}
else if (saved_status == TRUE) {
WL_ERR(("was called w/o DHCP OFF. Continue\n"));
}
}
else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
#if defined(DHCP_SCAN_SUPPRESS)
/* Since DHCP is complete, enable the scan back */
wl_cfg80211_scan_suppress(dev, 0);
#endif /* OEM_ANDROID */
#ifdef PKT_FILTER_SUPPORT
dhd->dhcp_in_progress = 0;
WL_TRACE_HW4(("DHCP is complete \n"));
/* Enable packet filtering */
if (dhd->early_suspended) {
WL_TRACE_HW4(("DHCP is complete , enable packet filter!!!\n"));
dhd_enable_packet_filter(1, dhd);
}
#endif /* PKT_FILTER_SUPPORT */
/* Restoring PM mode */
#ifdef COEX_DHCP
/* Stop any bt timer because DHCP session is done */
WL_TRACE(("disable BT DHCP Timer\n"));
if (btco_inf->timer_on) {
btco_inf->timer_on = 0;
del_timer_sync(&btco_inf->timer);
if (btco_inf->bt_state != BT_DHCP_IDLE) {
/* need to restore original btc flags & extra btc params */
WL_TRACE(("bt->bt_state:%d\n", btco_inf->bt_state));
/* wake up btcoex thread to restore btlags+params */
schedule_work(&btco_inf->work);
}
}
/* Restoring btc_flag paramter anyway */
if (saved_status == TRUE)
dev_wlc_bufvar_set(dev, "btc_flags",
(char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
#endif /* COEX_DHCP */
/* Restore original values */
if (saved_status == TRUE) {
regaddr = 66;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg66);
regaddr = 41;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg41);
regaddr = 68;
dev_wlc_intvar_set_reg(dev, "btc_params",
(char *)&regaddr, (char *)&saved_reg68);
WL_TRACE(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
saved_reg66, saved_reg41, saved_reg68));
}
saved_status = FALSE;
}
else {
WL_ERR(("Unkwown yet power setting, ignored\n"));
}
snprintf(command, 3, "OK");
return (strlen("OK"));
}
#endif

View File

@ -13,23 +13,18 @@
#include <wl_cfg80211.h>
#include <wl_cfgp2p.h>
s32 dhd_cfg80211_init(struct wl_priv *wl);
s32 dhd_cfg80211_deinit(struct wl_priv *wl);
s32 dhd_cfg80211_down(struct wl_priv *wl);
s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val);
s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl);
s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock);
#ifdef CONFIG_NL80211_TESTMODE
int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len);
#else
static inline int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
{
return 0;
}
#ifndef WL_ERR
#define WL_ERR CFG80211_ERR
#endif
#ifndef WL_TRACE
#define WL_TRACE CFG80211_TRACE
#endif
int wl_cfg80211_btcoex_init(struct wl_priv *wl);
void wl_cfg80211_btcoex_deinit(struct wl_priv *wl);
s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg);
s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg);
s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg);
s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val);
s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg);
s32 dhd_config_dongle(struct bcm_cfg80211 *cfg);
#endif /* __DHD_CFG80211__ */

View File

@ -0,0 +1,151 @@
/*
* Linux cfg80211 vendor command/event handlers of DHD
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_cfg_vendor.c 487126 2014-06-24 23:06:12Z $
*/
#include <linuxver.h>
#include <net/cfg80211.h>
#include <net/netlink.h>
#include <bcmutils.h>
#include <wl_cfg80211.h>
#include <wl_cfgvendor.h>
#include <dngl_stats.h>
#include <dhd.h>
#include <dhdioctl.h>
#include <brcm_nl80211.h>
#ifdef VENDOR_EXT_SUPPORT
static int dhd_cfgvendor_priv_string_handler(struct wiphy *wiphy,
struct wireless_dev *wdev, const void *data, int len)
{
const struct bcm_nlmsg_hdr *nlioc = data;
struct net_device *ndev = NULL;
struct bcm_cfg80211 *cfg;
struct sk_buff *reply;
void *buf = NULL, *cur;
dhd_pub_t *dhd;
dhd_ioctl_t ioc = { 0 };
int ret = 0, ret_len, payload, msglen;
int maxmsglen = PAGE_SIZE - 0x100;
int8 index;
WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));
DHD_ERROR(("entry: cmd = %d\n", nlioc->cmd));
cfg = wiphy_priv(wiphy);
dhd = cfg->pub;
DHD_OS_WAKE_LOCK(dhd);
/* send to dongle only if we are not waiting for reload already */
if (dhd->hang_was_sent) {
WL_ERR(("HANG was sent up earlier\n"));
DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
DHD_OS_WAKE_UNLOCK(dhd);
return OSL_ERROR(BCME_DONGLE_DOWN);
}
len -= sizeof(struct bcm_nlmsg_hdr);
ret_len = nlioc->len;
if (ret_len > 0 || len > 0) {
if (len > DHD_IOCTL_MAXLEN) {
WL_ERR(("oversize input buffer %d\n", len));
len = DHD_IOCTL_MAXLEN;
}
if (ret_len > DHD_IOCTL_MAXLEN) {
WL_ERR(("oversize return buffer %d\n", ret_len));
ret_len = DHD_IOCTL_MAXLEN;
}
payload = max(ret_len, len) + 1;
buf = vzalloc(payload);
if (!buf) {
DHD_OS_WAKE_UNLOCK(dhd);
return -ENOMEM;
}
memcpy(buf, (void *)nlioc + nlioc->offset, len);
*(char *)(buf + len) = '\0';
}
ndev = wdev_to_wlc_ndev(wdev, cfg);
index = dhd_net2idx(dhd->info, ndev);
if (index == DHD_BAD_IF) {
WL_ERR(("Bad ifidx from wdev:%p\n", wdev));
ret = BCME_ERROR;
goto done;
}
ioc.cmd = nlioc->cmd;
ioc.len = nlioc->len;
ioc.set = nlioc->set;
ioc.driver = nlioc->magic;
ret = dhd_ioctl_process(dhd, index, &ioc, buf);
if (ret) {
WL_TRACE(("dhd_ioctl_process return err %d\n", ret));
ret = OSL_ERROR(ret);
goto done;
}
cur = buf;
while (ret_len > 0) {
msglen = nlioc->len > maxmsglen ? maxmsglen : ret_len;
ret_len -= msglen;
payload = msglen + sizeof(msglen);
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
if (!reply) {
WL_ERR(("Failed to allocate reply msg\n"));
ret = -ENOMEM;
break;
}
if (nla_put(reply, BCM_NLATTR_DATA, msglen, cur) ||
nla_put_u16(reply, BCM_NLATTR_LEN, msglen)) {
kfree_skb(reply);
ret = -ENOBUFS;
break;
}
ret = cfg80211_vendor_cmd_reply(reply);
if (ret) {
WL_ERR(("testmode reply failed:%d\n", ret));
break;
}
cur += msglen;
}
done:
vfree(buf);
DHD_OS_WAKE_UNLOCK(dhd);
return ret;
}
const struct wiphy_vendor_command dhd_cfgvendor_cmds [] = {
{
{
.vendor_id = OUI_BRCM,
.subcmd = BRCM_VENDOR_SCMD_PRIV_STR
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = dhd_cfgvendor_priv_string_handler
},
};
int cfgvendor_attach(struct wiphy *wiphy)
{
wiphy->vendor_commands = dhd_cfgvendor_cmds;
wiphy->n_vendor_commands = ARRAY_SIZE(dhd_cfgvendor_cmds);
return 0;
}
int cfgvendor_detach(struct wiphy *wiphy)
{
wiphy->vendor_commands = NULL;
wiphy->n_vendor_commands = 0;
return 0;
}
#endif /* VENDOR_EXT_SUPPORT */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,15 +7,31 @@
#include <dhd.h>
#include <wlioctl.h>
#include <proto/802.11.h>
#ifdef POWER_OFF_IN_SUSPEND
#include <wl_android.h>
#include <bcmsdbus.h>
#include <linux/mmc/sdio_func.h>
#endif
#define FW_PATH_AUTO_SELECT 1
extern char firmware_path[MOD_PARAM_PATHLEN];
extern int disable_proptx;
extern uint dhd_doflow;
/* mac range */
typedef struct wl_mac_range {
uint32 oui;
uint32 nic_start;
uint32 nic_end;
} wl_mac_range_t;
/* mac list */
typedef struct wl_mac_list {
int count;
wl_mac_range_t *mac;
char name[MOD_PARAM_PATHLEN]; /* path */
} wl_mac_list_t;
/* mac list head */
typedef struct wl_mac_list_ctrl {
int count;
struct wl_mac_list *m_mac_list_head;
} wl_mac_list_ctrl_t;
/* channel list */
typedef struct wl_channel_list {
@ -31,10 +47,35 @@ typedef struct wmes_param {
int cwmax[AC_COUNT];
} wme_param_t;
#ifdef PKT_FILTER_SUPPORT
#define DHD_CONF_FILTER_MAX 8
/* filter list */
#define PKT_FILTER_LEN 150
typedef struct conf_pkt_filter_add {
/* in - # of channels, out - # of entries */
uint32 count;
/* variable length filter list */
char filter[DHD_CONF_FILTER_MAX][PKT_FILTER_LEN];
} conf_pkt_filter_add_t;
/* pkt_filter_del list */
typedef struct conf_pkt_filter_del {
/* in - # of channels, out - # of entries */
uint32 count;
/* variable length filter list */
uint32 id[DHD_CONF_FILTER_MAX];
} conf_pkt_filter_del_t;
#endif
typedef struct dhd_conf {
uint chip; /* chip number */
uint chiprev; /* chip revision */
wl_mac_list_ctrl_t fw_by_mac; /* Firmware auto selection by MAC */
wl_mac_list_ctrl_t nv_by_mac; /* NVRAM auto selection by MAC */
char fw_path[MOD_PARAM_PATHLEN]; /* Firmware path */
char nv_path[MOD_PARAM_PATHLEN]; /* NVRAM path */
uint band; /* Band, b:2.4G only, otherwise for auto */
int mimo_bw_cap; /* Bandwidth, 0:HT20ALL, 1: HT40ALL, 2:HT20IN2G_HT40PIN5G */
wl_country_t cspec; /* Country */
wl_channel_list_t channels; /* Support channels */
uint roam_off; /* Roaming, 0:enable, 1:disable */
@ -43,50 +84,61 @@ typedef struct dhd_conf {
int roam_scan_period[2]; /* Roaming scan period */
int roam_delta[2]; /* Roaming candidate qualification delta */
int fullroamperiod; /* Full Roaming period */
uint filter_out_all_packets; /* Filter out all packets in early suspend */
uint keep_alive_period; /* The perioid in ms to send keep alive packet */
uint force_wme_ac;
wme_param_t wme; /* WME parameters */
int stbc; /* STBC for Tx/Rx */
int phy_oclscdenable; /* phy_oclscdenable */
#ifdef PKT_FILTER_SUPPORT
conf_pkt_filter_add_t pkt_filter_add; /* Packet filter add */
conf_pkt_filter_del_t pkt_filter_del; /* Packet filter add */
#endif
int srl; /* short retry limit */
int lrl; /* long retry limit */
uint bcn_timeout; /* beacon timeout */
uint32 bus_txglom; /* bus:txglom */
uint32 ampdu_ba_wsize;
bool kso_enable;
int spect;
} dhd_conf_t;
void dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *dst, char *src);
void dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *fw_path);
void dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path);
void dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path);
#if defined(HW_OOB)
void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip);
#endif
void dhd_conf_set_fw_path(dhd_pub_t *dhd, char *fw_path);
void dhd_conf_set_nv_path(dhd_pub_t *dhd, char *nv_path);
int dhd_conf_set_band(dhd_pub_t *dhd);
uint dhd_conf_get_band(dhd_pub_t *dhd);
int dhd_conf_set_country(dhd_pub_t *dhd);
int dhd_conf_get_country(dhd_pub_t *dhd);
int dhd_conf_get_country(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);
int dhd_conf_set_roam(dhd_pub_t *dhd);
void dhd_conf_set_bw(dhd_pub_t *dhd);
void dhd_conf_set_mimo_bw_cap(dhd_pub_t *dhd);
void dhd_conf_force_wme(dhd_pub_t *dhd);
void dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp);
void dhd_conf_set_wme(dhd_pub_t *dhd);
void dhd_conf_set_stbc(dhd_pub_t *dhd);
void dhd_conf_set_phyoclscdenable(dhd_pub_t *dhd);
int dhd_conf_download_config(dhd_pub_t *dhd);
void dhd_conf_add_pkt_filter(dhd_pub_t *dhd);
bool dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id);
void dhd_conf_discard_pkt_filter(dhd_pub_t *dhd);
void dhd_conf_set_srl(dhd_pub_t *dhd);
void dhd_conf_set_lrl(dhd_pub_t *dhd);
void dhd_conf_set_glom(dhd_pub_t *dhd);
void dhd_conf_set_ampdu_ba_wsize(dhd_pub_t *dhd);
void dhd_conf_set_spect(dhd_pub_t *dhd);
int dhd_conf_read_config(dhd_pub_t *dhd);
int dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev);
uint dhd_conf_get_chip(void *context);
uint dhd_conf_get_chiprev(void *context);
int dhd_conf_preinit(dhd_pub_t *dhd);
int dhd_conf_reset(dhd_pub_t *dhd);
int dhd_conf_attach(dhd_pub_t *dhd);
void dhd_conf_detach(dhd_pub_t *dhd);
extern void *bcmsdh_get_drvdata(void);
#ifdef POWER_OFF_IN_SUSPEND
extern struct net_device *g_netdev;
#if defined(CONFIG_HAS_EARLYSUSPEND)
extern int g_wifi_on;
#ifdef WL_CFG80211
void wl_cfg80211_stop(void);
void wl_cfg80211_send_disconnect(void);
void wl_cfg80211_user_sync(bool lock);
#endif
#endif
void dhd_conf_wifi_suspend(struct sdio_func *func);
void dhd_conf_register_wifi_suspend(struct sdio_func *func);
void dhd_conf_unregister_wifi_suspend(struct sdio_func *func);
#endif
void *dhd_get_pub(struct net_device *dev);
#endif /* _dhd_config_ */

View File

@ -2,16 +2,16 @@
* Customer code to add GPIO control during WLAN start/stop
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_custom_gpio.c 417465 2013-08-09 11:47:27Z $
* $Id: dhd_custom_gpio.c 447105 2014-01-08 05:27:09Z $
*/
#include <typedefs.h>
#include <linuxver.h>
#include <osl.h>
#include <bcmutils.h>
#include <dngl_stats.h>
#include <dhd.h>
#include <dhd_linux.h>
#include <wlioctl.h>
#include <wl_iw.h>
@ -19,30 +19,12 @@
#define WL_ERROR(x) printf x
#define WL_TRACE(x)
#ifdef CUSTOMER_HW
#if defined(CUSTOMER_OOB)
extern int bcm_wlan_get_oob_irq(void);
#endif
extern void bcm_wlan_power_off(int);
extern void bcm_wlan_power_on(int);
#endif /* CUSTOMER_HW */
#if defined(CUSTOMER_HW2)
#if defined(PLATFORM_MPS)
int __attribute__ ((weak)) wifi_get_fw_nv_path(char *fw, char *nv) { return 0;};
#endif
#ifdef CONFIG_WIFI_CONTROL_FUNC
int wifi_set_power(int on, unsigned long msec);
int wifi_get_irq_number(unsigned long *irq_flags_ptr);
int wifi_get_mac_addr(unsigned char *buf);
void *wifi_get_country_code(char *ccode);
#else
int wifi_set_power(int on, unsigned long msec) { return -1; }
int wifi_get_irq_number(unsigned long *irq_flags_ptr) { return -1; }
int wifi_get_mac_addr(unsigned char *buf) { return -1; }
void *wifi_get_country_code(char *ccode) { return NULL; }
#endif /* CONFIG_WIFI_CONTROL_FUNC */
#endif
#if defined(OOB_INTR_ONLY)
@ -72,15 +54,12 @@ MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
* Broadcom provides just reference settings as example.
*
*/
int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr)
{
int host_oob_irq = 0;
#if defined(CUSTOMER_HW2) && !defined(PLATFORM_MPS)
host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
#elif defined(CUSTOMER_OOB)
host_oob_irq = bcm_wlan_get_oob_irq();
host_oob_irq = wifi_platform_get_irq_number(adapter, irq_flags_ptr);
#else
#if defined(CUSTOM_OOB_GPIO_NUM)
@ -98,13 +77,11 @@ int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
__FUNCTION__, dhd_oob_gpio_num));
#if defined CUSTOMER_HW
host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
#elif defined CUSTOMER_HW3 || defined(PLATFORM_MPS)
#if defined CUSTOMER_HW3 || defined(PLATFORM_MPS)
gpio_request(dhd_oob_gpio_num, "oob irq");
host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
gpio_direction_input(dhd_oob_gpio_num);
#endif /* CUSTOMER_HW */
#endif /* defined CUSTOMER_HW3 || defined(PLATFORM_MPS) */
#endif
return (host_oob_irq);
@ -112,55 +89,12 @@ int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
#endif
/* Customer function to control hw specific wlan gpios */
void
dhd_customer_gpio_wlan_ctrl(int onoff)
int
dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff)
{
switch (onoff) {
case WLAN_RESET_OFF:
WL_TRACE(("%s: call customer specific GPIO to insert WLAN RESET\n",
__FUNCTION__));
#ifdef CUSTOMER_HW
bcm_wlan_power_off(2);
#endif /* CUSTOMER_HW */
#if defined(CUSTOMER_HW2)
wifi_set_power(0, WIFI_TURNOFF_DELAY);
#endif
WL_ERROR(("=========== WLAN placed in RESET ========\n"));
break;
int err = 0;
case WLAN_RESET_ON:
WL_TRACE(("%s: call customer specific GPIO to remove WLAN RESET\n",
__FUNCTION__));
#ifdef CUSTOMER_HW
bcm_wlan_power_on(2);
//OSL_DELAY(200);
#endif /* CUSTOMER_HW */
#if defined(CUSTOMER_HW2)
wifi_set_power(1, 200);
#endif
WL_ERROR(("=========== WLAN going back to live ========\n"));
break;
case WLAN_POWER_OFF:
WL_TRACE(("%s: call customer specific GPIO to turn off WL_REG_ON\n",
__FUNCTION__));
#ifdef CUSTOMER_HW
bcm_wlan_power_off(1);
#endif /* CUSTOMER_HW */
WL_ERROR(("=========== WLAN placed in POWER OFF ========\n"));
break;
case WLAN_POWER_ON:
WL_TRACE(("%s: call customer specific GPIO to turn on WL_REG_ON\n",
__FUNCTION__));
#ifdef CUSTOMER_HW
bcm_wlan_power_on(1);
#endif /* CUSTOMER_HW */
/* Lets customer power to get stable */
//OSL_DELAY(200);
WL_ERROR(("=========== WLAN placed in POWER ON ========\n"));
break;
}
return err;
}
#ifdef GET_CUSTOM_MAC_ENABLE
@ -169,7 +103,7 @@ int rockchip_wifi_mac_addr(unsigned char *buf);
#endif
/* Function to get custom MAC address */
int
dhd_custom_get_mac_address(unsigned char *buf)
dhd_custom_get_mac_address(void *adapter, unsigned char *buf)
{
int ret = 0;
@ -178,8 +112,9 @@ dhd_custom_get_mac_address(unsigned char *buf)
return -EINVAL;
/* Customer access to MAC address stored outside of DHD driver */
#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
ret = wifi_get_mac_addr(buf);
#if (defined(CUSTOMER_HW2) || defined(CUSTOMER_HW10)) && (LINUX_VERSION_CODE >= \
KERNEL_VERSION(2, 6, 35))
ret = wifi_platform_get_mac_addr(adapter, buf);
#endif
#if defined(CUSTOMER_HW)
@ -245,6 +180,68 @@ const struct cntry_locales_custom translate_custom_table[] = {
{"TR", "TR", 0},
{"NO", "NO", 0},
#endif /* EXMAPLE_TABLE */
#if defined(CUSTOMER_HW2)
#if defined(BCM4335_CHIP)
{"", "XZ", 11}, /* Universal if Country code is unknown or empty */
#endif
{"AE", "AE", 1},
{"AR", "AR", 1},
{"AT", "AT", 1},
{"AU", "AU", 2},
{"BE", "BE", 1},
{"BG", "BG", 1},
{"BN", "BN", 1},
{"CA", "CA", 2},
{"CH", "CH", 1},
{"CY", "CY", 1},
{"CZ", "CZ", 1},
{"DE", "DE", 3},
{"DK", "DK", 1},
{"EE", "EE", 1},
{"ES", "ES", 1},
{"FI", "FI", 1},
{"FR", "FR", 1},
{"GB", "GB", 1},
{"GR", "GR", 1},
{"HR", "HR", 1},
{"HU", "HU", 1},
{"IE", "IE", 1},
{"IS", "IS", 1},
{"IT", "IT", 1},
{"ID", "ID", 1},
{"JP", "JP", 8},
{"KR", "KR", 24},
{"KW", "KW", 1},
{"LI", "LI", 1},
{"LT", "LT", 1},
{"LU", "LU", 1},
{"LV", "LV", 1},
{"MA", "MA", 1},
{"MT", "MT", 1},
{"MX", "MX", 1},
{"NL", "NL", 1},
{"NO", "NO", 1},
{"PL", "PL", 1},
{"PT", "PT", 1},
{"PY", "PY", 1},
{"RO", "RO", 1},
{"SE", "SE", 1},
{"SI", "SI", 1},
{"SK", "SK", 1},
{"TR", "TR", 7},
{"TW", "TW", 1},
{"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */
{"SD", "XZ", 11}, /* Universal if Country code is SUDAN */
{"SY", "XZ", 11}, /* Universal if Country code is SYRIAN ARAB REPUBLIC */
{"GL", "XZ", 11}, /* Universal if Country code is GREENLAND */
{"PS", "XZ", 11}, /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */
{"TL", "XZ", 11}, /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */
{"MH", "XZ", 11}, /* Universal if Country code is MARSHALL ISLANDS */
#ifdef BCM4330_CHIP
{"RU", "RU", 1},
{"US", "US", 5}
#endif
#endif /* CUSTOMER_HW2 */
};
@ -252,7 +249,7 @@ const struct cntry_locales_custom translate_custom_table[] = {
* input : ISO 3166-1 country abbreviation
* output: customized cspec
*/
void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec)
{
#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
@ -261,7 +258,7 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
if (!cspec)
return;
cloc_ptr = wifi_get_country_code(country_iso_code);
cloc_ptr = wifi_platform_get_country_code(adapter, country_iso_code);
if (cloc_ptr) {
strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ);
cspec->rev = cloc_ptr->custom_locale_rev;

View File

@ -3,13 +3,13 @@
*
* $ Copyright Open Broadcom Corporation $
*
* $Id: dhd_dbg.h 419132 2013-08-19 21:33:05Z $
* $Id: dhd_dbg.h 491225 2014-07-15 11:58:29Z $
*/
#ifndef _dhd_dbg_
#define _dhd_dbg_
#define USE_NET_RATELIMIT net_ratelimit()
#define USE_NET_RATELIMIT 1
#if defined(DHD_DEBUG)
@ -32,6 +32,7 @@
#define DHD_PNO(args) do {if (dhd_msg_level & DHD_PNO_VAL) printf args;} while (0)
#define DHD_TRACE_HW4 DHD_TRACE
#define DHD_INFO_HW4 DHD_INFO
#define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL)
#define DHD_TRACE_ON() (dhd_msg_level & DHD_TRACE_VAL)
@ -71,6 +72,7 @@
#define DHD_PNO(args)
#define DHD_TRACE_HW4 DHD_TRACE
#define DHD_INFO_HW4 DHD_INFO
#define DHD_ERROR_ON() 0
#define DHD_TRACE_ON() 0

View File

@ -1,69 +1,103 @@
/*
* Customer code to add GPIO control during WLAN start/stop
* Copyright (C) 1999-2011, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
*
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
* you also meet, for each linked independent module, the terms and conditions of
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
* $Id: dhd_custom_gpio.c,v 1.2.42.1 2010-10-19 00:41:09 Exp $
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/rfkill.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <osl.h>
#include <linux/rfkill-wlan.h>
#ifdef CUSTOMER_HW
#ifdef CONFIG_MACH_ODROID_4210
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/sdhci.h>
#include <plat/devs.h> // modifed plat-samsung/dev-hsmmcX.c EXPORT_SYMBOL(s3c_device_hsmmcx) added
#define sdmmc_channel s3c_device_hsmmc0
#endif
struct wifi_platform_data {
int (*set_power)(bool val);
int (*set_carddetect)(bool val);
void *(*mem_prealloc)(int section, unsigned long size);
int (*get_mac_addr)(unsigned char *buf);
void *(*get_country_code)(char *ccode);
};
struct resource dhd_wlan_resources = {0};
struct wifi_platform_data dhd_wlan_control = {0};
#ifdef CUSTOMER_OOB
int bcm_wlan_get_oob_irq(void)
uint bcm_wlan_get_oob_irq(void)
{
return rockchip_wifi_get_oob_irq();
return rockchip_wifi_get_oob_irq();
}
uint bcm_wlan_get_oob_irq_flags(void)
{
uint host_oob_irq_flags = 0;
host_oob_irq_flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE) & IRQF_TRIGGER_MASK;
printk("host_oob_irq_flags=%d\n", host_oob_irq_flags);
return host_oob_irq_flags;
}
#endif
void bcm_wlan_power_on(int flag)
int bcm_wlan_set_power(bool on)
{
if (flag == 1) {
int err = 0;
if (on) {
printk("======== PULL WL_REG_ON HIGH! ========\n");
rockchip_wifi_power(1);
rockchip_wifi_set_carddetect(1);
} else {
printk("======== PULL WL_REG_ON HIGH! (flag = %d) ========\n", flag);
rockchip_wifi_power(1);
printk("======== PULL WL_REG_ON LOW! ========\n");
rockchip_wifi_power(0);
}
return err;
}
void bcm_wlan_power_off(int flag)
int bcm_wlan_set_carddetect(bool present)
{
if (flag == 1) {
printk("======== Card detection to remove SDIO card! ========\n");
rockchip_wifi_power(1);
rockchip_wifi_set_carddetect(0);
rockchip_wifi_power(0);
int err = 0;
if (present) {
printk("======== Card detection to detect SDIO card! ========\n");
rockchip_wifi_set_carddetect(1);
} else {
printk("======== PULL WL_REG_ON LOW! (flag = %d) ========\n", flag);
rockchip_wifi_power(0);
printk("======== Card detection to remove SDIO card! ========\n");
rockchip_wifi_set_carddetect(0);
}
return err;
}
#ifdef CONFIG_DHD_USE_STATIC_BUF
extern void *bcmdhd_mem_prealloc(int section, unsigned long size);
void* bcm_wlan_prealloc(int section, unsigned long size)
{
void *alloc_ptr = NULL;
alloc_ptr = bcmdhd_mem_prealloc(section, size);
if (alloc_ptr) {
printk("success alloc section %d, size %ld\n", section, size);
if (size != 0L)
bzero(alloc_ptr, size);
return alloc_ptr;
}
printk("can't alloc section %d\n", section);
return NULL;
}
#endif
int bcm_wlan_set_plat_data(void) {
printk("======== %s ========\n", __FUNCTION__);
dhd_wlan_control.set_power = bcm_wlan_set_power;
dhd_wlan_control.set_carddetect = bcm_wlan_set_carddetect;
#ifdef CONFIG_DHD_USE_STATIC_BUF
dhd_wlan_control.mem_prealloc = bcm_wlan_prealloc;
#endif
return 0;
}
#endif /* CUSTOMER_HW */

853
drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c Normal file → Executable file
View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id$
* $Id: dhd_ip.c 468932 2014-04-09 06:58:15Z $
*/
#include <typedefs.h>
#include <osl.h>
@ -18,6 +18,12 @@
#include <dhd_ip.h>
#ifdef DHDTCPACK_SUPPRESS
#include <dhd_bus.h>
#include <dhd_proto.h>
#include <proto/bcmtcp.h>
#endif /* DHDTCPACK_SUPPRESS */
/* special values */
/* 802.3 llc/snap header */
static const uint8 llc_snap_hdr[SNAP_HDR_LEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
@ -73,7 +79,7 @@ pkt_frag_t pkt_frag_info(osl_t *osh, void *p)
}
iph = (struct ipv4_hdr *)(pt + ETHER_TYPE_LEN);
ipl = length - (pt + ETHER_TYPE_LEN - frame);
ipl = (uint)(length - (pt + ETHER_TYPE_LEN - frame));
/* We support IPv4 only */
if ((ipl < IPV4_OPTIONS_OFFSET) || (IP_VER(iph) != IP_VER_4)) {
@ -91,3 +97,846 @@ pkt_frag_t pkt_frag_info(osl_t *osh, void *p)
return (iph_frag & IPV4_FRAG_OFFSET_MASK)? DHD_PKT_FRAG_CONT : DHD_PKT_FRAG_FIRST;
}
}
#ifdef DHDTCPACK_SUPPRESS
typedef struct {
void *pkt_in_q; /* TCP ACK packet that is already in txq or DelayQ */
void *pkt_ether_hdr; /* Ethernet header pointer of pkt_in_q */
} tcpack_info_t;
typedef struct _tdata_psh_info_t {
uint32 end_seq; /* end seq# of a received TCP PSH DATA pkt */
struct _tdata_psh_info_t *next; /* next pointer of the link chain */
} tdata_psh_info_t;
typedef struct {
uint8 src_ip_addr[IPV4_ADDR_LEN]; /* SRC ip addrs of this TCP stream */
uint8 dst_ip_addr[IPV4_ADDR_LEN]; /* DST ip addrs of this TCP stream */
uint8 src_tcp_port[TCP_PORT_LEN]; /* SRC tcp ports of this TCP stream */
uint8 dst_tcp_port[TCP_PORT_LEN]; /* DST tcp ports of this TCP stream */
tdata_psh_info_t *tdata_psh_info_head; /* Head of received TCP PSH DATA chain */
tdata_psh_info_t *tdata_psh_info_tail; /* Tail of received TCP PSH DATA chain */
uint32 last_used_time; /* The last time this tcpdata_info was used(in ms) */
} tcpdata_info_t;
/* TCPACK SUPPRESS module */
typedef struct {
int tcpack_info_cnt;
tcpack_info_t tcpack_info_tbl[TCPACK_INFO_MAXNUM]; /* Info of TCP ACK to send */
int tcpdata_info_cnt;
tcpdata_info_t tcpdata_info_tbl[TCPDATA_INFO_MAXNUM]; /* Info of received TCP DATA */
tdata_psh_info_t *tdata_psh_info_pool; /* Pointer to tdata_psh_info elements pool */
tdata_psh_info_t *tdata_psh_info_free; /* free tdata_psh_info elements chain in pool */
#ifdef DHDTCPACK_SUP_DBG
int psh_info_enq_num; /* Number of free TCP PSH DATA info elements in pool */
#endif /* DHDTCPACK_SUP_DBG */
} tcpack_sup_module_t;
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
counter_tbl_t tack_tbl = {"tcpACK", 0, 1000, 10, {0, }, 1};
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
static void
_tdata_psh_info_pool_enq(tcpack_sup_module_t *tcpack_sup_mod,
tdata_psh_info_t *tdata_psh_info)
{
if ((tcpack_sup_mod == NULL) || (tdata_psh_info == NULL)) {
DHD_ERROR(("%s %d: ERROR %p %p\n", __FUNCTION__, __LINE__,
tcpack_sup_mod, tdata_psh_info));
return;
}
ASSERT(tdata_psh_info->next == NULL);
tdata_psh_info->next = tcpack_sup_mod->tdata_psh_info_free;
tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info;
#ifdef DHDTCPACK_SUP_DBG
tcpack_sup_mod->psh_info_enq_num++;
#endif
}
static tdata_psh_info_t*
_tdata_psh_info_pool_deq(tcpack_sup_module_t *tcpack_sup_mod)
{
tdata_psh_info_t *tdata_psh_info = NULL;
if (tcpack_sup_mod == NULL) {
DHD_ERROR(("%s %d: ERROR %p\n", __FUNCTION__, __LINE__,
tcpack_sup_mod));
return NULL;
}
tdata_psh_info = tcpack_sup_mod->tdata_psh_info_free;
if (tdata_psh_info == NULL)
DHD_ERROR(("%s %d: Out of tdata_disc_grp\n", __FUNCTION__, __LINE__));
else {
tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info->next;
tdata_psh_info->next = NULL;
#ifdef DHDTCPACK_SUP_DBG
tcpack_sup_mod->psh_info_enq_num--;
#endif /* DHDTCPACK_SUP_DBG */
}
return tdata_psh_info;
}
static int _tdata_psh_info_pool_init(dhd_pub_t *dhdp,
tcpack_sup_module_t *tcpack_sup_mod)
{
tdata_psh_info_t *tdata_psh_info_pool = NULL;
uint i;
DHD_TRACE(("%s %d: Enter\n", __FUNCTION__, __LINE__));
if (tcpack_sup_mod == NULL)
return BCME_ERROR;
ASSERT(tcpack_sup_mod->tdata_psh_info_pool == NULL);
ASSERT(tcpack_sup_mod->tdata_psh_info_free == NULL);
tdata_psh_info_pool =
MALLOC(dhdp->osh, sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
if (tdata_psh_info_pool == NULL)
return BCME_NOMEM;
bzero(tdata_psh_info_pool, sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
#ifdef DHDTCPACK_SUP_DBG
tcpack_sup_mod->psh_info_enq_num = 0;
#endif /* DHDTCPACK_SUP_DBG */
/* Enqueue newly allocated tcpdata psh info elements to the pool */
for (i = 0; i < TCPDATA_PSH_INFO_MAXNUM; i++)
_tdata_psh_info_pool_enq(tcpack_sup_mod, &tdata_psh_info_pool[i]);
ASSERT(tcpack_sup_mod->tdata_psh_info_free != NULL);
tcpack_sup_mod->tdata_psh_info_pool = tdata_psh_info_pool;
return BCME_OK;
}
static void _tdata_psh_info_pool_deinit(dhd_pub_t *dhdp,
tcpack_sup_module_t *tcpack_sup_mod)
{
uint i;
tdata_psh_info_t *tdata_psh_info;
DHD_TRACE(("%s %d: Enter\n", __FUNCTION__, __LINE__));
if (tcpack_sup_mod == NULL) {
DHD_ERROR(("%s %d: ERROR tcpack_sup_mod NULL!\n",
__FUNCTION__, __LINE__));
return;
}
for (i = 0; i < tcpack_sup_mod->tcpdata_info_cnt; i++) {
tcpdata_info_t *tcpdata_info = &tcpack_sup_mod->tcpdata_info_tbl[i];
/* Return tdata_psh_info elements allocated to each tcpdata_info to the pool */
while ((tdata_psh_info = tcpdata_info->tdata_psh_info_head)) {
tcpdata_info->tdata_psh_info_head = tdata_psh_info->next;
tdata_psh_info->next = NULL;
_tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info);
}
tcpdata_info->tdata_psh_info_tail = NULL;
}
#ifdef DHDTCPACK_SUP_DBG
DHD_ERROR(("%s %d: PSH INFO ENQ %d\n",
__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
#endif /* DHDTCPACK_SUP_DBG */
i = 0;
/* Be sure we recollected all tdata_psh_info elements */
while ((tdata_psh_info = tcpack_sup_mod->tdata_psh_info_free)) {
tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info->next;
tdata_psh_info->next = NULL;
i++;
}
ASSERT(i == TCPDATA_PSH_INFO_MAXNUM);
MFREE(dhdp->osh, tcpack_sup_mod->tdata_psh_info_pool,
sizeof(tdata_psh_info_t) * TCPDATA_PSH_INFO_MAXNUM);
tcpack_sup_mod->tdata_psh_info_pool = NULL;
return;
}
int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode)
{
int ret = BCME_OK;
dhd_os_tcpacklock(dhdp);
if (dhdp->tcpack_sup_mode == mode) {
DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode));
goto exit;
}
if (mode >= TCPACK_SUP_LAST_MODE ||
#ifndef BCMSDIO
mode == TCPACK_SUP_DELAYTX ||
#endif
FALSE) {
DHD_ERROR(("%s %d: Invalid mode %d\n", __FUNCTION__, __LINE__, mode));
ret = BCME_BADARG;
goto exit;
}
DHD_TRACE(("%s: %d -> %d\n",
__FUNCTION__, dhdp->tcpack_sup_mode, mode));
/* Old tcpack_sup_mode is TCPACK_SUP_DELAYTX */
if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX) {
tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
/* We won't need tdata_psh_info pool and tcpddata_info_tbl anymore */
_tdata_psh_info_pool_deinit(dhdp, tcpack_sup_mod);
tcpack_sup_mod->tcpdata_info_cnt = 0;
bzero(tcpack_sup_mod->tcpdata_info_tbl,
sizeof(tcpdata_info_t) * TCPDATA_INFO_MAXNUM);
/* For half duplex bus interface, tx precedes rx by default */
if (dhdp->bus)
dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
}
dhdp->tcpack_sup_mode = mode;
if (mode == TCPACK_SUP_OFF) {
ASSERT(dhdp->tcpack_sup_module != NULL);
MFREE(dhdp->osh, dhdp->tcpack_sup_module, sizeof(tcpack_sup_module_t));
dhdp->tcpack_sup_module = NULL;
goto exit;
}
if (dhdp->tcpack_sup_module == NULL) {
tcpack_sup_module_t *tcpack_sup_mod =
MALLOC(dhdp->osh, sizeof(tcpack_sup_module_t));
if (tcpack_sup_mod == NULL) {
DHD_ERROR(("%s %d: No MEM\n", __FUNCTION__, __LINE__));
dhdp->tcpack_sup_mode = TCPACK_SUP_OFF;
ret = BCME_NOMEM;
goto exit;
}
bzero(tcpack_sup_mod, sizeof(tcpack_sup_module_t));
dhdp->tcpack_sup_module = tcpack_sup_mod;
}
if (mode == TCPACK_SUP_DELAYTX) {
ret = _tdata_psh_info_pool_init(dhdp, dhdp->tcpack_sup_module);
if (ret != BCME_OK)
DHD_ERROR(("%s %d: pool init fail with %d\n", __FUNCTION__, __LINE__, ret));
else if (dhdp->bus)
dhd_bus_set_dotxinrx(dhdp->bus, FALSE);
}
exit:
dhd_os_tcpackunlock(dhdp);
return ret;
}
void
dhd_tcpack_info_tbl_clean(dhd_pub_t *dhdp)
{
tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
goto exit;
dhd_os_tcpacklock(dhdp);
if (!tcpack_sup_mod) {
DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n",
__FUNCTION__, __LINE__));
dhd_os_tcpackunlock(dhdp);
goto exit;
}
tcpack_sup_mod->tcpack_info_cnt = 0;
bzero(tcpack_sup_mod->tcpack_info_tbl, sizeof(tcpack_info_t) * TCPACK_INFO_MAXNUM);
dhd_os_tcpackunlock(dhdp);
exit:
return;
}
inline int dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt)
{
uint8 i;
tcpack_sup_module_t *tcpack_sup_mod;
tcpack_info_t *tcpack_info_tbl;
int tbl_cnt;
int ret = BCME_OK;
void *pdata;
uint32 pktlen;
if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
goto exit;
pdata = PKTDATA(dhdp->osh, pkt);
pktlen = PKTLEN(dhdp->osh, pkt) - dhd_prot_hdrlen(dhdp, pdata);
if (pktlen < TCPACKSZMIN || pktlen > TCPACKSZMAX) {
DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n",
__FUNCTION__, __LINE__, pktlen));
goto exit;
}
dhd_os_tcpacklock(dhdp);
tcpack_sup_mod = dhdp->tcpack_sup_module;
if (!tcpack_sup_mod) {
DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
ret = BCME_ERROR;
dhd_os_tcpackunlock(dhdp);
goto exit;
}
tbl_cnt = tcpack_sup_mod->tcpack_info_cnt;
tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl;
ASSERT(tbl_cnt <= TCPACK_INFO_MAXNUM);
for (i = 0; i < tbl_cnt; i++) {
if (tcpack_info_tbl[i].pkt_in_q == pkt) {
DHD_TRACE(("%s %d: pkt %p sent out. idx %d, tbl_cnt %d\n",
__FUNCTION__, __LINE__, pkt, i, tbl_cnt));
/* This pkt is being transmitted so remove the tcp_ack_info of it. */
if (i < tbl_cnt - 1) {
bcopy(&tcpack_info_tbl[tbl_cnt - 1],
&tcpack_info_tbl[i], sizeof(tcpack_info_t));
}
bzero(&tcpack_info_tbl[tbl_cnt - 1], sizeof(tcpack_info_t));
if (--tcpack_sup_mod->tcpack_info_cnt < 0) {
DHD_ERROR(("%s %d: ERROR!!! tcp_ack_info_cnt %d\n",
__FUNCTION__, __LINE__, tcpack_sup_mod->tcpack_info_cnt));
ret = BCME_ERROR;
}
break;
}
}
dhd_os_tcpackunlock(dhdp);
exit:
return ret;
}
static INLINE bool dhd_tcpdata_psh_acked(dhd_pub_t *dhdp, uint8 *ip_hdr,
uint8 *tcp_hdr, uint32 tcp_ack_num)
{
tcpack_sup_module_t *tcpack_sup_mod;
int i;
tcpdata_info_t *tcpdata_info = NULL;
tdata_psh_info_t *tdata_psh_info = NULL;
bool ret = FALSE;
if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX)
goto exit;
tcpack_sup_mod = dhdp->tcpack_sup_module;
if (!tcpack_sup_mod) {
DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
goto exit;
}
DHD_TRACE(("%s %d: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
" TCP port %d %d, ack %u\n", __FUNCTION__, __LINE__,
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]),
tcp_ack_num));
for (i = 0; i < tcpack_sup_mod->tcpdata_info_cnt; i++) {
tcpdata_info_t *tcpdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i];
DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
" TCP port %d %d\n", __FUNCTION__, __LINE__, i,
IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->src_ip_addr)),
IPV4_ADDR_TO_STR(ntoh32_ua(tcpdata_info_tmp->dst_ip_addr)),
ntoh16_ua(tcpdata_info_tmp->src_tcp_port),
ntoh16_ua(tcpdata_info_tmp->dst_tcp_port)));
/* If either IP address or TCP port number does not match, skip. */
if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET],
tcpdata_info_tmp->dst_ip_addr, IPV4_ADDR_LEN) == 0 &&
memcmp(&ip_hdr[IPV4_DEST_IP_OFFSET],
tcpdata_info_tmp->src_ip_addr, IPV4_ADDR_LEN) == 0 &&
memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET],
tcpdata_info_tmp->dst_tcp_port, TCP_PORT_LEN) == 0 &&
memcmp(&tcp_hdr[TCP_DEST_PORT_OFFSET],
tcpdata_info_tmp->src_tcp_port, TCP_PORT_LEN) == 0) {
tcpdata_info = tcpdata_info_tmp;
break;
}
}
if (tcpdata_info == NULL) {
DHD_TRACE(("%s %d: no tcpdata_info!\n", __FUNCTION__, __LINE__));
goto exit;
}
if (tcpdata_info->tdata_psh_info_head == NULL) {
DHD_TRACE(("%s %d: No PSH DATA to be acked!\n", __FUNCTION__, __LINE__));
}
while ((tdata_psh_info = tcpdata_info->tdata_psh_info_head)) {
if (IS_TCPSEQ_GE(tcp_ack_num, tdata_psh_info->end_seq)) {
DHD_TRACE(("%s %d: PSH ACKED! %u >= %u\n",
__FUNCTION__, __LINE__, tcp_ack_num, tdata_psh_info->end_seq));
tcpdata_info->tdata_psh_info_head = tdata_psh_info->next;
tdata_psh_info->next = NULL;
_tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info);
ret = TRUE;
} else
break;
}
if (tdata_psh_info == NULL)
tcpdata_info->tdata_psh_info_tail = NULL;
#ifdef DHDTCPACK_SUP_DBG
DHD_TRACE(("%s %d: PSH INFO ENQ %d\n",
__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
#endif /* DHDTCPACK_SUP_DBG */
exit:
return ret;
}
bool
dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt)
{
uint8 *new_ether_hdr; /* Ethernet header of the new packet */
uint16 new_ether_type; /* Ethernet type of the new packet */
uint8 *new_ip_hdr; /* IP header of the new packet */
uint8 *new_tcp_hdr; /* TCP header of the new packet */
uint32 new_ip_hdr_len; /* IP header length of the new packet */
uint32 cur_framelen;
uint32 new_tcp_ack_num; /* TCP acknowledge number of the new packet */
uint16 new_ip_total_len; /* Total length of IP packet for the new packet */
uint32 new_tcp_hdr_len; /* TCP header length of the new packet */
tcpack_sup_module_t *tcpack_sup_mod;
tcpack_info_t *tcpack_info_tbl;
int i;
bool ret = FALSE;
bool set_dotxinrx = TRUE;
if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF)
goto exit;
new_ether_hdr = PKTDATA(dhdp->osh, pkt);
cur_framelen = PKTLEN(dhdp->osh, pkt);
if (cur_framelen < TCPACKSZMIN || cur_framelen > TCPACKSZMAX) {
DHD_TRACE(("%s %d: Too short or long length %d to be TCP ACK\n",
__FUNCTION__, __LINE__, cur_framelen));
goto exit;
}
new_ether_type = new_ether_hdr[12] << 8 | new_ether_hdr[13];
if (new_ether_type != ETHER_TYPE_IP) {
DHD_TRACE(("%s %d: Not a IP packet 0x%x\n",
__FUNCTION__, __LINE__, new_ether_type));
goto exit;
}
DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, new_ether_type));
new_ip_hdr = new_ether_hdr + ETHER_HDR_LEN;
cur_framelen -= ETHER_HDR_LEN;
ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN);
new_ip_hdr_len = IPV4_HLEN(new_ip_hdr);
if (IP_VER(new_ip_hdr) != IP_VER_4 || IPV4_PROT(new_ip_hdr) != IP_PROT_TCP) {
DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n",
__FUNCTION__, __LINE__, IP_VER(new_ip_hdr), IPV4_PROT(new_ip_hdr)));
goto exit;
}
new_tcp_hdr = new_ip_hdr + new_ip_hdr_len;
cur_framelen -= new_ip_hdr_len;
ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN);
DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__));
/* is it an ack ? Allow only ACK flag, not to suppress others. */
if (new_tcp_hdr[TCP_FLAGS_OFFSET] != TCP_FLAG_ACK) {
DHD_TRACE(("%s %d: Do not touch TCP flag 0x%x\n",
__FUNCTION__, __LINE__, new_tcp_hdr[TCP_FLAGS_OFFSET]));
goto exit;
}
new_ip_total_len = ntoh16_ua(&new_ip_hdr[IPV4_PKTLEN_OFFSET]);
new_tcp_hdr_len = 4 * TCP_HDRLEN(new_tcp_hdr[TCP_HLEN_OFFSET]);
/* This packet has TCP data, so just send */
if (new_ip_total_len > new_ip_hdr_len + new_tcp_hdr_len) {
DHD_TRACE(("%s %d: Do nothing for TCP DATA\n", __FUNCTION__, __LINE__));
goto exit;
}
ASSERT(new_ip_total_len == new_ip_hdr_len + new_tcp_hdr_len);
new_tcp_ack_num = ntoh32_ua(&new_tcp_hdr[TCP_ACK_NUM_OFFSET]);
DHD_TRACE(("%s %d: TCP ACK with zero DATA length"
" IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n",
__FUNCTION__, __LINE__,
IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_SRC_IP_OFFSET])),
IPV4_ADDR_TO_STR(ntoh32_ua(&new_ip_hdr[IPV4_DEST_IP_OFFSET])),
ntoh16_ua(&new_tcp_hdr[TCP_SRC_PORT_OFFSET]),
ntoh16_ua(&new_tcp_hdr[TCP_DEST_PORT_OFFSET])));
/* Look for tcp_ack_info that has the same ip src/dst addrs and tcp src/dst ports */
dhd_os_tcpacklock(dhdp);
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
counter_printlog(&tack_tbl);
tack_tbl.cnt[0]++;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
tcpack_sup_mod = dhdp->tcpack_sup_module;
tcpack_info_tbl = tcpack_sup_mod->tcpack_info_tbl;
if (!tcpack_sup_mod) {
DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
ret = BCME_ERROR;
dhd_os_tcpackunlock(dhdp);
goto exit;
}
if (dhd_tcpdata_psh_acked(dhdp, new_ip_hdr, new_tcp_hdr, new_tcp_ack_num)) {
/* This TCPACK is ACK to TCPDATA PSH pkt, so keep set_dotxinrx TRUE */
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
tack_tbl.cnt[5]++;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
} else
set_dotxinrx = FALSE;
for (i = 0; i < tcpack_sup_mod->tcpack_info_cnt; i++) {
void *oldpkt; /* TCPACK packet that is already in txq or DelayQ */
uint8 *old_ether_hdr, *old_ip_hdr, *old_tcp_hdr;
uint32 old_ip_hdr_len, old_tcp_hdr_len;
uint32 old_tcpack_num; /* TCP ACK number of old TCPACK packet in Q */
if ((oldpkt = tcpack_info_tbl[i].pkt_in_q) == NULL) {
DHD_ERROR(("%s %d: Unexpected error!! cur idx %d, ttl cnt %d\n",
__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt));
break;
}
if (PKTDATA(dhdp->osh, oldpkt) == NULL) {
DHD_ERROR(("%s %d: oldpkt data NULL!! cur idx %d, ttl cnt %d\n",
__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpack_info_cnt));
break;
}
old_ether_hdr = tcpack_info_tbl[i].pkt_ether_hdr;
old_ip_hdr = old_ether_hdr + ETHER_HDR_LEN;
old_ip_hdr_len = IPV4_HLEN(old_ip_hdr);
old_tcp_hdr = old_ip_hdr + old_ip_hdr_len;
old_tcp_hdr_len = 4 * TCP_HDRLEN(old_tcp_hdr[TCP_HLEN_OFFSET]);
DHD_TRACE(("%s %d: oldpkt %p[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
" TCP port %d %d\n", __FUNCTION__, __LINE__, oldpkt, i,
IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_SRC_IP_OFFSET])),
IPV4_ADDR_TO_STR(ntoh32_ua(&old_ip_hdr[IPV4_DEST_IP_OFFSET])),
ntoh16_ua(&old_tcp_hdr[TCP_SRC_PORT_OFFSET]),
ntoh16_ua(&old_tcp_hdr[TCP_DEST_PORT_OFFSET])));
/* If either of IP address or TCP port number does not match, skip. */
if (memcmp(&new_ip_hdr[IPV4_SRC_IP_OFFSET],
&old_ip_hdr[IPV4_SRC_IP_OFFSET], IPV4_ADDR_LEN * 2) ||
memcmp(&new_tcp_hdr[TCP_SRC_PORT_OFFSET],
&old_tcp_hdr[TCP_SRC_PORT_OFFSET], TCP_PORT_LEN * 2))
continue;
old_tcpack_num = ntoh32_ua(&old_tcp_hdr[TCP_ACK_NUM_OFFSET]);
if (IS_TCPSEQ_GT(new_tcp_ack_num, old_tcpack_num)) {
/* New packet has higher TCP ACK number, so it replaces the old packet */
if (new_ip_hdr_len == old_ip_hdr_len &&
new_tcp_hdr_len == old_tcp_hdr_len) {
ASSERT(memcmp(new_ether_hdr, old_ether_hdr, ETHER_HDR_LEN) == 0);
bcopy(new_ip_hdr, old_ip_hdr, new_ip_total_len);
PKTFREE(dhdp->osh, pkt, FALSE);
DHD_TRACE(("%s %d: TCP ACK replace %u -> %u\n",
__FUNCTION__, __LINE__, old_tcpack_num, new_tcp_ack_num));
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
tack_tbl.cnt[2]++;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
ret = TRUE;
} else {
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
tack_tbl.cnt[6]++;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
DHD_TRACE(("%s %d: lenth mismatch %d != %d || %d != %d"
" ACK %u -> %u\n", __FUNCTION__, __LINE__,
new_ip_hdr_len, old_ip_hdr_len,
new_tcp_hdr_len, old_tcp_hdr_len,
old_tcpack_num, new_tcp_ack_num));
}
} else if (new_tcp_ack_num == old_tcpack_num) {
set_dotxinrx = TRUE;
/* TCPACK retransmission */
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
tack_tbl.cnt[3]++;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
} else {
DHD_TRACE(("%s %d: ACK number reverse old %u(0x%p) new %u(0x%p)\n",
__FUNCTION__, __LINE__, old_tcpack_num, oldpkt,
new_tcp_ack_num, pkt));
}
dhd_os_tcpackunlock(dhdp);
goto exit;
}
if (i == tcpack_sup_mod->tcpack_info_cnt && i < TCPACK_INFO_MAXNUM) {
/* No TCPACK packet with the same IP addr and TCP port is found
* in tcp_ack_info_tbl. So add this packet to the table.
*/
DHD_TRACE(("%s %d: Add pkt 0x%p(ether_hdr 0x%p) to tbl[%d]\n",
__FUNCTION__, __LINE__, pkt, new_ether_hdr,
tcpack_sup_mod->tcpack_info_cnt));
tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_in_q = pkt;
tcpack_info_tbl[tcpack_sup_mod->tcpack_info_cnt].pkt_ether_hdr = new_ether_hdr;
tcpack_sup_mod->tcpack_info_cnt++;
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
tack_tbl.cnt[1]++;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
} else {
ASSERT(i == tcpack_sup_mod->tcpack_info_cnt);
DHD_TRACE(("%s %d: No empty tcp ack info tbl\n",
__FUNCTION__, __LINE__));
}
dhd_os_tcpackunlock(dhdp);
exit:
/* Unless TCPACK_SUP_DELAYTX, dotxinrx is alwasy TRUE, so no need to set here */
if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX && set_dotxinrx)
dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
return ret;
}
bool
dhd_tcpdata_info_get(dhd_pub_t *dhdp, void *pkt)
{
uint8 *ether_hdr; /* Ethernet header of the new packet */
uint16 ether_type; /* Ethernet type of the new packet */
uint8 *ip_hdr; /* IP header of the new packet */
uint8 *tcp_hdr; /* TCP header of the new packet */
uint32 ip_hdr_len; /* IP header length of the new packet */
uint32 cur_framelen;
uint16 ip_total_len; /* Total length of IP packet for the new packet */
uint32 tcp_hdr_len; /* TCP header length of the new packet */
uint32 tcp_seq_num; /* TCP sequence number of the new packet */
uint16 tcp_data_len; /* TCP DATA length that excludes IP and TCP headers */
uint32 end_tcp_seq_num; /* TCP seq number of the last byte in the new packet */
tcpack_sup_module_t *tcpack_sup_mod;
tcpdata_info_t *tcpdata_info = NULL;
tdata_psh_info_t *tdata_psh_info;
int i;
bool ret = FALSE;
if (dhdp->tcpack_sup_mode != TCPACK_SUP_DELAYTX)
goto exit;
ether_hdr = PKTDATA(dhdp->osh, pkt);
cur_framelen = PKTLEN(dhdp->osh, pkt);
ether_type = ether_hdr[12] << 8 | ether_hdr[13];
if (ether_type != ETHER_TYPE_IP) {
DHD_TRACE(("%s %d: Not a IP packet 0x%x\n",
__FUNCTION__, __LINE__, ether_type));
goto exit;
}
DHD_TRACE(("%s %d: IP pkt! 0x%x\n", __FUNCTION__, __LINE__, ether_type));
ip_hdr = ether_hdr + ETHER_HDR_LEN;
cur_framelen -= ETHER_HDR_LEN;
ASSERT(cur_framelen >= IPV4_MIN_HEADER_LEN);
ip_hdr_len = IPV4_HLEN(ip_hdr);
if (IP_VER(ip_hdr) != IP_VER_4 || IPV4_PROT(ip_hdr) != IP_PROT_TCP) {
DHD_TRACE(("%s %d: Not IPv4 nor TCP! ip ver %d, prot %d\n",
__FUNCTION__, __LINE__, IP_VER(ip_hdr), IPV4_PROT(ip_hdr)));
goto exit;
}
tcp_hdr = ip_hdr + ip_hdr_len;
cur_framelen -= ip_hdr_len;
ASSERT(cur_framelen >= TCP_MIN_HEADER_LEN);
DHD_TRACE(("%s %d: TCP pkt!\n", __FUNCTION__, __LINE__));
ip_total_len = ntoh16_ua(&ip_hdr[IPV4_PKTLEN_OFFSET]);
tcp_hdr_len = 4 * TCP_HDRLEN(tcp_hdr[TCP_HLEN_OFFSET]);
/* This packet is mere TCP ACK, so do nothing */
if (ip_total_len == ip_hdr_len + tcp_hdr_len) {
DHD_TRACE(("%s %d: Do nothing for no data TCP ACK\n", __FUNCTION__, __LINE__));
goto exit;
}
ASSERT(ip_total_len > ip_hdr_len + tcp_hdr_len);
if ((tcp_hdr[TCP_FLAGS_OFFSET] & TCP_FLAG_PSH) == 0) {
DHD_TRACE(("%s %d: Not interested TCP DATA packet\n", __FUNCTION__, __LINE__));
goto exit;
}
DHD_TRACE(("%s %d: TCP DATA with nonzero DATA length"
" IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d, flag 0x%x\n",
__FUNCTION__, __LINE__,
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET]),
tcp_hdr[TCP_FLAGS_OFFSET]));
dhd_os_tcpacklock(dhdp);
tcpack_sup_mod = dhdp->tcpack_sup_module;
if (!tcpack_sup_mod) {
DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__));
ret = BCME_ERROR;
dhd_os_tcpackunlock(dhdp);
goto exit;
}
/* Look for tcpdata_info that has the same ip src/dst addrs and tcp src/dst ports */
i = 0;
while (i < tcpack_sup_mod->tcpdata_info_cnt) {
tcpdata_info_t *tdata_info_tmp = &tcpack_sup_mod->tcpdata_info_tbl[i];
uint32 now_in_ms = OSL_SYSUPTIME();
DHD_TRACE(("%s %d: data info[%d], IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
" TCP port %d %d\n", __FUNCTION__, __LINE__, i,
IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->src_ip_addr)),
IPV4_ADDR_TO_STR(ntoh32_ua(tdata_info_tmp->dst_ip_addr)),
ntoh16_ua(tdata_info_tmp->src_tcp_port),
ntoh16_ua(tdata_info_tmp->dst_tcp_port)));
/* If both IP address and TCP port number match, we found it so break. */
if (memcmp(&ip_hdr[IPV4_SRC_IP_OFFSET],
tdata_info_tmp->src_ip_addr, IPV4_ADDR_LEN * 2) == 0 &&
memcmp(&tcp_hdr[TCP_SRC_PORT_OFFSET],
tdata_info_tmp->src_tcp_port, TCP_PORT_LEN * 2) == 0) {
tcpdata_info = tdata_info_tmp;
tcpdata_info->last_used_time = now_in_ms;
break;
}
if (now_in_ms - tdata_info_tmp->last_used_time > TCPDATA_INFO_TIMEOUT) {
tdata_psh_info_t *tdata_psh_info_tmp;
tcpdata_info_t *last_tdata_info;
while ((tdata_psh_info_tmp = tdata_info_tmp->tdata_psh_info_head)) {
tdata_info_tmp->tdata_psh_info_head = tdata_psh_info_tmp->next;
tdata_psh_info_tmp->next = NULL;
DHD_TRACE(("%s %d: Clean tdata_psh_info(end_seq %u)!\n",
__FUNCTION__, __LINE__, tdata_psh_info_tmp->end_seq));
_tdata_psh_info_pool_enq(tcpack_sup_mod, tdata_psh_info_tmp);
}
#ifdef DHDTCPACK_SUP_DBG
DHD_ERROR(("%s %d: PSH INFO ENQ %d\n",
__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
#endif /* DHDTCPACK_SUP_DBG */
tcpack_sup_mod->tcpdata_info_cnt--;
ASSERT(tcpack_sup_mod->tcpdata_info_cnt >= 0);
last_tdata_info =
&tcpack_sup_mod->tcpdata_info_tbl[tcpack_sup_mod->tcpdata_info_cnt];
if (i < tcpack_sup_mod->tcpdata_info_cnt) {
ASSERT(last_tdata_info != tdata_info_tmp);
bcopy(last_tdata_info, tdata_info_tmp, sizeof(tcpdata_info_t));
}
bzero(last_tdata_info, sizeof(tcpdata_info_t));
DHD_TRACE(("%s %d: tcpdata_info(idx %d) is aged out. ttl cnt is now %d\n",
__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt));
/* Don't increase "i" here, so that the prev last tcpdata_info is checked */
} else
i++;
}
tcp_seq_num = ntoh32_ua(&tcp_hdr[TCP_SEQ_NUM_OFFSET]);
tcp_data_len = ip_total_len - ip_hdr_len - tcp_hdr_len;
end_tcp_seq_num = tcp_seq_num + tcp_data_len;
if (tcpdata_info == NULL) {
ASSERT(i == tcpack_sup_mod->tcpdata_info_cnt);
if (i >= TCPDATA_INFO_MAXNUM) {
DHD_TRACE(("%s %d: tcp_data_info_tbl FULL! %d %d"
" IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR" TCP port %d %d\n",
__FUNCTION__, __LINE__, i, tcpack_sup_mod->tcpdata_info_cnt,
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET])));
dhd_os_tcpackunlock(dhdp);
goto exit;
}
tcpdata_info = &tcpack_sup_mod->tcpdata_info_tbl[i];
/* No TCP flow with the same IP addr and TCP port is found
* in tcp_data_info_tbl. So add this flow to the table.
*/
DHD_TRACE(("%s %d: Add data info to tbl[%d]: IP addr "IPV4_ADDR_STR" "IPV4_ADDR_STR
" TCP port %d %d\n",
__FUNCTION__, __LINE__, tcpack_sup_mod->tcpdata_info_cnt,
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_SRC_IP_OFFSET])),
IPV4_ADDR_TO_STR(ntoh32_ua(&ip_hdr[IPV4_DEST_IP_OFFSET])),
ntoh16_ua(&tcp_hdr[TCP_SRC_PORT_OFFSET]),
ntoh16_ua(&tcp_hdr[TCP_DEST_PORT_OFFSET])));
bcopy(&ip_hdr[IPV4_SRC_IP_OFFSET], tcpdata_info->src_ip_addr,
IPV4_ADDR_LEN * 2);
bcopy(&tcp_hdr[TCP_SRC_PORT_OFFSET], tcpdata_info->src_tcp_port,
TCP_PORT_LEN * 2);
tcpdata_info->last_used_time = OSL_SYSUPTIME();
tcpack_sup_mod->tcpdata_info_cnt++;
}
ASSERT(tcpdata_info != NULL);
tdata_psh_info = _tdata_psh_info_pool_deq(tcpack_sup_mod);
#ifdef DHDTCPACK_SUP_DBG
DHD_TRACE(("%s %d: PSH INFO ENQ %d\n",
__FUNCTION__, __LINE__, tcpack_sup_mod->psh_info_enq_num));
#endif /* DHDTCPACK_SUP_DBG */
if (tdata_psh_info == NULL) {
DHD_ERROR(("%s %d: No more free tdata_psh_info!!\n", __FUNCTION__, __LINE__));
ret = BCME_ERROR;
dhd_os_tcpackunlock(dhdp);
goto exit;
}
tdata_psh_info->end_seq = end_tcp_seq_num;
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
tack_tbl.cnt[4]++;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
DHD_TRACE(("%s %d: TCP PSH DATA recvd! end seq %u\n",
__FUNCTION__, __LINE__, tdata_psh_info->end_seq));
ASSERT(tdata_psh_info->next == NULL);
if (tcpdata_info->tdata_psh_info_head == NULL)
tcpdata_info->tdata_psh_info_head = tdata_psh_info;
else {
ASSERT(tcpdata_info->tdata_psh_info_tail);
tcpdata_info->tdata_psh_info_tail->next = tdata_psh_info;
}
tcpdata_info->tdata_psh_info_tail = tdata_psh_info;
dhd_os_tcpackunlock(dhdp);
exit:
return ret;
}
#endif /* DHDTCPACK_SUPPRESS */

View File

@ -5,12 +5,18 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id$
* $Id: dhd_ip.h 458522 2014-02-27 02:26:15Z $
*/
#ifndef _dhd_ip_h_
#define _dhd_ip_h_
#ifdef DHDTCPACK_SUPPRESS
#include <dngl_stats.h>
#include <bcmutils.h>
#include <dhd.h>
#endif /* DHDTCPACK_SUPPRESS */
typedef enum pkt_frag
{
DHD_PKT_FRAG_NONE = 0,
@ -21,4 +27,28 @@ typedef enum pkt_frag
extern pkt_frag_t pkt_frag_info(osl_t *osh, void *p);
#ifdef DHDTCPACK_SUPPRESS
#define TCPACKSZMIN (ETHER_HDR_LEN + IPV4_MIN_HEADER_LEN + TCP_MIN_HEADER_LEN)
/* Size of MAX possible TCP ACK packet. Extra bytes for IP/TCP option fields */
#define TCPACKSZMAX (TCPACKSZMIN + 100)
/* Max number of TCP streams that have own src/dst IP addrs and TCP ports */
#define TCPACK_INFO_MAXNUM 4
#define TCPDATA_INFO_MAXNUM 4
#define TCPDATA_PSH_INFO_MAXNUM (8 * TCPDATA_INFO_MAXNUM)
#define TCPDATA_INFO_TIMEOUT 5000 /* Remove tcpdata_info if inactive for this time (in ms) */
extern int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 on);
extern void dhd_tcpack_info_tbl_clean(dhd_pub_t *dhdp);
extern int dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt);
extern bool dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt);
extern bool dhd_tcpdata_info_get(dhd_pub_t *dhdp, void *pkt);
/* #define DHDTCPACK_SUP_DBG */
#if defined(DEBUG_COUNTER) && defined(DHDTCPACK_SUP_DBG)
extern counter_tbl_t tack_tbl;
#endif /* DEBUG_COUNTER && DHDTCPACK_SUP_DBG */
#endif /* DHDTCPACK_SUPPRESS */
#endif /* _dhd_ip_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
/*
* DHD Linux header file (dhd_linux exports for cfg80211 and other components)
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_linux.h 399301 2013-04-29 21:41:52Z $
*/
/* wifi platform functions for power, interrupt and pre-alloc, either
* from Android-like platform device data, or Broadcom wifi platform
* device data.
*
*/
#ifndef __DHD_LINUX_H__
#define __DHD_LINUX_H__
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <dngl_stats.h>
#include <dhd.h>
#ifdef DHD_WMF
#include <dhd_wmf_linux.h>
#endif
/* Linux wireless extension support */
#if defined(WL_WIRELESS_EXT)
#include <wl_iw.h>
#endif /* defined(WL_WIRELESS_EXT) */
#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
#include <linux/earlysuspend.h>
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */
#define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */
typedef struct wifi_adapter_info {
const char *name;
uint irq_num;
uint intr_flags;
const char *fw_path;
const char *nv_path;
const char *conf_path;
void *wifi_plat_data; /* wifi ctrl func, for backward compatibility */
uint bus_type;
uint bus_num;
uint slot_num;
} wifi_adapter_info_t;
typedef struct bcmdhd_wifi_platdata {
uint num_adapters;
wifi_adapter_info_t *adapters;
} bcmdhd_wifi_platdata_t;
/** Per STA params. A list of dhd_sta objects are managed in dhd_if */
typedef struct dhd_sta {
uint16 flowid[NUMPRIO]; /* allocated flow ring ids (by priority) */
void * ifp; /* associated dhd_if */
struct ether_addr ea; /* stations ethernet mac address */
struct list_head list; /* link into dhd_if::sta_list */
int idx; /* index of self in dhd_pub::sta_pool[] */
int ifidx; /* index of interface in dhd */
} dhd_sta_t;
typedef dhd_sta_t dhd_sta_pool_t;
int dhd_wifi_platform_register_drv(void);
void dhd_wifi_platform_unregister_drv(void);
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);
int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present);
int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr);
int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf);
void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode);
void* wifi_platform_prealloc(wifi_adapter_info_t *adapter, int section, unsigned long size);
void* wifi_platform_get_prealloc_func_ptr(wifi_adapter_info_t *adapter);
int dhd_get_fw_mode(struct dhd_info *dhdinfo);
bool dhd_update_fw_nv_path(struct dhd_info *dhdinfo);
#ifdef DHD_WMF
dhd_wmf_t* dhd_wmf_conf(dhd_pub_t *dhdp, uint32 idx);
#endif /* DHD_WMF */
#endif /* __DHD_LINUX_H__ */

View File

@ -0,0 +1,812 @@
/*
* Linux platform device for DHD WLAN adapter
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_linux_platdev.c 401742 2013-05-13 15:03:21Z $
*/
#include <typedefs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <bcmutils.h>
#include <linux_osl.h>
#include <dhd_dbg.h>
#include <dngl_stats.h>
#include <dhd.h>
#include <dhd_bus.h>
#include <dhd_linux.h>
#include <wl_android.h>
#if defined(CONFIG_WIFI_CONTROL_FUNC)
#include <linux/wlan_plat.h>
#endif
#ifdef CONFIG_DTS
#include<linux/regulator/consumer.h>
#include<linux/of_gpio.h>
#endif /* CONFIG_DTS */
#ifdef CUSTOMER_HW
#if defined(CUSTOMER_OOB)
extern uint bcm_wlan_get_oob_irq(void);
extern uint bcm_wlan_get_oob_irq_flags(void);
#endif
extern int bcm_wlan_set_plat_data(void);
#endif /* CUSTOMER_HW */
struct wifi_platform_data {
int (*set_power)(bool val);
int (*set_carddetect)(bool val);
void *(*mem_prealloc)(int section, unsigned long size);
int (*get_mac_addr)(unsigned char *buf);
void *(*get_country_code)(char *ccode);
};
#define WIFI_PLAT_NAME "bcmdhd_wlan"
#define WIFI_PLAT_NAME2 "bcm4329_wlan"
#define WIFI_PLAT_EXT "bcmdhd_wifi_platform"
#ifdef CONFIG_DTS
struct regulator *wifi_regulator = NULL;
#endif /* CONFIG_DTS */
bool cfg_multichip = FALSE;
bcmdhd_wifi_platdata_t *dhd_wifi_platdata = NULL;
static int wifi_plat_dev_probe_ret = 0;
static bool is_power_on = FALSE;
#if !defined(CONFIG_DTS)
#if defined(DHD_OF_SUPPORT)
static bool dts_enabled = TRUE;
extern struct resource dhd_wlan_resources;
extern struct wifi_platform_data dhd_wlan_control;
#else
static bool dts_enabled = FALSE;
struct resource dhd_wlan_resources = {0};
struct wifi_platform_data dhd_wlan_control = {0};
#endif /* CONFIG_OF && !defined(CONFIG_ARCH_MSM) */
#endif /* !defind(CONFIG_DTS) */
static int dhd_wifi_platform_load(void);
extern void* wl_cfg80211_get_dhdp(void);
#ifdef ENABLE_4335BT_WAR
extern int bcm_bt_lock(int cookie);
extern void bcm_bt_unlock(int cookie);
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_get_adapter(uint32 bus_type, uint32 bus_num, uint32 slot_num)
{
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)) {
DHD_TRACE(("found adapter info '%s'\n", adapter->name));
return adapter;
}
}
return NULL;
}
void* wifi_platform_prealloc(wifi_adapter_info_t *adapter, int section, unsigned long size)
{
void *alloc_ptr = NULL;
struct wifi_platform_data *plat_data;
if (!adapter || !adapter->wifi_plat_data)
return NULL;
plat_data = adapter->wifi_plat_data;
if (plat_data->mem_prealloc) {
alloc_ptr = plat_data->mem_prealloc(section, size);
if (alloc_ptr) {
DHD_INFO(("success alloc section %d\n", section));
if (size != 0L)
bzero(alloc_ptr, size);
return alloc_ptr;
}
} else
return NULL;
DHD_ERROR(("%s: failed to alloc static mem section %d\n", __FUNCTION__, section));
return NULL;
}
void* wifi_platform_get_prealloc_func_ptr(wifi_adapter_info_t *adapter)
{
struct wifi_platform_data *plat_data;
if (!adapter || !adapter->wifi_plat_data)
return NULL;
plat_data = adapter->wifi_plat_data;
return plat_data->mem_prealloc;
}
int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr)
{
if (adapter == NULL)
return -1;
if (irq_flags_ptr)
*irq_flags_ptr = adapter->intr_flags;
return adapter->irq_num;
}
int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec)
{
int err = 0;
#ifdef CONFIG_DTS
if (on) {
err = regulator_enable(wifi_regulator);
is_power_on = TRUE;
}
else {
err = regulator_disable(wifi_regulator);
is_power_on = FALSE;
}
if (err < 0)
DHD_ERROR(("%s: regulator enable/disable failed", __FUNCTION__));
#else
struct wifi_platform_data *plat_data;
if (!adapter || !adapter->wifi_plat_data)
return -EINVAL;
plat_data = adapter->wifi_plat_data;
DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
if (plat_data->set_power) {
#ifdef ENABLE_4335BT_WAR
if (on) {
printk("WiFi: trying to acquire BT lock\n");
if (bcm_bt_lock(lock_cookie_wifi) != 0)
printk("** WiFi: timeout in acquiring bt lock**\n");
printk("%s: btlock acquired\n", __FUNCTION__);
}
else {
/* For a exceptional case, release btlock */
bcm_bt_unlock(lock_cookie_wifi);
}
#endif /* ENABLE_4335BT_WAR */
err = plat_data->set_power(on);
}
if (msec && !err)
OSL_SLEEP(msec);
if (on && !err)
is_power_on = TRUE;
else
is_power_on = FALSE;
#endif /* CONFIG_DTS */
return err;
}
int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present)
{
int err = 0;
struct wifi_platform_data *plat_data;
if (!adapter || !adapter->wifi_plat_data)
return -EINVAL;
plat_data = adapter->wifi_plat_data;
DHD_ERROR(("%s device present %d\n", __FUNCTION__, device_present));
if (plat_data->set_carddetect) {
err = plat_data->set_carddetect(device_present);
}
return err;
}
int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf)
{
struct wifi_platform_data *plat_data;
DHD_ERROR(("%s\n", __FUNCTION__));
if (!buf || !adapter || !adapter->wifi_plat_data)
return -EINVAL;
plat_data = adapter->wifi_plat_data;
if (plat_data->get_mac_addr) {
return plat_data->get_mac_addr(buf);
}
return -EOPNOTSUPP;
}
void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode)
{
/* get_country_code was added after 2.6.39 */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
struct wifi_platform_data *plat_data;
if (!ccode || !adapter || !adapter->wifi_plat_data)
return NULL;
plat_data = adapter->wifi_plat_data;
DHD_TRACE(("%s\n", __FUNCTION__));
if (plat_data->get_country_code) {
return plat_data->get_country_code(ccode);
}
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
return NULL;
}
static int wifi_plat_dev_drv_probe(struct platform_device *pdev)
{
struct resource *resource;
wifi_adapter_info_t *adapter;
#ifdef CONFIG_DTS
int irq, gpio;
#endif /* CONFIG_DTS */
/* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
* is kept for backward compatibility and supports only 1 adapter
*/
ASSERT(dhd_wifi_platdata != NULL);
ASSERT(dhd_wifi_platdata->num_adapters == 1);
adapter = &dhd_wifi_platdata->adapters[0];
adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data);
resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
if (resource == NULL)
resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
if (resource) {
adapter->irq_num = resource->start;
adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK;
}
#ifdef CONFIG_DTS
wifi_regulator = regulator_get(&pdev->dev, "wlreg_on");
if (wifi_regulator == NULL) {
DHD_ERROR(("%s regulator is null\n", __FUNCTION__));
return -1;
}
/* This is to get the irq for the OOB */
gpio = of_get_gpio(pdev->dev.of_node, 0);
if (gpio < 0) {
DHD_ERROR(("%s gpio information is incorrect\n", __FUNCTION__));
return -1;
}
irq = gpio_to_irq(gpio);
if (irq < 0) {
DHD_ERROR(("%s irq information is incorrect\n", __FUNCTION__));
return -1;
}
adapter->irq_num = irq;
/* need to change the flags according to our requirement */
adapter->intr_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
IORESOURCE_IRQ_SHAREABLE;
#endif /* CONFIG_DTS */
wifi_plat_dev_probe_ret = dhd_wifi_platform_load();
return wifi_plat_dev_probe_ret;
}
static int wifi_plat_dev_drv_remove(struct platform_device *pdev)
{
wifi_adapter_info_t *adapter;
/* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
* is kept for backward compatibility and supports only 1 adapter
*/
ASSERT(dhd_wifi_platdata != NULL);
ASSERT(dhd_wifi_platdata->num_adapters == 1);
adapter = &dhd_wifi_platdata->adapters[0];
if (is_power_on) {
#ifdef BCMPCIE
wifi_platform_bus_enumerate(adapter, FALSE);
wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
#else
wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
wifi_platform_bus_enumerate(adapter, FALSE);
#endif /* BCMPCIE */
}
#ifdef CONFIG_DTS
regulator_put(wifi_regulator);
#endif /* CONFIG_DTS */
return 0;
}
static int wifi_plat_dev_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
DHD_TRACE(("##> %s\n", __FUNCTION__));
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && \
defined(BCMSDIO)
bcmsdh_oob_intr_set(0);
#endif /* (OOB_INTR_ONLY) */
return 0;
}
static int wifi_plat_dev_drv_resume(struct platform_device *pdev)
{
DHD_TRACE(("##> %s\n", __FUNCTION__));
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && \
defined(BCMSDIO)
if (dhd_os_check_if_up(wl_cfg80211_get_dhdp()))
bcmsdh_oob_intr_set(1);
#endif /* (OOB_INTR_ONLY) */
return 0;
}
#ifdef CONFIG_DTS
static const struct of_device_id wifi_device_dt_match[] = {
{ .compatible = "android,bcmdhd_wlan", },
{},
};
#endif /* CONFIG_DTS */
static struct platform_driver wifi_platform_dev_driver = {
.probe = wifi_plat_dev_drv_probe,
.remove = wifi_plat_dev_drv_remove,
.suspend = wifi_plat_dev_drv_suspend,
.resume = wifi_plat_dev_drv_resume,
.driver = {
.name = WIFI_PLAT_NAME,
#ifdef CONFIG_DTS
.of_match_table = wifi_device_dt_match,
#endif /* CONFIG_DTS */
}
};
static struct platform_driver wifi_platform_dev_driver_legacy = {
.probe = wifi_plat_dev_drv_probe,
.remove = wifi_plat_dev_drv_remove,
.suspend = wifi_plat_dev_drv_suspend,
.resume = wifi_plat_dev_drv_resume,
.driver = {
.name = WIFI_PLAT_NAME2,
}
};
static int wifi_platdev_match(struct device *dev, void *data)
{
char *name = (char*)data;
struct platform_device *pdev = to_platform_device(dev);
if (strcmp(pdev->name, name) == 0) {
DHD_ERROR(("found wifi platform device %s\n", name));
return TRUE;
}
return FALSE;
}
static int wifi_ctrlfunc_register_drv(void)
{
int err = 0;
struct device *dev1, *dev2;
wifi_adapter_info_t *adapter;
dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match);
dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match);
#if !defined(CONFIG_DTS)
if (!dts_enabled) {
if (dev1 == NULL && dev2 == NULL) {
DHD_ERROR(("no wifi platform data, skip\n"));
return -ENXIO;
}
}
#endif /* !defined(CONFIG_DTS) */
/* multi-chip support not enabled, build one adapter information for
* DHD (either SDIO, USB or PCIe)
*/
adapter = kzalloc(sizeof(wifi_adapter_info_t), GFP_KERNEL);
adapter->name = "DHD generic adapter";
adapter->bus_type = -1;
adapter->bus_num = -1;
adapter->slot_num = -1;
adapter->irq_num = -1;
is_power_on = FALSE;
wifi_plat_dev_probe_ret = 0;
dhd_wifi_platdata = kzalloc(sizeof(bcmdhd_wifi_platdata_t), GFP_KERNEL);
dhd_wifi_platdata->num_adapters = 1;
dhd_wifi_platdata->adapters = adapter;
if (dev1) {
err = platform_driver_register(&wifi_platform_dev_driver);
if (err) {
DHD_ERROR(("%s: failed to register wifi ctrl func driver\n",
__FUNCTION__));
return err;
}
}
if (dev2) {
err = platform_driver_register(&wifi_platform_dev_driver_legacy);
if (err) {
DHD_ERROR(("%s: failed to register wifi ctrl func legacy driver\n",
__FUNCTION__));
return err;
}
}
#if !defined(CONFIG_DTS)
if (dts_enabled) {
adapter->wifi_plat_data = (void *)&dhd_wlan_control;
#ifdef CUSTOMER_HW
bcm_wlan_set_plat_data();
#ifdef CUSTOMER_OOB
adapter->irq_num = bcm_wlan_get_oob_irq();
adapter->intr_flags = bcm_wlan_get_oob_irq_flags();
#endif
#else
struct resource *resource;
resource = &dhd_wlan_resources;
adapter->irq_num = resource->start;
adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK;
#endif
wifi_plat_dev_probe_ret = dhd_wifi_platform_load();
}
#endif /* !defined(CONFIG_DTS) */
#ifdef CONFIG_DTS
wifi_plat_dev_probe_ret = platform_driver_register(&wifi_platform_dev_driver);
#endif /* CONFIG_DTS */
/* return probe function's return value if registeration succeeded */
return wifi_plat_dev_probe_ret;
}
void wifi_ctrlfunc_unregister_drv(void)
{
struct device *dev1, *dev2;
#ifdef CONFIG_DTS
DHD_ERROR(("unregister wifi platform drivers\n"));
platform_driver_unregister(&wifi_platform_dev_driver);
#else
dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match);
dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match);
if (!dts_enabled)
if (dev1 == NULL && dev2 == NULL)
return;
DHD_ERROR(("unregister wifi platform drivers\n"));
if (dev1)
platform_driver_unregister(&wifi_platform_dev_driver);
if (dev2)
platform_driver_unregister(&wifi_platform_dev_driver_legacy);
if (dts_enabled) {
wifi_adapter_info_t *adapter;
adapter = &dhd_wifi_platdata->adapters[0];
if (is_power_on) {
wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
wifi_platform_bus_enumerate(adapter, FALSE);
}
}
#endif /* !defined(CONFIG_DTS) */
kfree(dhd_wifi_platdata->adapters);
dhd_wifi_platdata->adapters = NULL;
dhd_wifi_platdata->num_adapters = 0;
kfree(dhd_wifi_platdata);
dhd_wifi_platdata = NULL;
}
static int bcmdhd_wifi_plat_dev_drv_probe(struct platform_device *pdev)
{
dhd_wifi_platdata = (bcmdhd_wifi_platdata_t *)(pdev->dev.platform_data);
return dhd_wifi_platform_load();
}
static int bcmdhd_wifi_plat_dev_drv_remove(struct platform_device *pdev)
{
int i;
wifi_adapter_info_t *adapter;
ASSERT(dhd_wifi_platdata != NULL);
/* 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);
wifi_platform_bus_enumerate(adapter, FALSE);
}
return 0;
}
static struct platform_driver dhd_wifi_platform_dev_driver = {
.probe = bcmdhd_wifi_plat_dev_drv_probe,
.remove = bcmdhd_wifi_plat_dev_drv_remove,
.driver = {
.name = WIFI_PLAT_EXT,
}
};
int dhd_wifi_platform_register_drv(void)
{
int err = 0;
struct device *dev;
/* register Broadcom wifi platform data driver if multi-chip is enabled,
* otherwise use Android style wifi platform data (aka wifi control function)
* if it exists
*
* to support multi-chip DHD, Broadcom wifi platform data device must
* be added in kernel early boot (e.g. board config file).
*/
if (cfg_multichip) {
dev = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_EXT, wifi_platdev_match);
if (dev == NULL) {
DHD_ERROR(("bcmdhd wifi platform data device not found!!\n"));
return -ENXIO;
}
err = platform_driver_register(&dhd_wifi_platform_dev_driver);
} else {
err = wifi_ctrlfunc_register_drv();
/* no wifi ctrl func either, load bus directly and ignore this error */
if (err) {
if (err == -ENXIO) {
/* wifi ctrl function does not exist */
err = dhd_wifi_platform_load();
} else {
/* unregister driver due to initialization failure */
wifi_ctrlfunc_unregister_drv();
}
}
}
return err;
}
#ifdef BCMPCIE
static int dhd_wifi_platform_load_pcie(void)
{
int err = 0;
int i;
wifi_adapter_info_t *adapter;
BCM_REFERENCE(i);
BCM_REFERENCE(adapter);
if (dhd_wifi_platdata == NULL) {
err = dhd_bus_register();
} else {
if (dhd_download_fw_on_driverload) {
/* power up all adapters */
for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
int retry = POWERUP_MAX_RETRY;
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));
do {
err = wifi_platform_set_power(adapter,
TRUE, WIFI_TURNON_DELAY);
if (err) {
DHD_ERROR(("failed to power up %s,"
" %d retry left\n",
adapter->name, retry));
/* WL_REG_ON state unknown, Power off forcely */
wifi_platform_set_power(adapter,
FALSE, WIFI_TURNOFF_DELAY);
continue;
} else {
err = wifi_platform_bus_enumerate(adapter, TRUE);
if (err) {
DHD_ERROR(("failed to enumerate bus %s, "
"%d retry left\n",
adapter->name, retry));
wifi_platform_set_power(adapter, FALSE,
WIFI_TURNOFF_DELAY);
} else {
break;
}
}
} while (retry--);
if (!retry) {
DHD_ERROR(("failed to power up %s, max retry reached**\n",
adapter->name));
return -ENODEV;
}
}
}
err = dhd_bus_register();
if (err) {
DHD_ERROR(("%s: pcie_register_driver failed\n", __FUNCTION__));
if (dhd_download_fw_on_driverload) {
/* power down all adapters */
for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
adapter = &dhd_wifi_platdata->adapters[i];
wifi_platform_bus_enumerate(adapter, FALSE);
wifi_platform_set_power(adapter,
FALSE, WIFI_TURNOFF_DELAY);
}
}
}
}
return err;
}
#else
static int dhd_wifi_platform_load_pcie(void)
{
return 0;
}
#endif /* BCMPCIE */
void dhd_wifi_platform_unregister_drv(void)
{
if (cfg_multichip)
platform_driver_unregister(&dhd_wifi_platform_dev_driver);
else
wifi_ctrlfunc_unregister_drv();
}
extern int dhd_watchdog_prio;
extern int dhd_dpc_prio;
extern uint dhd_deferred_tx;
#if defined(BCMLXSDMMC)
extern struct semaphore dhd_registration_sem;
#endif
#ifdef BCMSDIO
static int dhd_wifi_platform_load_sdio(void)
{
int i;
int err = 0;
wifi_adapter_info_t *adapter;
BCM_REFERENCE(i);
BCM_REFERENCE(adapter);
/* Sanity check on the module parameters
* - Both watchdog and DPC as tasklets are ok
* - If both watchdog and DPC are threads, TX must be deferred
*/
if (!(dhd_watchdog_prio < 0 && dhd_dpc_prio < 0) &&
!(dhd_watchdog_prio >= 0 && dhd_dpc_prio >= 0 && dhd_deferred_tx))
return -EINVAL;
#if defined(BCMLXSDMMC)
if (dhd_wifi_platdata == NULL) {
DHD_ERROR(("DHD wifi platform data is required for Android build\n"));
return -EINVAL;
}
sema_init(&dhd_registration_sem, 0);
/* power up all adapters */
for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
bool chip_up = FALSE;
int retry = POWERUP_MAX_RETRY;
struct semaphore dhd_chipup_sem;
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));
do {
sema_init(&dhd_chipup_sem, 0);
err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem);
if (err) {
DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n",
__FUNCTION__, err));
return err;
}
err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);
if (err) {
/* WL_REG_ON state unknown, Power off forcely */
wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
continue;
} else {
wifi_platform_bus_enumerate(adapter, TRUE);
err = 0;
}
if (down_timeout(&dhd_chipup_sem, msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) {
dhd_bus_unreg_sdio_notify();
chip_up = TRUE;
break;
}
DHD_ERROR(("failed to power up %s, %d retry left\n", adapter->name, retry));
dhd_bus_unreg_sdio_notify();
wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
wifi_platform_bus_enumerate(adapter, FALSE);
} while (retry--);
if (!chip_up) {
DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter->name));
return -ENODEV;
}
}
err = dhd_bus_register();
if (err) {
DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__));
goto fail;
}
/*
* Wait till MMC sdio_register_driver callback called and made driver attach.
* It's needed to make sync up exit from dhd insmod and
* Kernel MMC sdio device callback registration
*/
err = down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));
if (err) {
DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__));
dhd_bus_unregister();
goto fail;
}
return err;
fail:
/* 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);
wifi_platform_bus_enumerate(adapter, FALSE);
}
#else
/* x86 bring-up PC needs no power-up operations */
err = dhd_bus_register();
#endif
return err;
}
#else /* BCMSDIO */
static int dhd_wifi_platform_load_sdio(void)
{
return 0;
}
#endif /* BCMSDIO */
static int dhd_wifi_platform_load_usb(void)
{
return 0;
}
static int dhd_wifi_platform_load()
{
int err = 0;
printf("%s: Enter\n", __FUNCTION__);
wl_android_init();
if ((err = dhd_wifi_platform_load_usb()))
goto end;
else if ((err = dhd_wifi_platform_load_sdio()))
goto end;
else
err = dhd_wifi_platform_load_pcie();
end:
if (err)
wl_android_exit();
else
wl_android_post_init();
return err;
}

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_linux_sched.c 291086 2011-10-21 01:17:24Z $
* $Id: dhd_linux_sched.c 457570 2014-02-23 13:54:46Z $
*/
#include <linux/kernel.h>
#include <linux/module.h>
@ -19,3 +19,12 @@ int setScheduler(struct task_struct *p, int policy, struct sched_param *param)
#endif /* LinuxVer */
return rc;
}
int get_scheduler_policy(struct task_struct *p)
{
int rc = SCHED_NORMAL;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
rc = p->policy;
#endif /* LinuxVer */
return rc;
}

View File

@ -0,0 +1,299 @@
/*
* Broadcom Dongle Host Driver (DHD), Generic work queue framework
* Generic interface to handle dhd deferred work events
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_linux_wq.c 449578 2014-01-17 13:53:20Z $
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/ip.h>
#include <linux/kfifo.h>
#include <linuxver.h>
#include <osl.h>
#include <bcmutils.h>
#include <bcmendian.h>
#include <bcmdevs.h>
#include <dngl_stats.h>
#include <dhd.h>
#include <dhd_dbg.h>
#include <dhd_linux_wq.h>
struct dhd_deferred_event_t {
u8 event; /* holds the event */
void *event_data; /* Holds event specific data */
event_handler_t event_handler;
};
#define DEFRD_EVT_SIZE sizeof(struct dhd_deferred_event_t)
struct dhd_deferred_wq {
struct work_struct deferred_work; /* should be the first member */
/*
* work events may occur simultaneously.
* Can hold upto 64 low priority events and 4 high priority events
*/
#define DHD_PRIO_WORK_FIFO_SIZE (4 * sizeof(struct dhd_deferred_event_t))
#define DHD_WORK_FIFO_SIZE (64 * sizeof(struct dhd_deferred_event_t))
struct kfifo *prio_fifo;
struct kfifo *work_fifo;
u8 *prio_fifo_buf;
u8 *work_fifo_buf;
spinlock_t work_lock;
void *dhd_info; /* review: does it require */
};
static inline struct kfifo*
dhd_kfifo_init(u8 *buf, int size, spinlock_t *lock)
{
struct kfifo *fifo;
gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
fifo = kfifo_init(buf, size, flags, lock);
#else
fifo = (struct kfifo *)kzalloc(sizeof(struct kfifo), flags);
if (!fifo) {
return NULL;
}
kfifo_init(fifo, buf, size);
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */
return fifo;
}
static inline void
dhd_kfifo_free(struct kfifo *fifo)
{
kfifo_free(fifo);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
/* FC11 releases the fifo memory */
kfree(fifo);
#endif
}
/* deferred work functions */
static void dhd_deferred_work_handler(struct work_struct *data);
void*
dhd_deferred_work_init(void *dhd_info)
{
struct dhd_deferred_wq *work = NULL;
u8* buf;
unsigned long fifo_size = 0;
gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;
if (!dhd_info) {
DHD_ERROR(("%s: dhd info not initialized\n", __FUNCTION__));
goto return_null;
}
work = (struct dhd_deferred_wq *)kzalloc(sizeof(struct dhd_deferred_wq),
flags);
if (!work) {
DHD_ERROR(("%s: work queue creation failed \n", __FUNCTION__));
goto return_null;
}
INIT_WORK((struct work_struct *)work, dhd_deferred_work_handler);
/* initialize event fifo */
spin_lock_init(&work->work_lock);
/* allocate buffer to hold prio events */
fifo_size = DHD_PRIO_WORK_FIFO_SIZE;
fifo_size = is_power_of_2(fifo_size)? fifo_size : roundup_pow_of_two(fifo_size);
buf = (u8*)kzalloc(fifo_size, flags);
if (!buf) {
DHD_ERROR(("%s: prio work fifo allocation failed \n", __FUNCTION__));
goto return_null;
}
/* Initialize prio event fifo */
work->prio_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
if (!work->prio_fifo) {
kfree(buf);
goto return_null;
}
/* allocate buffer to hold work events */
fifo_size = DHD_WORK_FIFO_SIZE;
fifo_size = is_power_of_2(fifo_size)? fifo_size : roundup_pow_of_two(fifo_size);
buf = (u8*)kzalloc(fifo_size, flags);
if (!buf) {
DHD_ERROR(("%s: work fifo allocation failed \n", __FUNCTION__));
goto return_null;
}
/* Initialize event fifo */
work->work_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
if (!work->work_fifo) {
kfree(buf);
goto return_null;
}
work->dhd_info = dhd_info;
DHD_ERROR(("%s: work queue initialized \n", __FUNCTION__));
return work;
return_null:
if (work)
dhd_deferred_work_deinit(work);
return NULL;
}
void
dhd_deferred_work_deinit(void *work)
{
struct dhd_deferred_wq *deferred_work = work;
if (!deferred_work) {
DHD_ERROR(("%s: deferred work has been freed alread \n", __FUNCTION__));
return;
}
/* cancel the deferred work handling */
cancel_work_sync((struct work_struct *)deferred_work);
/*
* free work event fifo.
* kfifo_free frees locally allocated fifo buffer
*/
if (deferred_work->prio_fifo)
dhd_kfifo_free(deferred_work->prio_fifo);
if (deferred_work->work_fifo)
dhd_kfifo_free(deferred_work->work_fifo);
kfree(deferred_work);
}
/*
* Prepares event to be queued
* Schedules the event
*/
int
dhd_deferred_schedule_work(void *workq, void *event_data, u8 event,
event_handler_t event_handler, u8 priority)
{
struct dhd_deferred_wq *deferred_wq = (struct dhd_deferred_wq *) workq;
struct dhd_deferred_event_t deferred_event;
int status;
if (!deferred_wq) {
DHD_ERROR(("%s: work queue not initialized \n", __FUNCTION__));
ASSERT(0);
return DHD_WQ_STS_UNINITIALIZED;
}
if (!event || (event >= DHD_MAX_WQ_EVENTS)) {
DHD_ERROR(("%s: Unknown event \n", __FUNCTION__));
return DHD_WQ_STS_UNKNOWN_EVENT;
}
/*
* default element size is 1, which can be changed
* using kfifo_esize(). Older kernel(FC11) doesn't support
* changing element size. For compatibility changing
* element size is not prefered
*/
ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);
deferred_event.event = event;
deferred_event.event_data = event_data;
deferred_event.event_handler = event_handler;
if (priority == DHD_WORK_PRIORITY_HIGH) {
status = kfifo_in_spinlocked(deferred_wq->prio_fifo, &deferred_event,
DEFRD_EVT_SIZE, &deferred_wq->work_lock);
} else {
status = kfifo_in_spinlocked(deferred_wq->work_fifo, &deferred_event,
DEFRD_EVT_SIZE, &deferred_wq->work_lock);
}
if (!status) {
return DHD_WQ_STS_SCHED_FAILED;
}
schedule_work((struct work_struct *)deferred_wq);
return DHD_WQ_STS_OK;
}
static int
dhd_get_scheduled_work(struct dhd_deferred_wq *deferred_wq, struct dhd_deferred_event_t *event)
{
int status = 0;
if (!deferred_wq) {
DHD_ERROR(("%s: work queue not initialized \n", __FUNCTION__));
return DHD_WQ_STS_UNINITIALIZED;
}
/*
* default element size is 1 byte, which can be changed
* using kfifo_esize(). Older kernel(FC11) doesn't support
* changing element size. For compatibility changing
* element size is not prefered
*/
ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);
/* first read priorit event fifo */
status = kfifo_out_spinlocked(deferred_wq->prio_fifo, event,
DEFRD_EVT_SIZE, &deferred_wq->work_lock);
if (!status) {
/* priority fifo is empty. Now read low prio work fifo */
status = kfifo_out_spinlocked(deferred_wq->work_fifo, event,
DEFRD_EVT_SIZE, &deferred_wq->work_lock);
}
return status;
}
/*
* Called when work is scheduled
*/
static void
dhd_deferred_work_handler(struct work_struct *work)
{
struct dhd_deferred_wq *deferred_work = (struct dhd_deferred_wq *)work;
struct dhd_deferred_event_t work_event;
int status;
if (!deferred_work) {
DHD_ERROR(("%s: work queue not initialized\n", __FUNCTION__));
return;
}
do {
status = dhd_get_scheduled_work(deferred_work, &work_event);
DHD_TRACE(("%s: event to handle %d \n", __FUNCTION__, status));
if (!status) {
DHD_TRACE(("%s: No event to handle %d \n", __FUNCTION__, status));
break;
}
if (work_event.event > DHD_MAX_WQ_EVENTS) {
DHD_TRACE(("%s: Unknown event %d \n", __FUNCTION__, work_event.event));
break;
}
if (work_event.event_handler) {
work_event.event_handler(deferred_work->dhd_info,
work_event.event_data, work_event.event);
} else {
DHD_ERROR(("%s: event not defined %d\n", __FUNCTION__, work_event.event));
}
} while (1);
return;
}

View File

@ -0,0 +1,46 @@
/*
* Broadcom Dongle Host Driver (DHD), Generic work queue framework
* Generic interface to handle dhd deferred work events
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_linux_wq.h 449578 2014-01-17 13:53:20Z $
*/
#ifndef _dhd_linux_wq_h_
#define _dhd_linux_wq_h_
/*
* Work event definitions
*/
enum _wq_event {
DHD_WQ_WORK_IF_ADD = 1,
DHD_WQ_WORK_IF_DEL,
DHD_WQ_WORK_SET_MAC,
DHD_WQ_WORK_SET_MCAST_LIST,
DHD_WQ_WORK_IPV6_NDO,
DHD_WQ_WORK_HANG_MSG,
DHD_MAX_WQ_EVENTS
};
/*
* Work event priority
*/
#define DHD_WORK_PRIORITY_LOW 0
#define DHD_WORK_PRIORITY_HIGH 1
/*
* Error definitions
*/
#define DHD_WQ_STS_OK 0
#define DHD_WQ_STS_FAILED -1 /* General failure */
#define DHD_WQ_STS_UNINITIALIZED -2
#define DHD_WQ_STS_SCHED_FAILED -3
#define DHD_WQ_STS_UNKNOWN_EVENT -4
typedef void (*event_handler_t)(void *handle, void *event_data, u8 event);
void *dhd_deferred_work_init(void *dhd);
void dhd_deferred_work_deinit(void *workq);
int dhd_deferred_schedule_work(void *workq, void *event_data, u8 event,
event_handler_t evt_handler, u8 priority);
#endif /* _dhd_linux_wq_h_ */

View File

@ -0,0 +1,58 @@
/*
* DHD logging module for internal debug
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_sdio.c 281456 2011-09-02 01:49:45Z $
*/
#include <typedefs.h>
#include <osl.h>
#include <proto/ethernet.h>
#include <proto/802.1d.h>
#include <proto/802.11.h>
#include <linux/inet.h>
void dhd_blog(char *cp, int size)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
static struct socket * _udpSocket = NULL;
struct sockaddr_in _saAddr;
struct iovec iov;
struct msghdr msg;
if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &_udpSocket) >= 0)
{
{
memset(&_saAddr, 0, sizeof(_saAddr));
_saAddr.sin_family = AF_INET;
_saAddr.sin_port = htons(7651);
_saAddr.sin_addr.s_addr = in_aton("10.19.74.43");
iov.iov_base = cp;
iov.iov_len = size;
msg.msg_name = &_saAddr;
msg.msg_namelen = sizeof(struct sockaddr_in);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
{
mm_segment_t fs = get_fs();
set_fs(get_ds());
sock_sendmsg(_udpSocket, &msg, size);
set_fs(fs);
}
}
sock_release(_udpSocket);
}
#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
/*
* Linux DHD Bus Module for PCIE
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_pcie.h 491657 2014-07-17 06:29:40Z $
*/
#ifndef dhd_pcie_h
#define dhd_pcie_h
#include <bcmpcie.h>
#include <hnd_cons.h>
/* defines */
#define PCMSGBUF_HDRLEN 0
#define DONGLE_REG_MAP_SIZE (32 * 1024)
#define DONGLE_TCM_MAP_SIZE (4096 * 1024)
#define DONGLE_MIN_MEMSIZE (128 *1024)
#ifdef DHD_DEBUG
#define DHD_PCIE_SUCCESS 0
#define DHD_PCIE_FAILURE 1
#endif /* DHD_DEBUG */
#define REMAP_ENAB(bus) ((bus)->remap)
#define REMAP_ISADDR(bus, a) (((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
#define MAX_DHD_TX_FLOWS 256
/* user defined data structures */
#ifdef DHD_DEBUG
/* Device console log buffer state */
#define CONSOLE_LINE_MAX 192
#define CONSOLE_BUFFER_MAX 2024
typedef struct dhd_console {
uint count; /* Poll interval msec counter */
uint log_addr; /* Log struct address (fixed) */
hnd_log_t log; /* Log struct (host copy) */
uint bufsize; /* Size of log buffer */
uint8 *buf; /* Log buffer (host copy) */
uint last; /* Last buffer read index */
} dhd_console_t;
#endif /* DHD_DEBUG */
typedef struct ring_sh_info {
uint32 ring_mem_addr;
uint32 ring_state_w;
uint32 ring_state_r;
} ring_sh_info_t;
typedef struct dhd_bus {
dhd_pub_t *dhd;
struct pci_dev *dev; /* pci device handle */
dll_t const_flowring; /* constructed list of tx flowring queues */
si_t *sih; /* Handle for SI calls */
char *vars; /* Variables (from CIS and/or other) */
uint varsz; /* Size of variables buffer */
uint32 sbaddr; /* Current SB window pointer (-1, invalid) */
sbpcieregs_t *reg; /* Registers for PCIE core */
uint armrev; /* CPU core revision */
uint ramrev; /* SOCRAM core revision */
uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */
uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
uint32 srmemsize; /* Size of SRMEM */
uint32 bus; /* gSPI or SDIO bus */
uint32 intstatus; /* Intstatus bits (events) pending */
bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
bool fcstate; /* State of dongle flow-control */
uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */
char *fw_path; /* module_param: path to firmware image */
char *nv_path; /* module_param: path to nvram vars file */
char *nvram_params; /* user specified nvram params. */
int nvram_params_len;
struct pktq txq; /* Queue length used for flow-control */
uint rxlen; /* Length of valid data in buffer */
bool intr; /* Use interrupts */
bool ipend; /* Device interrupt is pending */
bool intdis; /* Interrupts disabled by isr */
uint intrcount; /* Count of device interrupt callbacks */
uint lastintrs; /* Count as of last watchdog timer */
#ifdef DHD_DEBUG
dhd_console_t console; /* Console output polling support */
uint console_addr; /* Console address from shared struct */
#endif /* DHD_DEBUG */
bool alp_only; /* Don't use HT clock (ALP only) */
bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram
* Available with socram rev 16
* Remap region not DMA-able
*/
uint32 resetinstr;
uint32 dongle_ram_base;
ulong shared_addr;
pciedev_shared_t *pcie_sh;
bool bus_flowctrl;
ioctl_comp_resp_msg_t ioct_resp;
uint32 dma_rxoffset;
volatile char *regs; /* pci device memory va */
volatile char *tcm; /* pci device memory va */
osl_t *osh;
uint32 nvram_csm; /* Nvram checksum */
uint16 pollrate;
uint16 polltick;
uint32 *pcie_mb_intr_addr;
void *pcie_mb_intr_osh;
bool sleep_allowed;
/* version 3 shared struct related info start */
ring_sh_info_t ring_sh[BCMPCIE_COMMON_MSGRINGS + MAX_DHD_TX_FLOWS];
uint8 h2d_ring_count;
uint8 d2h_ring_count;
uint32 ringmem_ptr;
uint32 ring_state_ptr;
uint32 d2h_dma_scratch_buffer_mem_addr;
uint32 h2d_mb_data_ptr_addr;
uint32 d2h_mb_data_ptr_addr;
/* version 3 shared struct related info end */
uint32 def_intmask;
bool ltrsleep_on_unload;
uint wait_for_d3_ack;
uint8 txmode_push;
uint32 max_sub_queues;
bool db1_for_mb;
} dhd_bus_t;
/* function declarations */
extern uint32* dhdpcie_bus_reg_map(osl_t *osh, ulong addr, int size);
extern int dhdpcie_bus_register(void);
extern void dhdpcie_bus_unregister(void);
extern bool dhdpcie_chipmatch(uint16 vendor, uint16 device);
extern struct dhd_bus* dhdpcie_bus_attach(osl_t *osh, volatile char* regs, volatile char* tcm);
extern uint32 dhdpcie_bus_cfg_read_dword(struct dhd_bus *bus, uint32 addr, uint32 size);
extern void dhdpcie_bus_cfg_write_dword(struct dhd_bus *bus, uint32 addr, uint32 size, uint32 data);
extern void dhdpcie_bus_intr_disable(struct dhd_bus *bus);
extern void dhdpcie_bus_release(struct dhd_bus *bus);
extern int32 dhdpcie_bus_isr(struct dhd_bus *bus);
extern void dhdpcie_free_irq(dhd_bus_t *bus);
extern int dhdpcie_bus_suspend(struct dhd_bus *bus, bool state);
extern int dhdpcie_pci_suspend_resume(struct pci_dev *dev, bool state);
extern int dhdpcie_start_host_pcieclock(dhd_bus_t *bus);
extern int dhdpcie_stop_host_pcieclock(dhd_bus_t *bus);
extern int dhdpcie_disable_device(dhd_bus_t *bus);
extern int dhdpcie_enable_device(dhd_bus_t *bus);
extern int dhdpcie_alloc_resource(dhd_bus_t *bus);
extern void dhdpcie_free_resource(dhd_bus_t *bus);
extern int dhd_buzzz_dump_dngl(dhd_bus_t *bus);
#endif /* dhd_pcie_h */

View File

@ -0,0 +1,859 @@
/*
* Linux DHD Bus Module for PCIE
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_pcie_linux.c 491657 2014-07-17 06:29:40Z $
*/
/* include files */
#include <typedefs.h>
#include <bcmutils.h>
#include <bcmdevs.h>
#include <siutils.h>
#include <hndsoc.h>
#include <hndpmu.h>
#include <sbchipc.h>
#if defined(DHD_DEBUG)
#include <hnd_armtrap.h>
#include <hnd_cons.h>
#endif /* defined(DHD_DEBUG) */
#include <dngl_stats.h>
#include <pcie_core.h>
#include <dhd.h>
#include <dhd_bus.h>
#include <dhd_proto.h>
#include <dhd_dbg.h>
#include <dhdioctl.h>
#include <bcmmsgbuf.h>
#include <pcicfg.h>
#include <dhd_pcie.h>
#include <dhd_linux.h>
#ifdef CONFIG_ARCH_MSM
#include <mach/msm_pcie.h>
#endif
#define PCI_CFG_RETRY 10
#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */
#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
#define OSL_PKTTAG_CLEAR(p) \
do { \
struct sk_buff *s = (struct sk_buff *)(p); \
ASSERT(OSL_PKTTAG_SZ == 32); \
*(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \
*(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
*(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
*(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
} while (0)
/* user defined data structures */
typedef struct dhd_pc_res {
uint32 bar0_size;
void* bar0_addr;
uint32 bar1_size;
void* bar1_addr;
} pci_config_res, *pPci_config_res;
typedef bool (*dhdpcie_cb_fn_t)(void *);
typedef struct dhdpcie_info
{
dhd_bus_t *bus;
osl_t *osh;
struct pci_dev *dev; /* pci device handle */
volatile char *regs; /* pci device memory va */
volatile char *tcm; /* pci device memory va */
uint32 tcm_size; /* pci device memory size */
struct pcos_info *pcos_info;
uint16 last_intrstatus; /* to cache intrstatus */
int irq;
char pciname[32];
struct pci_saved_state* state;
} dhdpcie_info_t;
struct pcos_info {
dhdpcie_info_t *pc;
spinlock_t lock;
wait_queue_head_t intr_wait_queue;
struct timer_list tuning_timer;
int tuning_timer_exp;
atomic_t timer_enab;
struct tasklet_struct tuning_tasklet;
};
/* function declarations */
static int __devinit
dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void __devexit
dhdpcie_pci_remove(struct pci_dev *pdev);
static int dhdpcie_init(struct pci_dev *pdev);
static irqreturn_t dhdpcie_isr(int irq, void *arg);
/* OS Routine functions for PCI suspend/resume */
static int dhdpcie_pci_suspend(struct pci_dev *dev, pm_message_t state);
static int dhdpcie_set_suspend_resume(struct pci_dev *dev, bool state);
static int dhdpcie_pci_resume(struct pci_dev *dev);
static int dhdpcie_resume_dev(struct pci_dev *dev);
static int dhdpcie_suspend_dev(struct pci_dev *dev);
static struct pci_device_id dhdpcie_pci_devid[] __devinitdata = {
{ vendor: 0x14e4,
device: PCI_ANY_ID,
subvendor: PCI_ANY_ID,
subdevice: PCI_ANY_ID,
class: PCI_CLASS_NETWORK_OTHER << 8,
class_mask: 0xffff00,
driver_data: 0,
},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, dhdpcie_pci_devid);
static struct pci_driver dhdpcie_driver = {
node: {},
name: "pcieh",
id_table: dhdpcie_pci_devid,
probe: dhdpcie_pci_probe,
remove: dhdpcie_pci_remove,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
save_state: NULL,
#endif
suspend: dhdpcie_pci_suspend,
resume: dhdpcie_pci_resume,
};
int dhdpcie_init_succeeded = FALSE;
static void dhdpcie_pme_active(struct pci_dev *pdev, bool enable)
{
uint16 pmcsr;
pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmcsr);
/* Clear PME Status by writing 1 to it and enable PME# */
pmcsr |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE;
if (!enable)
pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;
pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmcsr);
}
static int dhdpcie_set_suspend_resume(struct pci_dev *pdev, bool state)
{
int ret = 0;
dhdpcie_info_t *pch = pci_get_drvdata(pdev);
dhd_bus_t *bus = NULL;
if (pch) {
bus = pch->bus;
}
/* When firmware is not loaded do the PCI bus */
/* suspend/resume only */
if (bus && (bus->dhd->busstate == DHD_BUS_DOWN) &&
!bus->dhd->dongle_reset) {
ret = dhdpcie_pci_suspend_resume(bus->dev, state);
return ret;
}
if (bus && ((bus->dhd->busstate == DHD_BUS_SUSPEND)||
(bus->dhd->busstate == DHD_BUS_DATA))) {
ret = dhdpcie_bus_suspend(bus, state);
}
return ret;
}
static int dhdpcie_pci_suspend(struct pci_dev * pdev, pm_message_t state)
{
BCM_REFERENCE(state);
return dhdpcie_set_suspend_resume(pdev, TRUE);
}
static int dhdpcie_pci_resume(struct pci_dev *pdev)
{
return dhdpcie_set_suspend_resume(pdev, FALSE);
}
static int dhdpcie_suspend_dev(struct pci_dev *dev)
{
int ret;
DHD_TRACE_HW4(("%s: Enter\n", __FUNCTION__));
dhdpcie_pme_active(dev, TRUE);
pci_save_state(dev);
pci_enable_wake(dev, PCI_D0, TRUE);
pci_disable_device(dev);
ret = pci_set_power_state(dev, PCI_D3hot);
if (ret) {
DHD_ERROR(("%s: pci_set_power_state error %d\n",
__FUNCTION__, ret));
}
return ret;
}
static int dhdpcie_resume_dev(struct pci_dev *dev)
{
int err = 0;
DHD_TRACE_HW4(("%s: Enter\n", __FUNCTION__));
pci_restore_state(dev);
err = pci_enable_device(dev);
if (err) {
printf("%s:pci_enable_device error %d \n", __FUNCTION__, err);
return err;
}
pci_set_master(dev);
err = pci_set_power_state(dev, PCI_D0);
if (err) {
printf("%s:pci_set_power_state error %d \n", __FUNCTION__, err);
return err;
}
dhdpcie_pme_active(dev, FALSE);
return err;
}
int dhdpcie_pci_suspend_resume(struct pci_dev *dev, bool state)
{
int rc;
if (state)
rc = dhdpcie_suspend_dev(dev);
else
rc = dhdpcie_resume_dev(dev);
return rc;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
static int dhdpcie_device_scan(struct device *dev, void *data)
{
struct pci_dev *pcidev;
int *cnt = data;
pcidev = container_of(dev, struct pci_dev, dev);
if (pcidev->vendor != 0x14e4)
return 0;
DHD_INFO(("Found Broadcom PCI device 0x%04x\n", pcidev->device));
*cnt += 1;
if (pcidev->driver && strcmp(pcidev->driver->name, dhdpcie_driver.name))
DHD_ERROR(("Broadcom PCI Device 0x%04x has allocated with driver %s\n",
pcidev->device, pcidev->driver->name));
return 0;
}
#endif /* LINUX_VERSION >= 2.6.0 */
int
dhdpcie_bus_register(void)
{
int error = 0;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
if (!(error = pci_module_init(&dhdpcie_driver)))
return 0;
DHD_ERROR(("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error));
#else
if (!(error = pci_register_driver(&dhdpcie_driver))) {
bus_for_each_dev(dhdpcie_driver.driver.bus, NULL, &error, dhdpcie_device_scan);
if (!error) {
DHD_ERROR(("No Broadcom PCI device enumerated!\n"));
} else if (!dhdpcie_init_succeeded) {
DHD_ERROR(("%s: dhdpcie initialize failed.\n", __FUNCTION__));
} else {
return 0;
}
pci_unregister_driver(&dhdpcie_driver);
error = BCME_ERROR;
}
#endif /* LINUX_VERSION < 2.6.0 */
return error;
}
void
dhdpcie_bus_unregister(void)
{
pci_unregister_driver(&dhdpcie_driver);
}
int __devinit
dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) {
DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__));
return -ENODEV;
}
printf("PCI_PROBE: bus %X, slot %X,vendor %X, device %X"
"(good PCI location)\n", pdev->bus->number,
PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device);
if (dhdpcie_init (pdev)) {
DHD_ERROR(("%s: PCIe Enumeration failed\n", __FUNCTION__));
return -ENODEV;
}
DHD_TRACE(("%s: PCIe Enumeration done!!\n", __FUNCTION__));
return 0;
}
int
dhdpcie_detach(dhdpcie_info_t *pch)
{
if (pch) {
osl_t *osh = pch->osh;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
if (!dhd_download_fw_on_driverload)
pci_load_and_free_saved_state(pch->dev, &pch->state);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
MFREE(osh, pch, sizeof(dhdpcie_info_t));
}
return 0;
}
void __devexit
dhdpcie_pci_remove(struct pci_dev *pdev)
{
osl_t *osh = NULL;
dhdpcie_info_t *pch = NULL;
dhd_bus_t *bus = NULL;
DHD_TRACE(("%s Enter\n", __FUNCTION__));
pch = pci_get_drvdata(pdev);
bus = pch->bus;
osh = pch->osh;
dhdpcie_bus_release(bus);
pci_disable_device(pdev);
/* pcie info detach */
dhdpcie_detach(pch);
/* osl detach */
osl_detach(osh);
dhdpcie_init_succeeded = FALSE;
DHD_TRACE(("%s Exit\n", __FUNCTION__));
return;
}
/* Free Linux irq */
int
dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info)
{
dhd_bus_t *bus = dhdpcie_info->bus;
struct pci_dev *pdev = dhdpcie_info->bus->dev;
snprintf(dhdpcie_info->pciname, sizeof(dhdpcie_info->pciname),
"dhdpcie:%s", pci_name(pdev));
if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED,
dhdpcie_info->pciname, bus) < 0) {
DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
return -1;
}
DHD_TRACE(("%s %s\n", __FUNCTION__, dhdpcie_info->pciname));
return 0; /* SUCCESS */
}
#ifdef CONFIG_PHYS_ADDR_T_64BIT
#define PRINTF_RESOURCE "0x%016llx"
#else
#define PRINTF_RESOURCE "0x%08x"
#endif
/*
Name: osl_pci_get_resource
Parametrs:
1: struct pci_dev *pdev -- pci device structure
2: pci_res -- structure containing pci configuration space values
Return value:
int - Status (TRUE or FALSE)
Description:
Access PCI configuration space, retrieve PCI allocated resources , updates in resource structure.
*/
int dhdpcie_get_resource(dhdpcie_info_t *dhdpcie_info)
{
phys_addr_t bar0_addr, bar1_addr;
ulong bar1_size;
struct pci_dev *pdev = NULL;
pdev = dhdpcie_info->dev;
do {
if (pci_enable_device(pdev)) {
printf("%s: Cannot enable PCI device\n", __FUNCTION__);
break;
}
pci_set_master(pdev);
bar0_addr = pci_resource_start(pdev, 0); /* Bar-0 mapped address */
bar1_addr = pci_resource_start(pdev, 2); /* Bar-1 mapped address */
/* read Bar-1 mapped memory range */
bar1_size = pci_resource_len(pdev, 2);
if ((bar1_size == 0) || (bar1_addr == 0)) {
printf("%s: BAR1 Not enabled for this device size(%ld),"
" addr(0x"PRINTF_RESOURCE")\n",
__FUNCTION__, bar1_size, bar1_addr);
goto err;
}
dhdpcie_info->regs = (volatile char *) REG_MAP(bar0_addr, DONGLE_REG_MAP_SIZE);
dhdpcie_info->tcm = (volatile char *) REG_MAP(bar1_addr, DONGLE_TCM_MAP_SIZE);
dhdpcie_info->tcm_size = DONGLE_TCM_MAP_SIZE;
if (!dhdpcie_info->regs || !dhdpcie_info->tcm) {
DHD_ERROR(("%s:ioremap() failed\n", __FUNCTION__));
break;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
if (!dhd_download_fw_on_driverload) {
/* Backup PCIe configuration so as to use Wi-Fi on/off process
* in case of built in driver
*/
pci_save_state(pdev);
dhdpcie_info->state = pci_store_saved_state(pdev);
if (dhdpcie_info->state == NULL) {
DHD_ERROR(("%s pci_store_saved_state returns NULL\n",
__FUNCTION__));
REG_UNMAP(dhdpcie_info->regs);
REG_UNMAP(dhdpcie_info->tcm);
pci_disable_device(pdev);
break;
}
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
DHD_TRACE(("%s:Phys addr : reg space = %p base addr 0x"PRINTF_RESOURCE" \n",
__FUNCTION__, dhdpcie_info->regs, bar0_addr));
DHD_TRACE(("%s:Phys addr : tcm_space = %p base addr 0x"PRINTF_RESOURCE" \n",
__FUNCTION__, dhdpcie_info->tcm, bar1_addr));
return 0; /* SUCCESS */
} while (0);
err:
return -1; /* FAILURE */
}
int dhdpcie_scan_resource(dhdpcie_info_t *dhdpcie_info)
{
DHD_TRACE(("%s: ENTER\n", __FUNCTION__));
do {
/* define it here only!! */
if (dhdpcie_get_resource (dhdpcie_info)) {
DHD_ERROR(("%s: Failed to get PCI resources\n", __FUNCTION__));
break;
}
DHD_TRACE(("%s:Exit - SUCCESS \n",
__FUNCTION__));
return 0; /* SUCCESS */
} while (0);
DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
return -1; /* FAILURE */
}
int dhdpcie_init(struct pci_dev *pdev)
{
osl_t *osh = NULL;
dhd_bus_t *bus = NULL;
dhdpcie_info_t *dhdpcie_info = NULL;
wifi_adapter_info_t *adapter = NULL;
do {
/* osl attach */
if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
DHD_ERROR(("%s: osl_attach failed\n", __FUNCTION__));
break;
}
/* initialize static buffer */
adapter = dhd_wifi_platform_get_adapter(PCI_BUS, pdev->bus->number,
PCI_SLOT(pdev->devfn));
if (adapter != NULL)
DHD_ERROR(("%s: found adapter info '%s'\n", __FUNCTION__, adapter->name));
else
DHD_ERROR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
osl_static_mem_init(osh, adapter);
/* allocate linux spcific pcie structure here */
if (!(dhdpcie_info = MALLOC(osh, sizeof(dhdpcie_info_t)))) {
DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
break;
}
bzero(dhdpcie_info, sizeof(dhdpcie_info_t));
dhdpcie_info->osh = osh;
dhdpcie_info->dev = pdev;
/* Find the PCI resources, verify the */
/* vendor and device ID, map BAR regions and irq, update in structures */
if (dhdpcie_scan_resource(dhdpcie_info)) {
DHD_ERROR(("%s: dhd_Scan_PCI_Res failed\n", __FUNCTION__));
break;
}
/* Bus initialization */
bus = dhdpcie_bus_attach(osh, dhdpcie_info->regs, dhdpcie_info->tcm);
if (!bus) {
DHD_ERROR(("%s:dhdpcie_bus_attach() failed\n", __FUNCTION__));
break;
}
dhdpcie_info->bus = bus;
dhdpcie_info->bus->dev = pdev;
if (bus->intr) {
/* Register interrupt callback, but mask it (not operational yet). */
DHD_INTR(("%s: Registering and masking interrupts\n", __FUNCTION__));
dhdpcie_bus_intr_disable(bus);
if (dhdpcie_request_irq(dhdpcie_info)) {
DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
break;
}
} else {
bus->pollrate = 1;
DHD_INFO(("%s: PCIe interrupt function is NOT registered "
"due to polling mode\n", __FUNCTION__));
}
if (dhd_download_fw_on_driverload) {
if (dhd_bus_start(bus->dhd)) {
DHD_ERROR(("%s: dhd_bud_start() failed\n", __FUNCTION__));
break;
}
}
/* set private data for pci_dev */
pci_set_drvdata(pdev, dhdpcie_info);
/* Attach to the OS network interface */
DHD_TRACE(("%s(): Calling dhd_register_if() \n", __FUNCTION__));
if (dhd_register_if(bus->dhd, 0, TRUE)) {
DHD_ERROR(("%s(): ERROR.. dhd_register_if() failed\n", __FUNCTION__));
break;
}
dhdpcie_init_succeeded = TRUE;
DHD_TRACE(("%s:Exit - SUCCESS \n", __FUNCTION__));
return 0; /* return SUCCESS */
} while (0);
/* reverse the initialization in order in case of error */
if (bus)
dhdpcie_bus_release(bus);
if (dhdpcie_info)
dhdpcie_detach(dhdpcie_info);
pci_disable_device(pdev);
if (osh)
osl_detach(osh);
dhdpcie_init_succeeded = FALSE;
DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
return -1; /* return FAILURE */
}
/* Free Linux irq */
void
dhdpcie_free_irq(dhd_bus_t *bus)
{
struct pci_dev *pdev = NULL;
DHD_TRACE(("%s: freeing up the IRQ\n", __FUNCTION__));
if (bus) {
pdev = bus->dev;
free_irq(pdev->irq, bus);
}
DHD_TRACE(("%s: Exit\n", __FUNCTION__));
return;
}
/*
Name: dhdpcie_isr
Parametrs:
1: IN int irq -- interrupt vector
2: IN void *arg -- handle to private data structure
Return value:
Status (TRUE or FALSE)
Description:
Interrupt Service routine checks for the status register,
disable interrupt and queue DPC if mail box interrupts are raised.
*/
irqreturn_t
dhdpcie_isr(int irq, void *arg)
{
dhd_bus_t *bus = (dhd_bus_t*)arg;
if (dhdpcie_bus_isr(bus))
return TRUE;
else
return FALSE;
}
int
dhdpcie_start_host_pcieclock(dhd_bus_t *bus)
{
int ret = 0;
#ifdef SUPPORT_LINKDOWN_RECOVERY
int options = 0;
#endif /* SUPPORT_LINKDOWN_RECOVERY */
DHD_TRACE(("%s Enter:\n", __FUNCTION__));
if (bus == NULL)
return BCME_ERROR;
if (bus->dev == NULL)
return BCME_ERROR;
#if defined(CONFIG_ARCH_MSM)
#ifdef SUPPORT_LINKDOWN_RECOVERY
if (bus->islinkdown) {
options = MSM_PCIE_CONFIG_NO_CFG_RESTORE;
}
ret = msm_pcie_pm_control(MSM_PCIE_RESUME, bus->dev->bus->number,
NULL, NULL, options);
if (bus->islinkdown && !ret) {
msm_pcie_recover_config(bus->dev);
if (bus->dhd)
DHD_OS_WAKE_UNLOCK(bus->dhd);
bus->islinkdown = FALSE;
}
#else
ret = msm_pcie_pm_control(MSM_PCIE_RESUME, bus->dev->bus->number,
NULL, NULL, 0);
#endif /* SUPPORT_LINKDOWN_RECOVERY */
if (ret) {
DHD_ERROR(("%s Failed to bring up PCIe link\n", __FUNCTION__));
goto done;
}
done:
#endif /* CONFIG_ARCH_MSM */
DHD_TRACE(("%s Exit:\n", __FUNCTION__));
return ret;
}
int
dhdpcie_stop_host_pcieclock(dhd_bus_t *bus)
{
int ret = 0;
#ifdef SUPPORT_LINKDOWN_RECOVERY
int options = 0;
#endif
DHD_TRACE(("%s Enter:\n", __FUNCTION__));
if (bus == NULL)
return BCME_ERROR;
if (bus->dev == NULL)
return BCME_ERROR;
#if defined(CONFIG_ARCH_MSM)
#ifdef SUPPORT_LINKDOWN_RECOVERY
if (bus->islinkdown)
options = MSM_PCIE_CONFIG_NO_CFG_RESTORE | MSM_PCIE_CONFIG_LINKDOWN;
ret = msm_pcie_pm_control(MSM_PCIE_SUSPEND, bus->dev->bus->number,
NULL, NULL, options);
#else
ret = msm_pcie_pm_control(MSM_PCIE_SUSPEND, bus->dev->bus->number,
NULL, NULL, 0);
#endif /* SUPPORT_LINKDOWN_RECOVERY */
if (ret) {
DHD_ERROR(("Failed to stop PCIe link\n"));
goto done;
}
done:
#endif /* CONFIG_ARCH_MSM */
DHD_TRACE(("%s Exit:\n", __FUNCTION__));
return ret;
}
int
dhdpcie_disable_device(dhd_bus_t *bus)
{
if (bus == NULL)
return BCME_ERROR;
if (bus->dev == NULL)
return BCME_ERROR;
pci_disable_device(bus->dev);
return 0;
}
int
dhdpcie_enable_device(dhd_bus_t *bus)
{
int ret = BCME_ERROR;
dhdpcie_info_t *pch;
DHD_TRACE(("%s Enter:\n", __FUNCTION__));
if (bus == NULL)
return BCME_ERROR;
if (bus->dev == NULL)
return BCME_ERROR;
pch = pci_get_drvdata(bus->dev);
if (pch == NULL)
return BCME_ERROR;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
if (pci_load_saved_state(bus->dev, pch->state))
pci_disable_device(bus->dev);
else {
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
pci_restore_state(bus->dev);
ret = pci_enable_device(bus->dev);
if (!ret)
pci_set_master(bus->dev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */
if (ret)
pci_disable_device(bus->dev);
return ret;
}
int
dhdpcie_alloc_resource(dhd_bus_t *bus)
{
dhdpcie_info_t *dhdpcie_info;
phys_addr_t bar0_addr, bar1_addr;
ulong bar1_size;
do {
if (bus == NULL) {
DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
break;
}
if (bus->dev == NULL) {
DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
break;
}
dhdpcie_info = pci_get_drvdata(bus->dev);
if (dhdpcie_info == NULL) {
DHD_ERROR(("%s: dhdpcie_info is NULL\n", __FUNCTION__));
break;
}
bar0_addr = pci_resource_start(bus->dev, 0); /* Bar-0 mapped address */
bar1_addr = pci_resource_start(bus->dev, 2); /* Bar-1 mapped address */
/* read Bar-1 mapped memory range */
bar1_size = pci_resource_len(bus->dev, 2);
if ((bar1_size == 0) || (bar1_addr == 0)) {
printf("%s: BAR1 Not enabled for this device size(%ld),"
" addr(0x"PRINTF_RESOURCE")\n",
__FUNCTION__, bar1_size, bar1_addr);
break;
}
dhdpcie_info->regs = (volatile char *) REG_MAP(bar0_addr, DONGLE_REG_MAP_SIZE);
if (!dhdpcie_info->regs) {
DHD_ERROR(("%s: ioremap() for regs is failed\n", __FUNCTION__));
break;
}
bus->regs = dhdpcie_info->regs;
dhdpcie_info->tcm = (volatile char *) REG_MAP(bar1_addr, DONGLE_TCM_MAP_SIZE);
dhdpcie_info->tcm_size = DONGLE_TCM_MAP_SIZE;
if (!dhdpcie_info->tcm) {
DHD_ERROR(("%s: ioremap() for regs is failed\n", __FUNCTION__));
REG_UNMAP(dhdpcie_info->regs);
bus->regs = NULL;
break;
}
bus->tcm = dhdpcie_info->tcm;
DHD_TRACE(("%s:Phys addr : reg space = %p base addr 0x"PRINTF_RESOURCE" \n",
__FUNCTION__, dhdpcie_info->regs, bar0_addr));
DHD_TRACE(("%s:Phys addr : tcm_space = %p base addr 0x"PRINTF_RESOURCE" \n",
__FUNCTION__, dhdpcie_info->tcm, bar1_addr));
return 0;
} while (0);
return BCME_ERROR;
}
void
dhdpcie_free_resource(dhd_bus_t *bus)
{
dhdpcie_info_t *dhdpcie_info;
if (bus == NULL) {
DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__));
return;
}
if (bus->dev == NULL) {
DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__));
return;
}
dhdpcie_info = pci_get_drvdata(bus->dev);
if (dhdpcie_info == NULL) {
DHD_ERROR(("%s: dhdpcie_info is NULL\n", __FUNCTION__));
return;
}
if (bus->regs) {
REG_UNMAP(dhdpcie_info->regs);
bus->regs = NULL;
}
if (bus->tcm) {
REG_UNMAP(dhdpcie_info->tcm);
bus->tcm = NULL;
}
}

View File

@ -4,8 +4,9 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_pno.c 420056 2013-08-24 00:53:12Z $
* $Id: dhd_pno.c 423669 2013-09-18 13:01:55Z yangj$
*/
#ifdef PNO_SUPPORT
#include <typedefs.h>
#include <osl.h>
@ -35,12 +36,12 @@
#define htodchanspec(i) htod16(i)
#define dtohchanspec(i) dtoh16(i)
#else
#define htod32(i) i
#define htod16(i) i
#define dtoh32(i) i
#define dtoh16(i) i
#define htodchanspec(i) i
#define dtohchanspec(i) i
#define htod32(i) (i)
#define htod16(i) (i)
#define dtoh32(i) (i)
#define dtoh16(i) (i)
#define htodchanspec(i) (i)
#define dtohchanspec(i) (i)
#endif /* IL_BIGENDINA */
#define NULL_CHECK(p, s, err) \
@ -73,8 +74,8 @@ is_dfs(uint16 channel)
else
return FALSE;
}
static int
_dhd_pno_clean(dhd_pub_t *dhd)
int
dhd_pno_clean(dhd_pub_t *dhd)
{
int pfn = 0;
int err;
@ -108,7 +109,9 @@ _dhd_pno_suspend(dhd_pub_t *dhd)
dhd_pno_status_info_t *_pno_state;
NULL_CHECK(dhd, "dhd is NULL", err);
NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
DHD_PNO(("%s enter\n", __FUNCTION__));
_pno_state = PNO_GET_PNOSTATE(dhd);
err = dhd_iovar(dhd, 0, "pfn_suspend", (char *)&suspend, sizeof(suspend), 1);
if (err < 0) {
DHD_ERROR(("%s : failed to suspend pfn(error :%d)\n", __FUNCTION__, err));
@ -279,15 +282,15 @@ _dhd_pno_set(dhd_pub_t *dhd, const dhd_pno_params_t *pno_params, dhd_pno_mode_t
if (mode == DHD_PNO_BATCH_MODE) {
int _tmp = pfn_param.bestn;
/* set bestn to calculate the max mscan which firmware supports */
err = dhd_iovar(dhd, 0, "pfnmscan", (char *)&_tmp, sizeof(_tmp), 1);
err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 1);
if (err < 0) {
DHD_ERROR(("%s : failed to set pfnmscan\n", __FUNCTION__));
DHD_ERROR(("%s : failed to set pfnmem\n", __FUNCTION__));
goto exit;
}
/* get max mscan which the firmware supports */
err = dhd_iovar(dhd, 0, "pfnmscan", (char *)&_tmp, sizeof(_tmp), 0);
err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 0);
if (err < 0) {
DHD_ERROR(("%s : failed to get pfnmscan\n", __FUNCTION__));
DHD_ERROR(("%s : failed to get pfnmem\n", __FUNCTION__));
goto exit;
}
DHD_PNO((" returned mscan : %d, set bestn : %d\n", _tmp, pfn_param.bestn));
@ -649,6 +652,7 @@ _dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mod
kfree(iter);
}
}
params->params_legacy.nssid = 0;
params->params_legacy.scan_fr = 0;
params->params_legacy.pno_freq_expo_max = 0;
params->params_legacy.pno_repeat = 0;
@ -746,7 +750,7 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd)
dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
/* save current pno_mode before calling dhd_pno_clean */
mode = _pno_state->pno_mode;
_dhd_pno_clean(dhd);
dhd_pno_clean(dhd);
/* restore previous pno_mode */
_pno_state->pno_mode = mode;
if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
@ -790,9 +794,9 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd)
}
}
} else {
err = _dhd_pno_clean(dhd);
err = dhd_pno_clean(dhd);
if (err < 0) {
DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n",
DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
__FUNCTION__, err));
goto exit;
}
@ -836,15 +840,23 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
scan_fr, pno_repeat, pno_freq_expo_max, nchan));
_params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]);
if (!(_pno_state->pno_mode & DHD_PNO_LEGACY_MODE)) {
_pno_state->pno_mode |= DHD_PNO_LEGACY_MODE;
err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
DHD_ERROR(("%s : Legacy PNO mode was already started, "
"will disable previous one to start new one\n", __FUNCTION__));
err = dhd_pno_stop_for_ssid(dhd);
if (err < 0) {
DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n",
DHD_ERROR(("%s : failed to stop legacy PNO (err %d)\n",
__FUNCTION__, err));
goto exit;
}
}
_pno_state->pno_mode |= DHD_PNO_LEGACY_MODE;
err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
if (err < 0) {
DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n",
__FUNCTION__, err));
goto exit;
}
memset(_chan_list, 0, sizeof(_chan_list));
tot_nchan = nchan;
if (tot_nchan > 0 && channel_list) {
@ -909,7 +921,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
goto exit;
}
if ((err = _dhd_pno_add_ssid(dhd, ssid_list, nssid)) < 0) {
DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
DHD_ERROR(("failed to add ssid list(err %d), %d in firmware\n", err, nssid));
goto exit;
}
for (i = 0; i < nssid; i++) {
@ -976,6 +988,9 @@ dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params)
__FUNCTION__));
goto exit;
}
} else {
/* batch mode is already started */
return -EBUSY;
}
_params->params_batch.scan_fr = batch_params->scan_fr;
_params->params_batch.bestn = batch_params->bestn;
@ -1202,10 +1217,10 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
}
DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version,
plbestnet->status, plbestnet->count));
if (plbestnet->version != PFN_LSCANRESULT_VERSION) {
if (plbestnet->version != PFN_SCANRESULT_VERSION) {
err = BCME_VERSION;
DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n",
plbestnet->version, PFN_LSCANRESULT_VERSION));
plbestnet->version, PFN_SCANRESULT_VERSION));
goto exit;
}
plnetinfo = plbestnet->netinfo;
@ -1217,6 +1232,7 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n"));
goto exit;
}
memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE);
pbestnet_entry->recorded_time = jiffies; /* record the current time */
/* create header for the first entry */
allocate_header = (i == 0)? TRUE : FALSE;
@ -1257,11 +1273,11 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
/* fills the best network info */
pbestnet_entry->channel = plnetinfo->pfnsubnet.channel;
pbestnet_entry->RSSI = plnetinfo->RSSI;
if (pbestnet_entry->RSSI > 0) {
if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) {
/* if RSSI is positive value, we assume that
* this scan is aborted by other scan
*/
pbestnet_entry->RSSI *= -1;
DHD_PNO(("This scan is aborted\n"));
pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT);
}
pbestnet_entry->rtt0 = plnetinfo->rtt0;
@ -1295,6 +1311,15 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
plnetinfo++;
}
}
if (pscan_results->cnt_header == 0) {
/* In case that we didn't get any data from the firmware
* Remove the current scan_result list from get_bach.scan_results_list.
*/
DHD_PNO(("NO BATCH DATA from Firmware, Delete current SCAN RESULT LIST\n"));
list_del(&pscan_results->list);
MFREE(dhd->osh, pscan_results, SCAN_RESULTS_SIZE);
_params->params_batch.get_batch.top_node_cnt--;
}
/* increase total scan count using current scan count */
_params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header;
@ -1314,21 +1339,23 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
_params->params_batch.get_batch.tot_scan_cnt = 0;
}
convert_format:
if (!list_empty(&_params->params_batch.get_batch.expired_scan_results_list)) {
err = _dhd_pno_convert_format(dhd, &_params->params_batch, buf, bufsize);
if (err < 0) {
DHD_ERROR(("failed to convert the data into upper layer format\n"));
goto exit;
}
err = _dhd_pno_convert_format(dhd, &_params->params_batch, buf, bufsize);
if (err < 0) {
DHD_ERROR(("failed to convert the data into upper layer format\n"));
goto exit;
}
}
exit:
if (plbestnet)
MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN);
_params->params_batch.get_batch.buf = NULL;
_params->params_batch.get_batch.bufsize = 0;
if (_params) {
_params->params_batch.get_batch.buf = NULL;
_params->params_batch.get_batch.bufsize = 0;
_params->params_batch.get_batch.bytes_written = err;
}
mutex_unlock(&_pno_state->pno_mutex);
complete(&_pno_state->get_batch_done);
if (waitqueue_active(&_pno_state->get_batch_done.wait))
complete(&_pno_state->get_batch_done);
return err;
}
static void
@ -1354,6 +1381,7 @@ int
dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
{
int err = BCME_OK;
char *pbuf = buf;
dhd_pno_status_info_t *_pno_state;
struct dhd_pno_batch_params *params_batch;
NULL_CHECK(dhd, "dhd is NULL", err);
@ -1373,13 +1401,19 @@ dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) {
DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__));
memset(pbuf, 0, bufsize);
pbuf += sprintf(pbuf, "scancount=%d\n", 0);
sprintf(pbuf, "%s", RESULTS_END_MARKER);
err = strlen(buf);
goto exit;
}
params_batch->get_batch.buf = buf;
params_batch->get_batch.bufsize = bufsize;
params_batch->get_batch.reason = reason;
params_batch->get_batch.bytes_written = 0;
schedule_work(&_pno_state->work);
wait_for_completion(&_pno_state->get_batch_done);
err = params_batch->get_batch.bytes_written;
exit:
return err;
}
@ -1415,7 +1449,7 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd)
_pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE;
if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_HOTLIST_MODE)) {
mode = _pno_state->pno_mode;
_dhd_pno_clean(dhd);
dhd_pno_clean(dhd);
_pno_state->pno_mode = mode;
/* restart Legacy PNO if the Legacy PNO is on */
if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
@ -1479,9 +1513,9 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd)
}
}
} else {
err = _dhd_pno_clean(dhd);
err = dhd_pno_clean(dhd);
if (err < 0) {
DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n",
DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
__FUNCTION__, err));
goto exit;
}
@ -1674,9 +1708,9 @@ dhd_pno_stop_for_hotlist(dhd_pub_t *dhd)
dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE);
/* save current pno_mode before calling dhd_pno_clean */
mode = _pno_state->pno_mode;
err = _dhd_pno_clean(dhd);
err = dhd_pno_clean(dhd);
if (err < 0) {
DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n",
DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
__FUNCTION__, err));
goto exit;
}
@ -1726,9 +1760,9 @@ dhd_pno_stop_for_hotlist(dhd_pub_t *dhd)
}
}
} else {
err = _dhd_pno_clean(dhd);
err = dhd_pno_clean(dhd);
if (err < 0) {
DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n",
DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n",
__FUNCTION__, err));
goto exit;
}
@ -1765,11 +1799,15 @@ dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)
{
struct dhd_pno_batch_params *params_batch;
params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch;
DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__));
params_batch->get_batch.buf = NULL;
params_batch->get_batch.bufsize = 0;
params_batch->get_batch.reason = PNO_STATUS_EVENT;
schedule_work(&_pno_state->work);
if (!waitqueue_active(&_pno_state->get_batch_done.wait)) {
DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__));
params_batch->get_batch.buf = NULL;
params_batch->get_batch.bufsize = 0;
params_batch->get_batch.reason = PNO_STATUS_EVENT;
schedule_work(&_pno_state->work);
} else
DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING"
"will skip this event\n", __FUNCTION__));
break;
}
default:
@ -1789,8 +1827,8 @@ int dhd_pno_init(dhd_pub_t *dhd)
if (dhd->pno_state)
goto exit;
dhd->pno_state = MALLOC(dhd->osh, sizeof(dhd_pno_status_info_t));
NULL_CHECK(dhd->pno_state, "failed to create dhd_pno_state", err);
memset(dhd->pno_state, 0, sizeof(dhd_pno_status_info_t));
NULL_CHECK(dhd, "failed to create dhd_pno_state", err);
/* need to check whether current firmware support batching and hotlist scan */
_pno_state = PNO_GET_PNOSTATE(dhd);
_pno_state->wls_supported = TRUE;
@ -1810,12 +1848,27 @@ int dhd_pno_init(dhd_pub_t *dhd)
int dhd_pno_deinit(dhd_pub_t *dhd)
{
int err = BCME_OK;
dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd);
dhd_pno_status_info_t *_pno_state;
dhd_pno_params_t *_params;
NULL_CHECK(dhd, "dhd is NULL", err);
DHD_PNO(("%s enter\n", __FUNCTION__));
_pno_state = PNO_GET_PNOSTATE(dhd);
NULL_CHECK(_pno_state, "pno_state is NULL", err);
/* may need to free legacy ssid_list */
if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
_params = &_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
_dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
}
if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
_params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
/* clear resource if the BATCH MODE is on */
_dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
}
cancel_work_sync(&_pno_state->work);
if (dhd->pno_state)
MFREE(dhd->osh, dhd->pno_state, sizeof(dhd_pno_status_info_t));
MFREE(dhd->osh, _pno_state, sizeof(dhd_pno_status_info_t));
dhd->pno_state = NULL;
return err;
}
#endif /* PNO_SUPPORT */

View File

@ -3,12 +3,13 @@
* Prefered Network Offload code and Wi-Fi Location Service(WLS) code.
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_pno.h 419969 2013-08-23 18:54:36Z $
* $Id: dhd_pno.h 423669 2013-09-18 13:01:55Z $
*/
#ifndef __DHD_PNO_H__
#define __DHD_PNO_H__
#if defined(PNO_SUPPORT)
#define PNO_TLV_PREFIX 'S'
#define PNO_TLV_VERSION '1'
#define PNO_TLV_SUBTYPE_LEGACY_PNO '2'
@ -78,7 +79,7 @@ typedef struct cmd_tlv {
} cmd_tlv_t;
typedef enum dhd_pno_mode {
/* Wi-Fi Legacy PNO Mode */
DHD_PNO_NONE_MODE = 0,
DHD_PNO_NONE_MODE = 0,
DHD_PNO_LEGACY_MODE = (1 << (0)),
/* Wi-Fi Android BATCH SCAN Mode */
DHD_PNO_BATCH_MODE = (1 << (1)),
@ -134,6 +135,7 @@ struct dhd_pno_get_batch_info {
uint32 expired_tot_scan_cnt;
uint32 top_node_cnt;
uint32 bufsize;
uint32 bytes_written;
int reason;
struct list_head scan_results_list;
struct list_head expired_scan_results_list;
@ -228,4 +230,14 @@ extern int dhd_pno_stop_for_hotlist(dhd_pub_t *dhd);
extern int dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data);
extern int dhd_pno_init(dhd_pub_t *dhd);
extern int dhd_pno_deinit(dhd_pub_t *dhd);
#endif
#if (defined(NDISVER) && (NDISVER >= 0x0630)) && defined(PNO_SUPPORT)
extern int dhd_pno_cfg(dhd_pub_t *dhd, wl_pfn_cfg_t *pcfg);
extern int dhd_pno_suspend(dhd_pub_t *dhd, int pfn_suspend);
extern int dhd_pno_set_add(dhd_pub_t *dhd, wl_pfn_t *netinfo, int nssid, ushort scan_fr,
ushort slowscan_fr, uint8 pno_repeat, uint8 pno_freq_expo_max, int16 flags);
extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
extern int dhd_pno_clean(dhd_pub_t *dhd);
#endif /* (defined(NDISVER) && (NDISVER >= 0x0630)) && defined(PNO_SUPPORT) */
#endif /* __DHD_PNO_H__ */

View File

@ -6,7 +6,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhd_proto.h 390836 2013-03-13 23:43:53Z $
* $Id: dhd_proto.h 490409 2014-07-10 16:34:27Z $
*/
#ifndef _dhd_proto_h_
@ -14,11 +14,18 @@
#include <dhdioctl.h>
#include <wlioctl.h>
#ifdef BCMPCIE
#include <dhd_flowring.h>
#endif
#ifndef IOCTL_RESP_TIMEOUT
#define IOCTL_RESP_TIMEOUT 2000 /* In milli second default value for Production FW */
#endif /* IOCTL_RESP_TIMEOUT */
#ifndef MFG_IOCTL_RESP_TIMEOUT
#define MFG_IOCTL_RESP_TIMEOUT 20000 /* In milli second default value for MFG FW */
#endif /* MFG_IOCTL_RESP_TIMEOUT */
/*
* Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
*/
@ -26,13 +33,19 @@
/* Linkage, sets prot link and updates hdrlen in pub */
extern int dhd_prot_attach(dhd_pub_t *dhdp);
/* Initilizes the index block for dma'ing indices */
extern int dhd_prot_init_index_dma_block(dhd_pub_t *dhdp, uint8 type, uint32 length);
/* Unlink, frees allocated protocol memory (including dhd_prot) */
extern void dhd_prot_detach(dhd_pub_t *dhdp);
/* Initialize protocol: sync w/dongle state.
* Sets dongle media info (iswl, drv_version, mac address).
*/
extern int dhd_prot_init(dhd_pub_t *dhdp);
extern int dhd_sync_with_dongle(dhd_pub_t *dhdp);
/* Protocol initialization needed for IOCTL/IOVAR path */
extern int dhd_prot_init(dhd_pub_t *dhd);
/* Stop protocol: sync w/dongle state. */
extern void dhd_prot_stop(dhd_pub_t *dhdp);
@ -41,6 +54,7 @@ extern void dhd_prot_stop(dhd_pub_t *dhdp);
* Caller must reserve prot_hdrlen prepend space.
*/
extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, void *txp);
extern uint dhd_prot_hdrlen(dhd_pub_t *, void *txp);
/* Remove any protocol-specific data header. */
extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, void *rxp, uchar *buf, uint *len);
@ -68,6 +82,34 @@ extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
extern int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf,
uint reorder_info_len, void **pkt, uint32 *free_buf_count);
#ifdef BCMPCIE
extern int dhd_prot_process_msgbuf_txcpl(dhd_pub_t *dhd);
extern int dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd);
extern int dhd_prot_process_ctrlbuf(dhd_pub_t * dhd);
extern bool dhd_prot_dtohsplit(dhd_pub_t * dhd);
extern int dhd_post_dummy_msg(dhd_pub_t *dhd);
extern int dhdmsgbuf_lpbk_req(dhd_pub_t *dhd, uint len);
extern void dhd_prot_rx_dataoffset(dhd_pub_t *dhd, uint32 offset);
extern int dhd_prot_txdata(dhd_pub_t *dhd, void *p, uint8 ifidx);
extern int dhdmsgbuf_dmaxfer_req(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay);
extern int dhd_prot_flow_ring_create(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node);
extern void dhd_prot_clean_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info);
extern int dhd_post_tx_ring_item(dhd_pub_t *dhd, void *PKTBUF, uint8 ifindex);
extern int dhd_prot_flow_ring_delete(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node);
extern int dhd_prot_flow_ring_flush(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node);
extern int dhd_prot_ringupd_dump(dhd_pub_t *dhd, struct bcmstrbuf *b);
extern uint32 dhd_prot_metadatalen_set(dhd_pub_t *dhd, uint32 val, bool rx);
extern uint32 dhd_prot_metadatalen_get(dhd_pub_t *dhd, bool rx);
extern void dhd_prot_print_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info,
struct bcmstrbuf *strbuf);
extern void dhd_prot_print_info(dhd_pub_t *dhd, struct bcmstrbuf *strbuf);
extern void dhd_prot_update_txflowring(dhd_pub_t *dhdp, uint16 flow_id, void *msgring_info);
extern void dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flow_id, bool in_lock);
extern uint32 dhd_prot_txp_threshold(dhd_pub_t *dhd, bool set, uint32 val);
extern void dhd_prot_clear(dhd_pub_t *dhd);
#endif /* BCMPCIE */
/********************************
* For version-string expansion *

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/skbuff.h>
#include <linux/wlan_plat.h>
#define CONFIG_BROADCOM_WIFI_RESERVED_MEM
#ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM
#define WLAN_STATIC_PKT_BUF 4
#define WLAN_STATIC_SCAN_BUF0 5
#define WLAN_STATIC_SCAN_BUF1 6
#define WLAN_STATIC_DHD_INFO 7
#define PREALLOC_WLAN_SEC_NUM 5
#define PREALLOC_WLAN_BUF_NUM 160
#define PREALLOC_WLAN_SECTION_HEADER 24
#define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_BUF_NUM * 128)
#define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_BUF_NUM * 128)
#define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_BUF_NUM * 512)
#define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_BUF_NUM * 1024)
#define WLAN_SECTION_SIZE_7 (PREALLOC_WLAN_BUF_NUM * 128)
#define DHD_SKB_HDRSIZE 336
#define DHD_SKB_1PAGE_BUFSIZE ((PAGE_SIZE*1)-DHD_SKB_HDRSIZE)
#define DHD_SKB_2PAGE_BUFSIZE ((PAGE_SIZE*2)-DHD_SKB_HDRSIZE)
#define DHD_SKB_4PAGE_BUFSIZE ((PAGE_SIZE*4)-DHD_SKB_HDRSIZE)
#define WLAN_SKB_BUF_NUM 17
static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
struct wlan_mem_prealloc {
void *mem_ptr;
unsigned long size;
};
static struct wlan_mem_prealloc wlan_mem_array[PREALLOC_WLAN_SEC_NUM] = {
{NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER)},
{NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER)},
{NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER)},
{NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER)},
{NULL, (WLAN_SECTION_SIZE_7 + PREALLOC_WLAN_SECTION_HEADER)}
};
void *wlan_static_scan_buf0;
void *wlan_static_scan_buf1;
void *bcmdhd_mem_prealloc(int section, unsigned long size)
{
if (section == WLAN_STATIC_PKT_BUF) {
printk("1 %s: section=%d, wlan_static_skb=%p\n",
__FUNCTION__, section, wlan_static_skb);
return wlan_static_skb;
}
if (section == WLAN_STATIC_SCAN_BUF0) {
printk("2 %s: section=%d, wlan_static_scan_buf0=%p\n",
__FUNCTION__, section, wlan_static_scan_buf0);
return wlan_static_scan_buf0;
}
if (section == WLAN_STATIC_SCAN_BUF1) {
printk("3 %s: section=%d, wlan_static_scan_buf1=%p\n",
__FUNCTION__, section, wlan_static_scan_buf1);
return wlan_static_scan_buf1;
}
if (section == WLAN_STATIC_DHD_INFO) {
printk("4 %s: section=%d, wlan_mem_array[4]=%p\n",
__FUNCTION__, section, wlan_mem_array[4].mem_ptr);
return wlan_mem_array[4].mem_ptr;
}
if ((section < 0) || (section > PREALLOC_WLAN_SEC_NUM)) {
printk("5 %s: out of section %d\n", __FUNCTION__, section);
return NULL;
}
if (wlan_mem_array[section].size < size) {
printk("6 %s: wlan_mem_array[section].size=%lu, size=%lu\n",
__FUNCTION__, wlan_mem_array[section].size, size);
return NULL;
}
printk("7 %s: wlan_mem_array[section].mem_ptr=%p, size=%lu\n",
__FUNCTION__, &wlan_mem_array[section], size);
return wlan_mem_array[section].mem_ptr;
}
EXPORT_SYMBOL(bcmdhd_mem_prealloc);
int bcmdhd_init_wlan_mem(void)
{
int i;
int j;
for (i=0; i<8; i++) {
wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);
if (!wlan_static_skb[i])
goto err_skb_alloc;
printk("1 %s: wlan_static_skb[%d]=%p, size=%lu\n",
__FUNCTION__, i, wlan_static_skb[i], DHD_SKB_1PAGE_BUFSIZE);
}
for (; i<16; i++) {
wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);
if (!wlan_static_skb[i])
goto err_skb_alloc;
printk("2 %s: wlan_static_skb[%d]=%p, size=%lu\n",
__FUNCTION__, i, wlan_static_skb[i], DHD_SKB_2PAGE_BUFSIZE);
}
wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);
if (!wlan_static_skb[i])
goto err_skb_alloc;
printk("3 %s: wlan_static_skb[%d]=%p, size=%lu\n",
__FUNCTION__, i, wlan_static_skb[i], DHD_SKB_4PAGE_BUFSIZE);
for (i=0; i<PREALLOC_WLAN_SEC_NUM; i++) {
wlan_mem_array[i].mem_ptr =
kmalloc(wlan_mem_array[i].size, GFP_KERNEL);
if (!wlan_mem_array[i].mem_ptr)
goto err_mem_alloc;
printk("4 %s: wlan_mem_array[%d]=%p, size=%lu\n",
__FUNCTION__, i, wlan_static_skb[i], wlan_mem_array[i].size);
}
wlan_static_scan_buf0 = kmalloc (65536, GFP_KERNEL);
if(!wlan_static_scan_buf0)
goto err_mem_alloc;
printk("5 %s: wlan_static_scan_buf0=%p, size=%d\n",
__FUNCTION__, wlan_static_scan_buf0, 65536);
wlan_static_scan_buf1 = kmalloc (65536, GFP_KERNEL);
if(!wlan_static_scan_buf1)
goto err_mem_alloc;
printk("6 %s: wlan_static_scan_buf1=%p, size=%d\n",
__FUNCTION__, wlan_static_scan_buf1, 65536);
printk("%s: WIFI MEM Allocated\n", __FUNCTION__);
return 0;
err_mem_alloc:
pr_err("Failed to mem_alloc for WLAN\n");
for (j=0; j<i; j++)
kfree(wlan_mem_array[j].mem_ptr);
i = WLAN_SKB_BUF_NUM;
err_skb_alloc:
pr_err("Failed to skb_alloc for WLAN\n");
for (j=0; j<i; j++)
dev_kfree_skb(wlan_static_skb[j]);
return -ENOMEM;
}
#endif /* CONFIG_BROADCOM_WIFI_RESERVED_MEM */
static int __init bcmdhd_wlan_init(void)
{
printk("%s()\n", __FUNCTION__);
#ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM
bcmdhd_init_wlan_mem();
#endif
return 0;
}
__initcall(bcmdhd_wlan_init);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
* $Copyright Open 2009 Broadcom Corporation$
* $Id: dhd_wlfc.h 398418 2013-04-24 15:18:27Z $
* $Id: dhd_wlfc.h 490028 2014-07-09 05:58:25Z $
*
*/
#ifndef __wlfc_host_driver_definitions_h__
@ -10,35 +10,30 @@
#include <dhd_qmon.h>
#endif
/* #define OOO_DEBUG */
#define WLFC_UNSUPPORTED -9999
#define WLFC_NO_TRAFFIC -1
#define WLFC_MULTI_TRAFFIC 0
#define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */
/* 16 bits will provide an absolute max of 65536 slots */
#define WLFC_HANGER_MAXITEMS 1024
#define WLFC_HANGER_MAXITEMS 3072
#define WLFC_HANGER_ITEM_STATE_FREE 1
#define WLFC_HANGER_ITEM_STATE_FREE 1
#define WLFC_HANGER_ITEM_STATE_INUSE 2
#define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3
#define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3
#define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */
#define WLFC_PKTID_HSLOT_SHIFT 8
#define WLFC_HANGER_PKT_STATE_TXSTATUS 1
#define WLFC_HANGER_PKT_STATE_TXCOMPLETE 2
#define WLFC_HANGER_PKT_STATE_CLEANUP 4
/* x -> TXSTATUS TAG to/from firmware */
#define WLFC_PKTID_HSLOT_GET(x) \
(((x) >> WLFC_PKTID_HSLOT_SHIFT) & WLFC_PKTID_HSLOT_MASK)
#define WLFC_PKTID_HSLOT_SET(var, slot) \
((var) = ((var) & ~(WLFC_PKTID_HSLOT_MASK << WLFC_PKTID_HSLOT_SHIFT)) | \
(((slot) & WLFC_PKTID_HSLOT_MASK) << WLFC_PKTID_HSLOT_SHIFT))
#define WLFC_PKTID_FREERUNCTR_MASK 0xff
#define WLFC_PKTID_FREERUNCTR_GET(x) ((x) & WLFC_PKTID_FREERUNCTR_MASK)
#define WLFC_PKTID_FREERUNCTR_SET(var, ctr) \
((var) = (((var) & ~WLFC_PKTID_FREERUNCTR_MASK) | \
(((ctr) & WLFC_PKTID_FREERUNCTR_MASK))))
#define WLFC_PKTQ_PENQ(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec)))? \
NULL : pktq_penq((pq), (prec), (p)))
#define WLFC_PKTQ_PENQ_HEAD(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec))) ? \
NULL : pktq_penq_head((pq), (prec), (p)))
typedef enum {
Q_TYPE_PSQ,
Q_TYPE_AFQ
} q_type_t;
typedef enum ewlfc_packet_state {
eWLFC_PKTTYPE_NEW,
@ -57,12 +52,14 @@ typedef enum ewlfc_mac_entry_action {
typedef struct wlfc_hanger_item {
uint8 state;
uint8 gen;
uint8 pad[2];
uint8 pkt_state;
uint8 pkt_txstatus;
uint32 identifier;
void* pkt;
#ifdef PROP_TXSTATUS_DEBUG
uint32 push_time;
#endif
struct wlfc_hanger_item *next;
} wlfc_hanger_item_t;
typedef struct wlfc_hanger {
@ -83,12 +80,15 @@ typedef struct wlfc_hanger {
#define WLFC_STATE_CLOSE 2
#define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /* 2 for each AC traffic and bc/mc */
#define WLFC_AFQ_PREC_COUNT (AC_COUNT + 1)
#define WLFC_PSQ_LEN 2048
#define WLFC_FLOWCONTROL_HIWATER (2048 - 256)
#define WLFC_FLOWCONTROL_LOWATER 256
#define WLFC_LOG_BUF_SIZE (1024*1024)
typedef struct wlfc_mac_descriptor {
uint8 occupied;
uint8 interface_id;
@ -105,6 +105,8 @@ typedef struct wlfc_mac_descriptor {
uint8 seq[AC_COUNT + 1];
uint8 generation;
struct pktq psq;
/* packets at firmware */
struct pktq afq;
/* The AC pending bitmap that was reported to the fw at last change */
uint8 traffic_lastreported_bmp;
/* The new AC pending bitmap */
@ -112,17 +114,12 @@ typedef struct wlfc_mac_descriptor {
/* 1= send on next opportunity */
uint8 send_tim_signal;
uint8 mac_handle;
/* Number of packets in transit for this entry. */
/* Number of packets at dongle for this entry. */
uint transit_count;
/* Numbe of suppression to wait before evict from delayQ */
uint suppr_transit_count;
/* Used when a new suppress is detected to track the number of
* packets getting suppressed
*/
uint suppress_count;
/* flag. TRUE when in suppress state */
uint8 suppressed;
uint8 deleting;
#ifdef QMONITOR
dhd_qmon_t qmon;
@ -134,8 +131,18 @@ typedef struct wlfc_mac_descriptor {
uint32 opened_ct;
uint32 closed_ct;
#endif
struct wlfc_mac_descriptor* prev;
struct wlfc_mac_descriptor* next;
} wlfc_mac_descriptor_t;
typedef struct dhd_wlfc_commit_info {
uint8 needs_hdr;
uint8 ac_fifo_credit_spent;
ewlfc_packet_state_t pkt_type;
wlfc_mac_descriptor_t* mac_entry;
void* p;
} dhd_wlfc_commit_info_t;
#define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\
entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0)
@ -144,6 +151,7 @@ typedef struct wlfc_mac_descriptor {
typedef struct athost_wl_stat_counters {
uint32 pktin;
uint32 pktout;
uint32 pkt2bus;
uint32 pktdropped;
uint32 tlv_parse_failed;
@ -174,12 +182,14 @@ typedef struct athost_wl_stat_counters {
uint32 generic_error;
/* an extra one for bc/mc traffic */
uint32 send_pkts[AC_COUNT + 1];
uint32 drop_pkts[WLFC_PSQ_PREC_COUNT];
uint32 ooo_pkts[AC_COUNT + 1];
#ifdef PROP_TXSTATUS_DEBUG
/* all pkt2bus -> txstatus latency accumulated */
uint32 latency_sample_count;
uint32 total_status_latency;
uint32 latency_most_recent;
int idx_delta;
int idx_delta;
uint32 deltas[10];
uint32 fifo_credits_sent[6];
uint32 fifo_credits_back[6];
@ -187,6 +197,9 @@ typedef struct athost_wl_stat_counters {
uint32 signal_only_pkts_sent;
uint32 signal_only_pkts_freed;
#endif
uint32 cleanup_txq_cnt;
uint32 cleanup_psq_cnt;
uint32 cleanup_fw_cnt;
} athost_wl_stat_counters_t;
#ifdef PROP_TXSTATUS_DEBUG
@ -205,16 +218,23 @@ typedef struct athost_wl_stat_counters {
#define WLFC_FCMODE_NONE 0
#define WLFC_FCMODE_IMPLIED_CREDIT 1
#define WLFC_FCMODE_EXPLICIT_CREDIT 2
#define WLFC_ONLY_AMPDU_HOSTREORDER 3
/* Reserved credits ratio when borrowed by hihger priority */
#define WLFC_BORROW_LIMIT_RATIO 4
/* How long to defer borrowing in milliseconds */
#define WLFC_BORROW_DEFER_PERIOD_MS 100
/* How long to defer flow control in milliseconds */
#define WLFC_FC_DEFER_PERIOD_MS 200
/* How long to detect occurance per AC in miliseconds */
#define WLFC_RX_DETECTION_THRESHOLD_MS 100
/* Mask to represent available ACs (note: BC/MC is ignored */
#define WLFC_AC_MASK 0xF
/* Mask to check for only on-going AC_BE traffic */
#define WLFC_AC_BE_TRAFFIC_ONLY 0xD
typedef struct athost_wl_status_info {
uint8 last_seqid_to_wlc;
@ -226,6 +246,8 @@ typedef struct athost_wl_status_info {
/* stats */
athost_wl_stat_counters_t stats;
int Init_FIFO_credit[AC_COUNT + 2];
/* the additional ones are for bc/mc and ATIM FIFO */
int FIFO_credit[AC_COUNT + 2];
@ -243,46 +265,241 @@ typedef struct athost_wl_status_info {
/* A place holder for bc/mc and packets to unknown destinations */
wlfc_mac_descriptor_t other;
} destination_entries;
/* token position for different priority packets */
uint8 token_pos[AC_COUNT+1];
wlfc_mac_descriptor_t *active_entry_head;
int active_entry_count;
wlfc_mac_descriptor_t* requested_entry[WLFC_MAC_DESC_TABLE_SIZE];
int requested_entry_count;
/* pkt counts for each interface and ac */
int pkt_cnt_in_q[WLFC_MAX_IFNUM][AC_COUNT+1];
int pkt_cnt_per_ac[AC_COUNT+1];
int pkt_cnt_in_drv[WLFC_MAX_IFNUM][AC_COUNT+1];
uint8 allow_fc;
uint32 fc_defer_timestamp;
uint32 rx_timestamp[AC_COUNT+1];
/* ON/OFF state for flow control to the host network interface */
uint8 hostif_flow_state[WLFC_MAX_IFNUM];
uint8 host_ifidx;
/* to flow control an OS interface */
uint8 toggle_host_if;
/*
Mode in which the dhd flow control shall operate. Must be set before
traffic starts to the device.
0 - Do not do any proptxtstatus flow control
1 - Use implied credit from a packet status
2 - Use explicit credit
*/
uint8 proptxstatus_mode;
/* To borrow credits */
uint8 allow_credit_borrow;
/* Timestamp to compute how long to defer borrowing for */
uint32 borrow_defer_timestamp;
/* ac number for the first single ac traffic */
uint8 single_ac;
/* Timestamp for the first single ac traffic */
uint32 single_ac_timestamp;
bool bcmc_credit_supported;
} athost_wl_status_info_t;
int dhd_wlfc_enable(dhd_pub_t *dhd);
int dhd_wlfc_interface_event(struct dhd_info *,
ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea);
int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data);
int dhd_wlfc_event(struct dhd_info *dhd);
int dhd_os_wlfc_block(dhd_pub_t *pub);
int dhd_os_wlfc_unblock(dhd_pub_t *pub);
/* Please be mindful that total pkttag space is 32 octets only */
typedef struct dhd_pkttag {
/*
b[15] - 1 = wlfc packet
b[14:13] - encryption exemption
b[12 ] - 1 = event channel
b[11 ] - 1 = this packet was sent in response to one time packet request,
do not increment credit on status for this one. [WLFC_CTL_TYPE_MAC_REQUEST_PACKET].
b[10 ] - 1 = signal-only-packet to firmware [i.e. nothing to piggyback on]
b[9 ] - 1 = packet is host->firmware (transmit direction)
- 0 = packet received from firmware (firmware->host)
b[8 ] - 1 = packet was sent due to credit_request (pspoll),
packet does not count against FIFO credit.
- 0 = normal transaction, packet counts against FIFO credit
b[7 ] - 1 = AP, 0 = STA
b[6:4] - AC FIFO number
b[3:0] - interface index
*/
uint16 if_flags;
/* destination MAC address for this packet so that not every
module needs to open the packet to find this
*/
uint8 dstn_ether[ETHER_ADDR_LEN];
/*
This 32-bit goes from host to device for every packet.
*/
uint32 htod_tag;
void dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
int dhd_wlfc_init(dhd_pub_t *dhd);
void dhd_wlfc_deinit(dhd_pub_t *dhd);
/*
This 16-bit is original seq number for every suppress packet.
*/
uint16 htod_seq;
/*
This address is mac entry for every packet.
*/
void* entry;
/* bus specific stuff */
union {
struct {
void* stuff;
uint32 thing1;
uint32 thing2;
} sd;
struct {
void* bus;
void* urb;
} usb;
} bus_specific;
} dhd_pkttag_t;
#define DHD_PKTTAG_WLFCPKT_MASK 0x1
#define DHD_PKTTAG_WLFCPKT_SHIFT 15
#define DHD_PKTTAG_WLFCPKT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_WLFCPKT_MASK << DHD_PKTTAG_WLFCPKT_SHIFT)) | \
(((value) & DHD_PKTTAG_WLFCPKT_MASK) << DHD_PKTTAG_WLFCPKT_SHIFT)
#define DHD_PKTTAG_WLFCPKT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_WLFCPKT_SHIFT) & DHD_PKTTAG_WLFCPKT_MASK)
#define DHD_PKTTAG_EXEMPT_MASK 0x3
#define DHD_PKTTAG_EXEMPT_SHIFT 13
#define DHD_PKTTAG_EXEMPT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_EXEMPT_MASK << DHD_PKTTAG_EXEMPT_SHIFT)) | \
(((value) & DHD_PKTTAG_EXEMPT_MASK) << DHD_PKTTAG_EXEMPT_SHIFT)
#define DHD_PKTTAG_EXEMPT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_EXEMPT_SHIFT) & DHD_PKTTAG_EXEMPT_MASK)
#define DHD_PKTTAG_EVENT_MASK 0x1
#define DHD_PKTTAG_EVENT_SHIFT 12
#define DHD_PKTTAG_SETEVENT(tag, event) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_EVENT_MASK << DHD_PKTTAG_EVENT_SHIFT)) | \
(((event) & DHD_PKTTAG_EVENT_MASK) << DHD_PKTTAG_EVENT_SHIFT)
#define DHD_PKTTAG_EVENT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_EVENT_SHIFT) & DHD_PKTTAG_EVENT_MASK)
#define DHD_PKTTAG_ONETIMEPKTRQST_MASK 0x1
#define DHD_PKTTAG_ONETIMEPKTRQST_SHIFT 11
#define DHD_PKTTAG_SETONETIMEPKTRQST(tag) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_ONETIMEPKTRQST_MASK << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)) | \
(1 << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)
#define DHD_PKTTAG_ONETIMEPKTRQST(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) & DHD_PKTTAG_ONETIMEPKTRQST_MASK)
#define DHD_PKTTAG_SIGNALONLY_MASK 0x1
#define DHD_PKTTAG_SIGNALONLY_SHIFT 10
#define DHD_PKTTAG_SETSIGNALONLY(tag, signalonly) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_SIGNALONLY_MASK << DHD_PKTTAG_SIGNALONLY_SHIFT)) | \
(((signalonly) & DHD_PKTTAG_SIGNALONLY_MASK) << DHD_PKTTAG_SIGNALONLY_SHIFT)
#define DHD_PKTTAG_SIGNALONLY(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_SIGNALONLY_SHIFT) & DHD_PKTTAG_SIGNALONLY_MASK)
#define DHD_PKTTAG_PKTDIR_MASK 0x1
#define DHD_PKTTAG_PKTDIR_SHIFT 9
#define DHD_PKTTAG_SETPKTDIR(tag, dir) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_PKTDIR_MASK << DHD_PKTTAG_PKTDIR_SHIFT)) | \
(((dir) & DHD_PKTTAG_PKTDIR_MASK) << DHD_PKTTAG_PKTDIR_SHIFT)
#define DHD_PKTTAG_PKTDIR(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_PKTDIR_SHIFT) & DHD_PKTTAG_PKTDIR_MASK)
#define DHD_PKTTAG_CREDITCHECK_MASK 0x1
#define DHD_PKTTAG_CREDITCHECK_SHIFT 8
#define DHD_PKTTAG_SETCREDITCHECK(tag, check) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_CREDITCHECK_MASK << DHD_PKTTAG_CREDITCHECK_SHIFT)) | \
(((check) & DHD_PKTTAG_CREDITCHECK_MASK) << DHD_PKTTAG_CREDITCHECK_SHIFT)
#define DHD_PKTTAG_CREDITCHECK(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_CREDITCHECK_SHIFT) & DHD_PKTTAG_CREDITCHECK_MASK)
#define DHD_PKTTAG_IFTYPE_MASK 0x1
#define DHD_PKTTAG_IFTYPE_SHIFT 7
#define DHD_PKTTAG_SETIFTYPE(tag, isAP) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & \
~(DHD_PKTTAG_IFTYPE_MASK << DHD_PKTTAG_IFTYPE_SHIFT)) | \
(((isAP) & DHD_PKTTAG_IFTYPE_MASK) << DHD_PKTTAG_IFTYPE_SHIFT)
#define DHD_PKTTAG_IFTYPE(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_IFTYPE_SHIFT) & DHD_PKTTAG_IFTYPE_MASK)
#define DHD_PKTTAG_FIFO_MASK 0x7
#define DHD_PKTTAG_FIFO_SHIFT 4
#define DHD_PKTTAG_SETFIFO(tag, fifo) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_FIFO_MASK << DHD_PKTTAG_FIFO_SHIFT)) | \
(((fifo) & DHD_PKTTAG_FIFO_MASK) << DHD_PKTTAG_FIFO_SHIFT)
#define DHD_PKTTAG_FIFO(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_FIFO_SHIFT) & DHD_PKTTAG_FIFO_MASK)
#define DHD_PKTTAG_IF_MASK 0xf
#define DHD_PKTTAG_IF_SHIFT 0
#define DHD_PKTTAG_SETIF(tag, if) ((dhd_pkttag_t*)(tag))->if_flags = \
(((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_IF_MASK << DHD_PKTTAG_IF_SHIFT)) | \
(((if) & DHD_PKTTAG_IF_MASK) << DHD_PKTTAG_IF_SHIFT)
#define DHD_PKTTAG_IF(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \
DHD_PKTTAG_IF_SHIFT) & DHD_PKTTAG_IF_MASK)
#define DHD_PKTTAG_SETDSTN(tag, dstn_MAC_ea) memcpy(((dhd_pkttag_t*)((tag)))->dstn_ether, \
(dstn_MAC_ea), ETHER_ADDR_LEN)
#define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether
#define DHD_PKTTAG_SET_H2DTAG(tag, h2dvalue) ((dhd_pkttag_t*)(tag))->htod_tag = (h2dvalue)
#define DHD_PKTTAG_H2DTAG(tag) (((dhd_pkttag_t*)(tag))->htod_tag)
#define DHD_PKTTAG_SET_H2DSEQ(tag, seq) ((dhd_pkttag_t*)(tag))->htod_seq = (seq)
#define DHD_PKTTAG_H2DSEQ(tag) (((dhd_pkttag_t*)(tag))->htod_seq)
#define DHD_PKTTAG_SET_ENTRY(tag, entry) ((dhd_pkttag_t*)(tag))->entry = (entry)
#define DHD_PKTTAG_ENTRY(tag) (((dhd_pkttag_t*)(tag))->entry)
#define PSQ_SUP_IDX(x) (x * 2 + 1)
#define PSQ_DLY_IDX(x) (x * 2)
typedef int (*f_commitpkt_t)(void* ctx, void* p);
typedef bool (*f_processpkt_t)(void* p, void* arg);
#ifdef PROP_TXSTATUS_DEBUG
#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0)
#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do { (entry)->opened_ct++; } while (0)
#else
#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do {} while (0)
#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do {} while (0)
#endif
/* public functions */
int dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len,
uchar *reorder_info_buf, uint *reorder_info_len);
int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit,
void* commit_ctx, void *pktbuf);
void dhd_wlfc_cleanup(dhd_pub_t *dhd, ifpkt_cb_t fn, int arg);
bool ifpkt_fn(void* p, int ifid);
int dhd_wlfc_commit_packets(dhd_pub_t *dhdp, f_commitpkt_t fcommit,
void* commit_ctx, void *pktbuf, bool need_toggle_host_if);
int dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success);
int dhd_wlfc_init(dhd_pub_t *dhd);
#ifdef SUPPORT_P2P_GO_PS
int dhd_wlfc_suspend(dhd_pub_t *dhd);
int dhd_wlfc_resume(dhd_pub_t *dhd);
#endif /* SUPPORT_P2P_GO_PS */
int dhd_wlfc_hostreorder_init(dhd_pub_t *dhd);
int dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg);
int dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void* arg);
int dhd_wlfc_deinit(dhd_pub_t *dhd);
int dhd_wlfc_interface_event(dhd_pub_t *dhdp, uint8 action, uint8 ifid, uint8 iftype, uint8* ea);
int dhd_wlfc_FIFOcreditmap_event(dhd_pub_t *dhdp, uint8* event_data);
int dhd_wlfc_BCMCCredit_support_event(dhd_pub_t *dhdp);
int dhd_wlfc_enable(dhd_pub_t *dhdp);
int dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
int dhd_wlfc_clear_counts(dhd_pub_t *dhd);
int dhd_wlfc_get_enable(dhd_pub_t *dhd, bool *val);
int dhd_wlfc_get_mode(dhd_pub_t *dhd, int *val);
int dhd_wlfc_set_mode(dhd_pub_t *dhd, int val);
bool dhd_wlfc_is_supported(dhd_pub_t *dhd);
bool dhd_wlfc_is_header_only_pkt(dhd_pub_t * dhd, void *pktbuf);
int dhd_wlfc_flowcontrol(dhd_pub_t *dhdp, bool state, bool bAcquireLock);
int dhd_wlfc_save_rxpath_ac_time(dhd_pub_t * dhd, uint8 prio);
int dhd_wlfc_get_module_ignore(dhd_pub_t *dhd, int *val);
int dhd_wlfc_set_module_ignore(dhd_pub_t *dhd, int val);
int dhd_wlfc_get_credit_ignore(dhd_pub_t *dhd, int *val);
int dhd_wlfc_set_credit_ignore(dhd_pub_t *dhd, int val);
int dhd_wlfc_get_txstatus_ignore(dhd_pub_t *dhd, int *val);
int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val);
int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val);
int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val);
#endif /* __wlfc_host_driver_definitions_h__ */

View File

@ -4,7 +4,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dngl_stats.h 241182 2011-02-17 21:50:03Z $
* $Id: dngl_stats.h 464743 2014-03-25 21:04:32Z $
*/
#ifndef _dngl_stats_h_

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dngl_wlhdr.h 241182 2011-02-17 21:50:03Z $
* $Id: dngl_wlhdr.h 464743 2014-03-25 21:04:32Z $
*/
#ifndef _dngl_wlhdr_h_

View File

@ -0,0 +1,733 @@
/*
* HND generic packet pool operation primitives
*
* $Copyright Open Broadcom Corporation$
*
* $Id: $
*/
#include <typedefs.h>
#include <osl.h>
#include <bcmutils.h>
#include <hnd_pktpool.h>
/* Registry size is one larger than max pools, as slot #0 is reserved */
#define PKTPOOLREG_RSVD_ID (0U)
#define PKTPOOLREG_RSVD_PTR (POOLPTR(0xdeaddead))
#define PKTPOOLREG_FREE_PTR (POOLPTR(NULL))
#define PKTPOOL_REGISTRY_SET(id, pp) (pktpool_registry_set((id), (pp)))
#define PKTPOOL_REGISTRY_CMP(id, pp) (pktpool_registry_cmp((id), (pp)))
/* Tag a registry entry as free for use */
#define PKTPOOL_REGISTRY_CLR(id) \
PKTPOOL_REGISTRY_SET((id), PKTPOOLREG_FREE_PTR)
#define PKTPOOL_REGISTRY_ISCLR(id) \
(PKTPOOL_REGISTRY_CMP((id), PKTPOOLREG_FREE_PTR))
/* Tag registry entry 0 as reserved */
#define PKTPOOL_REGISTRY_RSV() \
PKTPOOL_REGISTRY_SET(PKTPOOLREG_RSVD_ID, PKTPOOLREG_RSVD_PTR)
#define PKTPOOL_REGISTRY_ISRSVD() \
(PKTPOOL_REGISTRY_CMP(PKTPOOLREG_RSVD_ID, PKTPOOLREG_RSVD_PTR))
/* Walk all un-reserved entries in registry */
#define PKTPOOL_REGISTRY_FOREACH(id) \
for ((id) = 1U; (id) <= pktpools_max; (id)++)
uint32 pktpools_max = 0U; /* maximum number of pools that may be initialized */
pktpool_t *pktpools_registry[PKTPOOL_MAXIMUM_ID + 1]; /* Pktpool registry */
/* Register/Deregister a pktpool with registry during pktpool_init/deinit */
static int pktpool_register(pktpool_t * poolptr);
static int pktpool_deregister(pktpool_t * poolptr);
/** accessor functions required when ROMming this file, forced into RAM */
static void
BCMRAMFN(pktpool_registry_set)(int id, pktpool_t *pp)
{
pktpools_registry[id] = pp;
}
static bool
BCMRAMFN(pktpool_registry_cmp)(int id, pktpool_t *pp)
{
return pktpools_registry[id] == pp;
}
int /* Construct a pool registry to serve a maximum of total_pools */
pktpool_attach(osl_t *osh, uint32 total_pools)
{
uint32 poolid;
if (pktpools_max != 0U) {
return BCME_ERROR;
}
ASSERT(total_pools <= PKTPOOL_MAXIMUM_ID);
/* Initialize registry: reserve slot#0 and tag others as free */
PKTPOOL_REGISTRY_RSV(); /* reserve slot#0 */
PKTPOOL_REGISTRY_FOREACH(poolid) { /* tag all unreserved entries as free */
PKTPOOL_REGISTRY_CLR(poolid);
}
pktpools_max = total_pools;
return (int)pktpools_max;
}
int /* Destruct the pool registry. Ascertain all pools were first de-inited */
pktpool_dettach(osl_t *osh)
{
uint32 poolid;
if (pktpools_max == 0U) {
return BCME_OK;
}
/* Ascertain that no pools are still registered */
ASSERT(PKTPOOL_REGISTRY_ISRSVD()); /* assert reserved slot */
PKTPOOL_REGISTRY_FOREACH(poolid) { /* ascertain all others are free */
ASSERT(PKTPOOL_REGISTRY_ISCLR(poolid));
}
pktpools_max = 0U; /* restore boot state */
return BCME_OK;
}
static int /* Register a pool in a free slot; return the registry slot index */
pktpool_register(pktpool_t * poolptr)
{
uint32 poolid;
if (pktpools_max == 0U) {
return PKTPOOL_INVALID_ID; /* registry has not yet been constructed */
}
ASSERT(pktpools_max != 0U);
/* find an empty slot in pktpools_registry */
PKTPOOL_REGISTRY_FOREACH(poolid) {
if (PKTPOOL_REGISTRY_ISCLR(poolid)) {
PKTPOOL_REGISTRY_SET(poolid, POOLPTR(poolptr)); /* register pool */
return (int)poolid; /* return pool ID */
}
} /* FOREACH */
return PKTPOOL_INVALID_ID; /* error: registry is full */
}
static int /* Deregister a pktpool, given the pool pointer; tag slot as free */
pktpool_deregister(pktpool_t * poolptr)
{
uint32 poolid;
ASSERT(POOLPTR(poolptr) != POOLPTR(NULL));
poolid = POOLID(poolptr);
ASSERT(poolid <= pktpools_max);
/* Asertain that a previously registered poolptr is being de-registered */
if (PKTPOOL_REGISTRY_CMP(poolid, POOLPTR(poolptr))) {
PKTPOOL_REGISTRY_CLR(poolid); /* mark as free */
} else {
ASSERT(0);
return BCME_ERROR; /* mismatch in registry */
}
return BCME_OK;
}
/*
* pktpool_init:
* User provides a pktpool_t sturcture and specifies the number of packets to
* be pre-filled into the pool (pplen). The size of all packets in a pool must
* be the same and is specified by plen.
* pktpool_init first attempts to register the pool and fetch a unique poolid.
* If registration fails, it is considered an BCME_ERR, caused by either the
* registry was not pre-created (pktpool_attach) or the registry is full.
* If registration succeeds, then the requested number of packets will be filled
* into the pool as part of initialization. In the event that there is no
* available memory to service the request, then BCME_NOMEM will be returned
* along with the count of how many packets were successfully allocated.
* In dongle builds, prior to memory reclaimation, one should limit the number
* of packets to be allocated during pktpool_init and fill the pool up after
* reclaim stage.
*/
int
pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 type)
{
int i, err = BCME_OK;
int pktplen;
uint8 pktp_id;
ASSERT(pktp != NULL);
ASSERT(osh != NULL);
ASSERT(pplen != NULL);
pktplen = *pplen;
bzero(pktp, sizeof(pktpool_t));
/* assign a unique pktpool id */
if ((pktp_id = (uint8) pktpool_register(pktp)) == PKTPOOL_INVALID_ID) {
return BCME_ERROR;
}
POOLSETID(pktp, pktp_id);
pktp->inited = TRUE;
pktp->istx = istx ? TRUE : FALSE;
pktp->plen = (uint16)plen;
pktp->type = type;
pktp->maxlen = PKTPOOL_LEN_MAX;
pktplen = LIMIT_TO_MAX(pktplen, pktp->maxlen);
for (i = 0; i < pktplen; i++) {
void *p;
p = PKTGET(osh, plen, TRUE);
if (p == NULL) {
/* Not able to allocate all requested pkts
* so just return what was actually allocated
* We can add to the pool later
*/
if (pktp->freelist == NULL) /* pktpool free list is empty */
err = BCME_NOMEM;
goto exit;
}
PKTSETPOOL(osh, p, TRUE, pktp); /* Tag packet with pool ID */
PKTSETFREELIST(p, pktp->freelist); /* insert p at head of free list */
pktp->freelist = p;
pktp->avail++;
#ifdef BCMDBG_POOL
pktp->dbg_q[pktp->dbg_qlen++].p = p;
#endif
}
exit:
pktp->len = pktp->avail;
*pplen = pktp->len;
return err;
}
/*
* pktpool_deinit:
* Prior to freeing a pktpool, all packets must be first freed into the pktpool.
* Upon pktpool_deinit, all packets in the free pool will be freed to the heap.
* An assert is in place to ensure that there are no packets still lingering
* around. Packets freed to a pool after the deinit will cause a memory
* corruption as the pktpool_t structure no longer exists.
*/
int
pktpool_deinit(osl_t *osh, pktpool_t *pktp)
{
uint16 freed = 0;
ASSERT(osh != NULL);
ASSERT(pktp != NULL);
#ifdef BCMDBG_POOL
{
int i;
for (i = 0; i <= pktp->len; i++) {
pktp->dbg_q[i].p = NULL;
}
}
#endif
while (pktp->freelist != NULL) {
void * p = pktp->freelist;
pktp->freelist = PKTFREELIST(p); /* unlink head packet from free list */
PKTSETFREELIST(p, NULL);
PKTSETPOOL(osh, p, FALSE, NULL); /* clear pool ID tag in pkt */
PKTFREE(osh, p, pktp->istx); /* free the packet */
freed++;
ASSERT(freed <= pktp->len);
}
pktp->avail -= freed;
ASSERT(pktp->avail == 0);
pktp->len -= freed;
pktpool_deregister(pktp); /* release previously acquired unique pool id */
POOLSETID(pktp, PKTPOOL_INVALID_ID);
pktp->inited = FALSE;
/* Are there still pending pkts? */
ASSERT(pktp->len == 0);
return 0;
}
int
pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal)
{
void *p;
int err = 0;
int len, psize, maxlen;
ASSERT(pktp->plen != 0);
maxlen = pktp->maxlen;
psize = minimal ? (maxlen >> 2) : maxlen;
for (len = (int)pktp->len; len < psize; len++) {
p = PKTGET(osh, pktp->len, TRUE);
if (p == NULL) {
err = BCME_NOMEM;
break;
}
if (pktpool_add(pktp, p) != BCME_OK) {
PKTFREE(osh, p, FALSE);
err = BCME_ERROR;
break;
}
}
return err;
}
static void *
pktpool_deq(pktpool_t *pktp)
{
void *p;
if (pktp->avail == 0)
return NULL;
ASSERT(pktp->freelist != NULL);
p = pktp->freelist; /* dequeue packet from head of pktpool free list */
pktp->freelist = PKTFREELIST(p); /* free list points to next packet */
PKTSETFREELIST(p, NULL);
pktp->avail--;
return p;
}
static void
pktpool_enq(pktpool_t *pktp, void *p)
{
ASSERT(p != NULL);
PKTSETFREELIST(p, pktp->freelist); /* insert at head of pktpool free list */
pktp->freelist = p; /* free list points to newly inserted packet */
pktp->avail++;
ASSERT(pktp->avail <= pktp->len);
}
/* utility for registering host addr fill function called from pciedev */
int
/* BCMATTACHFN */
(pktpool_hostaddr_fill_register)(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg)
{
ASSERT(cb != NULL);
ASSERT(pktp->cbext.cb == NULL);
pktp->cbext.cb = cb;
pktp->cbext.arg = arg;
return 0;
}
int
pktpool_rxcplid_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg)
{
ASSERT(cb != NULL);
ASSERT(pktp->rxcplidfn.cb == NULL);
pktp->rxcplidfn.cb = cb;
pktp->rxcplidfn.arg = arg;
return 0;
}
/* Callback functions for split rx modes */
/* when evr host posts rxbuffer, invike dma_rxfill from pciedev layer */
void
pktpool_invoke_dmarxfill(pktpool_t *pktp)
{
ASSERT(pktp->dmarxfill.cb);
ASSERT(pktp->dmarxfill.arg);
if (pktp->dmarxfill.cb)
pktp->dmarxfill.cb(pktp, pktp->dmarxfill.arg);
}
int
pkpool_haddr_avail_register_cb(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
{
ASSERT(cb != NULL);
pktp->dmarxfill.cb = cb;
pktp->dmarxfill.arg = arg;
return 0;
}
/* No BCMATTACHFN as it is used in xdc_enable_ep which is not an attach function */
int
pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
{
int i;
ASSERT(cb != NULL);
i = pktp->cbcnt;
if (i == PKTPOOL_CB_MAX)
return BCME_ERROR;
ASSERT(pktp->cbs[i].cb == NULL);
pktp->cbs[i].cb = cb;
pktp->cbs[i].arg = arg;
pktp->cbcnt++;
return 0;
}
int
pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
{
int i;
ASSERT(cb != NULL);
i = pktp->ecbcnt;
if (i == PKTPOOL_CB_MAX)
return BCME_ERROR;
ASSERT(pktp->ecbs[i].cb == NULL);
pktp->ecbs[i].cb = cb;
pktp->ecbs[i].arg = arg;
pktp->ecbcnt++;
return 0;
}
static int
pktpool_empty_notify(pktpool_t *pktp)
{
int i;
pktp->empty = TRUE;
for (i = 0; i < pktp->ecbcnt; i++) {
ASSERT(pktp->ecbs[i].cb != NULL);
pktp->ecbs[i].cb(pktp, pktp->ecbs[i].arg);
}
pktp->empty = FALSE;
return 0;
}
#ifdef BCMDBG_POOL
int
pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg)
{
int i;
ASSERT(cb);
i = pktp->dbg_cbcnt;
if (i == PKTPOOL_CB_MAX)
return BCME_ERROR;
ASSERT(pktp->dbg_cbs[i].cb == NULL);
pktp->dbg_cbs[i].cb = cb;
pktp->dbg_cbs[i].arg = arg;
pktp->dbg_cbcnt++;
return 0;
}
int pktpool_dbg_notify(pktpool_t *pktp);
int
pktpool_dbg_notify(pktpool_t *pktp)
{
int i;
for (i = 0; i < pktp->dbg_cbcnt; i++) {
ASSERT(pktp->dbg_cbs[i].cb);
pktp->dbg_cbs[i].cb(pktp, pktp->dbg_cbs[i].arg);
}
return 0;
}
int
pktpool_dbg_dump(pktpool_t *pktp)
{
int i;
printf("pool len=%d maxlen=%d\n", pktp->dbg_qlen, pktp->maxlen);
for (i = 0; i < pktp->dbg_qlen; i++) {
ASSERT(pktp->dbg_q[i].p);
printf("%d, p: 0x%x dur:%lu us state:%d\n", i,
pktp->dbg_q[i].p, pktp->dbg_q[i].dur/100, PKTPOOLSTATE(pktp->dbg_q[i].p));
}
return 0;
}
int
pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats)
{
int i;
int state;
bzero(stats, sizeof(pktpool_stats_t));
for (i = 0; i < pktp->dbg_qlen; i++) {
ASSERT(pktp->dbg_q[i].p != NULL);
state = PKTPOOLSTATE(pktp->dbg_q[i].p);
switch (state) {
case POOL_TXENQ:
stats->enq++; break;
case POOL_TXDH:
stats->txdh++; break;
case POOL_TXD11:
stats->txd11++; break;
case POOL_RXDH:
stats->rxdh++; break;
case POOL_RXD11:
stats->rxd11++; break;
case POOL_RXFILL:
stats->rxfill++; break;
case POOL_IDLE:
stats->idle++; break;
}
}
return 0;
}
int
pktpool_start_trigger(pktpool_t *pktp, void *p)
{
uint32 cycles, i;
if (!PKTPOOL(OSH_NULL, p))
return 0;
OSL_GETCYCLES(cycles);
for (i = 0; i < pktp->dbg_qlen; i++) {
ASSERT(pktp->dbg_q[i].p != NULL);
if (pktp->dbg_q[i].p == p) {
pktp->dbg_q[i].cycles = cycles;
break;
}
}
return 0;
}
int pktpool_stop_trigger(pktpool_t *pktp, void *p);
int
pktpool_stop_trigger(pktpool_t *pktp, void *p)
{
uint32 cycles, i;
if (!PKTPOOL(OSH_NULL, p))
return 0;
OSL_GETCYCLES(cycles);
for (i = 0; i < pktp->dbg_qlen; i++) {
ASSERT(pktp->dbg_q[i].p != NULL);
if (pktp->dbg_q[i].p == p) {
if (pktp->dbg_q[i].cycles == 0)
break;
if (cycles >= pktp->dbg_q[i].cycles)
pktp->dbg_q[i].dur = cycles - pktp->dbg_q[i].cycles;
else
pktp->dbg_q[i].dur =
(((uint32)-1) - pktp->dbg_q[i].cycles) + cycles + 1;
pktp->dbg_q[i].cycles = 0;
break;
}
}
return 0;
}
#endif /* BCMDBG_POOL */
int
pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp)
{
ASSERT(pktp);
pktp->availcb_excl = NULL;
return 0;
}
int
pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb)
{
int i;
ASSERT(pktp);
ASSERT(pktp->availcb_excl == NULL);
for (i = 0; i < pktp->cbcnt; i++) {
if (cb == pktp->cbs[i].cb) {
pktp->availcb_excl = &pktp->cbs[i];
break;
}
}
if (pktp->availcb_excl == NULL)
return BCME_ERROR;
else
return 0;
}
static int
pktpool_avail_notify(pktpool_t *pktp)
{
int i, k, idx;
int avail;
ASSERT(pktp);
if (pktp->availcb_excl != NULL) {
pktp->availcb_excl->cb(pktp, pktp->availcb_excl->arg);
return 0;
}
k = pktp->cbcnt - 1;
for (i = 0; i < pktp->cbcnt; i++) {
avail = pktp->avail;
if (avail) {
if (pktp->cbtoggle)
idx = i;
else
idx = k--;
ASSERT(pktp->cbs[idx].cb != NULL);
pktp->cbs[idx].cb(pktp, pktp->cbs[idx].arg);
}
}
/* Alternate between filling from head or tail
*/
pktp->cbtoggle ^= 1;
return 0;
}
void *
pktpool_get(pktpool_t *pktp)
{
void *p;
p = pktpool_deq(pktp);
if (p == NULL) {
/* Notify and try to reclaim tx pkts */
if (pktp->ecbcnt)
pktpool_empty_notify(pktp);
p = pktpool_deq(pktp);
if (p == NULL)
return NULL;
}
return p;
}
void
pktpool_free(pktpool_t *pktp, void *p)
{
ASSERT(p != NULL);
#ifdef BCMDBG_POOL
/* pktpool_stop_trigger(pktp, p); */
#endif
pktpool_enq(pktp, p);
if (pktp->emptycb_disable)
return;
if (pktp->cbcnt) {
if (pktp->empty == FALSE)
pktpool_avail_notify(pktp);
}
}
int
pktpool_add(pktpool_t *pktp, void *p)
{
ASSERT(p != NULL);
if (pktp->len == pktp->maxlen)
return BCME_RANGE;
/* pkts in pool have same length */
ASSERT(pktp->plen == PKTLEN(OSH_NULL, p));
PKTSETPOOL(OSH_NULL, p, TRUE, pktp);
pktp->len++;
pktpool_enq(pktp, p);
#ifdef BCMDBG_POOL
pktp->dbg_q[pktp->dbg_qlen++].p = p;
#endif
return 0;
}
/* Force pktpool_setmaxlen () into RAM as it uses a constant
* (PKTPOOL_LEN_MAX) that may be changed post tapeout for ROM-based chips.
*/
int
BCMRAMFN(pktpool_setmaxlen)(pktpool_t *pktp, uint16 maxlen)
{
if (maxlen > PKTPOOL_LEN_MAX)
maxlen = PKTPOOL_LEN_MAX;
/* if pool is already beyond maxlen, then just cap it
* since we currently do not reduce the pool len
* already allocated
*/
pktp->maxlen = (pktp->len > maxlen) ? pktp->len : maxlen;
return pktp->maxlen;
}
void
pktpool_emptycb_disable(pktpool_t *pktp, bool disable)
{
ASSERT(pktp);
pktp->emptycb_disable = disable;
}
bool
pktpool_emptycb_disabled(pktpool_t *pktp)
{
ASSERT(pktp);
return pktp->emptycb_disable;
}

View File

@ -0,0 +1,584 @@
/*
* HND generic pktq operation primitives
*
* $Copyright Open Broadcom Corporation$
*
* $Id: $
*/
#include <typedefs.h>
#include <osl.h>
#include <bcmutils.h>
#include <hnd_pktq.h>
/*
* osl multiple-precedence packet queue
* hi_prec is always >= the number of the highest non-empty precedence
*/
void * BCMFASTPATH
pktq_penq(struct pktq *pq, int prec, void *p)
{
struct pktq_prec *q;
ASSERT(prec >= 0 && prec < pq->num_prec);
ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
ASSERT(!pktq_full(pq));
ASSERT(!pktq_pfull(pq, prec));
q = &pq->q[prec];
if (q->head)
PKTSETLINK(q->tail, p);
else
q->head = p;
q->tail = p;
q->len++;
pq->len++;
if (pq->hi_prec < prec)
pq->hi_prec = (uint8)prec;
return p;
}
void * BCMFASTPATH
pktq_penq_head(struct pktq *pq, int prec, void *p)
{
struct pktq_prec *q;
ASSERT(prec >= 0 && prec < pq->num_prec);
ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */
ASSERT(!pktq_full(pq));
ASSERT(!pktq_pfull(pq, prec));
q = &pq->q[prec];
if (q->head == NULL)
q->tail = p;
PKTSETLINK(p, q->head);
q->head = p;
q->len++;
pq->len++;
if (pq->hi_prec < prec)
pq->hi_prec = (uint8)prec;
return p;
}
/*
* Append spktq 'list' to the tail of pktq 'pq'
*/
void BCMFASTPATH
pktq_append(struct pktq *pq, int prec, struct spktq *list)
{
struct pktq_prec *q;
struct pktq_prec *list_q;
list_q = &list->q[0];
/* empty list check */
if (list_q->head == NULL)
return;
ASSERT(prec >= 0 && prec < pq->num_prec);
ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
ASSERT(!pktq_full(pq));
ASSERT(!pktq_pfull(pq, prec));
q = &pq->q[prec];
if (q->head)
PKTSETLINK(q->tail, list_q->head);
else
q->head = list_q->head;
q->tail = list_q->tail;
q->len += list_q->len;
pq->len += list_q->len;
if (pq->hi_prec < prec)
pq->hi_prec = (uint8)prec;
list_q->head = NULL;
list_q->tail = NULL;
list_q->len = 0;
list->len = 0;
}
/*
* Prepend spktq 'list' to the head of pktq 'pq'
*/
void BCMFASTPATH
pktq_prepend(struct pktq *pq, int prec, struct spktq *list)
{
struct pktq_prec *q;
struct pktq_prec *list_q;
list_q = &list->q[0];
/* empty list check */
if (list_q->head == NULL)
return;
ASSERT(prec >= 0 && prec < pq->num_prec);
ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */
ASSERT(!pktq_full(pq));
ASSERT(!pktq_pfull(pq, prec));
q = &pq->q[prec];
/* set the tail packet of list to point at the former pq head */
PKTSETLINK(list_q->tail, q->head);
/* the new q head is the head of list */
q->head = list_q->head;
/* If the q tail was non-null, then it stays as is.
* If the q tail was null, it is now the tail of list
*/
if (q->tail == NULL) {
q->tail = list_q->tail;
}
q->len += list_q->len;
pq->len += list_q->len;
if (pq->hi_prec < prec)
pq->hi_prec = (uint8)prec;
list_q->head = NULL;
list_q->tail = NULL;
list_q->len = 0;
list->len = 0;
}
void * BCMFASTPATH
pktq_pdeq(struct pktq *pq, int prec)
{
struct pktq_prec *q;
void *p;
ASSERT(prec >= 0 && prec < pq->num_prec);
q = &pq->q[prec];
if ((p = q->head) == NULL)
return NULL;
if ((q->head = PKTLINK(p)) == NULL)
q->tail = NULL;
q->len--;
pq->len--;
PKTSETLINK(p, NULL);
return p;
}
void * BCMFASTPATH
pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p)
{
struct pktq_prec *q;
void *p;
ASSERT(prec >= 0 && prec < pq->num_prec);
q = &pq->q[prec];
if (prev_p == NULL)
return NULL;
if ((p = PKTLINK(prev_p)) == NULL)
return NULL;
q->len--;
pq->len--;
PKTSETLINK(prev_p, PKTLINK(p));
PKTSETLINK(p, NULL);
return p;
}
void * BCMFASTPATH
pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg)
{
struct pktq_prec *q;
void *p, *prev = NULL;
ASSERT(prec >= 0 && prec < pq->num_prec);
q = &pq->q[prec];
p = q->head;
while (p) {
if (fn == NULL || (*fn)(p, arg)) {
break;
} else {
prev = p;
p = PKTLINK(p);
}
}
if (p == NULL)
return NULL;
if (prev == NULL) {
if ((q->head = PKTLINK(p)) == NULL) {
q->tail = NULL;
}
} else {
PKTSETLINK(prev, PKTLINK(p));
if (q->tail == p) {
q->tail = prev;
}
}
q->len--;
pq->len--;
PKTSETLINK(p, NULL);
return p;
}
void * BCMFASTPATH
pktq_pdeq_tail(struct pktq *pq, int prec)
{
struct pktq_prec *q;
void *p, *prev;
ASSERT(prec >= 0 && prec < pq->num_prec);
q = &pq->q[prec];
if ((p = q->head) == NULL)
return NULL;
for (prev = NULL; p != q->tail; p = PKTLINK(p))
prev = p;
if (prev)
PKTSETLINK(prev, NULL);
else
q->head = NULL;
q->tail = prev;
q->len--;
pq->len--;
return p;
}
void
pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg)
{
struct pktq_prec *q;
void *p, *prev = NULL;
q = &pq->q[prec];
p = q->head;
while (p) {
if (fn == NULL || (*fn)(p, arg)) {
bool head = (p == q->head);
if (head)
q->head = PKTLINK(p);
else
PKTSETLINK(prev, PKTLINK(p));
PKTSETLINK(p, NULL);
PKTFREE(osh, p, dir);
q->len--;
pq->len--;
p = (head ? q->head : PKTLINK(prev));
} else {
prev = p;
p = PKTLINK(p);
}
}
if (q->head == NULL) {
ASSERT(q->len == 0);
q->tail = NULL;
}
}
bool BCMFASTPATH
pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
{
struct pktq_prec *q;
void *p;
ASSERT(prec >= 0 && prec < pq->num_prec);
/* Should this just assert pktbuf? */
if (!pktbuf)
return FALSE;
q = &pq->q[prec];
if (q->head == pktbuf) {
if ((q->head = PKTLINK(pktbuf)) == NULL)
q->tail = NULL;
} else {
for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
;
if (p == NULL)
return FALSE;
PKTSETLINK(p, PKTLINK(pktbuf));
if (q->tail == pktbuf)
q->tail = p;
}
q->len--;
pq->len--;
PKTSETLINK(pktbuf, NULL);
return TRUE;
}
void
pktq_init(struct pktq *pq, int num_prec, int max_len)
{
int prec;
ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
/* pq is variable size; only zero out what's requested */
bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
pq->num_prec = (uint16)num_prec;
pq->max = (uint16)max_len;
for (prec = 0; prec < num_prec; prec++)
pq->q[prec].max = pq->max;
}
void
pktq_set_max_plen(struct pktq *pq, int prec, int max_len)
{
ASSERT(prec >= 0 && prec < pq->num_prec);
if (prec < pq->num_prec)
pq->q[prec].max = (uint16)max_len;
}
void * BCMFASTPATH
pktq_deq(struct pktq *pq, int *prec_out)
{
struct pktq_prec *q;
void *p;
int prec;
if (pq->len == 0)
return NULL;
while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
pq->hi_prec--;
q = &pq->q[prec];
if ((p = q->head) == NULL)
return NULL;
if ((q->head = PKTLINK(p)) == NULL)
q->tail = NULL;
q->len--;
pq->len--;
if (prec_out)
*prec_out = prec;
PKTSETLINK(p, NULL);
return p;
}
void * BCMFASTPATH
pktq_deq_tail(struct pktq *pq, int *prec_out)
{
struct pktq_prec *q;
void *p, *prev;
int prec;
if (pq->len == 0)
return NULL;
for (prec = 0; prec < pq->hi_prec; prec++)
if (pq->q[prec].head)
break;
q = &pq->q[prec];
if ((p = q->head) == NULL)
return NULL;
for (prev = NULL; p != q->tail; p = PKTLINK(p))
prev = p;
if (prev)
PKTSETLINK(prev, NULL);
else
q->head = NULL;
q->tail = prev;
q->len--;
pq->len--;
if (prec_out)
*prec_out = prec;
PKTSETLINK(p, NULL);
return p;
}
void *
pktq_peek(struct pktq *pq, int *prec_out)
{
int prec;
if (pq->len == 0)
return NULL;
while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
pq->hi_prec--;
if (prec_out)
*prec_out = prec;
return (pq->q[prec].head);
}
void *
pktq_peek_tail(struct pktq *pq, int *prec_out)
{
int prec;
if (pq->len == 0)
return NULL;
for (prec = 0; prec < pq->hi_prec; prec++)
if (pq->q[prec].head)
break;
if (prec_out)
*prec_out = prec;
return (pq->q[prec].tail);
}
void
pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg)
{
int prec;
/* Optimize flush, if pktq len = 0, just return.
* pktq len of 0 means pktq's prec q's are all empty.
*/
if (pq->len == 0) {
return;
}
for (prec = 0; prec < pq->num_prec; prec++)
pktq_pflush(osh, pq, prec, dir, fn, arg);
if (fn == NULL)
ASSERT(pq->len == 0);
}
/* Return sum of lengths of a specific set of precedences */
int
pktq_mlen(struct pktq *pq, uint prec_bmp)
{
int prec, len;
len = 0;
for (prec = 0; prec <= pq->hi_prec; prec++)
if (prec_bmp & (1 << prec))
len += pq->q[prec].len;
return len;
}
/* Priority peek from a specific set of precedences */
void * BCMFASTPATH
pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out)
{
struct pktq_prec *q;
void *p;
int prec;
if (pq->len == 0)
{
return NULL;
}
while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
pq->hi_prec--;
while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
if (prec-- == 0)
return NULL;
q = &pq->q[prec];
if ((p = q->head) == NULL)
return NULL;
if (prec_out)
*prec_out = prec;
return p;
}
/* Priority dequeue from a specific set of precedences */
void * BCMFASTPATH
pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
{
struct pktq_prec *q;
void *p;
int prec;
if (pq->len == 0)
return NULL;
while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
pq->hi_prec--;
while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0))
if (prec-- == 0)
return NULL;
q = &pq->q[prec];
if ((p = q->head) == NULL)
return NULL;
if ((q->head = PKTLINK(p)) == NULL)
q->tail = NULL;
q->len--;
if (prec_out)
*prec_out = prec;
pq->len--;
PKTSETLINK(p, NULL);
return p;
}

View File

@ -4,16 +4,18 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: hndpmu.c 414368 2013-07-24 15:00:23Z $
* $Id: hndpmu.c 475037 2014-05-02 23:55:49Z $
*/
/*
* Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs.
* However, in the context of this file the baseband ('BB') PLL/FLL is referred to.
*
* Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used.
* They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012)
* pmu2_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop)
* pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports
* fractional frequency generation. pmu2_ does not support fractional frequency generation.
*/
#include <bcm_cfg.h>
@ -36,6 +38,16 @@
*/
#define PMU_NONE(args)
/** contains resource bit positions for a specific chip */
struct rsc_per_chip_s {
uint8 ht_avail;
uint8 macphy_clkavail;
uint8 ht_start;
uint8 otp_pu;
};
typedef struct rsc_per_chip_s rsc_per_chip_t;
/* SDIO Pad drive strength to select value mappings.
* The last strength value in each table must be 0 (the tri-state value).
@ -100,7 +112,7 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = {
/* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */
/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
/** SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = {
{3, 0x3},
{2, 0x2},
@ -108,7 +120,7 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = {
{0, 0x0} };
/*
/**
* SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel
* architecture page, section 'PMU Chip Control 1 Register definition', click link to picture
* BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has
@ -148,7 +160,7 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = {
void
si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
{
chipcregs_t *cc;
chipcregs_t *cc = NULL;
uint origidx, intr_val = 0;
sdiod_drive_str_t *str_tab = NULL;
uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */
@ -161,7 +173,8 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
}
/* Remember original core before switch to chipc */
cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
if (CHIPID(sih->chip) == BCM43362_CHIP_ID)
cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
@ -221,7 +234,36 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
break;
}
if (str_tab != NULL && cc != NULL) {
if (CHIPID(sih->chip) == BCM43362_CHIP_ID) {
if (str_tab != NULL && cc != NULL) {
uint32 cc_data_temp;
int i;
/* Pick the lowest available drive strength equal or greater than the
* requested strength. Drive strength of 0 requests tri-state.
*/
for (i = 0; drivestrength < str_tab[i].strength; i++)
;
if (i > 0 && drivestrength > str_tab[i].strength)
i--;
W_REG(osh, &cc->chipcontrol_addr, PMU_CHIPCTL1);
cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
cc_data_temp &= ~str_mask;
cc_data_temp |= str_tab[i].sel << str_shift;
W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
if (str_ovr_pmuval) { /* enables the selected drive strength */
W_REG(osh, &cc->chipcontrol_addr, str_ovr_pmuctl);
OR_REG(osh, &cc->chipcontrol_data, str_ovr_pmuval);
}
PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n",
drivestrength, str_tab[i].strength));
}
/* Return to original core */
si_restore_core(sih, origidx, intr_val);
}
else if (str_tab != NULL) {
uint32 cc_data_temp;
int i;
@ -234,19 +276,16 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
if (i > 0 && drivestrength > str_tab[i].strength)
i--;
W_REG(osh, &cc->chipcontrol_addr, PMU_CHIPCTL1);
cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
W_REG(osh, PMUREG(sih, chipcontrol_addr), PMU_CHIPCTL1);
cc_data_temp = R_REG(osh, PMUREG(sih, chipcontrol_data));
cc_data_temp &= ~str_mask;
cc_data_temp |= str_tab[i].sel << str_shift;
W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
W_REG(osh, PMUREG(sih, chipcontrol_data), cc_data_temp);
if (str_ovr_pmuval) { /* enables the selected drive strength */
W_REG(osh, &cc->chipcontrol_addr, str_ovr_pmuctl);
OR_REG(osh, &cc->chipcontrol_data, str_ovr_pmuval);
W_REG(osh, PMUREG(sih, chipcontrol_addr), str_ovr_pmuctl);
OR_REG(osh, PMUREG(sih, chipcontrol_data), str_ovr_pmuval);
}
PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n",
drivestrength, str_tab[i].strength));
}
/* Return to original core */
si_restore_core(sih, origidx, intr_val);
} /* si_sdiod_drive_strength_init */

View File

View File

@ -3,18 +3,18 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: aidmp.h 385510 2013-02-15 21:02:07Z $
* $Id: aidmp.h 456346 2014-02-18 16:48:52Z $
*/
#ifndef _AIDMP_H
#define _AIDMP_H
/* Manufacturer Ids */
#define MFGID_ARM 0x43b
#define MFGID_BRCM 0x4bf
#define MFGID_MIPS 0x4a7
/* Component Classes */
#define CC_SIM 0
#define CC_EROM 1
#define CC_CORESIGHT 9
@ -23,7 +23,7 @@
#define CC_GEN 0xe
#define CC_PRIMECELL 0xf
/* Enumeration ROM registers */
#define ER_EROMENTRY 0x000
#define ER_REMAPCONTROL 0xe00
#define ER_REMAPSELECT 0xe04
@ -31,7 +31,7 @@
#define ER_ITCR 0xf00
#define ER_ITIP 0xf04
/* Erom entries */
#define ER_TAG 0xe
#define ER_TAG1 0x6
#define ER_VALID 1
@ -41,7 +41,7 @@
#define ER_END 0xe
#define ER_BAD 0xffffffff
/* EROM CompIdentA */
#define CIA_MFG_MASK 0xfff00000
#define CIA_MFG_SHIFT 20
#define CIA_CID_MASK 0x000fff00
@ -49,7 +49,7 @@
#define CIA_CCL_MASK 0x000000f0
#define CIA_CCL_SHIFT 4
/* EROM CompIdentB */
#define CIB_REV_MASK 0xff000000
#define CIB_REV_SHIFT 24
#define CIB_NSW_MASK 0x00f80000
@ -61,13 +61,13 @@
#define CIB_NMP_MASK 0x000001f0
#define CIB_NMP_SHIFT 4
/* EROM MasterPortDesc */
#define MPD_MUI_MASK 0x0000ff00
#define MPD_MUI_SHIFT 8
#define MPD_MP_MASK 0x000000f0
#define MPD_MP_SHIFT 4
/* EROM AddrDesc */
#define AD_ADDR_MASK 0xfffff000
#define AD_SP_MASK 0x00000f00
#define AD_SP_SHIFT 8
@ -85,137 +85,137 @@
#define AD_SZ_SZD 0x00000030
#define AD_AG32 0x00000008
#define AD_ADDR_ALIGN 0x00000fff
#define AD_SZ_BASE 0x00001000
#define AD_SZ_BASE 0x00001000 /* 4KB */
/* EROM SizeDesc */
#define SD_SZ_MASK 0xfffff000
#define SD_SG32 0x00000008
#define SD_SZ_ALIGN 0x00000fff
#ifndef _LANGUAGE_ASSEMBLY
#if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__)
typedef volatile struct _aidmp {
uint32 oobselina30;
uint32 oobselina74;
uint32 oobselina30; /* 0x000 */
uint32 oobselina74; /* 0x004 */
uint32 PAD[6];
uint32 oobselinb30;
uint32 oobselinb74;
uint32 oobselinb30; /* 0x020 */
uint32 oobselinb74; /* 0x024 */
uint32 PAD[6];
uint32 oobselinc30;
uint32 oobselinc74;
uint32 oobselinc30; /* 0x040 */
uint32 oobselinc74; /* 0x044 */
uint32 PAD[6];
uint32 oobselind30;
uint32 oobselind74;
uint32 oobselind30; /* 0x060 */
uint32 oobselind74; /* 0x064 */
uint32 PAD[38];
uint32 oobselouta30;
uint32 oobselouta74;
uint32 oobselouta30; /* 0x100 */
uint32 oobselouta74; /* 0x104 */
uint32 PAD[6];
uint32 oobseloutb30;
uint32 oobseloutb74;
uint32 oobseloutb30; /* 0x120 */
uint32 oobseloutb74; /* 0x124 */
uint32 PAD[6];
uint32 oobseloutc30;
uint32 oobseloutc74;
uint32 oobseloutc30; /* 0x140 */
uint32 oobseloutc74; /* 0x144 */
uint32 PAD[6];
uint32 oobseloutd30;
uint32 oobseloutd74;
uint32 oobseloutd30; /* 0x160 */
uint32 oobseloutd74; /* 0x164 */
uint32 PAD[38];
uint32 oobsynca;
uint32 oobseloutaen;
uint32 oobsynca; /* 0x200 */
uint32 oobseloutaen; /* 0x204 */
uint32 PAD[6];
uint32 oobsyncb;
uint32 oobseloutben;
uint32 oobsyncb; /* 0x220 */
uint32 oobseloutben; /* 0x224 */
uint32 PAD[6];
uint32 oobsyncc;
uint32 oobseloutcen;
uint32 oobsyncc; /* 0x240 */
uint32 oobseloutcen; /* 0x244 */
uint32 PAD[6];
uint32 oobsyncd;
uint32 oobseloutden;
uint32 oobsyncd; /* 0x260 */
uint32 oobseloutden; /* 0x264 */
uint32 PAD[38];
uint32 oobaextwidth;
uint32 oobainwidth;
uint32 oobaoutwidth;
uint32 oobaextwidth; /* 0x300 */
uint32 oobainwidth; /* 0x304 */
uint32 oobaoutwidth; /* 0x308 */
uint32 PAD[5];
uint32 oobbextwidth;
uint32 oobbinwidth;
uint32 oobboutwidth;
uint32 oobbextwidth; /* 0x320 */
uint32 oobbinwidth; /* 0x324 */
uint32 oobboutwidth; /* 0x328 */
uint32 PAD[5];
uint32 oobcextwidth;
uint32 oobcinwidth;
uint32 oobcoutwidth;
uint32 oobcextwidth; /* 0x340 */
uint32 oobcinwidth; /* 0x344 */
uint32 oobcoutwidth; /* 0x348 */
uint32 PAD[5];
uint32 oobdextwidth;
uint32 oobdinwidth;
uint32 oobdoutwidth;
uint32 oobdextwidth; /* 0x360 */
uint32 oobdinwidth; /* 0x364 */
uint32 oobdoutwidth; /* 0x368 */
uint32 PAD[37];
uint32 ioctrlset;
uint32 ioctrlclear;
uint32 ioctrl;
uint32 ioctrlset; /* 0x400 */
uint32 ioctrlclear; /* 0x404 */
uint32 ioctrl; /* 0x408 */
uint32 PAD[61];
uint32 iostatus;
uint32 iostatus; /* 0x500 */
uint32 PAD[127];
uint32 ioctrlwidth;
uint32 iostatuswidth;
uint32 ioctrlwidth; /* 0x700 */
uint32 iostatuswidth; /* 0x704 */
uint32 PAD[62];
uint32 resetctrl;
uint32 resetstatus;
uint32 resetreadid;
uint32 resetwriteid;
uint32 resetctrl; /* 0x800 */
uint32 resetstatus; /* 0x804 */
uint32 resetreadid; /* 0x808 */
uint32 resetwriteid; /* 0x80c */
uint32 PAD[60];
uint32 errlogctrl;
uint32 errlogdone;
uint32 errlogstatus;
uint32 errlogaddrlo;
uint32 errlogaddrhi;
uint32 errlogid;
uint32 errloguser;
uint32 errlogflags;
uint32 errlogctrl; /* 0x900 */
uint32 errlogdone; /* 0x904 */
uint32 errlogstatus; /* 0x908 */
uint32 errlogaddrlo; /* 0x90c */
uint32 errlogaddrhi; /* 0x910 */
uint32 errlogid; /* 0x914 */
uint32 errloguser; /* 0x918 */
uint32 errlogflags; /* 0x91c */
uint32 PAD[56];
uint32 intstatus;
uint32 intstatus; /* 0xa00 */
uint32 PAD[255];
uint32 config;
uint32 config; /* 0xe00 */
uint32 PAD[63];
uint32 itcr;
uint32 itcr; /* 0xf00 */
uint32 PAD[3];
uint32 itipooba;
uint32 itipoobb;
uint32 itipoobc;
uint32 itipoobd;
uint32 itipooba; /* 0xf10 */
uint32 itipoobb; /* 0xf14 */
uint32 itipoobc; /* 0xf18 */
uint32 itipoobd; /* 0xf1c */
uint32 PAD[4];
uint32 itipoobaout;
uint32 itipoobbout;
uint32 itipoobcout;
uint32 itipoobdout;
uint32 itipoobaout; /* 0xf30 */
uint32 itipoobbout; /* 0xf34 */
uint32 itipoobcout; /* 0xf38 */
uint32 itipoobdout; /* 0xf3c */
uint32 PAD[4];
uint32 itopooba;
uint32 itopoobb;
uint32 itopoobc;
uint32 itopoobd;
uint32 itopooba; /* 0xf50 */
uint32 itopoobb; /* 0xf54 */
uint32 itopoobc; /* 0xf58 */
uint32 itopoobd; /* 0xf5c */
uint32 PAD[4];
uint32 itopoobain;
uint32 itopoobbin;
uint32 itopoobcin;
uint32 itopoobdin;
uint32 itopoobain; /* 0xf70 */
uint32 itopoobbin; /* 0xf74 */
uint32 itopoobcin; /* 0xf78 */
uint32 itopoobdin; /* 0xf7c */
uint32 PAD[4];
uint32 itopreset;
uint32 itopreset; /* 0xf90 */
uint32 PAD[15];
uint32 peripherialid4;
uint32 peripherialid5;
uint32 peripherialid6;
uint32 peripherialid7;
uint32 peripherialid0;
uint32 peripherialid1;
uint32 peripherialid2;
uint32 peripherialid3;
uint32 componentid0;
uint32 componentid1;
uint32 componentid2;
uint32 componentid3;
uint32 peripherialid4; /* 0xfd0 */
uint32 peripherialid5; /* 0xfd4 */
uint32 peripherialid6; /* 0xfd8 */
uint32 peripherialid7; /* 0xfdc */
uint32 peripherialid0; /* 0xfe0 */
uint32 peripherialid1; /* 0xfe4 */
uint32 peripherialid2; /* 0xfe8 */
uint32 peripherialid3; /* 0xfec */
uint32 componentid0; /* 0xff0 */
uint32 componentid1; /* 0xff4 */
uint32 componentid2; /* 0xff8 */
uint32 componentid3; /* 0xffc */
} aidmp_t;
#endif
#endif /* !_LANGUAGE_ASSEMBLY && !__ASSEMBLY__ */
/* Out-of-band Router registers */
#define OOB_BUSCONFIG 0x020
#define OOB_STATUSA 0x100
#define OOB_STATUSB 0x104
@ -247,7 +247,7 @@ typedef volatile struct _aidmp {
#define OOB_ITOPOOBC 0xf38
#define OOB_ITOPOOBD 0xf3c
/* DMP wrapper registers */
#define AI_OOBSELINA30 0x000
#define AI_OOBSELINA74 0x004
#define AI_OOBSELINB30 0x020
@ -339,10 +339,10 @@ typedef volatile struct _aidmp {
#define AI_COMPONENTID2 0xff8
#define AI_COMPONENTID3 0xffc
/* resetctrl */
#define AIRC_RESET 1
/* config */
#define AICFG_OOB 0x00000020
#define AICFG_IOS 0x00000010
#define AICFG_IOC 0x00000008
@ -350,11 +350,11 @@ typedef volatile struct _aidmp {
#define AICFG_ERRL 0x00000002
#define AICFG_RST 0x00000001
/* bit defines for AI_OOBSELOUTB74 reg */
#define OOB_SEL_OUTEN_B_5 15
#define OOB_SEL_OUTEN_B_6 23
/* AI_OOBSEL for A/B/C/D, 0-7 */
#define AI_OOBSEL_MASK 0x1F
#define AI_OOBSEL_0_SHIFT 0
#define AI_OOBSEL_1_SHIFT 8
@ -365,4 +365,4 @@ typedef volatile struct _aidmp {
#define AI_OOBSEL_6_SHIFT 16
#define AI_OOBSEL_7_SHIFT 24
#endif
#endif /* _AIDMP_H */

View File

@ -8,4 +8,4 @@
#ifndef _bcm_cfg_h_
#define _bcm_cfg_h_
#endif
#endif /* _bcm_cfg_h_ */

View File

@ -37,7 +37,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id$
* $Id: bcm_mpool_pub.h 407097 2013-06-11 18:43:16Z $
*/
#ifndef _BCM_MPOOL_PUB_H
@ -162,7 +162,7 @@ int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr,
int nobj,
void *memstart,
unsigned int memsize,
char poolname[BCM_MP_NAMELEN],
const char poolname[BCM_MP_NAMELEN],
bcm_mp_pool_h *newp);
@ -201,7 +201,7 @@ int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
*
*/
int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz,
char poolname[BCM_MP_NAMELEN],
const char poolname[BCM_MP_NAMELEN],
bcm_mp_pool_h *newp);

View File

@ -13,34 +13,34 @@
#include <proto/ethernet.h>
typedef struct cdc_ioctl {
uint32 cmd;
uint32 len;
uint32 flags;
uint32 status;
uint32 cmd; /* ioctl command value */
uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */
uint32 flags; /* flag defns given below */
uint32 status; /* status code returned from the device */
} cdc_ioctl_t;
/* Max valid buffer size that can be sent to the dongle */
#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN
#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF
/* len field is divided into input and output buffer lengths */
#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */
/* excluding IOCTL header */
#define CDCL_IOC_OUTLEN_SHIFT 0
#define CDCL_IOC_INLEN_MASK 0xFFFF0000
#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */
#define CDCL_IOC_INLEN_SHIFT 16
#define CDCF_IOC_ERROR 0x01
#define CDCF_IOC_SET 0x02
#define CDCF_IOC_OVL_IDX_MASK 0x3c
#define CDCF_IOC_OVL_RSV 0x40
#define CDCF_IOC_OVL 0x80
#define CDCF_IOC_ACTION_MASK 0xfe
#define CDCF_IOC_ACTION_SHIFT 1
#define CDCF_IOC_IF_MASK 0xF000
/* CDC flag definitions */
#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */
#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */
#define CDCF_IOC_OVL_IDX_MASK 0x3c /* overlay region index mask */
#define CDCF_IOC_OVL_RSV 0x40 /* 1=reserve this overlay region */
#define CDCF_IOC_OVL 0x80 /* 1=this ioctl corresponds to an overlay */
#define CDCF_IOC_ACTION_MASK 0xfe /* SET/GET, OVL_IDX, OVL_RSV, OVL mask */
#define CDCF_IOC_ACTION_SHIFT 1 /* SET/GET, OVL_IDX, OVL_RSV, OVL shift */
#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */
#define CDCF_IOC_IF_SHIFT 12
#define CDCF_IOC_ID_MASK 0xFFFF0000
#define CDCF_IOC_ID_SHIFT 16
#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */
#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */
#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
@ -50,41 +50,47 @@ typedef struct cdc_ioctl {
#define CDC_SET_IF_IDX(hdr, idx) \
((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT)))
/*
* BDC header
*
* The BDC header is used on data packets to convey priority across USB.
*/
struct bdc_header {
uint8 flags;
uint8 priority;
uint8 flags; /* Flags */
uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 USB flow control info */
uint8 flags2;
uint8 dataOffset;
uint8 dataOffset; /* Offset from end of BDC header to packet data, in
* 4-byte words. Leaves room for optional headers.
*/
};
#define BDC_HEADER_LEN 4
/* flags field bitmap */
#define BDC_FLAG_80211_PKT 0x01 /* Packet is in 802.11 format (dongle -> host) */
#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */
#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums: host->device */
#define BDC_FLAG_EVENT_MSG 0x08 /* Payload contains an event msg: device->host */
#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
#define BDC_FLAG_80211_PKT 0x01
#define BDC_FLAG_SUM_GOOD 0x04
#define BDC_FLAG_SUM_NEEDED 0x08
#define BDC_FLAG_EVENT_MSG 0x08
#define BDC_FLAG_VER_MASK 0xf0
#define BDC_FLAG_VER_SHIFT 4
/* priority field bitmap */
#define BDC_PRIORITY_MASK 0x07
#define BDC_PRIORITY_FC_MASK 0xf0
#define BDC_PRIORITY_FC_SHIFT 4
#define BDC_PRIORITY_FC_MASK 0xf0 /* flow control info mask */
#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */
#define BDC_FLAG2_IF_MASK 0x0f
/* flags2 field bitmap */
#define BDC_FLAG2_IF_MASK 0x0f /* interface index (host <-> dongle) */
#define BDC_FLAG2_IF_SHIFT 0
#define BDC_FLAG2_FC_FLAG 0x10
#define BDC_PROTO_VER_1 1
#define BDC_PROTO_VER 2
#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */
/* FLOW CONTROL info only */
/* version numbers */
#define BDC_PROTO_VER_1 1 /* Old Protocol version */
#define BDC_PROTO_VER 2 /* Protocol version */
/* flags2.if field access macros */
#define BDC_GET_IF_IDX(hdr) \
((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
#define BDC_SET_IF_IDX(hdr, idx) \
@ -105,4 +111,4 @@ struct bdc_header {
((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \
(((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT)))
#endif
#endif /* _bcmcdc_h_ */

View File

@ -3,26 +3,45 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: bcmdefs.h 416231 2013-08-02 07:38:34Z $
* $Id: bcmdefs.h 474209 2014-04-30 12:16:47Z $
*/
#ifndef _bcmdefs_h_
#define _bcmdefs_h_
/*
* One doesn't need to include this file explicitly, gets included automatically if
* typedefs.h is included.
*/
/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function
* arguments or local variables.
*/
#define BCM_REFERENCE(data) ((void)(data))
/* Allow for suppressing unused variable warnings. */
#ifdef __GNUC__
#define UNUSED_VAR __attribute__ ((unused))
#else
#define UNUSED_VAR
#endif
/* Compile-time assert can be used in place of ASSERT if the expression evaluates
* to a constant at compile time.
*/
#define STATIC_ASSERT(expr) { \
\
typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e; \
\
typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1]; \
/* Make sure the expression is constant. */ \
typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e UNUSED_VAR; \
/* Make sure the expression is true. */ \
typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1] UNUSED_VAR; \
}
/* Reclaiming text and data :
* The following macros specify special linker sections that can be reclaimed
* after a system is considered 'up'.
* BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN,
* as in most cases, the attach function calls the detach function to clean up on error).
*/
#define bcmreclaimed 0
#define _data _data
@ -36,11 +55,8 @@
#define BCMNMIATTACHDATA(_data) _data
#define CONST const
#undef BCM47XX_CA9
#ifdef __ARM_ARCH_7A__
#define BCM47XX_CA9
#endif
#ifndef BCMFASTPATH
#if defined(BCM47XX_CA9)
#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath")))
@ -49,38 +65,36 @@
#define BCMFASTPATH
#define BCMFASTPATH_HOST
#endif
#endif
#endif /* BCMFASTPATH */
/* Use the BCMRAMFN() macro to tag functions in source that must be included in RAM (excluded from
* ROM). This should eliminate the need to manually specify these functions in the ROM config file.
* It should only be used in special cases where the function must be in RAM for *all* ROM-based
* chips.
*/
#define BCMRAMFN(_fn) _fn
#define _data _data
#define BCMROMDAT_NAME(_data) _data
#define _fn _fn
#define _fn _fn
#define STATIC static
#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data)
#define BCMROMDAT_SIZEOF(data) sizeof(data)
#define BCMROMDAT_APATCH(data)
#define BCMROMDAT_SPATCH(data)
#define SI_BUS 0
#define PCI_BUS 1
#define PCMCIA_BUS 2
#define SDIO_BUS 3
#define JTAG_BUS 4
#define USB_BUS 5
#define SPI_BUS 6
#define RPC_BUS 7
/* Bus types */
#define SI_BUS 0 /* SOC Interconnect */
#define PCI_BUS 1 /* PCI target */
#define PCMCIA_BUS 2 /* PCMCIA target */
#define SDIO_BUS 3 /* SDIO target */
#define JTAG_BUS 4 /* JTAG */
#define USB_BUS 5 /* USB (does not support R/W REG) */
#define SPI_BUS 6 /* gSPI target */
#define RPC_BUS 7 /* RPC target */
/* Allows size optimization for single-bus image */
#ifdef BCMBUSTYPE
#define BUSTYPE(bus) (BCMBUSTYPE)
#else
#define BUSTYPE(bus) (bus)
#endif
/* Allows size optimization for single-backplane image */
#ifdef BCMCHIPTYPE
#define CHIPTYPE(bus) (BCMCHIPTYPE)
#else
@ -88,7 +102,7 @@
#endif
/* Allows size optimization for SPROM support */
#if defined(BCMSPROMBUS)
#define SPROMBUS (BCMSPROMBUS)
#elif defined(SI_PCMCIA_SROM)
@ -97,7 +111,7 @@
#define SPROMBUS (PCI_BUS)
#endif
/* Allows size optimization for single-chip image */
#ifdef BCMCHIPID
#define CHIPID(chip) (BCMCHIPID)
#else
@ -110,34 +124,41 @@
#define CHIPREV(rev) (rev)
#endif
/* Defines for DMA Address Width - Shared between OSL and HNDDMA */
#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */
#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */
#define DMADDR_MASK_26 0xFC000000 /* Address maks for 26-bits */
#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */
#define DMADDR_MASK_32 0x0
#define DMADDR_MASK_30 0xc0000000
#define DMADDR_MASK_0 0xffffffff
#define DMADDRWIDTH_26 26 /* 26-bit addressing capability */
#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */
#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */
#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */
#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */
#define DMADDRWIDTH_30 30
#define DMADDRWIDTH_32 32
#define DMADDRWIDTH_63 63
#define DMADDRWIDTH_64 64
#ifdef BCMDMA64OSL
typedef struct {
uint32 loaddr;
uint32 hiaddr;
} dma64addr_t;
typedef dma64addr_t dmaaddr_t;
#define PHYSADDRHI(_pa) ((_pa).hiaddr)
#define PHYSADDRHISET(_pa, _val) \
#define PHYSADDR64HI(_pa) ((_pa).hiaddr)
#define PHYSADDR64HISET(_pa, _val) \
do { \
(_pa).hiaddr = (_val); \
} while (0)
#define PHYSADDRLO(_pa) ((_pa).loaddr)
#define PHYSADDRLOSET(_pa, _val) \
#define PHYSADDR64LO(_pa) ((_pa).loaddr)
#define PHYSADDR64LOSET(_pa, _val) \
do { \
(_pa).loaddr = (_val); \
} while (0)
#ifdef BCMDMA64OSL
typedef dma64addr_t dmaaddr_t;
#define PHYSADDRHI(_pa) PHYSADDR64HI(_pa)
#define PHYSADDRHISET(_pa, _val) PHYSADDR64HISET(_pa, _val)
#define PHYSADDRLO(_pa) PHYSADDR64LO(_pa)
#define PHYSADDRLOSET(_pa, _val) PHYSADDR64LOSET(_pa, _val)
#else
typedef unsigned long dmaaddr_t;
#define PHYSADDRHI(_pa) (0)
@ -147,44 +168,55 @@ typedef unsigned long dmaaddr_t;
do { \
(_pa) = (_val); \
} while (0)
#endif
#endif /* BCMDMA64OSL */
#define PHYSADDRISZERO(_pa) (PHYSADDRLO(_pa) == 0 && PHYSADDRHI(_pa) == 0)
/* One physical DMA segment */
typedef struct {
dmaaddr_t addr;
uint32 length;
} hnddma_seg_t;
#define MAX_DMA_SEGS 4
#define MAX_DMA_SEGS 8
typedef struct {
void *oshdmah;
uint origsize;
void *oshdmah; /* Opaque handle for OSL to store its information */
uint origsize; /* Size of the virtual packet */
uint nsegs;
hnddma_seg_t segs[MAX_DMA_SEGS];
} hnddma_seg_map_t;
/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
* By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL.
* There is a compile time check in wlc.c which ensure that this value is at least as big
* as TXOFF. This value is used in dma_rxfill (hnddma.c).
*/
#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY)
/* add 40 bytes to allow for extra RPC header and info */
#define BCMEXTRAHDROOM 260
#else
#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
#if defined(BCM47XX_CA9)
#define BCMEXTRAHDROOM 224
#else
#define BCMEXTRAHDROOM 204
#endif
#endif
#endif /* linux && BCM47XX_CA9 */
#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
/* Packet alignment for most efficient SDIO (can change based on platform) */
#ifndef SDALIGN
#define SDALIGN 32
#endif
/* Headroom required for dongle-to-host communication. Packets allocated
* locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should
* leave this much room in front for low-level message headers which may
* be needed to get across the dongle bus to the host. (These messages
* don't go over the network, so room for the full WL header above would
* be a waste.).
*/
#define BCMDONGLEHDRSZ 12
#define BCMDONGLEPADSZ 16
@ -200,7 +232,16 @@ typedef struct {
#define BCMASSERT_SUPPORT
#endif
/* Macros for doing definition and get/set of bitfields
* Usage example, e.g. a three-bit field (bits 4-6):
* #define <NAME>_M BITFIELD_MASK(3)
* #define <NAME>_S 4
* ...
* regval = R_REG(osh, &regs->regfoo);
* field = GFIELD(regval, <NAME>);
* regval = SFIELD(regval, <NAME>, 1);
* W_REG(osh, &regs->regfoo, regval);
*/
#define BITFIELD_MASK(width) \
(((unsigned)1 << (width)) - 1)
#define GFIELD(val, field) \
@ -209,28 +250,71 @@ typedef struct {
(((val) & (~(field ## _M << field ## _S))) | \
((unsigned)(bits) << field ## _S))
/* define BCMSMALL to remove misc features for memory-constrained environments */
#ifdef BCMSMALL
#undef BCMSPACE
#define bcmspace FALSE
#define bcmspace FALSE /* if (bcmspace) code is discarded */
#else
#define BCMSPACE
#define bcmspace TRUE
#define bcmspace TRUE /* if (bcmspace) code is retained */
#endif
/* Max. nvram variable table size */
#ifndef MAXSZ_NVRAM_VARS
#define MAXSZ_NVRAM_VARS 4096
#endif
#define MAXSZ_NVRAM_VARS 4096
/* WL_ENAB_RUNTIME_CHECK may be set based upon the #define below (for ROM builds). It may also
* be defined via makefiles (e.g. ROM auto abandon unoptimized compiles).
*/
#ifdef BCMLFRAG /* BCMLFRAG support enab macros */
extern bool _bcmlfrag;
#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
#define BCMLFRAG_ENAB() (_bcmlfrag)
#elif defined(BCMLFRAG_DISABLED)
#define BCMLFRAG_ENAB() (0)
#else
#define BCMLFRAG_ENAB() (1)
#endif
#else
#define BCMLFRAG_ENAB() (0)
#endif /* BCMLFRAG_ENAB */
#ifdef BCMSPLITRX /* BCMLFRAG support enab macros */
extern bool _bcmsplitrx;
#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
#define BCMSPLITRX_ENAB() (_bcmsplitrx)
#elif defined(BCMSPLITRX_DISABLED)
#define BCMSPLITRX_ENAB() (0)
#else
#define BCMSPLITRX_ENAB() (1)
#endif
#else
#define BCMSPLITRX_ENAB() (0)
#endif /* BCMSPLITRX */
#ifdef BCM_SPLITBUF
extern bool _bcmsplitbuf;
#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
#define BCM_SPLITBUF_ENAB() (_bcmsplitbuf)
#elif defined(BCM_SPLITBUF_DISABLED)
#define BCM_SPLITBUF_ENAB() (0)
#else
#define BCM_SPLITBUF_ENAB() (1)
#endif
#else
#define BCM_SPLITBUF_ENAB() (0)
#endif /* BCM_SPLITBUF */
/* Max size for reclaimable NVRAM array */
#ifdef DL_NVRAM
#define NVRAM_ARRAY_MAXSIZE DL_NVRAM
#else
#define NVRAM_ARRAY_MAXSIZE MAXSZ_NVRAM_VARS
#endif
#endif /* DL_NVRAM */
#ifdef BCMUSBDEV_ENABLED
extern uint32 gFWID;
#endif
#endif
#endif /* _bcmdefs_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: bcmendian.h 241182 2011-02-17 21:50:03Z $
* $Id: bcmendian.h 402715 2013-05-16 18:50:09Z $
*
* This file by default provides proper behavior on little-endian architectures.
* On big-endian architectures, IL_BIGENDIAN should be defined.
@ -14,24 +14,44 @@
#include <typedefs.h>
/* Reverse the bytes in a 16-bit value */
#define BCMSWAP16(val) \
((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
(((uint16)(val) & (uint16)0xff00U) >> 8)))
/* Reverse the bytes in a 32-bit value */
#define BCMSWAP32(val) \
((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
(((uint32)(val) & (uint32)0x0000ff00U) << 8) | \
(((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \
(((uint32)(val) & (uint32)0xff000000U) >> 24)))
/* Reverse the two 16-bit halves of a 32-bit value */
#define BCMSWAP32BY16(val) \
((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
(((uint32)(val) & (uint32)0xffff0000U) >> 16)))
/* Reverse the bytes in a 64-bit value */
#define BCMSWAP64(val) \
((uint64)((((uint64)(val) & 0x00000000000000ffULL) << 56) | \
(((uint64)(val) & 0x000000000000ff00ULL) << 40) | \
(((uint64)(val) & 0x0000000000ff0000ULL) << 24) | \
(((uint64)(val) & 0x00000000ff000000ULL) << 8) | \
(((uint64)(val) & 0x000000ff00000000ULL) >> 8) | \
(((uint64)(val) & 0x0000ff0000000000ULL) >> 24) | \
(((uint64)(val) & 0x00ff000000000000ULL) >> 40) | \
(((uint64)(val) & 0xff00000000000000ULL) >> 56)))
/* Reverse the two 32-bit halves of a 64-bit value */
#define BCMSWAP64BY32(val) \
((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \
(((uint64)(val) & 0xffffffff00000000ULL) >> 32)))
/* Byte swapping macros
* Host <=> Network (Big Endian) for 16- and 32-bit values
* Host <=> Little-Endian for 16- and 32-bit values
*/
#ifndef hton16
#define HTON16(i) BCMSWAP16(i)
#define hton16(i) bcmswap16(i)
@ -49,12 +69,14 @@
#define htol16(i) (i)
#define HTOL32(i) (i)
#define htol32(i) (i)
#endif
#define HTOL64(i) (i)
#define htol64(i) (i)
#endif /* hton16 */
#define ltoh16_buf(buf, i)
#define htol16_buf(buf, i)
/* Unaligned loads and stores in host byte order */
#define load32_ua(a) ltoh32_ua(a)
#define store32_ua(a, v) htol32_ua_store(v, a)
#define load16_ua(a) ltoh16_ua(a)
@ -79,7 +101,9 @@
#ifdef __GNUC__
/* GNU macro versions avoid referencing the argument multiple times, while also
* avoiding the -fno-inline used in ROM builds.
*/
#define bcmswap16(val) ({ \
uint16 _val = (val); \
@ -91,6 +115,11 @@
BCMSWAP32(_val); \
})
#define bcmswap64(val) ({ \
uint64 _val = (val); \
BCMSWAP64(_val); \
})
#define bcmswap32by16(val) ({ \
uint32 _val = (val); \
BCMSWAP32BY16(_val); \
@ -157,9 +186,9 @@
_NTOH32_UA(_bytes); \
})
#else
#else /* !__GNUC__ */
/* Inline versions avoid referencing the argument multiple times */
static INLINE uint16
bcmswap16(uint16 val)
{
@ -172,15 +201,21 @@ bcmswap32(uint32 val)
return BCMSWAP32(val);
}
static INLINE uint64
bcmswap64(uint64 val)
{
return BCMSWAP64(val);
}
static INLINE uint32
bcmswap32by16(uint32 val)
{
return BCMSWAP32BY16(val);
}
/* Reverse pairs of bytes in a buffer (not for high-performance use) */
/* buf - start of buffer of shorts to swap */
/* len - byte length of buffer */
static INLINE void
bcmswap16_buf(uint16 *buf, uint len)
{
@ -192,7 +227,9 @@ bcmswap16_buf(uint16 *buf, uint len)
}
}
/*
* Store 16-bit value to unaligned little-endian byte array.
*/
static INLINE void
htol16_ua_store(uint16 val, uint8 *bytes)
{
@ -200,7 +237,9 @@ htol16_ua_store(uint16 val, uint8 *bytes)
bytes[1] = val >> 8;
}
/*
* Store 32-bit value to unaligned little-endian byte array.
*/
static INLINE void
htol32_ua_store(uint32 val, uint8 *bytes)
{
@ -210,7 +249,9 @@ htol32_ua_store(uint32 val, uint8 *bytes)
bytes[3] = val >> 24;
}
/*
* Store 16-bit value to unaligned network-(big-)endian byte array.
*/
static INLINE void
hton16_ua_store(uint16 val, uint8 *bytes)
{
@ -218,7 +259,9 @@ hton16_ua_store(uint16 val, uint8 *bytes)
bytes[1] = val & 0xff;
}
/*
* Store 32-bit value to unaligned network-(big-)endian byte array.
*/
static INLINE void
hton32_ua_store(uint32 val, uint8 *bytes)
{
@ -228,33 +271,41 @@ hton32_ua_store(uint32 val, uint8 *bytes)
bytes[3] = val & 0xff;
}
/*
* Load 16-bit value from unaligned little-endian byte array.
*/
static INLINE uint16
ltoh16_ua(const void *bytes)
{
return _LTOH16_UA((const uint8 *)bytes);
}
/*
* Load 32-bit value from unaligned little-endian byte array.
*/
static INLINE uint32
ltoh32_ua(const void *bytes)
{
return _LTOH32_UA((const uint8 *)bytes);
}
/*
* Load 16-bit value from unaligned big-(network-)endian byte array.
*/
static INLINE uint16
ntoh16_ua(const void *bytes)
{
return _NTOH16_UA((const uint8 *)bytes);
}
/*
* Load 32-bit value from unaligned big-(network-)endian byte array.
*/
static INLINE uint32
ntoh32_ua(const void *bytes)
{
return _NTOH32_UA((const uint8 *)bytes);
}
#endif
#endif
#endif /* !__GNUC__ */
#endif /* !_BCMENDIAN_H_ */

View File

@ -0,0 +1,728 @@
/*
* MSGBUF network driver ioctl/indication encoding
* Broadcom 802.11abg Networking Device Driver
*
* Definitions subject to change without notice.
*
* $Copyright Open Broadcom Corporation$
*
* $Id: bcmmsgbuf.h 490808 2014-07-12 00:33:13Z $
*/
#ifndef _bcmmsgbuf_h_
#define _bcmmsgbuf_h_
#include <proto/ethernet.h>
#include <wlioctl.h>
#include <bcmpcie.h>
#define MSGBUF_MAX_MSG_SIZE ETHER_MAX_LEN
#define D2H_EPOCH_MODULO 253 /* sequence number wrap */
#define D2H_EPOCH_INIT_VAL (D2H_EPOCH_MODULO + 1)
#define H2DRING_TXPOST_ITEMSIZE 48
#define H2DRING_RXPOST_ITEMSIZE 32
#define H2DRING_CTRL_SUB_ITEMSIZE 40
#define D2HRING_TXCMPLT_ITEMSIZE 16
#define D2HRING_RXCMPLT_ITEMSIZE 32
#define D2HRING_CTRL_CMPLT_ITEMSIZE 24
#define H2DRING_TXPOST_MAX_ITEM 512
#define H2DRING_RXPOST_MAX_ITEM 256
#define H2DRING_CTRL_SUB_MAX_ITEM 20
#define D2HRING_TXCMPLT_MAX_ITEM 1024
#define D2HRING_RXCMPLT_MAX_ITEM 256
#define D2HRING_CTRL_CMPLT_MAX_ITEM 20
enum {
DNGL_TO_HOST_MSGBUF,
HOST_TO_DNGL_MSGBUF
};
enum {
HOST_TO_DNGL_TXP_DATA,
HOST_TO_DNGL_RXP_DATA,
HOST_TO_DNGL_CTRL,
DNGL_TO_HOST_DATA,
DNGL_TO_HOST_CTRL
};
#define MESSAGE_PAYLOAD(a) (a & MSG_TYPE_INTERNAL_USE_START) ? TRUE : FALSE
#ifdef PCIE_API_REV1
#define BCMMSGBUF_DUMMY_REF(a, b) do {BCM_REFERENCE((a));BCM_REFERENCE((b));} while (0)
#define BCMMSGBUF_API_IFIDX(a) 0
#define BCMMSGBUF_API_SEQNUM(a) 0
#define BCMMSGBUF_IOCTL_XTID(a) 0
#define BCMMSGBUF_IOCTL_PKTID(a) ((a)->cmd_id)
#define BCMMSGBUF_SET_API_IFIDX(a, b) BCMMSGBUF_DUMMY_REF(a, b)
#define BCMMSGBUF_SET_API_SEQNUM(a, b) BCMMSGBUF_DUMMY_REF(a, b)
#define BCMMSGBUF_IOCTL_SET_PKTID(a, b) (BCMMSGBUF_IOCTL_PKTID(a) = (b))
#define BCMMSGBUF_IOCTL_SET_XTID(a, b) BCMMSGBUF_DUMMY_REF(a, b)
#else /* PCIE_API_REV1 */
#define BCMMSGBUF_API_IFIDX(a) ((a)->if_id)
#define BCMMSGBUF_IOCTL_PKTID(a) ((a)->pkt_id)
#define BCMMSGBUF_API_SEQNUM(a) ((a)->u.seq.seq_no)
#define BCMMSGBUF_IOCTL_XTID(a) ((a)->xt_id)
#define BCMMSGBUF_SET_API_IFIDX(a, b) (BCMMSGBUF_API_IFIDX((a)) = (b))
#define BCMMSGBUF_SET_API_SEQNUM(a, b) (BCMMSGBUF_API_SEQNUM((a)) = (b))
#define BCMMSGBUF_IOCTL_SET_PKTID(a, b) (BCMMSGBUF_IOCTL_PKTID((a)) = (b))
#define BCMMSGBUF_IOCTL_SET_XTID(a, b) (BCMMSGBUF_IOCTL_XTID((a)) = (b))
#endif /* PCIE_API_REV1 */
/* utility data structures */
union addr64 {
struct {
uint32 low;
uint32 high;
};
struct {
uint32 low_addr;
uint32 high_addr;
};
uint64 u64;
} DECLSPEC_ALIGN(8);
typedef union addr64 addr64_t;
/* IOCTL req Hdr */
/* cmn Msg Hdr */
typedef struct cmn_msg_hdr {
/* message type */
uint8 msg_type;
/* interface index this is valid for */
uint8 if_id;
/* flags */
uint8 flags;
/* sequence number */
uint8 epoch;
/* packet Identifier for the associated host buffer */
uint32 request_id;
} cmn_msg_hdr_t;
/* message type */
typedef enum bcmpcie_msgtype {
MSG_TYPE_GEN_STATUS = 0x1,
MSG_TYPE_RING_STATUS = 0x2,
MSG_TYPE_FLOW_RING_CREATE = 0x3,
MSG_TYPE_FLOW_RING_CREATE_CMPLT = 0x4,
MSG_TYPE_FLOW_RING_DELETE = 0x5,
MSG_TYPE_FLOW_RING_DELETE_CMPLT = 0x6,
MSG_TYPE_FLOW_RING_FLUSH = 0x7,
MSG_TYPE_FLOW_RING_FLUSH_CMPLT = 0x8,
MSG_TYPE_IOCTLPTR_REQ = 0x9,
MSG_TYPE_IOCTLPTR_REQ_ACK = 0xA,
MSG_TYPE_IOCTLRESP_BUF_POST = 0xB,
MSG_TYPE_IOCTL_CMPLT = 0xC,
MSG_TYPE_EVENT_BUF_POST = 0xD,
MSG_TYPE_WL_EVENT = 0xE,
MSG_TYPE_TX_POST = 0xF,
MSG_TYPE_TX_STATUS = 0x10,
MSG_TYPE_RXBUF_POST = 0x11,
MSG_TYPE_RX_CMPLT = 0x12,
MSG_TYPE_LPBK_DMAXFER = 0x13,
MSG_TYPE_LPBK_DMAXFER_CMPLT = 0x14,
MSG_TYPE_API_MAX_RSVD = 0x3F
} bcmpcie_msg_type_t;
typedef enum bcmpcie_msgtype_int {
MSG_TYPE_INTERNAL_USE_START = 0x40,
MSG_TYPE_EVENT_PYLD = 0x41,
MSG_TYPE_IOCT_PYLD = 0x42,
MSG_TYPE_RX_PYLD = 0x43,
MSG_TYPE_HOST_FETCH = 0x44,
MSG_TYPE_LPBK_DMAXFER_PYLD = 0x45,
MSG_TYPE_TXMETADATA_PYLD = 0x46,
MSG_TYPE_HOSTDMA_PTRS = 0x47
} bcmpcie_msgtype_int_t;
typedef enum bcmpcie_msgtype_u {
MSG_TYPE_TX_BATCH_POST = 0x80,
MSG_TYPE_IOCTL_REQ = 0x81,
MSG_TYPE_HOST_EVNT = 0x82,
MSG_TYPE_LOOPBACK = 0x83
} bcmpcie_msgtype_u_t;
/* if_id */
#define BCMPCIE_CMNHDR_IFIDX_PHYINTF_SHFT 5
#define BCMPCIE_CMNHDR_IFIDX_PHYINTF_MAX 0x7
#define BCMPCIE_CMNHDR_IFIDX_PHYINTF_MASK \
(BCMPCIE_CMNHDR_IFIDX_PHYINTF_MAX << BCMPCIE_CMNHDR_IFIDX_PHYINTF_SHFT)
#define BCMPCIE_CMNHDR_IFIDX_VIRTINTF_SHFT 0
#define BCMPCIE_CMNHDR_IFIDX_VIRTINTF_MAX 0x1F
#define BCMPCIE_CMNHDR_IFIDX_VIRTINTF_MASK \
(BCMPCIE_CMNHDR_IFIDX_PHYINTF_MAX << BCMPCIE_CMNHDR_IFIDX_PHYINTF_SHFT)
/* flags */
#define BCMPCIE_CMNHDR_FLAGS_DMA_R_IDX 0x1
#define BCMPCIE_CMNHDR_FLAGS_DMA_R_IDX_INTR 0x2
#define BCMPCIE_CMNHDR_FLAGS_PHASE_BIT 0x80
/* IOCTL request message */
typedef struct ioctl_req_msg {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* ioctl command type */
uint32 cmd;
/* ioctl transaction ID, to pair with a ioctl response */
uint16 trans_id;
/* input arguments buffer len */
uint16 input_buf_len;
/* expected output len */
uint16 output_buf_len;
/* to aling the host address on 8 byte boundary */
uint16 rsvd[3];
/* always aling on 8 byte boundary */
addr64_t host_input_buf_addr;
/* rsvd */
uint32 rsvd1[2];
} ioctl_req_msg_t;
/* buffer post messages for device to use to return IOCTL responses, Events */
typedef struct ioctl_resp_evt_buf_post_msg {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* length of the host buffer supplied */
uint16 host_buf_len;
/* to aling the host address on 8 byte boundary */
uint16 reserved[3];
/* always aling on 8 byte boundary */
addr64_t host_buf_addr;
uint32 rsvd[4];
} ioctl_resp_evt_buf_post_msg_t;
typedef struct pcie_dma_xfer_params {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* always aling on 8 byte boundary */
addr64_t host_input_buf_addr;
/* always aling on 8 byte boundary */
addr64_t host_ouput_buf_addr;
/* length of transfer */
uint32 xfer_len;
/* delay before doing the src txfer */
uint32 srcdelay;
/* delay before doing the dest txfer */
uint32 destdelay;
uint32 rsvd;
} pcie_dma_xfer_params_t;
/* Complete msgbuf hdr for flow ring update from host to dongle */
typedef struct tx_flowring_create_request {
cmn_msg_hdr_t msg;
uint8 da[ETHER_ADDR_LEN];
uint8 sa[ETHER_ADDR_LEN];
uint8 tid;
uint8 if_flags;
uint16 flow_ring_id;
uint8 tc;
uint8 priority;
uint16 int_vector;
uint16 max_items;
uint16 len_item;
addr64_t flow_ring_ptr;
} tx_flowring_create_request_t;
typedef struct tx_flowring_delete_request {
cmn_msg_hdr_t msg;
uint16 flow_ring_id;
uint16 reason;
uint32 rsvd[7];
} tx_flowring_delete_request_t;
typedef struct tx_flowring_flush_request {
cmn_msg_hdr_t msg;
uint16 flow_ring_id;
uint16 reason;
uint32 rsvd[7];
} tx_flowring_flush_request_t;
typedef union ctrl_submit_item {
ioctl_req_msg_t ioctl_req;
ioctl_resp_evt_buf_post_msg_t resp_buf_post;
pcie_dma_xfer_params_t dma_xfer;
tx_flowring_create_request_t flow_create;
tx_flowring_delete_request_t flow_delete;
tx_flowring_flush_request_t flow_flush;
unsigned char check[H2DRING_CTRL_SUB_ITEMSIZE];
} ctrl_submit_item_t;
/* Control Completion messages (20 bytes) */
typedef struct compl_msg_hdr {
/* status for the completion */
int16 status;
/* submisison flow ring id which generated this status */
uint16 flow_ring_id;
} compl_msg_hdr_t;
/* XOR checksum or a magic number to audit DMA done */
typedef uint32 dma_done_t;
/* completion header status codes */
#define BCMPCIE_SUCCESS 0
#define BCMPCIE_NOTFOUND 1
#define BCMPCIE_NOMEM 2
#define BCMPCIE_BADOPTION 3
#define BCMPCIE_RING_IN_USE 4
#define BCMPCIE_RING_ID_INVALID 5
#define BCMPCIE_PKT_FLUSH 6
#define BCMPCIE_NO_EVENT_BUF 7
#define BCMPCIE_NO_RX_BUF 8
#define BCMPCIE_NO_IOCTLRESP_BUF 9
#define BCMPCIE_MAX_IOCTLRESP_BUF 10
#define BCMPCIE_MAX_EVENT_BUF 11
/* IOCTL completion response */
typedef struct ioctl_compl_resp_msg {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
/* response buffer len where a host buffer is involved */
uint16 resp_len;
/* transaction id to pair with a request */
uint16 trans_id;
/* cmd id */
uint32 cmd;
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} ioctl_comp_resp_msg_t;
/* IOCTL request acknowledgement */
typedef struct ioctl_req_ack_msg {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
/* cmd id */
uint32 cmd;
uint32 rsvd[1];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} ioctl_req_ack_msg_t;
/* WL event message: send from device to host */
typedef struct wlevent_req_msg {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
/* event data len valid with the event buffer */
uint16 event_data_len;
/* sequence number */
uint16 seqnum;
/* rsvd */
uint32 rsvd;
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} wlevent_req_msg_t;
/* dma xfer complete message */
typedef struct pcie_dmaxfer_cmplt {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
uint32 rsvd[2];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} pcie_dmaxfer_cmplt_t;
/* general status message */
typedef struct pcie_gen_status {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
uint32 rsvd[2];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} pcie_gen_status_t;
/* ring status message */
typedef struct pcie_ring_status {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
/* message which firmware couldn't decode */
uint16 write_idx;
uint16 rsvd[3];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} pcie_ring_status_t;
typedef struct tx_flowring_create_response {
cmn_msg_hdr_t msg;
compl_msg_hdr_t cmplt;
uint32 rsvd[2];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} tx_flowring_create_response_t;
typedef struct tx_flowring_delete_response {
cmn_msg_hdr_t msg;
compl_msg_hdr_t cmplt;
uint32 rsvd[2];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} tx_flowring_delete_response_t;
typedef struct tx_flowring_flush_response {
cmn_msg_hdr_t msg;
compl_msg_hdr_t cmplt;
uint32 rsvd[2];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} tx_flowring_flush_response_t;
/* Common layout of all d2h control messages */
typedef struct ctrl_compl_msg {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
uint32 rsvd[2];
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} ctrl_compl_msg_t;
typedef union ctrl_completion_item {
ioctl_comp_resp_msg_t ioctl_resp;
wlevent_req_msg_t event;
ioctl_req_ack_msg_t ioct_ack;
pcie_dmaxfer_cmplt_t pcie_xfer_cmplt;
pcie_gen_status_t pcie_gen_status;
pcie_ring_status_t pcie_ring_status;
tx_flowring_create_response_t txfl_create_resp;
tx_flowring_delete_response_t txfl_delete_resp;
tx_flowring_flush_response_t txfl_flush_resp;
ctrl_compl_msg_t ctrl_compl;
unsigned char check[D2HRING_CTRL_CMPLT_ITEMSIZE];
} ctrl_completion_item_t;
/* H2D Rxpost ring work items */
typedef struct host_rxbuf_post {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* provided meta data buffer len */
uint16 metadata_buf_len;
/* provided data buffer len to receive data */
uint16 data_buf_len;
/* alignment to make the host buffers start on 8 byte boundary */
uint32 rsvd;
/* provided meta data buffer */
addr64_t metadata_buf_addr;
/* provided data buffer to receive data */
addr64_t data_buf_addr;
} host_rxbuf_post_t;
typedef union rxbuf_submit_item {
host_rxbuf_post_t rxpost;
unsigned char check[H2DRING_RXPOST_ITEMSIZE];
} rxbuf_submit_item_t;
/* D2H Rxcompletion ring work items */
typedef struct host_rxbuf_cmpl {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
/* filled up meta data len */
uint16 metadata_len;
/* filled up buffer len to receive data */
uint16 data_len;
/* offset in the host rx buffer where the data starts */
uint16 data_offset;
/* offset in the host rx buffer where the data starts */
uint16 flags;
/* rx status */
uint32 rx_status_0;
uint32 rx_status_1;
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
} host_rxbuf_cmpl_t;
typedef union rxbuf_complete_item {
host_rxbuf_cmpl_t rxcmpl;
unsigned char check[D2HRING_RXCMPLT_ITEMSIZE];
} rxbuf_complete_item_t;
typedef struct host_txbuf_post {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* eth header */
uint8 txhdr[ETHER_HDR_LEN];
/* flags */
uint8 flags;
/* number of segments */
uint8 seg_cnt;
/* provided meta data buffer for txstatus */
addr64_t metadata_buf_addr;
/* provided data buffer to receive data */
addr64_t data_buf_addr;
/* provided meta data buffer len */
uint16 metadata_buf_len;
/* provided data buffer len to receive data */
uint16 data_len;
uint32 rsvd;
} host_txbuf_post_t;
#define BCMPCIE_PKT_FLAGS_FRAME_802_3 0x01
#define BCMPCIE_PKT_FLAGS_FRAME_802_11 0x02
#define BCMPCIE_PKT_FLAGS_FRAME_EXEMPT_MASK 0x03 /* Exempt uses 2 bits */
#define BCMPCIE_PKT_FLAGS_FRAME_EXEMPT_SHIFT 0x02 /* needs to be shifted past other bits */
#define BCMPCIE_PKT_FLAGS_PRIO_SHIFT 5
#define BCMPCIE_PKT_FLAGS_PRIO_MASK (7 << BCMPCIE_PKT_FLAGS_PRIO_SHIFT)
/* These are added to fix up teh compile issues */
#define BCMPCIE_TXPOST_FLAGS_FRAME_802_3 BCMPCIE_PKT_FLAGS_FRAME_802_3
#define BCMPCIE_TXPOST_FLAGS_FRAME_802_11 BCMPCIE_PKT_FLAGS_FRAME_802_11
#define BCMPCIE_TXPOST_FLAGS_PRIO_SHIFT BCMPCIE_PKT_FLAGS_PRIO_SHIFT
#define BCMPCIE_TXPOST_FLAGS_PRIO_MASK BCMPCIE_PKT_FLAGS_PRIO_MASK
/* H2D Txpost ring work items */
typedef union txbuf_submit_item {
host_txbuf_post_t txpost;
unsigned char check[H2DRING_TXPOST_ITEMSIZE];
} txbuf_submit_item_t;
/* D2H Txcompletion ring work items */
typedef struct host_txbuf_cmpl {
/* common message header */
cmn_msg_hdr_t cmn_hdr;
/* completion message header */
compl_msg_hdr_t compl_hdr;
union {
struct {
/* provided meta data len */
uint16 metadata_len;
/* WLAN side txstatus */
uint16 tx_status;
};
/* XOR checksum or a magic number to audit DMA done */
dma_done_t marker;
};
} host_txbuf_cmpl_t;
typedef union txbuf_complete_item {
host_txbuf_cmpl_t txcmpl;
unsigned char check[D2HRING_TXCMPLT_ITEMSIZE];
} txbuf_complete_item_t;
#define BCMPCIE_D2H_METADATA_HDRLEN 4
#define BCMPCIE_D2H_METADATA_MINLEN (BCMPCIE_D2H_METADATA_HDRLEN + 4)
/* ret buf struct */
typedef struct ret_buf_ptr {
uint32 low_addr;
uint32 high_addr;
} ret_buf_t;
#ifdef PCIE_API_REV1
/* ioctl specific hdr */
typedef struct ioctl_hdr {
uint16 cmd;
uint16 retbuf_len;
uint32 cmd_id;
} ioctl_hdr_t;
typedef struct ioctlptr_hdr {
uint16 cmd;
uint16 retbuf_len;
uint16 buflen;
uint16 rsvd;
uint32 cmd_id;
} ioctlptr_hdr_t;
#else /* PCIE_API_REV1 */
typedef struct ioctl_req_hdr {
uint32 pkt_id; /* Packet ID */
uint32 cmd; /* IOCTL ID */
uint16 retbuf_len;
uint16 buflen;
uint16 xt_id; /* transaction ID */
uint16 rsvd[1];
} ioctl_req_hdr_t;
#endif /* PCIE_API_REV1 */
/* Complete msgbuf hdr for ioctl from host to dongle */
typedef struct ioct_reqst_hdr {
cmn_msg_hdr_t msg;
#ifdef PCIE_API_REV1
ioctl_hdr_t ioct_hdr;
#else
ioctl_req_hdr_t ioct_hdr;
#endif
ret_buf_t ret_buf;
} ioct_reqst_hdr_t;
typedef struct ioctptr_reqst_hdr {
cmn_msg_hdr_t msg;
#ifdef PCIE_API_REV1
ioctlptr_hdr_t ioct_hdr;
#else
ioctl_req_hdr_t ioct_hdr;
#endif
ret_buf_t ret_buf;
ret_buf_t ioct_buf;
} ioctptr_reqst_hdr_t;
/* ioctl response header */
typedef struct ioct_resp_hdr {
cmn_msg_hdr_t msg;
#ifdef PCIE_API_REV1
uint32 cmd_id;
#else
uint32 pkt_id;
#endif
uint32 status;
uint32 ret_len;
uint32 inline_data;
#ifdef PCIE_API_REV1
#else
uint16 xt_id; /* transaction ID */
uint16 rsvd[1];
#endif
} ioct_resp_hdr_t;
/* ioct resp header used in dongle */
/* ret buf hdr will be stripped off inside dongle itself */
typedef struct msgbuf_ioctl_resp {
ioct_resp_hdr_t ioct_hdr;
ret_buf_t ret_buf; /* ret buf pointers */
} msgbuf_ioct_resp_t;
/* WL evet hdr info */
typedef struct wl_event_hdr {
cmn_msg_hdr_t msg;
uint16 event;
uint8 flags;
uint8 rsvd;
uint16 retbuf_len;
uint16 rsvd1;
uint32 rxbufid;
} wl_event_hdr_t;
#define TXDESCR_FLOWID_PCIELPBK_1 0xFF
#define TXDESCR_FLOWID_PCIELPBK_2 0xFE
typedef struct txbatch_lenptr_tup {
uint32 pktid;
uint16 pktlen;
uint16 rsvd;
ret_buf_t ret_buf; /* ret buf pointers */
} txbatch_lenptr_tup_t;
typedef struct txbatch_cmn_msghdr {
cmn_msg_hdr_t msg;
uint8 priority;
uint8 hdrlen;
uint8 pktcnt;
uint8 flowid;
uint8 txhdr[ETHER_HDR_LEN];
uint16 rsvd;
} txbatch_cmn_msghdr_t;
typedef struct txbatch_msghdr {
txbatch_cmn_msghdr_t txcmn;
txbatch_lenptr_tup_t tx_tup[0]; /* Based on packet count */
} txbatch_msghdr_t;
/* TX desc posting header */
typedef struct tx_lenptr_tup {
uint16 pktlen;
uint16 rsvd;
ret_buf_t ret_buf; /* ret buf pointers */
} tx_lenptr_tup_t;
typedef struct txdescr_cmn_msghdr {
cmn_msg_hdr_t msg;
uint8 priority;
uint8 hdrlen;
uint8 descrcnt;
uint8 flowid;
uint32 pktid;
} txdescr_cmn_msghdr_t;
typedef struct txdescr_msghdr {
txdescr_cmn_msghdr_t txcmn;
uint8 txhdr[ETHER_HDR_LEN];
uint16 rsvd;
tx_lenptr_tup_t tx_tup[0]; /* Based on descriptor count */
} txdescr_msghdr_t;
/* Tx status header info */
typedef struct txstatus_hdr {
cmn_msg_hdr_t msg;
uint32 pktid;
} txstatus_hdr_t;
/* RX bufid-len-ptr tuple */
typedef struct rx_lenptr_tup {
uint32 rxbufid;
uint16 len;
uint16 rsvd2;
ret_buf_t ret_buf; /* ret buf pointers */
} rx_lenptr_tup_t;
/* Rx descr Post hdr info */
typedef struct rxdesc_msghdr {
cmn_msg_hdr_t msg;
uint16 rsvd0;
uint8 rsvd1;
uint8 descnt;
rx_lenptr_tup_t rx_tup[0];
} rxdesc_msghdr_t;
/* RX complete tuples */
typedef struct rxcmplt_tup {
uint16 retbuf_len;
uint16 data_offset;
uint32 rxstatus0;
uint32 rxstatus1;
uint32 rxbufid;
} rxcmplt_tup_t;
/* RX complete messge hdr */
typedef struct rxcmplt_hdr {
cmn_msg_hdr_t msg;
uint16 rsvd0;
uint16 rxcmpltcnt;
rxcmplt_tup_t rx_tup[0];
} rxcmplt_hdr_t;
typedef struct hostevent_hdr {
cmn_msg_hdr_t msg;
uint32 evnt_pyld;
} hostevent_hdr_t;
typedef struct dma_xfer_params {
uint32 src_physaddr_hi;
uint32 src_physaddr_lo;
uint32 dest_physaddr_hi;
uint32 dest_physaddr_lo;
uint32 len;
uint32 srcdelay;
uint32 destdelay;
} dma_xfer_params_t;
enum {
HOST_EVENT_CONS_CMD = 1
};
/* defines for flags */
#define MSGBUF_IOC_ACTION_MASK 0x1
#endif /* _bcmmsgbuf_h_ */

View File

@ -0,0 +1,197 @@
/*
* Broadcom PCIE
* Software-specific definitions shared between device and host side
* Explains the shared area between host and dongle
* $Copyright Open 2005 Broadcom Corporation$
*
* $Id: bcmpcie.h 490808 2014-07-12 00:33:13Z $
*/
#ifndef _bcmpcie_h_
#define _bcmpcie_h_
#include <bcmutils.h>
#define ADDR_64(x) (x.addr)
#define HIGH_ADDR_32(x) ((uint32) (((sh_addr_t) x).high_addr))
#define LOW_ADDR_32(x) ((uint32) (((sh_addr_t) x).low_addr))
typedef struct {
uint32 low_addr;
uint32 high_addr;
} sh_addr_t;
#ifdef BCMPCIE_SUPPORT_TX_PUSH_RING
#define BCMPCIE_PUSH_TX_RING 1
#else
#define BCMPCIE_PUSH_TX_RING 0
#endif /* BCMPCIE_SUPPORT_TX_PUSH_RING */
/* May be overridden by 43xxxxx-roml.mk */
#if !defined(BCMPCIE_MAX_TX_FLOWS)
#define BCMPCIE_MAX_TX_FLOWS 40
#endif /* ! BCMPCIE_MAX_TX_FLOWS */
#define PCIE_SHARED_VERSION 0x00005
#define PCIE_SHARED_VERSION_MASK 0x000FF
#define PCIE_SHARED_ASSERT_BUILT 0x00100
#define PCIE_SHARED_ASSERT 0x00200
#define PCIE_SHARED_TRAP 0x00400
#define PCIE_SHARED_IN_BRPT 0x00800
#define PCIE_SHARED_SET_BRPT 0x01000
#define PCIE_SHARED_PENDING_BRPT 0x02000
#define PCIE_SHARED_TXPUSH_SPRT 0x04000
#define PCIE_SHARED_EVT_SEQNUM 0x08000
#define PCIE_SHARED_DMA_INDEX 0x10000
#define BCMPCIE_H2D_MSGRING_CONTROL_SUBMIT 0
#define BCMPCIE_H2D_MSGRING_RXPOST_SUBMIT 1
#define BCMPCIE_D2H_MSGRING_CONTROL_COMPLETE 2
#define BCMPCIE_D2H_MSGRING_TX_COMPLETE 3
#define BCMPCIE_D2H_MSGRING_RX_COMPLETE 4
#define BCMPCIE_COMMON_MSGRING_MAX_ID 4
/* Added only for single tx ring */
#define BCMPCIE_H2D_TXFLOWRINGID 5
#define BCMPCIE_H2D_COMMON_MSGRINGS 2
#define BCMPCIE_D2H_COMMON_MSGRINGS 3
#define BCMPCIE_COMMON_MSGRINGS 5
enum h2dring_idx {
BCMPCIE_H2D_MSGRING_CONTROL_SUBMIT_IDX = 0,
BCMPCIE_H2D_MSGRING_RXPOST_SUBMIT_IDX = 1,
BCMPCIE_H2D_MSGRING_TXFLOW_IDX_START = 2
};
enum d2hring_idx {
BCMPCIE_D2H_MSGRING_CONTROL_COMPLETE_IDX = 0,
BCMPCIE_D2H_MSGRING_TX_COMPLETE_IDX = 1,
BCMPCIE_D2H_MSGRING_RX_COMPLETE_IDX = 2
};
typedef struct ring_mem {
uint16 idx;
uint8 type;
uint8 rsvd;
uint16 max_item;
uint16 len_items;
sh_addr_t base_addr;
} ring_mem_t;
#define RINGSTATE_INITED 1
typedef struct ring_state {
uint8 idx;
uint8 state;
uint16 r_offset;
uint16 w_offset;
uint16 e_offset;
} ring_state_t;
typedef struct ring_info {
/* locations in the TCM where the ringmem is and ringstate are defined */
uint32 ringmem_ptr; /* ring mem location in TCM */
uint32 h2d_w_idx_ptr;
uint32 h2d_r_idx_ptr;
uint32 d2h_w_idx_ptr;
uint32 d2h_r_idx_ptr;
/* host locations where the DMA of read/write indices are */
sh_addr_t h2d_w_idx_hostaddr;
sh_addr_t h2d_r_idx_hostaddr;
sh_addr_t d2h_w_idx_hostaddr;
sh_addr_t d2h_r_idx_hostaddr;
uint16 max_sub_queues;
uint16 rsvd;
} ring_info_t;
typedef struct {
/* shared area version captured at flags 7:0 */
uint32 flags;
uint32 trap_addr;
uint32 assert_exp_addr;
uint32 assert_file_addr;
uint32 assert_line;
uint32 console_addr; /* Address of hnd_cons_t */
uint32 msgtrace_addr;
uint32 fwid;
/* Used for debug/flow control */
uint16 total_lfrag_pkt_cnt;
uint16 max_host_rxbufs; /* rsvd in spec */
uint32 dma_rxoffset; /* rsvd in spec */
/* these will be used for sleep request/ack, d3 req/ack */
uint32 h2d_mb_data_ptr;
uint32 d2h_mb_data_ptr;
/* information pertinent to host IPC/msgbuf channels */
/* location in the TCM memory which has the ring_info */
uint32 rings_info_ptr;
/* block of host memory for the scratch buffer */
uint32 host_dma_scratch_buffer_len;
sh_addr_t host_dma_scratch_buffer;
/* block of host memory for the dongle to push the status into */
uint32 device_rings_stsblk_len;
sh_addr_t device_rings_stsblk;
#ifdef BCM_BUZZZ
uint32 buzzz; /* BUZZZ state format strings and trace buffer */
#endif
} pciedev_shared_t;
/* H2D mail box Data */
#define H2D_HOST_D3_INFORM 0x00000001
#define H2D_HOST_DS_ACK 0x00000002
#define H2D_HOST_CONS_INT 0x80000000 /* h2d int for console cmds */
/* D2H mail box Data */
#define D2H_DEV_D3_ACK 0x00000001
#define D2H_DEV_DS_ENTER_REQ 0x00000002
#define D2H_DEV_DS_EXIT_NOTE 0x00000004
#define D2H_DEV_FWHALT 0x10000000
extern pciedev_shared_t pciedev_shared;
#define NEXTTXP(i, d) ((((i)+1) >= (d)) ? 0 : ((i)+1))
#define NTXPACTIVE(r, w, d) (((r) <= (w)) ? ((w)-(r)) : ((d)-(r)+(w)))
#define NTXPAVAIL(r, w, d) (((d) - NTXPACTIVE((r), (w), (d))) > 1)
/* Function can be used to notify host of FW halt */
#define READ_AVAIL_SPACE(w, r, d) \
((w >= r) ? (w - r) : (d - r))
#define WRT_PEND(x) ((x)->wr_pending)
#define DNGL_RING_WPTR(msgbuf) (*((msgbuf)->tcm_rs_w_ptr))
#define BCMMSGBUF_RING_SET_W_PTR(msgbuf, a) (DNGL_RING_WPTR(msgbuf) = (a))
#define DNGL_RING_RPTR(msgbuf) (*((msgbuf)->tcm_rs_r_ptr))
#define BCMMSGBUF_RING_SET_R_PTR(msgbuf, a) (DNGL_RING_RPTR(msgbuf) = (a))
#define RING_READ_PTR(x) ((x)->ringstate->r_offset)
#define RING_WRITE_PTR(x) ((x)->ringstate->w_offset)
#define RING_START_PTR(x) ((x)->ringmem->base_addr.low_addr)
#define RING_MAX_ITEM(x) ((x)->ringmem->max_item)
#define RING_LEN_ITEMS(x) ((x)->ringmem->len_items)
#define HOST_RING_BASE(x) ((x)->ring_base.va)
#define HOST_RING_END(x) ((uint8 *)HOST_RING_BASE((x)) + \
((RING_MAX_ITEM((x))-1)*RING_LEN_ITEMS((x))))
#define WRITE_SPACE_AVAIL_CONTINUOUS(r, w, d) ((w >= r) ? (d - w) : (r - w))
#define WRITE_SPACE_AVAIL(r, w, d) (d - (NTXPACTIVE(r, w, d)) - 1)
#define CHECK_WRITE_SPACE(r, w, d) \
MIN(WRITE_SPACE_AVAIL(r, w, d), WRITE_SPACE_AVAIL_CONTINUOUS(r, w, d))
#endif /* _bcmpcie_h_ */

View File

View File

View File

@ -4,7 +4,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: bcmsdbus.h 408155 2013-06-17 21:52:27Z $
* $Id: bcmsdbus.h 408158 2013-06-17 22:15:35Z $
*/
#ifndef _sdio_api_h_
@ -28,35 +28,27 @@
#define SDIOH_DATA_PIO 0 /* PIO mode */
#define SDIOH_DATA_DMA 1 /* DMA mode */
#ifdef BCMSDIOH_TXGLOM
/* Max number of glommed pkts */
#ifdef CUSTOM_MAX_TXGLOM_SIZE
#define SDPCM_MAXGLOM_SIZE CUSTOM_MAX_TXGLOM_SIZE
#else
#define SDPCM_MAXGLOM_SIZE 10
#define SDPCM_MAXGLOM_SIZE 40
#endif /* CUSTOM_MAX_TXGLOM_SIZE */
#define SDPCM_TXGLOM_CPY 0 /* SDIO 2.0 should use copy mode */
#define SDPCM_TXGLOM_MDESC 1 /* SDIO 3.0 should use multi-desc mode */
#ifdef BCMSDIOH_TXGLOM_HIGHSPEED
#define SDPCM_DEFGLOM_MODE SDPCM_TXGLOM_MDESC
#ifdef CUSTOM_DEF_TXGLOM_SIZE
#define SDPCM_DEFGLOM_SIZE CUSTOM_DEF_TXGLOM_SIZE
#else
#define SDPCM_DEFGLOM_SIZE 10
#define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE
#endif /* CUSTOM_DEF_TXGLOM_SIZE */
#else
#define SDPCM_DEFGLOM_MODE SDPCM_TXGLOM_CPY
#define SDPCM_DEFGLOM_SIZE 3
#endif /* BCMSDIOH_TXGLOM_HIGHSPEED */
#if SDPCM_DEFGLOM_SIZE > SDPCM_MAXGLOM_SIZE
#warning "SDPCM_DEFGLOM_SIZE cannot be higher than SDPCM_MAXGLOM_SIZE!!"
#undef SDPCM_DEFGLOM_SIZE
#define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE
#endif
#endif /* BCMSDIOH_TXGLOM */
typedef int SDIOH_API_RC;
@ -66,12 +58,6 @@ typedef struct sdioh_info sdioh_info_t;
/* callback function, taking one arg */
typedef void (*sdioh_cb_fn_t)(void *);
/* attach, return handler on success, NULL if failed.
* The handler shall be provided by all subsequent calls. No local cache
* cfghdl points to the starting address of pci device mapped memory
*/
extern sdioh_info_t * sdioh_attach(osl_t *osh, void *cfghdl, uint irq);
extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *si);
extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si, sdioh_cb_fn_t fn, void *argh);
extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
@ -97,18 +83,6 @@ extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma, uint fi
uint rw, uint fnc_num, uint32 addr, uint regwidth, uint32 buflen, uint8 *buffer,
void *pkt);
#ifdef BCMSDIOH_TXGLOM
extern void sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, void *pkt, uint len);
extern void sdioh_glom_clear(sdioh_info_t *sd);
extern uint sdioh_set_mode(sdioh_info_t *sd, uint mode);
extern bool sdioh_glom_enabled(void);
#else
#define sdioh_glom_post(a, b, c, d)
#define sdioh_glom_clear(a)
#define sdioh_set_mode(a) (0)
#define sdioh_glom_enabled() (FALSE)
#endif
/* get cis data */
extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, uint8 *cis, uint32 length);
@ -135,9 +109,6 @@ extern int sdioh_waitlockfree(sdioh_info_t *si);
/* Reset and re-initialize the device */
extern int sdioh_sdio_reset(sdioh_info_t *si);
/* Helper function */
void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
#if defined(BCMSDIOH_STD)

View File

@ -5,7 +5,7 @@
*
* $ Copyright Open License Broadcom Corporation $
*
* $Id: bcmsdh.h 414953 2013-07-26 17:36:27Z $
* $Id: bcmsdh.h 450676 2014-01-22 22:45:13Z $
*/
/**
@ -22,7 +22,8 @@ extern const uint bcmsdh_msglevel;
#define BCMSDH_ERROR(x)
#define BCMSDH_INFO(x)
#if (defined(BCMSDIOH_STD) || defined(BCMSDIOH_BCM) || defined(BCMSDIOH_SPI))
#if defined(BCMSDIO) && (defined(BCMSDIOH_STD) || defined(BCMSDIOH_BCM) || \
defined(BCMSDIOH_SPI))
#define BCMSDH_ADAPTER
#endif /* BCMSDIO && (BCMSDIOH_STD || BCMSDIOH_BCM || BCMSDIOH_SPI) */
@ -30,14 +31,25 @@ extern const uint bcmsdh_msglevel;
typedef struct bcmsdh_info bcmsdh_info_t;
typedef void (*bcmsdh_cb_fn_t)(void *);
/* Attach and build an interface to the underlying SD host driver.
* - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh.
* - Returns the bcmsdh handle and virtual address base for register access.
* The returned handle should be used in all subsequent calls, but the bcmsh
* implementation may maintain a single "default" handle (e.g. the first or
* most recent one) to enable single-instance implementations to pass NULL.
#if 0 && (NDISVER >= 0x0630) && 1
extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl,
void **regsva, uint irq, shared_info_t *sh);
#else
extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva);
/**
* BCMSDH API context
*/
extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq);
struct bcmsdh_info
{
bool init_success; /* underlying driver successfully attached */
void *sdioh; /* handler for sdioh */
uint32 vendevid; /* Target Vendor and Device ID on SD bus */
osl_t *osh;
bool regfail; /* Save status of last reg_read/reg_write call */
uint32 sbwad; /* Save backplane window address */
void *os_cxt; /* Pointer to per-OS private data */
};
#endif
/* Detach - freeup resources allocated in attach */
extern int bcmsdh_detach(osl_t *osh, void *sdh);
@ -170,16 +182,18 @@ extern int bcmsdh_reset(bcmsdh_info_t *sdh);
/* helper functions */
extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
/* callback functions */
typedef struct {
/* attach to device */
void *(*attach)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot,
/* probe the device */
void *(*probe)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot,
uint16 func, uint bustype, void * regsva, osl_t * osh,
void * param);
/* detach from device */
void (*detach)(void *ch);
/* remove the device */
void (*remove)(void *context);
/* can we suspend now */
int (*suspend)(void *context);
/* resume from suspend */
int (*resume)(void *context);
} bcmsdh_driver_t;
/* platform specific/high level functions */
@ -191,14 +205,18 @@ extern void bcmsdh_device_remove(void * sdh);
extern int bcmsdh_reg_sdio_notify(void* semaphore);
extern void bcmsdh_unreg_sdio_notify(void);
extern int bcmsdh_set_drvdata(void * dhdp);
#if defined(OOB_INTR_ONLY)
extern int bcmsdh_register_oob_intr(void * dhdp);
extern void bcmsdh_unregister_oob_intr(void);
extern void bcmsdh_oob_intr_set(bool enable);
extern bool bcmsdh_is_oob_intr_registered(void);
#endif
extern int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler,
void* oob_irq_handler_context);
extern void bcmsdh_oob_intr_unregister(bcmsdh_info_t *sdh);
extern void bcmsdh_oob_intr_set(bcmsdh_info_t *sdh, bool enable);
#endif
extern void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *sdh);
extern void bcmsdh_dev_relax(bcmsdh_info_t *sdh);
extern bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *sdh);
int bcmsdh_suspend(bcmsdh_info_t *bcmsdh);
int bcmsdh_resume(bcmsdh_info_t *bcmsdh);
/* Function to pass device-status bits to DHD. */
extern uint32 bcmsdh_get_dstatus(void *sdh);

View File

@ -1,7 +1,7 @@
/*
* BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
*
* Copyright (C) 1999-2013, Broadcom Corporation
* Copyright (C) 1999-2014, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
* $Id: bcmsdh_sdmmc.h 396592 2013-04-13 16:14:38Z $
* $Id: bcmsdh_sdmmc.h 408158 2013-06-17 22:15:35Z $
*/
#ifndef __BCMSDH_SDMMC_H__
@ -40,10 +40,6 @@
#define sd_ack_intr(sd)
#define sd_wakeup(sd);
/* Allocate/init/free per-OS private data */
extern int sdioh_sdmmc_osinit(sdioh_info_t *sd);
extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
#define sd_log(x)
#define SDIOH_ASSERT(exp) \
@ -61,46 +57,32 @@ extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
/* private bus modes */
#define SDIOH_MODE_SD4 2
#define CLIENT_INTR 0x100 /* Get rid of this! */
#ifdef BCMSDIOH_TXGLOM
typedef struct glom_buf {
void *glom_pkt_head;
void *glom_pkt_tail;
uint32 count; /* Total number of pkts queued */
} glom_buf_t;
#endif /* BCMSDIOH_TXGLOM */
#define SDIOH_SDMMC_MAX_SG_ENTRIES 32
struct sdioh_info {
osl_t *osh; /* osh handler */
void *bcmsdh; /* upper layer handle */
bool client_intr_enabled; /* interrupt connnected flag */
bool intr_handler_valid; /* client driver interrupt handler valid */
sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
void *intr_handler_arg; /* argument to call interrupt handler */
uint16 intmask; /* Current active interrupts */
void *sdos_info; /* Pointer to per-OS private data */
uint irq; /* Client irq */
int intrcount; /* Client interrupts */
int intrcount; /* Client interrupts */
bool sd_use_dma; /* DMA on CMD53 */
bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
/* Must be on for sd_multiblock to be effective */
bool use_client_ints; /* If this is false, make sure to restore */
int sd_mode; /* SD1/SD4/SPI */
int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
uint8 num_funcs; /* Supported funcs on client */
uint32 com_cis_ptr;
bool use_client_ints; /* If this is false, make sure to restore */
int sd_mode; /* SD1/SD4/SPI */
int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
uint8 num_funcs; /* Supported funcs on client */
uint32 com_cis_ptr;
uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
#define SDIOH_SDMMC_MAX_SG_ENTRIES 32
struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES];
bool use_rxchain;
struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES];
struct sdio_func fake_func0;
struct sdio_func *func[SDIOD_MAX_IOFUNCS];
#ifdef BCMSDIOH_TXGLOM
glom_buf_t glom_info; /* pkt information used for glomming */
uint txglom_mode; /* Txglom mode: 0 - copy, 1 - multi-descriptor */
#endif
};
/************************************************************
@ -130,9 +112,11 @@ extern void sdioh_sdmmc_reg_unmap(osl_t *osh, int32 addr, int size);
extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
extern sdioh_info_t *sdioh_attach(osl_t *osh, struct sdio_func *func);
extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd);
typedef struct _BCMSDH_SDMMC_INSTANCE {
sdioh_info_t *sd;
struct sdio_func *func[SDIOD_MAX_IOFUNCS];
} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
#endif /* __BCMSDH_SDMMC_H__ */

View File

@ -4,7 +4,7 @@
*
* $Copyright Open 2005 Broadcom Corporation$
*
* $Id: bcmsdpcm.h 364353 2012-10-23 20:31:46Z $
* $Id: bcmsdpcm.h 472405 2014-04-23 23:46:55Z $
*/
#ifndef _bcmsdpcm_h_
@ -250,14 +250,11 @@ typedef struct {
uint32 assert_exp_addr;
uint32 assert_file_addr;
uint32 assert_line;
uint32 console_addr; /* Address of hndrte_cons_t */
uint32 console_addr; /* Address of hnd_cons_t */
uint32 msgtrace_addr;
uint32 brpt_addr;
uint32 fwid;
} sdpcm_shared_t;
extern sdpcm_shared_t sdpcm_shared;
/* Function can be used to notify host of FW halt */
extern void sdpcmd_fwhalt(void);
#endif /* _bcmsdpcm_h_ */

View File

View File

@ -3,7 +3,7 @@
*
* $ Copyright Open Broadcom Corporation $
*
* $Id: bcmsdstd.h 343301 2012-07-06 13:07:32Z $
* $Id: bcmsdstd.h 455390 2014-02-13 22:14:56Z $
*/
#ifndef _BCM_SD_STD_H
#define _BCM_SD_STD_H
@ -75,8 +75,10 @@ extern void sdstd_osfree(sdioh_info_t *sd);
#ifdef BCMSDIOH_TXGLOM
/* Setting the MAX limit to 10 */
#define SDIOH_MAXGLOM_SIZE 10
/* Total glom pkt can not exceed 64K
* need one more slot for glom padding packet
*/
#define SDIOH_MAXGLOM_SIZE (40+1)
typedef struct glom_buf {
uint32 count; /* Total number of pkts queued */
@ -102,29 +104,30 @@ struct sdioh_info {
uint target_dev; /* Target device ID */
uint16 intmask; /* Current active interrupts */
void *sdos_info; /* Pointer to per-OS private data */
void *bcmsdh; /* handler to upper layer stack (bcmsdh) */
uint32 controller_type; /* Host controller type */
uint8 version; /* Host Controller Spec Compliance Version */
uint irq; /* Client irq */
int intrcount; /* Client interrupts */
int local_intrcount; /* Controller interrupts */
bool host_init_done; /* Controller initted */
bool card_init_done; /* Client SDIO interface initted */
bool polled_mode; /* polling for command completion */
uint irq; /* Client irq */
int intrcount; /* Client interrupts */
int local_intrcount; /* Controller interrupts */
bool host_init_done; /* Controller initted */
bool card_init_done; /* Client SDIO interface initted */
bool polled_mode; /* polling for command completion */
bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
/* Must be on for sd_multiblock to be effective */
bool use_client_ints; /* If this is false, make sure to restore */
bool use_client_ints; /* If this is false, make sure to restore */
/* polling hack in wl_linux.c:wl_timer() */
int adapter_slot; /* Maybe dealing with multiple slots/controllers */
int sd_mode; /* SD1/SD4/SPI */
int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
uint32 data_xfer_count; /* Current transfer */
uint16 card_rca; /* Current Address */
int adapter_slot; /* Maybe dealing with multiple slots/controllers */
int sd_mode; /* SD1/SD4/SPI */
int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
uint32 data_xfer_count; /* Current transfer */
uint16 card_rca; /* Current Address */
int8 sd_dma_mode; /* DMA Mode (PIO, SDMA, ... ADMA2) on CMD53 */
uint8 num_funcs; /* Supported funcs on client */
uint32 com_cis_ptr;
uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
uint8 num_funcs; /* Supported funcs on client */
uint32 com_cis_ptr;
uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
void *dma_buf; /* DMA Buffer virtual address */
ulong dma_phys; /* DMA Buffer physical address */
void *adma2_dscr_buf; /* ADMA2 Descriptor Buffer virtual address */
@ -182,6 +185,13 @@ struct sdioh_info {
#define CHECK_TUNING_PRE_DATA 1
#define CHECK_TUNING_POST_DATA 2
#ifdef DHD_DEBUG
#define SD_DHD_DISABLE_PERIODIC_TUNING 0x01
#define SD_DHD_ENABLE_PERIODIC_TUNING 0x00
#endif
/************************************************************
* Internal interfaces: per-port references into bcmsdstd.c
*/
@ -209,8 +219,8 @@ extern void sdstd_spinbits(sdioh_info_t *sd, uint16 norm, uint16 err);
*/
/* Register mapping routines */
extern uint32 *sdstd_reg_map(osl_t *osh, int32 addr, int size);
extern void sdstd_reg_unmap(osl_t *osh, int32 addr, int size);
extern uint32 *sdstd_reg_map(osl_t *osh, ulong addr, int size);
extern void sdstd_reg_unmap(osl_t *osh, ulong addr, int size);
/* Interrupt (de)registration routines */
extern int sdstd_register_irq(sdioh_info_t *sd, uint irq);
@ -221,6 +231,10 @@ extern void sdstd_lock(sdioh_info_t *sd);
extern void sdstd_unlock(sdioh_info_t *sd);
extern void sdstd_waitlockfree(sdioh_info_t *sd);
/* OS-specific wrappers for safe concurrent register access */
extern void sdstd_os_lock_irqsave(sdioh_info_t *sd, ulong* flags);
extern void sdstd_os_unlock_irqrestore(sdioh_info_t *sd, ulong* flags);
/* OS-specific wait-for-interrupt-or-status */
extern int sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield, uint16 *bits);
@ -243,4 +257,8 @@ extern void sdstd_3_start_tuning(sdioh_info_t *sd);
extern void sdstd_3_osinit_tuning(sdioh_info_t *sd);
extern void sdstd_3_osclean_tuning(sdioh_info_t *sd);
extern void sdstd_enable_disable_periodic_timer(sdioh_info_t * sd, uint val);
extern sdioh_info_t *sdioh_attach(osl_t *osh, void *bar0, uint irq);
extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd);
#endif /* _BCM_SD_STD_H */

View File

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,10 @@
#define _bcmwifi_channels_h_
/* A chanspec holds the channel number, band, bandwidth and control sideband */
typedef uint16 chanspec_t;
/* channel defines */
#define CH_UPPER_SB 0x01
#define CH_LOWER_SB 0x02
#define CH_EWA_VALID 0x04
@ -23,105 +23,24 @@ typedef uint16 chanspec_t;
#define CH_40MHZ_APART 8
#define CH_20MHZ_APART 4
#define CH_10MHZ_APART 2
#define CH_5MHZ_APART 1
#define CH_MAX_2G_CHANNEL 14
#define MAXCHANNEL 224
#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
#define MAXCHANNEL 224 /* max # supported channels. The max channel no is above,
* this is that + 1 rounded up to a multiple of NBBY (8).
* DO NOT MAKE it > 255: channels are uint8's all over
*/
#define MAXCHANNEL_NUM (MAXCHANNEL - 1) /* max channel number */
/* make sure channel num is within valid range */
#define CH_NUM_VALID_RANGE(ch_num) ((ch_num) > 0 && (ch_num) <= MAXCHANNEL_NUM)
#define CHSPEC_CTLOVLP(sp1, sp2, sep) (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < \
(sep))
/* All builds use the new 11ac ratespec/chanspec */
#undef D11AC_IOTYPES
#define D11AC_IOTYPES
#ifndef D11AC_IOTYPES
#define WL_CHANSPEC_CHAN_MASK 0x00ff
#define WL_CHANSPEC_CHAN_SHIFT 0
#define WL_CHANSPEC_CTL_SB_MASK 0x0300
#define WL_CHANSPEC_CTL_SB_SHIFT 8
#define WL_CHANSPEC_CTL_SB_LOWER 0x0100
#define WL_CHANSPEC_CTL_SB_UPPER 0x0200
#define WL_CHANSPEC_CTL_SB_NONE 0x0300
#define WL_CHANSPEC_BW_MASK 0x0C00
#define WL_CHANSPEC_BW_SHIFT 10
#define WL_CHANSPEC_BW_10 0x0400
#define WL_CHANSPEC_BW_20 0x0800
#define WL_CHANSPEC_BW_40 0x0C00
#define WL_CHANSPEC_BAND_MASK 0xf000
#define WL_CHANSPEC_BAND_SHIFT 12
#ifdef WL_CHANSPEC_BAND_5G
#undef WL_CHANSPEC_BAND_5G
#endif
#ifdef WL_CHANSPEC_BAND_2G
#undef WL_CHANSPEC_BAND_2G
#endif
#define WL_CHANSPEC_BAND_5G 0x1000
#define WL_CHANSPEC_BAND_2G 0x2000
#define INVCHANSPEC 255
#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0)
#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
((channel) + CH_10MHZ_APART) : 0)
#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0)
#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \
((channel) + 3 * CH_10MHZ_APART) : 0)
#define LU_20_SB(channel) LOWER_20_SB(channel)
#define UL_20_SB(channel) UPPER_20_SB(channel)
#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
((channel) + CH_20MHZ_APART) : 0)
#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
WL_CHANSPEC_BAND_5G))
#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
#ifdef WL11N_20MHZONLY
#define CHSPEC_IS10(chspec) 0
#define CHSPEC_IS20(chspec) 1
#ifndef CHSPEC_IS40
#define CHSPEC_IS40(chspec) 0
#endif
#else
#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
#ifndef CHSPEC_IS40
#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
#endif
#endif
#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \
(LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
(UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))))
#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
#define CHANSPEC_STR_LEN 8
#else
#define WL_CHANSPEC_CHAN_MASK 0x00ff
#define WL_CHANSPEC_CHAN_SHIFT 0
#define WL_CHANSPEC_CHAN1_MASK 0x000f
@ -145,8 +64,9 @@ typedef uint16 chanspec_t;
#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU
#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL
#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU
#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL
#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL
#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU
#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
#define WL_CHANSPEC_BW_MASK 0x3800
#define WL_CHANSPEC_BW_SHIFT 11
@ -166,7 +86,7 @@ typedef uint16 chanspec_t;
#define WL_CHANSPEC_BAND_5G 0xc000
#define INVCHANSPEC 255
/* channel defines */
#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \
((channel) - CH_10MHZ_APART) : 0)
#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
@ -197,12 +117,16 @@ typedef uint16 chanspec_t;
((channel) | (ctlsb) | \
WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK)
#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK)
/* simple MACROs to get different fields of chanspec */
#ifdef WL11AC_80P80
#define CHSPEC_CHANNEL(chspec) wf_chspec_channel(chspec)
#else
#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
#endif
#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT
#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
#ifdef WL11N_20MHZONLY
@ -222,7 +146,7 @@ typedef uint16 chanspec_t;
#define CHSPEC_IS8080(chspec) 0
#endif
#else
#else /* !WL11N_20MHZONLY */
#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
@ -239,7 +163,7 @@ typedef uint16 chanspec_t;
#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080)
#endif
#endif
#endif /* !WL11N_20MHZONLY */
#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
@ -251,11 +175,45 @@ typedef uint16 chanspec_t;
(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
/**
* Number of chars needed for wf_chspec_ntoa() destination character buffer.
*/
#define CHANSPEC_STR_LEN 20
#define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\
CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080)
/* BW inequality comparisons, LE (<=), GE (>=), LT (<), GT (>), comparisons can be made
* as simple numeric comparisons, with the exception that 160 is the same BW as 80+80,
* but have different numeric values; (WL_CHANSPEC_BW_160 < WL_CHANSPEC_BW_8080).
*
* The LT/LE/GT/GE macros check first checks whether both chspec bandwidth and bw are 160 wide.
* If both chspec bandwidth and bw is not 160 wide, then the comparison is made.
*/
#define CHSPEC_BW_GE(chspec, bw) \
((CHSPEC_IS_BW_160_WIDE(chspec) &&\
(bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) ||\
(CHSPEC_BW(chspec) >= bw))
#define CHSPEC_BW_LE(chspec, bw) \
((CHSPEC_IS_BW_160_WIDE(chspec) &&\
(bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) ||\
(CHSPEC_BW(chspec) <= bw))
#define CHSPEC_BW_GT(chspec, bw) \
(!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
(bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) &&\
(CHSPEC_BW(chspec) > bw))
#define CHSPEC_BW_LT(chspec, bw) \
(!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
(bw == WL_CHANSPEC_BW_160 || bw == WL_CHANSPEC_BW_8080)) &&\
(CHSPEC_BW(chspec) < bw))
/* Legacy Chanspec defines
* These are the defines for the previous format of the chanspec_t
*/
#define WL_LCHANSPEC_CHAN_MASK 0x00ff
#define WL_LCHANSPEC_CHAN_SHIFT 0
@ -286,6 +244,13 @@ typedef uint16 chanspec_t;
#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
#define LCHSPEC_SB_UPPER(chspec) \
((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
#define LCHSPEC_SB_LOWER(chspec) \
((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band)))
#define CH20MHZ_LCHSPEC(channel) \
@ -293,53 +258,273 @@ typedef uint16 chanspec_t;
WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
#endif
/*
* WF_CHAN_FACTOR_* constants are used to calculate channel frequency
* given a channel number.
* chan_freq = chan_factor * 500Mhz + chan_number * 5
*/
/**
* Channel Factor for the starting frequence of 2.4 GHz channels.
* The value corresponds to 2407 MHz.
*/
#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */
/**
* Channel Factor for the starting frequence of 5 GHz channels.
* The value corresponds to 5000 MHz.
*/
#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */
/**
* Channel Factor for the starting frequence of 4.9 GHz channels.
* The value corresponds to 4000 MHz.
*/
#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */
#define WF_CHAN_FACTOR_2_4_G 4814
#define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */
/**
* No of sub-band vlaue of the specified Mhz chanspec
*/
#define WF_NUM_SIDEBANDS_40MHZ 2
#define WF_NUM_SIDEBANDS_80MHZ 4
#define WF_NUM_SIDEBANDS_8080MHZ 4
#define WF_NUM_SIDEBANDS_160MHZ 8
#define WF_CHAN_FACTOR_5_G 10000
#define WF_CHAN_FACTOR_4_G 8000
#define WLC_2G_25MHZ_OFFSET 5
/**
* Convert chanspec to ascii string
*
* @param chspec chanspec format
* @param buf ascii string of chanspec
*
* @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes
* Original chanspec in case of error
*
* @see CHANSPEC_STR_LEN
*/
extern char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf);
/**
* Convert chanspec to ascii string
*
* @param chspec chanspec format
* @param buf ascii string of chanspec
*
* @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes
* NULL in case of error
*
* @see CHANSPEC_STR_LEN
*/
extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf);
/**
* Convert ascii string to chanspec
*
* @param a pointer to input string
*
* @return >= 0 if successful or 0 otherwise
*/
extern chanspec_t wf_chspec_aton(const char *a);
/**
* Verify the chanspec fields are valid.
*
* Verify the chanspec is using a legal set field values, i.e. that the chanspec
* specified a band, bw, ctl_sb and channel and that the combination could be
* legal given some set of circumstances.
*
* @param chanspec input chanspec to verify
*
* @return TRUE if the chanspec is malformed, FALSE if it looks good.
*/
extern bool wf_chspec_malformed(chanspec_t chanspec);
/**
* Verify the chanspec specifies a valid channel according to 802.11.
*
* @param chanspec input chanspec to verify
*
* @return TRUE if the chanspec is a valid 802.11 channel
*/
extern bool wf_chspec_valid(chanspec_t chanspec);
/**
* Return the primary (control) channel.
*
* This function returns the channel number of the primary 20MHz channel. For
* 20MHz channels this is just the channel number. For 40MHz or wider channels
* it is the primary 20MHz channel specified by the chanspec.
*
* @param chspec input chanspec
*
* @return Returns the channel number of the primary 20MHz channel
*/
extern uint8 wf_chspec_ctlchan(chanspec_t chspec);
/**
* Return the bandwidth string.
*
* This function returns the bandwidth string for the passed chanspec.
*
* @param chspec input chanspec
*
* @return Returns the bandwidth string
*/
extern char * wf_chspec_to_bw_str(chanspec_t chspec);
/**
* Return the primary (control) chanspec.
*
* This function returns the chanspec of the primary 20MHz channel. For 20MHz
* channels this is just the chanspec. For 40MHz or wider channels it is the
* chanspec of the primary 20MHZ channel specified by the chanspec.
*
* @param chspec input chanspec
*
* @return Returns the chanspec of the primary 20MHz channel
*/
extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
/**
* Return a channel number corresponding to a frequency.
*
* This function returns the chanspec for the primary 40MHz of an 80MHz channel.
* The control sideband specifies the same 20MHz channel that the 80MHz channel is using
* as the primary 20MHz channel.
*/
extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec);
/*
* Return the channel number for a given frequency and base frequency.
* The returned channel number is relative to the given base frequency.
* If the given base frequency is zero, a base frequency of 5 GHz is assumed for
* frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
*
* Frequency is specified in MHz.
* The base frequency is specified as (start_factor * 500 kHz).
* Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
* 2.4 GHz and 5 GHz bands.
*
* The returned channel will be in the range [1, 14] in the 2.4 GHz band
* and [0, 200] otherwise.
* -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
* frequency is not a 2.4 GHz channel, or if the frequency is not and even
* multiple of 5 MHz from the base frequency to the base plus 1 GHz.
*
* Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
*
* @param freq frequency in MHz
* @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz
*
* @return Returns a channel number
*
* @see WF_CHAN_FACTOR_2_4_G
* @see WF_CHAN_FACTOR_5_G
*/
extern int wf_mhz2channel(uint freq, uint start_factor);
/**
* Return the center frequency in MHz of the given channel and base frequency.
*
* Return the center frequency in MHz of the given channel and base frequency.
* The channel number is interpreted relative to the given base frequency.
*
* The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
* The base frequency is specified as (start_factor * 500 kHz).
* Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
* 2.4 GHz and 5 GHz bands.
* The channel range of [1, 14] is only checked for a start_factor of
* WF_CHAN_FACTOR_2_4_G (4814).
* Odd start_factors produce channels on .5 MHz boundaries, in which case
* the answer is rounded down to an integral MHz.
* -1 is returned for an out of range channel.
*
* Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
*
* @param channel input channel number
* @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz
*
* @return Returns a frequency in MHz
*
* @see WF_CHAN_FACTOR_2_4_G
* @see WF_CHAN_FACTOR_5_G
*/
extern int wf_channel2mhz(uint channel, uint start_factor);
/**
* Returns the chanspec 80Mhz channel corresponding to the following input
* parameters
*
* primary_channel - primary 20Mhz channel
* center_channel - center frequecny of the 80Mhz channel
*
* The center_channel can be one of {42, 58, 106, 122, 138, 155}
*
* returns INVCHANSPEC in case of error
*/
extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel);
/**
* Convert ctl chan and bw to chanspec
*
* @param ctl_ch channel
* @param bw bandwidth
*
* @return > 0 if successful or 0 otherwise
*
*/
extern uint16 wf_channel2chspec(uint ctl_ch, uint bw);
extern uint wf_channel2freq(uint channel);
extern uint wf_freq2channel(uint freq);
/*
* Returns the 80+80 MHz chanspec corresponding to the following input parameters
*
* primary_20mhz - Primary 20 MHz channel
* chan0_80MHz - center channel number of one frequency segment
* chan1_80MHz - center channel number of the other frequency segment
*
* Parameters chan0_80MHz and chan1_80MHz are channel numbers in {42, 58, 106, 122, 138, 155}.
* The primary channel must be contained in one of the 80MHz channels. This routine
* will determine which frequency segment is the primary 80 MHz segment.
*
* Returns INVCHANSPEC in case of error.
*
* Refer to IEEE802.11ac section 22.3.14 "Channelization".
*/
extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz,
uint8 chan0_80Mhz, uint8 chan1_80Mhz);
#endif
/*
* Returns the primary 80 Mhz channel for the provided chanspec
*
* chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
*
* returns -1 in case the provided channel is 20/40 Mhz chanspec
*/
extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec);
/*
* Returns the secondary 80 Mhz channel for the provided chanspec
*
* chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
*
* returns -1 in case the provided channel is 20/40 Mhz chanspec
*/
extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec);
/*
* This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
*/
extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec);
#ifdef WL11AC_80P80
/*
* This function returns the centre chanel for the given chanspec.
* In case of 80+80 chanspec it returns the primary 80 Mhz centre channel
*/
extern uint8 wf_chspec_channel(chanspec_t chspec);
#endif
#endif /* _bcmwifi_channels_h_ */

View File

@ -11,30 +11,50 @@
#ifdef __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define WL_RATESET_SZ_DSSS 4
#define WL_RATESET_SZ_OFDM 8
#define WL_RATESET_SZ_HT_MCS 8
#define WL_RATESET_SZ_VHT_MCS 10
#if defined(WLPROPRIETARY_11N_RATES)
#define WL_RATESET_SZ_HT_MCS WL_RATESET_SZ_VHT_MCS
#else
#define WL_RATESET_SZ_HT_MCS 8
#endif
#define WL_RATESET_SZ_HT_IOCTL 8 /* MAC histogram, compatibility with wl utility */
#define WL_TX_CHAINS_MAX 3
#define WL_RATE_DISABLED (-128)
#define WL_RATE_DISABLED (-128) /* Power value corresponding to unsupported rate */
/* Transmit channel bandwidths */
typedef enum wl_tx_bw {
WL_TX_BW_20,
WL_TX_BW_40,
WL_TX_BW_80,
WL_TX_BW_20IN40,
WL_TX_BW_20IN80,
WL_TX_BW_40IN80
WL_TX_BW_40IN80,
WL_TX_BW_160,
WL_TX_BW_20IN160,
WL_TX_BW_40IN160,
WL_TX_BW_80IN160,
WL_TX_BW_ALL,
WL_TX_BW_8080,
WL_TX_BW_8080CHAN2,
WL_TX_BW_20IN8080,
WL_TX_BW_40IN8080,
WL_TX_BW_80IN8080
} wl_tx_bw_t;
/*
* Transmit modes.
* Not all modes are listed here, only those required for disambiguation. e.g. SPEXP is not listed
*/
typedef enum wl_tx_mode {
WL_TX_MODE_NONE,
WL_TX_MODE_STBC,
@ -44,7 +64,7 @@ typedef enum wl_tx_mode {
} wl_tx_mode_t;
/* Number of transmit chains */
typedef enum wl_tx_chains {
WL_TX_CHAINS_1 = 1,
WL_TX_CHAINS_2,
@ -52,7 +72,7 @@ typedef enum wl_tx_chains {
} wl_tx_chains_t;
/* Number of transmit streams */
typedef enum wl_tx_nss {
WL_TX_NSS_1 = 1,
WL_TX_NSS_2,
@ -61,9 +81,12 @@ typedef enum wl_tx_nss {
typedef enum clm_rates {
/************
* 1 chain *
************
*/
/* 1 Stream */
WL_RATE_1X1_DSSS_1 = 0,
WL_RATE_1X1_DSSS_2 = 1,
WL_RATE_1X1_DSSS_5_5 = 2,
@ -99,9 +122,12 @@ typedef enum clm_rates {
WL_RATE_1X1_VHT9SS1 = 21,
/************
* 2 chains *
************
*/
/* 1 Stream expanded + 1 */
WL_RATE_1X2_DSSS_1 = 22,
WL_RATE_1X2_DSSS_2 = 23,
WL_RATE_1X2_DSSS_5_5 = 24,
@ -136,7 +162,7 @@ typedef enum clm_rates {
WL_RATE_1X2_VHT8SS1 = 42,
WL_RATE_1X2_VHT9SS1 = 43,
/* 2 Streams */
WL_RATE_2X2_STBC_MCS0 = 44,
WL_RATE_2X2_STBC_MCS1 = 45,
WL_RATE_2X2_STBC_MCS2 = 46,
@ -177,9 +203,12 @@ typedef enum clm_rates {
WL_RATE_2X2_VHT8SS2 = 62,
WL_RATE_2X2_VHT9SS2 = 63,
/************
* 3 chains *
************
*/
/* 1 Stream expanded + 2 */
WL_RATE_1X3_DSSS_1 = 64,
WL_RATE_1X3_DSSS_2 = 65,
WL_RATE_1X3_DSSS_5_5 = 66,
@ -214,7 +243,7 @@ typedef enum clm_rates {
WL_RATE_1X3_VHT8SS1 = 84,
WL_RATE_1X3_VHT9SS1 = 85,
/* 2 Streams expanded + 1 */
WL_RATE_2X3_STBC_MCS0 = 86,
WL_RATE_2X3_STBC_MCS1 = 87,
WL_RATE_2X3_STBC_MCS2 = 88,
@ -255,7 +284,7 @@ typedef enum clm_rates {
WL_RATE_2X3_VHT8SS2 = 104,
WL_RATE_2X3_VHT9SS2 = 105,
/* 3 Streams */
WL_RATE_3X3_SDM_MCS16 = 106,
WL_RATE_3X3_SDM_MCS17 = 107,
WL_RATE_3X3_SDM_MCS18 = 108,
@ -277,9 +306,12 @@ typedef enum clm_rates {
WL_RATE_3X3_VHT9SS3 = 115,
/****************************
* TX Beamforming, 2 chains *
****************************
*/
/* 1 Stream expanded + 1 */
WL_RATE_1X2_TXBF_OFDM_6 = 116,
WL_RATE_1X2_TXBF_OFDM_9 = 117,
@ -310,7 +342,7 @@ typedef enum clm_rates {
WL_RATE_1X2_TXBF_VHT8SS1 = 132,
WL_RATE_1X2_TXBF_VHT9SS1 = 133,
/* 2 Streams */
WL_RATE_2X2_TXBF_SDM_MCS8 = 134,
WL_RATE_2X2_TXBF_SDM_MCS9 = 135,
@ -331,9 +363,12 @@ typedef enum clm_rates {
WL_RATE_2X2_TXBF_VHT7SS2 = 141,
/****************************
* TX Beamforming, 3 chains *
****************************
*/
/* 1 Stream expanded + 2 */
WL_RATE_1X3_TXBF_OFDM_6 = 142,
WL_RATE_1X3_TXBF_OFDM_9 = 143,
@ -364,7 +399,7 @@ typedef enum clm_rates {
WL_RATE_1X3_TXBF_VHT8SS1 = 158,
WL_RATE_1X3_TXBF_VHT9SS1 = 159,
/* 2 Streams expanded + 1 */
WL_RATE_2X3_TXBF_SDM_MCS8 = 160,
WL_RATE_2X3_TXBF_SDM_MCS9 = 161,
@ -386,7 +421,7 @@ typedef enum clm_rates {
WL_RATE_2X3_TXBF_VHT8SS2 = 168,
WL_RATE_2X3_TXBF_VHT9SS2 = 169,
/* 3 Streams */
WL_RATE_3X3_TXBF_SDM_MCS16 = 170,
WL_RATE_3X3_TXBF_SDM_MCS17 = 171,
@ -407,11 +442,11 @@ typedef enum clm_rates {
WL_RATE_3X3_TXBF_VHT7SS3 = 177
} clm_rates_t;
/* Number of rate codes */
#define WL_NUMRATES 178
#ifdef __cplusplus
}
#endif
#endif /* __cplusplus */
#endif
#endif /* _bcmwifi_rates_h_ */

View File

@ -0,0 +1,45 @@
/*
* Definitions for nl80211 vendor command/event access to host driver
*
* $Copyright Open Broadcom Corporation$
*
* $Id: brcm_nl80211.h 487126 2014-06-24 23:06:12Z $
*
*/
#ifndef _brcm_nl80211_h_
#define _brcm_nl80211_h_
#define OUI_BRCM 0x001018
enum wl_vendor_subcmd {
BRCM_VENDOR_SCMD_UNSPEC,
BRCM_VENDOR_SCMD_PRIV_STR
};
struct bcm_nlmsg_hdr {
uint cmd; /* common ioctl definition */
uint len; /* expected return buffer length */
uint offset; /* user buffer offset */
uint set; /* get or set request optional */
uint magic; /* magic number for verification */
};
enum bcmnl_attrs {
BCM_NLATTR_UNSPEC,
BCM_NLATTR_LEN,
BCM_NLATTR_DATA,
__BCM_NLATTR_AFTER_LAST,
BCM_NLATTR_MAX = __BCM_NLATTR_AFTER_LAST - 1
};
struct nl_prv_data {
int err; /* return result */
void *data; /* ioctl return buffer pointer */
uint len; /* ioctl return buffer length */
struct bcm_nlmsg_hdr *nlioc; /* bcm_nlmsg_hdr header pointer */
};
#endif /* _brcm_nl80211_h_ */

View File

@ -0,0 +1,97 @@
/*
* Initialization and support routines for self-booting compressed image.
*
* $Copyright Open Broadcom Corporation$
*
* $Id: circularbuf.h 452258 2014-01-29 19:17:57Z $
*/
#ifndef __CIRCULARBUF_H_INCLUDED__
#define __CIRCULARBUF_H_INCLUDED__
#include <osl.h>
#include <typedefs.h>
#include <bcmendian.h>
/* Enumerations of return values provided by MsgBuf implementation */
typedef enum {
CIRCULARBUF_FAILURE = -1,
CIRCULARBUF_SUCCESS
} circularbuf_ret_t;
/* Core circularbuf circular buffer structure */
typedef struct circularbuf_s
{
uint16 depth; /* Depth of circular buffer */
uint16 r_ptr; /* Read Ptr */
uint16 w_ptr; /* Write Ptr */
uint16 e_ptr; /* End Ptr */
uint16 wp_ptr; /* wp_ptr/pending - scheduled for DMA. But, not yet complete. */
uint16 rp_ptr; /* rp_ptr/pending - scheduled for DMA. But, not yet complete. */
uint8 *buf_addr;
void *mb_ctx;
void (*mb_ring_bell)(void *ctx);
} circularbuf_t;
#define CBUF_ERROR_VAL 0x00000001 /* Error level tracing */
#define CBUF_TRACE_VAL 0x00000002 /* Function level tracing */
#define CBUF_INFORM_VAL 0x00000004 /* debug level tracing */
extern int cbuf_msg_level;
#define CBUF_ERROR(args) do {if (cbuf_msg_level & CBUF_ERROR_VAL) printf args;} while (0)
#define CBUF_TRACE(args) do {if (cbuf_msg_level & CBUF_TRACE_VAL) printf args;} while (0)
#define CBUF_INFO(args) do {if (cbuf_msg_level & CBUF_INFORM_VAL) printf args;} while (0)
#define CIRCULARBUF_START(x) ((x)->buf_addr)
#define CIRCULARBUF_WRITE_PTR(x) ((x)->w_ptr)
#define CIRCULARBUF_READ_PTR(x) ((x)->r_ptr)
#define CIRCULARBUF_END_PTR(x) ((x)->e_ptr)
#define circularbuf_debug_print(handle) \
CBUF_INFO(("%s:%d:\t%p rp=%4d r=%4d wp=%4d w=%4d e=%4d\n", \
__FUNCTION__, __LINE__, \
(void *) CIRCULARBUF_START(handle), \
(int) (handle)->rp_ptr, (int) (handle)->r_ptr, \
(int) (handle)->wp_ptr, (int) (handle)->w_ptr, \
(int) (handle)->e_ptr));
/* Callback registered by application/mail-box with the circularbuf implementation.
* This will be invoked by the circularbuf implementation when write is complete and
* ready for informing the peer
*/
typedef void (*mb_ring_t)(void *ctx);
/* Public Functions exposed by circularbuf */
void
circularbuf_init(circularbuf_t *handle, void *buf_base_addr, uint16 total_buf_len);
void
circularbuf_register_cb(circularbuf_t *handle, mb_ring_t mb_ring_func, void *ctx);
/* Write Functions */
void *
circularbuf_reserve_for_write(circularbuf_t *handle, uint16 size);
void
circularbuf_write_complete(circularbuf_t *handle, uint16 bytes_written);
/* Read Functions */
void *
circularbuf_get_read_ptr(circularbuf_t *handle, uint16 *avail_len);
circularbuf_ret_t
circularbuf_read_complete(circularbuf_t *handle, uint16 bytes_read);
/*
* circularbuf_get_read_ptr() updates rp_ptr by the amount that the consumer
* is supposed to read. The consumer may not read the entire amount.
* In such a case, circularbuf_revert_rp_ptr() call follows a corresponding
* circularbuf_get_read_ptr() call to revert the rp_ptr back to
* the point till which data has actually been processed.
* It is not valid if it is preceded by multiple get_read_ptr() calls
*/
circularbuf_ret_t
circularbuf_revert_rp_ptr(circularbuf_t *handle, uint16 bytes);
#endif /* __CIRCULARBUF_H_INCLUDED__ */

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: dhdioctl.h 419132 2013-08-19 21:33:05Z $
* $Id: dhdioctl.h 438755 2013-11-22 23:20:40Z $
*/
#ifndef _dhdioctl_h_
@ -35,7 +35,8 @@ typedef struct dhd_ioctl {
/* Underlying BUS definition */
enum {
BUS_TYPE_USB = 0, /* for USB dongles */
BUS_TYPE_SDIO /* for SDIO dongles */
BUS_TYPE_SDIO, /* for SDIO dongles */
BUS_TYPE_PCIE /* for PCIE dongles */
};
/* per-driver magic numbers */
@ -67,7 +68,11 @@ enum {
#define DHD_GLOM_VAL 0x0400
#define DHD_EVENT_VAL 0x0800
#define DHD_BTA_VAL 0x1000
#if 0 && (NDISVER >= 0x0630) && 1
#define DHD_SCAN_VAL 0x2000
#else
#define DHD_ISCAN_VAL 0x2000
#endif
#define DHD_ARPOE_VAL 0x4000
#define DHD_REORDER_VAL 0x8000
#define DHD_NOCHECKDIED_VAL 0x20000 /* UTF WAR */

View File

@ -10,21 +10,21 @@
#define EPI_MAJOR_VERSION 1
#define EPI_MINOR_VERSION 88
#define EPI_MINOR_VERSION 201
#define EPI_RC_NUMBER 45
#define EPI_RC_NUMBER 34
#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
#define EPI_VERSION 1, 88, 45, 0
#define EPI_VERSION 1, 201, 34, 0
#define EPI_VERSION_NUM 0x01582d00
#define EPI_VERSION_NUM 0x01c92200
#define EPI_VERSION_DEV 1.88.45
#define EPI_VERSION_DEV 1.201.34
/* Driver Version String, ASCII, 32 chars max */
#define EPI_VERSION_STR "1.201.34.1 (r491657)"
#define EPI_VERSION_STR "1.88.45.3 (r420671)"
#endif
#endif /* _epivers_h_ */

View File

@ -24,7 +24,7 @@
#define EPI_VERSION_DEV @EPI_VERSION_DEV@
/* Driver Version String, ASCII, 32 chars max */
#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@)"
#endif
#endif /* _epivers_h_ */

View File

@ -4,7 +4,7 @@
#
# Epivers.h version support svn/sparse/gclient workspaces
#
# $Id: epivers.sh 363310 2012-10-17 03:37:57Z $
# $Id: epivers.sh 389103 2013-03-05 17:24:49Z $
#
# Version generation works off of svn property HeadURL, if
# not set it keys its versions from current svn workspace or
@ -45,9 +45,10 @@ if [ -f epivers.h ]; then
else # epivers.h doesn't exist
NULL="/dev/null"
svncmd="svn --non-interactive"
SVNCMD=${SVNCMD:-"svn --non-interactive"}
SRCBASE=${SRCBASE:-..}
NULL=/dev/null
[ -z "$VERBOSE" ] || NULL=/dev/stderr
# Check for the in file, if not there we're in the wrong directory
if [ ! -f epivers.h.in ]; then
@ -56,7 +57,7 @@ else # epivers.h doesn't exist
fi
# Following SVNURL should be expanded on checkout
SVNURL='$HeadURL: http://svn.sj.broadcom.com/svn/wlansvn/proj/tags/DHD/DHD_REL_1_88_45/src/include/epivers.sh $'
SVNURL='$HeadURL: http://svn.sj.broadcom.com/svn/wlansvn/proj/tags/DHD/DHD_REL_1_201_34/src/include/epivers.sh $'
# .gclient_info is created by gclient checkout/sync steps
# and contains "DEPS='<deps-url1> <deps-url2> ..." entry
@ -88,7 +89,7 @@ else # epivers.h doesn't exist
if echo "$SVNURL" | egrep -vq 'HeadURL.*epivers.sh.*|http://.*/DEPS'; then
[ -n "$VERBOSE" ] && \
echo "DBG: SVN URL ($SVNURL) wasn't expanded. Getting it from svn info"
SVNURL=$($svncmd info epivers.sh 2> $NULL | egrep "^URL:")
SVNURL=$($SVNCMD info epivers.sh 2> $NULL | egrep "^URL:")
fi
if echo "${TAG}" | grep -q "_BRANCH_\|_TWIG_"; then
@ -131,7 +132,7 @@ else # epivers.h doesn't exist
[ -n "$VERBOSE" ] && \
echo "DBG: Fetching $GETCOMPVER from trunk"
$svncmd export -q \
$SVNCMD export -q \
^/proj/trunk/src/tools/build/${GETCOMPVER} \
${GETCOMPVER} 2> $NULL
@ -304,7 +305,7 @@ else # epivers.h doesn't exist
fi
# Finally get version control revision number of <SRCBASE> (if any)
vc_version_num=$($svncmd info ${SRCBASE} 2> $NULL | awk -F': ' '/^Last Changed Rev: /{printf "%s", $2}')
vc_version_num=$($SVNCMD info ${SRCBASE} 2> $NULL | awk -F': ' '/^Last Changed Rev: /{printf "%s", $2}')
# OK, go do it
echo "maj=${maj}, min=${min}, rc=${rcnum}, inc=${incremental}, build=${build}"

View File

@ -0,0 +1,70 @@
/*
* HND arm trap handling.
*
* $Copyright Open Broadcom Corporation$
*
* $Id: hnd_armtrap.h 470663 2014-04-16 00:24:43Z $
*/
#ifndef _hnd_armtrap_h_
#define _hnd_armtrap_h_
/* ARM trap handling */
/* Trap types defined by ARM (see arminc.h) */
/* Trap locations in lo memory */
#define TRAP_STRIDE 4
#define FIRST_TRAP TR_RST
#define LAST_TRAP (TR_FIQ * TRAP_STRIDE)
#if defined(__ARM_ARCH_4T__)
#define MAX_TRAP_TYPE (TR_FIQ + 1)
#elif defined(__ARM_ARCH_7M__)
#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS)
#endif /* __ARM_ARCH_7M__ */
/* The trap structure is defined here as offsets for assembly */
#define TR_TYPE 0x00
#define TR_EPC 0x04
#define TR_CPSR 0x08
#define TR_SPSR 0x0c
#define TR_REGS 0x10
#define TR_REG(n) (TR_REGS + (n) * 4)
#define TR_SP TR_REG(13)
#define TR_LR TR_REG(14)
#define TR_PC TR_REG(15)
#define TRAP_T_SIZE 80
#ifndef _LANGUAGE_ASSEMBLY
#include <typedefs.h>
typedef struct _trap_struct {
uint32 type;
uint32 epc;
uint32 cpsr;
uint32 spsr;
uint32 r0; /* a1 */
uint32 r1; /* a2 */
uint32 r2; /* a3 */
uint32 r3; /* a4 */
uint32 r4; /* v1 */
uint32 r5; /* v2 */
uint32 r6; /* v3 */
uint32 r7; /* v4 */
uint32 r8; /* v5 */
uint32 r9; /* sb/v6 */
uint32 r10; /* sl/v7 */
uint32 r11; /* fp/v8 */
uint32 r12; /* ip */
uint32 r13; /* sp */
uint32 r14; /* lr */
uint32 pc; /* r15 */
} trap_t;
#endif /* !_LANGUAGE_ASSEMBLY */
#endif /* _hnd_armtrap_h_ */

View File

@ -0,0 +1,59 @@
/*
* Console support for RTE - for host use only.
*
* $Copyright Open Broadcom Corporation$
*
* $Id: hnd_cons.h 473343 2014-04-29 01:45:22Z $
*/
#ifndef _hnd_cons_h_
#define _hnd_cons_h_
#include <typedefs.h>
#include <siutils.h>
#define CBUF_LEN (128)
#define LOG_BUF_LEN 1024
#ifdef BOOTLOADER_CONSOLE_OUTPUT
#undef RWL_MAX_DATA_LEN
#undef CBUF_LEN
#undef LOG_BUF_LEN
#define RWL_MAX_DATA_LEN (4 * 1024 + 8)
#define CBUF_LEN (RWL_MAX_DATA_LEN + 64)
#define LOG_BUF_LEN (16 * 1024)
#endif
typedef struct {
uint32 buf; /* Can't be pointer on (64-bit) hosts */
uint buf_size;
uint idx;
uint out_idx; /* output index */
} hnd_log_t;
typedef struct {
/* Virtual UART
* When there is no UART (e.g. Quickturn), the host should write a complete
* input line directly into cbuf and then write the length into vcons_in.
* This may also be used when there is a real UART (at risk of conflicting with
* the real UART). vcons_out is currently unused.
*/
volatile uint vcons_in;
volatile uint vcons_out;
/* Output (logging) buffer
* Console output is written to a ring buffer log_buf at index log_idx.
* The host may read the output when it sees log_idx advance.
* Output will be lost if the output wraps around faster than the host polls.
*/
hnd_log_t log;
/* Console input line buffer
* Characters are read one at a time into cbuf until <CR> is received, then
* the buffer is processed as a command line. Also used for virtual UART.
*/
uint cbuf_idx;
char cbuf[CBUF_LEN];
} hnd_cons_t;
#endif /* _hnd_cons_h_ */

View File

@ -0,0 +1,186 @@
/*
* HND generic packet pool operation primitives
*
* $Copyright Open Broadcom Corporation$
*
* $Id: $
*/
#ifndef _hnd_pktpool_h_
#define _hnd_pktpool_h_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BCMPKTPOOL
#define POOL_ENAB(pool) ((pool) && (pool)->inited)
#define SHARED_POOL (pktpool_shared)
#else /* BCMPKTPOOL */
#define POOL_ENAB(bus) 0
#define SHARED_POOL ((struct pktpool *)NULL)
#endif /* BCMPKTPOOL */
#ifdef BCMFRAGPOOL
#define SHARED_FRAG_POOL (pktpool_shared_lfrag)
#endif
#define SHARED_RXFRAG_POOL (pktpool_shared_rxlfrag)
#ifndef PKTPOOL_LEN_MAX
#define PKTPOOL_LEN_MAX 40
#endif /* PKTPOOL_LEN_MAX */
#define PKTPOOL_CB_MAX 3
/* forward declaration */
struct pktpool;
typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg);
typedef struct {
pktpool_cb_t cb;
void *arg;
} pktpool_cbinfo_t;
/* call back fn extension to populate host address in pool pkt */
typedef int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg1, void* pkt, bool arg2);
typedef struct {
pktpool_cb_extn_t cb;
void *arg;
} pktpool_cbextn_info_t;
#ifdef BCMDBG_POOL
/* pkt pool debug states */
#define POOL_IDLE 0
#define POOL_RXFILL 1
#define POOL_RXDH 2
#define POOL_RXD11 3
#define POOL_TXDH 4
#define POOL_TXD11 5
#define POOL_AMPDU 6
#define POOL_TXENQ 7
typedef struct {
void *p;
uint32 cycles;
uint32 dur;
} pktpool_dbg_t;
typedef struct {
uint8 txdh; /* tx to host */
uint8 txd11; /* tx to d11 */
uint8 enq; /* waiting in q */
uint8 rxdh; /* rx from host */
uint8 rxd11; /* rx from d11 */
uint8 rxfill; /* dma_rxfill */
uint8 idle; /* avail in pool */
} pktpool_stats_t;
#endif /* BCMDBG_POOL */
typedef struct pktpool {
bool inited; /* pktpool_init was successful */
uint8 type; /* type of lbuf: basic, frag, etc */
uint8 id; /* pktpool ID: index in registry */
bool istx; /* direction: transmit or receive data path */
void * freelist; /* free list: see PKTNEXTFREE(), PKTSETNEXTFREE() */
uint16 avail; /* number of packets in pool's free list */
uint16 len; /* number of packets managed by pool */
uint16 maxlen; /* maximum size of pool <= PKTPOOL_LEN_MAX */
uint16 plen; /* size of pkt buffer, excluding lbuf|lbuf_frag */
bool empty;
uint8 cbtoggle;
uint8 cbcnt;
uint8 ecbcnt;
bool emptycb_disable;
pktpool_cbinfo_t *availcb_excl;
pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX];
pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX];
pktpool_cbextn_info_t cbext;
pktpool_cbextn_info_t rxcplidfn;
#ifdef BCMDBG_POOL
uint8 dbg_cbcnt;
pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX];
uint16 dbg_qlen;
pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1];
#endif
pktpool_cbinfo_t dmarxfill;
} pktpool_t;
extern pktpool_t *pktpool_shared;
#ifdef BCMFRAGPOOL
extern pktpool_t *pktpool_shared_lfrag;
#endif
extern pktpool_t *pktpool_shared_rxlfrag;
/* Incarnate a pktpool registry. On success returns total_pools. */
extern int pktpool_attach(osl_t *osh, uint32 total_pools);
extern int pktpool_dettach(osl_t *osh); /* Relinquish registry */
extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx, uint8 type);
extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp);
extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal);
extern void* pktpool_get(pktpool_t *pktp);
extern void pktpool_free(pktpool_t *pktp, void *p);
extern int pktpool_add(pktpool_t *pktp, void *p);
extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp);
extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb);
extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen);
extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen);
extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable);
extern bool pktpool_emptycb_disabled(pktpool_t *pktp);
extern int pktpool_hostaddr_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg1);
extern int pktpool_rxcplid_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg);
extern void pktpool_invoke_dmarxfill(pktpool_t *pktp);
extern int pkpool_haddr_avail_register_cb(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
#define POOLPTR(pp) ((pktpool_t *)(pp))
#define POOLID(pp) (POOLPTR(pp)->id)
#define POOLSETID(pp, ppid) (POOLPTR(pp)->id = (ppid))
#define pktpool_len(pp) (POOLPTR(pp)->len)
#define pktpool_avail(pp) (POOLPTR(pp)->avail)
#define pktpool_plen(pp) (POOLPTR(pp)->plen)
#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen)
/*
* ----------------------------------------------------------------------------
* A pool ID is assigned with a pkt pool during pool initialization. This is
* done by maintaining a registry of all initialized pools, and the registry
* index at which the pool is registered is used as the pool's unique ID.
* ID 0 is reserved and is used to signify an invalid pool ID.
* All packets henceforth allocated from a pool will be tagged with the pool's
* unique ID. Packets allocated from the heap will use the reserved ID = 0.
* Packets with non-zero pool id signify that they were allocated from a pool.
* A maximum of 15 pools are supported, allowing a 4bit pool ID to be used
* in place of a 32bit pool pointer in each packet.
* ----------------------------------------------------------------------------
*/
#define PKTPOOL_INVALID_ID (0)
#define PKTPOOL_MAXIMUM_ID (15)
/* Registry of pktpool(s) */
extern pktpool_t *pktpools_registry[PKTPOOL_MAXIMUM_ID + 1];
/* Pool ID to/from Pool Pointer converters */
#define PKTPOOL_ID2PTR(id) (pktpools_registry[id])
#define PKTPOOL_PTR2ID(pp) (POOLID(pp))
#ifdef BCMDBG_POOL
extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
extern int pktpool_start_trigger(pktpool_t *pktp, void *p);
extern int pktpool_dbg_dump(pktpool_t *pktp);
extern int pktpool_dbg_notify(pktpool_t *pktp);
extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats);
#endif /* BCMDBG_POOL */
#ifdef __cplusplus
}
#endif
#endif /* _hnd_pktpool_h_ */

View File

@ -0,0 +1,168 @@
/*
* HND generic pktq operation primitives
*
* $Copyright Open Broadcom Corporation$
*
* $Id: $
*/
#ifndef _hnd_pktq_h_
#define _hnd_pktq_h_
#ifdef __cplusplus
extern "C" {
#endif
/* osl multi-precedence packet queue */
#define PKTQ_LEN_MAX 0xFFFF /* Max uint16 65535 packets */
#ifndef PKTQ_LEN_DEFAULT
#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */
#endif
#ifndef PKTQ_MAX_PREC
#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */
#endif
typedef struct pktq_prec {
void *head; /* first packet to dequeue */
void *tail; /* last packet to dequeue */
uint16 len; /* number of queued packets */
uint16 max; /* maximum number of queued packets */
} pktq_prec_t;
#ifdef PKTQ_LOG
typedef struct {
uint32 requested; /* packets requested to be stored */
uint32 stored; /* packets stored */
uint32 saved; /* packets saved,
because a lowest priority queue has given away one packet
*/
uint32 selfsaved; /* packets saved,
because an older packet from the same queue has been dropped
*/
uint32 full_dropped; /* packets dropped,
because pktq is full with higher precedence packets
*/
uint32 dropped; /* packets dropped because pktq per that precedence is full */
uint32 sacrificed; /* packets dropped,
in order to save one from a queue of a highest priority
*/
uint32 busy; /* packets droped because of hardware/transmission error */
uint32 retry; /* packets re-sent because they were not received */
uint32 ps_retry; /* packets retried again prior to moving power save mode */
uint32 suppress; /* packets which were suppressed and not transmitted */
uint32 retry_drop; /* packets finally dropped after retry limit */
uint32 max_avail; /* the high-water mark of the queue capacity for packets -
goes to zero as queue fills
*/
uint32 max_used; /* the high-water mark of the queue utilisation for packets -
increases with use ('inverse' of max_avail)
*/
uint32 queue_capacity; /* the maximum capacity of the queue */
uint32 rtsfail; /* count of rts attempts that failed to receive cts */
uint32 acked; /* count of packets sent (acked) successfully */
uint32 txrate_succ; /* running total of phy rate of packets sent successfully */
uint32 txrate_main; /* running totoal of primary phy rate of all packets */
uint32 throughput; /* actual data transferred successfully */
uint32 airtime; /* cumulative total medium access delay in useconds */
uint32 _logtime; /* timestamp of last counter clear */
} pktq_counters_t;
typedef struct {
uint32 _prec_log;
pktq_counters_t* _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */
} pktq_log_t;
#endif /* PKTQ_LOG */
#define PKTQ_COMMON \
uint16 num_prec; /* number of precedences in use */ \
uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \
uint16 max; /* total max packets */ \
uint16 len; /* total number of packets */
/* multi-priority pkt queue */
struct pktq {
PKTQ_COMMON
/* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
struct pktq_prec q[PKTQ_MAX_PREC];
#ifdef PKTQ_LOG
pktq_log_t* pktqlog;
#endif
};
/* simple, non-priority pkt queue */
struct spktq {
PKTQ_COMMON
/* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
struct pktq_prec q[1];
};
#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
/* fn(pkt, arg). return true if pkt belongs to if */
typedef bool (*ifpkt_cb_t)(void*, int);
/* operations on a specific precedence in packet queue */
#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
#define pktq_pmax(pq, prec) ((pq)->q[prec].max)
#define pktq_plen(pq, prec) ((pq)->q[prec].len)
#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len)
#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max)
#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0)
#define pktq_ppeek(pq, prec) ((pq)->q[prec].head)
#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail)
extern void pktq_append(struct pktq *pq, int prec, struct spktq *list);
extern void pktq_prepend(struct pktq *pq, int prec, struct spktq *list);
extern void *pktq_penq(struct pktq *pq, int prec, void *p);
extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
extern void *pktq_pdeq(struct pktq *pq, int prec);
extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg);
extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
/* Empty the queue at particular precedence level */
extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir,
ifpkt_cb_t fn, int arg);
/* Remove a specified packet from its queue */
extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
/* operations on a set of precedences in packet queue */
extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
/* operations on packet queue as a whole */
#define pktq_len(pq) ((int)(pq)->len)
#define pktq_max(pq) ((int)(pq)->max)
#define pktq_avail(pq) ((int)((pq)->max - (pq)->len))
#define pktq_full(pq) ((pq)->len >= (pq)->max)
#define pktq_empty(pq) ((pq)->len == 0)
/* operations for single precedence queues */
#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p))
#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0)
#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
#define pktqflush(osh, pq) pktq_flush(osh, ((struct pktq *)(void *)pq), TRUE, NULL, 0)
#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len)
extern void pktq_init(struct pktq *pq, int num_prec, int max_len);
extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
/* prec_out may be NULL if caller is not interested in return value */
extern void *pktq_deq(struct pktq *pq, int *prec_out);
extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
extern void *pktq_peek(struct pktq *pq, int *prec_out);
extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg);
#ifdef __cplusplus
}
#endif
#endif /* _hnd_pktq_h_ */

View File

@ -3,16 +3,21 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: hndpmu.h 385540 2013-02-15 23:14:50Z $
* $Id: hndpmu.h 471127 2014-04-17 23:24:23Z $
*/
#ifndef _hndpmu_h_
#define _hndpmu_h_
#include <typedefs.h>
#include <osl_decl.h>
#include <siutils.h>
extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on);
extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on, uint32* min_res_mask);
extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength);
extern void si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear);
extern void si_pmu_slow_clk_reinit(si_t *sih, osl_t *osh);
#endif /* _hndpmu_h_ */

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: hndsoc.h 365041 2012-10-26 09:10:35Z $
* $Id: hndsoc.h 473238 2014-04-28 19:14:56Z $
*/
#ifndef _HNDSOC_H
@ -29,7 +29,9 @@
#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */
#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */
#ifndef SI_MAXCORES
#define SI_MAXCORES 32 /* NorthStar has more cores */
#endif /* SI_MAXCORES */
#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */
#define SI_FASTRAM_SWAPPED 0x19800000
@ -53,6 +55,7 @@
#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */
#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */
#define SI_SFLASH 0x14000000
#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */
#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */
#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */
@ -62,7 +65,6 @@
#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2
* (2 ZettaBytes), high 32 bits
*/
/* core codes */
#define NODEV_CORE_ID 0x700 /* Invalid coreid */
#define CC_CORE_ID 0x800 /* chipcommon core */
@ -125,6 +127,8 @@
#define PCIE2_CORE_ID 0x83c /* pci express Gen2 core */
#define USB30D_CORE_ID 0x83d /* usb 3.0 device core */
#define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */
#define GCI_CORE_ID 0x840 /* GCI Core */
#define M2MDMA_CORE_ID 0x844 /* memory to memory dma */
#define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */
#define AXI_CORE_ID 0x301 /* AXI/GPV core ID */
#define EROM_CORE_ID 0x366 /* EROM core ID */
@ -163,12 +167,12 @@
#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */
#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */
#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */
#define NS_PCIEG2_CORE_REV_B0 0x7 /* NS-B0 PCIE Gen 2 core rev */
/* There are TWO constants on all HND chips: SI_ENUM_BASE above,
* and chipcommon being the first core:
*/
#define SI_CC_IDX 0
/* SOC Interconnect types (aka chip types) */
#define SOCI_SB 0
#define SOCI_AI 1
@ -201,6 +205,7 @@
* communicate w/PMU regarding clock control.
*/
#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */
#define SI_PWR_CTL_ST 0x1e8 /* For memory clock gating */
/* clk_ctl_st register */
#define CCS_FORCEALP 0x00000001 /* force ALP request */
@ -211,12 +216,16 @@
#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */
#define CCS_HQCLKREQ 0x00000040 /* HQ Clock Required */
#define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */
#define CCS_SECICLKREQ 0x00000100 /* SECI Clock Req */
#define CCS_ARMFASTCLOCKREQ 0x00000100 /* ARM CR4 fast clock request */
#define CCS_AVBCLKREQ 0x00000400 /* AVB Clock enable request */
#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */
#define CCS_ERSRC_REQ_SHIFT 8
#define CCS_ALPAVAIL 0x00010000 /* ALP is available */
#define CCS_HTAVAIL 0x00020000 /* HT is available */
#define CCS_BP_ON_APL 0x00040000 /* RO: Backplane is running on ALP clock */
#define CCS_BP_ON_HT 0x00080000 /* RO: Backplane is running on HT clock */
#define CCS_ARMFASTCLOCKSTATUS 0x01000000 /* Fast CPU clock is running */
#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */
#define CCS_ERSRC_STS_SHIFT 24
@ -251,9 +260,9 @@
#define SOC_KNLDEV_NORFLASH 0x00000002
#define SOC_KNLDEV_NANDFLASH 0x00000004
#ifndef _LANGUAGE_ASSEMBLY
#if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__)
int soc_boot_dev(void *sih);
int soc_knl_dev(void *sih);
#endif /* _LANGUAGE_ASSEMBLY */
#endif /* !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__) */
#endif /* _HNDSOC_H */

View File

@ -3,31 +3,45 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: linux_osl.h 411126 2013-07-05 01:22:09Z $
* $Id: linux_osl.h 491170 2014-07-15 06:23:58Z $
*/
#ifndef _linux_osl_h_
#define _linux_osl_h_
#include <typedefs.h>
#define DECLSPEC_ALIGN(x) __attribute__ ((aligned(x)))
/* Linux Kernel: File Operations: start */
extern void * osl_os_open_image(char * filename);
extern int osl_os_get_image_block(char * buf, int len, void * image);
extern void osl_os_close_image(void * image);
extern int osl_os_image_size(void *image);
/* Linux Kernel: File Operations: end */
#ifdef BCMDRIVER
/* OSL initialization */
#ifdef SHARED_OSL_CMN
extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag, void **osh_cmn);
#else
extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag);
#endif /* SHARED_OSL_CMN */
extern void osl_detach(osl_t *osh);
extern int osl_static_mem_init(osl_t *osh, void *adapter);
extern int osl_static_mem_deinit(osl_t *osh, void *adapter);
extern void osl_set_bus_handle(osl_t *osh, void *bus_handle);
extern void* osl_get_bus_handle(osl_t *osh);
#ifdef EXYNOS5433_PCIE_WAR
extern void exynos_pcie_set_l1_exit(void);
extern void exynos_pcie_clear_l1_exit(void);
#endif /* EXYNOS5433_PCIE_WAR */
/* Global ASSERT type */
extern uint32 g_assert_type;
/* ASSERT */
#if defined(BCMASSERT_LOG)
#define ASSERT(exp) \
do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
@ -39,13 +53,26 @@ extern void osl_assert(const char *exp, const char *file, int line);
#if GCC_VERSION > 30100
#define ASSERT(exp) do {} while (0)
#else
/* ASSERT could cause segmentation fault on GCC3.1, use empty instead */
#define ASSERT(exp)
#endif
#endif
#endif /* GCC_VERSION > 30100 */
#endif /* __GNUC__ */
#endif
/* bcm_prefetch_32B */
static inline void bcm_prefetch_32B(const uint8 *addr, const int cachelines_32B)
{
#if defined(BCM47XX_CA9) && (__LINUX_ARM_ARCH__ >= 5)
switch (cachelines_32B) {
case 4: __asm__ __volatile__("pld\t%a0" :: "p"(addr + 96) : "cc");
case 3: __asm__ __volatile__("pld\t%a0" :: "p"(addr + 64) : "cc");
case 2: __asm__ __volatile__("pld\t%a0" :: "p"(addr + 32) : "cc");
case 1: __asm__ __volatile__("pld\t%a0" :: "p"(addr + 0) : "cc");
}
#endif
}
/* microsecond delay */
#define OSL_DELAY(usec) osl_delay(usec)
extern void osl_delay(uint usec);
@ -59,7 +86,7 @@ extern void osl_sleep(uint ms);
extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size);
extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size);
/* PCI configuration space access macros */
#define OSL_PCI_READ_CONFIG(osh, offset, size) \
osl_pci_read_config((osh), (offset), (size))
#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \
@ -67,22 +94,30 @@ extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size);
extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size);
extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val);
/* PCI device bus # and slot # */
#define OSL_PCI_BUS(osh) osl_pci_bus(osh)
#define OSL_PCI_SLOT(osh) osl_pci_slot(osh)
#define OSL_PCIE_DOMAIN(osh) osl_pcie_domain(osh)
#define OSL_PCIE_BUS(osh) osl_pcie_bus(osh)
extern uint osl_pci_bus(osl_t *osh);
extern uint osl_pci_slot(osl_t *osh);
extern uint osl_pcie_domain(osl_t *osh);
extern uint osl_pcie_bus(osl_t *osh);
extern struct pci_dev *osl_pci_device(osl_t *osh);
/* Pkttag flag should be part of public information */
typedef struct {
bool pkttag;
bool mmbus;
pktfree_cb_fn_t tx_fn;
void *tx_ctx;
bool mmbus; /* Bus supports memory-mapped register accesses */
pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */
void *tx_ctx; /* Context to the callback function */
void *unused[3];
} osl_pubinfo_t;
extern void osl_flag_set(osl_t *osh, uint32 mask);
extern bool osl_is_flag_set(osl_t *osh, uint32 mask);
#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \
do { \
((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \
@ -90,86 +125,163 @@ typedef struct {
} while (0)
/* host/bus architecture-specific byte swap */
#define BUS_SWAP32(v) (v)
#define MALLOC(osh, size) osl_malloc((osh), (size))
#define MALLOCZ(osh, size) osl_mallocz((osh), (size))
#define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size))
#define MALLOCED(osh) osl_malloced((osh))
#define MEMORY_LEFTOVER(osh) osl_check_memleak(osh)
extern void *osl_malloc(osl_t *osh, uint size);
extern void *osl_mallocz(osl_t *osh, uint size);
extern void osl_mfree(osl_t *osh, void *addr, uint size);
extern uint osl_malloced(osl_t *osh);
extern uint osl_check_memleak(osl_t *osh);
#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC)
#define NATIVE_MFREE(osh, addr, size) kfree(addr)
#define MALLOC_FAILED(osh) osl_malloc_failed((osh))
extern uint osl_malloc_failed(osl_t *osh);
/* allocate/free shared (dma-able) consistent memory */
#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align()
#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \
osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
#define DMA_ALLOC_CONSISTENT_FORCE32(osh, size, align, tot, pap, dmah) \
osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
#define DMA_FREE_CONSISTENT_FORCE32(osh, va, size, pa, dmah) \
osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
extern uint osl_dma_consistent_align(void);
extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap);
extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa);
#define DMA_TX 1
#define DMA_RX 2
extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align,
uint *tot, dmaaddr_t *pap);
extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa);
/* map/unmap direction */
#define DMA_TX 1 /* TX direction for DMA */
#define DMA_RX 2 /* RX direction for DMA */
/* map/unmap shared (dma-able) memory */
#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \
osl_dma_unmap((osh), (pa), (size), (direction))
extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
extern dmaaddr_t osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
hnddma_seg_map_t *txp_dmah);
extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction);
/* API for DMA addressing capability */
#define OSL_DMADDRWIDTH(osh, addrwidth) ({BCM_REFERENCE(osh); BCM_REFERENCE(addrwidth);})
#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0)
#if (defined(BCM47XX_CA9) && defined(__ARM_ARCH_7A__))
extern void osl_cache_flush(void *va, uint size);
extern void osl_cache_inv(void *va, uint size);
extern void osl_prefetch(const void *ptr);
#define OSL_CACHE_FLUSH(va, len) osl_cache_flush((void *) va, len)
#define OSL_CACHE_INV(va, len) osl_cache_inv((void *) va, len)
#define OSL_PREFETCH(ptr) osl_prefetch(ptr)
#ifdef __ARM_ARCH_7A__
extern int osl_arch_is_coherent(void);
#define OSL_ARCH_IS_COHERENT() osl_arch_is_coherent()
#else
#define OSL_ARCH_IS_COHERENT() NULL
#endif /* __ARM_ARCH_7A__ */
#else
#define OSL_CACHE_FLUSH(va, len) BCM_REFERENCE(va)
#define OSL_CACHE_INV(va, len) BCM_REFERENCE(va)
#define OSL_PREFETCH(ptr) BCM_REFERENCE(ptr)
#define OSL_ARCH_IS_COHERENT() NULL
#endif
/* register access macros */
#if defined(BCMSDIO)
#include <bcmsdh.h>
#define OSL_WRITE_REG(osh, r, v) (bcmsdh_reg_write(NULL, (uintptr)(r), sizeof(*(r)), (v)))
#define OSL_READ_REG(osh, r) (bcmsdh_reg_read(NULL, (uintptr)(r), sizeof(*(r))))
#define OSL_WRITE_REG(osh, r, v) (bcmsdh_reg_write(osl_get_bus_handle(osh), \
(uintptr)(r), sizeof(*(r)), (v)))
#define OSL_READ_REG(osh, r) (bcmsdh_reg_read(osl_get_bus_handle(osh), \
(uintptr)(r), sizeof(*(r))))
#elif defined(BCM47XX_ACP_WAR)
extern void osl_pcie_rreg(osl_t *osh, ulong addr, void *v, uint size);
#define OSL_READ_REG(osh, r) \
({\
__typeof(*(r)) __osl_v; \
osl_pcie_rreg(osh, (uintptr)(r), (void *)&__osl_v, sizeof(*(r))); \
__osl_v; \
})
#endif
#if defined(BCM47XX_ACP_WAR)
#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;})
#define SELECT_BUS_READ(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); bus_op;})
#else
#if defined(BCMSDIO)
#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) if (((osl_pubinfo_t*)(osh))->mmbus) \
mmap_op else bus_op
#define SELECT_BUS_READ(osh, mmap_op, bus_op) (((osl_pubinfo_t*)(osh))->mmbus) ? \
mmap_op : bus_op
#else
#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;})
#define SELECT_BUS_READ(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;})
#endif
#endif /* BCM47XX_ACP_WAR */
#define OSL_ERROR(bcmerror) osl_error(bcmerror)
extern int osl_error(int bcmerror);
/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */
#define PKTBUFSZ 2048
#define OSH_NULL NULL
#include <linuxver.h>
#include <linux/kernel.h>
#include <linux/string.h>
/*
* BINOSL selects the slightly slower function-call-based binary compatible osl.
* Macros expand to calls to functions defined in linux_osl.c .
*/
#include <linuxver.h> /* use current 2.4.x calling conventions */
#include <linux/kernel.h> /* for vsn/printf's */
#include <linux/string.h> /* for mem*, str* */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29)
#define OSL_SYSUPTIME() ((uint32)jiffies_to_msecs(jiffies))
#else
#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ))
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29) */
#define printf(fmt, args...) printk(fmt , ## args)
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/kernel.h> /* for vsn/printf's */
#include <linux/string.h> /* for mem*, str* */
/* bcopy's: Linux kernel doesn't provide these (anymore) */
#define bcopy(src, dst, len) memcpy((dst), (src), (len))
#define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
#define bzero(b, len) memset((b), '\0', (len))
/* register access macros */
#ifdef EXYNOS5433_PCIE_WAR
#define R_REG(osh, r) (\
SELECT_BUS_READ(osh, \
({ \
__typeof(*(r)) __osl_v; \
exynos_pcie_set_l1_exit(); \
switch (sizeof(*(r))) { \
case sizeof(uint8): __osl_v = \
readb((volatile uint8*)(r)); break; \
case sizeof(uint16): __osl_v = \
readw((volatile uint16*)(r)); break; \
case sizeof(uint32): __osl_v = \
readl((volatile uint32*)(r)); break; \
} \
exynos_pcie_clear_l1_exit(); \
__osl_v; \
}), \
OSL_READ_REG(osh, r)) \
)
#else
#define R_REG(osh, r) (\
SELECT_BUS_READ(osh, \
({ \
__typeof(*(r)) __osl_v; \
BCM_REFERENCE(osh); \
switch (sizeof(*(r))) { \
case sizeof(uint8): __osl_v = \
readb((volatile uint8*)(r)); break; \
@ -182,9 +294,22 @@ extern int osl_error(int bcmerror);
}), \
OSL_READ_REG(osh, r)) \
)
#endif /* EXYNOS5433_PCIE_WAR */
#ifdef EXYNOS5433_PCIE_WAR
#define W_REG(osh, r, v) do { \
exynos_pcie_set_l1_exit(); \
SELECT_BUS_WRITE(osh, \
switch (sizeof(*(r))) { \
case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \
case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \
case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \
}, \
(OSL_WRITE_REG(osh, r, v))); \
exynos_pcie_clear_l1_exit(); \
} while (0)
#else
#define W_REG(osh, r, v) do { \
BCM_REFERENCE(osh); \
SELECT_BUS_WRITE(osh, \
switch (sizeof(*(r))) { \
case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \
@ -193,61 +318,61 @@ extern int osl_error(int bcmerror);
}, \
(OSL_WRITE_REG(osh, r, v))); \
} while (0)
#endif /* EXYNOS5433_PCIE_WAR */
#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
/* bcopy, bcmp, and bzero functions */
#define bcopy(src, dst, len) memcpy((dst), (src), (len))
#define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
#define bzero(b, len) memset((b), '\0', (len))
/* uncached/cached virtual address */
#define OSL_UNCACHED(va) ((void *)va)
#define OSL_CACHED(va) ((void *)va)
#define OSL_PREF_RANGE_LD(va, sz) BCM_REFERENCE(va)
#define OSL_PREF_RANGE_ST(va, sz) BCM_REFERENCE(va)
#define OSL_CACHE_FLUSH(va, len)
#define OSL_PREF_RANGE_LD(va, sz)
#define OSL_PREF_RANGE_ST(va, sz)
/* get processor cycle count */
#if defined(__i386__)
#define OSL_GETCYCLES(x) rdtscl((x))
#else
#define OSL_GETCYCLES(x) ((x) = 0)
#endif
/* dereference an address that may cause a bus exception */
#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; })
/* map/unmap physical to virtual I/O */
#if !defined(CONFIG_MMC_MSM7X00A)
#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size))
#else
#define REG_MAP(pa, size) (void *)(0)
#endif
#endif /* !defined(CONFIG_MMC_MSM7X00A */
#define REG_UNMAP(va) iounmap((va))
/* shared (dma-able) memory access macros */
#define R_SM(r) *(r)
#define W_SM(r, v) (*(r) = (v))
#define BZERO_SM(r, len) memset((r), '\0', (len))
/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for
* performance reasons), we need the Linux headers.
*/
#include <linuxver.h> /* use current 2.4.x calling conventions */
#include <linuxver.h>
/* packet primitives */
#ifdef BCMDBG_CTRACE
#define PKTGET(osh, len, send) osl_pktget((osh), (len), __LINE__, __FILE__)
#define PKTDUP(osh, skb) osl_pktdup((osh), (skb), __LINE__, __FILE__)
#else
#define PKTGET(osh, len, send) osl_pktget((osh), (len))
#define PKTDUP(osh, skb) osl_pktdup((osh), (skb))
#endif
#define PKTLIST_DUMP(osh, buf)
#define PKTDBG_TRACE(osh, pkt, bit)
#endif /* BCMDBG_CTRACE */
#define PKTLIST_DUMP(osh, buf) BCM_REFERENCE(osh)
#define PKTDBG_TRACE(osh, pkt, bit) BCM_REFERENCE(osh)
#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send))
#ifdef CONFIG_DHD_USE_STATIC_BUF
#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len))
@ -255,21 +380,61 @@ extern int osl_error(int bcmerror);
#else
#define PKTGET_STATIC PKTGET
#define PKTFREE_STATIC PKTFREE
#endif
#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data)
#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len)
#endif /* CONFIG_DHD_USE_STATIC_BUF */
#define PKTDATA(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->data);})
#define PKTLEN(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->len);})
#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head))
#define PKTTAILROOM(osh, skb) skb_tailroom((struct sk_buff*)(skb))
#define PKTPADTAILROOM(osh, skb, padlen) osh_pktpadtailroom((osh), (skb), (padlen))
#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next)
#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x))
#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len))
#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes))
#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes))
#define PKTEXPHEADROOM(osh, skb, b) \
({ \
BCM_REFERENCE(osh); \
skb_realloc_headroom((struct sk_buff*)(skb), (b)); \
})
#define PKTTAILROOM(osh, skb) \
({ \
BCM_REFERENCE(osh); \
skb_tailroom((struct sk_buff*)(skb)); \
})
#define PKTPADTAILROOM(osh, skb, padlen) \
({ \
BCM_REFERENCE(osh); \
skb_pad((struct sk_buff*)(skb), (padlen)); \
})
#define PKTNEXT(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->next);})
#define PKTSETNEXT(osh, skb, x) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)); \
})
#define PKTSETLEN(osh, skb, len) \
({ \
BCM_REFERENCE(osh); \
__skb_trim((struct sk_buff*)(skb), (len)); \
})
#define PKTPUSH(osh, skb, bytes) \
({ \
BCM_REFERENCE(osh); \
skb_push((struct sk_buff*)(skb), (bytes)); \
})
#define PKTPULL(osh, skb, bytes) \
({ \
BCM_REFERENCE(osh); \
skb_pull((struct sk_buff*)(skb), (bytes)); \
})
#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb))
#define PKTSETPOOL(osh, skb, x, y) do {} while (0)
#define PKTPOOL(osh, skb) FALSE
#define PKTSHRINK(osh, m) (m)
#define PKTSETPOOL(osh, skb, x, y) BCM_REFERENCE(osh)
#define PKTPOOL(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
#define PKTFREELIST(skb) PKTLINK(skb)
#define PKTSETFREELIST(skb, x) PKTSETLINK((skb), (x))
#define PKTPTR(skb) (skb)
#define PKTID(skb) ({BCM_REFERENCE(skb); 0;})
#define PKTSETID(skb, id) ({BCM_REFERENCE(skb); BCM_REFERENCE(id);})
#define PKTSHRINK(osh, m) ({BCM_REFERENCE(osh); m;})
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
#define PKTORPHAN(skb) skb_orphan(skb)
#else
#define PKTORPHAN(skb) ({BCM_REFERENCE(skb); 0;})
#endif /* LINUX VERSION >= 3.6 */
#ifdef BCMDBG_CTRACE
#define DEL_CTRACE(zosh, zskb) { \
@ -308,7 +473,7 @@ extern int osl_error(int bcmerror);
}
#define PKTCALLER(zskb) UPDATE_CTRACE((struct sk_buff *)zskb, (char *)__FUNCTION__, __LINE__)
#endif
#endif /* BCMDBG_CTRACE */
#ifdef CTFPOOL
#define CTFPOOL_REFILL_THRESH 3
@ -326,23 +491,59 @@ typedef struct ctfpool {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
#define FASTBUF (1 << 0)
#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF)
#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF))
#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF)
#define PKTSETFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF); \
})
#define PKTCLRFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)); \
})
#define PKTISFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF); \
})
#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
#define FASTBUF (1 << 16)
#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF)
#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF))
#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF)
#define PKTSETFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->mac_len) |= FASTBUF); \
})
#define PKTCLRFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)); \
})
#define PKTISFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->mac_len) & FASTBUF); \
})
#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len)
#else
#define FASTBUF (1 << 0)
#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= FASTBUF)
#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF))
#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) & FASTBUF)
#define PKTSETFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->__unused) |= FASTBUF); \
})
#define PKTCLRFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)); \
})
#define PKTISFAST(osh, skb) \
({ \
BCM_REFERENCE(osh); \
((((struct sk_buff*)(skb))->__unused) & FASTBUF); \
})
#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused)
#endif
#endif /* 2.6.22 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool)
@ -357,61 +558,296 @@ extern void osl_ctfpool_replenish(osl_t *osh, uint thresh);
extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size);
extern void osl_ctfpool_cleanup(osl_t *osh);
extern void osl_ctfpool_stats(osl_t *osh, void *b);
#else
#define PKTSETFAST(osh, skb)
#define PKTCLRFAST(osh, skb)
#define PKTISFAST(osh, skb) (FALSE)
#endif
#else /* CTFPOOL */
#define PKTSETFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTCLRFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTISFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
#endif /* CTFPOOL */
#define PKTSETCTF(osh, skb)
#define PKTCLRCTF(osh, skb)
#define PKTISCTF(osh, skb) (FALSE)
#define PKTSETCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTCLRCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTISCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
#ifdef HNDCTF
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
#define SKIPCT (1 << 2)
#define CHAINED (1 << 3)
#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT)
#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT))
#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags & SKIPCT)
#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= CHAINED)
#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED))
#define PKTSETSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags |= SKIPCT); \
})
#define PKTCLRSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)); \
})
#define PKTSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags & SKIPCT); \
})
#define PKTSETCHAINED(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags |= CHAINED); \
})
#define PKTCLRCHAINED(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)); \
})
#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->pktc_flags & CHAINED)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
#define SKIPCT (1 << 18)
#define CHAINED (1 << 19)
#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT)
#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT))
#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT)
#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len |= CHAINED)
#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~CHAINED))
#define PKTSETSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len |= SKIPCT); \
})
#define PKTCLRSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)); \
})
#define PKTSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len & SKIPCT); \
})
#define PKTSETCHAINED(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len |= CHAINED); \
})
#define PKTCLRCHAINED(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len &= (~CHAINED)); \
})
#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->mac_len & CHAINED)
#else
#else /* 2.6.22 */
#define SKIPCT (1 << 2)
#define CHAINED (1 << 3)
#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT)
#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~SKIPCT))
#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused & SKIPCT)
#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused |= CHAINED)
#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~CHAINED))
#define PKTSETSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused |= SKIPCT); \
})
#define PKTCLRSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused &= (~SKIPCT)); \
})
#define PKTSKIPCT(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused & SKIPCT); \
})
#define PKTSETCHAINED(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused |= CHAINED); \
})
#define PKTCLRCHAINED(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused &= (~CHAINED)); \
})
#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->__unused & CHAINED)
#endif
#endif /* 2.6.22 */
typedef struct ctf_mark {
uint32 value;
} ctf_mark_t;
#define CTF_MARK(m) (m.value)
#else
#define PKTSETSKIPCT(osh, skb)
#define PKTCLRSKIPCT(osh, skb)
#define PKTSKIPCT(osh, skb)
#define CTF_MARK(m) 0
#else /* HNDCTF */
#define PKTSETSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTCLRSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define CTF_MARK(m) ({BCM_REFERENCE(m); 0;})
#endif /* HNDCTF */
#if defined(BCM_GMAC3)
/** pktalloced accounting in devices using GMAC Bulk Forwarding to DHD */
/* Account for packets delivered to downstream forwarder by GMAC interface. */
extern void osl_pkt_tofwder(osl_t *osh, void *skbs, int skb_cnt);
#define PKTTOFWDER(osh, skbs, skb_cnt) \
osl_pkt_tofwder(((osl_t *)osh), (void *)(skbs), (skb_cnt))
/* Account for packets received from downstream forwarder. */
#if defined(BCMDBG_CTRACE) /* pkt logging */
extern void osl_pkt_frmfwder(osl_t *osh, void *skbs, int skb_cnt,
int line, char *file);
#define PKTFRMFWDER(osh, skbs, skb_cnt) \
osl_pkt_frmfwder(((osl_t *)osh), (void *)(skbs), (skb_cnt), \
__LINE__, __FILE__)
#else /* ! (BCMDBG_PKT || BCMDBG_CTRACE) */
extern void osl_pkt_frmfwder(osl_t *osh, void *skbs, int skb_cnt);
#define PKTFRMFWDER(osh, skbs, skb_cnt) \
osl_pkt_frmfwder(((osl_t *)osh), (void *)(skbs), (skb_cnt))
#endif
/** GMAC Forwarded packet tagging for reduced cache flush/invalidate.
* In FWDERBUF tagged packet, only FWDER_PKTMAPSZ amount of data would have
* been accessed in the GMAC forwarder. This may be used to limit the number of
* cachelines that need to be flushed or invalidated.
* Packets sent to the DHD from a GMAC forwarder will be tagged w/ FWDERBUF.
* DHD may clear the FWDERBUF tag, if more than FWDER_PKTMAPSZ was accessed.
* Likewise, a debug print of a packet payload in say the ethernet driver needs
* to be accompanied with a clear of the FWDERBUF tag.
*/
/** Forwarded packets, have a HWRXOFF sized rx header (etc.h) */
#define FWDER_HWRXOFF (30)
/** Maximum amount of a pktadat that a downstream forwarder (GMAC) may have
* read into the L1 cache (not dirty). This may be used in reduced cache ops.
*
* Max 56: ET HWRXOFF[30] + BRCMHdr[4] + EtherHdr[14] + VlanHdr[4] + IP[4]
*/
#define FWDER_PKTMAPSZ (FWDER_HWRXOFF + 4 + 14 + 4 + 4)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
#define FWDERBUF (1 << 4)
#define PKTSETFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags |= FWDERBUF); \
})
#define PKTCLRFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags &= (~FWDERBUF)); \
})
#define PKTISFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags & FWDERBUF); \
})
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
#define FWDERBUF (1 << 20)
#define PKTSETFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len |= FWDERBUF); \
})
#define PKTCLRFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len &= (~FWDERBUF)); \
})
#define PKTISFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->mac_len & FWDERBUF); \
})
#else /* 2.6.22 */
#define FWDERBUF (1 << 4)
#define PKTSETFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused |= FWDERBUF); \
})
#define PKTCLRFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused &= (~FWDERBUF)); \
})
#define PKTISFWDERBUF(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->__unused & FWDERBUF); \
})
#endif /* 2.6.22 */
#else /* ! BCM_GMAC3 */
#define PKTSETFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); })
#define PKTCLRFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); })
#define PKTISFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;})
#endif /* ! BCM_GMAC3 */
#ifdef HNDCTF
/* For broadstream iqos */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
#define TOBR (1 << 5)
#define PKTSETTOBR(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags |= TOBR); \
})
#define PKTCLRTOBR(osh, skb) \
({ \
BCM_REFERENCE(osh); \
(((struct sk_buff*)(skb))->pktc_flags &= (~TOBR)); \
})
#define PKTISTOBR(skb) (((struct sk_buff*)(skb))->pktc_flags & TOBR)
#define PKTSETCTFIPCTXIF(skb, ifp) (((struct sk_buff*)(skb))->ctf_ipc_txif = ifp)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
#define PKTSETTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTCLRTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTISTOBR(skb) ({BCM_REFERENCE(skb); FALSE;})
#define PKTSETCTFIPCTXIF(skb, ifp) ({BCM_REFERENCE(skb); BCM_REFERENCE(ifp);})
#else /* 2.6.22 */
#define PKTSETTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTCLRTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTISTOBR(skb) ({BCM_REFERENCE(skb); FALSE;})
#define PKTSETCTFIPCTXIF(skb, ifp) ({BCM_REFERENCE(skb); BCM_REFERENCE(ifp);})
#endif /* 2.6.22 */
#else /* HNDCTF */
#define PKTSETTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTCLRTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);})
#define PKTISTOBR(skb) ({BCM_REFERENCE(skb); FALSE;})
#endif /* HNDCTF */
#ifdef BCMFA
#ifdef BCMFA_HW_HASH
#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx)
#else
#define PKTSETFAHIDX(skb, idx) ({BCM_REFERENCE(skb); BCM_REFERENCE(idx);})
#endif /* BCMFA_SW_HASH */
#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx)
#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp)
#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev)
#define AUX_TCP_FIN_RST (1 << 0)
#define AUX_FREED (1 << 1)
#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST)
#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST))
#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST)
#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED)
#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED))
#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED)
#define PKTISFABRIDGED(skb) PKTISFAAUX(skb)
#else
#define PKTISFAAUX(skb) ({BCM_REFERENCE(skb); FALSE;})
#define PKTISFABRIDGED(skb) ({BCM_REFERENCE(skb); FALSE;})
#define PKTISFAFREED(skb) ({BCM_REFERENCE(skb); FALSE;})
#define PKTCLRFAAUX(skb) BCM_REFERENCE(skb)
#define PKTSETFAFREED(skb) BCM_REFERENCE(skb)
#define PKTCLRFAFREED(skb) BCM_REFERENCE(skb)
#endif /* BCMFA */
extern void osl_pktfree(osl_t *osh, void *skb, bool send);
extern void *osl_pktget_static(osl_t *osh, uint len);
extern void osl_pktfree_static(osl_t *osh, void *skb, bool send);
extern int osh_pktpadtailroom(osl_t *osh, void* skb, int pad);
extern void osl_pktclone(osl_t *osh, void **pkt);
#ifdef BCMDBG_CTRACE
#define PKT_CTRACE_DUMP(osh, b) osl_ctrace_dump((osh), (b))
@ -425,7 +861,7 @@ extern void osl_ctrace_dump(osl_t *osh, struct bcmstrbuf *b);
extern void *osl_pkt_frmnative(osl_t *osh, void *skb);
extern void *osl_pktget(osl_t *osh, uint len);
extern void *osl_pktdup(osl_t *osh, void *skb);
#endif
#endif /* BCMDBG_CTRACE */
extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt);
#ifdef BCMDBG_CTRACE
#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), \
@ -433,7 +869,7 @@ extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt);
#define PKTISFRMNATIVE(osh, skb) osl_pkt_is_frmnative((osl_t *)(osh), (struct sk_buff *)(skb))
#else
#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb))
#endif
#endif /* BCMDBG_CTRACE */
#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt))
#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev)
@ -443,30 +879,33 @@ extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt);
#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW)
#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \
((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */
#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned)
#ifdef CONFIG_NF_CONNTRACK_MARK
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
#define PKTMARK(p) (((struct sk_buff *)(p))->mark)
#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m)
#else
#else /* !2.6.0 */
#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark)
#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m)
#endif
#else
#endif /* 2.6.0 */
#else /* CONFIG_NF_CONNTRACK_MARK */
#define PKTMARK(p) 0
#define PKTSETMARK(p, m)
#endif
#endif /* CONFIG_NF_CONNTRACK_MARK */
#define PKTALLOCED(osh) osl_pktalloced(osh)
extern uint osl_pktalloced(osl_t *osh);
#define OSL_RAND() osl_rand()
extern uint32 osl_rand(void);
#define DMA_MAP(osh, va, size, direction, p, dmah) \
osl_dma_map((osh), (va), (size), (direction), (p), (dmah))
#ifdef PKTC
/* Use 8 bytes of skb tstamp field to store below info */
struct chain_node {
struct sk_buff *link;
unsigned int flags:3, pkts:9, bytes:20;
@ -518,29 +957,29 @@ do { \
(t) = (p); \
} \
} while (0)
#endif
#else
#endif /* PKTC */
#else /* ! BCMDRIVER */
/* ASSERT */
#define ASSERT(exp) do {} while (0)
/* MALLOC and MFREE */
#define MALLOC(o, l) malloc(l)
#define MFREE(o, p, l) free(p)
#include <stdlib.h>
/* str* and mem* functions */
#include <string.h>
/* *printf functions */
#include <stdio.h>
/* bcopy, bcmp, and bzero */
extern void bcopy(const void *src, void *dst, size_t len);
extern int bcmp(const void *b1, const void *b2, size_t len);
extern void bzero(void *b, size_t len);
#endif
#endif /* ! BCMDRIVER */
#endif
#endif /* _linux_osl_h_ */

View File

@ -4,7 +4,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: linuxver.h 417757 2013-08-12 12:24:45Z $
* $Id: linuxver.h 431983 2013-10-25 06:53:27Z $
*/
#ifndef _linuxver_h_
@ -20,17 +20,21 @@
#else
#include <linux/autoconf.h>
#endif
#endif
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
#include <linux/module.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
#include <linux/kconfig.h>
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */
#ifdef __UNDEF_NO_VERSION__
#undef __NO_VERSION__
#else
#define __NO_VERSION__
#endif
#endif
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i")
@ -38,7 +42,7 @@
MODULE_PARM(_string_, "c" __MODULE_STRING(_size_))
#endif
/* linux/malloc.h is deprecated, use linux/slab.h instead. */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9))
#include <linux/malloc.h>
#else
@ -57,10 +61,10 @@
#include <linux/semaphore.h>
#else
#include <asm/semaphore.h>
#endif
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
#undef IP_TOS
#endif
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */
#include <asm/io.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41))
@ -79,23 +83,26 @@
#ifndef flush_scheduled_work
#define flush_scheduled_work() flush_scheduled_tasks()
#endif
#endif
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
#define DAEMONIZE(a)
#define DAEMONIZE(a) do { \
allow_signal(SIGKILL); \
allow_signal(SIGTERM); \
} while (0)
#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)))
#define DAEMONIZE(a) daemonize(a); \
allow_signal(SIGKILL); \
allow_signal(SIGTERM);
#else
#else /* Linux 2.4 (w/o preemption patch) */
#define RAISE_RX_SOFTIRQ() \
cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
#define DAEMONIZE(a) daemonize(); \
do { if (a) \
strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a)))); \
} while (0);
#endif
#endif /* LINUX_VERSION_CODE */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func)
@ -103,13 +110,13 @@
#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work)
#if !(LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18) && defined(RHEL_MAJOR) && \
(RHEL_MAJOR == 5))
/* Exclude RHEL 5 */
typedef void (*work_func_t)(void *work);
#endif
#endif
#endif /* >= 2.6.20 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
/* Some distributions have their own 2.6.x compatibility layers */
#ifndef IRQ_NONE
typedef void irqreturn_t;
#define IRQ_NONE
@ -118,30 +125,30 @@ typedef void irqreturn_t;
#endif
#else
typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
#endif
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
#define IRQF_SHARED SA_SHIRQ
#endif
#endif /* < 2.6.18 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
#ifdef CONFIG_NET_RADIO
#define CONFIG_WIRELESS_EXT
#endif
#endif
#endif /* < 2.6.17 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67)
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
#include <linux/sched.h>
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
#include <linux/sched/rt.h>
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
#include <net/lib80211.h>
@ -152,7 +159,7 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
#include <net/ieee80211.h>
#endif
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */
#ifndef __exit
@ -162,8 +169,13 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
#define __devexit
#endif
#ifndef __devinit
#define __devinit __init
#endif
# if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
# define __devinit __init
# else
/* All devices are hotpluggable since linux 3.8.0 */
# define __devinit
# endif
#endif /* !__devinit */
#ifndef __devinitdata
#define __devinitdata
#endif
@ -176,35 +188,39 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
#define pci_get_drvdata(dev) (dev)->sysdata
#define pci_set_drvdata(dev, value) (dev)->sysdata = (value)
/*
* New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration
*/
struct pci_device_id {
unsigned int vendor, device;
unsigned int subvendor, subdevice;
unsigned int class, class_mask;
unsigned long driver_data;
unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
unsigned long driver_data; /* Data private to the driver */
};
struct pci_driver {
struct list_head node;
char *name;
const struct pci_device_id *id_table;
const struct pci_device_id *id_table; /* NULL if wants all devices */
int (*probe)(struct pci_dev *dev,
const struct pci_device_id *id);
void (*remove)(struct pci_dev *dev);
void (*suspend)(struct pci_dev *dev);
void (*resume)(struct pci_dev *dev);
const struct pci_device_id *id); /* New device inserted */
void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug
* capable driver)
*/
void (*suspend)(struct pci_dev *dev); /* Device suspended */
void (*resume)(struct pci_dev *dev); /* Device woken up */
};
#define MODULE_DEVICE_TABLE(type, name)
#define PCI_ANY_ID (~0)
/* compatpci.c */
#define pci_module_init pci_register_driver
extern int pci_register_driver(struct pci_driver *drv);
extern void pci_unregister_driver(struct pci_driver *drv);
#endif
#endif /* PCI registration */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
#define pci_module_init pci_register_driver
@ -218,7 +234,7 @@ extern void pci_unregister_driver(struct pci_driver *drv);
#define module_init(x) __initcall(x);
#define module_exit(x) __exitcall(x);
#endif
#endif
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
#define WL_USE_NETDEV_OPS
@ -253,7 +269,11 @@ extern void pci_unregister_driver(struct pci_driver *drv);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42))
/*
* DMA mapping
*
* See linux/Documentation/DMA-mapping.txt
*/
#ifndef PCI_DMA_TODEVICE
#define PCI_DMA_TODEVICE 1
@ -262,7 +282,7 @@ extern void pci_unregister_driver(struct pci_driver *drv);
typedef u32 dma_addr_t;
/* Pure 2^n version of get_order */
static inline int get_order(unsigned long size)
{
int order;
@ -298,17 +318,26 @@ static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
#define pci_unmap_single(cookie, address, size, dir)
#endif
#endif /* DMA mapping */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43))
#define dev_kfree_skb_any(a) dev_kfree_skb(a)
#define netif_down(dev) do { (dev)->start = 0; } while (0)
/* pcmcia-cs provides its own netdevice compatibility layer */
#ifndef _COMPAT_NETDEVICE_H
/*
* SoftNet
*
* For pre-softnet kernels we need to tell the upper layer not to
* re-enter start_xmit() while we are in there. However softnet
* guarantees not to enter while we are in there so there is no need
* to do the netif_stop_queue() dance unless the transmit queue really
* gets stuck. This should also improve performance according to tests
* done by Aman Singla.
*/
#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
#define netif_wake_queue(dev) \
@ -325,12 +354,12 @@ static inline void netif_start_queue(struct net_device *dev)
#define netif_queue_stopped(dev) (dev)->tbusy
#define netif_running(dev) (dev)->start
#endif
#endif /* _COMPAT_NETDEVICE_H */
#define netif_device_attach(dev) netif_start_queue(dev)
#define netif_device_detach(dev) netif_stop_queue(dev)
/* 2.4.x renamed bottom halves to tasklets */
#define tasklet_struct tq_struct
static inline void tasklet_schedule(struct tasklet_struct *tasklet)
{
@ -349,25 +378,29 @@ static inline void tasklet_init(struct tasklet_struct *tasklet,
}
#define tasklet_kill(tasklet) { do {} while (0); }
/* 2.4.x introduced del_timer_sync() */
#define del_timer_sync(timer) del_timer(timer)
#else
#define netif_down(dev)
#endif
#endif /* SoftNet */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3))
/*
* Emit code to initialise a tq_struct's routine and data pointers
*/
#define PREPARE_TQUEUE(_tq, _routine, _data) \
do { \
(_tq)->routine = _routine; \
(_tq)->data = _data; \
} while (0)
/*
* Emit code to initialise all of a tq_struct
*/
#define INIT_TQUEUE(_tq, _routine, _data) \
do { \
INIT_LIST_HEAD(&(_tq)->list); \
@ -375,9 +408,9 @@ static inline void tasklet_init(struct tasklet_struct *tasklet,
PREPARE_TQUEUE((_tq), (_routine), (_data)); \
} while (0)
#endif
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */
/* Power management related macro & routines */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9)
#define PCI_SAVE_STATE(a, b) pci_save_state(a)
#define PCI_RESTORE_STATE(a, b) pci_restore_state(a)
@ -407,7 +440,12 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
for (i = 0; i < 16; i++)
pci_write_config_dword(dev, i * 4, buffer[i]);
}
/*
* otherwise, write the context information we know from bootup.
* This works around a problem where warm-booting from Windows
* combined with a D3(hot)->D0 transition causes PCI config
* header data to be forgotten.
*/
else {
for (i = 0; i < 6; i ++)
pci_write_config_dword(dev,
@ -417,14 +455,14 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
}
return 0;
}
#endif
#endif /* PCI power management */
/* Old cp0 access macros deprecated in 2.4.19 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19))
#define read_c0_count() read_32bit_cp0_register(CP0_COUNT)
#endif
/* Module refcount handled internally in 2.6.x */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
#ifndef SET_MODULE_OWNER
#define SET_MODULE_OWNER(dev) do {} while (0)
@ -434,7 +472,7 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
#define OLD_MOD_INC_USE_COUNT do {} while (0)
#define OLD_MOD_DEC_USE_COUNT do {} while (0)
#endif
#else
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */
#ifndef SET_MODULE_OWNER
#define SET_MODULE_OWNER(dev) do {} while (0)
#endif
@ -446,7 +484,7 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
#endif
#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
#endif
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */
#ifndef SET_NETDEV_DEV
#define SET_NETDEV_DEV(net, pdev) do {} while (0)
@ -456,14 +494,14 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
#ifndef HAVE_FREE_NETDEV
#define free_netdev(dev) kfree(dev)
#endif
#endif
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
/* struct packet_type redefined in 2.6.x */
#define af_packet_priv data
#endif
/* suspend args */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
#define DRV_SUSPEND_STATE_TYPE pm_message_t
#else
@ -475,11 +513,11 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
#endif
typedef struct {
void *parent;
void *parent; /* some external entity that the thread supposed to work for */
char *proc_name;
struct task_struct *p_task;
long thr_pid;
int prio;
int prio; /* priority */
struct semaphore sema;
int terminated;
struct completion completed;
@ -488,8 +526,8 @@ typedef struct {
} tsk_ctl_t;
/* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */
/* note this macro assumes there may be only one context waiting on thread's completion */
#ifdef DHD_DEBUG
#define DBG_THR(x) printk x
#else
@ -507,22 +545,22 @@ static inline bool binary_sema_down(tsk_ctl_t *tsk)
DBG_THR(("dhd_dpc_thread: Unexpected up_cnt %d\n", tsk->up_cnt));
}
spin_unlock_irqrestore(&tsk->spinlock, flags);
return FALSE;
return false;
} else
return TRUE;
return true;
}
static inline bool binary_sema_up(tsk_ctl_t *tsk)
{
bool sem_up = FALSE;
bool sem_up = false;
unsigned long flags = 0;
spin_lock_irqsave(&tsk->spinlock, flags);
if (tsk->up_cnt == 0) {
tsk->up_cnt++;
sem_up = TRUE;
sem_up = true;
} else if (tsk->up_cnt == 1) {
/* dhd_sched_dpc: dpc is alread up! */
} else
DBG_THR(("dhd_sched_dpc: unexpected up cnt %d!\n", tsk->up_cnt));
@ -565,7 +603,7 @@ static inline bool binary_sema_up(tsk_ctl_t *tsk)
(tsk_ctl)->thr_pid = -1; \
}
/* ----------------------- */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
#define KILL_PROC(nr, sig) \
@ -591,7 +629,7 @@ if (tsk) send_sig(sig, tsk, 1); \
kill_proc(pid, sig, 1); \
}
#endif
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
#include <linux/time.h>
@ -630,9 +668,14 @@ do { \
__ret; \
})
#endif
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */
/*
For < 2.6.24, wl creates its own netdev but doesn't
align the priv area like the genuine alloc_netdev().
Since netdev_priv() always gives us the aligned address, it will
not match our unaligned address for < 2.6.24
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
#define DEV_PRIV(dev) (dev->priv)
#else
@ -643,22 +686,45 @@ do { \
#define WL_ISR(i, d, p) wl_isr((i), (d))
#else
#define WL_ISR(i, d, p) wl_isr((i), (d), (p))
#endif
#endif /* < 2.6.20 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
#define netdev_priv(dev) dev->priv
#endif
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
#define CAN_SLEEP() ((!in_atomic() && !irqs_disabled()))
#else
#define CAN_SLEEP() (FALSE)
#endif
#define KMALLOC_FLAG (CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
#define RANDOM32 prandom_u32
#else
#define RANDOM32 random32
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
#define SRANDOM32(entropy) prandom_seed(entropy)
#else
#define SRANDOM32(entropy) srandom32(entropy)
#endif
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */
#endif
/*
* Overide latest kfifo functions with
* older version to work on older kernels
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) && !defined(WL_COMPAT_WIRELESS)
#define kfifo_in_spinlocked(a, b, c, d) kfifo_put(a, (u8 *)b, c)
#define kfifo_out_spinlocked(a, b, c, d) kfifo_get(a, (u8 *)b, c)
#define kfifo_esize(a) 1
#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)) && \
(LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)) && !defined(WL_COMPAT_WIRELESS)
#define kfifo_in_spinlocked(a, b, c, d) kfifo_in_locked(a, b, c, d)
#define kfifo_out_spinlocked(a, b, c, d) kfifo_out_locked(a, b, c, d)
#define kfifo_esize(a) 1
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */
#endif /* _linuxver_h_ */

View File

@ -2,7 +2,7 @@
* Command line options parser.
*
* $Copyright Open Broadcom Corporation$
* $Id: miniopt.h 241182 2011-02-17 21:50:03Z $
* $Id: miniopt.h 484281 2014-06-12 22:42:26Z $
*/
@ -14,6 +14,8 @@ extern "C" {
#endif
/* ---- Include Files ---------------------------------------------------- */
/* ---- Constants and Types ---------------------------------------------- */
#define MINIOPT_MAXKEY 128 /* Max options */

View File

@ -3,7 +3,7 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: msgtrace.h 369735 2012-11-19 22:50:22Z $
* $Id: msgtrace.h 439681 2013-11-27 15:39:50Z $
*/
#ifndef _MSGTRACE_H
@ -16,7 +16,8 @@
/* This marks the start of a packed structure section. */
#include <packed_section_start.h>
/* for osl_t */
#include <osl_decl.h>
#define MSGTRACE_VERSION 1
/* Message trace header */

View File

@ -3,81 +3,129 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: osl.h 370064 2012-11-20 21:00:25Z $
* $Id: osl.h 474639 2014-05-01 23:52:31Z $
*/
#ifndef _osl_h_
#define _osl_h_
#include <osl_decl.h>
typedef struct osl_info osl_t;
typedef struct osl_dmainfo osldma_t;
#define OSL_PKTTAG_SZ 32
#define OSL_PKTTAG_SZ 32 /* Size of PktTag */
/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */
typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status);
/* Drivers use REGOPSSET() to register register read/write funcitons */
typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size);
typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size);
#include <linux_osl.h>
#ifndef PKTDBG_TRACE
#define PKTDBG_TRACE(osh, pkt, bit)
#define PKTDBG_TRACE(osh, pkt, bit) BCM_REFERENCE(osh)
#endif
#define PKTCTFMAP(osh, p)
#define PKTCTFMAP(osh, p) BCM_REFERENCE(osh)
/* --------------------------------------------------------------------------
** Register manipulation macros.
*/
#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val)))
#ifndef AND_REG
#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
#endif
#endif /* !AND_REG */
#ifndef OR_REG
#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
#endif
#endif /* !OR_REG */
#if !defined(OSL_SYSUPTIME)
#define OSL_SYSUPTIME() (0)
#define OSL_SYSUPTIME_SUPPORT FALSE
#else
#define OSL_SYSUPTIME_SUPPORT TRUE
#endif
#endif /* OSL_SYSUPTIME */
#if !defined(PKTC)
#define PKTCGETATTR(s) (0)
#define PKTCSETATTR(skb, f, p, b)
#define PKTCCLRATTR(skb)
#if !defined(PKTC) && !defined(PKTC_DONGLE)
#define PKTCGETATTR(skb) (0)
#define PKTCSETATTR(skb, f, p, b) BCM_REFERENCE(skb)
#define PKTCCLRATTR(skb) BCM_REFERENCE(skb)
#define PKTCCNT(skb) (1)
#define PKTCLEN(skb) PKTLEN(NULL, skb)
#define PKTCGETFLAGS(skb) (0)
#define PKTCSETFLAGS(skb, f)
#define PKTCCLRFLAGS(skb)
#define PKTCSETFLAGS(skb, f) BCM_REFERENCE(skb)
#define PKTCCLRFLAGS(skb) BCM_REFERENCE(skb)
#define PKTCFLAGS(skb) (0)
#define PKTCSETCNT(skb, c)
#define PKTCINCRCNT(skb)
#define PKTCADDCNT(skb, c)
#define PKTCSETLEN(skb, l)
#define PKTCADDLEN(skb, l)
#define PKTCSETFLAG(skb, fb)
#define PKTCCLRFLAG(skb, fb)
#define PKTCSETCNT(skb, c) BCM_REFERENCE(skb)
#define PKTCINCRCNT(skb) BCM_REFERENCE(skb)
#define PKTCADDCNT(skb, c) BCM_REFERENCE(skb)
#define PKTCSETLEN(skb, l) BCM_REFERENCE(skb)
#define PKTCADDLEN(skb, l) BCM_REFERENCE(skb)
#define PKTCSETFLAG(skb, fb) BCM_REFERENCE(skb)
#define PKTCCLRFLAG(skb, fb) BCM_REFERENCE(skb)
#define PKTCLINK(skb) NULL
#define PKTSETCLINK(skb, x)
#define PKTSETCLINK(skb, x) BCM_REFERENCE(skb)
#define FOREACH_CHAINED_PKT(skb, nskb) \
for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb))
#define PKTCFREE PKTFREE
#endif
#define PKTCENQTAIL(h, t, p) \
do { \
if ((t) == NULL) { \
(h) = (t) = (p); \
} \
} while (0)
#endif /* !linux || !PKTC */
#ifndef HNDCTF
#define PKTSETCHAINED(osh, skb)
#define PKTCLRCHAINED(osh, skb)
#define PKTISCHAINED(skb) (FALSE)
#if !defined(HNDCTF) && !defined(PKTC_TX_DONGLE)
#define PKTSETCHAINED(osh, skb) BCM_REFERENCE(osh)
#define PKTCLRCHAINED(osh, skb) BCM_REFERENCE(osh)
#define PKTISCHAINED(skb) FALSE
#endif
#endif
/* Lbuf with fraglist */
#define PKTFRAGPKTID(osh, lb) (0)
#define PKTSETFRAGPKTID(osh, lb, id) BCM_REFERENCE(osh)
#define PKTFRAGTOTNUM(osh, lb) (0)
#define PKTSETFRAGTOTNUM(osh, lb, tot) BCM_REFERENCE(osh)
#define PKTFRAGTOTLEN(osh, lb) (0)
#define PKTSETFRAGTOTLEN(osh, lb, len) BCM_REFERENCE(osh)
#define PKTIFINDEX(osh, lb) (0)
#define PKTSETIFINDEX(osh, lb, idx) BCM_REFERENCE(osh)
#define PKTGETLF(osh, len, send, lbuf_type) (0)
/* in rx path, reuse totlen as used len */
#define PKTFRAGUSEDLEN(osh, lb) (0)
#define PKTSETFRAGUSEDLEN(osh, lb, len) BCM_REFERENCE(osh)
#define PKTFRAGLEN(osh, lb, ix) (0)
#define PKTSETFRAGLEN(osh, lb, ix, len) BCM_REFERENCE(osh)
#define PKTFRAGDATA_LO(osh, lb, ix) (0)
#define PKTSETFRAGDATA_LO(osh, lb, ix, addr) BCM_REFERENCE(osh)
#define PKTFRAGDATA_HI(osh, lb, ix) (0)
#define PKTSETFRAGDATA_HI(osh, lb, ix, addr) BCM_REFERENCE(osh)
/* RX FRAG */
#define PKTISRXFRAG(osh, lb) (0)
#define PKTSETRXFRAG(osh, lb) BCM_REFERENCE(osh)
#define PKTRESETRXFRAG(osh, lb) BCM_REFERENCE(osh)
/* TX FRAG */
#define PKTISTXFRAG(osh, lb) (0)
#define PKTSETTXFRAG(osh, lb) BCM_REFERENCE(osh)
/* Need Rx completion used for AMPDU reordering */
#define PKTNEEDRXCPL(osh, lb) (TRUE)
#define PKTSETNORXCPL(osh, lb) BCM_REFERENCE(osh)
#define PKTRESETNORXCPL(osh, lb) BCM_REFERENCE(osh)
#define PKTISFRAG(osh, lb) (0)
#define PKTFRAGISCHAINED(osh, i) (0)
/* TRIM Tail bytes from lfrag */
#define PKTFRAG_TRIM_TAILBYTES(osh, p, len) PKTSETLEN(osh, p, PKTLEN(osh, p) - len)
#endif /* _osl_h_ */

View File

@ -0,0 +1,16 @@
/*
* osl forward declarations
*
* $Copyright Open Broadcom Corporation$
*
* $Id$
*/
#ifndef _osl_decl_h_
#define _osl_decl_h_
/* osl handle type forward declaration */
typedef struct osl_info osl_t;
typedef struct osl_dmainfo osldma_t;
#endif

View File

@ -16,11 +16,14 @@
*
*
* $Copyright Open Broadcom Corporation$
* $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $
* $Id: packed_section_end.h 437241 2013-11-18 07:39:24Z $
*/
/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
* and undefined in packed_section_end.h. If it is NOT defined at this
* point, then there is a missing include of packed_section_start.h.
*/
#ifdef BWL_PACKED_SECTION
#undef BWL_PACKED_SECTION
#else
@ -30,6 +33,9 @@
/* Compiler-specific directives for structure packing are declared in
* packed_section_start.h. This marks the end of the structure packing section,
* so, undef them here.
*/
#undef BWL_PRE_PACKED_STRUCT
#undef BWL_POST_PACKED_STRUCT

View File

@ -16,11 +16,14 @@
*
*
* $Copyright Open Broadcom Corporation$
* $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $
* $Id: packed_section_start.h 437241 2013-11-18 07:39:24Z $
*/
/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
* and undefined in packed_section_end.h. If it is already defined at this
* point, then there is a missing include of packed_section_end.h.
*/
#ifdef BWL_PACKED_SECTION
#error "BWL_PACKED_SECTION is already defined!"
#else
@ -30,7 +33,7 @@
/* Declare compiler-specific directives for structure packing. */
#if defined(__GNUC__) || defined(__lint)
#define BWL_PRE_PACKED_STRUCT
#define BWL_POST_PACKED_STRUCT __attribute__ ((packed))

View File

@ -3,13 +3,133 @@
*
* $Copyright Open Broadcom Corporation$
*
* $Id: pcicfg.h 346935 2012-07-25 00:24:55Z $
* $Id: pcicfg.h 465082 2014-03-26 17:37:28Z $
*/
#ifndef _h_pcicfg_
#define _h_pcicfg_
#ifndef LINUX_POSTMOGRIFY_REMOVAL
/* The following inside ifndef's so we don't collide with NTDDK.H */
#ifndef PCI_MAX_BUS
#define PCI_MAX_BUS 0x100
#endif
#ifndef PCI_MAX_DEVICES
#define PCI_MAX_DEVICES 0x20
#endif
#ifndef PCI_MAX_FUNCTION
#define PCI_MAX_FUNCTION 0x8
#endif
#ifndef PCI_INVALID_VENDORID
#define PCI_INVALID_VENDORID 0xffff
#endif
#ifndef PCI_INVALID_DEVICEID
#define PCI_INVALID_DEVICEID 0xffff
#endif
/* Convert between bus-slot-function-register and config addresses */
#define PCICFG_BUS_SHIFT 16 /* Bus shift */
#define PCICFG_SLOT_SHIFT 11 /* Slot shift */
#define PCICFG_FUN_SHIFT 8 /* Function shift */
#define PCICFG_OFF_SHIFT 0 /* Register shift */
#define PCICFG_BUS_MASK 0xff /* Bus mask */
#define PCICFG_SLOT_MASK 0x1f /* Slot mask */
#define PCICFG_FUN_MASK 7 /* Function mask */
#define PCICFG_OFF_MASK 0xff /* Bus mask */
#define PCI_CONFIG_ADDR(b, s, f, o) \
((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \
| (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \
| (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \
| (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT))
#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK)
#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK)
#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK)
#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK)
/* PCIE Config space accessing MACROS */
#define PCIECFG_BUS_SHIFT 24 /* Bus shift */
#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */
#define PCIECFG_FUN_SHIFT 16 /* Function shift */
#define PCIECFG_OFF_SHIFT 0 /* Register shift */
#define PCIECFG_BUS_MASK 0xff /* Bus mask */
#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */
#define PCIECFG_FUN_MASK 7 /* Function mask */
#define PCIECFG_OFF_MASK 0xfff /* Register mask */
#define PCIE_CONFIG_ADDR(b, s, f, o) \
((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \
| (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \
| (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \
| (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT))
#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK)
#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK)
#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK)
#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK)
/* The actual config space */
#define PCI_BAR_MAX 6
#define PCI_ROM_BAR 8
#define PCR_RSVDA_MAX 2
/* Bits in PCI bars' flags */
#define PCIBAR_FLAGS 0xf
#define PCIBAR_IO 0x1
#define PCIBAR_MEM1M 0x2
#define PCIBAR_MEM64 0x4
#define PCIBAR_PREFETCH 0x8
#define PCIBAR_MEM32_MASK 0xFFFFFF80
/* pci config status reg has a bit to indicate that capability ptr is present */
#define PCI_CAPPTR_PRESENT 0x0010
typedef struct _pci_config_regs {
uint16 vendor;
uint16 device;
uint16 command;
uint16 status;
uint8 rev_id;
uint8 prog_if;
uint8 sub_class;
uint8 base_class;
uint8 cache_line_size;
uint8 latency_timer;
uint8 header_type;
uint8 bist;
uint32 base[PCI_BAR_MAX];
uint32 cardbus_cis;
uint16 subsys_vendor;
uint16 subsys_id;
uint32 baserom;
uint32 rsvd_a[PCR_RSVDA_MAX];
uint8 int_line;
uint8 int_pin;
uint8 min_gnt;
uint8 max_lat;
uint8 dev_dep[192];
} pci_config_regs;
#define SZPCR (sizeof (pci_config_regs))
#define MINSZPCR 64 /* offsetof (dev_dep[0] */
#endif /* !LINUX_POSTMOGRIFY_REMOVAL */
/* A structure for the config registers is nice, but in most
* systems the config space is not memory mapped, so we need
* field offsetts. :-(
*/
#define PCI_CFG_VID 0
#define PCI_CFG_DID 2
#define PCI_CFG_CMD 4
@ -38,36 +158,407 @@
#define PCI_CFG_MINGNT 0x3e
#define PCI_CFG_MAXLAT 0x3f
#define PCI_CFG_DEVCTRL 0xd8
#define PCI_BAR0_WIN 0x80
#define PCI_BAR1_WIN 0x84
#define PCI_SPROM_CONTROL 0x88
#define PCI_BAR1_CONTROL 0x8c
#define PCI_INT_STATUS 0x90
#define PCI_INT_MASK 0x94
#define PCI_TO_SB_MB 0x98
#define PCI_BACKPLANE_ADDR 0xa0
#define PCI_BACKPLANE_DATA 0xa4
#define PCI_CLK_CTL_ST 0xa8
#define PCI_BAR0_WIN2 0xac
#define PCI_GPIO_IN 0xb0
#define PCI_GPIO_OUT 0xb4
#define PCI_GPIO_OUTEN 0xb8
#ifndef LINUX_POSTMOGRIFY_REMOVAL
#define PCI_BAR0_SHADOW_OFFSET (2 * 1024)
#define PCI_BAR0_SPROM_OFFSET (4 * 1024)
#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024)
#define PCI_BAR0_PCISBR_OFFSET (4 * 1024)
#define PCIE2_BAR0_WIN2 0x70
#define PCIE2_BAR0_CORE2_WIN 0x74
#define PCIE2_BAR0_CORE2_WIN2 0x78
#define PCI_BAR0_WINSZ (16 * 1024)
/* Classes and subclasses */
#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024)
#define PCI_16KB0_CCREGS_OFFSET (12 * 1024)
#define PCI_16KBB0_WINSZ (16 * 1024)
typedef enum {
PCI_CLASS_OLD = 0,
PCI_CLASS_DASDI,
PCI_CLASS_NET,
PCI_CLASS_DISPLAY,
PCI_CLASS_MMEDIA,
PCI_CLASS_MEMORY,
PCI_CLASS_BRIDGE,
PCI_CLASS_COMM,
PCI_CLASS_BASE,
PCI_CLASS_INPUT,
PCI_CLASS_DOCK,
PCI_CLASS_CPU,
PCI_CLASS_SERIAL,
PCI_CLASS_INTELLIGENT = 0xe,
PCI_CLASS_SATELLITE,
PCI_CLASS_CRYPT,
PCI_CLASS_DSP,
PCI_CLASS_XOR = 0xfe
} pci_classes;
typedef enum {
PCI_DASDI_SCSI,
PCI_DASDI_IDE,
PCI_DASDI_FLOPPY,
PCI_DASDI_IPI,
PCI_DASDI_RAID,
PCI_DASDI_OTHER = 0x80
} pci_dasdi_subclasses;
typedef enum {
PCI_NET_ETHER,
PCI_NET_TOKEN,
PCI_NET_FDDI,
PCI_NET_ATM,
PCI_NET_OTHER = 0x80
} pci_net_subclasses;
typedef enum {
PCI_DISPLAY_VGA,
PCI_DISPLAY_XGA,
PCI_DISPLAY_3D,
PCI_DISPLAY_OTHER = 0x80
} pci_display_subclasses;
typedef enum {
PCI_MMEDIA_VIDEO,
PCI_MMEDIA_AUDIO,
PCI_MMEDIA_PHONE,
PCI_MEDIA_OTHER = 0x80
} pci_mmedia_subclasses;
typedef enum {
PCI_MEMORY_RAM,
PCI_MEMORY_FLASH,
PCI_MEMORY_OTHER = 0x80
} pci_memory_subclasses;
typedef enum {
PCI_BRIDGE_HOST,
PCI_BRIDGE_ISA,
PCI_BRIDGE_EISA,
PCI_BRIDGE_MC,
PCI_BRIDGE_PCI,
PCI_BRIDGE_PCMCIA,
PCI_BRIDGE_NUBUS,
PCI_BRIDGE_CARDBUS,
PCI_BRIDGE_RACEWAY,
PCI_BRIDGE_OTHER = 0x80
} pci_bridge_subclasses;
typedef enum {
PCI_COMM_UART,
PCI_COMM_PARALLEL,
PCI_COMM_MULTIUART,
PCI_COMM_MODEM,
PCI_COMM_OTHER = 0x80
} pci_comm_subclasses;
typedef enum {
PCI_BASE_PIC,
PCI_BASE_DMA,
PCI_BASE_TIMER,
PCI_BASE_RTC,
PCI_BASE_PCI_HOTPLUG,
PCI_BASE_OTHER = 0x80
} pci_base_subclasses;
typedef enum {
PCI_INPUT_KBD,
PCI_INPUT_PEN,
PCI_INPUT_MOUSE,
PCI_INPUT_SCANNER,
PCI_INPUT_GAMEPORT,
PCI_INPUT_OTHER = 0x80
} pci_input_subclasses;
typedef enum {
PCI_DOCK_GENERIC,
PCI_DOCK_OTHER = 0x80
} pci_dock_subclasses;
typedef enum {
PCI_CPU_386,
PCI_CPU_486,
PCI_CPU_PENTIUM,
PCI_CPU_ALPHA = 0x10,
PCI_CPU_POWERPC = 0x20,
PCI_CPU_MIPS = 0x30,
PCI_CPU_COPROC = 0x40,
PCI_CPU_OTHER = 0x80
} pci_cpu_subclasses;
typedef enum {
PCI_SERIAL_IEEE1394,
PCI_SERIAL_ACCESS,
PCI_SERIAL_SSA,
PCI_SERIAL_USB,
PCI_SERIAL_FIBER,
PCI_SERIAL_SMBUS,
PCI_SERIAL_OTHER = 0x80
} pci_serial_subclasses;
typedef enum {
PCI_INTELLIGENT_I2O
} pci_intelligent_subclasses;
typedef enum {
PCI_SATELLITE_TV,
PCI_SATELLITE_AUDIO,
PCI_SATELLITE_VOICE,
PCI_SATELLITE_DATA,
PCI_SATELLITE_OTHER = 0x80
} pci_satellite_subclasses;
typedef enum {
PCI_CRYPT_NETWORK,
PCI_CRYPT_ENTERTAINMENT,
PCI_CRYPT_OTHER = 0x80
} pci_crypt_subclasses;
typedef enum {
PCI_DSP_DPIO,
PCI_DSP_OTHER = 0x80
} pci_dsp_subclasses;
typedef enum {
PCI_XOR_QDMA,
PCI_XOR_OTHER = 0x80
} pci_xor_subclasses;
/* Header types */
#define PCI_HEADER_MULTI 0x80
#define PCI_HEADER_MASK 0x7f
typedef enum {
PCI_HEADER_NORMAL,
PCI_HEADER_BRIDGE,
PCI_HEADER_CARDBUS
} pci_header_types;
/* Overlay for a PCI-to-PCI bridge */
#define PPB_RSVDA_MAX 2
#define PPB_RSVDD_MAX 8
typedef struct _ppb_config_regs {
uint16 vendor;
uint16 device;
uint16 command;
uint16 status;
uint8 rev_id;
uint8 prog_if;
uint8 sub_class;
uint8 base_class;
uint8 cache_line_size;
uint8 latency_timer;
uint8 header_type;
uint8 bist;
uint32 rsvd_a[PPB_RSVDA_MAX];
uint8 prim_bus;
uint8 sec_bus;
uint8 sub_bus;
uint8 sec_lat;
uint8 io_base;
uint8 io_lim;
uint16 sec_status;
uint16 mem_base;
uint16 mem_lim;
uint16 pf_mem_base;
uint16 pf_mem_lim;
uint32 pf_mem_base_hi;
uint32 pf_mem_lim_hi;
uint16 io_base_hi;
uint16 io_lim_hi;
uint16 subsys_vendor;
uint16 subsys_id;
uint32 rsvd_b;
uint8 rsvd_c;
uint8 int_pin;
uint16 bridge_ctrl;
uint8 chip_ctrl;
uint8 diag_ctrl;
uint16 arb_ctrl;
uint32 rsvd_d[PPB_RSVDD_MAX];
uint8 dev_dep[192];
} ppb_config_regs;
/* PCI CAPABILITY DEFINES */
#define PCI_CAP_POWERMGMTCAP_ID 0x01
#define PCI_CAP_MSICAP_ID 0x05
#define PCI_CAP_VENDSPEC_ID 0x09
#define PCI_CAP_PCIECAP_ID 0x10
/* Data structure to define the Message Signalled Interrupt facility
* Valid for PCI and PCIE configurations
*/
typedef struct _pciconfig_cap_msi {
uint8 capID;
uint8 nextptr;
uint16 msgctrl;
uint32 msgaddr;
} pciconfig_cap_msi;
#define MSI_ENABLE 0x1 /* bit 0 of msgctrl */
/* Data structure to define the Power managment facility
* Valid for PCI and PCIE configurations
*/
typedef struct _pciconfig_cap_pwrmgmt {
uint8 capID;
uint8 nextptr;
uint16 pme_cap;
uint16 pme_sts_ctrl;
uint8 pme_bridge_ext;
uint8 data;
} pciconfig_cap_pwrmgmt;
#define PME_CAP_PM_STATES (0x1f << 27) /* Bits 31:27 states that can generate PME */
#define PME_CSR_OFFSET 0x4 /* 4-bytes offset */
#define PME_CSR_PME_EN (1 << 8) /* Bit 8 Enable generating of PME */
#define PME_CSR_PME_STAT (1 << 15) /* Bit 15 PME got asserted */
/* Data structure to define the PCIE capability */
typedef struct _pciconfig_cap_pcie {
uint8 capID;
uint8 nextptr;
uint16 pcie_cap;
uint32 dev_cap;
uint16 dev_ctrl;
uint16 dev_status;
uint32 link_cap;
uint16 link_ctrl;
uint16 link_status;
uint32 slot_cap;
uint16 slot_ctrl;
uint16 slot_status;
uint16 root_ctrl;
uint16 root_cap;
uint32 root_status;
} pciconfig_cap_pcie;
/* PCIE Enhanced CAPABILITY DEFINES */
#define PCIE_EXTCFG_OFFSET 0x100
#define PCIE_ADVERRREP_CAPID 0x0001
#define PCIE_VC_CAPID 0x0002
#define PCIE_DEVSNUM_CAPID 0x0003
#define PCIE_PWRBUDGET_CAPID 0x0004
/* PCIE Extended configuration */
#define PCIE_ADV_CORR_ERR_MASK 0x114
#define CORR_ERR_RE (1 << 0) /* Receiver */
#define CORR_ERR_BT (1 << 6) /* Bad TLP */
#define CORR_ERR_BD (1 << 7) /* Bad DLLP */
#define CORR_ERR_RR (1 << 8) /* REPLAY_NUM rollover */
#define CORR_ERR_RT (1 << 12) /* Reply timer timeout */
#define ALL_CORR_ERRORS (CORR_ERR_RE | CORR_ERR_BT | CORR_ERR_BD | \
CORR_ERR_RR | CORR_ERR_RT)
/* PCIE Root Control Register bits (Host mode only) */
#define PCIE_RC_CORR_SERR_EN 0x0001
#define PCIE_RC_NONFATAL_SERR_EN 0x0002
#define PCIE_RC_FATAL_SERR_EN 0x0004
#define PCIE_RC_PME_INT_EN 0x0008
#define PCIE_RC_CRS_EN 0x0010
/* PCIE Root Capability Register bits (Host mode only) */
#define PCIE_RC_CRS_VISIBILITY 0x0001
/* Header to define the PCIE specific capabilities in the extended config space */
typedef struct _pcie_enhanced_caphdr {
uint16 capID;
uint16 cap_ver : 4;
uint16 next_ptr : 12;
} pcie_enhanced_caphdr;
/* Everything below is BRCM HND proprietary */
/* Brcm PCI configuration registers */
#define cap_list rsvd_a[0]
#define bar0_window dev_dep[0x80 - 0x40]
#define bar1_window dev_dep[0x84 - 0x40]
#define sprom_control dev_dep[0x88 - 0x40]
#endif /* LINUX_POSTMOGRIFY_REMOVAL */
#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */
#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */
#define PCI_SPROM_CONTROL 0x88 /* sprom property control */
#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */
#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */
#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */
#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */
#define PCI_BACKPLANE_ADDR 0xa0 /* address an arbitrary location on the system backplane */
#define PCI_BACKPLANE_DATA 0xa4 /* data at the location specified by above address */
#define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */
#define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */
#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */
#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */
#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */
#define PCI_L1SS_CTRL2 0x24c /* The L1 PM Substates Control register */
/* Private Registers */
#define PCI_STAT_CTRL 0xa80
#define PCI_L0_EVENTCNT 0xa84
#define PCI_L0_STATETMR 0xa88
#define PCI_L1_EVENTCNT 0xa8c
#define PCI_L1_STATETMR 0xa90
#define PCI_L1_1_EVENTCNT 0xa94
#define PCI_L1_1_STATETMR 0xa98
#define PCI_L1_2_EVENTCNT 0xa9c
#define PCI_L1_2_STATETMR 0xaa0
#define PCI_L2_EVENTCNT 0xaa4
#define PCI_L2_STATETMR 0xaa8
#define PCI_PMCR_REFUP 0x1814 /* Trefup time */
#define PCI_PMCR_REFUP_EXT 0x1818 /* Trefup extend Max */
#define PCI_TPOWER_SCALE_MASK 0x3
#define PCI_TPOWER_SCALE_SHIFT 3 /* 0:1 is scale and 2 is rsvd */
#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */
#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */
#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */
#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the
* 8KB window, so their address is the "regular"
* address plus 4K
*/
/*
* PCIE GEN2 changed some of the above locations for
* Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase
* BAR0 maps 32K of register space
*/
#define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */
#define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */
#define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */
#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */
/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */
#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */
#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */
#ifndef LINUX_POSTMOGRIFY_REMOVAL
/* On AI chips we have a second window to map DMP regs are mapped: */
#define PCI_16KB0_WIN2_OFFSET (4 * 1024) /* bar0 + 4K is "Window 2" */
/* PCI_INT_STATUS */
#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */
/* PCI_INT_MASK */
#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */
#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */
#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */
#ifndef LINUX_POSTMOGRIFY_REMOVAL
/* PCI_SPROM_CONTROL */
#define SPROM_SZ_MSK 0x02 /* SPROM Size Mask */
#define SPROM_LOCKED 0x08 /* SPROM Locked */
#define SPROM_BLANK 0x04 /* indicating a blank SPROM */
#define SPROM_WRITEEN 0x10 /* SPROM write enable */
#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */
#define SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */
#define SPROM_OTPIN_USE 0x80 /* device OTP In use */
#endif /* LINUX_POSTMOGRIFY_REMOVAL */
/* Bits in PCI command and status regs */
#define PCI_CMD_IO 0x00000001 /* I/O enable */
#define PCI_CMD_MEMORY 0x00000002 /* Memory enable */
#define PCI_CMD_MASTER 0x00000004 /* Master enable */
#define PCI_CMD_SPECIAL 0x00000008 /* Special cycles enable */
#define PCI_CMD_INVALIDATE 0x00000010 /* Invalidate? */
#define PCI_CMD_VGA_PAL 0x00000040 /* VGA Palate */
#define PCI_STAT_TA 0x08000000 /* target abort status */
#endif /* LINUX_POSTMOGRIFY_REMOVAL */
#define PCI_CONFIG_SPACE_SIZE 256
#endif
#endif /* _h_pcicfg_ */

View File

@ -0,0 +1,624 @@
/*
* BCM43XX PCIE core hardware definitions.
*
* $Copyright Open Broadcom Corporation$
*
* $Id: pcie_core.h 483003 2014-06-05 19:57:46Z $
*/
#ifndef _PCIE_CORE_H
#define _PCIE_CORE_H
#include <sbhnddma.h>
#include <siutils.h>
/* cpp contortions to concatenate w/arg prescan */
#ifndef PAD
#define _PADLINE(line) pad ## line
#define _XSTR(line) _PADLINE(line)
#define PAD _XSTR(__LINE__)
#endif
/* PCIE Enumeration space offsets */
#define PCIE_CORE_CONFIG_OFFSET 0x0
#define PCIE_FUNC0_CONFIG_OFFSET 0x400
#define PCIE_FUNC1_CONFIG_OFFSET 0x500
#define PCIE_FUNC2_CONFIG_OFFSET 0x600
#define PCIE_FUNC3_CONFIG_OFFSET 0x700
#define PCIE_SPROM_SHADOW_OFFSET 0x800
#define PCIE_SBCONFIG_OFFSET 0xE00
#define PCIEDEV_MAX_DMAS 4
/* PCIE Bar0 Address Mapping. Each function maps 16KB config space */
#define PCIE_DEV_BAR0_SIZE 0x4000
#define PCIE_BAR0_WINMAPCORE_OFFSET 0x0
#define PCIE_BAR0_EXTSPROM_OFFSET 0x1000
#define PCIE_BAR0_PCIECORE_OFFSET 0x2000
#define PCIE_BAR0_CCCOREREG_OFFSET 0x3000
/* different register spaces to access thr'u pcie indirect access */
#define PCIE_CONFIGREGS 1 /* Access to config space */
#define PCIE_PCIEREGS 2 /* Access to pcie registers */
/* dma regs to control the flow between host2dev and dev2host */
typedef struct pcie_devdmaregs {
dma64regs_t tx;
uint32 PAD[2];
dma64regs_t rx;
uint32 PAD[2];
} pcie_devdmaregs_t;
#define PCIE_DB_HOST2DEV_0 0x1
#define PCIE_DB_HOST2DEV_1 0x2
#define PCIE_DB_DEV2HOST_0 0x3
#define PCIE_DB_DEV2HOST_1 0x4
/* door bell register sets */
typedef struct pcie_doorbell {
uint32 host2dev_0;
uint32 host2dev_1;
uint32 dev2host_0;
uint32 dev2host_1;
} pcie_doorbell_t;
/* SB side: PCIE core and host control registers */
typedef struct sbpcieregs {
uint32 control; /* host mode only */
uint32 iocstatus; /* PCIE2: iostatus */
uint32 PAD[1];
uint32 biststatus; /* bist Status: 0x00C */
uint32 gpiosel; /* PCIE gpio sel: 0x010 */
uint32 gpioouten; /* PCIE gpio outen: 0x14 */
uint32 PAD[2];
uint32 intstatus; /* Interrupt status: 0x20 */
uint32 intmask; /* Interrupt mask: 0x24 */
uint32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */
uint32 obffcontrol; /* PCIE2: 0x2C */
uint32 obffintstatus; /* PCIE2: 0x30 */
uint32 obffdatastatus; /* PCIE2: 0x34 */
uint32 PAD[2];
uint32 errlog; /* PCIE2: 0x40 */
uint32 errlogaddr; /* PCIE2: 0x44 */
uint32 mailboxint; /* PCIE2: 0x48 */
uint32 mailboxintmsk; /* PCIE2: 0x4c */
uint32 ltrspacing; /* PCIE2: 0x50 */
uint32 ltrhysteresiscnt; /* PCIE2: 0x54 */
uint32 PAD[42];
uint32 sbtopcie0; /* sb to pcie translation 0: 0x100 */
uint32 sbtopcie1; /* sb to pcie translation 1: 0x104 */
uint32 sbtopcie2; /* sb to pcie translation 2: 0x108 */
uint32 PAD[5];
/* pcie core supports in direct access to config space */
uint32 configaddr; /* pcie config space access: Address field: 0x120 */
uint32 configdata; /* pcie config space access: Data field: 0x124 */
union {
struct {
/* mdio access to serdes */
uint32 mdiocontrol; /* controls the mdio access: 0x128 */
uint32 mdiodata; /* Data to the mdio access: 0x12c */
/* pcie protocol phy/dllp/tlp register indirect access mechanism */
uint32 pcieindaddr; /* indirect access to the internal register: 0x130 */
uint32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */
uint32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */
uint32 PAD[177];
} pcie1;
struct {
/* mdio access to serdes */
uint32 mdiocontrol; /* controls the mdio access: 0x128 */
uint32 mdiowrdata; /* write data to mdio 0x12C */
uint32 mdiorddata; /* read data to mdio 0x130 */
uint32 PAD[3]; /* 0x134-0x138-0x13c */
/* door bell registers available from gen2 rev5 onwards */
pcie_doorbell_t dbls[PCIEDEV_MAX_DMAS]; /* 0x140 - 0x17F */
uint32 dataintf; /* 0x180 */
uint32 PAD[1]; /* 0x184 */
uint32 d2h_intrlazy_0; /* 0x188 */
uint32 h2d_intrlazy_0; /* 0x18c */
uint32 h2d_intstat_0; /* 0x190 */
uint32 h2d_intmask_0; /* 0x194 */
uint32 d2h_intstat_0; /* 0x198 */
uint32 d2h_intmask_0; /* 0x19c */
uint32 ltr_state; /* 0x1A0 */
uint32 pwr_int_status; /* 0x1A4 */
uint32 pwr_int_mask; /* 0x1A8 */
uint32 PAD[21]; /* 0x1AC - 0x200 */
pcie_devdmaregs_t h2d0_dmaregs; /* 0x200 - 0x23c */
pcie_devdmaregs_t d2h0_dmaregs; /* 0x240 - 0x27c */
pcie_devdmaregs_t h2d1_dmaregs; /* 0x280 - 0x2bc */
pcie_devdmaregs_t d2h1_dmaregs; /* 0x2c0 - 0x2fc */
pcie_devdmaregs_t h2d2_dmaregs; /* 0x300 - 0x33c */
pcie_devdmaregs_t d2h2_dmaregs; /* 0x340 - 0x37c */
pcie_devdmaregs_t h2d3_dmaregs; /* 0x380 - 0x3bc */
pcie_devdmaregs_t d2h3_dmaregs; /* 0x3c0 - 0x3fc */
} pcie2;
} u;
uint32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */
uint16 sprom[64]; /* SPROM shadow Area */
} sbpcieregs_t;
/* PCI control */
#define PCIE_RST_OE 0x01 /* When set, drives PCI_RESET out to pin */
#define PCIE_RST 0x02 /* Value driven out to pin */
#define PCIE_SPERST 0x04 /* SurvivePeRst */
#define PCIE_DISABLE_L1CLK_GATING 0x10
#define PCIE_DLYPERST 0x100 /* Delay PeRst to CoE Core */
#define PCIE_DISSPROMLD 0x200 /* DisableSpromLoadOnPerst */
#define PCIE_WakeModeL2 0x1000 /* Wake on L2 */
#define PCIE_CFGADDR 0x120 /* offsetof(configaddr) */
#define PCIE_CFGDATA 0x124 /* offsetof(configdata) */
/* Interrupt status/mask */
#define PCIE_INTA 0x01 /* PCIE INTA message is received */
#define PCIE_INTB 0x02 /* PCIE INTB message is received */
#define PCIE_INTFATAL 0x04 /* PCIE INTFATAL message is received */
#define PCIE_INTNFATAL 0x08 /* PCIE INTNONFATAL message is received */
#define PCIE_INTCORR 0x10 /* PCIE INTCORR message is received */
#define PCIE_INTPME 0x20 /* PCIE INTPME message is received */
#define PCIE_PERST 0x40 /* PCIE Reset Interrupt */
#define PCIE_INT_MB_FN0_0 0x0100 /* PCIE to SB Mailbox int Fn0.0 is received */
#define PCIE_INT_MB_FN0_1 0x0200 /* PCIE to SB Mailbox int Fn0.1 is received */
#define PCIE_INT_MB_FN1_0 0x0400 /* PCIE to SB Mailbox int Fn1.0 is received */
#define PCIE_INT_MB_FN1_1 0x0800 /* PCIE to SB Mailbox int Fn1.1 is received */
#define PCIE_INT_MB_FN2_0 0x1000 /* PCIE to SB Mailbox int Fn2.0 is received */
#define PCIE_INT_MB_FN2_1 0x2000 /* PCIE to SB Mailbox int Fn2.1 is received */
#define PCIE_INT_MB_FN3_0 0x4000 /* PCIE to SB Mailbox int Fn3.0 is received */
#define PCIE_INT_MB_FN3_1 0x8000 /* PCIE to SB Mailbox int Fn3.1 is received */
/* PCIE MailboxInt/MailboxIntMask register */
#define PCIE_MB_TOSB_FN0_0 0x0001 /* write to assert PCIEtoSB Mailbox interrupt */
#define PCIE_MB_TOSB_FN0_1 0x0002
#define PCIE_MB_TOSB_FN1_0 0x0004
#define PCIE_MB_TOSB_FN1_1 0x0008
#define PCIE_MB_TOSB_FN2_0 0x0010
#define PCIE_MB_TOSB_FN2_1 0x0020
#define PCIE_MB_TOSB_FN3_0 0x0040
#define PCIE_MB_TOSB_FN3_1 0x0080
#define PCIE_MB_TOPCIE_FN0_0 0x0100 /* int status/mask for SBtoPCIE Mailbox interrupts */
#define PCIE_MB_TOPCIE_FN0_1 0x0200
#define PCIE_MB_TOPCIE_FN1_0 0x0400
#define PCIE_MB_TOPCIE_FN1_1 0x0800
#define PCIE_MB_TOPCIE_FN2_0 0x1000
#define PCIE_MB_TOPCIE_FN2_1 0x2000
#define PCIE_MB_TOPCIE_FN3_0 0x4000
#define PCIE_MB_TOPCIE_FN3_1 0x8000
#define PCIE_MB_TOPCIE_D2H0_DB0 0x10000
#define PCIE_MB_TOPCIE_D2H0_DB1 0x20000
#define PCIE_MB_TOPCIE_D2H1_DB0 0x40000
#define PCIE_MB_TOPCIE_D2H1_DB1 0x80000
#define PCIE_MB_TOPCIE_D2H2_DB0 0x100000
#define PCIE_MB_TOPCIE_D2H2_DB1 0x200000
#define PCIE_MB_TOPCIE_D2H3_DB0 0x400000
#define PCIE_MB_TOPCIE_D2H3_DB1 0x800000
#define PCIE_MB_D2H_MB_MASK \
(PCIE_MB_TOPCIE_D2H0_DB0 | PCIE_MB_TOPCIE_D2H0_DB1 | \
PCIE_MB_TOPCIE_D2H1_DB1 | PCIE_MB_TOPCIE_D2H1_DB1 | \
PCIE_MB_TOPCIE_D2H2_DB1 | PCIE_MB_TOPCIE_D2H2_DB1 | \
PCIE_MB_TOPCIE_D2H3_DB1 | PCIE_MB_TOPCIE_D2H3_DB1)
/* SB to PCIE translation masks */
#define SBTOPCIE0_MASK 0xfc000000
#define SBTOPCIE1_MASK 0xfc000000
#define SBTOPCIE2_MASK 0xc0000000
/* Access type bits (0:1) */
#define SBTOPCIE_MEM 0
#define SBTOPCIE_IO 1
#define SBTOPCIE_CFG0 2
#define SBTOPCIE_CFG1 3
/* Prefetch enable bit 2 */
#define SBTOPCIE_PF 4
/* Write Burst enable for memory write bit 3 */
#define SBTOPCIE_WR_BURST 8
/* config access */
#define CONFIGADDR_FUNC_MASK 0x7000
#define CONFIGADDR_FUNC_SHF 12
#define CONFIGADDR_REG_MASK 0x0FFF
#define CONFIGADDR_REG_SHF 0
#define PCIE_CONFIG_INDADDR(f, r) ((((f) & CONFIGADDR_FUNC_MASK) << CONFIGADDR_FUNC_SHF) | \
(((r) & CONFIGADDR_REG_MASK) << CONFIGADDR_REG_SHF))
/* PCIE protocol regs Indirect Address */
#define PCIEADDR_PROT_MASK 0x300
#define PCIEADDR_PROT_SHF 8
#define PCIEADDR_PL_TLP 0
#define PCIEADDR_PL_DLLP 1
#define PCIEADDR_PL_PLP 2
/* PCIE protocol PHY diagnostic registers */
#define PCIE_PLP_MODEREG 0x200 /* Mode */
#define PCIE_PLP_STATUSREG 0x204 /* Status */
#define PCIE_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */
#define PCIE_PLP_LTLINKNUMREG 0x20c /* Link Training Link number */
#define PCIE_PLP_LTLANENUMREG 0x210 /* Link Training Lane number */
#define PCIE_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */
#define PCIE_PLP_ATTNREG 0x218 /* Attention */
#define PCIE_PLP_ATTNMASKREG 0x21C /* Attention Mask */
#define PCIE_PLP_RXERRCTR 0x220 /* Rx Error */
#define PCIE_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error */
#define PCIE_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */
#define PCIE_PLP_TESTCTRLREG 0x22C /* Test Control reg */
#define PCIE_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */
#define PCIE_PLP_TIMINGOVRDREG 0x234 /* Timing param override */
#define PCIE_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag */
#define PCIE_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag */
/* PCIE protocol DLLP diagnostic registers */
#define PCIE_DLLP_LCREG 0x100 /* Link Control */
#define PCIE_DLLP_LSREG 0x104 /* Link Status */
#define PCIE_DLLP_LAREG 0x108 /* Link Attention */
#define PCIE_DLLP_LAMASKREG 0x10C /* Link Attention Mask */
#define PCIE_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num */
#define PCIE_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num */
#define PCIE_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num */
#define PCIE_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */
#define PCIE_DLLP_LRREG 0x120 /* Link Replay */
#define PCIE_DLLP_LACKTOREG 0x124 /* Link Ack Timeout */
#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */
#define PCIE_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr */
#define PCIE_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr */
#define PCIE_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr */
#define PCIE_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write */
#define PCIE_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */
#define PCIE_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */
#define PCIE_DLLP_ERRCTRREG 0x144 /* Error Counter */
#define PCIE_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */
#define PCIE_DLLP_TESTREG 0x14C /* Test */
#define PCIE_DLLP_PKTBIST 0x150 /* Packet BIST */
#define PCIE_DLLP_PCIE11 0x154 /* DLLP PCIE 1.1 reg */
#define PCIE_DLLP_LSREG_LINKUP (1 << 16)
/* PCIE protocol TLP diagnostic registers */
#define PCIE_TLP_CONFIGREG 0x000 /* Configuration */
#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
#define PCIE_TLP_WRDMAUPPER 0x010 /* Write DMA Upper Address */
#define PCIE_TLP_WRDMALOWER 0x014 /* Write DMA Lower Address */
#define PCIE_TLP_WRDMAREQ_LBEREG 0x018 /* Write DMA Len/ByteEn Req */
#define PCIE_TLP_RDDMAUPPER 0x01C /* Read DMA Upper Address */
#define PCIE_TLP_RDDMALOWER 0x020 /* Read DMA Lower Address */
#define PCIE_TLP_RDDMALENREG 0x024 /* Read DMA Len Req */
#define PCIE_TLP_MSIDMAUPPER 0x028 /* MSI DMA Upper Address */
#define PCIE_TLP_MSIDMALOWER 0x02C /* MSI DMA Lower Address */
#define PCIE_TLP_MSIDMALENREG 0x030 /* MSI DMA Len Req */
#define PCIE_TLP_SLVREQLENREG 0x034 /* Slave Request Len */
#define PCIE_TLP_FCINPUTSREQ 0x038 /* Flow Control Inputs */
#define PCIE_TLP_TXSMGRSREQ 0x03C /* Tx StateMachine and Gated Req */
#define PCIE_TLP_ADRACKCNTARBLEN 0x040 /* Address Ack XferCnt and ARB Len */
#define PCIE_TLP_DMACPLHDR0 0x044 /* DMA Completion Hdr 0 */
#define PCIE_TLP_DMACPLHDR1 0x048 /* DMA Completion Hdr 1 */
#define PCIE_TLP_DMACPLHDR2 0x04C /* DMA Completion Hdr 2 */
#define PCIE_TLP_DMACPLMISC0 0x050 /* DMA Completion Misc0 */
#define PCIE_TLP_DMACPLMISC1 0x054 /* DMA Completion Misc1 */
#define PCIE_TLP_DMACPLMISC2 0x058 /* DMA Completion Misc2 */
#define PCIE_TLP_SPTCTRLLEN 0x05C /* Split Controller Req len */
#define PCIE_TLP_SPTCTRLMSIC0 0x060 /* Split Controller Misc 0 */
#define PCIE_TLP_SPTCTRLMSIC1 0x064 /* Split Controller Misc 1 */
#define PCIE_TLP_BUSDEVFUNC 0x068 /* Bus/Device/Func */
#define PCIE_TLP_RESETCTR 0x06C /* Reset Counter */
#define PCIE_TLP_RTRYBUF 0x070 /* Retry Buffer value */
#define PCIE_TLP_TGTDEBUG1 0x074 /* Target Debug Reg1 */
#define PCIE_TLP_TGTDEBUG2 0x078 /* Target Debug Reg2 */
#define PCIE_TLP_TGTDEBUG3 0x07C /* Target Debug Reg3 */
#define PCIE_TLP_TGTDEBUG4 0x080 /* Target Debug Reg4 */
/* PCIE2 MDIO register offsets */
#define PCIE2_MDIO_CONTROL 0x128
#define PCIE2_MDIO_WR_DATA 0x12C
#define PCIE2_MDIO_RD_DATA 0x130
/* MDIO control */
#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
#define MDIOCTL_DIVISOR_VAL 0x2
#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */
#define MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */
/* MDIO Data */
#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */
#define MDIODATA_TA 0x00020000 /* Turnaround */
#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift (rev < 10) */
#define MDIODATA_REGADDR_MASK_OLD 0x003c0000 /* Regaddr Mask (rev < 10) */
#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift (rev < 10) */
#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */
#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */
#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */
#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */
#define MDIODATA_DEVADDR_MASK 0x0f800000 /* Physmedia devaddr Mask */
#define MDIODATA_WRITE 0x10000000 /* write Transaction */
#define MDIODATA_READ 0x20000000 /* Read Transaction */
#define MDIODATA_START 0x40000000 /* start of Transaction */
#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */
#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */
/* MDIO control/wrData/rdData register defines for PCIE Gen 2 */
#define MDIOCTL2_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
#define MDIOCTL2_DIVISOR_VAL 0x2
#define MDIOCTL2_REGADDR_SHF 8 /* Regaddr shift */
#define MDIOCTL2_REGADDR_MASK 0x00FFFF00 /* Regaddr Mask */
#define MDIOCTL2_DEVADDR_SHF 24 /* Physmedia devaddr shift */
#define MDIOCTL2_DEVADDR_MASK 0x0f000000 /* Physmedia devaddr Mask */
#define MDIOCTL2_SLAVE_BYPASS 0x10000000 /* IP slave bypass */
#define MDIOCTL2_READ 0x20000000 /* IP slave bypass */
#define MDIODATA2_DONE 0x80000000 /* rd/wr transaction done */
#define MDIODATA2_MASK 0x7FFFFFFF /* rd/wr transaction data */
#define MDIODATA2_DEVADDR_SHF 4 /* Physmedia devaddr shift */
/* MDIO devices (SERDES modules)
* unlike old pcie cores (rev < 10), rev10 pcie serde organizes registers into a few blocks.
* two layers mapping (blockidx, register offset) is required
*/
#define MDIO_DEV_IEEE0 0x000
#define MDIO_DEV_IEEE1 0x001
#define MDIO_DEV_BLK0 0x800
#define MDIO_DEV_BLK1 0x801
#define MDIO_DEV_BLK2 0x802
#define MDIO_DEV_BLK3 0x803
#define MDIO_DEV_BLK4 0x804
#define MDIO_DEV_TXPLL 0x808 /* TXPLL register block idx */
#define MDIO_DEV_TXCTRL0 0x820
#define MDIO_DEV_SERDESID 0x831
#define MDIO_DEV_RXCTRL0 0x840
/* XgxsBlk1_A Register Offsets */
#define BLK1_PWR_MGMT0 0x16
#define BLK1_PWR_MGMT1 0x17
#define BLK1_PWR_MGMT2 0x18
#define BLK1_PWR_MGMT3 0x19
#define BLK1_PWR_MGMT4 0x1A
/* serdes regs (rev < 10) */
#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */
#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */
#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */
/* SERDES RX registers */
#define SERDES_RX_CTRL 1 /* Rx cntrl */
#define SERDES_RX_TIMER1 2 /* Rx Timer1 */
#define SERDES_RX_CDR 6 /* CDR */
#define SERDES_RX_CDRBW 7 /* CDR BW */
/* SERDES RX control register */
#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */
#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */
/* SERDES PLL registers */
#define SERDES_PLL_CTRL 1 /* PLL control reg */
#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */
/* Power management threshold */
#define PCIE_L0THRESHOLDTIME_MASK 0xFF00 /* bits 0 - 7 */
#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */
#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */
#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */
#define PCIE_ASPMTIMER_EXTEND 0x01000000 /* > rev7: enable extend ASPM timer */
/* SPROM offsets */
#define SRSH_ASPM_OFFSET 4 /* word 4 */
#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */
#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */
#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */
#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */
#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */
#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */
#define SRSH_CLKREQ_OFFSET_REV8 52 /* word 52 for srom rev 8 */
#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */
#define SRSH_BD_OFFSET 6 /* word 6 */
#define SRSH_AUTOINIT_OFFSET 18 /* auto initialization enable */
/* Linkcontrol reg offset in PCIE Cap */
#define PCIE_CAP_LINKCTRL_OFFSET 16 /* linkctrl offset in pcie cap */
#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */
#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */
#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */
#define PCIE_LINKSPEED_MASK 0xF0000 /* bits 0 - 3 of high word */
#define PCIE_LINKSPEED_SHIFT 16 /* PCIE_LINKSPEED_SHIFT */
/* Devcontrol reg offset in PCIE Cap */
#define PCIE_CAP_DEVCTRL_OFFSET 8 /* devctrl offset in pcie cap */
#define PCIE_CAP_DEVCTRL_MRRS_MASK 0x7000 /* Max read request size mask */
#define PCIE_CAP_DEVCTRL_MRRS_SHIFT 12 /* Max read request size shift */
#define PCIE_CAP_DEVCTRL_MRRS_128B 0 /* 128 Byte */
#define PCIE_CAP_DEVCTRL_MRRS_256B 1 /* 256 Byte */
#define PCIE_CAP_DEVCTRL_MRRS_512B 2 /* 512 Byte */
#define PCIE_CAP_DEVCTRL_MRRS_1024B 3 /* 1024 Byte */
#define PCIE_CAP_DEVCTRL_MPS_MASK 0x00e0 /* Max payload size mask */
#define PCIE_CAP_DEVCTRL_MPS_SHIFT 5 /* Max payload size shift */
#define PCIE_CAP_DEVCTRL_MPS_128B 0 /* 128 Byte */
#define PCIE_CAP_DEVCTRL_MPS_256B 1 /* 256 Byte */
#define PCIE_CAP_DEVCTRL_MPS_512B 2 /* 512 Byte */
#define PCIE_CAP_DEVCTRL_MPS_1024B 3 /* 1024 Byte */
#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */
#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */
#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */
#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */
#define PCIE_ASPM_L11_ENAB 8 /* ASPM L1.1 in PML1_sub_control2 */
#define PCIE_ASPM_L12_ENAB 4 /* ASPM L1.2 in PML1_sub_control2 */
/* Devcontrol2 reg offset in PCIE Cap */
#define PCIE_CAP_DEVCTRL2_OFFSET 0x28 /* devctrl2 offset in pcie cap */
#define PCIE_CAP_DEVCTRL2_LTR_ENAB_MASK 0x400 /* Latency Tolerance Reporting Enable */
#define PCIE_CAP_DEVCTRL2_OBFF_ENAB_SHIFT 13 /* Enable OBFF mechanism, select signaling method */
#define PCIE_CAP_DEVCTRL2_OBFF_ENAB_MASK 0x6000 /* Enable OBFF mechanism, select signaling method */
/* LTR registers in PCIE Cap */
#define PCIE_LTR0_REG_OFFSET 0x844 /* ltr0_reg offset in pcie cap */
#define PCIE_LTR1_REG_OFFSET 0x848 /* ltr1_reg offset in pcie cap */
#define PCIE_LTR2_REG_OFFSET 0x84c /* ltr2_reg offset in pcie cap */
#define PCIE_LTR0_REG_DEFAULT_60 0x883c883c /* active latency default to 60usec */
#define PCIE_LTR0_REG_DEFAULT_150 0x88968896 /* active latency default to 150usec */
#define PCIE_LTR1_REG_DEFAULT 0x88648864 /* idle latency default to 100usec */
#define PCIE_LTR2_REG_DEFAULT 0x90039003 /* sleep latency default to 3msec */
/* Status reg PCIE_PLP_STATUSREG */
#define PCIE_PLP_POLARITYINV_STAT 0x10
/* PCIE BRCM Vendor CAP REVID reg bits */
#define BRCMCAP_PCIEREV_CT_MASK 0xF00
#define BRCMCAP_PCIEREV_CT_SHIFT 8
#define BRCMCAP_PCIEREV_REVID_MASK 0xFF
#define BRCMCAP_PCIEREV_REVID_SHIFT 0
#define PCIE_REVREG_CT_PCIE1 0
#define PCIE_REVREG_CT_PCIE2 1
/* PCIE GEN2 specific defines */
/* PCIE BRCM Vendor Cap offsets w.r.t to vendor cap ptr */
#define PCIE2R0_BRCMCAP_REVID_OFFSET 4
#define PCIE2R0_BRCMCAP_BAR0_WIN0_WRAP_OFFSET 8
#define PCIE2R0_BRCMCAP_BAR0_WIN2_OFFSET 12
#define PCIE2R0_BRCMCAP_BAR0_WIN2_WRAP_OFFSET 16
#define PCIE2R0_BRCMCAP_BAR0_WIN_OFFSET 20
#define PCIE2R0_BRCMCAP_BAR1_WIN_OFFSET 24
#define PCIE2R0_BRCMCAP_SPROM_CTRL_OFFSET 28
#define PCIE2R0_BRCMCAP_BAR2_WIN_OFFSET 32
#define PCIE2R0_BRCMCAP_INTSTATUS_OFFSET 36
#define PCIE2R0_BRCMCAP_INTMASK_OFFSET 40
#define PCIE2R0_BRCMCAP_PCIE2SB_MB_OFFSET 44
#define PCIE2R0_BRCMCAP_BPADDR_OFFSET 48
#define PCIE2R0_BRCMCAP_BPDATA_OFFSET 52
#define PCIE2R0_BRCMCAP_CLKCTLSTS_OFFSET 56
/* definition of configuration space registers of PCIe gen2
* http://hwnbu-twiki.sj.broadcom.com/twiki/pub/Mwgroup/CurrentPcieGen2ProgramGuide/pcie_ep.htm
*/
#define PCIECFGREG_STATUS_CMD 0x4
#define PCIECFGREG_PM_CSR 0x4C
#define PCIECFGREG_MSI_CAP 0x58
#define PCIECFGREG_MSI_ADDR_L 0x5C
#define PCIECFGREG_MSI_ADDR_H 0x60
#define PCIECFGREG_MSI_DATA 0x64
#define PCIECFGREG_LINK_STATUS_CTRL 0xBC
#define PCIECFGREG_LINK_STATUS_CTRL2 0xDC
#define PCIECFGREG_RBAR_CTRL 0x228
#define PCIECFGREG_PML1_SUB_CTRL1 0x248
#define PCIECFGREG_REG_BAR2_CONFIG 0x4E0
#define PCIECFGREG_REG_BAR3_CONFIG 0x4F4
#define PCIECFGREG_PDL_CTRL1 0x1004
#define PCIECFGREG_PDL_IDDQ 0x1814
#define PCIECFGREG_REG_PHY_CTL7 0x181c
/* PCIECFGREG_PML1_SUB_CTRL1 Bit Definition */
#define PCI_PM_L1_2_ENA_MASK 0x00000001 /* PCI-PM L1.2 Enabled */
#define PCI_PM_L1_1_ENA_MASK 0x00000002 /* PCI-PM L1.1 Enabled */
#define ASPM_L1_2_ENA_MASK 0x00000004 /* ASPM L1.2 Enabled */
#define ASPM_L1_1_ENA_MASK 0x00000008 /* ASPM L1.1 Enabled */
/* PCIe gen2 mailbox interrupt masks */
#define I_MB 0x3
#define I_BIT0 0x1
#define I_BIT1 0x2
/* PCIE gen2 config regs */
#define PCIIntstatus 0x090
#define PCIIntmask 0x094
#define PCISBMbx 0x98
/* enumeration Core regs */
#define PCIH2D_MailBox 0x140
#define PCIH2D_DB1 0x144
#define PCID2H_MailBox 0x148
#define PCIMailBoxInt 0x48
#define PCIMailBoxMask 0x4C
#define I_F0_B0 (0x1 << 8) /* Mail box interrupt Function 0 interrupt, bit 0 */
#define I_F0_B1 (0x1 << 9) /* Mail box interrupt Function 0 interrupt, bit 1 */
#define PCIECFGREG_DEVCONTROL 0xB4
/* SROM hardware region */
#define SROM_OFFSET_BAR1_CTRL 52
#define BAR1_ENC_SIZE_MASK 0x000e
#define BAR1_ENC_SIZE_SHIFT 1
#define BAR1_ENC_SIZE_1M 0
#define BAR1_ENC_SIZE_2M 1
#define BAR1_ENC_SIZE_4M 2
#define PCIEGEN2_CAP_DEVSTSCTRL2_OFFSET 0xD4
#define PCIEGEN2_CAP_DEVSTSCTRL2_LTRENAB 0x400
/*
* Latency Tolerance Reporting (LTR) states
* Active has the least tolerant latency requirement
* Sleep is most tolerant
*/
#define LTR_ACTIVE 2
#define LTR_ACTIVE_IDLE 1
#define LTR_SLEEP 0
#define LTR_FINAL_MASK 0x300
#define LTR_FINAL_SHIFT 8
/* pwrinstatus, pwrintmask regs */
#define PCIEGEN2_PWRINT_D0_STATE_SHIFT 0
#define PCIEGEN2_PWRINT_D1_STATE_SHIFT 1
#define PCIEGEN2_PWRINT_D2_STATE_SHIFT 2
#define PCIEGEN2_PWRINT_D3_STATE_SHIFT 3
#define PCIEGEN2_PWRINT_L0_LINK_SHIFT 4
#define PCIEGEN2_PWRINT_L0s_LINK_SHIFT 5
#define PCIEGEN2_PWRINT_L1_LINK_SHIFT 6
#define PCIEGEN2_PWRINT_L2_L3_LINK_SHIFT 7
#define PCIEGEN2_PWRINT_OBFF_CHANGE_SHIFT 8
#define PCIEGEN2_PWRINT_D0_STATE_MASK (1 << PCIEGEN2_PWRINT_D0_STATE_SHIFT)
#define PCIEGEN2_PWRINT_D1_STATE_MASK (1 << PCIEGEN2_PWRINT_D1_STATE_SHIFT)
#define PCIEGEN2_PWRINT_D2_STATE_MASK (1 << PCIEGEN2_PWRINT_D2_STATE_SHIFT)
#define PCIEGEN2_PWRINT_D3_STATE_MASK (1 << PCIEGEN2_PWRINT_D3_STATE_SHIFT)
#define PCIEGEN2_PWRINT_L0_LINK_MASK (1 << PCIEGEN2_PWRINT_L0_LINK_SHIFT)
#define PCIEGEN2_PWRINT_L0s_LINK_MASK (1 << PCIEGEN2_PWRINT_L0s_LINK_SHIFT)
#define PCIEGEN2_PWRINT_L1_LINK_MASK (1 << PCIEGEN2_PWRINT_L1_LINK_SHIFT)
#define PCIEGEN2_PWRINT_L2_L3_LINK_MASK (1 << PCIEGEN2_PWRINT_L2_L3_LINK_SHIFT)
#define PCIEGEN2_PWRINT_OBFF_CHANGE_MASK (1 << PCIEGEN2_PWRINT_OBFF_CHANGE_SHIFT)
/* sbtopcie mail box */
#define SBTOPCIE_MB_FUNC0_SHIFT 8
#define SBTOPCIE_MB_FUNC1_SHIFT 10
#define SBTOPCIE_MB_FUNC2_SHIFT 12
#define SBTOPCIE_MB_FUNC3_SHIFT 14
/* pcieiocstatus */
#define PCIEGEN2_IOC_D0_STATE_SHIFT 8
#define PCIEGEN2_IOC_D1_STATE_SHIFT 9
#define PCIEGEN2_IOC_D2_STATE_SHIFT 10
#define PCIEGEN2_IOC_D3_STATE_SHIFT 11
#define PCIEGEN2_IOC_L0_LINK_SHIFT 12
#define PCIEGEN2_IOC_L1_LINK_SHIFT 13
#define PCIEGEN2_IOC_L1L2_LINK_SHIFT 14
#define PCIEGEN2_IOC_L2_L3_LINK_SHIFT 15
#define PCIEGEN2_IOC_D0_STATE_MASK (1 << PCIEGEN2_IOC_D0_STATE_SHIFT)
#define PCIEGEN2_IOC_D1_STATE_MASK (1 << PCIEGEN2_IOC_D1_STATE_SHIF)
#define PCIEGEN2_IOC_D2_STATE_MASK (1 << PCIEGEN2_IOC_D2_STATE_SHIF)
#define PCIEGEN2_IOC_D3_STATE_MASK (1 << PCIEGEN2_IOC_D3_STATE_SHIF)
#define PCIEGEN2_IOC_L0_LINK_MASK (1 << PCIEGEN2_IOC_L0_LINK_SHIF)
#define PCIEGEN2_IOC_L1_LINK_MASK (1 << PCIEGEN2_IOC_L1_LINK_SHIF)
#define PCIEGEN2_IOC_L1L2_LINK_MASK (1 << PCIEGEN2_IOC_L1L2_LINK_SHIFT)
#define PCIEGEN2_IOC_L2_L3_LINK_MASK (1 << PCIEGEN2_IOC_L2_L3_LINK_SHIFT)
/* stat_ctrl */
#define PCIE_STAT_CTRL_RESET 0x1
#define PCIE_STAT_CTRL_ENABLE 0x2
#define PCIE_STAT_CTRL_INTENABLE 0x4
#define PCIE_STAT_CTRL_INTSTATUS 0x8
#ifdef BCMDRIVER
void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs);
#endif /* BCMDRIVER */
#endif /* _PCIE_CORE_H */

File diff suppressed because it is too large Load Diff

View File

@ -9,22 +9,24 @@
#ifndef _802_1_D_
#define _802_1_D_
#define PRIO_8021D_NONE 2
#define PRIO_8021D_BK 1
#define PRIO_8021D_BE 0
#define PRIO_8021D_EE 3
#define PRIO_8021D_CL 4
#define PRIO_8021D_VI 5
#define PRIO_8021D_VO 6
#define PRIO_8021D_NC 7
#define MAXPRIO 7
/* 802.1D priority defines */
#define PRIO_8021D_NONE 2 /* None = - */
#define PRIO_8021D_BK 1 /* BK - Background */
#define PRIO_8021D_BE 0 /* BE - Best-effort */
#define PRIO_8021D_EE 3 /* EE - Excellent-effort */
#define PRIO_8021D_CL 4 /* CL - Controlled Load */
#define PRIO_8021D_VI 5 /* Vi - Video */
#define PRIO_8021D_VO 6 /* Vo - Voice */
#define PRIO_8021D_NC 7 /* NC - Network Control */
#define MAXPRIO 7 /* 0-7 */
#define NUMPRIO (MAXPRIO + 1)
#define ALLPRIO -1
#define ALLPRIO -1 /* All prioirty */
/* Converts prio to precedence since the numerical value of
* PRIO_8021D_BE and PRIO_8021D_NONE are swapped.
*/
#define PRIO2PREC(prio) \
(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio))
#endif
#endif /* _802_1_D__ */

View File

@ -3,7 +3,7 @@
*
* Fundamental constants relating to 802.3
*
* $Id: 802.3.h 417942 2013-08-13 07:53:57Z $
* $Id: 802.3.h 417943 2013-08-13 07:54:04Z $
*/
#ifndef _802_3_h_

Some files were not shown because too many files have changed in this diff Show More