1. seandroid
  2. Untitled project
  3. kernel/common

Commits

Dmitry Shmidt  committed 4bc66bf

net: wireless: bcmdhd: Update to version 1.88.4

- Improve P2P concurrency
- Re-arch proptxstatus code
- Fix WMM (QoS) traffic differentiation test

Change-Id: Id204048255a5ab41913da260adf9154a350f7a77
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>

  • Participants
  • Parent commits cad1684
  • Branches android-3.4

Comments (0)

Files changed (111)

File drivers/net/wireless/bcmdhd/Makefile

View file
-# bcmdhd for 43241
+# bcmdhd
+#
+#
+#
+#
 #
 
 DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER                     \
 	-DKEEP_ALIVE -DGET_CUSTOM_MAC_ENABLE -DPKT_FILTER_SUPPORT             \
 	-DEMBEDDED_PLATFORM -DENABLE_INSMOD_NO_FW_LOAD -DPNO_SUPPORT          \
 	-DDHD_USE_IDLECOUNT -DSET_RANDOM_MAC_SOFTAP -DROAM_ENABLE -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                           \
-	-DCUSTOM_SDIO_F2_BLKSIZE=128                                          \
+	-DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST                            \
+	-DESCAN_RESULT_PATCH -DHT40_GO -DPASS_ARP_PACKET -DSDIO_CRC_ERROR_FIX \
+	-DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD          \
+	-DCUSTOM_SDIO_F2_BLKSIZE=128 -DSUPPORT_PM2_ONLY	-DWLTDLS              \
 	-Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
 
 DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o   \
 	dhd_linux_sched.o dhd_sdio.o bcmwifi_channels.o bcmevent.o hndpmu.o   \
-	bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o linux_osl.o            \
-	bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.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
 
 obj-$(CONFIG_BCMDHD) += bcmdhd.o
 bcmdhd-objs += $(DHDOFILES)

File drivers/net/wireless/bcmdhd/aiutils.c

View file
  * Misc utility routines for accessing chip-specific features
  * of the SiliconBackplane-based Broadcom chips.
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * 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: aiutils.c 347614 2012-07-27 10:24:51Z $
+ * $Id: aiutils.c 385510 2013-02-15 21:02:07Z $
  */
 #include <bcm_cfg.h>
 #include <typedefs.h>
 
 #define BCM47162_DMP() (0)
 #define BCM5357_DMP() (0)
+#define BCM4707_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)
 	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;
 	}
 }
 
 
-
+/* parse the enumeration rom to identify all cores */
 void
 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;
 
 		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));
 		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);
 					sii->oob_router = addrl;
 				}
 			}
-			if (cid != GMAC_COMMON_4706_CORE_ID)
+			if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID)
 				continue;
 		}
 
 			         (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)
 							"0x%x\n", addrh, sizeh, sizel));
 						SI_ERROR(("First Slave ASD for"
 							"core 0x%04x malformed "
-					          "(0x%08x)\n", cid, asd));
-					goto error;
+							"(0x%08x)\n", cid, asd));
+						goto error;
+					}
 				}
-		}
 			} while (1);
 		}
 		sii->coresba[idx] = addrl;
 		sii->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,
 			j++;
 		} while (asd != 0);
 
-		
+		/* Go through the ASDs for other slave ports */
 		for (i = 1; i < nsp; i++) {
 			j = 0;
 			do {
 			}
 		}
 
-		
+		/* Now get master wrappers */
 		for (i = 0; i < nmw; i++) {
 			asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
 			              &sizel, &sizeh);
 				sii->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,
 		}
 
 
-		
+		/* Don't record bridges */
 		if (br)
 			continue;
 
-		
+		/* Done with core */
 		sii->numcores++;
 	}
 
 	return;
 }
 
-
+/* 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)
 {
 	addr = sii->coresba[coreidx];
 	wrap = sii->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:
-		
+		/* map new one */
 		if (!sii->regs[coreidx]) {
 			sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
 			ASSERT(GOODREGS(sii->regs[coreidx]));
 		}
 		sii->curmap = regs = sii->regs[coreidx];
-		if (!sii->wrappers[coreidx]) {
+		if (!sii->wrappers[coreidx] && (wrap != 0)) {
 			sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
 			ASSERT(GOODREGS(sii->wrappers[coreidx]));
 		}
 	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)) {
 		}
 	}
 
-	
+	/* 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);
 	}
 		j++;
 	} while (asd != 0);
 
-	
+	/* Go through the ASDs for other slave ports */
 	for (i = 1; i < nsp; i++) {
 		j = 0;
 		do {
 	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)
 {
 	}
 }
 
-
+/* Return the size of the nth address space in the current core */
 uint32
 ai_addrspacesize(si_t *sih, uint asidx)
 {
 		SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
 		return sii->curidx;
 	}
+	if (BCM4707_DMP()) {
+		SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
+			__FUNCTION__));
+		return sii->curidx;
+	}
 	ai = sii->curwrap;
 
 	return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f);
 }
 
