Merge remote-tracking branch 'common/linux-bcm43xx-2.6.39' into common-39
diff --git a/drivers/net/wireless/bcm4329/include/bcmspibrcm.h b/drivers/net/wireless/bcm4329/include/bcmspibrcm.h
deleted file mode 100644
index 9dce878..0000000
--- a/drivers/net/wireless/bcm4329/include/bcmspibrcm.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
- *
- * Copyright (C) 2010, Broadcom Corporation
- * All Rights Reserved.
- * 
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
- * the contents of this file may not be disclosed to third parties, copied
- * or duplicated in any form, in whole or in part, without the prior
- * written permission of Broadcom Corporation.
- *
- * $Id: bcmspibrcm.h,v 1.4.4.1.4.3.6.1 2008/09/27 17:03:25 Exp $
- */
-
-/* global msglevel for debug messages - bitvals come from sdiovar.h */
-
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-
-#define sd_log(x)
-
-#define SDIOH_ASSERT(exp) \
-	do { if (!(exp)) \
-		printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
-	} while (0)
-
-#define BLOCK_SIZE_F1		64
-#define BLOCK_SIZE_F2 		2048
-#define BLOCK_SIZE_F3 		2048
-
-/* internal return code */
-#define SUCCESS	0
-#undef ERROR
-#define ERROR	1
-#define ERROR_UF	2
-#define ERROR_OF	3
-
-/* private bus modes */
-#define SDIOH_MODE_SPI		0
-
-#define USE_BLOCKMODE		0x2	/* Block mode can be single block or multi */
-#define USE_MULTIBLOCK		0x4
-
-struct sdioh_info {
-	uint 		cfg_bar;		/* pci cfg address for bar */
-	uint32		caps;			/* cached value of capabilities reg */
-	void		*bar0;			/* BAR0 for PCI Device */
-	osl_t 		*osh;			/* osh handler */
-	void		*controller;	/* Pointer to SPI Controller's private data struct */
-
-	uint		lockcount; 		/* nest count of spi_lock() calls */
-	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 */
-	bool		initialized;		/* card initialized */
-	uint32		target_dev;		/* Target device ID */
-	uint32		intmask;		/* Current active interrupts */
-	void		*sdos_info;		/* Pointer to per-OS private data */
-
-	uint32		controller_type;	/* Host controller type */
-	uint8		version;		/* Host Controller Spec Compliance Version */
-	uint 		irq;			/* Client irq */
-	uint32 		intrcount;		/* Client interrupts */
-	uint32 		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_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 */
-						/*  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[SPI_MAX_IOFUNCS];		/* Blocksize */
-	uint32 		data_xfer_count;	/* Current transfer */
-	uint16 		card_rca;		/* Current Address */
-	uint8 		num_funcs;		/* Supported funcs on client */
-	uint32 		card_dstatus;		/* 32bit device status */
-	uint32 		com_cis_ptr;
-	uint32 		func_cis_ptr[SPI_MAX_IOFUNCS];
-	void		*dma_buf;
-	ulong		dma_phys;
-	int 		r_cnt;			/* rx count */
-	int 		t_cnt;			/* tx_count */
-	uint32		wordlen;			/* host processor 16/32bits */
-	uint32		prev_fun;
-	uint32		chip;
-	uint32		chiprev;
-	bool		resp_delay_all;
-	bool		dwordmode;
-
-	struct spierrstats_t spierrstats;
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmspibrcm.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/**************************************************************
- * Internal interfaces: bcmspibrcm.c references to per-port code
- */
-
-/* Interrupt (de)registration routines */
-extern int spi_register_irq(sdioh_info_t *sd, uint irq);
-extern void spi_free_irq(uint irq, sdioh_info_t *sd);
-
-/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
-extern void spi_lock(sdioh_info_t *sd);
-extern void spi_unlock(sdioh_info_t *sd);
-
-/* Allocate/init/free per-OS private data */
-extern int spi_osinit(sdioh_info_t *sd);
-extern void spi_osfree(sdioh_info_t *sd);
-
-#define SPI_RW_FLAG_M			BITFIELD_MASK(1)	/* Bit [31] - R/W Command Bit */
-#define SPI_RW_FLAG_S			31
-#define SPI_ACCESS_M			BITFIELD_MASK(1)	/* Bit [30] - Fixed/Incr Access */
-#define SPI_ACCESS_S			30
-#define SPI_FUNCTION_M			BITFIELD_MASK(2)	/* Bit [29:28] - Function Number */
-#define SPI_FUNCTION_S			28
-#define SPI_REG_ADDR_M			BITFIELD_MASK(17)	/* Bit [27:11] - Address */
-#define SPI_REG_ADDR_S			11
-#define SPI_LEN_M			BITFIELD_MASK(11)	/* Bit [10:0] - Packet length */
-#define SPI_LEN_S			0
diff --git a/drivers/net/wireless/bcm4329/include/spid.h b/drivers/net/wireless/bcm4329/include/spid.h
deleted file mode 100644
index c740296..0000000
--- a/drivers/net/wireless/bcm4329/include/spid.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * SPI device spec header file
- *
- * Copyright (C) 2010, Broadcom Corporation
- * All Rights Reserved.
- * 
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
- * the contents of this file may not be disclosed to third parties, copied
- * or duplicated in any form, in whole or in part, without the prior
- * written permission of Broadcom Corporation.
- *
- * $Id: spid.h,v 1.7.10.1.16.3 2009/04/09 19:23:14 Exp $
- */
-
-#ifndef	_SPI_H
-#define	_SPI_H
-
-/*
- * Brcm SPI Device Register Map.
- *
- */
-
-typedef volatile struct {
-	uint8	config;			/* 0x00, len, endian, clock, speed, polarity, wakeup */
-	uint8	response_delay;		/* 0x01, read response delay in bytes (corerev < 3) */
-	uint8	status_enable;		/* 0x02, status-enable, intr with status, response_delay
-					 * function selection, command/data error check
-					 */
-	uint8	reset_bp;		/* 0x03, reset on wlan/bt backplane reset (corerev >= 1) */
-	uint16	intr_reg;		/* 0x04, Intr status register */
-	uint16	intr_en_reg;		/* 0x06, Intr mask register */
-	uint32	status_reg;		/* 0x08, RO, Status bits of last spi transfer */
-	uint16	f1_info_reg;		/* 0x0c, RO, enabled, ready for data transfer, blocksize */
-	uint16	f2_info_reg;		/* 0x0e, RO, enabled, ready for data transfer, blocksize */
-	uint16	f3_info_reg;		/* 0x10, RO, enabled, ready for data transfer, blocksize */
-	uint32	test_read;		/* 0x14, RO 0xfeedbead signature */
-	uint32	test_rw;		/* 0x18, RW */
-	uint8	resp_delay_f0;		/* 0x1c, read resp delay bytes for F0 (corerev >= 3) */
-	uint8	resp_delay_f1;		/* 0x1d, read resp delay bytes for F1 (corerev >= 3) */
-	uint8	resp_delay_f2;		/* 0x1e, read resp delay bytes for F2 (corerev >= 3) */
-	uint8	resp_delay_f3;		/* 0x1f, read resp delay bytes for F3 (corerev >= 3) */
-} spi_regs_t;
-
-/* SPI device register offsets */
-#define SPID_CONFIG			0x00
-#define SPID_RESPONSE_DELAY		0x01
-#define SPID_STATUS_ENABLE		0x02
-#define SPID_RESET_BP			0x03	/* (corerev >= 1) */
-#define SPID_INTR_REG			0x04	/* 16 bits - Interrupt status */
-#define SPID_INTR_EN_REG		0x06	/* 16 bits - Interrupt mask */
-#define SPID_STATUS_REG			0x08	/* 32 bits */
-#define SPID_F1_INFO_REG		0x0C	/* 16 bits */
-#define SPID_F2_INFO_REG		0x0E	/* 16 bits */
-#define SPID_F3_INFO_REG		0x10	/* 16 bits */
-#define SPID_TEST_READ			0x14	/* 32 bits */
-#define SPID_TEST_RW			0x18	/* 32 bits */
-#define SPID_RESP_DELAY_F0		0x1c	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F1		0x1d	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F2		0x1e	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F3		0x1f	/* 8 bits (corerev >= 3) */
-
-/* Bit masks for SPID_CONFIG device register */
-#define WORD_LENGTH_32	0x1	/* 0/1 16/32 bit word length */
-#define ENDIAN_BIG	0x2	/* 0/1 Little/Big Endian */
-#define CLOCK_PHASE	0x4	/* 0/1 clock phase delay */
-#define CLOCK_POLARITY	0x8	/* 0/1 Idle state clock polarity is low/high */
-#define HIGH_SPEED_MODE	0x10	/* 1/0 High Speed mode / Normal mode */
-#define INTR_POLARITY	0x20	/* 1/0 Interrupt active polarity is high/low */
-#define WAKE_UP		0x80	/* 0/1 Wake-up command from Host to WLAN */
-
-/* Bit mask for SPID_RESPONSE_DELAY device register */
-#define RESPONSE_DELAY_MASK	0xFF	/* Configurable rd response delay in multiples of 8 bits */
-
-/* Bit mask for SPID_STATUS_ENABLE device register */
-#define STATUS_ENABLE		0x1	/* 1/0 Status sent/not sent to host after read/write */
-#define INTR_WITH_STATUS	0x2	/* 0/1 Do-not / do-interrupt if status is sent */
-#define RESP_DELAY_ALL		0x4	/* Applicability of resp delay to F1 or all func's read */
-#define DWORD_PKT_LEN_EN	0x8	/* Packet len denoted in dwords instead of bytes */
-#define CMD_ERR_CHK_EN		0x20	/* Command error check enable */
-#define DATA_ERR_CHK_EN		0x40	/* Data error check enable */
-
-/* Bit mask for SPID_RESET_BP device register */
-#define RESET_ON_WLAN_BP_RESET	0x4	/* enable reset for WLAN backplane */
-#define RESET_ON_BT_BP_RESET	0x8	/* enable reset for BT backplane */
-#define RESET_SPI		0x80	/* reset the above enabled logic */
-
-/* Bit mask for SPID_INTR_REG device register */
-#define DATA_UNAVAILABLE	0x0001	/* Requested data not available; Clear by writing a "1" */
-#define F2_F3_FIFO_RD_UNDERFLOW	0x0002
-#define F2_F3_FIFO_WR_OVERFLOW	0x0004
-#define COMMAND_ERROR		0x0008	/* Cleared by writing 1 */
-#define DATA_ERROR		0x0010	/* Cleared by writing 1 */
-#define F2_PACKET_AVAILABLE	0x0020
-#define F3_PACKET_AVAILABLE	0x0040
-#define F1_OVERFLOW		0x0080	/* Due to last write. Bkplane has pending write requests */
-#define MISC_INTR0		0x0100
-#define MISC_INTR1		0x0200
-#define MISC_INTR2		0x0400
-#define MISC_INTR3		0x0800
-#define MISC_INTR4		0x1000
-#define F1_INTR			0x2000
-#define F2_INTR			0x4000
-#define F3_INTR			0x8000
-
-/* Bit mask for 32bit SPID_STATUS_REG device register */
-#define STATUS_DATA_NOT_AVAILABLE	0x00000001
-#define STATUS_UNDERFLOW		0x00000002
-#define STATUS_OVERFLOW			0x00000004
-#define STATUS_F2_INTR			0x00000008
-#define STATUS_F3_INTR			0x00000010
-#define STATUS_F2_RX_READY		0x00000020
-#define STATUS_F3_RX_READY		0x00000040
-#define STATUS_HOST_CMD_DATA_ERR	0x00000080
-#define STATUS_F2_PKT_AVAILABLE		0x00000100
-#define STATUS_F2_PKT_LEN_MASK		0x000FFE00
-#define STATUS_F2_PKT_LEN_SHIFT		9
-#define STATUS_F3_PKT_AVAILABLE		0x00100000
-#define STATUS_F3_PKT_LEN_MASK		0xFFE00000
-#define STATUS_F3_PKT_LEN_SHIFT		21
-
-/* Bit mask for 16 bits SPID_F1_INFO_REG device register */
-#define F1_ENABLED 			0x0001
-#define F1_RDY_FOR_DATA_TRANSFER	0x0002
-#define F1_MAX_PKT_SIZE			0x01FC
-
-/* Bit mask for 16 bits SPID_F2_INFO_REG device register */
-#define F2_ENABLED 			0x0001
-#define F2_RDY_FOR_DATA_TRANSFER	0x0002
-#define F2_MAX_PKT_SIZE			0x3FFC
-
-/* Bit mask for 16 bits SPID_F3_INFO_REG device register */
-#define F3_ENABLED 			0x0001
-#define F3_RDY_FOR_DATA_TRANSFER	0x0002
-#define F3_MAX_PKT_SIZE			0x3FFC
-
-/* Bit mask for 32 bits SPID_TEST_READ device register read in 16bit LE mode */
-#define TEST_RO_DATA_32BIT_LE		0xFEEDBEAD
-
-/* Maximum number of I/O funcs */
-#define SPI_MAX_IOFUNCS		4
-
-#define SPI_MAX_PKT_LEN		(2048*4)
-
-/* Misc defines */
-#define SPI_FUNC_0		0
-#define SPI_FUNC_1		1
-#define SPI_FUNC_2		2
-#define SPI_FUNC_3		3
-
-#define WAIT_F2RXFIFORDY	100
-#define WAIT_F2RXFIFORDY_DELAY	20
-
-#endif /* _SPI_H */
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c
index f67b13a..89320b6 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh.c
@@ -22,7 +22,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.c 300445 2011-12-03 05:37:20Z $
+ * $Id: bcmsdh.c 344235 2012-07-11 23:47:18Z $
  */
 
 /**
@@ -362,9 +362,10 @@
 		}
 		bcopy(cis, tmp_buf, length);
 		for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); tmp_ptr++) {
-			ptr += sprintf((char*)ptr, "%.2x ", *tmp_ptr & 0xff);
+			ptr += snprintf((char*)ptr, (cis + length - ptr - 4),
+				"%.2x ", *tmp_ptr & 0xff);
 			if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
-				ptr += sprintf((char *)ptr, "\n");
+				ptr += snprintf((char *)ptr, (cis + length - ptr -4), "\n");
 		}
 		MFREE(bcmsdh->osh, tmp_buf, length);
 	}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
index d257dda..edecb5f 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
@@ -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_linux.c 312788 2012-02-03 23:06:32Z $
+ * $Id: bcmsdh_linux.c 343302 2012-07-06 13:07:38Z $
  */
 
 /**
@@ -684,6 +684,11 @@
 module_param(sd_uhsimode, int, 0);
 #endif
 
+#ifdef BCMSDIOH_TXGLOM
+extern uint sd_txglom;
+module_param(sd_txglom, uint, 0);
+#endif
+
 #ifdef BCMSDH_MODULE
 EXPORT_SYMBOL(bcmsdh_attach);
 EXPORT_SYMBOL(bcmsdh_detach);
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
index 374154f..67c2fbf 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
@@ -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.c 314904 2012-02-14 21:36:04Z $
+ * $Id: bcmsdh_sdmmc.c 344243 2012-07-12 00:06:23Z $
  */
 #include <typedefs.h>
 
@@ -799,41 +799,49 @@
 #if defined(MMC_SDIO_ABORT)
 			/* to allow abort command through F1 */
 			else if (regaddr == SDIOD_CCCR_IOABORT) {
-				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
-				*/
-				sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
-				sdio_release_host(gInstance->func[func]);
+				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
+					*/
+					sdio_writeb(gInstance->func[func],
+						*byte, regaddr, &err_ret);
+					sdio_release_host(gInstance->func[func]);
+				}
 			}
 #endif /* MMC_SDIO_ABORT */
 			else if (regaddr < 0xF0) {
 				sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
 			} else {
 				/* Claim host controller, perform F0 write, and release */
-				sdio_claim_host(gInstance->func[func]);
-				sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
-				sdio_release_host(gInstance->func[func]);
+				if (gInstance->func[func]) {
+					sdio_claim_host(gInstance->func[func]);
+					sdio_f0_writeb(gInstance->func[func],
+						*byte, regaddr, &err_ret);
+					sdio_release_host(gInstance->func[func]);
+				}
 			}
 		} else {
 			/* Claim host controller, perform Fn write, and release */
-			sdio_claim_host(gInstance->func[func]);
-			sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
-			sdio_release_host(gInstance->func[func]);
+			if (gInstance->func[func]) {
+				sdio_claim_host(gInstance->func[func]);
+				sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
+				sdio_release_host(gInstance->func[func]);
+			}
 		}
 	} else { /* CMD52 Read */
 		/* Claim host controller, perform Fn read, and release */
-		sdio_claim_host(gInstance->func[func]);
-
-		if (func == 0) {
-			*byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
-		} else {
-			*byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
+		if (gInstance->func[func]) {
+			sdio_claim_host(gInstance->func[func]);
+			if (func == 0) {
+				*byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
+			} else {
+				*byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
+			}
+			sdio_release_host(gInstance->func[func]);
 		}
-
-		sdio_release_host(gInstance->func[func]);
 	}
 
 	if (err_ret) {
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
index a78faeb..c93e41c 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
@@ -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 312783 2012-02-03 22:53:56Z $
+ * $Id: bcmsdh_sdmmc_linux.c 331154 2012-05-04 00:41:40Z $
  */
 
 #include <typedefs.h>
@@ -188,7 +188,6 @@
 
 	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)) {
@@ -202,7 +201,6 @@
 		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) */
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index 725a909..6106555 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -24,7 +24,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: dhd.h 333052 2012-05-12 02:09:28Z $
+ * $Id: dhd.h 344123 2012-07-11 09:33:49Z $
  */
 
 /****************
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
index 970216e..351c372 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
@@ -69,6 +69,9 @@
 	return 0;
 }
 
+/*
+ * dhd_cfg80211_set_p2p_info : gets called when GO or GC created
+ */
 s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
 {
 	dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
@@ -83,7 +86,7 @@
 	dhd_arp_offload_set(dhd, 0);
 	dhd_arp_offload_enable(dhd, false);
 #endif /* ARP_OFFLOAD_SUPPORT */
-
+	/* diable all filtering in p2p mode */
 	dhd_os_set_packet_filter(dhd, 0);
 
 	/* Setup timeout if Beacons are lost and roam is off to report link down */
@@ -94,6 +97,9 @@
 	return 0;
 }
 
+/*
+ * dhd_cfg80211_clean_p2p_info : gets called when GO or GC terminated
+ */
 s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
 {
 	dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
@@ -108,7 +114,6 @@
 	dhd_arp_offload_set(dhd, dhd_arp_mode);
 	dhd_arp_offload_enable(dhd, true);
 #endif /* ARP_OFFLOAD_SUPPORT */
-
 	dhd_os_set_packet_filter(dhd, 1);
 
 	/* Setup timeout if Beacons are lost and roam is off to report link down */
diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
index 9750eeb..de519a5 100644
--- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
@@ -20,7 +20,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: dhd_custom_gpio.c,v 1.2.42.1 2010-10-19 00:41:09 Exp $
+* $Id: dhd_custom_gpio.c 339054 2012-06-15 04:56:55Z $
 */
 
 #include <typedefs.h>
@@ -97,13 +97,13 @@
 #endif /* CUSTOMER_HW2 */
 
 	if (dhd_oob_gpio_num < 0) {
-		WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
+		WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined\n",
 			__FUNCTION__));
 		return (dhd_oob_gpio_num);
 	}
 
 	WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
-	         __FUNCTION__, dhd_oob_gpio_num));
+		__FUNCTION__, dhd_oob_gpio_num));
 
 #if defined CUSTOMER_HW
 	host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index d32ce11..4faef15 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -22,7 +22,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: dhd_linux.c 333885 2012-05-18 00:39:03Z $