+uint
+ai_flag_alt(si_t *sih)
+{
+	si_info_t *sii;
+	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;
+	}
+	if (BCM5357_DMP()) {
+		SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
+		return sii->curidx;
+	}
+	if (BCM4707_DMP()) {
+		SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
+			__FUNCTION__));
+		return sii->curidx;
+	}
+	ai = sii->curwrap;
+
+	return ((R_REG(sii->osh, &ai->oobselouta30) >> AI_OOBSEL_1_SHIFT) & AI_OOBSEL_MASK);
+}
+
 void
 ai_setint(si_t *sih, int siflag)
 {
 	        ((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)
 {
 		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 (!sii->regs[coreidx]) {
 			sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx],
 			                            SI_CORE_SIZE);
 		}
 		r = (uint32 *)((uchar *)sii->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)) {
-			
+			/* 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 +
 	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);
 
 	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->ioctrl, bits);
-	dummy = R_REG(sii->osh, &ai->ioctrl);
-	BCM_REFERENCE(dummy);
-	OSL_DELAY(10);
-
 	W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
 	dummy = R_REG(sii->osh, &ai->resetctrl);
 	BCM_REFERENCE(dummy);
 	OSL_DELAY(1);
-}
 
+	W_REG(sii->osh, &ai->ioctrl, bits);
+	dummy = R_REG(sii->osh, &ai->ioctrl);
+	BCM_REFERENCE(dummy);
+	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)
 {
 	ASSERT(GOODREGS(sii->curwrap));
 	ai = sii->curwrap;
 
-	
+	/*
+	 * Must do the disable sequence first to work for arbitrary current core state.
+	 */
 	ai_core_disable(sih, (bits | resetbits));
 
-	
+	/*
+	 * Now do the initialization sequence.
+	 */
 	W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
 	dummy = R_REG(sii->osh, &ai->ioctrl);
 	BCM_REFERENCE(dummy);
 		          __FUNCTION__));
 		return;
 	}
+	if (BCM4707_DMP()) {
+		SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
+			__FUNCTION__));
+		return;
+	}
 
 	ASSERT(GOODREGS(sii->curwrap));
 	ai = sii->curwrap;
 		          __FUNCTION__));
 		return 0;
 	}
+	if (BCM4707_DMP()) {
+		SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
+			__FUNCTION__));
+		return 0;
+	}
 
 	ASSERT(GOODREGS(sii->curwrap));
 	ai = sii->curwrap;
 		          __FUNCTION__));
 		return 0;
 	}
+	if (BCM4707_DMP()) {
+		SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
+			__FUNCTION__));
+		return 0;
+	}
 
 	ASSERT(GOODREGS(sii->curwrap));
 	ai = sii->curwrap;

File drivers/net/wireless/bcmdhd/bcmevent.c

View file
 /*
  * bcmevent read-only data shared by kernel or app layers
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  *      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: bcmevent.c 370587 2012-11-22 09:32:38Z $
+ * $Id: bcmevent.c 389384 2013-03-06 12:20:17Z $
  */
 
 #include <typedefs.h>
 #include <proto/bcmeth.h>
 #include <proto/bcmevent.h>
 
-#if WLC_E_LAST != 107
+#if WLC_E_LAST != 125
 #error "You need to add an entry to bcmevent_names[] for the new event"
 #endif
 
 	{ WLC_E_ACTION_FRAME_RX, "ACTION_FRAME_RX" },
 	{ WLC_E_ACTION_FRAME_COMPLETE, "ACTION_FRAME_COMPLETE" },
 #endif
-#if 0 && (NDISVER >= 0x0620)
+#if 0 && (0>= 0x0620)
 	{ WLC_E_PRE_ASSOC_IND, "ASSOC_RECV" },
 	{ WLC_E_PRE_REASSOC_IND, "REASSOC_RECV" },
 	{ WLC_E_CHANNEL_ADOPTED, "CHANNEL_ADOPTED" },
 	{ 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" },
 #endif 
 	{ WLC_E_ESCAN_RESULT, "WLC_E_ESCAN_RESULT" },
 	{ WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "WLC_E_AF_OFF_CHAN_COMPLETE" },
 #ifdef WLTDLS
 	{ WLC_E_TDLS_PEER_EVENT, "TDLS_PEER_EVENT" },
 #endif /* WLTDLS */
+	{ WLC_E_NATIVE, "NATIVE" },
+#ifdef WLPKTDLYSTAT
+	{ WLC_E_PKTDELAY_IND, "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" },
+#ifdef WLWNM
+	{ WLC_E_WNM_STA_SLEEP, "WMM_STA_SLEEP" },
+#endif /* WLWNM */
+#if defined(WL_PROXDETECT)
+	{ WLC_E_PROXD, "WLC_E_PROXD" },
+#endif
+	{ WLC_E_CCA_CHAN_QUAL, "CCA_BASED_CHANNEL_QUALITY" },
 };
 
 const int bcmevent_names_size = ARRAYSIZE(bcmevent_names);

File drivers/net/wireless/bcmdhd/bcmsdh.c

View file
  *  BCMSDH interface glue
  *  implement bcmsdh API for SDIOH driver
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * 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.c 347614 2012-07-27 10:24:51Z $
+ * $Id: bcmsdh.c 373331 2012-12-07 04:46:22Z $
  */
 
 /**
 
 	return sdioh_gpioout(sd, gpio, enab);
 }
-
-#ifdef BCMSDIOH_TXGLOM
-void
-bcmsdh_glom_post(void *sdh, uint8 *frame, uint len)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
-	sdioh_glom_post(bcmsdh->sdioh, frame, 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 */

File drivers/net/wireless/bcmdhd/bcmsdh_linux.c