+ * $Id: dhd_linux.c 344350 2012-07-12 08:35:03Z $
  */
 
 #include <typedefs.h>
@@ -1026,7 +1026,7 @@
 #endif
 			netif_stop_queue(ifp->net);
 			unregister_netdev(ifp->net);
-			ret = DHD_DEL_IF;
+			ret = DHD_DEL_IF;	/* Make sure the free_netdev() is called */
 
 #ifdef WL_CFG80211
 			if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
@@ -2648,7 +2648,9 @@
 	}
 
 	sema_init(&dhd->proto_sem, 1);
+#ifdef DHDTHREAD
 	sema_init(&dhd->sdsem, 1);
+#endif
 
 #ifdef PROP_TXSTATUS
 	spin_lock_init(&dhd->wlfc_spinlock);
@@ -3226,8 +3228,10 @@
 	setbit(eventmask, WLC_E_MIC_ERROR);
 	setbit(eventmask, WLC_E_ASSOC_REQ_IE);
 	setbit(eventmask, WLC_E_ASSOC_RESP_IE);
+#ifndef WL_CFG80211
 	setbit(eventmask, WLC_E_PMKID_CACHE);
 	setbit(eventmask, WLC_E_TXFAIL);
+#endif
 	setbit(eventmask, WLC_E_JOIN_START);
 	setbit(eventmask, WLC_E_SCAN_COMPLETE);
 #ifdef WLMEDIA_HTSF
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index e578d70..ed3da83 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -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: dhd_sdio.c 326662 2012-04-10 06:38:08Z $
+ * $Id: dhd_sdio.c 338148 2012-06-11 20:35:45Z $
  */
 
 #include <typedefs.h>
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 5df25c1..19da8f2 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -33,17 +33,17 @@
 
 #define	EPI_RC_NUMBER		195
 
-#define	EPI_INCREMENTAL_NUMBER	75
+#define	EPI_INCREMENTAL_NUMBER	98
 
 #define	EPI_BUILD_NUMBER	0
 
-#define	EPI_VERSION		5, 90, 195, 75
+#define	EPI_VERSION		5, 90, 195, 98
 
-#define	EPI_VERSION_NUM		0x055ac34b
+#define	EPI_VERSION_NUM		0x055ac362
 
 #define EPI_VERSION_DEV		5.90.195
 
 
-#define	EPI_VERSION_STR		"5.90.195.75"
+#define	EPI_VERSION_STR		"5.90.195.98"
 
 #endif 
diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h
index aa4df44..78ced30 100644
--- a/drivers/net/wireless/bcmdhd/include/sbchipc.h
+++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h
@@ -5,7 +5,7 @@
  * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer,
  * GPIO interface, extbus, and support for serial and parallel flashes.
  *
- * $Id: sbchipc.h 333924 2012-05-18 04:48:52Z $
+ * $Id: sbchipc.h 343982 2012-07-11 00:29:37Z $
  *
  * Copyright (C) 1999-2011, Broadcom Corporation
  * 
@@ -1726,6 +1726,11 @@
 #define SECI_MODE_SHIFT		4 
 #define SECI_UPD_SECI		(1 << 7)
 