View file
 /*
  * SDIO access interface for drivers - linux specific (pci only)
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * 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_linux.c 347638 2012-07-27 11:39:03Z $
+ * $Id: bcmsdh_linux.c 384887 2013-02-13 13:23:52Z $
  */
 
 /**
 #include <bcmutils.h>
 #include <dngl_stats.h>
 #include <dhd.h>
-#endif /* defined(OOB_INTR_ONLY) */
-
+#endif 
 
 /**
  * SDIO Host Controller info
 	bool oob_irq_enable_flag;
 #if defined(OOB_INTR_ONLY)
 	spinlock_t irq_lock;
-#endif /* defined(OOB_INTR_ONLY) */
+#endif 
 };
 static bcmsdh_hc_t *sdhcinfo = NULL;
 
+struct device *pm_dev;
+
 /* driver info, initialized when bcmsdh_register is called */
 static bcmsdh_driver_t drvinfo = {NULL, NULL};
 
 /* forward declarations */
 static int __devinit bcmsdh_probe(struct device *dev);
 static int __devexit bcmsdh_remove(struct device *dev);
-#endif /* defined(BCMLXSDMMC) */
+#endif 
 
 #if !defined(BCMLXSDMMC)
 static
-#endif /* !defined(BCMLXSDMMC) */
+#endif 
 int bcmsdh_probe(struct device *dev)
 {
 	osl_t *osh = NULL;
-	bcmsdh_hc_t *sdhc = NULL;
+	bcmsdh_hc_t *sdhc = NULL, *sdhc_org = sdhcinfo;
 	ulong regs = 0;
 	bcmsdh_info_t *sdh = NULL;
 #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
 	struct platform_device *pdev;
 	struct resource *r;
-#endif /* !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) */
+#endif 
 	int irq = 0;
 	uint32 vendevid;
 	unsigned long irq_flags = 0;
 	pdev = to_platform_device(dev);
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	if (!r || irq == NO_IRQ)
+	if (!r || irq < 0)
 		return -ENXIO;
-#endif /* !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) */
+#endif 
 
 #if defined(OOB_INTR_ONLY)
 #ifdef HW_OOB
 	irq = dhd_customer_oob_irq_map(&irq_flags);
 	if  (irq < 0) {
 		SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__));
-		return 1;
+		goto err;
 	}
-#endif /* defined(OOB_INTR_ONLY) */
+#endif 
 	/* allocate SDIO Host Controller state info */
 	if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) {
 		SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
 		SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
 		goto err;
 	}
-#endif /* defined(BCMLXSDMMC) */
+#endif 
 	sdhc->sdh = sdh;
 	sdhc->oob_irq = irq;
 	sdhc->oob_flags = irq_flags;
 	sdhc->oob_irq_enable_flag = FALSE;
 #if defined(OOB_INTR_ONLY)
 	spin_lock_init(&sdhc->irq_lock);
-#endif /* defined(BCMLXSDMMC) */
+#endif 
 
 	/* chain SDIO Host Controller info together */
 	sdhc->next = sdhcinfo;
 	sdhcinfo = sdhc;
 
+#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+	if (!device_init_wakeup(dev, 1))
+		pm_dev = dev;
+#endif /* !CONFIG_HAS_WAKELOCK */
+
 	/* Read the vendor/device ID from the CIS */
 	vendevid = bcmsdh_query_device(sdh);
 	/* try to attach to the target device */
 		if (sdhc->sdh)
 			bcmsdh_detach(sdhc->osh, sdhc->sdh);
 		MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
+		sdhcinfo = sdhc_org;
 	}
 	if (osh)
 		osl_detach(osh);
 
 #if !defined(BCMLXSDMMC)
 static
-#endif /* !defined(BCMLXSDMMC) */
+#endif 
 int bcmsdh_remove(struct device *dev)
 {
 	bcmsdh_hc_t *sdhc, *prev;
 	osl_t *osh;
-
-	sdhc = sdhcinfo;
-	drvinfo.detach(sdhc->ch);
-	bcmsdh_detach(sdhc->osh, sdhc->sdh);
+	int sdhcinfo_null = false;
 
 	/* 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;
+			else {
+				if (sdhc->next != NULL) {
+					SDLX_MSG(("%s: more SDHC exist, should be care about it\n",
+						__FUNCTION__));
+				}
+				sdhcinfo_null = true;
+			}
 			break;
 		}
 		prev = sdhc;
 		return 0;
 	}
 
+	/* detach ch & sdhc if dev is valid */
+	drvinfo.detach(sdhc->ch);
+	bcmsdh_detach(sdhc->osh, sdhc->sdh);
+
+#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+	if (pm_dev) {
+		device_init_wakeup(pm_dev, 0);
+		pm_dev = NULL;
+	}
+#endif /* !CONFIG_HAS_WAKELOCK */
+
+	if (sdhcinfo_null == true)
+		sdhcinfo = NULL;
+
 	/* release SDIO Host Controller info */
 	osh = sdhc->osh;
 	MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
 
 #if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY)
 	dev_set_drvdata(dev, NULL);