+#define SECI_SLIP_ESC_CHAR	0xDB
+#define SECI_SIGNOFF_0		SECI_SLIP_ESC_CHAR
+#define SECI_SIGNOFF_1		0
+#define SECI_REFRESH_REQ	0xDA
+
 
 #define CLKCTL_STS_SECI_CLK_REQ		(1 << 8)
 #define CLKCTL_STS_SECI_CLK_AVAIL	(1 << 24)
diff --git a/drivers/net/wireless/bcmdhd/include/sdioh.h b/drivers/net/wireless/bcmdhd/include/sdioh.h
index 5f47d6f..1d820d1 100644
--- a/drivers/net/wireless/bcmdhd/include/sdioh.h
+++ b/drivers/net/wireless/bcmdhd/include/sdioh.h
@@ -22,7 +22,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: sdioh.h 300017 2011-12-01 20:30:27Z $
+ * $Id: sdioh.h 345478 2012-07-18 06:45:15Z $
  */
 
 #ifndef	_SDIOH_H
@@ -90,6 +90,10 @@
 #define SD3_PresetVal_SDR50		0x06a
 #define SD3_PresetVal_SDR104	0x06c
 #define SD3_PresetVal_DDR50		0x06e
+/* SDIO3.0 Revx specific Registers */
+#define SD3_Tuning_Info_Register 0x0EC
+#define SD3_WL_BT_reset_register 0x0F0
+
 
 /* preset value indices */
 #define SD3_PRESETVAL_INITIAL_IX	0
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 87d971a..723d398 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -358,6 +358,7 @@
 static s32 wl_iscan_pending(struct wl_priv *wl);
 static s32 wl_iscan_inprogress(struct wl_priv *wl);
 static s32 wl_iscan_aborted(struct wl_priv *wl);
+static void wl_scan_timeout_process(struct work_struct *work);
 
 /*
  * find most significant bit set
@@ -1518,6 +1519,8 @@
 	s32 passive_scan;
 	wl_scan_results_t *results;
 	WL_SCAN(("Enter \n"));
+
+	mutex_lock(&wl->usr_sync);
 	wl->escan_info.ndev = ndev;
 	wl->escan_info.wiphy = wiphy;
 	wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
@@ -1526,7 +1529,7 @@
 		&passive_scan, sizeof(passive_scan), false);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
-		return err;
+		goto exit;
 	}
 	results = (wl_scan_results_t *) wl->escan_info.escan_buf;
 	results->version = 0;
@@ -1534,6 +1537,8 @@
 	results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
 
 	err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
+exit:
+	mutex_unlock(&wl->usr_sync);
 	return err;
 }
 
@@ -1580,7 +1585,6 @@
 	/* Arm scan timeout timer */
 	mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
 	iscan_req = false;
-	wl->scan_request = request;
 	if (request) {		/* scan bss */
 		ssids = request->ssids;
 		if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
@@ -1661,6 +1665,7 @@
 		/* we don't do iscan in ibss */
 		ssids = this_ssid;
 	}
+	wl->scan_request = request;
 	wl_set_drv_status(wl, SCANNING, ndev);
 	if (iscan_req) {
 		err = wl_do_iscan(wl, request);
@@ -1724,12 +1729,9 @@
 
 scan_out:
 	wl_clr_drv_status(wl, SCANNING, ndev);
-	if (wl->scan_request) {
-		if (timer_pending(&wl->scan_timeout))
-			del_timer_sync(&wl->scan_timeout);
-		cfg80211_scan_done(wl->scan_request, true);
-		wl->scan_request = NULL;
-	}
+	if (timer_pending(&wl->scan_timeout))
+		del_timer_sync(&wl->scan_timeout);
+	wl->scan_request = NULL;
 	return err;
 }
 
@@ -1750,6 +1752,7 @@
 			wl->scan_busy_count++;
 			if (wl->scan_busy_count > WL_SCAN_BUSY_MAX) {
 				wl->scan_busy_count = 0;
+				WL_ERR(("Continuous scan failures!! Exercising FW hang recovery\n"));
 				net_os_send_hang_message(ndev);
 			}
 		}
@@ -3069,6 +3072,7 @@
 	s32 pm;
 	s32 err = 0;
 	struct wl_priv *wl = wiphy_priv(wiphy);
+	dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
 
 	CHECK_SYS_UP(wl);
 
@@ -3077,7 +3081,7 @@
 		return err;
 	}
 
-	pm = enabled ? PM_FAST : PM_OFF;
+	pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF;
 	pm = htod32(pm);
 	err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
 	if (unlikely(err)) {
@@ -3511,6 +3515,7 @@
 	wifi_p2p_ie_t *p2p_ie;
 	wpa_ie_fixed_t *wps_ie;
 	scb_val_t scb_val;
+	wifi_wfd_ie_t *wfd_ie;
 	const struct ieee80211_mgmt *mgmt;
 	struct wl_priv *wl = wiphy_priv(wiphy);
 	struct net_device *dev = NULL;
@@ -3518,6 +3523,7 @@
 	s32 bssidx = 0;
 	u32 p2pie_len = 0;
 	u32 wpsie_len = 0;
+	u32 wfdie_len = 0;
 	u32 id;
 	u32 retry = 0;
 	bool ack = false;
@@ -3567,6 +3573,11 @@
 				/* Total length of P2P Information Element */
 				p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
 			}
+			if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)(buf + ie_offset), ie_len))
+			    != NULL) {
+				/* Total length of WFD Information Element */
+				wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+			}
 			if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
 				!= NULL) {
 				/* Order of Vendor IE is 1) WPS IE +
@@ -3578,7 +3589,7 @@
 					sizeof(wps_ie->tag);
 				wl_cfgp2p_set_management_ie(wl, dev, bssidx,
 					VNDR_IE_PRBRSP_FLAG,
-					(u8 *)wps_ie, wpsie_len + p2pie_len);
+					(u8 *)wps_ie, wpsie_len + p2pie_len+ wfdie_len);
 			}
 			cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
 			goto exit;
@@ -4087,11 +4098,13 @@
 	wpa_ie_fixed_t *wpa_ie;
 	bcm_tlv_t *wpa2_ie;
 	wifi_p2p_ie_t *p2p_ie;
+	wifi_wfd_ie_t *wfd_ie;
 	bool is_bssup = false;
 	bool update_bss = false;
 	bool pbc = false;
 	u16 wpsie_len = 0;
 	u16 p2pie_len = 0;
+	u32 wfdie_len = 0;
 	u8 beacon_ie[IE_MAX_LEN];
 	s32 ie_offset = 0;
 	s32 bssidx = 0;
@@ -4149,10 +4162,24 @@
 		} else {
 			WL_ERR(("No P2PIE in beacon \n"));
 		}
+		/* find the WFD IEs */
+		if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)info->tail, info->tail_len)) != NULL) {
+			/* Total length of P2P Information Element */
+			wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+			if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) {
+				memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len);
+			} else {
+				WL_ERR(("Found WFD IE but there is no space, (%d)(%d)(%d)\n",
+					wpsie_len, p2pie_len, wfdie_len));
+				wfdie_len = 0;
+			}
+		} else {
+			WL_ERR(("No WFDIE in beacon \n"));
+		}
 		/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
 		wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
 		wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
-			beacon_ie, wpsie_len + p2pie_len);
+			beacon_ie, wpsie_len + p2pie_len + wfdie_len);
 
 		/* find the RSN_IE */
 		if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
@@ -4623,7 +4650,7 @@
 #endif
 		WIPHY_FLAG_4ADDR_STATION;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
-	wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+	/* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
 #endif
 	WL_DBG(("Registering custom regulatory)\n"));
 	wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
@@ -4714,8 +4741,9 @@
 	}
 	notif_bss_info->rssi = dtoh16(bi->RSSI);
 	memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
-	mgmt_type = wl->active_scan ?
-		IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
+	mgmt_type = (bi->flags & WL_BSS_FLAGS_FROM_BEACON) ?
+			 IEEE80211_STYPE_BEACON : IEEE80211_STYPE_PROBE_RESP;
+
 	if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
 	    mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
 	}
@@ -4744,7 +4772,7 @@
 		return -EINVAL;
 	}
 
-	WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM "
+	WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
 			"mgmt_type %d frame_len %d\n", bi->SSID,
 			notif_bss_info->rssi, notif_bss_info->channel,
 			mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
@@ -6018,7 +6046,9 @@
 	unsigned long flags;
 
 	WL_DBG(("Enter \n"));
-	wl->scan_busy_count = 0;
+	if(!aborted)
+		wl->scan_busy_count = 0;
+
 	if (!wl_get_drv_status(wl, SCANNING, ndev)) {
 		wl_clr_drv_status(wl, SCANNING, ndev);
 		WL_ERR(("Scan complete while device not scanning\n"));
@@ -6175,13 +6205,30 @@
 {
 	struct wl_priv *wl = (struct wl_priv *)data;
 
+	schedule_work(&wl->work_scan_timeout);
+}
+
+static void wl_scan_timeout_process(struct work_struct *work)
+{
+	struct wl_priv *wl;
+
+	wl = (wl_priv_t *)container_of(work, wl_priv_t, work_scan_timeout);
+
 	if (wl->scan_request) {
 		WL_ERR(("timer expired\n"));
 		if (wl->escan_on)
-			wl_notify_escan_complete(wl, wl->escan_info.ndev, true, false);
+			wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
 		else
 			wl_notify_iscan_complete(wl_to_iscan(wl), true);
 	}
+
+	/* Assume FW is in bad state if there are continuous scan timeouts */
+	wl->scan_busy_count++;
+	if (wl->scan_busy_count > WL_SCAN_BUSY_MAX) {
+		wl->scan_busy_count = 0;
+		WL_ERR(("Continuous scan timeouts!! Exercising FW hang recovery\n"));
+		net_os_send_hang_message(wl->escan_info.ndev);
+	}
 }
 
 static void wl_iscan_timer(unsigned long data)