-#endif /* !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY) */
+#endif 
 
 	return 0;
 }
 	/* 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;
 	}
 
 		if (error)
 			return -ENODEV;
 
-		error = enable_irq_wake(sdhcinfo->oob_irq);
+			error = enable_irq_wake(sdhcinfo->oob_irq);
 		if (error)
 			SDLX_MSG(("%s enable_irq_wake error=%d \n", __FUNCTION__, error));
 		sdhcinfo->oob_irq_registered = TRUE;
 		sdhcinfo->oob_irq_enable_flag = flag;
 		if (flag) {
 			enable_irq(sdhcinfo->oob_irq);
-			enable_irq_wake(sdhcinfo->oob_irq);
+				enable_irq_wake(sdhcinfo->oob_irq);
 		} else {
-			disable_irq_wake(sdhcinfo->oob_irq);
+				disable_irq_wake(sdhcinfo->oob_irq);
 			disable_irq(sdhcinfo->oob_irq);
 		}
 	}
 		sdhcinfo->oob_irq_registered = FALSE;
 	}
 }
-#endif /* defined(OOB_INTR_ONLY) */
+#endif 
 
 #if defined(BCMLXSDMMC)
 void *bcmsdh_get_drvdata(void)
 #ifdef BCMSDIOH_STD
 extern int sd_uhsimode;
 module_param(sd_uhsimode, int, 0);
+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);
-#endif
 
 #ifdef BCMSDH_MODULE
 EXPORT_SYMBOL(bcmsdh_attach);

File drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c

View file
 /*
  * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * 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.c 379078 2013-01-16 00:41:36Z $
+ * $Id: bcmsdh_sdmmc.c 386902 2013-02-22 09:10:37Z $
  */
 #include <typedefs.h>
 
 uint sd_hiok = FALSE;	/* Don't use hi-speed mode by default */
 uint sd_msglevel = 0x01;
 uint sd_use_dma = TRUE;
+
+
+#ifndef CUSTOM_RXCHAIN
+#define CUSTOM_RXCHAIN 0
+#endif
+
 DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
 DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
 DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
 	sd->sd_blockmode = TRUE;
 	sd->use_client_ints = TRUE;
 	sd->client_block_size[0] = 64;
-	sd->use_rxchain = FALSE;
+	sd->use_rxchain = CUSTOM_RXCHAIN;
 
 	gInstance->sd = sd;
 
 extern SDIOH_API_RC
 sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
 {
-	int err_ret;
+	int err_ret = 0;
 #if defined(MMC_SDIO_ABORT)
 	int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
 #endif
+
 	sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr));
 
 	DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
 					if (gInstance->func[func]) {
 						sdio_claim_host(gInstance->func[func]);
 						/*
-						* this sdio_f0_writeb() can be replaced with
-						* another api depending upon MMC driver change.
-						* As of this time, this is temporaray one
-						*/
+						 * this sdio_f0_writeb() can be replaced with
+						 * another api depending upon MMC driver change.
+						 * As of this time, this is temporaray one
+						 */
 						sdio_writeb(gInstance->func[func],
 							*byte, regaddr, &err_ret);
 						sdio_release_host(gInstance->func[func]);
 	}
 
 	if (err_ret) {
-		sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
-		                        rw ? "Write" : "Read", func, regaddr, *byte, err_ret));
+		if ((regaddr == 0x1001F) && (err_ret == -110)) {
+		} else {
+			sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
+				rw ? "Write" : "Read", func, regaddr, *byte, err_ret));
+		}
 	}
 
 	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
 	/* Claim host controller */
 	sdio_claim_host(gInstance->func[func]);
 
-	if(rw) { /* CMD53 Write */
+	if(rw) { /* CMD52 Write */
 		if (nbytes == 4) {
 			sdio_writel(gInstance->func[func], *word, addr, &err_ret);
 		} else if (nbytes == 2) {
 			if (gInstance->func[0]) {
 				sdio_claim_host(gInstance->func[0]);
 				/*
-				* this sdio_f0_writeb() can be replaced with another api
-				* depending upon MMC driver change.
-				* As of this time, this is temporaray one
-				*/
+				 * this sdio_f0_writeb() can be replaced with another api
+				 * depending upon MMC driver change.
+				 * As of this time, this is temporaray one
+				 */
 				sdio_writeb(gInstance->func[0],
 					func, SDIOD_CCCR_IOABORT, &err_ret);
 				sdio_release_host(gInstance->func[0]);
 		if (err_ret)
 #endif /* MMC_SDIO_ABORT */
 		{
-		sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x\n",
-		                        rw ? "Write" : "Read", err_ret));
+			sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
+				rw ? "Write" : "Read", err_ret));
 		}
 	}
 
 	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
 }
 
+
 static SDIOH_API_RC
 sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
                      uint addr, void *pkt)
 	bool fifo = (fix_inc == SDIOH_DATA_FIX);
 	uint32	SGCount = 0;
 	int err_ret = 0;
-	void *pnext, *pprev;
+	void *pnext;
 	uint ttl_len, dma_len, lft_len, xfred_len, pkt_len;
 	uint blk_num;
 	int blk_size;
 	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
 
 	ttl_len = xfred_len = 0;
+
 	/* at least 4 bytes alignment of skb buff is guaranteed */
 	for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext))
 		ttl_len += PKTLEN(sd->osh, pnext);
 
 	blk_size = sd->client_block_size[func];