@@ -6273,7 +6320,9 @@
 
 	WL_DBG(("Enter \n"));
 
-	wl->scan_busy_count = 0;
+	if(!aborted)
+		wl->scan_busy_count = 0;
+
 	if (wl->scan_request) {
 		if (wl->scan_request->dev == wl->p2p_net)
 			dev = wl_to_prmry_ndev(wl);
@@ -6344,8 +6393,11 @@
 	u32 i;
 	wifi_p2p_ie_t * p2p_ie;
 	u8 *p2p_dev_addr = NULL;
+
 	WL_DBG((" enter event type : %d, status : %d \n",
 		ntoh32(e->event_type), ntoh32(e->status)));
+
+	mutex_lock(&wl->usr_sync);
 	/* P2P SCAN is coming from primary interface */
 	if (wl_get_p2p_status(wl, SCANNING)) {
 		if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
@@ -6358,7 +6410,7 @@
 		!wl_get_drv_status(wl, SCANNING, ndev)) {
 		WL_ERR(("escan is not ready ndev %p wl->escan_on %d drv_status 0x%x\n",
 			ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev)));
-		return err;
+		goto exit;
 	}
 
 	if (status == WLC_E_STATUS_PARTIAL) {
@@ -6448,7 +6500,6 @@
 						bss->RSSI = bi->RSSI;
 						bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
 					}
-
 					goto exit;
 				}
 			}
@@ -6456,7 +6507,6 @@
 			list->version = dtoh32(bi->version);
 			list->buflen += bi_length;
 			list->count++;
-
 		}
 
 	}
@@ -6469,12 +6519,10 @@
 			if (wl->afx_hdl->peer_chan == WL_INVALID)
 				complete(&wl->act_frm_scan);
 		} else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
-			mutex_lock(&wl->usr_sync);
 			WL_INFO(("ESCAN COMPLETED\n"));
 			wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
 			wl_inform_bss(wl);
 			wl_notify_escan_complete(wl, ndev, false, false);
-			mutex_unlock(&wl->usr_sync);
 		}
 	}
 	else if (status == WLC_E_STATUS_ABORT) {
@@ -6486,14 +6534,15 @@
 			if (wl->afx_hdl->peer_chan == WL_INVALID)
 				complete(&wl->act_frm_scan);
 		} else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
-			mutex_lock(&wl->usr_sync);
 			WL_INFO(("ESCAN ABORTED\n"));
 			wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
 			wl_inform_bss(wl);
 			wl_notify_escan_complete(wl, ndev, true, false);
-			mutex_unlock(&wl->usr_sync);
 		}
 	}
+	else if (status == WLC_E_STATUS_NEWSCAN) {
+		 /* Do Nothing. Ignore this event */
+	}
 	else {
 		WL_ERR(("unexpected Escan Event %d : abort\n", status));
 		wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
@@ -6504,14 +6553,13 @@
 			if (wl->afx_hdl->peer_chan == WL_INVALID)
 				complete(&wl->act_frm_scan);
 		} else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
-			mutex_lock(&wl->usr_sync);
 			wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
 			wl_inform_bss(wl);
 			wl_notify_escan_complete(wl, ndev, true, false);
-			mutex_unlock(&wl->usr_sync);
 		}
 	}
 exit:
+	mutex_unlock(&wl->usr_sync);
 	return err;
 }
 
@@ -6574,6 +6622,7 @@
 		return -ENOMEM;
 	wl_init_event_handler(wl);
 	mutex_init(&wl->usr_sync);
+	INIT_WORK(&wl->work_scan_timeout, wl_scan_timeout_process);
 	err = wl_init_scan(wl);
 	if (err)
 		return err;
@@ -6593,6 +6642,7 @@
 	wl_link_down(wl);
 	del_timer_sync(&wl->scan_timeout);
 	wl_term_iscan(wl);
+	cancel_work_sync(&wl->work_scan_timeout);
 	wl_deinit_priv_mem(wl);
 	unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
 }
@@ -7097,6 +7147,10 @@
 			band = IEEE80211_BAND_5GHZ;
 			ht40_allowed = (bw_cap == WLC_N_BW_20ALL) ? FALSE : TRUE;
 		}
+		else {
+			WL_ERR(("Invalid Channel received %x\n", channel));
+			continue;
+		}
 
 		for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
 			if (band_chan_arr[j].hw_value == channel) {
@@ -7225,7 +7279,7 @@
 			wiphy->bands[IEEE80211_BAND_2GHZ] =
 				&__wl_band_2ghz;
 			index = IEEE80211_BAND_2GHZ;
-			if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL)
+			if (bw_cap == WLC_N_BW_40ALL)
 				wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
 		}
 		if ((index >= 0) && nmode) {
@@ -7234,6 +7288,7 @@
 			wiphy->bands[index]->ht_cap.ht_supported = TRUE;
 			wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 			wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+			wiphy->bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
 		}
 	}
 
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 49bed70..974770e 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -61,13 +61,24 @@
 /* 0 invalidates all debug messages.  default is 1 */
 #define WL_DBG_LEVEL 0xFF
 
-#define	WL_ERR(args)									\
+#if defined(DHD_DEBUG)
+#define	WL_ERR(args)								\
 do {										\
-	if (wl_dbg_level & WL_DBG_ERR) {				\
+	if (wl_dbg_level & WL_DBG_ERR) {					\
 			printk(KERN_ERR "CFG80211-ERROR) %s : ", __func__);	\
 			printk args;						\
 		} 								\
 } while (0)
+#else /* defined(DHD_DEBUG) */
+#define	WL_ERR(args)								\
+do {										\
+	if ((wl_dbg_level & WL_DBG_ERR) && net_ratelimit())  {			\
+			printk(KERN_INFO "CFG80211-ERROR) %s : ", __func__);	\
+			printk args;						\
+		} 								\
+} while (0)
+#endif /* defined(DHD_DEBUG) */
+
 #ifdef WL_INFO
 #undef WL_INFO
 #endif
@@ -387,7 +398,7 @@
 };
 
 /* private data of cfg80211 interface */
-struct wl_priv {
+typedef struct wl_priv {
 	struct wireless_dev *wdev;	/* representing wl cfg80211 device */
 
 	struct wireless_dev *p2p_wdev;	/* representing wl cfg80211 device for P2P */
@@ -457,7 +468,9 @@
 	u16 hostapd_chan;            /* remember chan requested by framework for hostapd  */
 	u16 deauth_reason;           /* Place holder to save deauth/disassoc reasons */
 	u16 scan_busy_count;
-};
+	struct work_struct work_scan_timeout;
+} wl_priv_t;
+
 
 static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
 {
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index bdcfa953..f06ae50 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -641,8 +641,8 @@
 	}
 set_ie:
 	ret = wl_cfgp2p_set_management_ie(wl, dev,
-	            wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE),
-	            VNDR_IE_PRBREQ_FLAG, ie, ie_len);
+				wl_cfgp2p_find_idx(wl, dev),
+				VNDR_IE_PRBREQ_FLAG, ie, ie_len);
 
 	if (unlikely(ret < 0)) {
 		CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
@@ -846,6 +846,11 @@
 /* Check whether the given IE looks like WFA P2P IE. */
 #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
 		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
+	/* Check whether the given IE looks like WFA WFDisplay IE. */
+#define WFA_OUI_TYPE_WFD	0x0a			/* WiFi Display OUI TYPE */
+#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
+				(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
+
 /* Delete and Set a management vndr ie to firmware
  * Parameters:
  * @wl       : wl_private data
@@ -970,7 +975,8 @@
 				ie_len = ie_buf[pos++];
 				if ((ie_id == DOT11_MNG_VS_ID) &&
 				   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
-					wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+					wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
+					wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
 					CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :"
 						"%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
 						ie_buf[pos+1], ie_buf[pos+2]));
@@ -996,7 +1002,8 @@
 				ie_len = ie_buf[pos++];
 				if ((ie_id == DOT11_MNG_VS_ID) &&
 				   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
-					wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+					wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
+					wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
 					CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :"
 						"%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
 						ie_buf[pos+1], ie_buf[pos+2]));
@@ -1107,6 +1114,19 @@
 	return NULL;
 }
 
+wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
+{
+	bcm_tlv_t *ie;
+
+	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+		if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
+			return (wifi_wfd_ie_t *)ie;
+		}
+	}
+	return NULL;
+}
+
 static s32
 wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
             s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete)
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index 05323ed..03a645a 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -31,6 +31,8 @@
 struct wl_priv;
 extern u32 wl_dbg_level;
 
+typedef struct wifi_p2p_ie wifi_wfd_ie_t;
+
 /* Enumeration of the usages of the BSSCFGs used by the P2P Library.  Do not
  * confuse this with a bsscfg index.  This value is an index into the
  * saved_ie[] array of structures which in turn contains a bsscfg index field.
@@ -192,6 +194,9 @@
 extern wifi_p2p_ie_t *
 wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
 
+extern wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len);
+
 extern s32
 wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
             s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len);
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
index 51a8064..7bea3dc 100644
--- a/drivers/net/wireless/bcmdhd/wldev_common.c
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -334,8 +334,11 @@
 	scb_val_t scbval;
 	char smbuf[WLC_IOCTL_SMLEN];
 
-	if (!country_code)
+	if (!country_code) {
+		WLDEV_ERROR(("%s: set country failed for %s\n",
+			__FUNCTION__, country_code));
 		return error;
+	}
 
 	error = wldev_iovar_getbuf(dev, "country", &cspec, sizeof(cspec),
 		smbuf, sizeof(smbuf), NULL);