-	if (!sd->use_rxchain || ttl_len <= blk_size) {
-		blk_num = 0;
-		dma_len = 0;
-	} else {
+	if (((!write && sd->use_rxchain) ||
+		0) && (ttl_len > blk_size)) {
 		blk_num = ttl_len / blk_size;
 		dma_len = blk_num * blk_size;
+	} else {
+		blk_num = 0;
+		dma_len = 0;
 	}
+
 	lft_len = ttl_len - dma_len;
 
 	sd_trace(("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n",
 		memset(&mmc_dat, 0, sizeof(struct mmc_data));
 
 		/* Set up DMA descriptors */
-		pprev = pkt;
 		for (pnext = pkt;
 		     pnext && dma_len;
 		     pnext = PKTNEXT(sd->osh, pnext)) {
 			       __FUNCTION__,
 			       write ? "write" : "read",
 			       err_ret));
-			sd_err(("%s:Disabling rxchain and fire it with PIO\n",
-			       __FUNCTION__));
-			sd->use_rxchain = FALSE;
-			pkt = pprev;
-			lft_len = ttl_len;
-		} else if (!fifo) {
+		}
+		if (!fifo) {
 			addr = addr + ttl_len - lft_len - dma_len;
 		}
 	}
 				xfred_len = 0;
 			}
 
-			/* Align Patch
-			 *  read or small packet(ex:BDC header) skip 32 byte align
-			 *  otherwise, padding DHD_SDALIGN for performance
-			 */
-			if (write == 0 || pkt_len < 32)
+			/* Align Patch */
+			if (!write || pkt_len < 32)
 				pkt_len = (pkt_len + 3) & 0xFFFFFFFC;
 			else if (pkt_len % blk_size)
 				pkt_len += blk_size - (pkt_len % blk_size);
  */
 extern SDIOH_API_RC
 sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func,
-                     uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
+	uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
 {
 	SDIOH_API_RC Status;
-	void *mypkt = NULL;
+	void *tmppkt;
+	void *orig_buf = NULL;
+	uint copylen = 0;
 
 	sd_trace(("%s: Enter\n", __FUNCTION__));
 
 	DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
 	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
-	/* Case 1: we don't have a packet. */
-	if (pkt == NULL) {
-		sd_data(("%s: Creating new %s Packet, len=%d\n",
-		         __FUNCTION__, write ? "TX" : "RX", buflen_u));
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-		if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) {
-#else
-		if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) {
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-			sd_err(("%s: PKTGET failed: len %d\n",
-			           __FUNCTION__, buflen_u));
-			return SDIOH_API_RC_FAIL;
-		}
 
-		/* For a write, copy the buffer data into the packet. */
-		if (write) {
-			bcopy(buffer, PKTDATA(sd->osh, mypkt), buflen_u);
-		}
-
-		Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
-
-		/* For a read, copy the packet data back to the buffer. */
-		if (!write) {
-			bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u);
-		}
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-		PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE);
-#else
-		PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE);
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-	} else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) {
-		/* Case 2: We have a packet, but it is unaligned. */
-
-		/* In this case, we cannot have a chain. */
+	if (pkt == NULL) {
+		/* Case 1: we don't have a packet. */
+		orig_buf = buffer;
+		copylen = buflen_u;
+	} else if ((ulong)PKTDATA(sd->osh, pkt) & DMA_ALIGN_MASK) {
+		/* Case 2: We have a packet, but it is unaligned.
+		 * in this case, we cannot have a chain.
+		 */
 		ASSERT(PKTNEXT(sd->osh, pkt) == NULL);
 
-		sd_data(("%s: Creating aligned %s Packet, len=%d\n",
-		         __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt)));
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-		if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) {
-#else
-		if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) {
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-			sd_err(("%s: PKTGET failed: len %d\n",
-			           __FUNCTION__, PKTLEN(sd->osh, pkt)));
+		orig_buf =	PKTDATA(sd->osh, pkt);
+		copylen = PKTLEN(sd->osh, pkt);
+	}
+
+	tmppkt = pkt;
+	if (copylen) {
+		tmppkt = PKTGET_STATIC(sd->osh, copylen, write ? TRUE : FALSE);
+		if (tmppkt == NULL) {
+			sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, copylen));
 			return SDIOH_API_RC_FAIL;
 		}
-
 		/* For a write, copy the buffer data into the packet. */
-		if (write) {
-			bcopy(PKTDATA(sd->osh, pkt),
-			      PKTDATA(sd->osh, mypkt),
-			      PKTLEN(sd->osh, pkt));
-		}
+		if (write)
+			bcopy(orig_buf, PKTDATA(sd->osh, tmppkt), copylen);
+	}
 
-		Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
+	Status = sdioh_request_packet(sd, fix_inc, write, func, addr, tmppkt);
 
+	if (copylen) {
 		/* For a read, copy the packet data back to the buffer. */
-		if (!write) {
-			bcopy(PKTDATA(sd->osh, mypkt),
-			      PKTDATA(sd->osh, pkt),
-			      PKTLEN(sd->osh, mypkt));
-		}
-#ifdef CONFIG_DHD_USE_STATIC_BUF
-		PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE);
-#else
-		PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE);
-#endif /* CONFIG_DHD_USE_STATIC_BUF */
-	} else { /* case 3: We have a packet and it is aligned. */
-		sd_data(("%s: Aligned %s Packet, direct DMA\n",
-		         __FUNCTION__, write ? "Tx" : "Rx"));
-		Status = sdioh_request_packet(sd, fix_inc, write, func, addr, pkt);
+		if (!write)
+			bcopy(PKTDATA(sd->osh, tmppkt), orig_buf, PKTLEN(sd->osh, tmppkt));
+		PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE);
 	}
 
 	return (Status);
 	int ret;
 	sdioh_info_t *sd = gInstance->sd;
 
-	if (!sd) return (0);
+	if (!sd) {
+		sd_err(("%s Failed, sd is NULL\n", __FUNCTION__));
+		return (0);
+	}
 
 	/* Need to do this stages as we can't enable the interrupt till
 		downloading of the firmware is complete, other wise polling

File drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c

View file
 /*
  * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * 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 381548 2013-01-28 17:25:38Z $
+ * $Id: bcmsdh_sdmmc_linux.c 383841 2013-02-08 00:10:58Z $
  */
 
 #include <typedefs.h>
 	if (func->num != 2)
 		return 0;
 
-	sd_trace_hw4(("%s Enter\n", __FUNCTION__));
-
+	sd_trace(("%s Enter\n", __FUNCTION__));
 	if (dhd_os_check_wakelock(bcmsdh_get_drvdata()))
 		return -EBUSY;
-
 	sdio_flags = sdio_get_host_pm_caps(func);
 
 	if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
 		sd_err(("%s: error while trying to keep power\n", __FUNCTION__));
 		return ret;
 	}
-
 #if defined(OOB_INTR_ONLY)
 	bcmsdh_oob_intr_set(0);
-#endif	/* defined(OOB_INTR_ONLY) */
+#endif 
 	dhd_mmc_suspend = TRUE;
 	smp_mb();
 
 {
 #if defined(OOB_INTR_ONLY)
 	struct sdio_func *func = dev_to_sdio_func(pdev);
-#endif /* defined(OOB_INTR_ONLY) */
-	sd_trace_hw4(("%s Enter\n", __FUNCTION__));
-
+#endif 
+	sd_trace(("%s Enter\n", __FUNCTION__));
 	dhd_mmc_suspend = FALSE;
 #if defined(OOB_INTR_ONLY)
 	if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata()))
 		bcmsdh_oob_intr_set(1);
-#endif /* (OOB_INTR_ONLY) */
+#endif 
+
 	smp_mb();
 	return 0;
 }
 		return -ENOMEM;
 
 	error = sdio_register_driver(&bcmsdh_sdmmc_driver);
-	if (error && gInstance) {
+	if (error) {
 		kfree(gInstance);
-		gInstance = 0;
+		gInstance = NULL;
 	}
 
 	return error;
 
 	sdio_unregister_driver(&bcmsdh_sdmmc_driver);
 
-	if (gInstance)
+	if (gInstance) {
 		kfree(gInstance);
+		gInstance = NULL;
+	}
 }

File drivers/net/wireless/bcmdhd/bcmutils.c

View file
 /*
  * Driver O/S-independent utility routines
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  *      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: bcmutils.c 312855 2012-02-04 02:01:18Z $
+ * $Id: bcmutils.c 380908 2013-01-24 12:26:18Z $
  */
 
 #include <bcm_cfg.h>
 }
 
 uint8 * BCMFASTPATH
-pktoffset(osl_t *osh, void *p,  uint offset)
+pktdataoffset(osl_t *osh, void *p,  uint offset)
 {
 	uint total = pkttotlen(osh, p);
 	uint pkt_off = 0, len = 0;
 	return (uint8*) (pdata+pkt_off);
 }
 
+
+/* given a offset in pdata, find the pkt seg hdr */
+void *
+pktoffset(osl_t *osh, void *p,  uint offset)
+{
+	uint total = pkttotlen(osh, p);
+	uint len = 0;
+
+	if (offset > total)
+		return NULL;
+
+	for (; p; p = PKTNEXT(osh, p)) {
+		len += PKTLEN(osh, p);
+		if (len > offset)
+			break;
+	}
+	return p;
+}
+
 /*
  * osl multiple-precedence packet queue
  * hi_prec is always >= the number of the highest non-empty precedence
 }
 
 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));
+	}
+
+	q->len--;
+
+	pq->len--;
+
+	PKTSETLINK(p, NULL);
+
+	return p;
+}
+
+void * BCMFASTPATH
 pktq_pdeq_tail(struct pktq *pq, int prec)
 {
 	struct pktq_prec *q;
 
 #endif /* BCMDRIVER */
 
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
 const unsigned char bcm_ctype[] = {
 
 	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 0-7 */
 
 	return (i == 6);
 }
+#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
 
 
 #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
 
 	eh = (struct ether_header *) pktdata;
 
-	if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) {
+	if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
 		uint16 vlan_tag;
 		int vlan_prio, dscp_prio = 0;
 
 		vlan_tag = ntoh16(evh->vlan_tag);
 		vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
 
-		if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) {
+		if (evh->ether_type == hton16(ETHER_TYPE_IP)) {
 			uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
 			uint8 tos_tc = IP_TOS46(ip_body);
 			dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
 			evh->vlan_tag = hton16(vlan_tag);
 			rc |= PKTPRIO_UPD;
 		}
-	} else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
+	} else if (eh->ether_type == hton16(ETHER_TYPE_IP)) {
 		uint8 *ip_body = pktdata + sizeof(struct ether_header);
 		uint8 tos_tc = IP_TOS46(ip_body);
 		priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
 #endif	/* BCMDRIVER */
 
 
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
 /*******************************************************************************
  * crc8
  *
 	}
 	return NULL;
 }
+#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
 
 #if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
 	defined(DHD_DEBUG)
 int
+bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
+{
+	int i, slen = 0;
+	uint32 bit, mask;
+	const char *name;
+	mask = bd->mask;
+	if (len < 2 || !buf)
+		return 0;
+
+	buf[0] = '\0';
+
+	for (i = 0;  (name = bd->bitfield[i].name) != NULL; i++) {
+		bit = bd->bitfield[i].bit;
+		if ((flags & mask) == bit) {
+			if (len > (int)strlen(name)) {
+				slen = strlen(name);
+				strncpy(buf, name, slen+1);
+			}
+			break;
+		}
+	}
+	return slen;
+}
+
+int
 bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
 {
 	int i;
 	}
 	printf("\n");
 }
+
+/* Look for vendor-specific IE with specified OUI and optional type */
+bcm_tlv_t *
+find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len)
+{
+	bcm_tlv_t *ie;
+	uint8 ie_len;
+
+	ie = (bcm_tlv_t*)tlvs;
+
+	/* make sure we are looking at a valid IE */
+	if (ie == NULL ||
+	    !bcm_valid_tlv(ie, tlvs_len))
+		return NULL;
+
+	/* Walk through the IEs looking for an OUI match */
+	do {
+		ie_len = ie->len;
+		if ((ie->id == DOT11_MNG_PROPR_ID) &&
+		    (ie_len >= (DOT11_OUI_LEN + type_len)) &&
+		    !bcmp(ie->data, voui, DOT11_OUI_LEN))
+		{
+			/* compare optional type */
+			if (type_len == 0 ||
+			    !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
+				return (ie);		/* a match */
+			}
+		}
+	} while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
+
+	return NULL;
+}
+
 #if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
 	defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
 #define SSID_FMT_BUF_LEN	((4 * DOT11_MAX_SSID_LEN) + 1)
 
 	return buf_len;
 }
+
+/* calculate a * b + c */
+void
+bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c)
+{
+#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;}
+	uint32 r1, r0;
+	uint32 a1, a0, b1, b0, t, cc = 0;
+
+	a1 = a >> 16;
+	a0 = a & 0xffff;
+	b1 = b >> 16;
+	b0 = b & 0xffff;
+
+	r0 = a0 * b0;
+	FORMALIZE(r0);
+
+	t = (a1 * b0) << 16;
+	FORMALIZE(t);
+
+	r0 += t;
+	FORMALIZE(r0);
+
+	t = (a0 * b1) << 16;
+	FORMALIZE(t);
+
+	r0 += t;
+	FORMALIZE(r0);
+
+	FORMALIZE(c);
+
+	r0 += c;
+	FORMALIZE(r0);
+
+	r0 |= (cc % 2) ? 0x80000000 : 0;
+	r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2);
+
+	*r_high = r1;
+	*r_low = r0;
+}
+
+/* calculate a / b */
+void
+bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
+{
+	uint32 a1 = a_high, a0 = a_low, r0 = 0;
+
+	if (b < 2)
+		return;
+
+	while (a1 != 0) {
+		r0 += (0xffffffff / b) * a1;
+		bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
+	}
+
+	r0 += a0 / b;
+	*r = r0;
+}
+
+#ifndef setbit     /* As in the header file */
+#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
+/* Set bit in byte array. */
+void
+setbit(void *array, uint bit)
+{
+	((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY);
+}
+
+/* Clear bit in byte array. */
+void
+clrbit(void *array, uint bit)
+{
+	((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY));
+}
+
+/* Test if bit is set in byte array. */
+bool
+isset(const void *array, uint bit)
+{
+	return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY)));
+}
+
+/* Test if bit is clear in byte array. */
+bool
+isclr(const void *array, uint bit)
+{
+	return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0);
+}
+#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */
+#endif /* setbit */

File drivers/net/wireless/bcmdhd/bcmwifi_channels.c

View file
  * Contents are wifi-specific, used by any kernel or app-level
  * software that might want wifi things as it grows.
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
 
 #include <bcm_cfg.h>
 #include <typedefs.h>
+#include <bcmutils.h>
 
 #ifdef BCMDRIVER
 #include <osl.h>
-#include <bcmutils.h>
 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
 #define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
 #else
 		return 0;
 
 	/* if we are looking at a 'g', then the first number was a band */
-	c = tolower(a[0]);
+	c = tolower((int)a[0]);
 	if (c == 'g') {
 		a ++; /* consume the char */
 
 		if (!read_uint(&a, &ctl_ch))
 			return 0;
 
-		c = tolower(a[0]);
+		c = tolower((int)a[0]);
 	}
 	else {
 		/* first number is channel, use default for band */
 	 * or '+80' if bw = 80, to make '80+80' bw.
 	 */
 
-	c = tolower(a[0]);
+	c = tolower((int)a[0]);
 
 	/* if we have a 2g/40 channel, we should have a l/u spec now */
 	if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) {
 
 	return chspec;
 }
+
 #endif /* D11AC_IOTYPES */
 
 /*
 
 	return freq;
 }
+
+/* These chan_info[] & lookup routines replicate those from wlc_phy.c because of BMAC split */
+static const struct chan_info {
+	uint16	chan;	/* channel number */
+	uint16	freq;	/* in MHz */
+} chan_info[] = {
+	/* 11b/11g */
+/* 0 */		{1,	2412},
+/* 1 */		{2,	2417},
+/* 2 */		{3,	2422},
+/* 3 */		{4,	2427},
+/* 4 */		{5,	2432},
+/* 5 */		{6,	2437},
+/* 6 */		{7,	2442},
+/* 7 */		{8,	2447},
+/* 8 */		{9,	2452},
+/* 9 */		{10,	2457},
+/* 10 */	{11,	2462},
+/* 11 */	{12,	2467},
+/* 12 */	{13,	2472},
+/* 13 */	{14,	2484},
+
+#ifdef BAND5G
+/* 11a japan high */
+/* 14 */	{34,	5170},
+/* 15 */	{38,	5190},
+/* 16 */	{42,	5210},
+/* 17 */	{46,	5230},
+
+/* 11a usa low */
+/* 18 */	{36,	5180},
+/* 19 */	{40,	5200},
+/* 20 */	{44,	5220},
+/* 21 */	{48,	5240},
+/* 22 */	{52,	5260},
+/* 23 */	{56,	5280},
+/* 24 */	{60,	5300},
+/* 25 */	{64,	5320},
+
+/* 11a Europe */
+/* 26 */	{100,	5500},
+/* 27 */	{104,	5520},
+/* 28 */	{108,	5540},
+/* 29 */	{112,	5560},
+/* 30 */	{116,	5580},
+/* 31 */	{120,	5600},
+/* 32 */	{124,	5620},
+/* 33 */	{128,	5640},
+/* 34 */	{132,	5660},
+/* 35 */	{136,	5680},
+/* 36 */	{140,	5700},
+
+/* 11a usa high, ref5 only */
+/* 37 */	{149,	5745},
+/* 38 */	{153,	5765},
+/* 39 */	{157,	5785},
+/* 40 */	{161,	5805},
+/* 41 */	{165,	5825},
+
+/* 11a japan */
+/* 42 */	{184,	4920},
+/* 43 */	{188,	4940},
+/* 44 */	{192,	4960},
+/* 45 */	{196,	4980},
+/* 46 */	{200,	5000},
+/* 47 */	{204,	5020},
+/* 48 */	{208,	5040},
+/* 49 */	{212,	5060},
+/* 50 */	{216,	5080}
+#endif /* BAND5G */
+};
+
+/*
+ * Converts channel frequency to channel number.
+ * Returns 0 if the frequency does not match any channel definition.
+ */
+uint
+wf_freq2channel(uint freq)
+{
+	uint i;
+
+	for (i = 0; i < ARRAYSIZE(chan_info); i++) {
+		if (chan_info[i].freq == freq)
+			return (chan_info[i].chan);
+	}
+	return (0);
+}
+
+/*
+ * Converts channel number to channel frequency.
+ * Returns 0 if the channel is out of range.
+ * Also used by some code in wlc_iw.c
+ */
+uint
+wf_channel2freq(uint channel)
+{
+	uint i;
+
+	for (i = 0; i < ARRAYSIZE(chan_info); i++)
+		if (chan_info[i].chan == channel)
+			return (chan_info[i].freq);
+	return (0);
+}

File drivers/net/wireless/bcmdhd/dhd.h

View file
  * Provides type definitions and function prototypes used to link the
  * DHD OS, bus, and protocol modules.
  *
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2013, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * 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.h 373887 2012-12-10 21:58:02Z $
+ * $Id: dhd.h 390859 2013-03-14 01:09:31Z $
  */
 
 /****************
 #include <wlioctl.h>
 #include <wlfc_proto.h>
 
+#if 0 && (0>= 0x0600)
+#include <wdf.h>
+#include <WdfMiniport.h>
+#endif 
 
+#if defined(KEEP_ALIVE)
+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
+#define KEEP_ALIVE_PERIOD 55000
+#define NULL_PKT_STR	"null_pkt"
+#endif /* KEEP_ALIVE */
 /* Forward decls */
 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_DATA		/* Ready for frame transfers */
 };
 
+#if 0 && (0>= 0x0600)
+/* Firmware requested operation mode */
+#define STA_MASK			0x0001
+#define HOSTAPD_MASK		0x0002
+#define WFD_MASK			0x0004
+#define SOFTAP_FW_MASK	0x0008
+#define P2P_GO_ENABLED		0x0010
+#define P2P_GC_ENABLED		0x0020
+#define CONCURENT_MASK		0x00F0
+#endif 
+
 enum dhd_op_flags {
 /* Firmware requested operation mode */
-	DHD_FLAG_STA_MODE				= BIT(0), /* STA only */
-	DHD_FLAG_HOSTAP_MODE				= BIT(1), /* SOFTAP only */
-	DHD_FLAG_P2P_MODE				= BIT(2), /* P2P Only */
+	DHD_FLAG_STA_MODE				= (1 << (0)), /* STA only */
+	DHD_FLAG_HOSTAP_MODE				= (1 << (1)), /* SOFTAP only */
+	DHD_FLAG_P2P_MODE				= (1 << (2)), /* P2P Only */
 	/* STA + P2P */
 	DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE),
-	DHD_FLAG_CONCURR_MULTI_CHAN_MODE		= BIT(4), /* STA + P2P */
+	DHD_FLAG_CONCURR_MULTI_CHAN_MODE		= (1 << (4)), /* STA + P2P */
 	/* Current P2P mode for P2P connection */
-	DHD_FLAG_P2P_GC_MODE				= BIT(5),
-	DHD_FLAG_P2P_GO_MODE				= BIT(6),
-	DHD_FLAG_MBSS_MODE				= BIT(7) /* MBSS in future */
+	DHD_FLAG_P2P_GC_MODE				= (1 << (5)),