bcm4329: Update to version 4.218.248.6

Auto-merge: no

Change-Id: I33451efb37f03abe4008d1bfeef378bc61249c69
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/bcm4329/src/bcmsdio/sys/bcmpcispi.c b/bcm4329/src/bcmsdio/sys/bcmpcispi.c
index ba3e0c5..1a8b671 100644
--- a/bcm4329/src/bcmsdio/sys/bcmpcispi.c
+++ b/bcm4329/src/bcmsdio/sys/bcmpcispi.c
@@ -1,7 +1,7 @@
 /*
  * Broadcom SPI over PCI-SPI Host Controller, low-level hardware driver
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, 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: bcmpcispi.c,v 1.22.2.4.4.5 2008/07/09 21:23:30 Exp $
+ * $Id: bcmpcispi.c,v 1.22.2.4.4.5.6.1 2010/08/13 00:26:05 Exp $
  */
 
 #include <typedefs.h>
@@ -606,18 +606,23 @@
 	spin_count = 0;
 	while ((SPIPCI_RREG(sd->osh, &regs->spih_stat) & SPIH_WFEMPTY) == 0) {
 		if (spin_count > SPI_SPIN_BOUND) {
-			ASSERT(FALSE); /* Spin bound exceeded */
+			sd_err(("%s: SPIH_WFEMPTY spin bits out of bound %u times \n",
+				__FUNCTION__, spin_count));
+			ASSERT(FALSE);
 		}
 		spin_count++;
 	}
-	spin_count = 0;
+
 	/* Wait for SPI Transfer state machine to return to IDLE state.
 	 * The state bits are only implemented in Rev >= 5 FPGA.  These
 	 * bits are hardwired to 00 for Rev < 5, so this check doesn't cause
 	 * any problems.
 	 */
+	spin_count = 0;
 	while ((SPIPCI_RREG(osh, &regs->spih_stat) & SPIH_STATE_MASK) != 0) {
 		if (spin_count > SPI_SPIN_BOUND) {
+			sd_err(("%s: SPIH_STATE_MASK spin bits out of bound %u times \n",
+				__FUNCTION__, spin_count));
 			ASSERT(FALSE);
 		}
 		spin_count++;
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh.c b/bcm4329/src/bcmsdio/sys/bcmsdh.c
index aed6859..4bf5889 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh.c
@@ -40,9 +40,7 @@
 
 #include <sdio.h>	/* sdio spec */
 
-/* Defines number of access retries to configuration registers */
 #define SDIOH_API_ACCESS_RETRY_LIMIT	2
-
 const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
 
 
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
index 0555f87..559f481 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
+++ b/bcm4329/src/bcmsdio/sys/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,v 1.42.10.10.2.12 2010/03/10 03:09:48 Exp $
+ * $Id: bcmsdh_linux.c,v 1.42.10.10.2.14.4.2 2010/09/15 00:30:11 Exp $
  */
 
 /**
@@ -75,7 +75,11 @@
 	bcmsdh_info_t *sdh;		/* SDIO Host Controller handle */
 	void *ch;
 	unsigned int oob_irq;
-	unsigned long oob_flags;
+	unsigned long oob_flags; /* OOB Host specifiction as edge and etc */
+	bool oob_irq_registered;
+#if defined(OOB_INTR_ONLY)
+	spinlock_t irq_lock;
+#endif
 };
 static bcmsdh_hc_t *sdhcinfo = NULL;
 
@@ -176,7 +180,7 @@
 #endif /* BCMLXSDMMC */
 	int irq = 0;
 	uint32 vendevid;
-	unsigned long irq_flags = IRQF_TRIGGER_FALLING;
+	unsigned long irq_flags = 0;
 
 #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
 	pdev = to_platform_device(dev);
@@ -187,6 +191,12 @@
 #endif /* BCMLXSDMMC */
 
 #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 */
 	irq = dhd_customer_oob_irq_map(&irq_flags);
 	if  (irq < 0) {
 		SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__));
@@ -225,6 +235,10 @@
 	sdhc->sdh = sdh;
 	sdhc->oob_irq = irq;
 	sdhc->oob_flags = irq_flags;
+	sdhc->oob_irq_registered = FALSE;	/* to make sure.. */
+#if defined(OOB_INTR_ONLY)
+	spin_lock_init(&sdhc->irq_lock);
+#endif
 
 	/* chain SDIO Host Controller info together */
 	sdhc->next = sdhcinfo;
@@ -338,7 +352,7 @@
 				/* slot only . Allows for having multiple */
 				/* WL devices at once in a PC */
 				/* Only one instance of dhd will be */
-				/* useable at a time */
+				/* usable at a time */
 				/* Upper word is bus number, */
 				/* lower word is slot number */
 				/* Default value of 0xFFFFffff turns this */
@@ -365,20 +379,21 @@
 		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));
+			          __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));
+		          __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) ||
@@ -439,7 +454,7 @@
 	pci_set_master(pdev);
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		SDLX_MSG(("%s: Cannot enble PCI device\n", __FUNCTION__));
+		SDLX_MSG(("%s: Cannot enable PCI device\n", __FUNCTION__));
 		goto err;
 	}
 	if (!(sdh = bcmsdh_attach(osh, (void *)(uintptr)pci_resource_start(pdev, 0),
@@ -566,15 +581,34 @@
 #endif /* BCMPLATFORM_BUS */
 }
 
+
+
 #if defined(OOB_INTR_ONLY)
+void bcmsdh_oob_intr_set(bool enable)
+{
+	static bool curstate = 1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
+	if (curstate != enable) {
+		if (enable)
+			enable_irq(sdhcinfo->oob_irq);
+		else
+			disable_irq_nosync(sdhcinfo->oob_irq);
+		curstate = enable;
+	}
+	spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
+}
+
 static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
 {
 	dhd_pub_t *dhdp;
 
 	dhdp = (dhd_pub_t *)dev_get_drvdata(sdhcinfo->dev);
 
+	bcmsdh_oob_intr_set(0);
+
 	if (dhdp == NULL) {
-		disable_irq(sdhcinfo->oob_irq);
 		SDLX_MSG(("Out of band GPIO interrupt fired way too early\n"));
 		return IRQ_HANDLED;
 	}
@@ -592,14 +626,18 @@
 
 	dev_set_drvdata(sdhcinfo->dev, dhdp);
 
-	/* 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 (!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 (error)
-		return -ENODEV;
-
-	set_irq_wake(sdhcinfo->oob_irq, 1);
+		set_irq_wake(sdhcinfo->oob_irq, 1);
+		sdhcinfo->oob_irq_registered = TRUE;
+	}
 
 	return 0;
 }
@@ -611,14 +649,7 @@
 	set_irq_wake(sdhcinfo->oob_irq, 0);
 	disable_irq(sdhcinfo->oob_irq);	/* just in case.. */
 	free_irq(sdhcinfo->oob_irq, NULL);
-}
-
-void bcmsdh_oob_intr_set(bool enable)
-{
-	if (enable)
-		enable_irq(sdhcinfo->oob_irq);
-	else
-		disable_irq(sdhcinfo->oob_irq);
+	sdhcinfo->oob_irq_registered = FALSE;
 }
 #endif /* defined(OOB_INTR_ONLY) */
 /* Module parameters specific to each host-controller driver */
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
index 48d3f37..bda9193 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/bcm4329/src/bcmsdio/sys/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,v 1.1.2.5.6.29 2010/03/19 17:16:08 Exp $
+ * $Id: bcmsdh_sdmmc.c,v 1.1.2.5.6.30.4.1 2010/09/02 23:12:21 Exp $
  */
 #include <typedefs.h>
 
@@ -55,7 +55,7 @@
 #if !defined(OOB_INTR_ONLY)
 static void IRQHandler(struct sdio_func *func);
 static void IRQHandlerF2(struct sdio_func *func);
-#endif
+#endif /* !defined(OOB_INTR_ONLY) */
 static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
 extern int sdio_reset_comm(struct mmc_card *card);
 
@@ -676,6 +676,8 @@
 	else
 		data = 4;	/* disable hw oob interrupt */
 
+	data |= 4;		/* Active HIGH */
+
 	status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
 	return status;
 }
@@ -1064,11 +1066,13 @@
 	return (Status);
 }
 
+/* this function performs "abort" for both of host & device */
 extern int
 sdioh_abort(sdioh_info_t *sd, uint func)
 {
+#if defined(MMC_SDIO_ABORT)
 	char t_func = (char) func;
-
+#endif /* defined(MMC_SDIO_ABORT) */
 	sd_trace(("%s: Enter\n", __FUNCTION__));
 
 #if defined(MMC_SDIO_ABORT)
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
index 196ad4f..8992a42 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
+++ b/bcm4329/src/bcmsdio/sys/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,v 1.1.2.5.6.15 2010/04/14 21:11:46 Exp $
+ * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.6.17 2010/08/13 00:36:19 Exp $
  */
 
 #include <typedefs.h>
@@ -39,13 +39,22 @@
 
 #if !defined(SDIO_VENDOR_ID_BROADCOM)
 #define SDIO_VENDOR_ID_BROADCOM		0x02d0
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
+#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
+
+#define SDIO_DEVICE_ID_BROADCOM_DEFAULT	0x0000
+
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
+#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB	0x0492	/* BCM94325SDGWB */
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
 #if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
-#define SDIO_DEVICE_ID_BROADCOM_4325	0x0000
+#define SDIO_DEVICE_ID_BROADCOM_4325	0x0493
 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
 #if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
 #define SDIO_DEVICE_ID_BROADCOM_4329	0x4329
 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
+#define SDIO_DEVICE_ID_BROADCOM_4319	0x4319
+#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
 
 #include <bcmsdh_sdmmc.h>
 
@@ -116,15 +125,18 @@
 	sd_info(("Function#: 0x%04x\n", func->num));
 
 	if (func->num == 2) {
-		sd_trace(("F2 found, calling bcmsdh_probe...\n"));
+		sd_trace(("F2 found, calling bcmsdh_remove...\n"));
 		bcmsdh_remove(&sdmmc_dev);
 	}
 }
 
 /* devices we support, null terminated */
 static const struct sdio_device_id bcmsdh_sdmmc_ids[] = {
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT) },
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) },
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) },
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329) },
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) },
 	{ /* end: all zeroes */				},
 };
 
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c
index 1046a17..e2e0ca6 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c
@@ -1,7 +1,7 @@
 /*
  * Broadcom SPI Host Controller Driver - Linux Per-port
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdstd.c b/bcm4329/src/bcmsdio/sys/bcmsdstd.c
index 0b1b575..0ca1f8f 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdstd.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdstd.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: bcmsdstd.c,v 1.64.4.1.4.4.2.17 2010/03/10 03:09:48 Exp $
+ * $Id: bcmsdstd.c,v 1.64.4.1.4.4.2.18 2010/08/17 17:00:48 Exp $
  */
 
 #include <typedefs.h>
@@ -119,7 +119,7 @@
 void
 sdstd_wreg16(sdioh_info_t *sd, uint reg, uint16 data)
 {
-	*(volatile uint16 *)(sd->mem_space + reg) = (volatile uint16) data;
+	*(volatile uint16 *)(sd->mem_space + reg) = (uint16)data;
 	sd_ctrl(("16: W Reg 0x%02x, Data 0x%x\n", reg, data));
 }
 
@@ -129,7 +129,7 @@
 	volatile uint16 data = *(volatile uint16 *)(sd->mem_space + reg);
 	sd_ctrl(("16: OR Reg 0x%02x, Val 0x%x\n", reg, val));
 	data |= val;
-	*(volatile uint16 *)(sd->mem_space + reg) = (volatile uint16)data;
+	*(volatile uint16 *)(sd->mem_space + reg) = (uint16)data;
 
 }
 static void
@@ -140,7 +140,7 @@
 	sd_ctrl(("16: MOD Reg 0x%02x, Mask 0x%x, Val 0x%x\n", reg, mask, val));
 	data &= ~mask;
 	data |= (val & mask);
-	*(volatile uint16 *)(sd->mem_space + reg) = (volatile uint16)data;
+	*(volatile uint16 *)(sd->mem_space + reg) = (uint16)data;
 }
 
 
@@ -155,7 +155,7 @@
 static inline void
 sdstd_wreg(sdioh_info_t *sd, uint reg, uint32 data)
 {
-	*(volatile uint32 *)(sd->mem_space + reg) = (volatile uint32)data;
+	*(volatile uint32 *)(sd->mem_space + reg) = (uint32)data;
 	sd_ctrl(("32: W Reg 0x%02x, Data 0x%x\n", reg, data));
 
 }
@@ -164,7 +164,7 @@
 static inline void
 sdstd_wreg8(sdioh_info_t *sd, uint reg, uint8 data)
 {
-	*(volatile uint8 *)(sd->mem_space + reg) = (volatile uint8)data;
+	*(volatile uint8 *)(sd->mem_space + reg) = (uint8)data;
 	sd_ctrl(("08: W Reg 0x%02x, Data 0x%x\n", reg, data));
 }
 static uint8
@@ -287,7 +287,7 @@
 	return SDIOH_API_RC_SUCCESS;
 }
 
-/* Configure callback to client when we recieve client interrupt */
+/* Configure callback to client when we receive client interrupt */
 extern SDIOH_API_RC
 sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
 {
@@ -2778,10 +2778,6 @@
 				data++;
 			}
 
-			/* Handle < 4 bytes.  wlc_pio.c currently (as of 12/20/05) truncates buflen
-			 * to be evenly divisable by 4.  However dongle passes arbitrary lengths,
-			 * so handle it here
-			 */
 			bytes = blocksize % 4;
 
 			/* If no leftover bytes, go to next block */
@@ -2898,7 +2894,8 @@
 }
 
 /* Reset and re-initialize the device */
-int sdioh_sdio_reset(sdioh_info_t *si)
+int
+sdioh_sdio_reset(sdioh_info_t *si)
 {
 	uint8 hreg;
 
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c
index 5746b08..a8b98e2 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c
@@ -1,7 +1,7 @@
 /*
  *  'Standard' SDIO HOST CONTROLLER driver - linux portion
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, 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: bcmsdstd_linux.c,v 1.11.18.2 2008/05/28 18:36:56 Exp $
+ * $Id: bcmsdstd_linux.c,v 1.11.18.2.16.1 2010/08/17 17:03:13 Exp $
  */
 
 #include <typedefs.h>
@@ -186,7 +186,9 @@
 
 	spin_lock_irqsave(&sdos->lock, flags);
 	if (sd->lockcount) {
-		sd_err(("%s: Already locked!\n", __FUNCTION__));
+		sd_err(("%s: Already locked! called from %p\n",
+		       __FUNCTION__,
+		       __builtin_return_address(0)));
 		ASSERT(sd->lockcount == 0);
 	}
 	sdstd_devintr_off(sd);
diff --git a/bcm4329/src/dhd/exe/dhdu.c b/bcm4329/src/dhd/exe/dhdu.c
index afd8b61..2d3ec73 100644
--- a/bcm4329/src/dhd/exe/dhdu.c
+++ b/bcm4329/src/dhd/exe/dhdu.c
@@ -828,7 +828,7 @@
 
 	UNUSED_PARAMETER(cmd);
 
-	memset(&sdreg, 0, sizeof(sdreg));
+	bzero(&sdreg, sizeof(sdreg));
 
 	/* arg count */
 	for (argc = 0; argv[argc]; argc++);
@@ -1880,7 +1880,7 @@
 	uint argc;
 	void *ptr = NULL;
 
-	memset(&sdreg, 0, sizeof(sdreg));
+	bzero(&sdreg, sizeof(sdreg));
 
 	/* arg count */
 	for (argc = 0; argv[argc]; argc++);
diff --git a/bcm4329/src/dhd/linux/Makefile b/bcm4329/src/dhd/linux/Makefile
index 768dd51..4d5a957 100644
--- a/bcm4329/src/dhd/linux/Makefile
+++ b/bcm4329/src/dhd/linux/Makefile
@@ -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: Makefile,v 1.55.2.6.2.10.6.28 2010/03/26 21:49:31 Exp $
+# $Id: Makefile,v 1.55.2.6.2.10.6.42 2010/08/20 00:15:16 Exp $
 #
 
 # Try a couple of places for LINUXDIR if not specified
@@ -161,17 +161,23 @@
 
 ifeq ($(CONFIG_NET_RADIO),y)
 CFILES +=  bcmwifi.c
-	ifeq ($(findstring -cfg-,-$(TARGET)-),)
-	CFILES += wl_iw.c
-	endif
+CFILES += wl_iw.c
 else
 	ifeq ($(CONFIG_WIRELESS_EXT),y)
 	CFILES += bcmwifi.c
-		ifeq ($(findstring -cfg-,-$(TARGET)-),)
-		CFILES += wl_iw.c
-		endif
+	CFILES += wl_iw.c
 	endif
 endif
+ifeq ($(BCM_KVER), 2.6)
+CFG80211_KVER:=$(shell echo $(LINUXVER) | cut -c5-6 | sed 's/3[1-9]/true/')
+ifeq ($(CFG80211_KVER), true)
+	ifeq ($(CONFIG_CFG80211),m)
+	DFLAGS += -DCONFIG_CFG80211
+	CFILES += wl_cfg80211.c
+	endif
+endif
+endif
+
 
 OFILES=$(CFILES:.c=.o)
 
@@ -221,10 +227,18 @@
 DFLAGS += -DSOFTAP
 CFILES += sha1.c md5.c
 endif
-ifneq ($(findstring -cfg-,-$(TARGET)-),)
-DFLAGS += -DWL_CFG80211
-CFILES += wl_cfg80211.c
-endif
+ifneq ($(findstring -nexus-,-$(TARGET)-),)
+DFLAGS += -DOEM_ANDROID -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT
+DFLAGS += -Dlinux
+DFLAGS += -DBCMDBG
+DFLAGS += -DDHD_USE_STATIC_BUF
+DFLAGS += -DCUSTOMER_HW2
+DFLAGS += -DCUSTOM_OOB_GPIO_NUM=152
+DFLAGS += -DOOB_INTR_ONLY
+DFLAGS += -DMMC_SDIO_ABORT
+DFLAGS += -DSOFTAP
+DFLAGS += -DPNO_SUPPORT
+else
 ifneq ($(findstring -oob-,-$(TARGET)-),)
 DFLAGS += -DOOB_INTR_ONLY
 DFLAGS += -DHW_OOB
@@ -234,6 +248,7 @@
 DFLAGS += -DSDIO_ISR_THREAD
 endif
 endif
+endif
 ifneq ($(findstring -sdmmc-,-$(TARGET)-),)
 DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS 
 CFILES += dhd_sdio.c bcmsdh_sdmmc.c bcmsdh.c bcmsdh_linux.c bcmsdh_sdmmc_linux.c
@@ -253,6 +268,13 @@
 DFLAGS += -DSANDGATE2G
 endif
 
+ifeq ($(OEM_ANDROID),1)
+DFLAGS += -DOEM_ANDROID -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT
+endif
+ifeq ($(OEM_CHROMIUMOS),1)
+DFLAGS += -DOEM_CHROMIUMOS -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT
+endif
+
 CFLAGS += -fshort-wchar $(DFLAGS) $(WFLAGS) $(IFLAGS) $(CUSTOM_FLAGS)
 
 
@@ -284,11 +306,10 @@
 
 TARGETS := \
 	dhd-cdc-usb dhd-cdc-sdstd \
-	dhd-cdc-sdspi-pci dhd-cdc-sdmmc-gpl dhd-cdc-sdmmc-oob-gpl \
+	dhd-cdc-sdspi-pci dhd-cdc-sdmmc-gpl dhd-cdc-sdmmc-oob-gpl dhd-cdc-sdmmc-nexus-gpl\
 	dhd-cdc-usb-apsta dhd-cdc-usb-gpl \
 	dhd-cdc-sdstd-apsta \
-	dhd-cdc-sdmmc-softap-gpl \
-	dhd-cdc-sdmmc-cfg-gpl
+	dhd-cdc-sdmmc-softap-gpl
 
 
 TARGETS += \
@@ -335,7 +356,7 @@
 ifeq ($(BCM_KVER), 2.6)
 	$(OBJCOPY) --strip-unneeded $(OBJDIR)/$(KMODULES) $(OBJDIR)/$(KMODULES).stripped
 else
-	$(OBJCOPY) --strip-unneeded $(OBJDIR)/$(MODULES) $(OBJDIR)/$(MODULES).stripped
+	$(OBJCOPY) --strip-unneeded $(OBJDIR)/dhd.o $(OBJDIR)/dhd.o.stripped
 endif
 
 dep: $(foreach file,$(CFILES),.$(file).depend)
diff --git a/bcm4329/src/dhd/linux/makefile.26 b/bcm4329/src/dhd/linux/makefile.26
index eceee8e..da7319b 100644
--- a/bcm4329/src/dhd/linux/makefile.26
+++ b/bcm4329/src/dhd/linux/makefile.26
@@ -22,8 +22,13 @@
 # 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: makefile.26,v 1.1.144.1 2008/05/07 22:53:44 Exp $
+# $Id: makefile.26,v 1.1.144.1.14.1 2010/04/16 20:27:14 Exp $
 
+ifneq ($(findstring -nexus-,-$(TARGET)-),)
+obj-m += bcm4329.o
+bcm4329-objs = $(DHDOFILES)
+else
 obj-m += dhd.o
 dhd-objs = $(DHDOFILES)
+endif
 EXTRA_CFLAGS = $(DHDCFLAGS)
diff --git a/bcm4329/src/dhd/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h
index 3b22eb7..cc7e8cb 100644
--- a/bcm4329/src/dhd/sys/dhd.h
+++ b/bcm4329/src/dhd/sys/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,v 1.32.4.7.2.4.14.29 2010/02/23 06:58:21 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.49 2010/08/20 17:32:48 Exp $
  */
 
 /****************
@@ -59,6 +59,11 @@
 
 #include <wlioctl.h>
 
+#ifdef DHD_DEBUG
+#ifndef DHD_DEBUG_TRAP
+#define DHD_DEBUG_TRAP
+#endif
+#endif
 
 /* Forward decls */
 struct dhd_bus;
@@ -145,33 +150,48 @@
 	/* Last error from dongle */
 	int dongle_error;
 
+	/* 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 */
+#endif /* PNO_SUPPORT */
+	int dtim_skip;         /* dtim skip , default 0 means wake each dtim */
+
+	/* Pkt filter defination */
+	char * pktfilter[100];
+	int pktfilter_count;
+
 	uint8 country_code[WLC_CNTRY_BUF_SZ];
+	char eventmask[WL_EVENTING_MASK_LEN];
+
 } dhd_pub_t;
 
-	#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
 
 	#define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-	#define _DHD_PM_RESUME_WAIT(a, b) do {\
+	#define _DHD_PM_RESUME_WAIT(a, b) do { \
 			int retry = 0; \
+			smp_mb(); \
 			while (dhd_mmc_suspend && retry++ != b) { \
 				wait_event_interruptible_timeout(a, FALSE, HZ/100); \
 			} \
 		} 	while (0)
-	#define DHD_PM_RESUME_WAIT(a) 			_DHD_PM_RESUME_WAIT(a, 30)
+	#define DHD_PM_RESUME_WAIT(a) 		_DHD_PM_RESUME_WAIT(a, 30)
 	#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)
 	#define DHD_PM_RESUME_RETURN		do { if (dhd_mmc_suspend) return; } while (0)
 
 	#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
 	#define SPINWAIT_SLEEP(a, exp, us) do { \
-		uint countdown = (us) + 9; \
-		while ((exp) && (countdown >= 10)) { \
+		uint countdown = (us) + 9999; \
+		while ((exp) && (countdown >= 10000)) { \
 			wait_event_interruptible_timeout(a, FALSE, HZ/100); \
-			countdown -= 10; \
+			countdown -= 10000; \
 		} \
 	} while (0)
 
-	#else
+#else
 
 	#define DHD_PM_RESUME_WAIT_INIT(a)
 	#define DHD_PM_RESUME_WAIT(a)
@@ -188,7 +208,8 @@
 		} \
 	} while (0)
 
-	#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+
 #define DHD_IF_VIF	0x01	/* Virtual IF (Hidden from user) */
 
 /* Wakelock Functions */
@@ -262,9 +283,13 @@
 extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub);
 extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub);
 extern void dhd_customer_gpio_wlan_ctrl(int onoff);
+extern int dhd_custom_get_mac_address(unsigned char *buf);
 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);
+#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 /* defined(OOB_INTR_ONLY) */
@@ -311,6 +336,7 @@
 extern uint dhd_bus_status(dhd_pub_t *dhdp);
 extern int  dhd_bus_start(dhd_pub_t *dhdp);
 
+extern void print_buf(void *pbuf, int len, int bytes_per_line);
 
 
 typedef enum cust_gpio_modes {
@@ -320,6 +346,7 @@
 	WLAN_POWER_OFF
 } cust_gpio_modes_t;
 extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
+extern int wl_iw_send_priv_event(struct net_device *dev, char *flag);
 /*
  * Insmod parameters for debug/test
  */
@@ -327,6 +354,10 @@
 /* Watchdog timer interval */
 extern uint dhd_watchdog_ms;
 
+#if defined(DHD_DEBUG)
+/* Console output poll interval */
+extern uint dhd_console_ms;
+#endif /* defined(DHD_DEBUG) */
 
 /* Use interrupts */
 extern uint dhd_intr;
@@ -334,6 +365,27 @@
 /* Use polling */
 extern uint dhd_poll;
 
+/* ARP offload agent mode */
+extern uint dhd_arp_mode;
+
+/* ARP offload enable */
+extern uint dhd_arp_enable;
+
+/* Pkt filte enable control */
+extern uint dhd_pkt_filter_enable;
+
+/*  Pkt filter init setup */
+extern uint dhd_pkt_filter_init;
+
+/* Pkt filter mode control */
+extern uint dhd_master_mode;
+
+/* Roaming mode control */
+extern uint dhd_roam;
+
+/* Roaming mode control */
+extern uint dhd_radio_up;
+
 /* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
 extern int dhd_idletime;
 #define DHD_IDLETIME_TICKS 1
@@ -364,9 +416,6 @@
 #define DHD_DEL_IF	-0xe
 #define DHD_BAD_IF	-0xf
 
-#ifdef APSTA_PINGTEST
-#define MAX_GUEST 8
-#endif
 
 extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
 extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
diff --git a/bcm4329/src/dhd/sys/dhd_bus.h b/bcm4329/src/dhd/sys/dhd_bus.h
index 93392f9..9e29fb9 100644
--- a/bcm4329/src/dhd/sys/dhd_bus.h
+++ b/bcm4329/src/dhd/sys/dhd_bus.h
@@ -4,7 +4,7 @@
  * Provides type definitions and function prototypes used to link the
  * DHD OS, bus, and protocol modules.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -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_bus.h,v 1.4.6.3.2.3.6.5 2009/06/02 21:56:30 Exp $
+ * $Id: dhd_bus.h,v 1.4.6.3.2.3.6.6 2010/05/17 18:18:13 Exp $
  */
 
 #ifndef _dhd_bus_h_
@@ -60,6 +60,10 @@
 /* Watchdog timer function */
 extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
 
+#ifdef DHD_DEBUG
+/* Device console input function */
+extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#endif
 
 /* Deferred processing for the bus, return TRUE requests reschedule */
 extern bool dhd_bus_dpc(struct dhd_bus *bus);
diff --git a/bcm4329/src/dhd/sys/dhd_cdc.c b/bcm4329/src/dhd/sys/dhd_cdc.c
index 43b21c3..61f6a6f 100644
--- a/bcm4329/src/dhd/sys/dhd_cdc.c
+++ b/bcm4329/src/dhd/sys/dhd_cdc.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_cdc.c,v 1.22.4.2.4.7.2.34 2010/01/21 22:08:34 Exp $
+ * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.41 2010/06/23 19:58:18 Exp $
  *
  * 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
@@ -41,6 +41,7 @@
 #include <dhd_bus.h>
 #include <dhd_dbg.h>
 
+extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
 
 /* Packet alignment for most efficient SDIO (can change based on platform) */
 #ifndef DHD_SDALIGN
@@ -193,7 +194,7 @@
 	return ret;
 }
 
-static int
+int
 dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 {
 	dhd_prot_t *prot = dhd->prot;
@@ -210,7 +211,7 @@
 	msg->len = htol32(len);
 	msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
 	CDC_SET_IF_IDX(msg, ifidx);
-	msg->flags |= htol32(msg->flags);
+	msg->flags = htol32(msg->flags);
 
 	if (buf)
 		memcpy(prot->buf, buf, len);
@@ -322,23 +323,12 @@
 	bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
 }
 
-#ifdef APSTA_PINGTEST
-extern struct ether_addr guest_eas[MAX_GUEST];
-#endif
 
 void
 dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf)
 {
 #ifdef BDC
 	struct bdc_header *h;
-#ifdef APSTA_PINGTEST
-	struct	ether_header *eh;
-	int i;
-#ifdef DHD_DEBUG
-	char eabuf1[ETHER_ADDR_STR_LEN];
-	char eabuf2[ETHER_ADDR_STR_LEN];
-#endif /* DHD_DEBUG */
-#endif /* APSTA_PINGTEST */
 #endif /* BDC */
 
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@@ -346,9 +336,6 @@
 #ifdef BDC
 	/* Push BDC header used to convey priority for buses that don't */
 
-#ifdef APSTA_PINGTEST
-	eh = (struct ether_header *)PKTDATA(dhd->osh, pktbuf);
-#endif
 
 	PKTPUSH(dhd->osh, pktbuf, BDC_HEADER_LEN);
 
@@ -361,19 +348,6 @@
 
 	h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK);
 	h->flags2 = 0;
-#ifdef APSTA_PINGTEST
-	for (i = 0; i < MAX_GUEST; ++i) {
-		if (!ETHER_ISNULLADDR(eh->ether_dhost) &&
-		    bcmp(eh->ether_dhost, guest_eas[i].octet, ETHER_ADDR_LEN) == 0) {
-			DHD_TRACE(("send on if 1; sa %s, da %s\n",
-			       bcm_ether_ntoa((struct ether_addr *)(eh->ether_shost), eabuf1),
-			       bcm_ether_ntoa((struct ether_addr *)(eh->ether_dhost), eabuf2)));
-			/* assume all guest STAs are on interface 1 */
-			h->flags2 = 1;
-			break;
-		}
-	}
-#endif /* APSTA_PINGTEST */
 	h->rssi = 0;
 #endif /* BDC */
 	BDC_SET_IF_IDX(h, ifidx);
@@ -510,266 +484,30 @@
 	return;
 }
 
-int dhd_set_suspend(int value, dhd_pub_t *dhd)
-{
-	int power_mode = PM_MAX;
-	wl_pkt_filter_enable_t	enable_parm;
-	char iovbuf[32];
-	int bcn_li_dtim = 3;
-#ifdef CUSTOMER_HW2
-	uint roamvar = 1;
-#endif /* CUSTOMER_HW2 */
-
-#define htod32(i) i
-
-	if (dhd && dhd->up) {
-		dhd_os_proto_block(dhd);
-		if (value) {
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
-				(char *)&power_mode, sizeof(power_mode));
-			/* Enable packet filter, only allow unicast packet to send up */
-			enable_parm.id = htod32(100);
-			enable_parm.enable = htod32(1);
-			bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
-				sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-			/* set bcn_li_dtim */
-			bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
-				4, iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
-			/* Disable build-in roaming to allowed ext supplicant to take of romaing */
-			bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#endif /* CUSTOMER_HW2 */
-		} else {
-			power_mode = PM_FAST;
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
-				sizeof(power_mode));
-			/* disable pkt filter */
-			enable_parm.id = htod32(100);
-			enable_parm.enable = htod32(0);
-			bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
-				sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-			/* set bcn_li_dtim */
-			bcn_li_dtim = 0;
-			bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
-				4, iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
-			roamvar = 0;
-			bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#endif /* CUSTOMER_HW2 */
-		}
-		dhd_os_proto_unblock(dhd);
-	}
-
-	return 0;
-}
-
-#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
-
-/* Convert user's input in hex pattern to byte-size mask */
-static int
-wl_pattern_atoh(char *src, char *dst)
-{
-	int i;
-	if (strncmp(src, "0x", 2) != 0 &&
-	    strncmp(src, "0X", 2) != 0) {
-		printf("Mask invalid format. Needs to start with 0x\n");
-		return -1;
-	}
-	src = src + 2; /* Skip past 0x */
-	if (strlen(src) % 2 != 0) {
-		printf("Mask invalid format. Needs to be of even length\n");
-		return -1;
-	}
-	for (i = 0; *src != '\0'; i++) {
-		char num[3];
-		strncpy(num, src, 2);
-		num[2] = '\0';
-		dst[i] = (uint8)strtoul(num, NULL, 16);
-		src += 2;
-	}
-	return i;
-}
-
-int
-dhd_preinit_ioctls(dhd_pub_t *dhd)
-{
-	char eventmask[WL_EVENTING_MASK_LEN];
-	char iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
-	int ret;
-	uint up = 0;
-#ifdef CUSTOMER_HW2
-	uint roamvar = 0;
-#else
-	uint roamvar = 1;
-#endif
-	uint power_mode = PM_FAST;
-	uint32 dongle_align = DHD_SDALIGN;
-	uint32 glom = 0;
-
-	uint bcn_timeout = 3;
-	int arpoe = 1;
-	int arp_ol = 0xf;
-	int scan_assoc_time = 40;
-	int scan_unassoc_time = 80;
-	const char 				*str;
-	wl_pkt_filter_t		pkt_filter;
-	wl_pkt_filter_t		*pkt_filterp;
-	int						buf_len;
-	int						str_len;
-	uint32					mask_size;
-	uint32					pattern_size;
-	char buf[256];
-	uint filter_mode = 1;
-
-	dhd_os_proto_block(dhd);
-	/* Get the device MAC address */
-	strcpy(iovbuf, "cur_etheraddr");
-	if ((ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
-		DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
-		dhd_os_proto_unblock(dhd);
-		return BCME_NOTUP;
-	}
-	memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
-
-	/* Set Country code */
-	if (dhd->country_code[0] != 0) {
-		if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
-			dhd->country_code, sizeof(dhd->country_code)) < 0) {
-			DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
-		}
-	}
-
-	/* Set PowerSave mode */
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode));
-
-	/* Match Host and Dongle rx alignment */
-	bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-	/* disable glom option per default */
-	bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	/* Setup timeout if Beacons are lost and roam is off to report link down */
-	if (roamvar) {
-		bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
-		dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	}
-
-	/* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */
-	bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-	/* Force STA UP */
-	dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
-
-	/* Setup event_msgs */
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
-	dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
-	bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
-
-	setbit(eventmask, WLC_E_SET_SSID);
-	setbit(eventmask, WLC_E_PRUNE);
-	setbit(eventmask, WLC_E_AUTH);
-	setbit(eventmask, WLC_E_REASSOC);
-	setbit(eventmask, WLC_E_REASSOC_IND);
-	setbit(eventmask, WLC_E_DEAUTH_IND);
-	setbit(eventmask, WLC_E_DISASSOC_IND);
-	setbit(eventmask, WLC_E_DISASSOC);
-	setbit(eventmask, WLC_E_JOIN);
-	setbit(eventmask, WLC_E_ASSOC_IND);
-	setbit(eventmask, WLC_E_PSK_SUP);
-	setbit(eventmask, WLC_E_LINK);
-	setbit(eventmask, WLC_E_NDIS_LINK);
-	setbit(eventmask, WLC_E_MIC_ERROR);
-	setbit(eventmask, WLC_E_PMKID_CACHE);
-	setbit(eventmask, WLC_E_TXFAIL);
-	setbit(eventmask, WLC_E_JOIN_START);
-	setbit(eventmask, WLC_E_SCAN_COMPLETE);
-
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
-		sizeof(scan_assoc_time));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
-		sizeof(scan_unassoc_time));
-
-	/* Set ARP offload */
-	bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-	/* add a default packet filter pattern */
-	str = "pkt_filter_add";
-	str_len = strlen(str);
-	strncpy(buf, str, str_len);
-	buf[ str_len ] = '\0';
-	buf_len = str_len + 1;
-
-	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
-
-	/* Parse packet filter id. */
-	pkt_filter.id = htod32(100);
-
-	/* Parse filter polarity. */
-	pkt_filter.negate_match = htod32(0);
-
-	/* Parse filter type. */
-	pkt_filter.type = htod32(0);
-
-	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = htod32(0);
-
-	/* Parse pattern filter mask. */
-	mask_size =	htod32(wl_pattern_atoh("0xff",
-		(char *) pkt_filterp->u.pattern.mask_and_pattern));
-
-	/* Parse pattern filter pattern. */
-	pattern_size = htod32(wl_pattern_atoh("0x00",
-		(char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
-
-	if (mask_size != pattern_size) {
-		DHD_ERROR(("Mask and pattern not the same size\n"));
-		dhd_os_proto_unblock(dhd);
-		return -EINVAL;
-	}
-
-	pkt_filter.u.pattern.size_bytes = mask_size;
-	buf_len += WL_PKT_FILTER_FIXED_LEN;
-	buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
-
-	/* Keep-alive attributes are set in local	variable (keep_alive_pkt), and
-	** then memcpy'ed into buffer (keep_alive_pktp) since there is no
-	** guarantee that the buffer is properly aligned.
-	*/
-	memcpy((char *)pkt_filterp, &pkt_filter,
-		WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
-
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
-
-	/* set mode to allow pattern */
-	bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-	dhd_os_proto_unblock(dhd);
-	return 0;
-}
-
 int
 dhd_prot_init(dhd_pub_t *dhd)
 {
 	int ret = 0;
+	char buf[128];
+
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
+	dhd_os_proto_block(dhd);
 
+	/* Get the device MAC address */
+	strcpy(buf, "cur_etheraddr");
+	ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+	if (ret < 0) {
+		dhd_os_proto_unblock(dhd);
+		return ret;
+	}
+	memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+
+	dhd_os_proto_unblock(dhd);
+
+#ifdef EMBEDDED_PLATFORM
 	ret = dhd_preinit_ioctls(dhd);
+#endif /* EMBEDDED_PLATFORM */
 
 	/* Always assumes wl for now */
 	dhd->iswl = TRUE;
diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c
index a0e6a73..bea33b6 100644
--- a/bcm4329/src/dhd/sys/dhd_common.c
+++ b/bcm4329/src/dhd/sys/dhd_common.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_common.c,v 1.5.6.8.2.6.6.41 2010/02/24 01:52:41 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.3 2010/09/10 21:30:16 Exp $
  */
 #include <typedefs.h>
 #include <osl.h>
@@ -37,9 +37,21 @@
 #include <dhd_dbg.h>
 #include <msgtrace.h>
 
+#include <wlioctl.h>
+
+#ifdef SET_RANDOM_MAC_SOFTAP
+#include <linux/random.h>
+#include <linux/jiffies.h>
+#endif
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+int wifi_get_mac_addr(unsigned char *buf);
+#endif /* GET_CUSTOM_MAC_ENABLE */
 
 int dhd_msg_level;
 
+#include <wl_iw.h>
+
 char fw_path[MOD_PARAM_PATHLEN];
 char nv_path[MOD_PARAM_PATHLEN];
 
@@ -48,6 +60,25 @@
 uint32 dhd_conn_status;
 uint32 dhd_conn_reason;
 
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+
+extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
+extern void dhd_ind_scan_confirm(void *h, bool status);
+extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen);
+void dhd_iscan_lock(void);
+void dhd_iscan_unlock(void);
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#ifndef DHD_SDALIGN
+#define DHD_SDALIGN	32
+#endif
+#if !ISPOWEROF2(DHD_SDALIGN)
+#error DHD_SDALIGN is not a power of 2!
+#endif
+
 #ifdef DHD_DEBUG
 const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on "
 	__DATE__ " at " __TIME__;
@@ -57,7 +88,6 @@
 
 void dhd_set_timer(void *bus, uint wdtick);
 
-
 /* IOVar table */
 enum {
 	IOV_VERSION = 1,
@@ -66,6 +96,10 @@
 	IOV_BCMERROR,
 	IOV_WDTICK,
 	IOV_DUMP,
+#ifdef DHD_DEBUG
+	IOV_CONS,
+	IOV_DCONSOLE_POLL,
+#endif
 	IOV_CLEARCOUNTS,
 	IOV_LOGDUMP,
 	IOV_LOGCAL,
@@ -84,6 +118,10 @@
 	{"bcmerror",	IOV_BCMERROR,	0,	IOVT_INT8,	0 },
 	{"wdtick",	IOV_WDTICK, 0,	IOVT_UINT32,	0 },
 	{"dump",	IOV_DUMP,	0,	IOVT_BUFFER,	DHD_IOCTL_MAXLEN },
+#ifdef DHD_DEBUG
+	{"dconpoll",	IOV_DCONSOLE_POLL, 0,	IOVT_UINT32,	0 },
+	{"cons",	IOV_CONS,	0,	IOVT_BUFFER,	0 },
+#endif
 	{"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID,	0 },
 	{"gpioob",	IOV_GPIOOB,	0,	IOVT_UINT32,	0 },
 	{"ioctl_timeout",	IOV_IOCTLTIMEOUT,	0,	IOVT_UINT32,	0 },
@@ -223,6 +261,21 @@
 		bcmerror = dhd_dump(dhd_pub, arg, len);
 		break;
 
+#ifdef DHD_DEBUG
+	case IOV_GVAL(IOV_DCONSOLE_POLL):
+		int_val = (int32)dhd_console_ms;
+		bcopy(&int_val, arg, val_size);
+		break;
+
+	case IOV_SVAL(IOV_DCONSOLE_POLL):
+		dhd_console_ms = (uint)int_val;
+		break;
+
+	case IOV_SVAL(IOV_CONS):
+		if (len > 0)
+			bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+		break;
+#endif
 
 	case IOV_SVAL(IOV_CLEARCOUNTS):
 		dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
@@ -459,9 +512,6 @@
 	return bcmerror;
 }
 
-#ifdef APSTA_PINGTEST
-struct ether_addr guest_eas[MAX_GUEST];
-#endif
 
 #ifdef SHOW_EVENTS
 static void
@@ -570,16 +620,6 @@
 
 	case WLC_E_ASSOC_IND:
 	case WLC_E_REASSOC_IND:
-#ifdef APSTA_PINGTEST
-		{
-			int i;
-			for (i = 0; i < MAX_GUEST; ++i)
-				if (ETHER_ISNULLADDR(&guest_eas[i]))
-					break;
-			if (i < MAX_GUEST)
-				bcopy(event->addr.octet, guest_eas[i].octet, ETHER_ADDR_LEN);
-		}
-#endif /* APSTA_PINGTEST */
 		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
 		break;
 
@@ -600,18 +640,6 @@
 
 	case WLC_E_DEAUTH_IND:
 	case WLC_E_DISASSOC_IND:
-#ifdef APSTA_PINGTEST
-		{
-			int i;
-			for (i = 0; i < MAX_GUEST; ++i) {
-				if (bcmp(guest_eas[i].octet, event->addr.octet,
-				         ETHER_ADDR_LEN) == 0) {
-					bzero(guest_eas[i].octet, ETHER_ADDR_LEN);
-					break;
-				}
-			}
-		}
-#endif /* APSTA_PINGTEST */
 		DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name, eabuf, (int)reason));
 		break;
 
@@ -892,3 +920,1264 @@
 	evt->datalen = ntoh32(evt->datalen);
 	evt->version = ntoh16(evt->version);
 }
+
+void print_buf(void *pbuf, int len, int bytes_per_line)
+{
+	int i, j = 0;
+	unsigned char *buf = pbuf;
+
+	if (bytes_per_line == 0) {
+		bytes_per_line = len;
+	}
+
+	for (i = 0; i < len; i++) {
+		printf("%2.2x", *buf++);
+		j++;
+		if (j == bytes_per_line) {
+			printf("\n");
+			j = 0;
+		} else {
+			printf(":");
+		}
+	}
+	printf("\n");
+}
+
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+
+#ifdef PKT_FILTER_SUPPORT
+/* Convert user's input in hex pattern to byte-size mask */
+static int
+wl_pattern_atoh(char *src, char *dst)
+{
+	int i;
+	if (strncmp(src, "0x", 2) != 0 &&
+	    strncmp(src, "0X", 2) != 0) {
+		DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
+		return -1;
+	}
+	src = src + 2; /* Skip past 0x */
+	if (strlen(src) % 2 != 0) {
+		DHD_ERROR(("Mask invalid format. Needs to be of even length\n"));
+		return -1;
+	}
+	for (i = 0; *src != '\0'; i++) {
+		char num[3];
+		strncpy(num, src, 2);
+		num[2] = '\0';
+		dst[i] = (uint8)strtoul(num, NULL, 16);
+		src += 2;
+	}
+	return i;
+}
+
+void
+dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode)
+{
+	char				*argv[8];
+	int					i = 0;
+	const char 			*str;
+	int					buf_len;
+	int					str_len;
+	char				*arg_save = 0, *arg_org = 0;
+	int					rc;
+	char				buf[128];
+	wl_pkt_filter_enable_t	enable_parm;
+	wl_pkt_filter_enable_t	* pkt_filterp;
+
+	if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
+		DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+		goto fail;
+	}
+	arg_org = arg_save;
+	memcpy(arg_save, arg, strlen(arg) + 1);
+
+	argv[i] = bcmstrtok(&arg_save, " ", 0);
+
+	i = 0;
+	if (NULL == argv[i]) {
+		DHD_ERROR(("No args provided\n"));
+		goto fail;
+	}
+
+	str = "pkt_filter_enable";
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[str_len] = '\0';
+	buf_len = str_len + 1;
+
+	pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1);
+
+	/* Parse packet filter id. */
+	enable_parm.id = htod32(strtoul(argv[i], NULL, 0));
+
+	/* Parse enable/disable value. */
+	enable_parm.enable = htod32(enable);
+
+	buf_len += sizeof(enable_parm);
+	memcpy((char *)pkt_filterp,
+	       &enable_parm,
+	       sizeof(enable_parm));
+
+	/* Enable/disable the specified filter. */
+	rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+	rc = rc >= 0 ? 0 : rc;
+	if (rc)
+		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+		__FUNCTION__, arg, rc));
+	else
+		DHD_TRACE(("%s: successfully added pktfilter %s\n",
+		__FUNCTION__, arg));
+
+	/* Contorl the master mode */
+	bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, sizeof(buf));
+	rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+	rc = rc >= 0 ? 0 : rc;
+	if (rc)
+		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+		__FUNCTION__, arg, rc));
+
+fail:
+	if (arg_org)
+		MFREE(dhd->osh, arg_org, strlen(arg) + 1);
+}
+
+void
+dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
+{
+	const char 			*str;
+	wl_pkt_filter_t		pkt_filter;
+	wl_pkt_filter_t		*pkt_filterp;
+	int					buf_len;
+	int					str_len;
+	int 				rc;
+	uint32				mask_size;
+	uint32				pattern_size;
+	char				*argv[8], * buf = 0;
+	int					i = 0;
+	char				*arg_save = 0, *arg_org = 0;
+#define BUF_SIZE		2048
+
+	if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
+		DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+		goto fail;
+	}
+
+	arg_org = arg_save;
+
+	if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) {
+		DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+		goto fail;
+	}
+
+	memcpy(arg_save, arg, strlen(arg) + 1);
+
+	if (strlen(arg) > BUF_SIZE) {
+		DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf)));
+		goto fail;
+	}
+
+	argv[i] = bcmstrtok(&arg_save, " ", 0);
+	while (argv[i++])
+		argv[i] = bcmstrtok(&arg_save, " ", 0);
+
+	i = 0;
+	if (NULL == argv[i]) {
+		DHD_ERROR(("No args provided\n"));
+		goto fail;
+	}
+
+	str = "pkt_filter_add";
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[ str_len ] = '\0';
+	buf_len = str_len + 1;
+
+	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+
+	/* Parse packet filter id. */
+	pkt_filter.id = htod32(strtoul(argv[i], NULL, 0));
+
+	if (NULL == argv[++i]) {
+		DHD_ERROR(("Polarity not provided\n"));
+		goto fail;
+	}
+
+	/* Parse filter polarity. */
+	pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0));
+
+	if (NULL == argv[++i]) {
+		DHD_ERROR(("Filter type not provided\n"));
+		goto fail;
+	}
+
+	/* Parse filter type. */
+	pkt_filter.type = htod32(strtoul(argv[i], NULL, 0));
+
+	if (NULL == argv[++i]) {
+		DHD_ERROR(("Offset not provided\n"));
+		goto fail;
+	}
+
+	/* Parse pattern filter offset. */
+	pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0));
+
+	if (NULL == argv[++i]) {
+		DHD_ERROR(("Bitmask not provided\n"));
+		goto fail;
+	}
+
+	/* Parse pattern filter mask. */
+	mask_size =
+		htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern));
+
+	if (NULL == argv[++i]) {
+		DHD_ERROR(("Pattern not provided\n"));
+		goto fail;
+	}
+
+	/* Parse pattern filter pattern. */
+	pattern_size =
+		htod32(wl_pattern_atoh(argv[i],
+	         (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
+
+	if (mask_size != pattern_size) {
+		DHD_ERROR(("Mask and pattern not the same size\n"));
+		goto fail;
+	}
+
+	pkt_filter.u.pattern.size_bytes = mask_size;
+	buf_len += WL_PKT_FILTER_FIXED_LEN;
+	buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
+
+	/* Keep-alive attributes are set in local	variable (keep_alive_pkt), and
+	** then memcpy'ed into buffer (keep_alive_pktp) since there is no
+	** guarantee that the buffer is properly aligned.
+	*/
+	memcpy((char *)pkt_filterp,
+	       &pkt_filter,
+	       WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+
+	rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+	rc = rc >= 0 ? 0 : rc;
+
+	if (rc)
+		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+		__FUNCTION__, arg, rc));
+	else
+		DHD_TRACE(("%s: successfully added pktfilter %s\n",
+		__FUNCTION__, arg));
+
+fail:
+	if (arg_org)
+		MFREE(dhd->osh, arg_org, strlen(arg) + 1);
+
+	if (buf)
+		MFREE(dhd->osh, buf, BUF_SIZE);
+}
+#endif
+
+#ifdef ARP_OFFLOAD_SUPPORT
+void
+dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode)
+{
+	char iovbuf[32];
+	int retcode;
+
+	bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+	retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	retcode = retcode >= 0 ? 0 : retcode;
+	if (retcode)
+		DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n",
+		__FUNCTION__, arp_mode, retcode));
+	else
+		DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
+		__FUNCTION__, arp_mode));
+}
+
+void
+dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
+{
+	char iovbuf[32];
+	int retcode;
+
+	bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
+	retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	retcode = retcode >= 0 ? 0 : retcode;
+	if (retcode)
+		DHD_TRACE(("%s: failed to enabe ARP offload to %d, retcode = %d\n",
+		__FUNCTION__, arp_enable, retcode));
+	else
+		DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
+		__FUNCTION__, arp_enable));
+}
+#endif
+
+int
+dhd_preinit_ioctls(dhd_pub_t *dhd)
+{
+	char iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
+	uint up = 0;
+	char buf[128], *ptr;
+	uint power_mode = PM_FAST;
+	uint32 dongle_align = DHD_SDALIGN;
+	uint32 glom = 0;
+	uint bcn_timeout = 3;
+	int scan_assoc_time = 40;
+	int scan_unassoc_time = 40;
+#ifdef GET_CUSTOM_MAC_ENABLE
+	int ret;
+	struct ether_addr ea_addr;
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+	dhd_os_proto_block(dhd);
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+	/*
+	** Read MAC address from external customer place
+	** NOTE that default mac address has to be present in otp or nvram file
+	** to bring up firmware but unique per board mac address maybe provided
+	** by customer code
+	*/
+	ret = dhd_custom_get_mac_address(ea_addr.octet);
+	if (!ret) {
+		bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
+		ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+		if (ret < 0) {
+			DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+		} else
+			memcpy(dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN);
+	}
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+#ifdef SET_RANDOM_MAC_SOFTAP
+	if (strstr(fw_path, "apsta") != NULL) {
+		uint rand_mac;
+		int ret;
+
+		srandom32((uint)jiffies);
+		rand_mac = random32();
+		iovbuf[0] = 0x02;              /* locally administered bit */
+		iovbuf[1] = 0x1A;
+		iovbuf[2] = 0x11;
+		iovbuf[3] = (unsigned char)(rand_mac & 0x0F) | 0xF0;
+		iovbuf[4] = (unsigned char)(rand_mac >> 8);
+		iovbuf[5] = (unsigned char)(rand_mac >> 16);
+
+		printk("Broadcom Dongle Host Driver mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
+			iovbuf[0], iovbuf[1], iovbuf[2], iovbuf[3], iovbuf[4], iovbuf[5]);
+
+		bcm_mkiovar("cur_etheraddr", (void *)iovbuf, ETHER_ADDR_LEN, buf, sizeof(buf));
+		ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+		if (ret < 0) {
+			DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+		} else
+			memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
+	}
+#endif /* SET_RANDOM_MAC_SOFTAP */
+
+	/* Set Country code */
+	if (dhd->country_code[0] != 0) {
+		if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
+			dhd->country_code, sizeof(dhd->country_code)) < 0) {
+			DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
+		}
+	}
+
+	/* query for 'ver' to get version info from firmware */
+	memset(buf, 0, sizeof(buf));
+	ptr = buf;
+	bcm_mkiovar("ver", 0, 0, buf, sizeof(buf));
+	dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+	bcmstrtok(&ptr, "\n", 0);
+	/* Print fw version info */
+	DHD_ERROR(("Firmware version = %s\n", buf));
+
+	/* Set PowerSave mode */
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode));
+
+	/* Match Host and Dongle rx alignment */
+	bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+	/* disable glom option per default */
+	bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+	/* Setup timeout if Beacons are lost and roam is off to report link down */
+	bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+	/* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */
+	bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf));
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+	if (dhd_roam == 0)
+	{
+		/* set internal roaming roaming parameters */
+		int roam_scan_period = 30; /* in sec */
+		int roam_fullscan_period = 120; /* in sec */
+		int roam_trigger = -85;
+		int roam_delta = 15;
+		int band;
+		int band_temp_set = WLC_BAND_2G;
+
+		if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_ROAM_SCAN_PERIOD, \
+			(char *)&roam_scan_period, sizeof(roam_scan_period)) < 0)
+			DHD_ERROR(("%s: roam scan setup failed\n", __FUNCTION__));
+
+		bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, \
+					 4, iovbuf, sizeof(iovbuf));
+		if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, \
+			iovbuf, sizeof(iovbuf)) < 0)
+			DHD_ERROR(("%s: roam fullscan setup failed\n", __FUNCTION__));
+
+		if (dhdcdc_query_ioctl(dhd, 0, WLC_GET_BAND, \
+				(char *)&band, sizeof(band)) < 0)
+			DHD_ERROR(("%s: roam delta setting failed\n", __FUNCTION__));
+		else {
+			if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_ALL))
+			{
+				/* temp set band to insert new roams values */
+				if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_BAND, \
+					(char *)&band_temp_set, sizeof(band_temp_set)) < 0)
+					DHD_ERROR(("%s: local band seting failed\n", __FUNCTION__));
+			}
+			if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_ROAM_DELTA, \
+				(char *)&roam_delta, sizeof(roam_delta)) < 0)
+				DHD_ERROR(("%s: roam delta setting failed\n", __FUNCTION__));
+
+			if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_ROAM_TRIGGER, \
+				(char *)&roam_trigger, sizeof(roam_trigger)) < 0)
+				DHD_ERROR(("%s: roam trigger setting failed\n", __FUNCTION__));
+
+			/* Restore original band settinngs */
+			if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_BAND, \
+				(char *)&band, sizeof(band)) < 0)
+				DHD_ERROR(("%s: Original band restore failed\n", __FUNCTION__));
+		}
+	}
+
+	/* Force STA UP */
+	if (dhd_radio_up)
+		dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+
+	/* Setup event_msgs */
+	bcm_mkiovar("event_msgs", dhd->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
+		sizeof(scan_assoc_time));
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
+		sizeof(scan_unassoc_time));
+
+#ifdef ARP_OFFLOAD_SUPPORT
+	/* Set and enable ARP offload feature */
+	if (dhd_arp_enable)
+		dhd_arp_offload_set(dhd, dhd_arp_mode);
+	dhd_arp_offload_enable(dhd, dhd_arp_enable);
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+#ifdef PKT_FILTER_SUPPORT
+	{
+		int i;
+		/* Set up pkt filter */
+		if (dhd_pkt_filter_enable) {
+			for (i = 0; i < dhd->pktfilter_count; i++) {
+				dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
+				dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
+					dhd_pkt_filter_init, dhd_master_mode);
+			}
+		}
+	}
+#endif /* PKT_FILTER_SUPPORT */
+
+	dhd_os_proto_unblock(dhd);
+
+	return 0;
+}
+
+#ifdef SIMPLE_ISCAN
+
+uint iscan_thread_id;
+iscan_buf_t * iscan_chain = 0;
+
+iscan_buf_t *
+dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
+{
+	iscan_buf_t *iscanbuf_alloc = 0;
+	iscan_buf_t *iscanbuf_head;
+
+	dhd_iscan_lock();
+
+	iscanbuf_alloc = (iscan_buf_t*)MALLOC(dhd->osh, sizeof(iscan_buf_t));
+	if (iscanbuf_alloc == NULL)
+		goto fail;
+
+	iscanbuf_alloc->next = NULL;
+	iscanbuf_head = *iscanbuf;
+
+	DHD_ISCAN(("%s: addr of allocated node = 0x%X"
+		   "addr of iscanbuf_head = 0x%X dhd = 0x%X\n",
+		   __FUNCTION__, iscanbuf_alloc, iscanbuf_head, dhd));
+
+	if (iscanbuf_head == NULL) {
+		*iscanbuf = iscanbuf_alloc;
+		DHD_ISCAN(("%s: Head is allocated\n", __FUNCTION__));
+		goto fail;
+	}
+
+	while (iscanbuf_head->next)
+		iscanbuf_head = iscanbuf_head->next;
+
+	iscanbuf_head->next = iscanbuf_alloc;
+
+fail:
+	dhd_iscan_unlock();
+	return iscanbuf_alloc;
+}
+
+void
+dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
+{
+	iscan_buf_t *iscanbuf_free = 0;
+	iscan_buf_t *iscanbuf_prv = 0;
+	iscan_buf_t *iscanbuf_cur = iscan_chain;
+	dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+
+	dhd_iscan_lock();
+	/* If iscan_delete is null then delete the entire 
+	 * chain or else delete specific one provided
+	 */
+	if (!iscan_delete) {
+		while (iscanbuf_cur) {
+			iscanbuf_free = iscanbuf_cur;
+			iscanbuf_cur = iscanbuf_cur->next;
+			iscanbuf_free->next = 0;
+			MFREE(dhd->osh, iscanbuf_free, sizeof(iscan_buf_t));
+		}
+		iscan_chain = 0;
+	} else {
+		while (iscanbuf_cur) {
+			if (iscanbuf_cur == iscan_delete)
+				break;
+			iscanbuf_prv = iscanbuf_cur;
+			iscanbuf_cur = iscanbuf_cur->next;
+		}
+		if (iscanbuf_prv)
+			iscanbuf_prv->next = iscan_delete->next;
+
+		iscan_delete->next = 0;
+		MFREE(dhd->osh, iscan_delete, sizeof(iscan_buf_t));
+
+		if (!iscanbuf_prv)
+			iscan_chain = 0;
+	}
+	dhd_iscan_unlock();
+}
+
+iscan_buf_t *
+dhd_iscan_result_buf(void)
+{
+	return iscan_chain;
+}
+
+
+
+/*
+* print scan cache
+* print partial iscan_skip list differently
+*/
+int
+dhd_iscan_print_cache(iscan_buf_t *iscan_skip)
+{
+	int i = 0, l = 0;
+	iscan_buf_t *iscan_cur;
+	wl_iscan_results_t *list;
+	wl_scan_results_t *results;
+	wl_bss_info_t UNALIGNED *bi;
+
+	dhd_iscan_lock();
+
+	iscan_cur = dhd_iscan_result_buf();
+
+	while (iscan_cur) {
+		list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+		if (!list)
+			break;
+
+		results = (wl_scan_results_t *)&list->results;
+		if (!results)
+			break;
+
+		if (results->version != WL_BSS_INFO_VERSION) {
+			DHD_ISCAN(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+				__FUNCTION__, results->version));
+			goto done;
+		}
+
+		bi = results->bss_info;
+		for (i = 0; i < results->count; i++) {
+			if (!bi)
+				break;
+
+			DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
+				iscan_cur != iscan_skip?"BSS":"bss", l, i,
+				bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+				bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5]));
+
+			bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+		}
+		iscan_cur = iscan_cur->next;
+		l++;
+	}
+
+done:
+	dhd_iscan_unlock();
+	return 0;
+}
+
+/*
+* delete disappeared AP from specific scan cache but skip partial list in iscan_skip
+*/
+int
+dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
+{
+	int i = 0, j = 0, l = 0;
+	iscan_buf_t *iscan_cur;
+	wl_iscan_results_t *list;
+	wl_scan_results_t *results;
+	wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+
+	uchar *s_addr = addr;
+
+	dhd_iscan_lock();
+	DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n",
+		__FUNCTION__, s_addr[0], s_addr[1], s_addr[2],
+		s_addr[3], s_addr[4], s_addr[5]));
+
+	iscan_cur = dhd_iscan_result_buf();
+
+	while (iscan_cur) {
+		if (iscan_cur != iscan_skip) {
+			list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+			if (!list)
+				break;
+
+			results = (wl_scan_results_t *)&list->results;
+			if (!results)
+				break;
+
+			if (results->version != WL_BSS_INFO_VERSION) {
+				DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+				__FUNCTION__, results->version));
+				goto done;
+			}
+
+			bi = results->bss_info;
+			for (i = 0; i < results->count; i++) {
+				if (!bi)
+					break;
+
+				if (!memcmp(bi->BSSID.octet, addr, ETHER_ADDR_LEN)) {
+					DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
+					__FUNCTION__, l, i, bi->BSSID.octet[0],
+					bi->BSSID.octet[1], bi->BSSID.octet[2],
+					bi->BSSID.octet[3], bi->BSSID.octet[4],
+					bi->BSSID.octet[5]));
+
+					bi_new = bi;
+					bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+/*
+					if(bi && bi_new) {
+						bcopy(bi, bi_new, results->buflen -
+						dtoh32(bi_new->length));
+						results->buflen -= dtoh32(bi_new->length);
+					}
+*/
+					results->buflen -= dtoh32(bi_new->length);
+					results->count--;
+
+					for (j = i; j < results->count; j++) {
+						if (bi && bi_new) {
+							DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d]"
+							"%X:%X:%X:%X:%X:%X\n",
+							__FUNCTION__, l, j, bi->BSSID.octet[0],
+							bi->BSSID.octet[1], bi->BSSID.octet[2],
+							bi->BSSID.octet[3], bi->BSSID.octet[4],
+							bi->BSSID.octet[5]));
+
+							bi_next = (wl_bss_info_t *)((uintptr)bi +
+								dtoh32(bi->length));
+							bcopy(bi, bi_new, dtoh32(bi->length));
+							bi_new = (wl_bss_info_t *)((uintptr)bi_new +
+								dtoh32(bi_new->length));
+							bi = bi_next;
+						}
+					}
+
+					if (results->count == 0) {
+						/* Prune now empty partial scan list */
+						dhd_iscan_free_buf(dhdp, iscan_cur);
+						goto done;
+					}
+					break;
+				}
+				bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+			}
+		}
+		iscan_cur = iscan_cur->next;
+		l++;
+	}
+
+done:
+	dhd_iscan_unlock();
+	return 0;
+}
+
+int
+dhd_iscan_remove_duplicates(void * dhdp, iscan_buf_t *iscan_cur)
+{
+	int i = 0;
+	wl_iscan_results_t *list;
+	wl_scan_results_t *results;
+	wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+
+	dhd_iscan_lock();
+
+	DHD_ISCAN(("%s: Scan cache before delete\n",
+		__FUNCTION__));
+	dhd_iscan_print_cache(iscan_cur);
+
+	if (!iscan_cur)
+		goto done;
+
+	list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+	if (!list)
+		goto done;
+
+	results = (wl_scan_results_t *)&list->results;
+	if (!results)
+		goto done;
+
+	if (results->version != WL_BSS_INFO_VERSION) {
+		DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+			__FUNCTION__, results->version));
+		goto done;
+	}
+
+	bi = results->bss_info;
+	for (i = 0; i < results->count; i++) {
+		if (!bi)
+			break;
+
+		DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n",
+			__FUNCTION__, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+			bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5]));
+
+		dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
+
+		bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+	}
+
+done:
+	DHD_ISCAN(("%s: Scan cache after delete\n", __FUNCTION__));
+	dhd_iscan_print_cache(iscan_cur);
+	dhd_iscan_unlock();
+	return 0;
+}
+
+void
+dhd_iscan_ind_scan_confirm(void *dhdp, bool status)
+{
+
+	dhd_ind_scan_confirm(dhdp, status);
+}
+
+int
+dhd_iscan_request(void * dhdp, uint16 action)
+{
+	int rc;
+	wl_iscan_params_t params;
+	dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+	char buf[WLC_IOCTL_SMLEN];
+
+
+	memset(&params, 0, sizeof(wl_iscan_params_t));
+	memcpy(&params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+	params.params.bss_type = DOT11_BSSTYPE_ANY;
+	params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
+
+	params.params.nprobes = htod32(-1);
+	params.params.active_time = htod32(-1);
+	params.params.passive_time = htod32(-1);
+	params.params.home_time = htod32(-1);
+	params.params.channel_num = htod32(0);
+
+	params.version = htod32(ISCAN_REQ_VERSION);
+	params.action = htod16(action);
+	params.scan_duration = htod16(0);
+
+	bcm_mkiovar("iscan", (char *)&params, sizeof(wl_iscan_params_t), buf, WLC_IOCTL_SMLEN);
+	rc = dhd_wl_ioctl(dhdp, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN);
+
+	return rc;
+}
+
+static int
+dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
+{
+	wl_iscan_results_t *list_buf;
+	wl_iscan_results_t list;
+	wl_scan_results_t *results;
+	iscan_buf_t *iscan_cur;
+	int status = -1;
+	dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+	int rc;
+
+
+	iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain);
+	if (!iscan_cur) {
+		DHD_ERROR(("%s: Failed to allocate node\n", __FUNCTION__));
+		dhd_iscan_free_buf(dhdp, 0);
+		dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT);
+		goto fail;
+	}
+
+	dhd_iscan_lock();
+
+	memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
+	list_buf = (wl_iscan_results_t*)iscan_cur->iscan_buf;
+	results = &list_buf->results;
+	results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+	results->version = 0;
+	results->count = 0;
+
+	memset(&list, 0, sizeof(list));
+	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+	bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
+		iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
+	rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
+
+	results->buflen = dtoh32(results->buflen);
+	results->version = dtoh32(results->version);
+	*scan_count = results->count = dtoh32(results->count);
+	status = dtoh32(list_buf->status);
+
+	dhd_iscan_unlock();
+
+	if (!(*scan_count))
+		dhd_iscan_free_buf(dhdp, iscan_cur);
+	else
+		dhd_iscan_remove_duplicates(dhdp, iscan_cur);
+
+
+fail:
+	return status;
+}
+
+#endif 
+
+#ifdef PNO_SUPPORT
+int dhd_pno_clean(dhd_pub_t *dhd)
+{
+	char iovbuf[128];
+	int pfn_enabled = 0;
+	int iov_len = 0;
+	int ret;
+
+	/* Disable pfn */
+	iov_len = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf));
+	if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) >= 0) {
+		/* clear pfn */
+		iov_len = bcm_mkiovar("pfnclear", 0, 0, iovbuf, sizeof(iovbuf));
+		if (iov_len) {
+			if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0) {
+				DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+			}
+		}
+		else {
+			ret = -1;
+			DHD_ERROR(("%s failed code %d\n", __FUNCTION__, iov_len));
+		}
+	}
+	else
+		DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+
+	return ret;
+}
+
+int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
+{
+	char iovbuf[128];
+	int ret = -1;
+
+	if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
+		DHD_ERROR(("%s error exit\n", __FUNCTION__));
+		return ret;
+	}
+
+	/* Enable/disable PNO */
+	if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
+		if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
+			DHD_ERROR(("%s failed for error=%d\n", __FUNCTION__, ret));
+			return ret;
+		}
+		else {
+			dhd->pno_enable = pfn_enabled;
+			DHD_TRACE(("%s set pno as %d\n", __FUNCTION__, dhd->pno_enable));
+		}
+	}
+	else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, ret));
+
+	return ret;
+}
+
+/* Function to execute combined scan */
+int
+dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr)
+{
+	int err = -1;
+	char iovbuf[128];
+	int k, i;
+	wl_pfn_param_t pfn_param;
+	wl_pfn_t	pfn_element;
+
+	DHD_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, scan_fr));
+
+	if ((!dhd) && (!ssids_local)) {
+		DHD_ERROR(("%s error exit\n", __FUNCTION__));
+		err = -1;
+	}
+
+	/* Check for broadcast ssid */
+	for (k = 0; k < nssid; k++) {
+		if (!ssids_local[k].SSID_len) {
+			DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", k));
+			return err;
+		}
+	}
+/* #define  PNO_DUMP 1 */
+#ifdef PNO_DUMP
+	{
+		int j;
+		for (j = 0; j < nssid; j++) {
+			DHD_ERROR(("%d: scan  for  %s size =%d\n", j,
+				ssids_local[j].SSID, ssids_local[j].SSID_len));
+		}
+	}
+#endif /* PNO_DUMP */
+
+	/* clean up everything */
+	if  ((err = dhd_pno_clean(dhd)) < 0) {
+		DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err));
+		return err;
+	}
+	memset(&pfn_param, 0, sizeof(pfn_param));
+	memset(&pfn_element, 0, sizeof(pfn_element));
+
+	/* set pfn parameters */
+	pfn_param.version = htod32(PFN_VERSION);
+	pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
+
+	/* set up pno scan fr */
+	if (scan_fr  != 0)
+		pfn_param.scan_freq = htod32(scan_fr);
+
+	bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf));
+	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+	/* set all pfn ssid */
+	for (i = 0; i < nssid; i++) {
+
+		pfn_element.bss_type = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
+		pfn_element.auth = (DOT11_OPEN_SYSTEM);
+		pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
+		pfn_element.wsec = htod32(0);
+		pfn_element.infra = htod32(1);
+
+		memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len);
+		pfn_element.ssid.SSID_len = ssids_local[i].SSID_len;
+
+		if ((err =
+		bcm_mkiovar("pfn_add", (char *)&pfn_element,
+			sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) {
+			if ((err =
+			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
+				DHD_ERROR(("%s failed for i=%d error=%d\n",
+					__FUNCTION__, i, err));
+				return err;
+			}
+		}
+		else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err));
+	}
+
+	/* Enable PNO */
+	/* dhd_pno_enable(dhd, 1); */
+	return err;
+}
+
+int dhd_pno_get_status(dhd_pub_t *dhd)
+{
+	int ret = -1;
+
+	if (!dhd)
+		return ret;
+	else
+		return (dhd->pno_enable);
+}
+
+#endif /* PNO_SUPPORT */
+
+#if defined(CSCAN)
+
+/* Androd ComboSCAN support */
+/*
+ *  data parsing from ComboScan tlv list
+*/
+int
+wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token,
+                     int input_size, int *bytes_left)
+{
+	char* str = *list_str;
+	uint16 short_temp;
+	uint32 int_temp;
+
+	if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
+		DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+		return -1;
+	}
+
+	/* Clean all dest bytes */
+	memset(dst, 0, dst_size);
+	while (*bytes_left > 0) {
+
+		if (str[0] != token) {
+			DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n",
+				__FUNCTION__, token, str[0], *bytes_left));
+			return -1;
+		}
+
+		*bytes_left -= 1;
+		str += 1;
+
+		if (input_size == 1) {
+			memcpy(dst, str, input_size);
+		}
+		else if (input_size == 2) {
+			memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)),
+				input_size);
+		}
+		else if (input_size == 4) {
+			memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)),
+				input_size);
+		}
+
+		*bytes_left -= input_size;
+		str += input_size;
+		*list_str = str;
+		return 1;
+	}
+	return 1;
+}
+
+/*
+ *  channel list parsing from cscan tlv list
+*/
+int
+wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list,
+                             int channel_num, int *bytes_left)
+{
+	char* str = *list_str;
+	int idx = 0;
+
+	if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
+		DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+		return -1;
+	}
+
+	while (*bytes_left > 0) {
+
+		if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) {
+			*list_str = str;
+			DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
+			return idx;
+		}
+		/* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */
+		*bytes_left -= 1;
+		str += 1;
+
+		if (str[0] == 0) {
+			/* All channels */
+			channel_list[idx] = 0x0;
+		}
+		else {
+			channel_list[idx] = (uint16)str[0];
+			DHD_TRACE(("%s channel=%d \n", __FUNCTION__,  channel_list[idx]));
+		}
+		*bytes_left -= 1;
+		str += 1;
+
+		if (idx++ > 255) {
+			DHD_ERROR(("%s Too many channels \n", __FUNCTION__));
+			return -1;
+		}
+	}
+
+	*list_str = str;
+	return idx;
+}
+
+/*
+ *  SSIDs list parsing from cscan tlv list
+ */
+int
+wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left)
+{
+	char* str =  *list_str;
+	int idx = 0;
+
+	if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) {
+		DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+		return -1;
+	}
+
+	while (*bytes_left > 0) {
+
+		if (str[0] != CSCAN_TLV_TYPE_SSID_IE) {
+			*list_str = str;
+			DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
+			return idx;
+		}
+
+		/* Get proper CSCAN_TLV_TYPE_SSID_IE */
+		*bytes_left -= 1;
+		str += 1;
+
+		if (str[0] == 0) {
+			/* Broadcast SSID */
+			ssid[idx].SSID_len = 0;
+			memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN);
+			*bytes_left -= 1;
+			str += 1;
+
+			DHD_TRACE(("BROADCAST SCAN  left=%d\n", *bytes_left));
+		}
+		else if (str[0] <= DOT11_MAX_SSID_LEN) {
+			/* Get proper SSID size */
+			ssid[idx].SSID_len = str[0];
+			*bytes_left -= 1;
+			str += 1;
+
+			/* Get SSID */
+			if (ssid[idx].SSID_len > *bytes_left) {
+				DHD_ERROR(("%s out of memory range len=%d but left=%d\n",
+				__FUNCTION__, ssid[idx].SSID_len, *bytes_left));
+				return -1;
+			}
+
+			memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len);
+
+			*bytes_left -= ssid[idx].SSID_len;
+			str += ssid[idx].SSID_len;
+
+			DHD_TRACE(("%s :size=%d left=%d\n",
+				(char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left));
+		}
+		else {
+			DHD_ERROR(("### SSID size more that %d\n", str[0]));
+			return -1;
+		}
+
+		if (idx++ >  max) {
+			DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx));
+			return -1;
+		}
+	}
+
+	*list_str = str;
+	return idx;
+}
+
+/* Parse a comma-separated list from list_str into ssid array, starting
+ * at index idx.  Max specifies size of the ssid array.  Parses ssids
+ * and returns updated idx; if idx >= max not all fit, the excess have
+ * not been copied.  Returns -1 on empty string, or on ssid too long.
+ */
+int
+wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max)
+{
+	char* str, *ptr;
+
+	if ((list_str == NULL) || (*list_str == NULL))
+		return -1;
+
+	for (str = *list_str; str != NULL; str = ptr) {
+
+		/* check for next TAG */
+		if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) {
+			*list_str	 = str + strlen(GET_CHANNEL);
+			return idx;
+		}
+
+		if ((ptr = strchr(str, ',')) != NULL) {
+			*ptr++ = '\0';
+		}
+
+		if (strlen(str) > DOT11_MAX_SSID_LEN) {
+			DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN));
+			return -1;
+		}
+
+		if (strlen(str) == 0)
+			ssid[idx].SSID_len = 0;
+
+		if (idx < max) {
+			strcpy((char*)ssid[idx].SSID, str);
+			ssid[idx].SSID_len = strlen(str);
+		}
+		idx++;
+	}
+	return idx;
+}
+
+/*
+ * Parse channel list from iwpriv CSCAN
+ */
+int
+wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num)
+{
+	int num;
+	int val;
+	char* str;
+	char* endptr = NULL;
+
+	if ((list_str == NULL)||(*list_str == NULL))
+		return -1;
+
+	str = *list_str;
+	num = 0;
+	while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) {
+		val = (int)strtoul(str, &endptr, 0);
+		if (endptr == str) {
+			printf("could not parse channel number starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, *list_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num == channel_num) {
+			DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n",
+				channel_num, *list_str));
+			return -1;
+		}
+
+		channel_list[num++] = (uint16)val;
+	}
+	*list_str = str;
+	return num;
+}
+
+#endif 
diff --git a/bcm4329/src/dhd/sys/dhd_custom_gpio.c b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
index 2dc6e42..8c6ec47 100644
--- a/bcm4329/src/dhd/sys/dhd_custom_gpio.c
+++ b/bcm4329/src/dhd/sys/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.1.4.6 2010/02/19 22:56:49 Exp $
+* $Id: dhd_custom_gpio.c,v 1.1.4.8.4.1 2010/09/02 23:13:16 Exp $
 */
 
 
@@ -42,11 +42,11 @@
 extern  void bcm_wlan_power_off(int);
 extern  void bcm_wlan_power_on(int);
 #endif /* CUSTOMER_HW */
-
 #ifdef CUSTOMER_HW2
 int wifi_set_carddetect(int on);
 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);
 #endif
 
 #if defined(OOB_INTR_ONLY)
@@ -55,6 +55,10 @@
 extern int sdioh_mmc_irq(int irq);
 #endif /* (BCMLXSDMMC)  */
 
+#ifdef CUSTOMER_HW3
+#include <mach/gpio.h>
+#endif
+
 /* Customer specific Host GPIO defintion  */
 static int dhd_oob_gpio_num = -1; /* GG 19 */
 
@@ -63,27 +67,36 @@
 
 int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
 {
-	int  host_oob_irq;
+	int  host_oob_irq = 0;
+
 #ifdef CUSTOMER_HW2
 	host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
-#else
+
+#else /* for NOT  CUSTOMER_HW2 */
 #if defined(CUSTOM_OOB_GPIO_NUM)
 	if (dhd_oob_gpio_num < 0) {
 		dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
 	}
 #endif
-	*irq_flags_ptr = IRQF_TRIGGER_FALLING;
+
 	if (dhd_oob_gpio_num < 0) {
 		WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
-			             __FUNCTION__));
+			__FUNCTION__));
 		return (dhd_oob_gpio_num);
 	}
 
 	WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
 	         __FUNCTION__, dhd_oob_gpio_num));
 
-	host_oob_irq = sdioh_mmc_irq(dhd_oob_gpio_num);
-#endif
+#if defined CUSTOMER_HW
+	host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
+#elif defined CUSTOMER_HW3
+	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 /* CUSTOMER_HW2 */
+
 	return (host_oob_irq);
 }
 #endif /* defined(OOB_INTR_ONLY) */
@@ -130,9 +143,37 @@
 				__FUNCTION__));
 #ifdef CUSTOMER_HW
 			bcm_wlan_power_on(1);
-#endif /* CUSTOMER_HW */
 			/* Lets customer power to get stable */
-			OSL_DELAY(500);
+			OSL_DELAY(50);
+#endif /* CUSTOMER_HW */
 		break;
 	}
 }
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+/* Function to get custom MAC address */
+int
+dhd_custom_get_mac_address(unsigned char *buf)
+{
+	int ret = 0;
+
+	WL_TRACE(("%s Enter\n", __FUNCTION__));
+	if (!buf)
+		return -EINVAL;
+
+	/* Customer access to MAC address stored outside of DHD driver */
+#ifdef CUSTOMER_HW2
+	ret = wifi_get_mac_addr(buf);
+#endif
+
+#ifdef EXAMPLE_GET_MAC
+	/* EXAMPLE code */
+	{
+		struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
+		bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+	}
+#endif /* EXAMPLE_GET_MAC */
+
+	return ret;
+}
+#endif /* GET_CUSTOM_MAC_ENABLE */
diff --git a/bcm4329/src/dhd/sys/dhd_dbg.h b/bcm4329/src/dhd/sys/dhd_dbg.h
index e6d18f7..b48c1d7 100644
--- a/bcm4329/src/dhd/sys/dhd_dbg.h
+++ b/bcm4329/src/dhd/sys/dhd_dbg.h
@@ -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_dbg.h,v 1.5.6.2.4.2.14.4 2009/12/11 01:13:49 Exp $
+ * $Id: dhd_dbg.h,v 1.5.6.2.4.2.14.10 2010/05/21 21:49:38 Exp $
  */
 
 #ifndef _dhd_dbg_
@@ -42,6 +42,7 @@
 #define DHD_GLOM(args)		do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0)
 #define DHD_EVENT(args)		do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0)
 #define DHD_BTA(args)		do {if (dhd_msg_level & DHD_BTA_VAL) printf args;} while (0)
+#define DHD_ISCAN(args)		do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0)
 
 #define DHD_ERROR_ON()		(dhd_msg_level & DHD_ERROR_VAL)
 #define DHD_TRACE_ON()		(dhd_msg_level & DHD_TRACE_VAL)
@@ -55,6 +56,7 @@
 #define DHD_GLOM_ON()		(dhd_msg_level & DHD_GLOM_VAL)
 #define DHD_EVENT_ON()		(dhd_msg_level & DHD_EVENT_VAL)
 #define DHD_BTA_ON()		(dhd_msg_level & DHD_BTA_VAL)
+#define DHD_ISCAN_ON()		(dhd_msg_level & DHD_ISCAN_VAL)
 
 #else /* DHD_DEBUG */
 
@@ -70,6 +72,7 @@
 #define DHD_GLOM(args)
 #define DHD_EVENT(args)
 #define DHD_BTA(args)
+#define DHD_ISCAN(args)
 
 #define DHD_ERROR_ON()		0
 #define DHD_TRACE_ON()		0
@@ -83,7 +86,7 @@
 #define DHD_GLOM_ON()		0
 #define DHD_EVENT_ON()		0
 #define DHD_BTA_ON()		0
-
+#define DHD_ISCAN_ON()		0
 #endif /* DHD_DEBUG */
 
 #define DHD_LOG(args)
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index c25a9b7..2eff469 100644
--- a/bcm4329/src/dhd/sys/dhd_linux.c
+++ b/bcm4329/src/dhd/sys/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,v 1.65.4.9.2.12.2.66 2010/04/01 17:01:25 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104 2010/08/20 19:15:40 Exp $
  */
 
 #ifdef CONFIG_WIFI_CONTROL_FUNC
@@ -61,7 +61,6 @@
 #ifdef CONFIG_HAS_WAKELOCK
 #include <linux/wakelock.h>
 #endif
-#include <linux/freezer.h>
 #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
 #include <linux/wlan_plat.h>
 
@@ -116,6 +115,17 @@
 	return 0;
 }
 
+int wifi_get_mac_addr(unsigned char *buf)
+{
+	printk("%s\n", __FUNCTION__);
+	if (!buf)
+		return -EINVAL;
+	if (wifi_control_data && wifi_control_data->get_mac_addr) {
+		return wifi_control_data->get_mac_addr(buf);
+	}
+	return -EOPNOTSUPP;
+}
+
 static int wifi_probe(struct platform_device *pdev)
 {
 	struct wifi_platform_data *wifi_ctrl =
@@ -140,8 +150,8 @@
 	DHD_TRACE(("## %s\n", __FUNCTION__));
 	wifi_control_data = wifi_ctrl;
 
-	wifi_set_carddetect(0);	/* CardDetect (1->0) */
 	wifi_set_power(0, 0);	/* Power Off */
+	wifi_set_carddetect(0);	/* CardDetect (1->0) */
 
 	up(&wifi_control_sem);
 	return 0;
@@ -205,12 +215,18 @@
 /* Linux wireless extension support */
 #if defined(CONFIG_WIRELESS_EXT)
 #include <wl_iw.h>
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 #if defined(CONFIG_HAS_EARLYSUSPEND)
 #include <linux/earlysuspend.h>
+extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
 #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
 
+#ifdef PKT_FILTER_SUPPORT
+extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg);
+extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
+#endif
+
 /* Interface control information */
 typedef struct dhd_if {
 	struct dhd_info *info;			/* back pointer to dhd_info */
@@ -230,7 +246,7 @@
 typedef struct dhd_info {
 #if defined(CONFIG_WIRELESS_EXT)
 	wl_iw_t		iw;		/* wireless extensions state (must be first) */
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 	dhd_pub_t pub;
 
@@ -263,6 +279,8 @@
 	int wl_count;
 	int wl_packet;
 
+	int hang_was_sent;
+
 	/* Thread to issue ioctl for multicast */
 	long sysioc_pid;
 	struct semaphore sysioc_sem;
@@ -286,7 +304,8 @@
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 struct semaphore dhd_registration_sem;
-#endif 
+#define DHD_REGISTRATION_TIMEOUT  8000  /* msec : allowed time to finished dhd registration */
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
 /* load firmware and/or nvram values from the filesystem */
 module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
 module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
@@ -302,6 +321,31 @@
 uint dhd_watchdog_ms = 10;
 module_param(dhd_watchdog_ms, uint, 0);
 
+#ifdef DHD_DEBUG
+/* Console poll interval */
+uint dhd_console_ms = 0;
+module_param(dhd_console_ms, uint, 0);
+#endif /* DHD_DEBUG */
+
+/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */
+uint dhd_arp_mode = 0xb;
+module_param(dhd_arp_mode, uint, 0);
+
+/* ARP offload enable */
+uint dhd_arp_enable = TRUE;
+module_param(dhd_arp_enable, uint, 0);
+
+/* Global Pkt filter enable control */
+uint dhd_pkt_filter_enable = TRUE;
+module_param(dhd_pkt_filter_enable, uint, 0);
+
+/*  Pkt filter init setup */
+uint dhd_pkt_filter_init = 0;
+module_param(dhd_pkt_filter_init, uint, 0);
+
+/* Pkt filter mode control */
+uint dhd_master_mode = TRUE;
+module_param(dhd_master_mode, uint, 1);
 
 /* Watchdog thread priority, -1 to use kernel timer */
 int dhd_watchdog_prio = 97;
@@ -315,6 +359,16 @@
 extern int dhd_dongle_memsize;
 module_param(dhd_dongle_memsize, int, 0);
 
+/* Control fw roaming */
+#ifdef CUSTOMER_HW2
+uint dhd_roam = 0;
+#else
+uint dhd_roam = 1;
+#endif
+
+/* Control radio state */
+uint dhd_radio_up = 1;
+
 /* Network inteface name */
 char iface_name[IFNAMSIZ];
 module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
@@ -383,6 +437,9 @@
 
 /* Version string to report */
 #ifdef DHD_DEBUG
+#ifndef SRCBASE
+#define SRCBASE        "drivers/net/wireless/bcm4329"
+#endif
 #define DHD_COMPILED "\nCompiled in " SRCBASE
 #else
 #define DHD_COMPILED
@@ -397,7 +454,7 @@
 
 #if defined(CONFIG_WIRELESS_EXT)
 struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 static void dhd_dpc(ulong data);
 /* forward decl */
@@ -417,18 +474,22 @@
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
 static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored)
 {
-	switch (action)
-	{
-		case PM_HIBERNATION_PREPARE:
-		case PM_SUSPEND_PREPARE:
-			dhd_mmc_suspend = TRUE;
-			return NOTIFY_OK;
-		case PM_POST_HIBERNATION:
-		case PM_POST_SUSPEND:
-			dhd_mmc_suspend = FALSE;
-		return NOTIFY_OK;
+	int ret = NOTIFY_DONE;
+
+	switch (action) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		dhd_mmc_suspend = TRUE;
+		ret = NOTIFY_OK;
+		break;
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		dhd_mmc_suspend = FALSE;
+		ret = NOTIFY_OK;
+		break;
 	}
-	return 0;
+	smp_mb();
+	return ret;
 }
 
 static struct notifier_block dhd_sleep_pm_notifier = {
@@ -439,28 +500,126 @@
 extern int unregister_pm_notifier(struct notifier_block *nb);
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
 
+static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
+{
+#ifdef PKT_FILTER_SUPPORT
+	DHD_TRACE(("%s: %d\n", __FUNCTION__, value));
+	/* 1 - Enable packet filter, only allow unicast packet to send up */
+	/* 0 - Disable packet filter */
+	if (dhd_pkt_filter_enable) {
+		int i;
+
+		for (i = 0; i < dhd->pktfilter_count; i++) {
+			dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
+			dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
+					value, dhd_master_mode);
+		}
+	}
+#endif
+}
 
 #if defined(CONFIG_HAS_EARLYSUSPEND)
-extern int dhd_set_suspend(int value, dhd_pub_t *dhd);
+static int dhd_set_suspend(int value, dhd_pub_t *dhd)
+{
+	int power_mode = PM_MAX;
+	/* wl_pkt_filter_enable_t	enable_parm; */
+	char iovbuf[32];
+	int bcn_li_dtim = 3;
+#ifdef CUSTOMER_HW2
+	uint roamvar = 1;
+#endif /* CUSTOMER_HW2 */
+
+	DHD_TRACE(("%s: enter, value = %d in_suspend = %d\n",
+			__FUNCTION__, value, dhd->in_suspend));
+
+	if (dhd && dhd->up) {
+		if (value && dhd->in_suspend) {
+
+			/* Kernel suspended */
+				DHD_TRACE(("%s: force extra Suspend setting \n", __FUNCTION__));
+
+			dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
+				(char *)&power_mode, sizeof(power_mode));
+
+			/* Enable packet filter, only allow unicast packet to send up */
+			dhd_set_packet_filter(1, dhd);
+
+				/* if dtim skip setup as default force it to wake each thrid dtim
+				 *  for better power saving.
+				 *  Note that side effect is chance to miss BC/MC packet
+				*/
+				if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1))
+					bcn_li_dtim = 3;
+				else
+					bcn_li_dtim = dhd->dtim_skip;
+			bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+				4, iovbuf, sizeof(iovbuf));
+			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#ifdef CUSTOMER_HW2
+			/* Disable build-in roaming to allowed ext supplicant to take of roaming */
+			bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#endif /* CUSTOMER_HW2 */
+		} else {
+
+			/* Kernel resumed  */
+				DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__));
+
+			power_mode = PM_FAST;
+			dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
+				sizeof(power_mode));
+
+			/* disable pkt filter */
+			dhd_set_packet_filter(0, dhd);
+
+				/* restore pre-suspend setting for dtim_skip */
+				bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
+					4, iovbuf, sizeof(iovbuf));
+
+				dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#ifdef CUSTOMER_HW2
+			roamvar = dhd_roam;
+			bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#endif /* CUSTOMER_HW2 */
+		}
+	}
+
+	return 0;
+}
+
+static void dhd_suspend_resume_helper(struct dhd_info *dhd, int val)
+{
+	dhd_pub_t *dhdp = &dhd->pub;
+
+	dhd_os_wake_lock(dhdp);
+	dhd_os_proto_block(dhdp);
+	/* Set flag when early suspend was called */
+	dhdp->in_suspend = val;
+	if (!dhdp->suspend_disable_flag)
+		dhd_set_suspend(val, dhdp);
+	dhd_os_proto_unblock(dhdp);
+	dhd_os_wake_unlock(dhdp);
+}
 
 static void dhd_early_suspend(struct early_suspend *h)
 {
-	struct dhd_info *dhdp;
-	dhdp = container_of(h, struct dhd_info, early_suspend);
+	struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
 
 	DHD_TRACE(("%s: enter\n", __FUNCTION__));
 
-	dhd_set_suspend(1, &dhdp->pub);
+	if (dhd)
+		dhd_suspend_resume_helper(dhd, 1);
 }
 
 static void dhd_late_resume(struct early_suspend *h)
 {
-	struct dhd_info *dhdp;
-	dhdp = container_of(h, struct dhd_info, early_suspend);
+	struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
 
 	DHD_TRACE(("%s: enter\n", __FUNCTION__));
 
-	dhd_set_suspend(0, &dhdp->pub);
+	if (dhd)
+		dhd_suspend_resume_helper(dhd, 0);
 }
 #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
 
@@ -584,7 +743,11 @@
 _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 {
 	struct net_device *dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+	struct netdev_hw_addr *ha;
+#else
 	struct dev_mc_list *mclist;
+#endif
 	uint32 allmulti, cnt;
 
 	wl_ioctl_t ioc;
@@ -594,15 +757,19 @@
 
 	ASSERT(dhd && dhd->iflist[ifidx]);
 	dev = dhd->iflist[ifidx]->net;
-	mclist = dev->mc_list;
+
+	netif_addr_lock_bh(dev);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+	cnt = netdev_mc_count(dev);
+#else
 	cnt = dev->mc_count;
+#endif
+	netif_addr_unlock_bh(dev);
 
 	/* Determine initial value of allmulti flag */
 	allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE;
 
 	/* Send down the multicast list first. */
-
-
 	buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETHER_ADDR_LEN);
 	if (!(bufp = buf = MALLOC(dhd->pub.osh, buflen))) {
 		DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
@@ -617,10 +784,22 @@
 	memcpy(bufp, &cnt, sizeof(cnt));
 	bufp += sizeof(cnt);
 
-	for (cnt = 0; mclist && (cnt < dev->mc_count); cnt++, mclist = mclist->next) {
+	netif_addr_lock_bh(dev);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+	netdev_for_each_mc_addr(ha, dev) {
+		if (!cnt)
+			break;
+		memcpy(bufp, ha->addr, ETHER_ADDR_LEN);
+		bufp += ETHER_ADDR_LEN;
+		cnt--;
+	}
+#else
+	for (mclist = dev->mc_list;(mclist && (cnt > 0)); cnt--, mclist = mclist->next) {
 		memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN);
 		bufp += ETHER_ADDR_LEN;
 	}
+#endif
+	netif_addr_unlock_bh(dev);
 
 	memset(&ioc, 0, sizeof(ioc));
 	ioc.cmd = WLC_SET_VAR;
@@ -810,8 +989,6 @@
 	bool in_ap = FALSE;
 #endif
 
-	set_freezable();
-
 	DAEMONIZE("dhd_sysioc");
 
 	while (down_interruptible(&dhd->sysioc_sem) == 0) {
@@ -941,11 +1118,19 @@
 
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
+	dhd_os_wake_lock(&dhd->pub);
+
 	/* Reject if down */
 	if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) {
 		DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
 			 __FUNCTION__, dhd->pub.up, dhd->pub.busstate));
 		netif_stop_queue(net);
+		/* Send Event when bus down detected during data session */
+		if (dhd->pub.busstate == DHD_BUS_DOWN)  {
+			DHD_ERROR(("%s: Event HANG send up\n", __FUNCTION__));
+			net_os_send_hang_message(net);
+		}
+		dhd_os_wake_unlock(&dhd->pub);
 		return -ENODEV;
 	}
 
@@ -953,6 +1138,7 @@
 	if (ifidx == DHD_BAD_IF) {
 		DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx));
 		netif_stop_queue(net);
+		dhd_os_wake_unlock(&dhd->pub);
 		return -ENODEV;
 	}
 
@@ -984,13 +1170,14 @@
 
 	ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf);
 
-
 done:
 	if (ret)
 		dhd->pub.dstats.tx_dropped++;
 	else
 		dhd->pub.tx_packets++;
 
+	dhd_os_wake_unlock(&dhd->pub);
+
 	/* Return ok: we always eat the packet */
 	return 0;
 }
@@ -1187,24 +1374,19 @@
 	}
 #endif /* DHD_SCHED */
 
-	set_freezable();
-
 	DAEMONIZE("dhd_watchdog");
 
 	/* Run until signal received */
 	while (1) {
 		if (down_interruptible (&dhd->watchdog_sem) == 0) {
 			dhd_os_wake_lock(&dhd->pub);
-			/* Call the bus module watchdog */
-			dhd_bus_watchdog(&dhd->pub);
 
+			if (dhd->pub.dongle_reset == FALSE) {
+				/* Call the bus module watchdog */
+				dhd_bus_watchdog(&dhd->pub);
+			}
 			/* Count the tick for reference */
 			dhd->pub.tickcnt++;
-
-			/* Reschedule the watchdog */
-			if (dhd->wd_timer_valid) {
-				mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-			}
 			dhd_os_wake_unlock(&dhd->pub);
 		}
 		else
@@ -1219,8 +1401,15 @@
 {
 	dhd_info_t *dhd = (dhd_info_t *)data;
 
+	dhd_os_wake_lock(&dhd->pub);
 	if (dhd->watchdog_pid >= 0) {
 		up(&dhd->watchdog_sem);
+
+		/* Reschedule the watchdog */
+		if (dhd->wd_timer_valid) {
+				mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+		}
+		dhd_os_wake_unlock(&dhd->pub);
 		return;
 	}
 
@@ -1231,12 +1420,9 @@
 	dhd->pub.tickcnt++;
 
 	/* Reschedule the watchdog */
-#if defined(CONTINUOUS_WATCHDOG)
-	mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-#else
 	if (dhd->wd_timer_valid)
 		mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-#endif /* defined(CONTINUOUS_WATCHDOG) */
+	dhd_os_wake_unlock(&dhd->pub);
 }
 
 static int
@@ -1256,8 +1442,6 @@
 	}
 #endif /* DHD_SCHED */
 
-	set_freezable();
-
 	DAEMONIZE("dhd_dpc");
 
 	/* Run until signal received */
@@ -1526,28 +1710,40 @@
 	uint driver = 0;
 	int ifidx;
 	bool is_set_key_cmd;
+	int ret;
+
+	dhd_os_wake_lock(&dhd->pub);
 
 	ifidx = dhd_net2idx(dhd, net);
 	DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
 
-	if (ifidx == DHD_BAD_IF)
+	if (ifidx == DHD_BAD_IF) {
+		dhd_os_wake_unlock(&dhd->pub);
 		return -1;
+	}
 
 #if defined(CONFIG_WIRELESS_EXT)
 	/* linux wireless extensions */
 	if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
 		/* may recurse, do NOT lock */
-		return wl_iw_ioctl(net, ifr, cmd);
+		ret = wl_iw_ioctl(net, ifr, cmd);
+		dhd_os_wake_unlock(&dhd->pub);
+		return ret;
 	}
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
-	if (cmd == SIOCETHTOOL)
-		return (dhd_ethtool(dhd, (void*)ifr->ifr_data));
+	if (cmd == SIOCETHTOOL) {
+		ret = dhd_ethtool(dhd, (void*)ifr->ifr_data);
+		dhd_os_wake_unlock(&dhd->pub);
+		return ret;
+	}
 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
 
-	if (cmd != SIOCDEVPRIVATE)
+	if (cmd != SIOCDEVPRIVATE) {
+		dhd_os_wake_unlock(&dhd->pub);
 		return -EOPNOTSUPP;
+	}
 
 	memset(&ioc, 0, sizeof(ioc));
 
@@ -1600,7 +1796,7 @@
 
 	/* send to dongle (must be up, and wl) */
 	if (dhd->pub.busstate != DHD_BUS_DATA) {
-		DHD_ERROR(("%s DONGLE_DOWN,__FUNCTION__\n", __FUNCTION__));
+		DHD_ERROR(("%s DONGLE_DOWN\n", __FUNCTION__));
 		bcmerror = BCME_DONGLE_DOWN;
 		goto done;
 	}
@@ -1625,6 +1821,12 @@
 	bcmerror = dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
 
 done:
+	if ((bcmerror == -ETIMEDOUT) || ((dhd->pub.busstate == DHD_BUS_DOWN) &&
+			(!dhd->pub.dongle_reset))) {
+		DHD_ERROR(("%s: Event HANG send up\n", __FUNCTION__));
+		net_os_send_hang_message(net);
+	}
+
 	if (!bcmerror && buf && ioc.buf) {
 		if (copy_to_user(ioc.buf, buf, buflen))
 			bcmerror = -EFAULT;
@@ -1633,6 +1835,8 @@
 	if (buf)
 		MFREE(dhd->pub.osh, buf, buflen);
 
+	dhd_os_wake_unlock(&dhd->pub);
+
 	return OSL_ERROR(bcmerror);
 }
 
@@ -1643,7 +1847,6 @@
 	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
 
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
 	if (dhd->pub.up == 0) {
 		return 0;
 	}
@@ -1673,7 +1876,11 @@
 	ifidx = dhd_net2idx(dhd, net);
 	DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
 
-	/* ASSERT(ifidx == 0); */
+	if ((dhd->iflist[ifidx]) && (dhd->iflist[ifidx]->state == WLC_E_IF_DEL)) {
+		DHD_ERROR(("%s: Error: called when IF already deleted\n", __FUNCTION__));
+		return -1;
+	}
+
 
 	if (ifidx == 0) { /* do it only for primary eth0 */
 
@@ -1712,7 +1919,7 @@
 	osl_detach(osh);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
 	up(&dhd_registration_sem);
-#endif 
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
 }
 
 int
@@ -1860,7 +2067,7 @@
 		DHD_ERROR(("wl_iw_attach failed\n"));
 		goto fail;
 	}
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 	/* Set up the watchdog timer */
 	init_timer(&dhd->timer);
@@ -1940,6 +2147,9 @@
 {
 	int ret = -1;
 	dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
+#ifdef EMBEDDED_PLATFORM
+	char iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
+#endif /* EMBEDDED_PLATFORM */
 
 	ASSERT(dhd);
 
@@ -1985,6 +2195,41 @@
 		return -ENODEV;
 	}
 
+#ifdef EMBEDDED_PLATFORM
+	bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+	dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
+	bcopy(iovbuf, dhdp->eventmask, WL_EVENTING_MASK_LEN);
+
+	setbit(dhdp->eventmask, WLC_E_SET_SSID);
+	setbit(dhdp->eventmask, WLC_E_PRUNE);
+	setbit(dhdp->eventmask, WLC_E_AUTH);
+	setbit(dhdp->eventmask, WLC_E_REASSOC);
+	setbit(dhdp->eventmask, WLC_E_REASSOC_IND);
+	setbit(dhdp->eventmask, WLC_E_DEAUTH_IND);
+	setbit(dhdp->eventmask, WLC_E_DISASSOC_IND);
+	setbit(dhdp->eventmask, WLC_E_DISASSOC);
+	setbit(dhdp->eventmask, WLC_E_JOIN);
+	setbit(dhdp->eventmask, WLC_E_ASSOC_IND);
+	setbit(dhdp->eventmask, WLC_E_PSK_SUP);
+	setbit(dhdp->eventmask, WLC_E_LINK);
+	setbit(dhdp->eventmask, WLC_E_NDIS_LINK);
+	setbit(dhdp->eventmask, WLC_E_MIC_ERROR);
+	setbit(dhdp->eventmask, WLC_E_PMKID_CACHE);
+	setbit(dhdp->eventmask, WLC_E_TXFAIL);
+	setbit(dhdp->eventmask, WLC_E_JOIN_START);
+	setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
+#ifdef PNO_SUPPORT
+	setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
+#endif /* PNO_SUPPORT */
+
+/* enable dongle roaming event */
+	setbit(dhdp->eventmask, WLC_E_ROAM);
+
+	dhdp->pktfilter_count = 1;
+	/* Setup filter to allow only unicast */
+	dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00";
+#endif /* EMBEDDED_PLATFORM */
+
 	/* Bus is ready, do any protocol initialization */
 	if ((ret = dhd_prot_init(&dhd->pub)) < 0)
 		return ret;
@@ -2080,21 +2325,21 @@
 	if (ifidx == 1) {
 		DHD_TRACE(("%s ACCESS POINT MAC: \n", __FUNCTION__));
 		/*  ACCESSPOINT INTERFACE CASE */
-		temp_addr[0] |= 0X02;  /* set bit 2 , - Locally Administered address  */
+		temp_addr[0] |= 0x02;  /* set bit 2 , - Locally Administered address  */
 	}
 	net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 	net->ethtool_ops = &dhd_ethtool_ops;
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
 
-#ifdef CONFIG_WIRELESS_EXT
+#if defined(CONFIG_WIRELESS_EXT)
 #if WIRELESS_EXT < 19
 	net->get_wireless_stats = dhd_get_wireless_stats;
 #endif /* WIRELESS_EXT < 19 */
 #if WIRELESS_EXT > 12
 	net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def;
 #endif /* WIRELESS_EXT > 12 */
-#endif /* CONFIG_WIRELESS_EXT */
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 	dhd->pub.rxsz = net->mtu + net->hard_header_len + dhd->pub.hdrlen;
 
@@ -2108,6 +2353,8 @@
 	printf("%s: Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", net->name,
 	       dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
 	       dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
+
+#if defined(CONFIG_WIRELESS_EXT)
 #ifdef SOFTAP
 	if (ifidx == 0)
 		/* Don't call for SOFTAP Interface in SOFTAP MODE */
@@ -2115,10 +2362,11 @@
 #else
 		wl_iw_iscan_set_scan_broadcast_prep(net, 1);
 #endif /* SOFTAP */
+#endif /* CONFIG_WIRELESS_EXT */
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 	up(&dhd_registration_sem);
-#endif 
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
 	return 0;
 
 fail:
@@ -2170,7 +2418,8 @@
 			int i;
 
 #if defined(CONFIG_HAS_EARLYSUSPEND)
-			unregister_early_suspend(&dhd->early_suspend);
+			if (dhd->early_suspend.suspend)
+				unregister_early_suspend(&dhd->early_suspend);
 #endif	/* defined(CONFIG_HAS_EARLYSUSPEND) */
 #if defined(CONFIG_WIRELESS_EXT)
 			/* Attach and link in the iw */
@@ -2230,6 +2479,19 @@
 	}
 }
 
+static void __exit
+dhd_module_cleanup(void)
+{
+	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+	dhd_bus_unregister();
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+	wifi_del_dev();
+#endif
+	/* Call customer gpio to turn off power with WL_REG_ON signal */
+	dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+}
+
 static int __init
 dhd_module_init(void)
 {
@@ -2289,7 +2551,7 @@
 	 * It's needed to make sync up exit from dhd insmod  and
 	 * Kernel MMC sdio device callback registration
 	 */
-	if (down_timeout(&dhd_registration_sem,  msecs_to_jiffies(10000)) != 0) {
+	if (down_timeout(&dhd_registration_sem,  msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) {
 		error = -EINVAL;
 		DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__));
 		goto fail_2;
@@ -2312,20 +2574,6 @@
 	return error;
 }
 
-static void __exit
-dhd_module_cleanup(void)
-{
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-	dhd_bus_unregister();
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-	wifi_del_dev();
-#endif
-	/* Call customer gpio to turn off power with WL_REG_ON signal */
-	dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
-}
-
-
 module_init(dhd_module_init);
 module_exit(dhd_module_cleanup);
 
@@ -2378,14 +2626,17 @@
 	int timeout = dhd_ioctl_timeout_msec;
 
 	/* Convert timeout in millsecond to jiffies */
-	timeout = timeout * HZ / 1000;
+	/* timeout = timeout * HZ / 1000; */
+	timeout = msecs_to_jiffies(timeout);
 
 	/* Wait until control frame is available */
 	add_wait_queue(&dhd->ioctl_resp_wait, &wait);
 	set_current_state(TASK_INTERRUPTIBLE);
-
-	while (!(*condition) && (!signal_pending(current) && timeout))
+	smp_mb();
+	while (!(*condition) && (!signal_pending(current) && timeout)) {
 		timeout = schedule_timeout(timeout);
+		smp_mb();
+	}
 
 	if (signal_pending(current))
 		*pending = TRUE;
@@ -2412,8 +2663,12 @@
 dhd_os_wd_timer(void *bus, uint wdtick)
 {
 	dhd_pub_t *pub = bus;
-	dhd_info_t *dhd = (dhd_info_t *)pub->info;
 	static uint save_dhd_watchdog_ms = 0;
+	dhd_info_t *dhd = (dhd_info_t *)pub->info;
+
+	/* don't start the wd until fw is loaded */
+	if (pub->busstate == DHD_BUS_DOWN)
+		return;
 
 	/* Totally stop the timer */
 	if (!wdtick && dhd->wd_timer_valid == TRUE) {
@@ -2577,7 +2832,7 @@
 	else
 		return NULL;
 }
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 static int
 dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
@@ -2594,8 +2849,18 @@
 #if defined(CONFIG_WIRELESS_EXT)
 	ASSERT(dhd->iflist[*ifidx] != NULL);
 
-	wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
-#endif
+	if (ntoh32(event->event_type) == WLC_E_IF) {
+		DHD_INFO(("<0> interface:%d OP:%d don't pass to wext,"
+			"net_device might not be created yet\n",
+				*ifidx, ntoh32(event->event_type)));
+		return bcmerror;
+	}
+
+	ASSERT(dhd->iflist[*ifidx]->net != NULL);
+
+	if (dhd->iflist[*ifidx]->net)
+		wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 	return (bcmerror);
 }
@@ -2645,12 +2910,70 @@
 	/* Turning on watchdog back */
 	if (!flag)
 		dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
-
 	DHD_ERROR(("%s:  WLAN OFF DONE\n", __FUNCTION__));
 
 	return 1;
 }
 
+int net_os_set_suspend_disable(struct net_device *dev, int val)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+	int ret = 0;
+
+	if (dhd) {
+		ret = dhd->pub.suspend_disable_flag;
+		dhd->pub.suspend_disable_flag = val;
+	}
+	return ret;
+}
+
+int net_os_set_suspend(struct net_device *dev, int val)
+{
+	int ret = 0;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+	if (dhd) {
+		dhd_os_proto_block(&dhd->pub);
+		ret = dhd_set_suspend(val, &dhd->pub);
+		dhd_os_proto_unblock(&dhd->pub);
+	}
+#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+	return ret;
+}
+
+int net_os_set_dtim_skip(struct net_device *dev, int val)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+	if (dhd)
+		dhd->pub.dtim_skip = val;
+
+	return 0;
+}
+
+int net_os_set_packet_filter(struct net_device *dev, int val)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+	int ret = 0;
+
+	/* Packet filtering is set only if we still in early-suspend and
+	 * we need either to turn it ON or turn it OFF
+	 * We can always turn it OFF in case of early-suspend, but we turn it
+	 * back ON only if suspend_disable_flag was not set
+	*/
+	if (dhd && dhd->pub.up) {
+		dhd_os_proto_block(&dhd->pub);
+		if (dhd->pub.in_suspend) {
+			if (!val || (val && !dhd->pub.suspend_disable_flag))
+				dhd_set_packet_filter(val, &dhd->pub);
+		}
+		dhd_os_proto_unblock(&dhd->pub);
+	}
+	return ret;
+}
+
+
 void
 dhd_dev_init_ioctl(struct net_device *dev)
 {
@@ -2659,6 +2982,47 @@
 	dhd_preinit_ioctls(&dhd->pub);
 }
 
+#ifdef PNO_SUPPORT
+/* Linux wrapper to call common dhd_pno_clean */
+int
+dhd_dev_pno_reset(struct net_device *dev)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+	return (dhd_pno_clean(&dhd->pub));
+}
+
+
+/* Linux wrapper to call common dhd_pno_enable */
+int
+dhd_dev_pno_enable(struct net_device *dev,  int pfn_enabled)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+	return (dhd_pno_enable(&dhd->pub, pfn_enabled));
+}
+
+
+/* Linux wrapper to call common dhd_pno_set */
+int
+dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ushort  scan_fr)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+	return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr));
+}
+
+/* Linux wrapper to get  pno status */
+int
+dhd_dev_get_pno_status(struct net_device *dev)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+	return (dhd_pno_get_status(&dhd->pub));
+}
+
+#endif /* PNO_SUPPORT */
+
 static int
 dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
 {
@@ -2687,6 +3051,43 @@
 	return pend;
 }
 
+#ifdef DHD_DEBUG
+int
+write_to_file(dhd_pub_t *dhd, uint8 *buf, int size)
+{
+	int ret = 0;
+	struct file *fp;
+	mm_segment_t old_fs;
+	loff_t pos = 0;
+
+	/* change to KERNEL_DS address limit */
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	/* open file to write */
+	fp = filp_open("/tmp/mem_dump", O_WRONLY|O_CREAT, 0640);
+	if (!fp) {
+		printf("%s: open file error\n", __FUNCTION__);
+		ret = -1;
+		goto exit;
+	}
+
+	/* Write buf to file */
+	fp->f_op->write(fp, buf, size, &pos);
+
+exit:
+	/* free buf before return */
+	MFREE(dhd->osh, buf, size);
+	/* close file before return */
+	if (fp)
+		filp_close(fp, current->files);
+	/* restore previous address limit */
+	set_fs(old_fs);
+
+	return ret;
+}
+#endif /* DHD_DEBUG */
+
 int dhd_os_wake_lock_timeout(dhd_pub_t *pub)
 {
 	dhd_info_t *dhd = (dhd_info_t *)(pub->info);
@@ -2803,3 +3204,17 @@
 		ret = dhd_os_wake_unlock(&dhd->pub);
 	return ret;
 }
+
+int net_os_send_hang_message(struct net_device *dev)
+{
+	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+	int ret = 0;
+
+	if (dhd) {
+		if (!dhd->hang_was_sent) {
+			dhd->hang_was_sent = 1;
+			ret = wl_iw_send_priv_event(dev, "HANG");
+		}
+	}
+	return ret;
+}
diff --git a/bcm4329/src/dhd/sys/dhd_linux_sched.c b/bcm4329/src/dhd/sys/dhd_linux_sched.c
index 3189123..480b416 100644
--- a/bcm4329/src/dhd/sys/dhd_linux_sched.c
+++ b/bcm4329/src/dhd/sys/dhd_linux_sched.c
@@ -1,7 +1,7 @@
 /*
  * Expose some of the kernel scheduler routines
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/sys/dhd_proto.h b/bcm4329/src/dhd/sys/dhd_proto.h
index 1e2401a..7ef6929 100644
--- a/bcm4329/src/dhd/sys/dhd_proto.h
+++ b/bcm4329/src/dhd/sys/dhd_proto.h
@@ -4,7 +4,7 @@
  * Provides type definitions and function prototypes used to link the
  * DHD OS, bus, and protocol modules.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -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_proto.h,v 1.2.82.1.4.1.16.6 2009/06/17 01:01:55 Exp $
+ * $Id: dhd_proto.h,v 1.2.82.1.4.1.16.7 2010/05/10 12:54:59 Exp $
  */
 
 #ifndef _dhd_proto_h_
@@ -34,7 +34,11 @@
 #include <wlioctl.h>
 
 #ifndef IOCTL_RESP_TIMEOUT
-#define IOCTL_RESP_TIMEOUT  2000 /* In milli second */
+#define IOCTL_RESP_TIMEOUT  3000 /* In milli second */
+#endif
+
+#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
+#define IOCTL_CHIP_ACTIVE_TIMEOUT  10 /* In milli second */
 #endif
 
 /*
diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c
index 8cb567f..bd73556 100644
--- a/bcm4329/src/dhd/sys/dhd_sdio.c
+++ b/bcm4329/src/dhd/sys/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,v 1.157.2.27.2.33.2.109 2010/04/22 05:52:46 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.129.4.1 2010/09/02 23:13:16 Exp $
  */
 
 #include <typedefs.h>
@@ -36,13 +36,11 @@
 #include <bcmutils.h>
 #include <bcmendian.h>
 #include <bcmdevs.h>
-
 #include <siutils.h>
 #include <hndpmu.h>
 #include <hndsoc.h>
 #include <sbchipc.h>
 #include <sbhnddma.h>
-
 #include <sdio.h>
 #include <sbsdio.h>
 #include <sbsdpcmdev.h>
@@ -60,6 +58,13 @@
 #include <dhdioctl.h>
 #include <sdiovar.h>
 
+#ifdef DHD_DEBUG
+#include <hndrte_cons.h>
+#endif /* DHD_DEBUG */
+#ifdef DHD_DEBUG_TRAP
+#include <hndrte_armtrap.h>
+#endif /* DHD_DEBUG_TRAP */
+
 #define QLEN		256	/* bulk rx and tx queue lengths */
 #define FCHI		(QLEN - 10)
 #define FCLOW		(FCHI / 2)
@@ -119,11 +124,11 @@
 /* Bump up limit on waiting for HT to account for first startup;
  * if the image is doing a CRC calculation before programming the PMU
  * for HT availability, it could take a couple hundred ms more, so
- * max out at a half second (500000us).
+ * max out at a 1 second (1000000us).
  */
-#if (PMU_MAX_TRANSITION_DLY <= 500000)
+#if (PMU_MAX_TRANSITION_DLY < 1000000)
 #undef PMU_MAX_TRANSITION_DLY
-#define PMU_MAX_TRANSITION_DLY 500000
+#define PMU_MAX_TRANSITION_DLY 1000000
 #endif
 
 /* Value for ChipClockCSR during initial setup */
@@ -141,6 +146,17 @@
 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
 
+#ifdef DHD_DEBUG
+/* Device console log buffer state */
+typedef struct dhd_console {
+	uint		count;			/* Poll interval msec counter */
+	uint		log_addr;		/* Log struct address (fixed) */
+	hndrte_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 */
 
 /* Private data for SDIO bus interaction */
 typedef struct dhd_bus {
@@ -208,6 +224,10 @@
 	uint		polltick;		/* Tick counter */
 	uint		pollcnt;		/* Count of active polls */
 
+#ifdef DHD_DEBUG
+	dhd_console_t	console;		/* Console output polling support */
+	uint		console_addr;		/* Console address from shared struct */
+#endif /* DHD_DEBUG */
 
 	uint		regfails;		/* Count of R_REG/W_REG failures */
 
@@ -404,6 +424,10 @@
 static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
 #endif
 
+#ifdef DHD_DEBUG_TRAP
+static int dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size);
+static int dhdsdio_mem_dump(dhd_bus_t *bus);
+#endif /* DHD_DEBUG_TRAP */
 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
 
 static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
@@ -929,7 +953,6 @@
 	        (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
 	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
 	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-	bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 
 #ifdef DHD_DEBUG
 	tx_packets[PKTPRIO(pkt)]++;
@@ -995,6 +1018,9 @@
 			}
 
 		}
+		if (ret == 0) {
+			bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+		}
 	} while ((ret < 0) && retrydata && retries++ < TXRETRIES);
 
 done:
@@ -1046,7 +1072,7 @@
 	/* Check for existing queue, current flow-control, pending event, or pending clock */
 	if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
 	    (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
-	    (bus->clkstate == CLK_PENDING)) {
+	    (bus->clkstate != CLK_AVAIL)) {
 		DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
 			pktq_len(&bus->txq)));
 		bus->fcqueued++;
@@ -1082,6 +1108,7 @@
 
 		/* Otherwise, send it now */
 		BUS_WAKE(bus);
+		/* Make sure back plane ht clk is on, no pending allowed */
 		dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
 
 #ifndef SDTEST
@@ -1236,6 +1263,8 @@
 	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
 	if (!DATAOK(bus)) {
+		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
+			__FUNCTION__, bus->tx_max, bus->tx_seq));
 		bus->ctrl_frame_stat = TRUE;
 		/* Send from dpc */
 		bus->ctrl_frame_buf = frame;
@@ -1243,15 +1272,16 @@
 
 		dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
 
-		if (bus->ctrl_frame_stat == FALSE)
+		if (bus->ctrl_frame_stat == FALSE) {
+			DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
 			ret = 0;
-		else
+		} else {
+			DHD_INFO(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
 			ret = -1;
+		}
 	}
 
 	if (ret == -1) {
-		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
 #ifdef DHD_DEBUG
 		if (DHD_BYTES_ON() && DHD_CTL_ON()) {
 			prhex("Tx Frame", frame, len);
@@ -1261,6 +1291,7 @@
 #endif
 
 		do {
+			bus->ctrl_frame_stat = FALSE;
 			ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
 			                          frame, len, NULL, NULL, NULL);
 			ASSERT(ret != BCME_PENDING);
@@ -1289,6 +1320,9 @@
 				}
 
 			}
+			if (ret == 0) {
+				bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+			}
 		} while ((ret < 0) && retries++ < TXRETRIES);
 	}
 
@@ -1333,11 +1367,21 @@
 		         __FUNCTION__, rxlen, msglen));
 	} else if (timeleft == 0) {
 		DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
+#ifdef DHD_DEBUG_TRAP
+		dhd_os_sdlock(bus->dhd);
+		dhdsdio_checkdied(bus, NULL, 0);
+		dhd_os_sdunlock(bus->dhd);
+#endif /* DHD_DEBUG_TRAP */
 	} else if (pending == TRUE) {
 		DHD_CTL(("%s: cancelled\n", __FUNCTION__));
 		return -ERESTARTSYS;
 	} else {
 		DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
+#ifdef DHD_DEBUG_TRAP
+		dhd_os_sdlock(bus->dhd);
+		dhdsdio_checkdied(bus, NULL, 0);
+		dhd_os_sdunlock(bus->dhd);
+#endif /* DHD_DEBUG_TRAP */
 	}
 
 	if (rxlen)
@@ -1357,6 +1401,9 @@
 	IOV_SDCIS,
 	IOV_MEMBYTES,
 	IOV_MEMSIZE,
+#ifdef DHD_DEBUG_TRAP
+	IOV_CHECKDIED,
+#endif
 	IOV_DOWNLOAD,
 	IOV_FORCEEVEN,
 	IOV_SDIOD_DRIVE,
@@ -1408,6 +1455,9 @@
 	{"txminmax", IOV_TXMINMAX,	0,	IOVT_UINT32,	0 },
 	{"cpu",		IOV_CPU,	0,	IOVT_BOOL,	0 },
 #endif /* DHD_DEBUG */
+#ifdef DHD_DEBUG_TRAP
+	{"checkdied",	IOV_CHECKDIED,	0,	IOVT_BUFFER,	0 },
+#endif /* DHD_DEBUG_TRAP  */
 #ifdef SDTEST
 	{"extloop",	IOV_EXTLOOP,	0,	IOVT_BOOL,	0 },
 	{"pktgen",	IOV_PKTGEN,	0,	IOVT_BUFFER,	sizeof(dhd_pktgen_t) },
@@ -1636,6 +1686,301 @@
 	return bcmerror;
 }
 
+#ifdef DHD_DEBUG_TRAP
+static int
+dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
+{
+	uint32 addr;
+	int rv;
+
+	/* Read last word in memory to determine address of sdpcm_shared structure */
+	if ((rv = dhdsdio_membytes(bus, FALSE, bus->ramsize - 4, (uint8 *)&addr, 4)) < 0)
+		return rv;
+
+	addr = ltoh32(addr);
+
+	DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
+
+	/*
+	 * Check if addr is valid.
+	 * NVRAM length at the end of memory should have been overwritten.
+	 */
+	if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
+		DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n", __FUNCTION__, addr));
+		return BCME_ERROR;
+	}
+
+	/* Read hndrte_shared structure */
+	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
+		return rv;
+
+	/* Endianness */
+	sh->flags = ltoh32(sh->flags);
+	sh->trap_addr = ltoh32(sh->trap_addr);
+	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
+	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
+	sh->assert_line = ltoh32(sh->assert_line);
+	sh->console_addr = ltoh32(sh->console_addr);
+	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
+
+	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
+		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
+		           "is different than sdpcm_shared version %d in dongle\n",
+		           __FUNCTION__, SDPCM_SHARED_VERSION,
+		           sh->flags & SDPCM_SHARED_VERSION_MASK));
+		return BCME_ERROR;
+	}
+
+	return BCME_OK;
+}
+
+static int
+dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
+{
+	int bcmerror = 0;
+	uint msize = 512;
+	char *mbuffer = NULL;
+	uint maxstrlen = 256;
+	char *str = NULL;
+	trap_t tr;
+	sdpcm_shared_t sdpcm_shared;
+	struct bcmstrbuf strbuf;
+
+	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+	if (data == NULL) {
+		/*
+		 * Called after a rx ctrl timeout. "data" is NULL.
+		 * allocate memory to trace the trap or assert.
+		 */
+		size = msize;
+		mbuffer = data = MALLOC(bus->dhd->osh, msize);
+		if (mbuffer == NULL) {
+			DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
+			bcmerror = BCME_NOMEM;
+			goto done;
+		}
+	}
+
+	if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
+		DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
+		bcmerror = BCME_NOMEM;
+		goto done;
+	}
+
+	if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0)
+		goto done;
+
+	bcm_binit(&strbuf, data, size);
+
+	bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
+	            sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
+
+	if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
+		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
+		 * (Avoids conflict with real asserts for programmatic parsing of output.)
+		 */
+		bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
+	}
+
+	if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
+		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
+		 * (Avoids conflict with real asserts for programmatic parsing of output.)
+		 */
+		bcm_bprintf(&strbuf, "No trap%s in dongle",
+		          (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
+		          ?"/assrt" :"");
+	} else {
+		if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
+			/* Download assert */
+			bcm_bprintf(&strbuf, "Dongle assert");
+			if (sdpcm_shared.assert_exp_addr != 0) {
+				str[0] = '\0';
+				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
+				                                 sdpcm_shared.assert_exp_addr,
+				                                 (uint8 *)str, maxstrlen)) < 0)
+					goto done;
+
+				str[maxstrlen - 1] = '\0';
+				bcm_bprintf(&strbuf, " expr \"%s\"", str);
+			}
+
+			if (sdpcm_shared.assert_file_addr != 0) {
+				str[0] = '\0';
+				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
+				                                 sdpcm_shared.assert_file_addr,
+				                                 (uint8 *)str, maxstrlen)) < 0)
+					goto done;
+
+				str[maxstrlen - 1] = '\0';
+				bcm_bprintf(&strbuf, " file \"%s\"", str);
+			}
+
+			bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line);
+		}
+
+		if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
+			if ((bcmerror = dhdsdio_membytes(bus, FALSE,
+			                                 sdpcm_shared.trap_addr,
+			                                 (uint8*)&tr, sizeof(trap_t))) < 0)
+				goto done;
+
+			bcm_bprintf(&strbuf,
+			"Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
+			"lp 0x%x, rpc 0x%x Trap offset 0x%x, "
+			"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
+			tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13, tr.r14, tr.pc,
+			sdpcm_shared.trap_addr,
+			tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5, tr.r6, tr.r7);
+		}
+	}
+
+	if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
+		DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
+	}
+
+	if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
+			/* Mem dump to a file on device */
+			dhdsdio_mem_dump(bus);
+	}
+
+done:
+	if (mbuffer)
+		MFREE(bus->dhd->osh, mbuffer, msize);
+	if (str)
+		MFREE(bus->dhd->osh, str, maxstrlen);
+
+	return bcmerror;
+}
+
+static int
+dhdsdio_mem_dump(dhd_bus_t *bus)
+{
+	int ret = 0;
+	int size; /* Full mem size */
+	int start = 0; /* Start address */
+	int read_size = 0; /* Read size of each iteration */
+	uint8 *buf = NULL, *databuf = NULL;
+
+	/* Get full mem size */
+	size = bus->ramsize;
+	buf = MALLOC(bus->dhd->osh, size);
+	if (!buf) {
+		printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size);
+		return -1;
+	}
+
+	/* Read mem content */
+	printf("Dump dongle memory");
+	databuf = buf;
+	while (size)
+	{
+		read_size = MIN(MEMBLOCK, size);
+		if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size)))
+		{
+			printf("%s: Error membytes %d\n", __FUNCTION__, ret);
+			if (buf) {
+				MFREE(bus->dhd->osh, buf, size);
+			}
+			return -1;
+		}
+		printf(".");
+
+		/* Decrement size and increment start address */
+		size -= read_size;
+		start += read_size;
+		databuf += read_size;
+	}
+	printf("Done\n");
+
+#ifdef DHD_DEBUG
+	/* free buf before return !!! */
+	if (write_to_file(bus->dhd, buf, bus->ramsize))
+	{
+		printf("%s: Error writing to files\n", __FUNCTION__);
+		return -1;
+	}
+	/* buf free handled in write_to_file, not here */
+#else
+	MFREE(bus->dhd->osh, buf, size);
+#endif
+	return 0;
+}
+#endif /* DHD_DEBUG_TRAP */
+
+#ifdef DHD_DEBUG
+#define CONSOLE_LINE_MAX	192
+
+static int
+dhdsdio_readconsole(dhd_bus_t *bus)
+{
+	dhd_console_t *c = &bus->console;
+	uint8 line[CONSOLE_LINE_MAX], ch;
+	uint32 n, idx, addr;
+	int rv;
+
+	/* Don't do anything until FWREADY updates console address */
+	if (bus->console_addr == 0)
+		return 0;
+
+	/* Read console log struct */
+	addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
+	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
+		return rv;
+
+	/* Allocate console buffer (one time only) */
+	if (c->buf == NULL) {
+		c->bufsize = ltoh32(c->log.buf_size);
+		if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
+			return BCME_NOMEM;
+	}
+
+	idx = ltoh32(c->log.idx);
+
+	/* Protect against corrupt value */
+	if (idx > c->bufsize)
+		return BCME_ERROR;
+
+	/* Skip reading the console buffer if the index pointer has not moved */
+	if (idx == c->last)
+		return BCME_OK;
+
+	/* Read the console buffer */
+	addr = ltoh32(c->log.buf);
+	if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
+		return rv;
+
+	while (c->last != idx) {
+		for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+			if (c->last == idx) {
+				/* This would output a partial line.  Instead, back up
+				 * the buffer pointer and output this line next time around.
+				 */
+				if (c->last >= n)
+					c->last -= n;
+				else
+					c->last = c->bufsize - n;
+				goto break2;
+			}
+			ch = c->buf[c->last];
+			c->last = (c->last + 1) % c->bufsize;
+			if (ch == '\n')
+				break;
+			line[n] = ch;
+		}
+
+		if (n > 0) {
+			if (line[n - 1] == '\r')
+				n--;
+			line[n] = 0;
+			printf("CONSOLE: %s\n", line);
+		}
+	}
+break2:
+
+	return BCME_OK;
+}
+#endif /* DHD_DEBUG */
 
 int
 dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
@@ -3881,10 +4226,13 @@
 		DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
 		          __FUNCTION__, rxdone, framecnt));
 		bus->intdis = FALSE;
+#if defined(OOB_INTR_ONLY)
+		bcmsdh_oob_intr_set(1);
+#endif /* (OOB_INTR_ONLY) */
 		bcmsdh_intr_enable(sdh);
 	}
 
-	if (DATAOK(bus) && bus->ctrl_frame_stat) {
+	if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
 		int ret, i;
 
 		ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
@@ -3916,13 +4264,16 @@
 			}
 
 		}
+		if (ret == 0) {
+				bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+		}
+
 		printf("Return_dpc value is : %d\n", ret);
-		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 		bus->ctrl_frame_stat = FALSE;
 		dhd_wait_event_wakeup(bus->dhd);
 	}
 	/* Send queued frames (limit 1 if rx may still be pending) */
-	else if ((bus->clkstate != CLK_PENDING) && !bus->fcstate &&
+	else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
 	    pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
 		framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
 		framecnt = dhdsdio_sendfromq(bus, framecnt);
@@ -3937,7 +4288,9 @@
 		bus->dhd->busstate = DHD_BUS_DOWN;
 		bus->intstatus = 0;
 	} else if (bus->clkstate == CLK_PENDING) {
-		/* Awaiting I_CHIPACTIVE; don't resched */
+		DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting \
+			I_CHIPACTIVE interrupt", __FUNCTION__));
+			resched = TRUE;
 	} else if (bus->intstatus || bus->ipend ||
 	           (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
 			PKT_AVAILABLE()) {  /* Read multiple frames */
@@ -3961,7 +4314,6 @@
 bool
 dhd_bus_dpc(struct dhd_bus *bus)
 {
-#ifdef SDIO_ISR_THREAD
 	bool resched;
 
 	/* Call the DPC directly. */
@@ -3969,9 +4321,6 @@
 	resched = dhdsdio_dpc(bus);
 
 	return resched;
-#else
-	return dhdsdio_dpc(bus);
-#endif /* SDIO_ISR_THREAD */
 }
 
 void
@@ -3980,6 +4329,8 @@
 	dhd_bus_t *bus = (dhd_bus_t*)arg;
 	bcmsdh_info_t *sdh;
 
+	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
 	if (!bus) {
 		DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
 		return;
@@ -3990,9 +4341,6 @@
 		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
 		return;
 	}
-
-	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
 	/* Count the interrupt call */
 	bus->intrcount++;
 	bus->ipend = TRUE;
@@ -4319,6 +4667,19 @@
 		bus->lastintrs = bus->intrcount;
 	}
 
+#ifdef DHD_DEBUG
+	/* Poll for console output periodically */
+	if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
+		bus->console.count += dhd_watchdog_ms;
+		if (bus->console.count >= dhd_console_ms) {
+			bus->console.count -= dhd_console_ms;
+			/* Make sure backplane clock is on */
+			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+			if (dhdsdio_readconsole(bus) < 0)
+				dhd_console_ms = 0;	/* On error, stop trying */
+		}
+	}
+#endif /* DHD_DEBUG */
 
 #ifdef SDTEST
 	/* Generate packets if configured */
@@ -4336,7 +4697,6 @@
 			bus->idlecount = 0;
 			if (bus->activity) {
 				bus->activity = FALSE;
-			} else {
 				dhdsdio_clkctl(bus, CLK_NONE, FALSE);
 			}
 		}
@@ -4347,6 +4707,68 @@
 	return bus->ipend;
 }
 
+#ifdef DHD_DEBUG
+extern int
+dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
+{
+	dhd_bus_t *bus = dhdp->bus;
+	uint32 addr, val;
+	int rv;
+	void *pkt;
+
+	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
+	if (bus->console_addr == 0)
+		return BCME_UNSUPPORTED;
+
+	/* Exclusive bus access */
+	dhd_os_sdlock(bus->dhd);
+
+	/* Don't allow input if dongle is in reset */
+	if (bus->dhd->dongle_reset) {
+		dhd_os_sdunlock(bus->dhd);
+		return BCME_NOTREADY;
+	}
+
+	/* Request clock to allow SDIO accesses */
+	BUS_WAKE(bus);
+	/* No pend allowed since txpkt is called later, ht clk has to be on */
+	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+	/* Zero cbuf_index */
+	addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx);
+	val = htol32(0);
+	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+		goto done;
+
+	/* Write message into cbuf */
+	addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf);
+	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
+		goto done;
+
+	/* Write length into vcons_in */
+	addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in);
+	val = htol32(msglen);
+	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+		goto done;
+
+	/* Bump dongle by sending an empty event pkt.
+	 * sdpcm_sendup (RX) checks for virtual console input.
+	 */
+	if (((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL) &&
+		bus->clkstate == CLK_AVAIL)
+		dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, TRUE);
+
+done:
+	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+		bus->activity = FALSE;
+		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+	}
+
+	dhd_os_sdunlock(bus->dhd);
+
+	return rv;
+}
+#endif /* DHD_DEBUG */
 
 #ifdef DHD_DEBUG
 static void
diff --git a/bcm4329/src/dongle/dngl_stats.h b/bcm4329/src/dongle/dngl_stats.h
index c1776a8..e5db54e 100644
--- a/bcm4329/src/dongle/dngl_stats.h
+++ b/bcm4329/src/dongle/dngl_stats.h
@@ -2,7 +2,7 @@
  * Common stats definitions for clients of dongle
  * ports
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/aidmp.h b/bcm4329/src/include/aidmp.h
index 44b3de8..a927e5d 100644
--- a/bcm4329/src/include/aidmp.h
+++ b/bcm4329/src/include/aidmp.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom AMBA Interconnect definitions.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmcdc.h b/bcm4329/src/include/bcmcdc.h
index 641d755..c2a860b 100644
--- a/bcm4329/src/include/bcmcdc.h
+++ b/bcm4329/src/include/bcmcdc.h
@@ -4,7 +4,7 @@
  *
  * Definitions subject to change without notice.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmdevs.h b/bcm4329/src/include/bcmdevs.h
index acfd414..14853f1 100644
--- a/bcm4329/src/include/bcmdevs.h
+++ b/bcm4329/src/include/bcmdevs.h
@@ -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: bcmdevs.h,v 13.172.4.5.4.10.2.28 2010/01/28 06:57:23 Exp $
+ * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.36 2010/05/25 08:33:44 Exp $
  */
 
 
diff --git a/bcm4329/src/include/bcmendian.h b/bcm4329/src/include/bcmendian.h
index 38887df..ae46838 100644
--- a/bcm4329/src/include/bcmendian.h
+++ b/bcm4329/src/include/bcmendian.h
@@ -1,7 +1,7 @@
 /*
  * Byte order utilities
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmpcispi.h b/bcm4329/src/include/bcmpcispi.h
index e3be826..7d98fb7 100644
--- a/bcm4329/src/include/bcmpcispi.h
+++ b/bcm4329/src/include/bcmpcispi.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom PCI-SPI Host Controller Register Definitions
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmperf.h b/bcm4329/src/include/bcmperf.h
index dfc3f44..2a78784 100644
--- a/bcm4329/src/include/bcmperf.h
+++ b/bcm4329/src/include/bcmperf.h
@@ -1,7 +1,7 @@
 /*
  * Performance counters software interface.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdbus.h b/bcm4329/src/include/bcmsdbus.h
index 0e629c0..b7b67bc 100644
--- a/bcm4329/src/include/bcmsdbus.h
+++ b/bcm4329/src/include/bcmsdbus.h
@@ -2,7 +2,7 @@
  * Definitions for API from sdio common code (bcmsdh) to individual
  * host controller drivers.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdh.h b/bcm4329/src/include/bcmsdh.h
index f8ab8ab..f5dee5c 100644
--- a/bcm4329/src/include/bcmsdh.h
+++ b/bcm4329/src/include/bcmsdh.h
@@ -3,7 +3,7 @@
  *     export functions to client drivers
  *     abstract OS and BUS specific details of SDIO
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdh_sdmmc.h b/bcm4329/src/include/bcmsdh_sdmmc.h
index b572f34..4e6d1b5 100644
--- a/bcm4329/src/include/bcmsdh_sdmmc.h
+++ b/bcm4329/src/include/bcmsdh_sdmmc.h
@@ -1,7 +1,7 @@
 /*
  * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdpcm.h b/bcm4329/src/include/bcmsdpcm.h
index b63b1d3..77aca45 100644
--- a/bcm4329/src/include/bcmsdpcm.h
+++ b/bcm4329/src/include/bcmsdpcm.h
@@ -2,7 +2,7 @@
  * Broadcom SDIO/PCMCIA
  * Software-specific definitions shared between device and host side
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -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: bcmsdpcm.h,v 1.1.2.3 2009/04/09 18:52:06 Exp $
+ * $Id: bcmsdpcm.h,v 1.1.2.4 2010/07/02 01:15:46 Exp $
  */
 
 #ifndef	_bcmsdpcm_h_
@@ -241,7 +241,7 @@
  * Shared structure between dongle and the host
  * The structure contains pointers to trap or assert information shared with the host
  */
-#define SDPCM_SHARED_VERSION       0x0001
+#define SDPCM_SHARED_VERSION       0x0002
 #define SDPCM_SHARED_VERSION_MASK  0x00FF
 #define SDPCM_SHARED_ASSERT_BUILT  0x0100
 #define SDPCM_SHARED_ASSERT        0x0200
@@ -255,6 +255,7 @@
 	uint32  assert_line;
 	uint32	console_addr;		/* Address of hndrte_cons_t */
 	uint32  msgtrace_addr;
+	uint8   tag[32];
 } sdpcm_shared_t;
 
 extern sdpcm_shared_t sdpcm_shared;
diff --git a/bcm4329/src/include/bcmsdspi.h b/bcm4329/src/include/bcmsdspi.h
index b1e2be9..eaae10d 100644
--- a/bcm4329/src/include/bcmsdspi.h
+++ b/bcm4329/src/include/bcmsdspi.h
@@ -1,7 +1,7 @@
 /*
  * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmspi.h b/bcm4329/src/include/bcmspi.h
index 0c46538..2e2bc93 100644
--- a/bcm4329/src/include/bcmspi.h
+++ b/bcm4329/src/include/bcmspi.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom SPI Low-Level Hardware Driver API
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmutils.h b/bcm4329/src/include/bcmutils.h
index 7010838..f85ed35 100644
--- a/bcm4329/src/include/bcmutils.h
+++ b/bcm4329/src/include/bcmutils.h
@@ -20,7 +20,7 @@
  *      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.h,v 13.184.4.6.2.1.18.24 2009/12/10 20:19:19 Exp $
+ * $Id: bcmutils.h,v 13.184.4.6.2.1.18.25 2010/04/26 06:05:24 Exp $
  */
 
 
diff --git a/bcm4329/src/include/bcmwifi.h b/bcm4329/src/include/bcmwifi.h
index 52f17a6..038aedc 100644
--- a/bcm4329/src/include/bcmwifi.h
+++ b/bcm4329/src/include/bcmwifi.h
@@ -42,7 +42,7 @@
 #define CH_5MHZ_APART			1
 #define CH_MAX_2G_CHANNEL		14	
 #define WLC_MAX_2G_CHANNEL		CH_MAX_2G_CHANNEL 
-#define	MAXCHANNEL			224
+#define	MAXCHANNEL		224	
 
 #define WL_CHANSPEC_CHAN_MASK		0x00ff
 #define WL_CHANSPEC_CHAN_SHIFT		0
@@ -118,7 +118,7 @@
 				  (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 CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G((chspec))? WLC_BAND_5G: WLC_BAND_2G)
 
 #define CHANSPEC_STR_LEN    8
 
diff --git a/bcm4329/src/include/dhdioctl.h b/bcm4329/src/include/dhdioctl.h
index ee78c3d..980a143 100644
--- a/bcm4329/src/include/dhdioctl.h
+++ b/bcm4329/src/include/dhdioctl.h
@@ -5,7 +5,7 @@
  *
  * Definitions subject to change without notice.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -25,7 +25,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: dhdioctl.h,v 13.7.8.1.4.1.16.4 2009/09/05 16:50:35 Exp $
+ * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.5 2010/05/21 21:49:38 Exp $
  */
 
 #ifndef _dhdioctl_h_
@@ -79,6 +79,7 @@
 #define DHD_GLOM_VAL	0x0400
 #define DHD_EVENT_VAL	0x0800
 #define DHD_BTA_VAL	0x1000
+#define DHD_ISCAN_VAL 0x2000
 
 #ifdef SDTEST
 /* For pktgen iovar */
diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h
index 3ab7ad7..92dc326 100644
--- a/bcm4329/src/include/epivers.h
+++ b/bcm4329/src/include/epivers.h
@@ -31,18 +31,18 @@
 
 #define	EPI_MINOR_VERSION	218
 
-#define	EPI_RC_NUMBER		223
+#define	EPI_RC_NUMBER		248
 
-#define	EPI_INCREMENTAL_NUMBER	0
+#define	EPI_INCREMENTAL_NUMBER	6
 
 #define	EPI_BUILD_NUMBER	0
 
-#define	EPI_VERSION		4, 218, 223, 0
+#define	EPI_VERSION		4, 218, 248, 6
 
-#define	EPI_VERSION_NUM		0x04dadf00
+#define	EPI_VERSION_NUM		0x04daf806
 
 
-#define	EPI_VERSION_STR		"4.218.223.0"
-#define	EPI_ROUTER_VERSION_STR	"4.219.223.0"
+#define	EPI_VERSION_STR		"4.218.248.6"
+#define	EPI_ROUTER_VERSION_STR	"4.219.248.6"
 
 #endif 
diff --git a/bcm4329/src/include/hndpmu.h b/bcm4329/src/include/hndpmu.h
index afd78d7..e829b3d 100644
--- a/bcm4329/src/include/hndpmu.h
+++ b/bcm4329/src/include/hndpmu.h
@@ -1,7 +1,7 @@
 /*
  * HND SiliconBackplane PMU support.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, 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: hndpmu.h,v 13.14.4.3.4.3.8.6 2009/09/14 09:21:45 Exp $
+ * $Id: hndpmu.h,v 13.14.4.3.4.3.8.7 2010/04/09 13:20:51 Exp $
  */
 
 #ifndef _hndpmu_h_
diff --git a/bcm4329/src/include/hndrte_armtrap.h b/bcm4329/src/include/hndrte_armtrap.h
new file mode 100644
index 0000000..ca3281b
--- /dev/null
+++ b/bcm4329/src/include/hndrte_armtrap.h
@@ -0,0 +1,88 @@
+/*
+ * HNDRTE arm trap handling.
+ *
+ * Copyright (C) 1999-2010, 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: hndrte_armtrap.h,v 13.3.196.2 2010/07/15 19:06:11 Exp $
+ */
+
+#ifndef	_hndrte_armtrap_h
+#define	_hndrte_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;
+	uint32		r1;
+	uint32		r2;
+	uint32		r3;
+	uint32		r4;
+	uint32		r5;
+	uint32		r6;
+	uint32		r7;
+	uint32		r8;
+	uint32		r9;
+	uint32		r10;
+	uint32		r11;
+	uint32		r12;
+	uint32		r13;
+	uint32		r14;
+	uint32		pc;
+} trap_t;
+
+#endif	/* !_LANGUAGE_ASSEMBLY */
+
+#endif	/* _hndrte_armtrap_h */
diff --git a/bcm4329/src/include/hndrte_cons.h b/bcm4329/src/include/hndrte_cons.h
new file mode 100644
index 0000000..a424174
--- /dev/null
+++ b/bcm4329/src/include/hndrte_cons.h
@@ -0,0 +1,63 @@
+/*
+ * Console support for hndrte.
+ *
+ * Copyright (C) 1999-2010, 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: hndrte_cons.h,v 13.1.2.4 2010/07/15 19:06:11 Exp $
+ */
+
+#include <typedefs.h>
+
+#define CBUF_LEN	(128)
+
+#define LOG_BUF_LEN	1024
+
+typedef struct {
+	uint32		buf;		/* Can't be pointer on (64-bit) hosts */
+	uint		buf_size;
+	uint		idx;
+	char		*_buf_compat;	/* Redundant pointer for backward compat. */
+} hndrte_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.
+	 */
+	hndrte_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];
+} hndrte_cons_t;
diff --git a/bcm4329/src/include/hndsoc.h b/bcm4329/src/include/hndsoc.h
index dcbab43..3542417 100644
--- a/bcm4329/src/include/hndsoc.h
+++ b/bcm4329/src/include/hndsoc.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom HND chip & on-chip-interconnect-related definitions.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/linux_osl.h b/bcm4329/src/include/linux_osl.h
index 98afe9c..b059c2a 100644
--- a/bcm4329/src/include/linux_osl.h
+++ b/bcm4329/src/include/linux_osl.h
@@ -1,7 +1,7 @@
 /*
  * Linux OS Independent Layer
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, 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: linux_osl.h,v 13.131.30.5 2009/10/27 04:42:45 Exp $
+ * $Id: linux_osl.h,v 13.131.30.8 2010/04/26 05:42:18 Exp $
  */
 
 
@@ -319,5 +319,4 @@
 
 
 #define OSL_SYSUPTIME()		((uint32)jiffies * (1000 / HZ))
-
 #endif	
diff --git a/bcm4329/src/include/linuxver.h b/bcm4329/src/include/linuxver.h
index a36de95..6ed2265 100644
--- a/bcm4329/src/include/linuxver.h
+++ b/bcm4329/src/include/linuxver.h
@@ -2,7 +2,7 @@
  * Linux-specific abstractions to gain some independence from linux kernel versions.
  * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -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: linuxver.h,v 13.38.8.1.8.3 2009/06/19 04:42:45 Exp $
+ * $Id: linuxver.h,v 13.38.8.1.8.6 2010/04/29 05:00:46 Exp $
  */
 
 
@@ -32,7 +32,7 @@
 #include <linux/version.h>
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
 #include <linux/config.h>
-#else
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
 #include <linux/autoconf.h>
 #endif
 #include <linux/module.h>
@@ -66,6 +66,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
+#include <linux/semaphore.h>
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
 #undef IP_TOS
 #endif 
diff --git a/bcm4329/src/include/miniopt.h b/bcm4329/src/include/miniopt.h
index 91e6603..3667fb1 100644
--- a/bcm4329/src/include/miniopt.h
+++ b/bcm4329/src/include/miniopt.h
@@ -1,7 +1,7 @@
 /*
  * Command line options parser.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/msgtrace.h b/bcm4329/src/include/msgtrace.h
index d79a89e..1479086 100644
--- a/bcm4329/src/include/msgtrace.h
+++ b/bcm4329/src/include/msgtrace.h
@@ -1,7 +1,7 @@
 /*
  * Trace messages sent over HBUS
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/osl.h b/bcm4329/src/include/osl.h
index 02b2b21..5599e53 100644
--- a/bcm4329/src/include/osl.h
+++ b/bcm4329/src/include/osl.h
@@ -1,7 +1,7 @@
 /*
  * OS Abstraction Layer
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/packed_section_end.h b/bcm4329/src/include/packed_section_end.h
index e455d69..5b61c18 100644
--- a/bcm4329/src/include/packed_section_end.h
+++ b/bcm4329/src/include/packed_section_end.h
@@ -15,7 +15,7 @@
  * #include <packed_section_end.h>
  *
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/packed_section_start.h b/bcm4329/src/include/packed_section_start.h
index a15562e..cb93aa6 100644
--- a/bcm4329/src/include/packed_section_start.h
+++ b/bcm4329/src/include/packed_section_start.h
@@ -15,7 +15,7 @@
  * #include <packed_section_end.h>
  *
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/pcicfg.h b/bcm4329/src/include/pcicfg.h
index 61c2f4a..898962c 100644
--- a/bcm4329/src/include/pcicfg.h
+++ b/bcm4329/src/include/pcicfg.h
@@ -1,7 +1,7 @@
 /*
  * pcicfg.h: PCI configuration constants and structures.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/802.11.h b/bcm4329/src/include/proto/802.11.h
index 3ef7de2..fd26317 100644
--- a/bcm4329/src/include/proto/802.11.h
+++ b/bcm4329/src/include/proto/802.11.h
@@ -976,6 +976,7 @@
 #define DOT11_MNG_EXT_CSA_ID			60	
 #define	DOT11_MNG_HT_ADD			61	
 #define	DOT11_MNG_EXT_CHANNEL_OFFSET		62	
+#define DOT11_MNG_WAPI_ID				68	
 #define	DOT11_MNG_HT_BSS_COEXINFO_ID		72	
 #define	DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID	73	
 #define	DOT11_MNG_HT_OBSS_ID			74	
@@ -1422,6 +1423,8 @@
 #define AES_KEY_SIZE		16	
 #define AES_MIC_SIZE		8	
 
+#define SMS4_KEY_LEN		16
+#define SMS4_WPI_CBC_MAC_LEN	16
 
 
 #include <packed_section_end.h>
diff --git a/bcm4329/src/include/proto/802.11e.h b/bcm4329/src/include/proto/802.11e.h
index 0c53530..1dd6f45 100644
--- a/bcm4329/src/include/proto/802.11e.h
+++ b/bcm4329/src/include/proto/802.11e.h
@@ -1,7 +1,7 @@
 /*
  * 802.11e protocol header file
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/802.1d.h b/bcm4329/src/include/proto/802.1d.h
index efd7117..45c728b 100644
--- a/bcm4329/src/include/proto/802.1d.h
+++ b/bcm4329/src/include/proto/802.1d.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/bcmeth.h b/bcm4329/src/include/proto/bcmeth.h
index bd34a0b..fdb5a2a 100644
--- a/bcm4329/src/include/proto/bcmeth.h
+++ b/bcm4329/src/include/proto/bcmeth.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom Ethernettype  protocol definitions
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/bcmevent.h b/bcm4329/src/include/proto/bcmevent.h
index 1791478..46c04d3 100644
--- a/bcm4329/src/include/proto/bcmevent.h
+++ b/bcm4329/src/include/proto/bcmevent.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom Event  protocol definitions
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/bcmip.h b/bcm4329/src/include/proto/bcmip.h
index 9645016..9d2fd6f 100644
--- a/bcm4329/src/include/proto/bcmip.h
+++ b/bcm4329/src/include/proto/bcmip.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/ethernet.h b/bcm4329/src/include/proto/ethernet.h
index 05530d5..9ad2ea0 100644
--- a/bcm4329/src/include/proto/ethernet.h
+++ b/bcm4329/src/include/proto/ethernet.h
@@ -1,7 +1,7 @@
 /*
  * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, 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: ethernet.h,v 9.45.56.3 2009/08/15 00:51:27 Exp $
+ * $Id: ethernet.h,v 9.45.56.5 2010/02/22 22:04:36 Exp $
  */
 
 
@@ -67,6 +67,7 @@
 #define ETHER_TYPE_8021Q	0x8100		
 #define	ETHER_TYPE_BRCM		0x886c		
 #define	ETHER_TYPE_802_1X	0x888e		
+#define ETHER_TYPE_WAI		0x88b4		
 #ifdef BCMWPA2
 #define	ETHER_TYPE_802_1X_PREAUTH 0x88c7	
 #endif
diff --git a/bcm4329/src/include/proto/sdspi.h b/bcm4329/src/include/proto/sdspi.h
index 3c7bcf3..7739e68 100644
--- a/bcm4329/src/include/proto/sdspi.h
+++ b/bcm4329/src/include/proto/sdspi.h
@@ -1,7 +1,7 @@
 /*
  * SD-SPI Protocol Standard
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/vlan.h b/bcm4329/src/include/proto/vlan.h
index 2dda4d5..670bc44 100644
--- a/bcm4329/src/include/proto/vlan.h
+++ b/bcm4329/src/include/proto/vlan.h
@@ -1,7 +1,7 @@
 /*
  * 802.1Q VLAN protocol definitions
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/wpa.h b/bcm4329/src/include/proto/wpa.h
index 4c50125..f5d0cd5 100644
--- a/bcm4329/src/include/proto/wpa.h
+++ b/bcm4329/src/include/proto/wpa.h
@@ -1,7 +1,7 @@
 /*
  * Fundamental types and constants relating to WPA
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbconfig.h b/bcm4329/src/include/sbconfig.h
index edf497c..da18ccb 100644
--- a/bcm4329/src/include/sbconfig.h
+++ b/bcm4329/src/include/sbconfig.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom SiliconBackplane hardware register definitions.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbhnddma.h b/bcm4329/src/include/sbhnddma.h
index 2aeee9e..7681395 100644
--- a/bcm4329/src/include/sbhnddma.h
+++ b/bcm4329/src/include/sbhnddma.h
@@ -2,7 +2,7 @@
  * Generic Broadcom Home Networking Division (HND) DMA engine HW interface
  * This supports the following chips: BCM42xx, 44xx, 47xx .
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbpcmcia.h b/bcm4329/src/include/sbpcmcia.h
index 121b1a9..d6d8033 100644
--- a/bcm4329/src/include/sbpcmcia.h
+++ b/bcm4329/src/include/sbpcmcia.h
@@ -1,7 +1,7 @@
 /*
  * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbsdio.h b/bcm4329/src/include/sbsdio.h
index 43ed6b5..75aaf4d 100644
--- a/bcm4329/src/include/sbsdio.h
+++ b/bcm4329/src/include/sbsdio.h
@@ -4,7 +4,7 @@
  *
  * SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbsdpcmdev.h b/bcm4329/src/include/sbsdpcmdev.h
index 57e832d..7c7c7e4 100644
--- a/bcm4329/src/include/sbsdpcmdev.h
+++ b/bcm4329/src/include/sbsdpcmdev.h
@@ -1,7 +1,7 @@
 /*
  * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific device core support
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbsocram.h b/bcm4329/src/include/sbsocram.h
index 170e8f2..5ede0b6 100644
--- a/bcm4329/src/include/sbsocram.h
+++ b/bcm4329/src/include/sbsocram.h
@@ -1,7 +1,7 @@
 /*
  * BCM47XX Sonics SiliconBackplane embedded ram core
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sdio.h b/bcm4329/src/include/sdio.h
index d20d69c..280cb84 100644
--- a/bcm4329/src/include/sdio.h
+++ b/bcm4329/src/include/sdio.h
@@ -2,7 +2,7 @@
  * SDIO spec header file
  * Protocol and standard (common) device definitions
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/siutils.h b/bcm4329/src/include/siutils.h
index c55293b..cb9f140 100644
--- a/bcm4329/src/include/siutils.h
+++ b/bcm4329/src/include/siutils.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: siutils.h,v 13.197.4.2.4.3.8.14 2010/03/19 18:31:43 Exp $
+ * $Id: siutils.h,v 13.197.4.2.4.3.8.16 2010/06/23 21:36:05 Exp $
  */
 
 
diff --git a/bcm4329/src/include/trxhdr.h b/bcm4329/src/include/trxhdr.h
index b79ac35..8f5eed9 100644
--- a/bcm4329/src/include/trxhdr.h
+++ b/bcm4329/src/include/trxhdr.h
@@ -1,7 +1,7 @@
 /*
  * TRX image file header format.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/typedefs.h b/bcm4329/src/include/typedefs.h
index e4daeee..4d9dd76 100644
--- a/bcm4329/src/include/typedefs.h
+++ b/bcm4329/src/include/typedefs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/wlioctl.h b/bcm4329/src/include/wlioctl.h
index 58a2f6c..345ba34 100644
--- a/bcm4329/src/include/wlioctl.h
+++ b/bcm4329/src/include/wlioctl.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: wlioctl.h,v 1.601.4.15.2.14.2.60 2010/04/12 05:33:02 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.62 2010/08/19 01:20:12 Exp $
  */
 
 
@@ -288,6 +288,7 @@
 #define CRYPTO_ALGO_AES_OCB_MSDU	5
 #define CRYPTO_ALGO_AES_OCB_MPDU	6
 #define CRYPTO_ALGO_NALG		7
+#define CRYPTO_ALGO_SMS4		11
 
 #define WSEC_GEN_MIC_ERROR	0x0001
 #define WSEC_GEN_REPLAY		0x0002
@@ -338,6 +339,7 @@
 #define AES_ENABLED		0x0004
 #define WSEC_SWFLAG		0x0008
 #define SES_OW_ENABLED		0x0040	
+#define SMS4_ENABLED		0x0100
 
 
 #define WPA_AUTH_DISABLED	0x0000	
@@ -349,6 +351,7 @@
 #define WPA2_AUTH_PSK		0x0080	
 #define BRCM_AUTH_PSK           0x0100  
 #define BRCM_AUTH_DPT		0x0200	
+#define WPA_AUTH_WAPI		0x0400	
 
 #define WPA_AUTH_PFN_ANY	0xffffffff	
 
@@ -1314,6 +1317,8 @@
 
 #define PFN_VERSION			1
 
+#define MAX_PFN_LIST_COUNT	16
+
 
 typedef struct wl_pfn_param {
 	int32 version;			
@@ -1324,12 +1329,12 @@
 } wl_pfn_param_t;
 
 typedef struct wl_pfn {
-	wlc_ssid_t		ssid;
-	int32			bss_type;
-	int32			infra;
-	int32			auth;
-	uint32			wpa_auth;
-	int32			wsec;
+	wlc_ssid_t		ssid;			
+	int32			bss_type;		
+	int32			infra;			
+	int32			auth;			
+	uint32			wpa_auth;		
+	int32			wsec;			
 #ifdef WLPFN_AUTO_CONNECT
 	union {
 		wl_wsec_key_t	sec_key;		
diff --git a/bcm4329/src/shared/aiutils.c b/bcm4329/src/shared/aiutils.c
index 1962711..df48ac0 100644
--- a/bcm4329/src/shared/aiutils.c
+++ b/bcm4329/src/shared/aiutils.c
@@ -2,7 +2,7 @@
  * Misc utility routines for accessing chip-specific features
  * of the SiliconBackplane-based Broadcom chips.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -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: aiutils.c,v 1.6.4.7.4.5 2009/09/25 00:32:01 Exp $
+ * $Id: aiutils.c,v 1.6.4.7.4.6 2010/04/21 20:43:47 Exp $
  */
 
 #include <typedefs.h>
diff --git a/bcm4329/src/shared/bcmutils.c b/bcm4329/src/shared/bcmutils.c
index c553d8e..43c04ee 100644
--- a/bcm4329/src/shared/bcmutils.c
+++ b/bcm4329/src/shared/bcmutils.c
@@ -20,7 +20,7 @@
  *      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,v 1.210.4.5.2.4.6.17 2009/11/17 02:20:12 Exp $
+ * $Id: bcmutils.c,v 1.210.4.5.2.4.6.19 2010/04/26 06:05:25 Exp $
  */
 
 #include <typedefs.h>
diff --git a/bcm4329/src/shared/bcmwifi.c b/bcm4329/src/shared/bcmwifi.c
index 641a4fd..803acf8 100644
--- a/bcm4329/src/shared/bcmwifi.c
+++ b/bcm4329/src/shared/bcmwifi.c
@@ -3,7 +3,7 @@
  * Contents are wifi-specific, used by any kernel or app-level
  * software that might want wifi things as it grows.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/shared/hndpmu.c b/bcm4329/src/shared/hndpmu.c
index 25712ac..307347a 100644
--- a/bcm4329/src/shared/hndpmu.c
+++ b/bcm4329/src/shared/hndpmu.c
@@ -2,7 +2,7 @@
  * Misc utility routines for accessing PMU corerev specific features
  * of the SiliconBackplane-based Broadcom chips.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -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: hndpmu.c,v 1.95.2.17.4.11.2.50 2009/10/26 14:45:51 Exp $
+ * $Id: hndpmu.c,v 1.95.2.17.4.11.2.63 2010/07/21 13:55:09 Exp $
  */
 
 #include <typedefs.h>
diff --git a/bcm4329/src/shared/miniopt.c b/bcm4329/src/shared/miniopt.c
index 44199ea..6a184a7 100644
--- a/bcm4329/src/shared/miniopt.c
+++ b/bcm4329/src/shared/miniopt.c
@@ -1,7 +1,7 @@
 /*
  * Description.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/shared/sbutils.c b/bcm4329/src/shared/sbutils.c
index 567e94e..46cd510 100644
--- a/bcm4329/src/shared/sbutils.c
+++ b/bcm4329/src/shared/sbutils.c
@@ -2,7 +2,7 @@
  * Misc utility routines for accessing chip-specific features
  * of the SiliconBackplane-based Broadcom chips.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -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: sbutils.c,v 1.662.4.10.2.7.4.1 2009/09/25 00:32:01 Exp $
+ * $Id: sbutils.c,v 1.662.4.10.2.7.4.2 2010/04/19 05:48:48 Exp $
  */
 
 #include <typedefs.h>
diff --git a/bcm4329/src/shared/siutils.c b/bcm4329/src/shared/siutils.c
index 6472a78..1814db0 100644
--- a/bcm4329/src/shared/siutils.c
+++ b/bcm4329/src/shared/siutils.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: siutils.c,v 1.662.4.4.4.16.4.26 2010/02/01 05:51:56 Exp $
+ * $Id: siutils.c,v 1.662.4.4.4.16.4.28 2010/06/23 21:37:54 Exp $
  */
 
 #include <typedefs.h>
diff --git a/bcm4329/src/shared/siutils_priv.h b/bcm4329/src/shared/siutils_priv.h
index 1ec59aa..e8ad7e5 100644
--- a/bcm4329/src/shared/siutils_priv.h
+++ b/bcm4329/src/shared/siutils_priv.h
@@ -1,7 +1,7 @@
 /*
  * Include file private to the SOC Interconnect support files.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/wl/sys/wl_cfg80211.c b/bcm4329/src/wl/sys/wl_cfg80211.c
new file mode 100644
index 0000000..81491cb
--- /dev/null
+++ b/bcm4329/src/wl/sys/wl_cfg80211.c
@@ -0,0 +1,4491 @@
+/*
+ * Linux Cfg80211 support
+ *
+ * Copyright (C) 1999-2010, 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: wl_cfg80211.c,v 1.1.2.28 2010/05/04 21:43:38 Exp $
+ */
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhdioctl.h>
+#include <wlioctl.h>
+
+#include <proto/ethernet.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+
+#include <net/rtnetlink.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/firmware.h>
+#include <wl_cfg80211.h>
+
+static struct sdio_func *cfg80211_sdio_func = NULL;
+static struct wl_dev *wl_cfg80211_dev = NULL;
+
+#ifdef WL_CFG80211_BACKTRACE
+uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO | WL_DBG_DBG;
+#else
+uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
+#endif
+
+#define WL_4329_FW_FILE "brcm/fw_4329.bin"
+#define WL_4329_NVRAM_FILE "brcm/nvram_4329.txt"
+
+/*
+** cfg80211_ops api/callback list
+*/
+static int32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+	enum nl80211_iftype type, uint32 *flags, struct vif_params *params);
+static int32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+	struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid);
+static int32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+	struct cfg80211_scan_request *request);
+static int32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed);
+static int32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_ibss_params *params);
+static int32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
+static int32 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+	uint8 *mac, struct station_info *sinfo);
+static int32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+      struct net_device *dev, bool enabled, int32 timeout);
+static int32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+      struct net_device *dev, const uint8 *addr,
+      const struct cfg80211_bitrate_mask *mask);
+static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_connect_params *sme);
+static int32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+	uint16 reason_code);
+static int32 wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, int32 dbm);
+static int32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm);
+static int32 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
+	uint8 key_idx);
+static int32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr, struct key_params *params);
+static int32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr);
+static int32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr, void *cookie,
+     void (*callback)(void *cookie, struct key_params *params));
+static int32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+	struct net_device *dev, uint8 key_idx);
+static int32 wl_cfg80211_resume(struct wiphy *wiphy);
+static int32 wl_cfg80211_suspend(struct wiphy *wiphy);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+static int32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_pmksa *pmksa);
+static int32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_pmksa *pmksa);
+static int32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev);
+#endif
+/*
+** event & event Q handlers for cfg80211 interfaces
+*/
+static int32 wl_create_event_handler(struct wl_priv *wl);
+static void wl_destroy_event_handler(struct wl_priv *wl);
+static int32 wl_event_handler(void *data);
+static void wl_init_eq(struct wl_priv *wl);
+static void wl_flush_eq(struct wl_priv *wl);
+static void wl_lock_eq(struct wl_priv *wl);
+static void wl_unlock_eq(struct wl_priv *wl);
+static void wl_init_eq_lock(struct wl_priv *wl);
+static void wl_init_eloop_handler(struct wl_event_loop *el);
+static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
+static int32 wl_enq_event(struct wl_priv *wl, uint32 type, const wl_event_msg_t *msg, void *data);
+static void wl_put_event(struct wl_event_q *e);
+static void wl_wakeup_event(struct wl_priv *wl);
+static int32 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data);
+static int32 wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data);
+static int32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data);
+static int32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data);
+static int32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data);
+static int32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data);
+
+/*
+** register/deregister sdio function 
+*/
+static struct sdio_func *wl_sdio_func(void);
+static void wl_clear_sdio_func(void);
+
+/*
+** ioctl utilites 
+*/
+static int32 wl_dev_bufvar_get(struct net_device *dev, int8 *name, int8 *buf, int32 buf_len);
+static __used int32 wl_dev_bufvar_set(struct net_device *dev, int8 *name, int8 *buf, int32 len);
+static int32 wl_dev_intvar_set(struct net_device *dev, int8 *name, int32 val);
+static int32 wl_dev_intvar_get(struct net_device *dev, int8 *name, int32 *retval);
+static int32 wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg, uint32 len);
+
+
+/*
+** cfg80211 set_wiphy_params utilities 
+*/
+static int32 wl_set_frag(struct net_device *dev, uint32 frag_threshold);
+static int32 wl_set_rts(struct net_device *dev, uint32 frag_threshold);
+static int32 wl_set_retry(struct net_device *dev, uint32 retry, bool l);
+
+/*
+** wl profile utilities
+*/
+static int32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data, int32 item);
+static void * wl_read_prof(struct wl_priv *wl, int32 item);
+static void wl_init_prof(struct wl_profile *prof);
+
+
+/*
+** cfg80211 connect utilites 
+*/
+static int32 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme);
+static int32 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme);
+static int32 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme);
+static int32 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme);
+static int32 wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme);
+static int32 wl_get_assoc_ies(struct wl_priv *wl);
+
+
+/* 
+** information element utilities 
+*/
+static void wl_rst_ie(struct wl_priv *wl);
+static int32 wl_add_ie(struct wl_priv *wl, uint8 t, uint8 l, uint8 *v);
+static int32 wl_mrg_ie(struct wl_priv *wl, uint8 *ie_stream, uint16 ie_size);
+static int32 wl_cp_ie(struct wl_priv *wl, uint8 *dst, uint16 dst_size);
+static uint32 wl_get_ielen(struct wl_priv *wl);
+
+
+static int32 wl_mode_to_nl80211_iftype(int32 mode);
+
+static struct wireless_dev *wl_alloc_wdev(int32 sizeof_iface, struct device *dev);
+static void wl_free_wdev(struct wl_priv *wl);
+
+static int32 wl_inform_bss(struct wl_priv *wl);
+static int32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
+static int32 wl_update_bss_info(struct wl_priv *wl);
+
+static int32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr, struct key_params *params);
+
+
+/*
+** key indianess swap utilities 
+*/
+static void swap_key_from_BE(struct wl_wsec_key *key);
+static void swap_key_to_BE(struct wl_wsec_key *key);
+
+
+/*
+** wl_priv memory init/deinit utilities
+*/
+static int32 wl_init_priv_mem(struct wl_priv *wl);
+static void wl_deinit_priv_mem(struct wl_priv *wl);
+
+static void wl_delay(uint32 ms);
+
+/* 
+** store/restore cfg80211 instance data
+*/
+static void wl_set_drvdata(struct wl_dev *dev, void *data);
+static void *wl_get_drvdata(struct wl_dev *dev);
+
+/*
+** ibss mode utilities
+*/
+static bool wl_is_ibssmode(struct wl_priv *wl);
+static bool wl_is_ibssstarter(struct wl_priv *wl);
+
+/* 
+** dongle up/down , default configuration utilities 
+*/
+static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
+static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
+static void wl_link_up(struct wl_priv *wl);
+static void wl_link_down(struct wl_priv *wl);
+static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype);
+static int32 __wl_cfg80211_up(struct wl_priv *wl);
+static int32 __wl_cfg80211_down(struct wl_priv *wl);
+static int32 wl_dongle_probecap(struct wl_priv *wl);
+static void wl_init_conf(struct wl_conf *conf);
+
+/*
+** dongle configuration utilities
+*/
+#ifndef EMBEDDED_PLATFORM
+static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype);
+static int32 wl_dongle_country(struct net_device *ndev, uint8 ccode);
+static int32 wl_dongle_up(struct net_device *ndev, uint32 up);
+static int32 wl_dongle_power(struct net_device *ndev, uint32 power_mode);
+static int32 wl_dongle_glom(struct net_device *ndev, uint32 glom, uint32 dongle_align);
+static int32 wl_dongle_roam(struct net_device *ndev, uint32 roamvar, uint32 bcn_timeout);
+static int32 wl_dongle_eventmsg(struct net_device *ndev);
+static int32 wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time,
+	int32 scan_unassoc_time);
+static int32 wl_dongle_offload(struct net_device *ndev, int32 arpoe, int32 arp_ol);
+static int32 wl_pattern_atoh(int8 *src, int8 *dst);
+static int32 wl_dongle_filter(struct net_device *ndev, uint32 filter_mode);
+static int32 wl_update_wiphybands(struct wl_priv *wl);
+#endif /* !EMBEDDED_PLATFORM */
+static int32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
+
+/*
+** iscan handler 
+*/
+static void wl_iscan_timer(ulong data);
+static void wl_term_iscan(struct wl_priv *wl);
+static int32 wl_init_iscan(struct wl_priv *wl);
+static int32 wl_iscan_thread(void *data);
+static int32 wl_dev_iovar_setbuf(struct net_device *dev, int8 *iovar, void *param,
+	int32 paramlen, void *bufptr, int32 buflen);
+static int32 wl_dev_iovar_getbuf(struct net_device *dev, int8 *iovar, void *param,
+	int32 paramlen, void *bufptr, int32 buflen);
+static int32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, uint16 action);
+static int32 wl_do_iscan(struct wl_priv *wl);
+static int32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
+static int32 wl_invoke_iscan(struct wl_priv *wl);
+static int32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status,
+	struct wl_scan_results **bss_list);
+static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
+static void wl_init_iscan_eloop(struct wl_iscan_eloop *el);
+static int32 wl_iscan_done(struct wl_priv *wl);
+static int32 wl_iscan_pending(struct wl_priv *wl);
+static int32 wl_iscan_inprogress(struct wl_priv *wl);
+static int32 wl_iscan_aborted(struct wl_priv *wl);
+
+/*
+** fw/nvram downloading handler
+*/
+static void wl_init_fw(struct wl_fw_ctrl *fw);
+
+/*
+* find most significant bit set 
+*/
+static __used uint32 wl_find_msb(uint16 bit16);
+
+/*
+* update pmklist to dongle
+*/
+static __used int32 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
+	int32 err);
+
+
+#define WL_PRIV_GET() 										\
+	({											\
+		struct wl_iface *ci;								\
+		if (unlikely(!(wl_cfg80211_dev && (ci = wl_get_drvdata(wl_cfg80211_dev))))) {	\
+			WL_ERR(("wl_cfg80211_dev is unavailable\n"));				\
+			BUG();									\
+		} 									\
+		ci_to_wl(ci);							\
+	})
+
+#define CHECK_SYS_UP()							\
+	do {										\
+		struct wl_priv *wl = wiphy_to_wl(wiphy);	\
+		if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) {	\
+			WL_INFO(("device is not ready : status (%d)\n", (int)wl->status));	\
+			return -EIO;	\
+		}	\
+	} while (0)
+
+
+extern int dhd_wait_pend8021x(struct net_device *dev);
+
+#if (WL_DBG_LEVEL > 0)
+#define WL_DBG_ESTR_MAX	32
+static int8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
+"SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
+"DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
+"REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
+"BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
+"TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
+"EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
+"BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND", "PFN_NET_LOST",
+"RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START", "IBSS_ASSOC",
+"RADIO", "PSM_WATCHDOG",
+"PROBREQ_MSG",
+"SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED", "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
+"UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
+"IF",
+"RSSI", "PFN_SCAN_COMPLETE", "ACTION_FRAME", "ACTION_FRAME_COMPLETE",
+};
+#endif	/* WL_DBG_LEVEL */
+
+#define CHAN2G(_channel, _freq, _flags) {			\
+	.band			= IEEE80211_BAND_2GHZ,		\
+	.center_freq		= (_freq),			\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+
+#define CHAN5G(_channel, _flags) {				\
+	.band			= IEEE80211_BAND_5GHZ,		\
+	.center_freq		= 5000 + (5 * (_channel)),	\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+
+#define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
+#define RATETAB_ENT(_rateid, _flags) \
+	{                                                               \
+		.bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
+		.hw_value       = (_rateid),                            \
+		.flags          = (_flags),                             \
+	}
+
+static struct ieee80211_rate __wl_rates[] = {
+	RATETAB_ENT(WLC_RATE_1M, 0),
+	RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(WLC_RATE_6M, 0),
+	RATETAB_ENT(WLC_RATE_9M, 0),
+	RATETAB_ENT(WLC_RATE_12M, 0),
+	RATETAB_ENT(WLC_RATE_18M, 0),
+	RATETAB_ENT(WLC_RATE_24M, 0),
+	RATETAB_ENT(WLC_RATE_36M, 0),
+	RATETAB_ENT(WLC_RATE_48M, 0),
+	RATETAB_ENT(WLC_RATE_54M, 0),
+};
+
+#define wl_a_rates		(__wl_rates + 4)
+#define wl_a_rates_size	8
+#define wl_g_rates		(__wl_rates + 0)
+#define wl_g_rates_size	12
+
+static struct ieee80211_channel __wl_2ghz_channels[] = {
+	CHAN2G(1, 2412, 0),
+	CHAN2G(2, 2417, 0),
+	CHAN2G(3, 2422, 0),
+	CHAN2G(4, 2427, 0),
+	CHAN2G(5, 2432, 0),
+	CHAN2G(6, 2437, 0),
+	CHAN2G(7, 2442, 0),
+	CHAN2G(8, 2447, 0),
+	CHAN2G(9, 2452, 0),
+	CHAN2G(10, 2457, 0),
+	CHAN2G(11, 2462, 0),
+	CHAN2G(12, 2467, 0),
+	CHAN2G(13, 2472, 0),
+	CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel __wl_5ghz_a_channels[] = {
+	CHAN5G(34, 0),		CHAN5G(36, 0),
+	CHAN5G(38, 0),		CHAN5G(40, 0),
+	CHAN5G(42, 0),		CHAN5G(44, 0),
+	CHAN5G(46, 0),		CHAN5G(48, 0),
+	CHAN5G(52, 0),		CHAN5G(56, 0),
+	CHAN5G(60, 0),		CHAN5G(64, 0),
+	CHAN5G(100, 0),		CHAN5G(104, 0),
+	CHAN5G(108, 0),		CHAN5G(112, 0),
+	CHAN5G(116, 0),		CHAN5G(120, 0),
+	CHAN5G(124, 0),		CHAN5G(128, 0),
+	CHAN5G(132, 0),		CHAN5G(136, 0),
+	CHAN5G(140, 0),		CHAN5G(149, 0),
+	CHAN5G(153, 0),		CHAN5G(157, 0),
+	CHAN5G(161, 0),		CHAN5G(165, 0),
+	CHAN5G(184, 0),		CHAN5G(188, 0),
+	CHAN5G(192, 0),		CHAN5G(196, 0),
+	CHAN5G(200, 0),		CHAN5G(204, 0),
+	CHAN5G(208, 0),		CHAN5G(212, 0),
+	CHAN5G(216, 0),
+};
+
+static struct ieee80211_channel __wl_5ghz_n_channels[] = {
+	CHAN5G(32, 0),		CHAN5G(34, 0),
+	CHAN5G(36, 0),		CHAN5G(38, 0),
+	CHAN5G(40, 0),		CHAN5G(42, 0),
+	CHAN5G(44, 0),		CHAN5G(46, 0),
+	CHAN5G(48, 0),		CHAN5G(50, 0),
+	CHAN5G(52, 0),		CHAN5G(54, 0),
+	CHAN5G(56, 0),		CHAN5G(58, 0),
+	CHAN5G(60, 0),		CHAN5G(62, 0),
+	CHAN5G(64, 0),		CHAN5G(66, 0),
+	CHAN5G(68, 0),		CHAN5G(70, 0),
+	CHAN5G(72, 0),		CHAN5G(74, 0),
+	CHAN5G(76, 0),		CHAN5G(78, 0),
+	CHAN5G(80, 0),		CHAN5G(82, 0),
+	CHAN5G(84, 0),		CHAN5G(86, 0),
+	CHAN5G(88, 0),		CHAN5G(90, 0),
+	CHAN5G(92, 0),		CHAN5G(94, 0),
+	CHAN5G(96, 0),		CHAN5G(98, 0),
+	CHAN5G(100, 0),		CHAN5G(102, 0),
+	CHAN5G(104, 0),		CHAN5G(106, 0),
+	CHAN5G(108, 0),		CHAN5G(110, 0),
+	CHAN5G(112, 0),		CHAN5G(114, 0),
+	CHAN5G(116, 0),		CHAN5G(118, 0),
+	CHAN5G(120, 0),		CHAN5G(122, 0),
+	CHAN5G(124, 0),		CHAN5G(126, 0),
+	CHAN5G(128, 0),		CHAN5G(130, 0),
+	CHAN5G(132, 0),		CHAN5G(134, 0),
+	CHAN5G(136, 0),		CHAN5G(138, 0),
+	CHAN5G(140, 0),		CHAN5G(142, 0),
+	CHAN5G(144, 0),		CHAN5G(145, 0),
+	CHAN5G(146, 0),		CHAN5G(147, 0),
+	CHAN5G(148, 0),		CHAN5G(149, 0),
+	CHAN5G(150, 0),		CHAN5G(151, 0),
+	CHAN5G(152, 0),		CHAN5G(153, 0),
+	CHAN5G(154, 0),		CHAN5G(155, 0),
+	CHAN5G(156, 0),		CHAN5G(157, 0),
+	CHAN5G(158, 0),		CHAN5G(159, 0),
+	CHAN5G(160, 0),		CHAN5G(161, 0),
+	CHAN5G(162, 0),		CHAN5G(163, 0),
+	CHAN5G(164, 0),		CHAN5G(165, 0),
+	CHAN5G(166, 0),		CHAN5G(168, 0),
+	CHAN5G(170, 0),		CHAN5G(172, 0),
+	CHAN5G(174, 0),		CHAN5G(176, 0),
+	CHAN5G(178, 0),		CHAN5G(180, 0),
+	CHAN5G(182, 0),		CHAN5G(184, 0),
+	CHAN5G(186, 0),		CHAN5G(188, 0),
+	CHAN5G(190, 0),		CHAN5G(192, 0),
+	CHAN5G(194, 0),		CHAN5G(196, 0),
+	CHAN5G(198, 0),		CHAN5G(200, 0),
+	CHAN5G(202, 0),		CHAN5G(204, 0),
+	CHAN5G(206, 0),		CHAN5G(208, 0),
+	CHAN5G(210, 0),		CHAN5G(212, 0),
+	CHAN5G(214, 0),		CHAN5G(216, 0),
+	CHAN5G(218, 0),		CHAN5G(220, 0),
+	CHAN5G(222, 0),		CHAN5G(224, 0),
+	CHAN5G(226, 0),		CHAN5G(228, 0),
+};
+
+static struct ieee80211_supported_band __wl_band_2ghz = {
+	.band    	= IEEE80211_BAND_2GHZ,
+	.channels 	= __wl_2ghz_channels,
+	.n_channels = ARRAY_SIZE(__wl_2ghz_channels),
+	.bitrates 	= wl_g_rates,
+	.n_bitrates = wl_g_rates_size,
+};
+
+static struct ieee80211_supported_band __wl_band_5ghz_a = {
+	.band		= IEEE80211_BAND_5GHZ,
+	.channels 	= __wl_5ghz_a_channels,
+	.n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
+	.bitrates 	= wl_a_rates,
+	.n_bitrates = wl_a_rates_size,
+};
+
+static struct ieee80211_supported_band __wl_band_5ghz_n = {
+	.band   	= IEEE80211_BAND_5GHZ,
+	.channels	= __wl_5ghz_n_channels,
+	.n_channels	= ARRAY_SIZE(__wl_5ghz_n_channels),
+	.bitrates 	= wl_a_rates,
+	.n_bitrates = wl_a_rates_size,
+};
+
+static const uint32 __wl_cipher_suites[] = {
+	WLAN_CIPHER_SUITE_WEP40,
+	WLAN_CIPHER_SUITE_WEP104,
+	WLAN_CIPHER_SUITE_TKIP,
+	WLAN_CIPHER_SUITE_CCMP,
+	WLAN_CIPHER_SUITE_AES_CMAC,
+};
+
+static void
+swap_key_from_BE(struct wl_wsec_key *key)
+{
+	key->index = htod32(key->index);
+	key->len = htod32(key->len);
+	key->algo = htod32(key->algo);
+	key->flags = htod32(key->flags);
+	key->rxiv.hi = htod32(key->rxiv.hi);
+	key->rxiv.lo = htod16(key->rxiv.lo);
+	key->iv_initialized = htod32(key->iv_initialized);
+}
+
+static void
+swap_key_to_BE(struct wl_wsec_key *key)
+{
+	key->index = dtoh32(key->index);
+	key->len = dtoh32(key->len);
+	key->algo = dtoh32(key->algo);
+	key->flags = dtoh32(key->flags);
+	key->rxiv.hi = dtoh32(key->rxiv.hi);
+	key->rxiv.lo = dtoh16(key->rxiv.lo);
+	key->iv_initialized = dtoh32(key->iv_initialized);
+}
+
+static int32
+wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg, uint32 len)
+{
+	struct ifreq ifr;
+	struct wl_ioctl ioc;
+	mm_segment_t fs;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In : cmd (%d)\n", cmd));
+#endif
+	memset(&ioc, 0, sizeof(ioc));
+	ioc.cmd = cmd;
+	ioc.buf = arg;
+	ioc.len = len;
+	strcpy(ifr.ifr_name, dev->name);
+	ifr.ifr_data = (caddr_t) &ioc;
+
+
+	fs = get_fs();
+	set_fs(get_ds());
+	err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+	set_fs(fs);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+	enum nl80211_iftype type, uint32 *flags, struct vif_params *params)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct wireless_dev *wdev;
+	int32 infra = 0;
+	int32 ap = 0;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	switch (type) {
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_WDS:
+		WL_ERR(("type (%d) : currently we do not support this type\n", type));
+		return -EOPNOTSUPP;
+	case NL80211_IFTYPE_ADHOC:
+		wl->conf->mode = WL_MODE_IBSS;
+		break;
+	case NL80211_IFTYPE_STATION:
+		wl->conf->mode = WL_MODE_BSS;
+		infra = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	infra = htod32(infra);
+	ap = htod32(ap);
+	wdev = ndev->ieee80211_ptr;
+	wdev->iftype = type;
+	WL_DBG(("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra));
+	if (unlikely((err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra)))) ||
+		unlikely((err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap))))) {
+		WL_ERR(("Error (%d)\n", err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	/* -EINPROGRESS: Call commit handler */
+	return -EINPROGRESS;
+}
+
+static void
+wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
+{
+	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
+	params->bss_type = DOT11_BSSTYPE_ANY;
+	params->scan_type = 0;
+	params->nprobes = -1;
+	params->active_time = -1;
+	params->passive_time = -1;
+	params->home_time = -1;
+	params->channel_num = 0;
+
+	params->nprobes = htod32(params->nprobes);
+	params->active_time = htod32(params->active_time);
+	params->passive_time = htod32(params->passive_time);
+	params->home_time = htod32(params->home_time);
+	if (ssid && ssid->SSID_len)
+		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
+
+}
+
+static int32
+wl_dev_iovar_setbuf(struct net_device *dev, int8 *iovar, void *param,
+	int32 paramlen, void *bufptr, int32 buflen)
+{
+	int32 iolen;
+
+	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+	BUG_ON(unlikely(!iolen));
+
+	return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
+}
+
+static int32
+wl_dev_iovar_getbuf(struct net_device *dev, int8 *iovar, void *param,
+	int32 paramlen, void *bufptr, int32 buflen)
+{
+	int32 iolen;
+
+	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+	BUG_ON(unlikely(!iolen));
+
+	return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
+}
+
+static int32
+wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, uint16 action)
+{
+	int32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
+	struct wl_iscan_params *params;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (ssid && ssid->SSID_len)
+		params_size += sizeof(struct wlc_ssid);
+	params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
+	if (unlikely(!params))
+		return -ENOMEM;
+	memset(params, 0, params_size);
+	BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
+
+	wl_iscan_prep(&params->params, ssid);
+
+	params->version = htod32(ISCAN_REQ_VERSION);
+	params->action = htod16(action);
+	params->scan_duration = htod16(0);
+
+	/* params_size += OFFSETOF(wl_iscan_params_t, params); */
+	if (unlikely((err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+		iscan->ioctl_buf, WLC_IOCTL_SMLEN)))) {
+		if (err == -EBUSY) {
+			WL_INFO(("system busy : iscan canceled\n"));
+		} else {
+			WL_ERR(("error (%d)\n", err));
+		}
+	}
+	kfree(params);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+
+static int32
+wl_do_iscan(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+	struct wlc_ssid ssid;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	/* Broadcast scan by default */
+	memset(&ssid, 0, sizeof(ssid));
+
+	iscan->state = WL_ISCAN_STATE_SCANING;
+
+	if (wl->active_scan) {
+		int32 passive_scan = 0;
+		/* make it active scan */
+		if (unlikely((err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
+			&passive_scan, sizeof(passive_scan))))) {
+			WL_DBG(("error (%d)\n", err));
+			return err;
+		}
+	}
+	wl->iscan_kickstart = TRUE;
+	wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+	mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
+	iscan->timer_on = 1;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+
+static int32
+__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+	struct cfg80211_scan_request *request,  struct cfg80211_ssid *this_ssid)
+{
+	struct wl_priv *wl = ndev_to_wl(ndev);
+	struct cfg80211_ssid *ssids;
+	struct wl_scan_req *sr = wl_to_sr(wl);
+	uint32 n_ssids;
+	bool iscan_req;
+	bool spec_scan;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
+		WL_ERR(("Scanning already : status (%d)\n", (int)wl->status));
+		return -EAGAIN;
+	}
+	if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) {
+		WL_ERR(("Scanning being aborted : status (%d)\n", (int)wl->status));
+		return -EAGAIN;
+	}
+
+	iscan_req = FALSE;
+	spec_scan = FALSE;
+	if (request) {	/* scan bss */
+		ssids = request->ssids;
+		n_ssids = min(request->n_ssids, WL_NUM_SCAN_MAX);
+		if (wl->iscan_on && n_ssids && !ssids->ssid_len) { /* for specific scan,
+								* ssids->ssid_len has 
+								* non-zero(ssid string) length.  
+								* Otherwise this is 0.
+								* we do not iscan for
+								* specific scan request
+								*/
+			iscan_req = TRUE;
+		}
+	} else {	/* scan in ibss */
+		/* we don't do iscan in ibss */
+		ssids = this_ssid;
+		n_ssids = 1;
+	}
+	wl->scan_request = request;
+	set_bit(WL_STATUS_SCANNING, &wl->status);
+	if (iscan_req) {
+		if (likely(!(err = wl_do_iscan(wl))))
+			return err;
+		else
+			goto scan_out;
+	} else {
+		WL_DBG(("n_ssid (%d), ssid \"%s\", ssid_len (%d)\n",
+		n_ssids, ssids->ssid, ssids->ssid_len));
+		memset(&sr->ssid, 0, sizeof(sr->ssid));
+		if (n_ssids) {
+			sr->ssid.SSID_len = MIN(sizeof(sr->ssid.SSID), ssids->ssid_len);
+			if (sr->ssid.SSID_len) {
+				memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
+				sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
+				WL_DBG(("Specific scan ssid=\"%s\" len=%d\n", sr->ssid.SSID,
+				sr->ssid.SSID_len));
+				spec_scan = TRUE;
+			} else {
+				WL_DBG(("Broadcast scan\n"));
+			}
+		} else {
+			/* broadcast scan */
+			WL_DBG(("Broadcast scan\n"));
+		}
+		WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
+		if (wl->active_scan) {
+			int32 pssive_scan = 0;
+			/* make it active scan */
+			if (unlikely((err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+				&pssive_scan, sizeof(pssive_scan))))) {
+				WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
+				goto scan_out;
+			}
+		}
+		if ((err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid, sizeof(sr->ssid)))) {
+			if (err == -EBUSY) {
+				WL_INFO(("system busy : scan for \"%s\" canceled\n",
+				sr->ssid.SSID));
+			} else {
+				WL_ERR(("WLC_SCAN error (%d)\n", err));
+			}
+			goto scan_out;
+		}
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return 0;
+
+scan_out:
+	clear_bit(WL_STATUS_SCANNING, &wl->status);
+	wl->scan_request = NULL;
+	return err;
+}
+
+
+static int32
+wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+	struct cfg80211_scan_request *request)
+{
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	if (unlikely((err = __wl_cfg80211_scan(wiphy, ndev, request, NULL)))) {
+		WL_DBG(("scan error (%d)\n", err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_dev_intvar_set(struct net_device *dev, int8 *name, int32 val)
+{
+	int8 buf[WLC_IOCTL_SMLEN];
+	uint32 len;
+	int32 err = 0;
+
+	val = htod32(val);
+	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+	BUG_ON(unlikely(!len));
+
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len)))) {
+		WL_ERR(("error (%d)\n", err));
+	}
+
+	return err;
+}
+
+static int32
+wl_dev_intvar_get(struct net_device *dev, int8 *name, int32 *retval)
+{
+	union {
+		int8 buf[WLC_IOCTL_SMLEN];
+		int32 val;
+	} var;
+	uint32 len;
+	uint32 data_null;
+	int32 err = 0;
+
+	len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
+	BUG_ON(unlikely(!len));
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len)))) {
+		WL_ERR(("error (%d)\n", err));
+	}
+	*retval = dtoh32(var.val);
+
+	return err;
+}
+
+static int32
+wl_set_rts(struct net_device *dev, uint32 rts_threshold)
+{
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely((err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold)))) {
+		WL_ERR(("Error (%d)\n", err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_set_frag(struct net_device *dev, uint32 frag_threshold)
+{
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely((err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold)))) {
+		WL_ERR(("Error (%d)\n", err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_set_retry(struct net_device *dev, uint32 retry, bool l)
+{
+	int32 err = 0;
+	uint32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	retry = htod32(retry);
+	if (unlikely((err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry))))) {
+		WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct net_device *ndev = wl_to_ndev(wl);
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+		(wl->conf->rts_threshold != wiphy->rts_threshold)) {
+		wl->conf->rts_threshold = wiphy->rts_threshold;
+		if (!(err = wl_set_rts(ndev, wl->conf->rts_threshold))) {
+			return err;
+		}
+	}
+	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+		(wl->conf->frag_threshold != wiphy->frag_threshold)) {
+		wl->conf->frag_threshold = wiphy->frag_threshold;
+		if (!(err = wl_set_frag(ndev, wl->conf->frag_threshold))) {
+			return err;
+		}
+	}
+	if (changed & WIPHY_PARAM_RETRY_LONG && (wl->conf->retry_long != wiphy->retry_long)) {
+		wl->conf->retry_long = wiphy->retry_long;
+		if (!(err = wl_set_retry(ndev, wl->conf->retry_long, TRUE))) {
+			return err;
+		}
+	}
+	if (changed & WIPHY_PARAM_RETRY_SHORT && (wl->conf->retry_short != wiphy->retry_short)) {
+		wl->conf->retry_short = wiphy->retry_short;
+		if (!(err = wl_set_retry(ndev, wl->conf->retry_short, FALSE))) {
+			return err;
+		}
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_ibss_params *params)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct cfg80211_bss *bss;
+	struct ieee80211_channel *chan;
+	struct wl_join_params join_params;
+	struct cfg80211_ssid ssid;
+	int32 scan_retry = 0;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In \n"));
+#endif
+	CHECK_SYS_UP();
+	if (params->bssid) {
+		WL_ERR(("Invalid bssid\n"));
+		return -EOPNOTSUPP;
+	}
+	bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
+	if (!bss) {
+		memcpy(ssid.ssid, params->ssid, params->ssid_len);
+		ssid.ssid_len = params->ssid_len;
+		do {
+			if (unlikely(__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == -EBUSY)) {
+				wl_delay(150);
+			} else {
+				break;
+			}
+		} while (++scan_retry < WL_SCAN_RETRY_MAX);
+		rtnl_unlock();	/* to allow scan_inform to paropagate to cfg80211 plane */
+		schedule_timeout_interruptible(4 * HZ);	/* wait 4 secons till scan done.... */
+		rtnl_lock();
+		bss = cfg80211_get_ibss(wiphy, NULL,
+			params->ssid, params->ssid_len);
+	}
+	if (bss) {
+		wl->ibss_starter = FALSE;
+		WL_DBG(("Found IBSS\n"));
+	} else {
+		wl->ibss_starter = TRUE;
+	}
+	if ((chan = params->channel)) {
+		wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
+	}
+	/* 
+	** Join with specific BSSID and cached SSID
+	** If SSID is zero join based on BSSID only
+	*/
+	memset(&join_params, 0, sizeof(join_params));
+	memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, params->ssid_len);
+	join_params.ssid.SSID_len = htod32(params->ssid_len);
+	if (params->bssid)
+		memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
+	else
+		memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
+
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, sizeof(join_params))))) {
+		WL_ERR(("Error (%d)\n", err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	wl_link_down(wl);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+	struct wl_priv *wl = ndev_to_wl(dev);
+	struct wl_security *sec;
+	int32 val = 0;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+		val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+	else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+		val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+	else
+		val = WPA_AUTH_DISABLED;
+	WL_DBG(("setting wpa_auth to 0x%0x\n", val));
+	if (unlikely((err = wl_dev_intvar_set(dev, "wpa_auth", val)))) {
+		WL_ERR(("set wpa_auth failed (%d)\n", err));
+		return err;
+	}
+	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec->wpa_versions = sme->crypto.wpa_versions;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+	struct wl_priv *wl = ndev_to_wl(dev);
+	struct wl_security *sec;
+	int32 val = 0;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	switch (sme->auth_type) {
+	case NL80211_AUTHTYPE_OPEN_SYSTEM:
+		val = 0;
+		WL_DBG(("open system\n"));
+		break;
+	case NL80211_AUTHTYPE_SHARED_KEY:
+		val = 1;
+		WL_DBG(("shared key\n"));
+		break;
+	case NL80211_AUTHTYPE_AUTOMATIC:
+		val = 2;
+		WL_DBG(("automatic\n"));
+		break;
+	case NL80211_AUTHTYPE_NETWORK_EAP:
+		WL_DBG(("network eap\n"));
+	default :
+		val = 2;
+		WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
+		break;
+	}
+
+	if (unlikely((err = wl_dev_intvar_set(dev, "auth", val)))) {
+		WL_ERR(("set auth failed (%d)\n", err));
+		return err;
+	}
+	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec->auth_type = sme->auth_type;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+
+static int32
+wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+	struct wl_priv *wl = ndev_to_wl(dev);
+	struct wl_security *sec;
+	int32 pval = 0;
+	int32 gval = 0;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (sme->crypto.n_ciphers_pairwise) {
+		switch (sme->crypto.ciphers_pairwise[0]) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+			pval =	WEP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			pval = TKIP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			pval = AES_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+			pval = AES_ENABLED;
+			break;
+		default:
+			WL_ERR(("invalid cipher pairwise (%d)\n",
+			sme->crypto.ciphers_pairwise[0]));
+			return -EINVAL;
+		}
+	}
+	if (sme->crypto.cipher_group) {
+		switch (sme->crypto.cipher_group) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+			gval =	WEP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			gval = TKIP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			gval = AES_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+			gval = AES_ENABLED;
+			break;
+		default:
+			WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
+			return -EINVAL;
+		}
+	}
+
+	WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
+	if (unlikely((err = wl_dev_intvar_set(dev, "wsec", pval|gval)))) {
+		WL_ERR(("error (%d)\n", err));
+		return err;
+	}
+
+	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
+	sec->cipher_group = sme->crypto.cipher_group;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+	struct wl_priv *wl = ndev_to_wl(dev);
+	struct wl_security *sec;
+	int32 val = 0;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+
+	if (sme->crypto.n_akm_suites) {
+		if (unlikely((err = wl_dev_intvar_get(dev, "wpa_auth", &val)))) {
+			WL_ERR(("could not get wpa_auth (%d)\n", err));
+			return err;
+		}
+		if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+			switch (sme->crypto.akm_suites[0]) {
+			case WLAN_AKM_SUITE_8021X:
+				val = WPA_AUTH_UNSPECIFIED;
+				break;
+			case WLAN_AKM_SUITE_PSK:
+				val = WPA_AUTH_PSK;
+				break;
+			default :
+				WL_ERR(("invalid cipher group (%d)\n",
+				sme->crypto.cipher_group));
+				return -EINVAL;
+			}
+		} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+			switch (sme->crypto.akm_suites[0]) {
+			case WLAN_AKM_SUITE_8021X:
+				val = WPA2_AUTH_UNSPECIFIED;
+				break;
+			case WLAN_AKM_SUITE_PSK:
+				val = WPA2_AUTH_PSK;
+				break;
+			default :
+				WL_ERR(("invalid cipher group (%d)\n",
+				sme->crypto.cipher_group));
+				return -EINVAL;
+			}
+		}
+
+		WL_DBG(("setting wpa_auth to %d\n", val));
+		if (unlikely((err = wl_dev_intvar_set(dev, "wpa_auth", val)))) {
+			WL_ERR(("could not set wpa_auth (%d)\n", err));
+			return err;
+		}
+	}
+	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec->wpa_auth = sme->crypto.akm_suites[0];
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+	struct wl_priv *wl = ndev_to_wl(dev);
+	struct wl_security *sec;
+	struct wl_wsec_key key;
+	int32 val;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	WL_DBG(("key len (%d)\n", sme->key_len));
+	if (sme->key_len) {
+		sec = wl_read_prof(wl, WL_PROF_SEC);
+		WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions,
+			sec->cipher_pairwise));
+		if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) &&
+			(sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
+			WLAN_CIPHER_SUITE_WEP104))) {
+			memset(&key, 0, sizeof(key));
+			key.len = (uint32)sme->key_len;
+			key.index = (uint32)sme->key_idx;
+			if (unlikely(key.len > sizeof(key.data))) {
+				WL_ERR(("Too long key length (%u)\n", key.len));
+				return -EINVAL;
+			}
+			memcpy(key.data, sme->key, key.len);
+			key.flags = WL_PRIMARY_KEY;
+			switch (sec->cipher_pairwise) {
+			case WLAN_CIPHER_SUITE_WEP40:
+				key.algo = CRYPTO_ALGO_WEP1;
+				break;
+			case WLAN_CIPHER_SUITE_WEP104:
+				key.algo = CRYPTO_ALGO_WEP128;
+				break;
+			default :
+				WL_ERR(("Invalid algorithm (%d)\n",
+				sme->crypto.ciphers_pairwise[0]));
+				return -EINVAL;
+			}
+			/* Set the new key/index */
+			WL_DBG(("key length (%d) key index (%d) algo (%d)\n", key.len,
+				key.index, key.algo));
+			WL_DBG(("key \"%s\"\n", key.data));
+			swap_key_from_BE(&key);
+			if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) {
+				WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+				return err;
+			}
+			if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
+				WL_DBG(("set auth_type to shared key\n"));
+				val = 1;	/* shared key */
+				if (unlikely((err = wl_dev_intvar_set(dev, "auth", val)))) {
+					WL_ERR(("set auth failed (%d)\n", err));
+					return err;
+				}
+			}
+		}
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_connect_params *sme)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct ieee80211_channel *chan = sme->channel;
+	struct wlc_ssid ssid;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In \n"));
+#endif
+	CHECK_SYS_UP();
+	if (unlikely(!sme->ssid)) {
+		WL_ERR(("Invalid ssid\n"));
+		return -EOPNOTSUPP;
+	}
+	if (chan) {
+		wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
+		WL_DBG(("channel (%d), center_req (%d) \n", wl->channel, chan->center_freq));
+	}
+	WL_DBG(("ie (%p), ie_len (%d)\n", sme->ie, sme->ie_len));
+	if (unlikely((err = wl_set_wpa_version(dev, sme)))) {
+		return err;
+	}
+	if (unlikely((err = wl_set_auth_type(dev, sme)))) {
+		return err;
+	}
+	if (unlikely((err = wl_set_set_cipher(dev, sme)))) {
+		return err;
+	}
+	if (unlikely((err = wl_set_key_mgmt(dev, sme)))) {
+		return err;
+	}
+	if (unlikely((err = wl_set_set_sharedkey(dev, sme)))) {
+		return err;
+	}
+	wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
+	/* 
+	**  Join with specific BSSID and cached SSID
+	**  If SSID is zero join based on BSSID only
+	 */
+	memset(&ssid, 0, sizeof(ssid));
+	ssid.SSID_len = MIN(sizeof(ssid.SSID), sme->ssid_len);
+	memcpy(ssid.SSID, sme->ssid, ssid.SSID_len);
+	ssid.SSID_len = htod32(ssid.SSID_len);
+	wl_update_prof(wl, NULL, &ssid, WL_PROF_SSID);
+	if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+		WL_DBG(("ssid \"%s\", len (%d)\n", ssid.SSID, ssid.SSID_len));
+	}
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))) {
+		WL_ERR(("error (%d)\n", err));
+		return err;
+	}
+	set_bit(WL_STATUS_CONNECTING, &wl->status);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+	uint16 reason_code)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	scb_val_t scbval;
+	bool act = FALSE;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	WL_DBG(("Reason %d\n", reason_code));
+	CHECK_SYS_UP();
+	if (likely((act = *(bool *)wl_read_prof(wl, WL_PROF_ACT)))) {
+		scbval.val = reason_code;
+		memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
+		scbval.val = htod32(scbval.val);
+		if (unlikely((err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
+			sizeof(scb_val_t))))) {
+			WL_ERR(("error (%d)\n", err));
+			return err;
+		}
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, int32 dbm)
+{
+
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct net_device *ndev = wl_to_ndev(wl);
+	uint16 txpwrmw;
+	int32 err  = 0;
+	int32 disable = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	switch (type) {
+	case TX_POWER_AUTOMATIC:
+		break;
+	case TX_POWER_LIMITED:
+		if (dbm < 0) {
+			WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
+			return -EINVAL;
+		}
+		break;
+	case TX_POWER_FIXED:
+		if (dbm < 0) {
+			WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
+			return -EINVAL;
+		}
+			break;
+	}
+	/* Make sure radio is off or on as far as software is concerned */
+	disable = WL_RADIO_SW_DISABLE << 16;
+	disable = htod32(disable);
+	if (unlikely((err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable))))) {
+		WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
+		return err;
+	}
+
+	if (dbm > 0xffff)
+		txpwrmw = 0xffff;
+	else
+		txpwrmw = (uint16)dbm;
+	if (unlikely((err = wl_dev_intvar_set(ndev, "qtxpower",
+		(int32)(bcm_mw_to_qdbm(txpwrmw)))))) {
+		WL_ERR(("qtxpower error (%d)\n", err));
+		return err;
+	}
+	wl->conf->tx_power = dbm;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct net_device *ndev = wl_to_ndev(wl);
+	int32 txpwrdbm;
+	uint8 result;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	if (unlikely((err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm)))) {
+		WL_ERR(("error (%d)\n", err));
+		return err;
+	}
+	result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
+	*dbm = (int32)bcm_qdbm_to_mw(result);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, uint8 key_idx)
+{
+	uint32 index;
+	int32 wsec;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	WL_DBG(("key index (%d)\n", key_idx));
+	CHECK_SYS_UP();
+
+	if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
+		WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
+		return err;
+	}
+	wsec = dtoh32(wsec);
+	if (wsec & WEP_ENABLED) {
+		/* Just select a new current key */
+		index = (uint32)key_idx;
+		index = htod32(index);
+		if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY,
+			&index, sizeof(index))))) {
+			WL_ERR(("error (%d)\n", err));
+		}
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr, struct key_params *params)
+{
+	struct wl_wsec_key key;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	memset(&key, 0, sizeof(key));
+	key.index = (uint32)key_idx;
+	/* Instead of bcast for ea address for default wep keys, driver needs it to be Null */
+	if (!ETHER_ISMULTI(mac_addr))
+		memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
+	key.len = (uint32)params->key_len;
+	/* check for key index change */
+	if (key.len == 0) {
+		/* key delete */
+		swap_key_from_BE(&key);
+		if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) {
+			WL_ERR(("key delete error (%d)\n", err));
+			return err;
+		}
+	} else {
+		if (key.len > sizeof(key.data)) {
+			WL_ERR(("Invalid key length (%d)\n", key.len));
+			return -EINVAL;
+		}
+
+		WL_DBG(("Setting the key index %d\n", key.index));
+		memcpy(key.data, params->key, key.len);
+
+		if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
+			uint8 keybuf[8];
+			memcpy(keybuf, &key.data[24], sizeof(keybuf));
+			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+			memcpy(&key.data[16], keybuf, sizeof(keybuf));
+		}
+
+		/* if IW_ENCODE_EXT_RX_SEQ_VALID set */
+		if (params->seq && params->seq_len == 6) {
+			/* rx iv */
+			uint8 *ivptr;
+			ivptr = (uint8 *)params->seq;
+			key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
+				(ivptr[3] << 8) | ivptr[2];
+			key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+			key.iv_initialized = TRUE;
+		}
+
+		switch (params->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+			key.algo = CRYPTO_ALGO_WEP1;
+			WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+			break;
+		case WLAN_CIPHER_SUITE_WEP104:
+			key.algo = CRYPTO_ALGO_WEP128;
+			WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			key.algo = CRYPTO_ALGO_TKIP;
+			WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+			break;
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+			key.algo = CRYPTO_ALGO_AES_CCM;
+			WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			key.algo = CRYPTO_ALGO_AES_CCM;
+			WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
+			break;
+		default:
+			WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
+			return -EINVAL;
+		}
+		swap_key_from_BE(&key);
+
+		dhd_wait_pend8021x(dev);
+		if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) {
+			WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+			return err;
+		}
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr, struct key_params *params)
+{
+	struct wl_wsec_key key;
+	int32 val;
+	int32 wsec;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	WL_DBG(("key index (%d)\n", key_idx));
+	CHECK_SYS_UP();
+
+	if (mac_addr)
+		return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
+	memset(&key, 0, sizeof(key));
+
+	key.len = (uint32)params->key_len;
+	key.index = (uint32)key_idx;
+
+	if (unlikely(key.len > sizeof(key.data))) {
+		WL_ERR(("Too long key length (%u)\n", key.len));
+		return -EINVAL;
+	}
+	memcpy(key.data, params->key, key.len);
+
+	key.flags = WL_PRIMARY_KEY;
+	switch (params->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		key.algo = CRYPTO_ALGO_WEP1;
+		WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		key.algo = CRYPTO_ALGO_WEP128;
+		WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		key.algo = CRYPTO_ALGO_TKIP;
+		WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		key.algo = CRYPTO_ALGO_AES_CCM;
+		WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		key.algo = CRYPTO_ALGO_AES_CCM;
+		WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
+		break;
+	default:
+		WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
+		return -EINVAL;
+	}
+
+	/* Set the new key/index */
+	swap_key_from_BE(&key);
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) {
+		WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+		return err;
+	}
+
+	val = WEP_ENABLED;
+	if (unlikely((err = wl_dev_intvar_get(dev, "wsec", &wsec)))) {
+		WL_ERR(("get wsec error (%d)\n", err));
+			return err;
+	}
+	wsec  &= ~(WEP_ENABLED);
+	wsec |= val;
+	if (unlikely((err = wl_dev_intvar_set(dev, "wsec", wsec)))) {
+		WL_ERR(("set wsec error (%d)\n", err));
+		return err;
+	}
+
+	val = 1;	/* assume shared key. otherwise 0 */
+	val = htod32(val);
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))) {
+		WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr)
+{
+	struct wl_wsec_key key;
+	int32 err = 0;
+	int32 val;
+	int32 wsec;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	memset(&key, 0, sizeof(key));
+
+	key.index = (uint32)key_idx;
+	key.flags = WL_PRIMARY_KEY;
+	key.algo = CRYPTO_ALGO_OFF; 
+
+	WL_DBG(("key index (%d)\n", key_idx));
+	/* Set the new key/index */
+	swap_key_from_BE(&key);
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) {
+		if (err == -EINVAL) {
+			if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
+				/* we ignore this key index in this case */
+				WL_DBG(("invalid key index (%d)\n", key_idx));
+			}
+		} else {
+			WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+		}
+		return err;
+	}
+
+	val = 0;
+	if (unlikely((err = wl_dev_intvar_get(dev, "wsec", &wsec)))) {
+		WL_ERR(("get wsec error (%d)\n", err));
+			return err;
+	}
+	wsec  &= ~(WEP_ENABLED);
+	wsec |= val;
+	if (unlikely((err = wl_dev_intvar_set(dev, "wsec", wsec)))) {
+		WL_ERR(("set wsec error (%d)\n", err));
+		return err;
+	}
+
+	val = 0;	/* assume open key. otherwise 1 */
+	val = htod32(val);
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))) {
+		WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+     uint8 key_idx, const uint8 *mac_addr, void *cookie,
+     void (*callback)(void *cookie, struct key_params *params))
+{
+	struct key_params params;
+	struct wl_wsec_key key;
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct wl_security *sec;
+	int32 wsec;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	WL_DBG(("key index (%d)\n", key_idx));
+	CHECK_SYS_UP();
+
+	memset(&key, 0, sizeof(key));
+	key.index = key_idx;
+	swap_key_to_BE(&key);
+	memset(&params, 0, sizeof(params));
+	params.key_len = (uint8)MIN(DOT11_MAX_KEY_SIZE, key.len);
+	memcpy(params.key, key.data, params.key_len);
+
+	if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
+		WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
+		return err;
+	}
+	wsec = dtoh32(wsec);
+	switch (wsec) {
+	case WEP_ENABLED:
+		sec = wl_read_prof(wl, WL_PROF_SEC);
+		if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
+			params.cipher = WLAN_CIPHER_SUITE_WEP40;
+			WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+		} else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
+			params.cipher = WLAN_CIPHER_SUITE_WEP104;
+			WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+		}
+		break;
+	case TKIP_ENABLED:
+		params.cipher = WLAN_CIPHER_SUITE_TKIP;
+		WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+		break;
+	case AES_ENABLED:
+		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+		WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+		break;
+	default:
+		WL_ERR(("Invalid algo (0x%x)\n", wsec));
+		return -EINVAL;
+	}
+
+	callback(cookie, &params);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+     struct net_device *dev, uint8 key_idx)
+{
+	WL_INFO(("Not supported\n"));
+	CHECK_SYS_UP();
+	return -EOPNOTSUPP;
+}
+
+static int32
+wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+	uint8 *mac, struct station_info *sinfo)
+
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	scb_val_t scb_val;
+	int rssi;
+	int32 rate;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	if (unlikely(memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) {
+		WL_ERR(("Wrong Mac address\n"));
+		return -ENOENT;
+	}
+
+	/* Report the current tx rate */
+	if ((err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate)))) {
+		WL_ERR(("Could not get rate (%d)\n", err));
+	} else {
+		rate = dtoh32(rate);
+		sinfo->filled |= STATION_INFO_TX_BITRATE;
+		sinfo->txrate.legacy = rate * 5;
+		WL_DBG(("Rate %d Mbps\n", (rate/2)));
+	}
+
+	if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+		scb_val.val = 0;
+		if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) {
+			WL_ERR(("Could not get rssi (%d)\n", err));
+			return err;
+		}
+		rssi = dtoh32(scb_val.val);
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = rssi;
+		WL_DBG(("RSSI %d dBm\n", rssi));
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+       bool enabled, int32 timeout)
+{
+	int32 pm;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	pm = enabled ? PM_FAST : PM_OFF;
+	pm = htod32(pm);
+	WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))) {
+		if (err == -ENODEV) {
+			WL_DBG(("net_device is not ready yet\n"));
+		} else {
+			WL_ERR(("error (%d)\n", err));
+		}
+		return err;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static __used uint32
+wl_find_msb(uint16 bit16)
+{
+	uint32 ret = 0;
+
+	if (bit16 & 0xff00) {
+		ret += 8;
+		bit16 >>= 8;
+	}
+
+	if (bit16 & 0xf0) {
+		ret += 4;
+		bit16 >>= 4;
+	}
+
+	if (bit16 & 0xc) {
+		ret += 2;
+		bit16 >>= 2;
+	}
+
+	if (bit16 & 2)
+		ret += bit16 & 2;
+	else if (bit16)
+		ret += bit16;
+
+	return ret;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+static int32
+wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+	const uint8 *addr, const struct cfg80211_bitrate_mask *mask)
+{
+	struct wl_rateset rateset;
+	int32 rate;
+	int32 val;
+	int32 err_bg;
+	int32 err_a;
+	uint32 legacy;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	/* addr param is always NULL. ignore it */
+	/* Get current rateset */
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
+		sizeof(rateset))))) {
+		WL_ERR(("could not get current rateset (%d)\n", err));
+		return err;
+	}
+
+	rateset.count = dtoh32(rateset.count);
+
+	if (!(legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy)))
+		legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
+
+	val = wl_g_rates[legacy-1].bitrate * 100000;
+
+	if (val < rateset.count) {
+		/* Select rate by rateset index */
+		rate = rateset.rates[val] & 0x7f;
+	} else {
+		/* Specified rate in bps */
+		rate = val / 500000;
+	}
+
+	WL_DBG(("rate %d mbps\n", (rate/2)));
+
+	/*
+	*
+	*	Set rate override,
+	*	Since the is a/b/g-blind, both a/bg_rate are enforced.
+	*/
+	err_bg = wl_dev_intvar_set(dev, "bg_rate", rate);
+	err_a = wl_dev_intvar_set(dev, "a_rate", rate);
+	if (unlikely(err_bg && err_a)) {
+		WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a));
+		return (err_bg | err_a);
+	}
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+#else
+static int32
+wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+	const uint8 *addr, const struct cfg80211_bitrate_mask *mask)
+{
+	struct wl_rateset rateset;
+	int32 rate;
+	int32 val;
+	int32 err_bg;
+	int32 err_a;
+	int32 err = 0;
+	int i;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	/* addr param is always NULL. ignore it */
+	/* Get current rateset */
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
+		sizeof(rateset))))) {
+		WL_ERR(("could not get current rateset (%d)\n", err));
+		return err;
+	}
+
+	rateset.count = dtoh32(rateset.count);
+
+	if (mask->fixed || mask->maxrate) {
+		val = mask->fixed ? (mask->fixed * 1000) : (mask->maxrate * 1000);
+		if (val < rateset.count) {
+			/* Select rate by rateset index */
+			rate = rateset.rates[val] & 0x7f;
+		} else {
+			/* Specified rate in bps */
+			rate = val / 500000;
+		}
+	} else {
+		/* Select maximum rate */
+		rate = rateset.rates[rateset.count - 1] & 0x7f;
+	}
+
+	if (mask->fixed) {
+		/*
+			Set rate override,
+			Since the is a/b/g-blind, both a/bg_rate are enforced.
+		*/
+		err_bg = wl_dev_intvar_set(dev, "bg_rate", rate);
+		err_a = wl_dev_intvar_set(dev, "a_rate", rate);
+		if (unlikely(err_bg && err_a)) {
+			WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a));
+			return (err_bg | err_a);
+		}
+	} else {
+		/*
+			clear rate override
+			Since the is a/b/g-blind, both a/bg_rate are enforced.
+		*/
+		/* 0 is for clearing rate override */
+		err_bg = wl_dev_intvar_set(dev, "bg_rate", 0);
+		/* 0 is for clearing rate override */
+		err_a = wl_dev_intvar_set(dev, "a_rate", 0);
+
+		if (unlikely(err_bg && err_a)) {
+			WL_ERR(("could not set max rate (%d) (%d)\n", err_bg, err_a));
+			return (err_bg | err_a);
+		}
+
+		/* Remove rates above selected rate */
+		for (i = 0; i < rateset.count; i++)
+			if ((rateset.rates[i] & 0x7f) > rate)
+				break;
+		rateset.count = htod32(i);
+
+		/* Set current rateset */
+		if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_RATESET, &rateset,
+			sizeof(rateset))))) {
+			WL_ERR(("error (%d)\n", err));
+			return err;
+		}
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */
+
+static int32
+wl_cfg80211_resume(struct wiphy *wiphy)
+{
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	wl_invoke_iscan(wiphy_to_wl(wiphy));
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_suspend(struct wiphy *wiphy)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+
+	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+	wl_term_iscan(wl);
+	if (wl->scan_request) {
+		cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE means abort */
+		wl->scan_request = NULL;
+	}
+	clear_bit(WL_STATUS_SCANNING, &wl->status);
+	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static __used int32
+wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, int32 err)
+{
+	int8 eabuf[ETHER_ADDR_STR_LEN];
+	int i, j;
+
+	memset(eabuf, 0, ETHER_ADDR_STR_LEN);
+
+	WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
+	for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
+		WL_DBG(("PMKID[%d]: %s =\n", i,
+			bcm_ether_ntoa(&pmk_list->pmkids.pmkid[i].BSSID,
+			eabuf)));
+		for (j = 0; j < WPA2_PMKID_LEN; j++) {
+			WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
+		}
+	}
+	if (likely(!err)) {
+		err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
+			sizeof(*pmk_list));
+	}
+
+	return err;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+static int32
+wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_pmksa *pmksa)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	int8 eabuf[ETHER_ADDR_STR_LEN];
+	int32 err = 0;
+	int i;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+
+	CHECK_SYS_UP();
+	memset(eabuf, 0, ETHER_ADDR_STR_LEN);
+	for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+		if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
+			ETHER_ADDR_LEN))
+				break;
+	if (i < WL_NUM_PMKIDS_MAX) {
+		memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+		memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+		if (i == wl->pmk_list->pmkids.npmkid)
+			wl->pmk_list->pmkids.npmkid++;
+	} else {
+		err = -EINVAL;
+	}
+	WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %s =\n",
+		bcm_ether_ntoa(&wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID,
+		eabuf)));
+	for (i = 0; i < WPA2_PMKID_LEN; i++) {
+		WL_DBG(("%02x\n",
+		wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].PMKID[i]));
+	}
+
+	err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+	struct cfg80211_pmksa *pmksa)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	int8 eabuf[ETHER_ADDR_STR_LEN];
+	struct _pmkid_list pmkid;
+	int32 err = 0;
+	int i;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+
+	CHECK_SYS_UP();
+	memset(eabuf, 0, ETHER_ADDR_STR_LEN);
+	memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+	memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+
+	WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %s =\n",
+		bcm_ether_ntoa(&pmkid.pmkid[0].BSSID, eabuf)));
+	for (i = 0; i < WPA2_PMKID_LEN; i++) {
+		WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
+	}
+
+	for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+		if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
+			break;
+
+	if ((wl->pmk_list->pmkids.npmkid > 0) && (i < wl->pmk_list->pmkids.npmkid)) {
+		memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
+		for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
+			memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
+				&wl->pmk_list->pmkids.pmkid[i+1].BSSID, ETHER_ADDR_LEN);
+			memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
+				&wl->pmk_list->pmkids.pmkid[i+1].PMKID, WPA2_PMKID_LEN);
+		}
+		wl->pmk_list->pmkids.npmkid--;
+	}
+	else {
+		err = -EINVAL;
+	}
+
+	err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+
+}
+
+static int32
+wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+{
+	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	CHECK_SYS_UP();
+	memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
+	err = wl_update_pmklist(dev, wl->pmk_list, err);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */
+
+static struct cfg80211_ops wl_cfg80211_ops = {
+	.change_virtual_intf = wl_cfg80211_change_iface,
+	.scan = wl_cfg80211_scan,
+	.set_wiphy_params = wl_cfg80211_set_wiphy_params,
+	.join_ibss = wl_cfg80211_join_ibss,
+	.leave_ibss = wl_cfg80211_leave_ibss,
+	.get_station = wl_cfg80211_get_station,
+	.set_tx_power = wl_cfg80211_set_tx_power,
+	.get_tx_power = wl_cfg80211_get_tx_power,
+	.add_key = wl_cfg80211_add_key,
+	.del_key = wl_cfg80211_del_key,
+	.get_key = wl_cfg80211_get_key,
+	.set_default_key = wl_cfg80211_config_default_key,
+	.set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
+	.set_power_mgmt = wl_cfg80211_set_power_mgmt,
+	.set_bitrate_mask = wl_cfg80211_set_bitrate_mask,
+	.connect = wl_cfg80211_connect,
+	.disconnect = wl_cfg80211_disconnect,
+	.suspend = wl_cfg80211_suspend,
+	.resume = wl_cfg80211_resume,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+	.set_pmksa = wl_cfg80211_set_pmksa,
+	.del_pmksa = wl_cfg80211_del_pmksa,
+	.flush_pmksa = wl_cfg80211_flush_pmksa
+#endif
+};
+
+static int32
+wl_mode_to_nl80211_iftype(int32 mode)
+{
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	switch (mode) {
+	case WL_MODE_BSS:
+		return NL80211_IFTYPE_STATION;
+	case WL_MODE_IBSS:
+		return NL80211_IFTYPE_ADHOC;
+	default:
+		return NL80211_IFTYPE_UNSPECIFIED;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static struct wireless_dev *
+wl_alloc_wdev(int32 sizeof_iface, struct device *dev)
+{
+	struct wireless_dev *wdev;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+	if (unlikely(!wdev)) {
+		WL_ERR(("Could not allocate wireless device\n"));
+		return ERR_PTR(-ENOMEM);
+	}
+	wdev->wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv) + sizeof_iface);
+	if (unlikely(!wdev->wiphy)) {
+		WL_ERR(("Couldn not allocate wiphy device\n"));
+		err = -ENOMEM;
+		goto wiphy_new_out;
+	}
+	set_wiphy_dev(wdev->wiphy, dev);
+	wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+	wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+#endif
+	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)| BIT(NL80211_IFTYPE_ADHOC);
+	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
+	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;	/* Set it as 11a by default.
+								** This will be updated with 
+								** 11n phy tables in "ifconfig up"
+								** if phy has 11n capability
+								*/
+	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+	wdev->wiphy->cipher_suites = __wl_cipher_suites;
+	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+#ifndef WL_POWERSAVE_DISABLED
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+	wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power 
+							* save mode by default 
+							*/
+#else
+	wdev->wiphy->ps_default = TRUE;	/* enable power save mode by default */
+#endif
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+	wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+#else
+	wdev->wiphy->ps_default = FALSE;
+#endif
+#endif /* !WL_POWERSAVE_DISABLED */
+	if (unlikely(((err = wiphy_register(wdev->wiphy)) < 0))) {
+		WL_ERR(("Couldn not register wiphy device (%d)\n", err));
+		goto wiphy_register_out;
+	}
+	return wdev;
+
+wiphy_register_out:
+	wiphy_free(wdev->wiphy);
+
+wiphy_new_out:
+	kfree(wdev);
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return ERR_PTR(err);
+}
+
+static void
+wl_free_wdev(struct wl_priv *wl)
+{
+	struct wireless_dev *wdev = wl_to_wdev(wl);
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely(!wdev)) {
+		WL_ERR(("wdev is invalid\n"));
+		return;
+	}
+	wiphy_unregister(wdev->wiphy);
+	wiphy_free(wdev->wiphy);
+	kfree(wdev);
+	wl_to_wdev(wl) = NULL;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+}
+
+static int32
+wl_inform_bss(struct wl_priv *wl)
+{
+	struct wl_scan_results *bss_list;
+	struct wl_bss_info *bi = NULL;	/* must be initialized */
+	int32 err = 0;
+	int i;
+
+
+	bss_list = wl->bss_list;
+	if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) {
+			WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n", bss_list->version));
+			return -EOPNOTSUPP;
+	}
+	WL_DBG(("scanned AP count (%d)\n", bss_list->count));
+	bi = next_bss(bss_list, bi);
+	for_each_bss(bss_list, bi, i) {
+		if (unlikely(err = wl_inform_single_bss(wl, bi)))
+			break;
+	}
+	return err;
+}
+
+static int32
+wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
+{
+	struct wiphy *wiphy = wl_to_wiphy(wl);
+	struct ieee80211_mgmt *mgmt;
+	struct ieee80211_channel *channel;
+	struct ieee80211_supported_band *band;
+	struct wl_cfg80211_bss_info *notif_bss_info;
+	struct wl_scan_req *sr = wl_to_sr(wl);
+	uint32 signal;
+	uint32 freq;
+	int32 err = 0;
+
+	if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
+		WL_DBG(("Beacon size is larger than allocated buffer. Discard it!!\n"));
+		return err;
+	}
+	notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(uint8) +
+		WL_BSS_INFO_MAX, GFP_KERNEL);
+	if (unlikely(!notif_bss_info)) {
+		WL_ERR(("notif_bss_info alloc failed\n"));
+		return -ENOMEM;
+	}
+	mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
+	notif_bss_info->channel = CHSPEC_CHANNEL(bi->chanspec);
+	if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
+		band = wiphy->bands[IEEE80211_BAND_2GHZ];
+	else
+		band = wiphy->bands[IEEE80211_BAND_5GHZ];
+	notif_bss_info->rssi = bi->RSSI;
+	memcpy(mgmt->bssid, &bi->BSSID,  ETHER_ADDR_LEN);
+	if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
+		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+			IEEE80211_STYPE_PROBE_RESP);
+	}
+	mgmt->u.probe_resp.timestamp = 0;
+	mgmt->u.probe_resp.beacon_int = cpu_to_le16(bi->beacon_period);
+	mgmt->u.probe_resp.capab_info = cpu_to_le16(bi->capability);
+	wl_rst_ie(wl);
+	wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
+	wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count, bi->rateset.rates);
+	wl_mrg_ie(wl, ((uint8 *)bi) + bi->ie_offset, bi->ie_length);
+	wl_cp_ie(wl, mgmt->u.probe_resp.variable, WL_BSS_INFO_MAX -
+		offsetof(struct wl_cfg80211_bss_info, frame_buf));
+	notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.probe_resp.variable) +
+		wl_get_ielen(wl);
+	freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+	channel = ieee80211_get_channel(wiphy, freq);
+
+	WL_DBG(("SSID : \"%s\", rssi (%d), capability : 0x04%x\n", bi->SSID, notif_bss_info->rssi,
+		mgmt->u.probe_resp.capab_info));
+
+	signal = notif_bss_info->rssi * 100;
+	if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
+		le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL))) {
+		WL_ERR(("cfg80211_inform_bss_frame error\n"));
+		kfree(notif_bss_info);
+		return -EINVAL;
+	}
+	kfree(notif_bss_info);
+
+	return err;
+}
+
+static bool
+wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
+{
+	uint32 event = ntoh32(e->event_type);
+	uint16 flags =	ntoh16(e->flags);
+
+	if (event == WLC_E_JOIN || event == WLC_E_ASSOC_IND || event == WLC_E_REASSOC_IND) {
+		return TRUE;
+	} else if (event == WLC_E_LINK) {
+		if (flags & WLC_EVENT_MSG_LINK) {
+			if (wl_is_ibssmode(wl)) {
+				if (wl_is_ibssstarter(wl)) {
+				}
+			} else {
+
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+static bool
+wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
+{
+	uint32 event = ntoh32(e->event_type);
+	uint16 flags =	ntoh16(e->flags);
+
+	if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
+		return TRUE;
+	} else if (event == WLC_E_LINK) {
+		if (!(flags & WLC_EVENT_MSG_LINK)) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static int32
+wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data)
+{
+	bool act;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (wl_is_linkup(wl, e)) {
+		wl_link_up(wl);
+		if (wl_is_ibssmode(wl)) {
+			cfg80211_ibss_joined(ndev, (int8 *)&e->addr, GFP_KERNEL);
+			WL_DBG(("joined in IBSS network\n"));
+		} else {
+			wl_bss_connect_done(wl, ndev, e, data);
+			WL_DBG(("joined in BSS network \"%s\"\n",
+			((struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID))->SSID));
+		}
+		act = TRUE;
+		wl_update_prof(wl, e, &act, WL_PROF_ACT);
+	} else if (wl_is_linkdown(wl, e)) {
+		cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
+		clear_bit(WL_STATUS_CONNECTED, &wl->status);
+		wl_link_down(wl);
+		wl_init_prof(wl->profile);
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data)
+{
+	bool act;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl_bss_roaming_done(wl, ndev, e, data);
+	act = TRUE;
+	wl_update_prof(wl, e, &act, WL_PROF_ACT);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static __used int32
+wl_dev_bufvar_set(struct net_device *dev, int8 *name, int8 *buf, int32 len)
+{
+	struct wl_priv *wl = ndev_to_wl(dev);
+	uint32 buflen;
+
+	buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+	BUG_ON(unlikely(!buflen));
+
+	return (wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen));
+}
+
+static int32
+wl_dev_bufvar_get(struct net_device *dev, int8 *name, int8 *buf, int32 buf_len)
+{
+	struct wl_priv *wl = ndev_to_wl(dev);
+	uint32 len;
+	int32 err = 0;
+
+	len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+	BUG_ON(unlikely(!len));
+	if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
+		WL_IOCTL_LEN_MAX)))) {
+		WL_ERR(("error (%d)\n", err));
+		return err;
+	}
+	memcpy(buf, wl->ioctl_buf, buf_len);
+
+	return err;
+}
+
+static int32
+wl_get_assoc_ies(struct wl_priv *wl)
+{
+	struct net_device *ndev = wl_to_ndev(wl);
+	struct wl_assoc_ielen *assoc_info;
+	struct wl_connect_info *conn_info = wl_to_conn(wl);
+	uint32 req_len;
+	uint32 resp_len;
+	int32 err = 0;
+
+	if (unlikely(err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf,
+		WL_ASSOC_INFO_MAX))) {
+		WL_ERR(("could not get assoc info (%d)\n", err));
+		return err;
+	}
+	assoc_info = (struct wl_assoc_ielen *)wl->extra_buf;
+	req_len = assoc_info->req_len;
+	resp_len = assoc_info->resp_len;
+	if (req_len) {
+		if (unlikely(err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf,
+			WL_ASSOC_INFO_MAX))) {
+			WL_ERR(("could not get assoc req (%d)\n", err));
+			return err;
+		}
+		conn_info->req_ie_len = req_len;
+		conn_info->req_ie = kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
+	} else {
+		conn_info->req_ie_len = 0;
+		conn_info->req_ie = NULL;
+	}
+	if (resp_len) {
+		if (unlikely(err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf,
+			WL_ASSOC_INFO_MAX))) {
+			WL_ERR(("could not get assoc resp (%d)\n", err));
+			return err;
+		}
+		conn_info->resp_ie_len = resp_len;
+		conn_info->resp_ie = kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
+	} else {
+		conn_info->resp_ie_len = 0;
+		conn_info->resp_ie = NULL;
+	}
+	WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len, conn_info->resp_ie_len));
+
+	return err;
+}
+
+static int32
+wl_update_bss_info(struct wl_priv *wl)
+{
+	struct cfg80211_bss *bss;
+	struct wl_bss_info *bi;
+	struct wlc_ssid *ssid;
+	int32 err = 0;
+
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (wl_is_ibssmode(wl))
+		return err;
+
+	ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID);
+	bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (int8 *)&wl->bssid, ssid->SSID,
+		ssid->SSID_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+
+	rtnl_lock();
+	if (unlikely(!bss)) {
+		WL_DBG(("Could not find the AP\n"));
+		*(uint32*)wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+		if (unlikely(err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO, wl->extra_buf,
+			WL_EXTRA_BUF_MAX))) {
+			WL_ERR(("Could not get bss info %d\n", err));
+			goto update_bss_info_out;
+		}
+		bi = (struct wl_bss_info *)(wl->extra_buf + 4);
+		if (unlikely(memcmp(&bi->BSSID, &wl->bssid, ETHER_ADDR_LEN))) {
+			err = -EIO;
+			goto update_bss_info_out;
+		}
+		if (unlikely((err = wl_inform_single_bss(wl, bi))))
+			goto update_bss_info_out;
+	} else {
+		WL_DBG(("Found the AP in the list - BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+			bss->bssid[0], bss->bssid[1], bss->bssid[2], bss->bssid[3],
+			bss->bssid[4], bss->bssid[5]));
+		cfg80211_put_bss(bss);
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+update_bss_info_out:
+	rtnl_unlock();
+	return err;
+}
+
+static int32
+wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data)
+{
+	struct wl_connect_info *conn_info = wl_to_conn(wl);
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl_get_assoc_ies(wl);
+	memcpy(&wl->bssid, &e->addr,  ETHER_ADDR_LEN);
+	wl_update_bss_info(wl);
+	cfg80211_roamed(ndev,
+		(uint8 *)&wl->bssid,
+		conn_info->req_ie, conn_info->req_ie_len,
+		conn_info->resp_ie, conn_info->resp_ie_len,
+		GFP_KERNEL);
+		WL_DBG(("Report roaming result\n"));
+
+	set_bit(WL_STATUS_CONNECTED, &wl->status);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data)
+{
+	struct wl_connect_info *conn_info = wl_to_conn(wl);
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl_get_assoc_ies(wl);
+	memcpy(&wl->bssid, &e->addr,  ETHER_ADDR_LEN);
+	wl_update_bss_info(wl);
+	if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
+		cfg80211_connect_result(ndev,
+			(uint8 *)&wl->bssid,
+			conn_info->req_ie, conn_info->req_ie_len,
+			conn_info->resp_ie, conn_info->resp_ie_len,
+			WLAN_STATUS_SUCCESS,
+			GFP_KERNEL);
+		WL_DBG(("Report connect result\n"));
+	} else {
+		cfg80211_roamed(ndev,
+			(uint8 *)&wl->bssid,
+			conn_info->req_ie, conn_info->req_ie_len,
+			conn_info->resp_ie, conn_info->resp_ie_len,
+			GFP_KERNEL);
+		 WL_DBG(("Report roaming result\n"));
+	}
+	set_bit(WL_STATUS_CONNECTED, &wl->status);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data)
+{
+	uint16 flags =	ntoh16(e->flags);
+	enum nl80211_key_type key_type;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+
+	rtnl_lock();
+	if (flags & WLC_EVENT_MSG_GROUP)
+		key_type = NL80211_KEYTYPE_GROUP;
+	else
+		key_type = NL80211_KEYTYPE_PAIRWISE;
+
+	cfg80211_michael_mic_failure(ndev, (uint8 *)&e->addr, key_type, -1, NULL, GFP_KERNEL);
+	rtnl_unlock();
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return 0;
+}
+
+static int32
+wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
+	const wl_event_msg_t *e, void* data)
+{
+	struct channel_info channel_inform;
+	struct wl_scan_results *bss_list;
+	uint32 len = WL_SCAN_BUF_MAX;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+
+	if (wl->iscan_on && wl->iscan_kickstart)
+		return wl_wakeup_iscan(wl_to_iscan(wl));
+
+	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
+		WL_ERR(("Scan complete while device not scanning\n"));
+		return -EINVAL;
+	}
+	if (unlikely(!wl->scan_request)) {
+	}
+	rtnl_lock();
+	if (unlikely((err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
+		sizeof(channel_inform))))) {
+		WL_ERR(("scan busy (%d)\n", err));
+		goto scan_done_out;
+	}
+	channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
+	if (unlikely(channel_inform.scan_channel)) {
+
+		WL_DBG(("channel_inform.scan_channel (%d)\n", channel_inform.scan_channel));
+	}
+	wl->bss_list = wl->scan_results;
+	bss_list = wl->bss_list;
+	memset(bss_list, 0, len);
+	bss_list->buflen = htod32(len);
+	if (unlikely((err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len)))) {
+		WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
+		err = -EINVAL;
+		goto scan_done_out;
+	}
+	bss_list->buflen = dtoh32(bss_list->buflen);
+	bss_list->version = dtoh32(bss_list->version);
+	bss_list->count = dtoh32(bss_list->count);
+
+	if ((err = wl_inform_bss(wl))) {
+		goto scan_done_out;
+	}
+
+scan_done_out :
+	if (wl->scan_request) {
+		cfg80211_scan_done(wl->scan_request, FALSE);
+		wl->scan_request = NULL;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	rtnl_unlock();
+	return err;
+}
+
+static void
+wl_init_conf(struct wl_conf *conf)
+{
+	conf->mode = (uint32)-1;
+	conf->frag_threshold = (uint32)-1;
+	conf->rts_threshold = (uint32)-1;
+	conf->retry_short = (uint32)-1;
+	conf->retry_long = (uint32)-1;
+	conf->tx_power = -1;
+}
+
+static void
+wl_init_prof(struct wl_profile *prof)
+{
+	memset(prof, 0, sizeof(*prof));
+}
+
+static void
+wl_init_eloop_handler(struct wl_event_loop *el)
+{
+	memset(el, 0, sizeof(*el));
+	el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
+	el->handler[WLC_E_JOIN] = wl_notify_connect_status;
+	el->handler[WLC_E_LINK] = wl_notify_connect_status;
+	el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
+	el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
+	el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
+	el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
+	el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
+	el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
+}
+
+static int32
+wl_init_priv_mem(struct wl_priv *wl)
+{
+	wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
+	if (unlikely(!wl->scan_results)) {
+		WL_ERR(("Scan results alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
+	if (unlikely(!wl->conf)) {
+		WL_ERR(("wl_conf alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL);
+	if (unlikely(!wl->profile)) {
+		WL_ERR(("wl_profile alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->bss_info = (void *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+	if (unlikely(!wl->bss_info)) {
+		WL_ERR(("Bss information alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->scan_req_int = (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
+	if (unlikely(!wl->scan_req_int)) {
+		WL_ERR(("Scan req alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
+	if (unlikely(!wl->ioctl_buf)) {
+		WL_ERR(("Ioctl buf alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+	if (unlikely(!wl->extra_buf)) {
+		WL_ERR(("Extra buf alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
+	if (unlikely(!wl->iscan)) {
+		WL_ERR(("Iscan buf alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->fw = (void *)kzalloc(sizeof(*wl->fw), GFP_KERNEL);
+	if (unlikely(!wl->fw)) {
+		WL_ERR(("fw object alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+	wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
+	if (unlikely(!wl->pmk_list)) {
+		WL_ERR(("pmk list alloc failed\n"));
+		goto init_priv_mem_out;
+	}
+
+	return 0;
+
+init_priv_mem_out:
+	wl_deinit_priv_mem(wl);
+
+	return -ENOMEM;
+}
+
+static void
+wl_deinit_priv_mem(struct wl_priv *wl)
+{
+	if (wl->scan_results) {
+		kfree(wl->scan_results);
+		wl->scan_results = NULL;
+	}
+	if (wl->bss_info) {
+		kfree(wl->bss_info);
+		wl->bss_info = NULL;
+	}
+	if (wl->conf) {
+		kfree(wl->conf);
+		wl->conf = NULL;
+	}
+	if (wl->profile) {
+		kfree(wl->profile);
+		wl->profile = NULL;
+	}
+	if (wl->scan_req_int) {
+		kfree(wl->scan_req_int);
+		wl->scan_req_int = NULL;
+	}
+	if (wl->ioctl_buf) {
+		kfree(wl->ioctl_buf);
+		wl->ioctl_buf = NULL;
+	}
+	if (wl->extra_buf) {
+		kfree(wl->extra_buf);
+		wl->extra_buf = NULL;
+	}
+	if (wl->iscan) {
+		kfree(wl->iscan);
+		wl->iscan = NULL;
+	}
+	if (wl->fw) {
+		kfree(wl->fw);
+		wl->fw = NULL;
+	}
+	if (wl->pmk_list) {
+		kfree(wl->pmk_list);
+		wl->pmk_list = NULL;
+	}
+}
+
+
+static int32
+wl_create_event_handler(struct wl_priv *wl)
+{
+	sema_init(&wl->event_sync, 0);
+	init_completion(&wl->event_exit);
+	if (unlikely(((wl->event_pid = kernel_thread(wl_event_handler, wl, 0)) < 0))) {
+		WL_ERR(("failed to create event thread\n"));
+		return -ENOMEM;
+	}
+	WL_DBG(("pid %d\n", wl->event_pid));
+	return 0;
+}
+
+static void
+wl_destroy_event_handler(struct wl_priv *wl)
+{
+	if (wl->event_pid >= 0) {
+		KILL_PROC(wl->event_pid, SIGTERM);
+		wait_for_completion(&wl->event_exit);
+	}
+}
+
+static void
+wl_term_iscan(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+
+	if (wl->iscan_on && iscan->pid >= 0) {
+		iscan->state = WL_ISCAN_STATE_IDLE;
+		KILL_PROC(iscan->pid, SIGTERM);
+		wait_for_completion(&iscan->exited);
+		iscan->pid = -1;
+	}
+}
+
+static void
+wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
+{
+	struct wl_priv *wl = iscan_to_wl(iscan);
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
+		WL_ERR(("Scan complete while device not scanning\n"));
+		return;
+	}
+	if (likely(wl->scan_request)) {
+		cfg80211_scan_done(wl->scan_request, aborted);
+		wl->scan_request = NULL;
+	}
+	wl->iscan_kickstart = FALSE;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+}
+
+static int32
+wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
+{
+	if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
+		WL_DBG(("wake up iscan\n"));
+		up(&iscan->sync);
+		return 0;
+	}
+
+	return -EIO;
+}
+
+static int32
+wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status, struct wl_scan_results **bss_list)
+{
+	struct wl_iscan_results list;
+	struct wl_scan_results *results;
+	struct wl_iscan_results *list_buf;
+	int32 err = 0;
+
+	memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
+	list_buf = (struct wl_iscan_results *)iscan->scan_buf;
+	results = &list_buf->results;
+	results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+	results->version = 0;
+	results->count = 0;
+
+	memset(&list, 0, sizeof(list));
+	list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
+	if (unlikely((err = wl_dev_iovar_getbuf(
+		iscan->dev,
+		"iscanresults",
+		&list,
+		WL_ISCAN_RESULTS_FIXED_SIZE,
+		iscan->scan_buf,
+		WL_ISCAN_BUF_MAX)))) {
+		WL_ERR(("error (%d)\n", err));
+		return err;
+	}
+	results->buflen = dtoh32(results->buflen);
+	results->version = dtoh32(results->version);
+	results->count = dtoh32(results->count);
+	WL_DBG(("results->count = %d\n", results->count));
+	WL_DBG(("results->buflen = %d\n", results->buflen));
+	*status = dtoh32(list_buf->status);
+	*bss_list = results;
+
+	return err;
+}
+
+static int32
+wl_iscan_done(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl->iscan;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	iscan->state = WL_ISCAN_STATE_IDLE;
+	rtnl_lock();
+	wl_inform_bss(wl);
+	wl_notify_iscan_complete(iscan, FALSE);
+	rtnl_unlock();
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_iscan_pending(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl->iscan;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	/* Reschedule the timer */
+	mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
+	iscan->timer_on = 1;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_iscan_inprogress(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl->iscan;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	rtnl_lock();
+	wl_inform_bss(wl);
+	wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
+	rtnl_unlock();
+	/* Reschedule the timer */
+	mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
+	iscan->timer_on = 1;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_iscan_aborted(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl->iscan;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	iscan->state = WL_ISCAN_STATE_IDLE;
+	rtnl_lock();
+	wl_notify_iscan_complete(iscan, TRUE);
+	rtnl_unlock();
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_iscan_thread(void *data)
+{
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+	struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
+	struct wl_priv *wl = iscan_to_wl(iscan);
+	struct wl_iscan_eloop *el = &iscan->el;
+	uint32 status;
+	int err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	sched_setscheduler(current, SCHED_FIFO, &param);
+	status = WL_SCAN_RESULTS_PARTIAL;
+	while (likely(!down_interruptible(&iscan->sync))) {
+		if (iscan->timer_on) {
+			del_timer_sync(&iscan->timer);
+			iscan->timer_on = 0;
+		}
+		rtnl_lock();
+		if (unlikely((err = wl_get_iscan_results(iscan, &status, &wl->bss_list)))) {
+			status = WL_SCAN_RESULTS_ABORTED;
+			WL_ERR(("Abort iscan\n"));
+		}
+		rtnl_unlock();
+		el->handler[status](wl);
+	}
+	if (iscan->timer_on) {
+		del_timer_sync(&iscan->timer);
+		iscan->timer_on = 0;
+	}
+	complete_and_exit(&iscan->exited, 0);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return 0;
+}
+
+static void
+wl_iscan_timer(ulong data)
+{
+	struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
+
+	if (iscan) {
+		iscan->timer_on = 0;
+		WL_DBG(("timer expired\n"));
+		wl_wakeup_iscan(iscan);
+	}
+}
+
+static int32
+wl_invoke_iscan(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+	int err = 0;
+
+	if (wl->iscan_on && iscan->pid < 0) {
+		iscan->state = WL_ISCAN_STATE_IDLE;
+		sema_init(&iscan->sync, 0);
+		init_completion(&iscan->exited);
+		iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
+		if (unlikely(iscan->pid < 0)) {
+			WL_ERR(("Could not create iscan thread\n"));
+			return -ENOMEM;
+		}
+	}
+
+	return err;
+}
+
+static void
+wl_init_iscan_eloop(struct wl_iscan_eloop *el)
+{
+	memset(el, 0, sizeof(*el));
+	el->handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
+	el->handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
+	el->handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
+	el->handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
+	el->handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
+}
+
+static int32
+wl_init_iscan(struct wl_priv *wl)
+{
+	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+	int err = 0;
+
+	if (wl->iscan_on) {
+		iscan->dev = wl_to_ndev(wl);
+		iscan->state = WL_ISCAN_STATE_IDLE;
+		wl_init_iscan_eloop(&iscan->el);
+		iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
+		init_timer(&iscan->timer);
+		iscan->timer.data = (ulong)iscan;
+		iscan->timer.function = wl_iscan_timer;
+		sema_init(&iscan->sync, 0);
+		init_completion(&iscan->exited);
+		iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
+		if (unlikely(iscan->pid < 0)) {
+			WL_ERR(("Could not create iscan thread\n"));
+			return -ENOMEM;
+		}
+		iscan->data = wl;
+	}
+
+	return err;
+}
+
+static void
+wl_init_fw(struct wl_fw_ctrl *fw)
+{
+	fw->status = 0;	/* init fw loading status. 0 means nothing was loaded yet */
+}
+
+static int32
+wl_init_priv(struct wl_priv *wl)
+{
+	struct wiphy *wiphy = wl_to_wiphy(wl);
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl->scan_request = NULL;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+	defined(CHROMIUMOS_COMPAT_WIRELESS)
+	wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
+#else
+	wl->pwr_save = wiphy->ps_default;
+#endif
+#ifndef WL_ISCAN_DISABLED
+	wl->iscan_on = TRUE;	/* iscan on & off switch. we enable iscan per default */
+#else
+	wl->iscan_on = FALSE;
+#endif /* WL_ISCAN_DISABLED */
+#ifndef WL_ROAM_DISABLED
+	wl->roam_on = TRUE;	/* roam on & off switch. we enable roam per default */
+#else
+	wl->roam_on = FALSE;
+#endif /* WL_ROAM_DISABLED */
+
+	wl->iscan_kickstart = FALSE;
+	wl->active_scan = TRUE;	/* we do active scan for specific scan per default */
+	wl->dongle_up = FALSE;	/* dongle is not up yet */
+	wl_init_eq(wl);
+	if (unlikely((err = wl_init_priv_mem(wl))))
+		return err;
+	if (unlikely(wl_create_event_handler(wl)))
+		return -ENOMEM;
+	wl_init_eloop_handler(&wl->el);
+	mutex_init(&wl->usr_sync);
+	if (unlikely((err = wl_init_iscan(wl))))
+		return err;
+	wl_init_fw(wl->fw);
+	wl_init_conf(wl->conf);
+	wl_init_prof(wl->profile);
+	wl_link_down(wl);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static void
+wl_deinit_priv(struct wl_priv *wl)
+{
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl_destroy_event_handler(wl);
+	wl->dongle_up = FALSE;	/* dongle down */
+	wl_flush_eq(wl);
+	wl_link_down(wl);
+	wl_term_iscan(wl);
+	wl_deinit_priv_mem(wl);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+}
+
+int32
+wl_cfg80211_attach(struct net_device *ndev, void *data)
+{
+	struct wireless_dev *wdev;
+	struct wl_priv *wl;
+	struct wl_iface *ci;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely(!ndev)) {
+		WL_ERR(("ndev is invaild\n"));
+		return -ENODEV;
+	}
+	wl_cfg80211_dev = kzalloc(sizeof(struct wl_dev), GFP_KERNEL);
+	if (unlikely(!wl_cfg80211_dev)) {
+		WL_ERR(("wl_cfg80211_dev is invalid\n"));
+		return -ENOMEM;
+	}
+	WL_DBG(("func %p\n", wl_sdio_func()));
+#ifndef WL_CFG80211_LOCALTEST
+	wdev = wl_alloc_wdev(sizeof(struct wl_iface), &wl_sdio_func()->dev);
+#else
+	wdev = wl_alloc_wdev(sizeof(struct wl_iface), NULL);
+#endif
+	if (unlikely(IS_ERR(wdev)))
+		return -ENOMEM;
+
+	wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
+	wl = wdev_to_wl(wdev);
+	wl->wdev = wdev;
+	wl->pub = data;
+	ci = (struct wl_iface *)wl_to_ci(wl);
+	ci->wl = wl;
+	ndev->ieee80211_ptr = wdev;
+	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+	wdev->netdev = ndev;
+	if (unlikely((err = wl_init_priv(wl)))) {
+		WL_ERR(("Failed to init iwm_priv (%d)\n", err));
+		goto cfg80211_attach_out;
+	}
+	wl_set_drvdata(wl_cfg80211_dev, ci);
+	set_bit(WL_STATUS_READY, &wl->status);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+
+cfg80211_attach_out:
+	wl_free_wdev(wl);
+	return err;
+}
+
+void
+wl_cfg80211_detach(void)
+{
+	struct wl_priv *wl;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl = WL_PRIV_GET();
+
+	wl_deinit_priv(wl);
+	wl_free_wdev(wl);
+	wl_set_drvdata(wl_cfg80211_dev, NULL);
+	kfree(wl_cfg80211_dev);
+	wl_cfg80211_dev = NULL;
+	wl_clear_sdio_func();
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+}
+
+static void
+wl_wakeup_event(struct wl_priv *wl)
+{
+	up(&wl->event_sync);
+}
+
+static int32
+wl_event_handler(void *data)
+{
+	struct wl_priv *wl = (struct wl_priv *)data;
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+	struct wl_event_q *e;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	sched_setscheduler(current, SCHED_FIFO, &param);
+	while (likely(!down_interruptible(&wl->event_sync))) {
+		if (unlikely(!(e = wl_deq_event(wl)))) {
+			WL_ERR(("eqeue empty..\n"));
+			BUG();
+		}
+		WL_DBG(("event type (%d)\n", e->etype));
+		if (wl->el.handler[e->etype]) {
+			wl->el.handler[e->etype](wl, wl_to_ndev(wl), &e->emsg, e->edata);
+		} 	else {
+			WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
+		}
+		wl_put_event(e);
+	}
+	complete_and_exit(&wl->event_exit, 0);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+}
+
+void
+wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void* data)
+{
+	uint32 event_type = ntoh32(e->event_type);
+	struct wl_priv *wl = ndev_to_wl(ndev);
+#if (WL_DBG_LEVEL > 0)
+	int8 *estr = (event_type <= sizeof(wl_dbg_estr)/WL_DBG_ESTR_MAX-1) ?
+		wl_dbg_estr[event_type] : (int8 *)"Unknown";
+#endif /* (WL_DBG_LEVEL > 0) */
+	WL_DBG(("event_type (%d):""WLC_E_""%s\n", event_type, estr));
+	if (likely(!wl_enq_event(wl, event_type, e, data)))
+		wl_wakeup_event(wl);
+}
+
+static void
+wl_init_eq(struct wl_priv *wl)
+{
+	wl_init_eq_lock(wl);
+	INIT_LIST_HEAD(&wl->eq_list);
+}
+
+static void
+wl_flush_eq(struct wl_priv *wl)
+{
+	struct wl_event_q *e;
+
+	wl_lock_eq(wl);
+	while (!list_empty(&wl->eq_list)) {
+		e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
+		list_del(&e->eq_list);
+		kfree(e);
+	}
+	wl_unlock_eq(wl);
+}
+
+/* 
+* retrieve first queued event from head
+*/
+
+static struct wl_event_q *
+wl_deq_event(struct wl_priv *wl)
+{
+	struct wl_event_q *e = NULL;
+
+	wl_lock_eq(wl);
+	if (likely(!list_empty(&wl->eq_list))) {
+		e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
+		list_del(&e->eq_list);
+	}
+	wl_unlock_eq(wl);
+
+	return e;
+}
+
+/*
+** push event to tail of the queue
+*/
+
+static int32
+wl_enq_event(struct wl_priv *wl, uint32 event, const wl_event_msg_t *msg, void *data)
+{
+	struct wl_event_q *e;
+	int32 err = 0;
+
+	if (unlikely(!(e = kzalloc(sizeof(struct wl_event_q), GFP_KERNEL)))) {
+		WL_ERR(("event alloc failed\n"));
+		return -ENOMEM;
+	}
+
+	e->etype = event;
+	memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
+	if (data) {
+	}
+	wl_lock_eq(wl);
+	list_add_tail(&e->eq_list, &wl->eq_list);
+	wl_unlock_eq(wl);
+
+	return err;
+}
+
+static void
+wl_put_event(struct wl_event_q *e)
+{
+	kfree(e);
+}
+
+void
+wl_cfg80211_sdio_func(void *func)
+{
+	cfg80211_sdio_func = (struct sdio_func *)func;
+}
+
+static void
+wl_clear_sdio_func(void)
+{
+	cfg80211_sdio_func = NULL;
+}
+
+
+static struct sdio_func  *
+wl_sdio_func(void)
+{
+	return cfg80211_sdio_func;
+}
+
+static int32
+wl_dongle_mode(struct net_device *ndev, int32 iftype)
+{
+	int32 infra = 0;
+	int32 ap = 0;
+	int32 err = 0;
+
+	switch (iftype) {
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_WDS:
+		WL_ERR(("type (%d) : currently we do not support this mode\n", iftype));
+		err = -EINVAL;
+		return err;
+	case NL80211_IFTYPE_ADHOC:
+		break;
+	case NL80211_IFTYPE_STATION:
+		infra = 1;
+		break;
+	default:
+		err = -EINVAL;
+		WL_ERR(("invalid type (%d)\n", iftype));
+		return err;
+	}
+	infra = htod32(infra);
+	ap = htod32(ap);
+	WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
+	if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
+		unlikely(err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap)))) {
+		WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+		return err;
+	}
+
+	return -EINPROGRESS;
+}
+
+#ifndef EMBEDDED_PLATFORM
+static int32
+wl_dongle_country(struct net_device *ndev, uint8 ccode)
+{
+
+	int32 err = 0;
+
+
+	return err;
+}
+
+static int32
+wl_dongle_up(struct net_device *ndev, uint32 up)
+{
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely(err =  wl_dev_ioctl(ndev, WLC_UP, &up, sizeof(up)))) {
+		WL_ERR(("WLC_UP error (%d)\n", err));
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return err;
+}
+
+static int32
+wl_dongle_power(struct net_device *ndev, uint32 power_mode)
+{
+	int32 err = 0;
+
+	if (unlikely(err =  wl_dev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode)))) {
+		WL_ERR(("WLC_SET_PM error (%d)\n", err));
+	}
+	return err;
+}
+
+static int32
+wl_dongle_glom(struct net_device *ndev, uint32 glom, uint32 dongle_align)
+{
+	int8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
+	int32 err = 0;
+
+	/* Match Host and Dongle rx alignment */
+	bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
+	if (unlikely(err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+		WL_ERR(("txglomalign error (%d)\n", err));
+		goto dongle_glom_out;
+	}
+	/* disable glom option per default */
+	bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+	if (unlikely(err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+		WL_ERR(("txglom error (%d)\n", err));
+		goto dongle_glom_out;
+	}
+dongle_glom_out :
+	return err;
+}
+
+static int32
+wl_dongle_roam(struct net_device *ndev, uint32 roamvar, uint32 bcn_timeout)
+{
+	int8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
+	int32 err = 0;
+
+	/* Setup timeout if Beacons are lost and roam is off to report link down */
+	if (roamvar) {
+		bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+		if (unlikely(err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+			WL_ERR(("bcn_timeout error (%d)\n", err));
+			goto dongle_rom_out;
+		}
+	}
+	/* Enable/Disable built-in roaming to allow supplicant to take care of roaming */
+	bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+	if (unlikely(err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+		WL_ERR(("roam_off error (%d)\n", err));
+		goto dongle_rom_out;
+	}
+dongle_rom_out :
+	return err;
+}
+
+static int32
+wl_dongle_eventmsg(struct net_device *ndev)
+{
+
+	int8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
+	int8 eventmask[WL_EVENTING_MASK_LEN];
+	int32 err = 0;
+
+	/* Setup event_msgs */
+	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+	if (unlikely(err =  wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf)))) {
+		WL_ERR(("Get event_msgs error (%d)\n", err));
+		goto dongle_eventmsg_out;
+	}
+	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
+
+	setbit(eventmask, WLC_E_SET_SSID);
+	setbit(eventmask, WLC_E_PRUNE);
+	setbit(eventmask, WLC_E_AUTH);
+	setbit(eventmask, WLC_E_REASSOC);
+	setbit(eventmask, WLC_E_REASSOC_IND);
+	setbit(eventmask, WLC_E_DEAUTH_IND);
+	setbit(eventmask, WLC_E_DISASSOC_IND);
+	setbit(eventmask, WLC_E_DISASSOC);
+	setbit(eventmask, WLC_E_JOIN);
+	setbit(eventmask, WLC_E_ASSOC_IND);
+	setbit(eventmask, WLC_E_PSK_SUP);
+	setbit(eventmask, WLC_E_LINK);
+	setbit(eventmask, WLC_E_NDIS_LINK);
+	setbit(eventmask, WLC_E_MIC_ERROR);
+	setbit(eventmask, WLC_E_PMKID_CACHE);
+	setbit(eventmask, WLC_E_TXFAIL);
+	setbit(eventmask, WLC_E_JOIN_START);
+	setbit(eventmask, WLC_E_SCAN_COMPLETE);
+
+	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+	if (unlikely(err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+		WL_ERR(("Set event_msgs error (%d)\n", err));
+		goto dongle_eventmsg_out;
+	}
+
+dongle_eventmsg_out :
+	return err;
+}
+
+static int32
+wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time, int32 scan_unassoc_time)
+{
+	int32 err = 0;
+
+	if ((err =  wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
+		sizeof(scan_assoc_time)))) {
+		if (err == -EOPNOTSUPP) {
+			WL_INFO(("Scan assoc time is not supported\n"));
+		} else {
+			WL_ERR(("Scan assoc time error (%d)\n", err));
+		}
+		goto dongle_scantime_out;
+	}
+	if ((err =  wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
+		sizeof(scan_unassoc_time)))) {
+		if (err == -EOPNOTSUPP) {
+			WL_INFO(("Scan unassoc time is not supported\n"));
+		} else {
+			WL_ERR(("Scan unassoc time error (%d)\n", err));
+		}
+		goto dongle_scantime_out;
+	}
+
+dongle_scantime_out :
+	return err;
+}
+
+static int32
+wl_dongle_offload(struct net_device *ndev, int32 arpoe, int32 arp_ol)
+{
+	int8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
+	int32 err = 0;
+
+	/* Set ARP offload */
+	bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
+	if ((err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+		if (err == -EOPNOTSUPP) {
+			WL_INFO(("arpoe is not supported\n"));
+		} else {
+			WL_ERR(("arpoe error (%d)\n", err));
+		}
+		goto dongle_offload_out;
+	}
+	bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
+	if ((err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+		if (err == -EOPNOTSUPP) {
+			WL_INFO(("arp_ol is not supported\n"));
+		} else {
+			WL_ERR(("arp_ol error (%d)\n", err));
+		}
+		goto dongle_offload_out;
+	}
+
+dongle_offload_out :
+	return err;
+}
+
+static int32
+wl_pattern_atoh(int8 *src, int8 *dst)
+{
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+	int i;
+	if (strncmp(src, "0x", 2) != 0 &&
+	    strncmp(src, "0X", 2) != 0) {
+		WL_ERR(("Mask invalid format. Needs to start with 0x\n"));
+		return -1;
+	}
+	src = src + 2; /* Skip past 0x */
+	if (strlen(src) % 2 != 0) {
+		WL_ERR(("Mask invalid format. Needs to be of even length\n"));
+		return -1;
+	}
+	for (i = 0; *src != '\0'; i++) {
+		char num[3];
+		strncpy(num, src, 2);
+		num[2] = '\0';
+		dst[i] = (uint8)strtoul(num, NULL, 16);
+		src += 2;
+	}
+	return i;
+}
+
+static int32
+wl_dongle_filter(struct net_device *ndev, uint32 filter_mode)
+{
+	int8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" + '\0' + bitvec  */
+	const int8 				*str;
+	struct wl_pkt_filter		pkt_filter;
+	struct wl_pkt_filter		*pkt_filterp;
+	int32						buf_len;
+	int32						str_len;
+	uint32					mask_size;
+	uint32					pattern_size;
+	int8 buf[256];
+	int32 err = 0;
+
+/* add a default packet filter pattern */
+	str = "pkt_filter_add";
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[ str_len ] = '\0';
+	buf_len = str_len + 1;
+
+	pkt_filterp = (struct wl_pkt_filter *) (buf + str_len + 1);
+
+	/* Parse packet filter id. */
+	pkt_filter.id = htod32(100);
+
+	/* Parse filter polarity. */
+	pkt_filter.negate_match = htod32(0);
+
+	/* Parse filter type. */
+	pkt_filter.type = htod32(0);
+
+	/* Parse pattern filter offset. */
+	pkt_filter.u.pattern.offset = htod32(0);
+
+	/* Parse pattern filter mask. */
+	mask_size =	htod32(wl_pattern_atoh("0xff",
+		(char *) pkt_filterp->u.pattern.mask_and_pattern));
+
+	/* Parse pattern filter pattern. */
+	pattern_size = htod32(wl_pattern_atoh("0x00",
+		(char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
+
+	if (mask_size != pattern_size) {
+		WL_ERR(("Mask and pattern not the same size\n"));
+		err = -EINVAL;
+		goto dongle_filter_out;
+	}
+
+	pkt_filter.u.pattern.size_bytes = mask_size;
+	buf_len += WL_PKT_FILTER_FIXED_LEN;
+	buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
+
+	/* Keep-alive attributes are set in local	variable (keep_alive_pkt), and
+	** then memcpy'ed into buffer (keep_alive_pktp) since there is no
+	** guarantee that the buffer is properly aligned.
+	*/
+	memcpy((char *)pkt_filterp, &pkt_filter,
+		WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+
+	if ((err =  wl_dev_ioctl(ndev, WLC_SET_VAR, buf, buf_len))) {
+		if (err == -EOPNOTSUPP) {
+			WL_INFO(("filter not supported\n"));
+		} else {
+			WL_ERR(("filter (%d)\n", err));
+		}
+		goto dongle_filter_out;
+	}
+
+	/* set mode to allow pattern */
+	bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf));
+	if ((err =  wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
+		if (err == -EOPNOTSUPP) {
+			WL_INFO(("filter_mode not supported\n"));
+		} else {
+			WL_ERR(("filter_mode (%d)\n", err));
+		}
+		goto dongle_filter_out;
+	}
+
+dongle_filter_out :
+	return err;
+}
+#endif /* !EMBEDDED_PLATFORM */
+
+int32
+wl_config_dongle(struct wl_priv *wl, bool need_lock)
+{
+#ifndef DHD_SDALIGN
+#define DHD_SDALIGN	32
+#endif
+	struct net_device *ndev;
+	struct wireless_dev *wdev;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (wl->dongle_up)
+		return err;
+
+
+	ndev = wl_to_ndev(wl);
+	wdev = ndev->ieee80211_ptr;
+	if (need_lock)
+		rtnl_lock();
+
+#ifndef EMBEDDED_PLATFORM
+	if (unlikely((err = wl_dongle_up(ndev, 0))))
+		goto default_conf_out;
+	if (unlikely((err = wl_dongle_country(ndev, 0))))
+		goto default_conf_out;
+	if (unlikely((err = wl_dongle_power(ndev, PM_FAST))))
+		goto default_conf_out;
+	if (unlikely((err = wl_dongle_glom(ndev, 0, DHD_SDALIGN))))
+		goto default_conf_out;
+	if (unlikely((err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3))))
+		goto default_conf_out;
+	if (unlikely((err = wl_dongle_eventmsg(ndev))))
+		goto default_conf_out;
+
+	wl_dongle_scantime(ndev, 40, 80);
+	wl_dongle_offload(ndev, 1, 0xf);
+	wl_dongle_filter(ndev, 1);
+#endif /* !EMBEDDED_PLATFORM */
+
+	err = wl_dongle_mode(ndev, wdev->iftype);
+	if (unlikely(err && err != -EINPROGRESS))
+		goto default_conf_out;
+	if (unlikely((err = wl_dongle_probecap(wl))))
+		goto default_conf_out;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	/* -EINPROGRESS: Call commit handler */
+
+default_conf_out :
+	if (need_lock)
+		rtnl_unlock();
+
+	wl->dongle_up = TRUE;
+
+	return err;
+
+}
+
+static int32
+wl_update_wiphybands(struct wl_priv *wl)
+{
+	struct wiphy *wiphy;
+	int32 phy_list;
+	int8 phy;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	if (unlikely(err =  wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list,
+		sizeof(phy_list)))) {
+		WL_ERR(("error (%d)\n", err));
+		return err;
+	}
+
+	phy = ((char *)&phy_list)[1];
+	WL_DBG(("%c phy\n", phy));
+	if (phy == 'n' || phy == 'a') {
+		wiphy = wl_to_wiphy(wl);
+		wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+__wl_cfg80211_up(struct wl_priv *wl)
+{
+	int32 err = 0;
+
+	if (unlikely(err = wl_config_dongle(wl, FALSE)))
+		return err;
+
+	wl_invoke_iscan(wl);
+	set_bit(WL_STATUS_READY, &wl->status);
+	return err;
+}
+
+static int32
+__wl_cfg80211_down(struct wl_priv *wl)
+{
+	int32 err = 0;
+
+	/* Check if cfg80211 interface is already down */
+	if (!test_bit(WL_STATUS_READY, &wl->status))
+		return err;	   /* it is even not ready */
+
+	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+	wl_term_iscan(wl);
+	if (wl->scan_request) {
+		cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE means abort */
+		wl->scan_request = NULL;
+	}
+	clear_bit(WL_STATUS_READY, &wl->status);
+	clear_bit(WL_STATUS_SCANNING, &wl->status);
+	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+	clear_bit(WL_STATUS_CONNECTED, &wl->status);
+
+	return err;
+}
+
+int32
+wl_cfg80211_up(void)
+{
+	struct wl_priv *wl;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl = WL_PRIV_GET();
+	mutex_lock(&wl->usr_sync);
+	err = __wl_cfg80211_up(wl);
+	mutex_unlock(&wl->usr_sync);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+int32
+wl_cfg80211_down(void)
+{
+	struct wl_priv *wl;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl = WL_PRIV_GET();
+	mutex_lock(&wl->usr_sync);
+	err = __wl_cfg80211_down(wl);
+	mutex_unlock(&wl->usr_sync);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+	return err;
+}
+
+static int32
+wl_dongle_probecap(struct wl_priv *wl)
+{
+	int32 err = 0;
+
+	if (unlikely((err = wl_update_wiphybands(wl))))
+		return err;
+
+	return err;
+}
+
+static void *
+wl_read_prof(struct wl_priv *wl, int32 item)
+{
+	switch (item) {
+	case WL_PROF_SEC:
+		return &wl->profile->sec;
+	case WL_PROF_ACT:
+		return &wl->profile->active;
+	case WL_PROF_BSSID:
+		return &wl->profile->bssid;
+	case WL_PROF_SSID:
+		return &wl->profile->ssid;
+	}
+	WL_ERR(("invalid item (%d)\n", item));
+	return NULL;
+}
+
+static int32
+wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data, int32 item)
+{
+	int32 err = 0;
+	struct wlc_ssid *ssid;
+
+	switch (item) {
+	case WL_PROF_SSID:
+		ssid = (wlc_ssid_t *)data;
+		memset(wl->profile->ssid.SSID, 0, sizeof(wl->profile->ssid.SSID));
+		memcpy(wl->profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
+		wl->profile->ssid.SSID_len = ssid->SSID_len;
+		break;
+	case WL_PROF_BSSID:
+		if (data)
+			memcpy(wl->profile->bssid, data, ETHER_ADDR_LEN);
+		else
+			memset(wl->profile->bssid, 0, ETHER_ADDR_LEN);
+		break;
+	case WL_PROF_SEC:
+		memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec));
+		break;
+	case WL_PROF_ACT:
+		wl->profile->active = *(bool *)data;
+		break;
+	default :
+		WL_ERR(("unsupported item (%d)\n", item));
+		err = -EOPNOTSUPP;
+		break;
+	}
+
+	return err;
+}
+
+void
+wl_cfg80211_dbg_level(uint32 level)
+{
+	wl_dbg_level = level;
+}
+
+static bool
+wl_is_ibssmode(struct wl_priv *wl)
+{
+	return (wl->conf->mode == WL_MODE_IBSS);
+}
+
+static bool
+wl_is_ibssstarter(struct wl_priv *wl)
+{
+	return wl->ibss_starter;
+}
+
+static void
+wl_rst_ie(struct wl_priv *wl)
+{
+	struct wl_ie *ie = wl_to_ie(wl);
+
+	ie->offset = 0;
+}
+
+static int32
+wl_add_ie(struct wl_priv *wl, uint8 t, uint8 l, uint8 *v)
+{
+	struct wl_ie *ie = wl_to_ie(wl);
+	int32 err = 0;
+
+	if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
+		WL_ERR(("ei crosses buffer boundary\n"));
+		return -ENOSPC;
+	}
+	ie->buf[ie->offset] = t;
+	ie->buf[ie->offset+1] = l;
+	memcpy(&ie->buf[ie->offset+2], v, l);
+	ie->offset += l+2;
+
+	return err;
+}
+
+static int32
+wl_mrg_ie(struct wl_priv *wl, uint8 *ie_stream, uint16 ie_size)
+{
+	struct wl_ie *ie = wl_to_ie(wl);
+	int32 err = 0;
+
+	if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
+		WL_ERR(("ei_stream crosses buffer boundary\n"));
+		return -ENOSPC;
+	}
+	memcpy(&ie->buf[ie->offset], ie_stream,  ie_size);
+	ie->offset += ie_size;
+
+	return err;
+}
+
+static int32
+wl_cp_ie(struct wl_priv *wl, uint8 *dst, uint16 dst_size)
+{
+	struct wl_ie *ie = wl_to_ie(wl);
+	int32 err = 0;
+
+	if (unlikely(ie->offset > dst_size)) {
+		WL_ERR(("dst_size is not enough\n"));
+		return -ENOSPC;
+	}
+	memcpy(dst, &ie->buf[0], ie->offset);
+
+	return err;
+}
+
+static uint32
+wl_get_ielen(struct wl_priv *wl)
+{
+	struct wl_ie *ie = wl_to_ie(wl);
+
+	return ie->offset;
+}
+
+static void
+wl_link_up(struct wl_priv *wl)
+{
+	wl->link_up = TRUE;
+}
+
+static void
+wl_link_down(struct wl_priv *wl)
+{
+	struct wl_connect_info *conn_info = wl_to_conn(wl);
+
+	wl->link_up = FALSE;
+	if (conn_info->req_ie) {
+		kfree(conn_info->req_ie);
+		conn_info->req_ie = NULL;
+	}
+	conn_info->req_ie_len = 0;
+	if (conn_info->resp_ie) {
+		kfree(conn_info->resp_ie);
+		conn_info->resp_ie = NULL;
+	}
+	conn_info->resp_ie_len = 0;
+}
+
+static void
+wl_lock_eq(struct wl_priv *wl)
+{
+	spin_lock_irq(&wl->eq_lock);
+}
+
+static void
+wl_unlock_eq(struct wl_priv *wl)
+{
+	spin_unlock_irq(&wl->eq_lock);
+}
+
+static void
+wl_init_eq_lock(struct wl_priv *wl)
+{
+	spin_lock_init(&wl->eq_lock);
+}
+
+static void
+wl_delay(uint32 ms)
+{
+	if (ms < 1000 / HZ) {
+		cond_resched();
+		mdelay(ms);
+	} else {
+		msleep(ms);
+	}
+}
+
+static void
+wl_set_drvdata(struct wl_dev *dev, void *data)
+{
+	dev->driver_data = data;
+}
+
+static void *
+wl_get_drvdata(struct wl_dev *dev)
+{
+	return dev->driver_data;
+}
+
+int32
+wl_cfg80211_read_fw(int8 *buf, uint32 size)
+{
+	const struct firmware *fw_entry;
+	struct wl_priv *wl;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In : size (%d)\n", size));
+#endif
+	wl = WL_PRIV_GET();
+
+	fw_entry = wl->fw->fw_entry;
+
+	if (fw_entry->size < wl->fw->ptr + size) {
+		size = fw_entry->size - wl->fw->ptr;
+	}
+	memcpy(buf, &fw_entry->data[wl->fw->ptr], size);
+	wl->fw->ptr += size;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out : size (%d)\n", size));
+#endif
+	return size;
+}
+
+void
+wl_cfg80211_release_fw(void)
+{
+	struct wl_priv *wl;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl = WL_PRIV_GET();
+	release_firmware(wl->fw->fw_entry);
+	wl->fw->ptr = 0;
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+}
+
+void *
+wl_cfg80211_request_fw(int8 *file_name)
+{
+	struct wl_priv *wl;
+	const struct firmware *fw_entry = NULL;
+	int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	WL_DBG(("file name : \"%s\"\n", file_name));
+	wl = WL_PRIV_GET();
+
+	if (!test_bit(WL_FW_LOADING_DONE, &wl->fw->status)) {
+		if (unlikely(err = request_firmware(&wl->fw->fw_entry, file_name,
+			&wl_sdio_func()->dev))) {
+			WL_ERR(("Could not download fw (%d)\n", err));
+			goto req_fw_out;
+		}
+		set_bit(WL_FW_LOADING_DONE, &wl->fw->status);
+		fw_entry = wl->fw->fw_entry;
+		if (fw_entry) {
+			WL_DBG(("fw size (%d), data (%p)\n", fw_entry->size, fw_entry->data));
+		}
+	} else if (!test_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status)) {
+		if (unlikely(err = request_firmware(&wl->fw->fw_entry, file_name,
+			&wl_sdio_func()->dev))) {
+			WL_ERR(("Could not download nvram (%d)\n", err));
+			goto req_fw_out;
+		}
+		set_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status);
+		fw_entry = wl->fw->fw_entry;
+		if (fw_entry) {
+			WL_DBG(("nvram size (%d), data (%p)\n", fw_entry->size, fw_entry->data));
+		}
+	} else {
+		WL_DBG(("Downloading already done. Nothing to do more\n"));
+		err = -EPERM;
+	}
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+
+req_fw_out:
+	if (unlikely(err)) {
+		return NULL;
+	}
+	wl->fw->ptr = 0;
+	return (void *)fw_entry->data;
+}
+
+int8 *
+wl_cfg80211_get_fwname(void)
+{
+	struct wl_priv *wl;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl = WL_PRIV_GET();
+	strcpy(wl->fw->fw_name, WL_4329_FW_FILE);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return wl->fw->fw_name;
+}
+
+int8 *
+wl_cfg80211_get_nvramname(void)
+{
+	struct wl_priv *wl;
+
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("In\n"));
+#endif
+	wl = WL_PRIV_GET();
+	strcpy(wl->fw->nvram_name, WL_4329_NVRAM_FILE);
+#ifdef WL_CFG80211_BACKTRACE
+	WL_DBG(("Out\n"));
+#endif
+	return wl->fw->nvram_name;
+}
diff --git a/bcm4329/src/wl/sys/wl_cfg80211.h b/bcm4329/src/wl/sys/wl_cfg80211.h
new file mode 100644
index 0000000..2722699
--- /dev/null
+++ b/bcm4329/src/wl/sys/wl_cfg80211.h
@@ -0,0 +1,372 @@
+/*
+ * Linux Cfg80211 support
+ *
+ * Copyright (C) 1999-2010, 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: wl_cfg80211.h,v 1.1.2.19 2010/05/04 21:21:00 Exp $
+ */
+
+#ifndef _wl_cfg80211_h_
+#define _wl_cfg80211_h_
+
+#include <linux/wireless.h>
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <wlioctl.h>
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+
+struct wl_conf;
+struct wl_iface;
+struct wl_priv;
+struct wl_security;
+struct wl_ibss;
+
+#if defined(IL_BIGENDIAN)
+#include <bcmendian.h>
+#define htod32(i) (bcmswap32(i))
+#define htod16(i) (bcmswap16(i))
+#define dtoh32(i) (bcmswap32(i))
+#define dtoh16(i) (bcmswap16(i))
+#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
+#endif
+
+#define WL_DBG_NONE	0
+#define WL_DBG_DBG 	(1 << 2)
+#define WL_DBG_INFO	(1 << 1)
+#define WL_DBG_ERR	(1 << 0)
+#define WL_DBG_MASK ((WL_DBG_DBG | WL_DBG_INFO | WL_DBG_ERR) << 1)
+
+#define WL_DBG_LEVEL 1	/* 0 invalidates all debug messages. default is 1 */
+#define	WL_ERR(args)									\
+	do {										\
+		if (wl_dbg_level & WL_DBG_ERR) {				\
+			if (net_ratelimit()) {						\
+				printk("ERROR @%s : ", __FUNCTION__);	\
+				printk args;						\
+			} 								\
+		}									\
+	} while (0)
+#define	WL_INFO(args)									\
+	do {										\
+		if (wl_dbg_level & WL_DBG_INFO) {				\
+			if (net_ratelimit()) {						\
+				printk("INFO @%s : ", __FUNCTION__);	\
+				printk args;						\
+			}								\
+		}									\
+	} while (0)
+#if (WL_DBG_LEVEL > 0)
+#define	WL_DBG(args)								\
+	do {									\
+		if (wl_dbg_level & WL_DBG_DBG) {			\
+			printk("DEBUG @%s :", __FUNCTION__);	\
+			printk args;							\
+		}									\
+	} while (0)
+#else /* !(WL_DBG_LEVEL > 0) */
+#define	WL_DBG(args)
+#endif /* (WL_DBG_LEVEL > 0) */
+
+#define WL_SCAN_RETRY_MAX 		3	/* used for ibss scan */
+#define WL_NUM_SCAN_MAX 		1
+#define WL_NUM_PMKIDS_MAX 		MAXPMKID	/* will be used for 2.6.33 kernel
+							* or later 
+							*/
+#define WL_SCAN_BUF_MAX 		(1024 * 8)
+#define WL_TLV_INFO_MAX 		1024
+#define WL_BSS_INFO_MAX			2048
+#define WL_ASSOC_INFO_MAX 		512	/* 
+						* needs to grab assoc info from dongle to 
+						* report it to cfg80211 through "connect"
+						* event 
+						*/
+#define WL_IOCTL_LEN_MAX 		1024
+#define WL_EXTRA_BUF_MAX 		2048
+#define WL_ISCAN_BUF_MAX   		2048	/* the buf lengh can be WLC_IOCTL_MAXLEN (8K)
+						* to reduce iteration 
+						*/
+#define WL_ISCAN_TIMER_INTERVAL_MS	3000
+#define WL_SCAN_ERSULTS_LAST 	(WL_SCAN_RESULTS_NO_MEM+1)
+#define WL_AP_MAX				256	/* virtually unlimitted as long
+							* as kernel memory allows
+							*/
+#define WL_FILE_NAME_MAX		256
+
+/* dongle status */
+enum wl_status {
+	WL_STATUS_READY,
+	WL_STATUS_SCANNING,
+	WL_STATUS_SCAN_ABORTING,
+	WL_STATUS_CONNECTING,
+	WL_STATUS_CONNECTED
+};
+
+/* wi-fi mode */
+enum wl_mode {
+	WL_MODE_BSS,
+	WL_MODE_IBSS,
+	WL_MODE_AP
+};
+
+/* dongle profile list */
+enum wl_prof_list {
+	WL_PROF_MODE,
+	WL_PROF_SSID,
+	WL_PROF_SEC,
+	WL_PROF_IBSS,
+	WL_PROF_BAND,
+	WL_PROF_BSSID,
+	WL_PROF_ACT
+};
+
+/* dongle iscan state */
+enum wl_iscan_state {
+	WL_ISCAN_STATE_IDLE,
+	WL_ISCAN_STATE_SCANING
+};
+
+/* fw downloading status */
+enum wl_fw_status {
+	WL_FW_LOADING_DONE,
+	WL_NVRAM_LOADING_DONE
+};
+
+/* dongle configuration */
+struct wl_conf {
+	uint32 mode;	/* adhoc , infrastructure or ap */
+	uint32 frag_threshold;
+	uint32 rts_threshold;
+	uint32 retry_short;
+	uint32 retry_long;
+	int32 tx_power;
+	struct ieee80211_channel channel;
+};
+
+/* cfg80211 main event loop */
+struct wl_event_loop {
+	int32 (*handler[WLC_E_LAST])(struct wl_priv *wl, struct net_device *ndev,
+		const wl_event_msg_t *e, void *data);
+};
+
+/* representing interface of cfg80211 plane */
+struct wl_iface {
+	struct wl_priv *wl;
+};
+
+struct wl_dev {
+	void *driver_data;	/* to store cfg80211 object information */
+};
+
+/* bss inform structure for cfg80211 interface */
+struct wl_cfg80211_bss_info {
+	uint16 band;
+	uint16 channel;
+	int16 rssi;
+	uint16 frame_len;
+	uint8 frame_buf[1];
+};
+
+/* basic structure of scan request */
+struct wl_scan_req {
+	struct wlc_ssid ssid;
+};
+
+/* basic structure of information element */
+struct wl_ie {
+	uint16 offset;
+	uint8 buf[WL_TLV_INFO_MAX];
+};
+
+/* event queue for cfg80211 main event */
+struct wl_event_q {
+	struct list_head eq_list;
+	uint32 etype;
+	wl_event_msg_t emsg;
+	int8 edata[1];
+};
+
+/* security information with currently associated ap */
+struct wl_security {
+	uint32 wpa_versions;
+	uint32 auth_type;
+	uint32 cipher_pairwise;
+	uint32 cipher_group;
+	uint32 wpa_auth;
+};
+
+/* ibss information for currently joined ibss network */
+struct wl_ibss {
+	uint8 beacon_interval;	/* in millisecond */
+	uint8 atim;		/* in millisecond */
+	int8 join_only;
+	uint8 band;
+	uint8 channel;
+};
+
+/* dongle profile */
+struct wl_profile {
+	uint32 mode;
+	struct wlc_ssid ssid;
+	uint8 bssid[ETHER_ADDR_LEN];
+	struct wl_security sec;
+	struct wl_ibss ibss;
+	int32 band;
+	bool active;
+};
+
+/* dongle iscan event loop */
+struct wl_iscan_eloop {
+	int32 (*handler[WL_SCAN_ERSULTS_LAST])(struct wl_priv *wl);
+};
+
+/* dongle iscan controller */
+struct wl_iscan_ctrl {
+	struct net_device *dev;
+	struct timer_list timer;
+	uint32 timer_ms;
+	uint32 timer_on;
+	int32 state;
+	int32 pid;
+	struct semaphore sync;
+	struct completion exited;
+	struct wl_iscan_eloop el;
+	void *data;
+	int8 ioctl_buf[WLC_IOCTL_SMLEN];
+	int8 scan_buf[WL_ISCAN_BUF_MAX];
+};
+
+/* association inform */
+struct wl_connect_info {
+	uint8 *req_ie;
+	int32 req_ie_len;
+	uint8 *resp_ie;
+	int32 resp_ie_len;
+};
+
+/* firmware /nvram downloading controller */
+struct wl_fw_ctrl {
+	const struct firmware *fw_entry;
+	ulong status;
+	uint32 ptr;
+	int8 fw_name[WL_FILE_NAME_MAX];
+	int8 nvram_name[WL_FILE_NAME_MAX];
+};
+
+/* assoc ie length */
+struct wl_assoc_ielen {
+	uint32	req_len;
+	uint32	resp_len;
+};
+
+/* wpa2 pmk list */
+struct wl_pmk_list {
+	pmkid_list_t pmkids;
+	pmkid_t foo[MAXPMKID-1];
+};
+
+
+/* dongle private data of cfg80211 interface */
+struct wl_priv {
+	struct wireless_dev *wdev;	/* representing wl cfg80211 device */
+	struct wl_conf *conf;	/* dongle configuration */
+	struct cfg80211_scan_request *scan_request;	/* scan request object */
+	struct wl_event_loop el;	/* main event loop */
+	struct list_head	eq_list;	/* used for event queue */
+	spinlock_t eq_lock;	/* for event queue synchronization */
+	struct mutex usr_sync;	/* maily for dongle up/down synchronization */
+	struct wl_scan_results *bss_list;	/* bss_list holding scanned ap information */
+	struct wl_scan_results *scan_results;
+	struct wl_scan_req *scan_req_int;	/* scan request object for internal purpose */
+	struct wl_cfg80211_bss_info *bss_info;	/* bss information for cfg80211 layer */
+	struct wl_ie ie;	/* information element object for internal purpose */
+	struct ether_addr bssid;	/* bssid of currently engaged network */
+	struct semaphore event_sync;	/* for synchronization of main event thread */
+	struct completion event_exit;
+	struct wl_profile *profile;		/* holding dongle profile */
+	struct wl_iscan_ctrl *iscan;	/* iscan controller */
+	struct wl_connect_info conn_info;	/* association information container */
+	struct wl_fw_ctrl *fw;	/* control firwmare / nvram paramter downloading */
+	struct wl_pmk_list *pmk_list;	/* wpa2 pmk list */
+	int32 event_pid;	/* pid of main event handler thread */
+	ulong status;	/* current dongle status */
+	void * pub;
+	uint32 channel;	/* current channel */
+	bool iscan_on;	/* iscan on/off switch */
+	bool iscan_kickstart;	/* indicate iscan already started */
+	bool active_scan;	/* current scan mode */
+	bool ibss_starter;	/* indicates this sta is ibss starter */
+	bool link_up;	/* link/connection up flag */
+	bool pwr_save;	/* indicate whether dongle to support power save mode */
+	bool dongle_up;	/* indicate whether dongle up or not */
+	bool roam_on;	/* on/off switch for dongle self-roaming */
+	bool scan_tried;	/* indicates if first scan attempted */
+	uint8 *ioctl_buf;	/* ioctl buffer */
+	uint8 *extra_buf;	/* maily to grab assoc information */
+	uint8 ci[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+#define wl_to_dev(w) (wiphy_dev(wl->wdev->wiphy))
+#define wl_to_wiphy(w) (w->wdev->wiphy)
+#define wiphy_to_wl(w) ((struct wl_priv *)(wiphy_priv(w)))
+#define wl_to_wdev(w) (w->wdev)
+#define wdev_to_wl(w) ((struct wl_priv *)(wdev_priv(w)))
+#define wl_to_ndev(w) (w->wdev->netdev)
+#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr))
+#define ci_to_wl(c) (ci->wl)
+#define wl_to_ci(w) (&w->ci)
+#define wl_to_sr(w) (w->scan_req_int)
+#define wl_to_ie(w) (&w->ie)
+#define iscan_to_wl(i) ((struct wl_priv *)(i->data))
+#define wl_to_iscan(w) (w->iscan)
+#define wl_to_conn(w) (&w->conn_info)
+
+inline static struct wl_bss_info * next_bss(struct wl_scan_results *list,
+	struct wl_bss_info *bss) {
+	return (bss = bss ?
+	 (struct wl_bss_info *)((uintptr)bss + dtoh32(bss->length)) : list->bss_info);
+}
+#define for_each_bss(list, bss, __i)	\
+	for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
+
+extern int32 wl_cfg80211_attach(struct net_device *ndev, void *data);
+extern void wl_cfg80211_detach(void);
+/* event handler from dongle */
+extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void* data);
+extern void wl_cfg80211_sdio_func(void *func);	/* set sdio function info */
+extern int32 wl_cfg80211_up(void);	/* dongle up */
+extern int32 wl_cfg80211_down(void);	/* dongle down */
+extern void wl_cfg80211_dbg_level(uint32 level);	/* set dongle debugging level */
+extern void * wl_cfg80211_request_fw(int8 *file_name);	/* request fw /nvram downloading */
+extern int32 wl_cfg80211_read_fw(int8 *buf, uint32 size);	/* read fw image */
+extern void wl_cfg80211_release_fw(void);	/* release fw */
+extern int8 * wl_cfg80211_get_fwname(void); /* get firmware name for the dongle */
+extern int8 * wl_cfg80211_get_nvramname(void); /* get nvram name for the dongle */
+
+#endif /* _wl_cfg80211_h_ */
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index de32e94..2cd629c 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.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: wl_iw.c,v 1.51.4.9.2.6.4.104 2010/04/21 23:21:00 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.13 2010/09/15 03:34:56 Exp $
  */
 
 
@@ -53,11 +53,38 @@
 #define WL_ASSOC(x)
 #define WL_INFORM(x)
 #define WL_WSEC(x)
+#define WL_SCAN(x)
 
 #include <wl_iw.h>
 
 
-#define IW_WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+
+#ifndef IW_ENCODE_ALG_SM4
+#define IW_ENCODE_ALG_SM4 0x20
+#endif
+
+#ifndef IW_AUTH_WAPI_ENABLED
+#define IW_AUTH_WAPI_ENABLED 0x20
+#endif
+
+#ifndef IW_AUTH_WAPI_VERSION_1
+#define IW_AUTH_WAPI_VERSION_1	0x00000008
+#endif
+
+#ifndef IW_AUTH_CIPHER_SMS4
+#define IW_AUTH_CIPHER_SMS4	0x00000020
+#endif
+
+#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
+#define IW_AUTH_KEY_MGMT_WAPI_PSK 4
+#endif
+
+#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
+#define IW_AUTH_KEY_MGMT_WAPI_CERT 8
+#endif
+
+
+#define IW_WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
 
 #include <linux/rtnetlink.h>
 #include <linux/mutex.h>
@@ -82,6 +109,7 @@
 	} while (0)
 
 static int		g_onoff = G_WLAN_SET_ON;
+wl_iw_extra_params_t	 g_wl_iw_params;
 static struct mutex	wl_start_lock;
 static struct mutex	wl_cache_lock;
 
@@ -133,7 +161,9 @@
 static wlc_ssid_t g_ssid;
 
 static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;	
-static volatile uint g_first_broadcast_scan;	
+static volatile uint g_first_broadcast_scan;
+static volatile uint g_first_counter_scans;
+#define MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN 3
 
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
@@ -150,8 +180,10 @@
 #endif 
 
 #if defined(WL_IW_USE_ISCAN)
+#if !defined(CSCAN)
 static void wl_iw_free_ss_cache(void);
 static int   wl_iw_run_ss_cache_timer(int kick_off);
+#endif
 int  wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
 static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len);
 #define ISCAN_STATE_IDLE   0
@@ -178,8 +210,13 @@
 	struct completion sysioc_exited;
 
 	uint32 scan_flag;	
-
+#if defined CSCAN
+	char ioctlbuf[WLC_IOCTL_MEDLEN];
+#else
 	char ioctlbuf[WLC_IOCTL_SMLEN];
+#endif
+	wl_iscan_params_t *iscan_ex_params_p;
+	int iscan_ex_param_size;
 } iscan_info_t;
 #define COEX_DHCP 1 
 static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
@@ -222,6 +259,8 @@
 	union iwreq_data *wrqu,
 	char *extra
 );
+
+#ifndef CSCAN
 static int
 wl_iw_get_scan(
 	struct net_device *dev,
@@ -237,7 +276,7 @@
 	char *extra,
 	short max_size
 );
-
+#endif
 
 static void swap_key_from_BE(
 	        wl_wsec_key_t *key
@@ -283,7 +322,9 @@
 		return ret;
 	}
 
-	WL_TRACE(("%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
+	net_os_wake_lock(dev);
+
+	WL_INFORM(("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
 		__FUNCTION__, current->pid, cmd, arg, len));
 
 	if (g_onoff == G_WLAN_SET_ON) {
@@ -298,6 +339,7 @@
 		ret = dev_open(dev);
 		if (ret) {
 			WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret));
+			net_os_wake_unlock(dev);
 			return ret;
 		}
 
@@ -311,8 +353,11 @@
 		set_fs(fs);
 	}
 	else {
-		WL_TRACE(("%s: call after driver stop\n", __FUNCTION__));
+		WL_TRACE(("%s: call after driver stop : ignored\n", __FUNCTION__));
 	}
+
+	net_os_wake_unlock(dev);
+
 	return ret;
 }
 
@@ -388,6 +433,9 @@
 	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
 	ASSERT(iolen);
 
+	if (iolen == 0)
+		return 0;
+
 	return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
 }
 
@@ -624,15 +672,21 @@
 
 		dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm));
 		dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
-	}
-	else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
+
+		/* Disable packet filtering if necessary */
+		net_os_set_packet_filter(dev, 0);
+
+	} else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
 
 		WL_TRACE(("%s: DHCP session done\n", __FUNCTION__));
 
 		dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
-	}
-	else {
-		WL_TRACE(("Unkwown yet power setting, ignored\n"));
+
+		/* Enable packet filtering if was turned off */
+		net_os_set_packet_filter(dev, 1);
+
+	} else {
+		WL_ERROR(("Unkwown yet power setting, ignored\n"));
 	}
 
 	p += snprintf(p, MAX_WX_STRING, "OK");
@@ -644,6 +698,35 @@
 #endif
 
 static int
+wl_iw_get_power_mode(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int error;
+	char *p = extra;
+	int pm_local = PM_FAST;
+
+	error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local));
+	if (!error) {
+		WL_TRACE(("%s: Powermode = %d\n", __func__, pm_local));
+		if (pm_local == PM_OFF)
+			pm_local = 1; /* Active */
+		else
+			pm_local = 0; /* Auto */
+		p += snprintf(p, MAX_WX_STRING, "powermode = %d", pm_local);
+	}
+	else {
+		WL_TRACE(("%s: Error = %d\n", __func__, error));
+		p += snprintf(p, MAX_WX_STRING, "FAIL");
+	}
+	wrqu->data.length = p - extra + 1;
+	return error;
+}
+
+static int
 wl_iw_set_btcoex_dhcp(
 	struct net_device *dev,
 	struct iw_request_info *info,
@@ -768,6 +851,36 @@
 	return error;
 }
 
+static int
+wl_iw_set_suspend(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int suspend_flag;
+	int ret_now;
+	int ret = 0;
+
+	suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0';
+
+	if (suspend_flag != 0)
+		suspend_flag = 1;
+
+	ret_now = net_os_set_suspend_disable(dev, suspend_flag);
+
+	if (ret_now != suspend_flag) {
+		if (!(ret = net_os_set_suspend(dev, ret_now)))
+			WL_ERROR(("%s: Suspend Flag %d -> %d\n", \
+					__FUNCTION__, ret_now, suspend_flag));
+		else
+			WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
+	}
+
+	return ret;
+}
+
 int
 wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
 {
@@ -804,7 +917,7 @@
 	char *p = extra;
 	static int link_speed;
 
-	
+	net_os_wake_lock(dev);
 	if (g_onoff == G_WLAN_SET_ON) {
 		error = dev_wlc_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed));
 		link_speed *= 500000;
@@ -814,9 +927,356 @@
 
 	wrqu->data.length = p - extra + 1;
 
+	net_os_wake_unlock(dev);
 	return error;
 }
 
+
+static int
+wl_iw_get_dtim_skip(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int error = -1;
+	char *p = extra;
+	char iovbuf[32];
+
+	net_os_wake_lock(dev);
+	if (g_onoff == G_WLAN_SET_ON) {
+
+			memset(iovbuf, 0, sizeof(iovbuf));
+			strcpy(iovbuf, "bcn_li_dtim");
+
+			if ((error = dev_wlc_ioctl(dev, WLC_GET_VAR,
+				&iovbuf, sizeof(iovbuf))) >= 0) {
+
+				p += snprintf(p, MAX_WX_STRING, "Dtim_skip %d", iovbuf[0]);
+				WL_TRACE(("%s: get dtim_skip = %d\n", __FUNCTION__, iovbuf[0]));
+				wrqu->data.length = p - extra + 1;
+			}
+			else
+				WL_ERROR(("%s: get dtim_skip failed code %d\n", \
+					__FUNCTION__, error));
+	}
+	net_os_wake_unlock(dev);
+	return error;
+}
+
+
+static int
+wl_iw_set_dtim_skip(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int error = -1;
+	char *p = extra;
+	int bcn_li_dtim;
+	char iovbuf[32];
+
+	net_os_wake_lock(dev);
+	if (g_onoff == G_WLAN_SET_ON) {
+
+		bcn_li_dtim = htod32((uint)*(extra + strlen(DTIM_SKIP_SET_CMD) + 1) - '0');
+
+		if ((bcn_li_dtim >= 0) || ((bcn_li_dtim <= 5))) {
+
+			memset(iovbuf, 0, sizeof(iovbuf));
+			bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+				4, iovbuf, sizeof(iovbuf));
+
+			if ((error = dev_wlc_ioctl(dev, WLC_SET_VAR,
+				&iovbuf, sizeof(iovbuf))) >= 0) {
+				p += snprintf(p, MAX_WX_STRING, "OK");
+
+				net_os_set_dtim_skip(dev, bcn_li_dtim);
+
+				WL_TRACE(("%s: set dtim_skip %d OK\n", __FUNCTION__, \
+					bcn_li_dtim));
+				goto exit;
+			}
+			else  WL_ERROR(("%s: set dtim_skip %d failed code %d\n", \
+				__FUNCTION__, bcn_li_dtim, error));
+		}
+		else  WL_ERROR(("%s Incorrect dtim_skip setting %d, ignored\n", \
+			__FUNCTION__, bcn_li_dtim));
+	}
+
+	p += snprintf(p, MAX_WX_STRING, "FAIL");
+
+exit:
+	wrqu->data.length = p - extra + 1;
+	net_os_wake_unlock(dev);
+	return error;
+}
+
+
+static int
+wl_iw_get_band(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int error = -1;
+	char *p = extra;
+	static int band;
+
+	net_os_wake_lock(dev);
+
+	if (g_onoff == G_WLAN_SET_ON) {
+		error = dev_wlc_ioctl(dev, WLC_GET_BAND, &band, sizeof(band));
+
+		p += snprintf(p, MAX_WX_STRING, "Band %d", band);
+
+		wrqu->data.length = p - extra + 1;
+	}
+
+	net_os_wake_unlock(dev);
+	return error;
+}
+
+
+static int
+wl_iw_set_band(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int error = -1;
+	char *p = extra;
+	uint band;
+
+	net_os_wake_lock(dev);
+
+	if (g_onoff == G_WLAN_SET_ON) {
+
+		band = htod32((uint)*(extra + strlen(BAND_SET_CMD) + 1) - '0');
+
+		if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
+
+			
+			if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND,
+				&band, sizeof(band))) >= 0) {
+				p += snprintf(p, MAX_WX_STRING, "OK");
+				WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band));
+				goto exit;
+			}
+			else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \
+					band, error));
+		}
+		else WL_ERROR(("%s Incorrect band setting %d, ignored\n", __FUNCTION__, band));
+	}
+
+	p += snprintf(p, MAX_WX_STRING, "FAIL");
+
+exit:
+	wrqu->data.length = p - extra + 1;
+	net_os_wake_unlock(dev);
+	return error;
+}
+
+#ifdef PNO_SUPPORT
+
+static int
+wl_iw_set_pno_reset(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int error = -1;
+	char *p = extra;
+
+	net_os_wake_lock(dev);
+	if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
+
+		if ((error = dhd_dev_pno_reset(dev)) >= 0) {
+				p += snprintf(p, MAX_WX_STRING, "OK");
+				WL_TRACE(("%s: set OK\n", __FUNCTION__));
+				goto exit;
+		}
+		else  WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
+	}
+
+	p += snprintf(p, MAX_WX_STRING, "FAIL");
+
+exit:
+	wrqu->data.length = p - extra + 1;
+	net_os_wake_unlock(dev);
+	return error;
+}
+
+
+
+static int
+wl_iw_set_pno_enable(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int error = -1;
+	char *p = extra;
+	int pfn_enabled;
+
+	net_os_wake_lock(dev);
+	pfn_enabled = htod32((uint)*(extra + strlen(PNOENABLE_SET_CMD) + 1) - '0');
+
+	if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
+
+		if ((error = dhd_dev_pno_enable(dev, pfn_enabled)) >= 0) {
+				p += snprintf(p, MAX_WX_STRING, "OK");
+				WL_TRACE(("%s: set OK\n", __FUNCTION__));
+				goto exit;
+		}
+		else  WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
+	}
+
+	p += snprintf(p, MAX_WX_STRING, "FAIL");
+
+exit:
+	wrqu->data.length = p - extra + 1;
+	net_os_wake_unlock(dev);
+	return error;
+}
+
+
+
+static int
+wl_iw_set_pno_set(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int res = -1;
+	wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+	int nssid = 0;
+	cmd_tlv_t *cmd_tlv_temp;
+	char type;
+	char *str_ptr;
+	int tlv_size_left;
+	int pno_time;
+
+#ifdef PNO_SET_DEBUG
+	int i;
+	char pno_in_example[] = {'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ', \
+							'S', 0x01, 0x01, 0x00,
+							'S',
+							0x04,
+							'B', 'R', 'C', 'M',
+							'S',
+							0x04,
+							'G', 'O', 'O', 'G',
+							'T',
+							0x00,
+							0x0A
+							};
+#endif
+
+	net_os_wake_lock(dev);
+	WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
+		__FUNCTION__, info->cmd, info->flags,
+		wrqu->data.pointer, wrqu->data.length));
+
+	if (g_onoff == G_WLAN_SET_OFF) {
+		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+		goto exit_proc;
+	}
+
+	if (wrqu->data.length < (strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t))) {
+		WL_ERROR(("%s aggument=%d  less %d\n", __FUNCTION__, \
+			wrqu->data.length, strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t)));
+		goto exit_proc;
+	}
+
+#ifdef PNO_SET_DEBUG
+	if (!(extra = kmalloc(sizeof(pno_in_example) +100, GFP_KERNEL))) {
+		res = -ENOMEM;
+		goto exit_proc;
+	}
+	memcpy(extra, pno_in_example, sizeof(pno_in_example));
+	wrqu->data.length = sizeof(pno_in_example);
+	for (i = 0; i < wrqu->data.length; i++)
+		printf("%02X ", extra[i]);
+	printf("\n");
+#endif
+
+	str_ptr = extra;
+#ifdef PNO_SET_DEBUG
+	str_ptr +=  strlen("PNOSETUP ");
+	tlv_size_left = wrqu->data.length - strlen("PNOSETUP ");
+#else
+	str_ptr +=  strlen(PNOSETUP_SET_CMD);
+	tlv_size_left = wrqu->data.length - strlen(PNOSETUP_SET_CMD);
+#endif
+
+	cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
+	memset(ssids_local, 0, sizeof(ssids_local));
+
+	if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && \
+		(cmd_tlv_temp->version == PNO_TLV_VERSION) && \
+		(cmd_tlv_temp->subver == PNO_TLV_SUBVERSION))
+	{
+		str_ptr += sizeof(cmd_tlv_t);
+		tlv_size_left  -= sizeof(cmd_tlv_t);
+
+		if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \
+				MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
+			WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
+			goto exit_proc;
+		}
+		else {
+			while (tlv_size_left > 0)
+			{
+				type = str_ptr[0];
+				switch (type) {
+					case PNO_TLV_TYPE_TIME:
+
+					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+						&pno_time, \
+						sizeof(pno_time), \
+						type, sizeof(short), &tlv_size_left)) == -1) {
+							WL_ERROR(("%s return %d\n", \
+							__FUNCTION__, res));
+							goto exit_proc;
+					}
+					break;
+
+					default:
+						WL_ERROR(("%s get unkwown type %X\n", \
+							__FUNCTION__, type));
+						goto exit_proc;
+					break;
+				}
+			}
+		}
+	}
+	else {
+		WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
+		goto exit_proc;
+	}
+
+	res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time);
+
+exit_proc:
+	net_os_wake_unlock(dev);
+	return res;
+}
+#endif
+
 static int
 wl_iw_get_rssi(
 	struct net_device *dev,
@@ -832,12 +1292,15 @@
 	static char ssidbuf[SSID_FMT_BUF_LEN];
 	scb_val_t scb_val;
 
+	net_os_wake_lock(dev);
+
 	bzero(&scb_val, sizeof(scb_val_t));
 
 	if (g_onoff == G_WLAN_SET_ON) {
 		error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
 		if (error) {
 			WL_ERROR(("%s: Fails %d\n", __FUNCTION__, error));
+			net_os_wake_unlock(dev);
 			return error;
 		}
 		rssi = dtoh32(scb_val.val);
@@ -852,10 +1315,11 @@
 	p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
 	wrqu->data.length = p - extra + 1;
 
+	net_os_wake_unlock(dev);
 	return error;
 }
 
-static int
+int
 wl_iw_send_priv_event(
 	struct net_device *dev,
 	char *flag
@@ -873,6 +1337,7 @@
 	strcpy(extra, flag);
 	wrqu.data.length = strlen(extra);
 	wireless_send_event(dev, cmd, &wrqu, extra);
+	net_os_wake_lock_timeout_enable(dev);
 	WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
 
 	return 0;
@@ -946,25 +1411,28 @@
 		dhd_dev_reset(dev, 1);
 
 #if defined(WL_IW_USE_ISCAN)
+#if !defined(CSCAN)
 		wl_iw_free_ss_cache();
 		wl_iw_run_ss_cache_timer(0);
-		memset(g_scan, 0, G_SCAN_RESULTS);
 
 		g_ss_cache_ctrl.m_link_down = 1;
+#endif
+		memset(g_scan, 0, G_SCAN_RESULTS);
 		g_scan_specified_ssid = 0;
 
 		g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
+		g_first_counter_scans = 0;
 #endif
 
 #if defined(BCMLXSDMMC)
 		sdioh_stop(NULL);
 #endif
 
+		net_os_set_dtim_skip(dev, 0);
+
 		dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
 
 		wl_iw_send_priv_event(dev, "STOP");
-
-		net_os_wake_lock_timeout_enable(dev);
 	}
 
 	mutex_unlock(&wl_start_lock);
@@ -996,8 +1464,6 @@
 	wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
 #endif
 
-	net_os_wake_lock_timeout_enable(dev);
-
 	WL_TRACE(("Exited %s \n", __FUNCTION__));
 
 	return ret;
@@ -1153,28 +1619,6 @@
 
 
 #ifdef SOFTAP
-void print_buf(void *pbuf, int len, int bytes_per_line)
-{
-	int i, j = 0;
-	unsigned char *buf = pbuf;
-
-	if (bytes_per_line == 0) {
-		bytes_per_line = len;
-	}
-
-	for (i = 0; i < len; i++) {
-		WL_SOFTAP(("%2.2x", *buf++));
-		j++;
-		if (j == bytes_per_line) {
-			WL_SOFTAP(("\n"));
-			j = 0;
-		} else {
-			WL_SOFTAP((":"));
-		}
-	}
-	WL_SOFTAP(("\n"));
-}
-
 static int iwpriv_get_assoc_list(struct net_device *dev,
 		struct iw_request_info *info,
 		union iwreq_data *p_iwrq,
@@ -1431,6 +1875,7 @@
 	if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
 		return error;
 
+	g_wl_iw_params.target_channel = chan;
 	
 	return -EINPROGRESS;
 }
@@ -1451,7 +1896,6 @@
 	if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
 		return error;
 
-	
 	fwrq->m = dtoh32(ci.hw_channel);
 	fwrq->e = dtoh32(0);
 	return 0;
@@ -1525,9 +1969,9 @@
 )
 {
 	struct iw_range *range = (struct iw_range *) extra;
-	int channels[MAXCHANNEL+1];
-	wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
+	wl_uint32_list_t *list;
 	wl_rateset_t rateset;
+	int8 *channels;
 	int error, i, k;
 	uint sf, ch;
 
@@ -1545,14 +1989,23 @@
 	if (!extra)
 		return -EINVAL;
 
+	channels = kmalloc((MAXCHANNEL+1)*4, GFP_KERNEL);
+	if (!channels) {
+		WL_ERROR(("Could not alloc channels\n"));
+		return -ENOMEM;
+	}
+	list = (wl_uint32_list_t *)channels;
+
 	dwrq->length = sizeof(struct iw_range);
 	memset(range, 0, sizeof(range));
 
 	range->min_nwid = range->max_nwid = 0;
 
 	list->count = htod32(MAXCHANNEL);
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
+	if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4))) {
+		kfree(channels);
 		return error;
+	}
 	for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
 		range->freq[i].i = dtoh32(list->element[i]);
 
@@ -1584,8 +2037,10 @@
 	range->avg_qual.noise = 0x100 - 75;	
 #endif 
 
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+	if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) {
+		kfree(channels);
 		return error;
+	}
 	rateset.count = dtoh32(rateset.count);
 	range->num_bitrates = rateset.count;
 	for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
@@ -1620,8 +2075,10 @@
 		}
 	}
 
-	if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
+	if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) {
+		kfree(channels);
 		return error;
+	}
 	i = dtoh32(i);
 	if (i == WLC_PHY_TYPE_A)
 		range->throughput = 24000000;	
@@ -1690,6 +2147,8 @@
 #endif
 #endif 
 
+	kfree(channels);
+
 	return 0;
 }
 
@@ -1764,6 +2223,41 @@
 	return 0;
 }
 
+
+static int
+wl_iw_ch_to_chanspec(int ch, wl_join_params_t *join_params, int *join_params_size)
+{
+	chanspec_t chanspec = 0;
+
+	if (ch != 0) {
+
+		join_params->params.chanspec_num = 1;
+		join_params->params.chanspec_list[0] = ch;
+
+		if (join_params->params.chanspec_list[0])
+			chanspec |= WL_CHANSPEC_BAND_2G;
+		else
+			chanspec |= WL_CHANSPEC_BAND_5G;
+
+		chanspec |= WL_CHANSPEC_BW_20;
+		chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+
+		*join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
+			join_params->params.chanspec_num * sizeof(chanspec_t);
+
+		join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
+		join_params->params.chanspec_list[0] |= chanspec;
+		join_params->params.chanspec_list[0] =
+		        htodchanspec(join_params->params.chanspec_list[0]);
+
+		join_params->params.chanspec_num = htod32(join_params->params.chanspec_num);
+
+		WL_TRACE(("%s  join_params->params.chanspec_list[0]= %X\n", \
+			__FUNCTION__, join_params->params.chanspec_list[0]));
+	}
+	return 1;
+}
+
 static int
 wl_iw_set_wap(
 	struct net_device *dev,
@@ -1774,6 +2268,7 @@
 {
 	int error = -EINVAL;
 	wl_join_params_t join_params;
+	int join_params_size;
 
 	WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
 
@@ -1795,16 +2290,26 @@
 
 	
 	memset(&join_params, 0, sizeof(join_params));
+	join_params_size = sizeof(join_params.ssid);
 
 	memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
 	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
 	memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN);
 
-	if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, sizeof(join_params)))) {
-		WL_ERROR(("Invalid ioctl data.\n"));
+	WL_TRACE(("%s  target_channel=%d\n", __FUNCTION__, g_wl_iw_params.target_channel));
+	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
+
+	if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
+		WL_ERROR(("%s Invalid ioctl data=%d\n", __FUNCTION__, error));
 		return error;
 	}
 
+	if (g_ssid.SSID_len) {
+		WL_TRACE(("%s: join SSID=%s BSSID="MACSTR" ch=%d\n", __FUNCTION__,  \
+			g_ssid.SSID, MAC2STR((u8 *)awrq->sa_data), \
+			g_wl_iw_params.target_channel));
+	}
+
 	
 	memset(&g_ssid, 0, sizeof(g_ssid));
 	return 0;
@@ -1871,6 +2376,7 @@
 }
 #endif 
 
+#ifndef WL_IW_USE_ISCAN
 static int
 wl_iw_get_aplist(
 	struct net_device *dev,
@@ -1946,6 +2452,7 @@
 	}
 	return 0;
 }
+#endif
 
 #ifdef WL_IW_USE_ISCAN
 static int
@@ -1971,7 +2478,8 @@
 		return -EINVAL;
 
 	if ((!iscan) || (iscan->sysioc_pid < 0)) {
-		return wl_iw_get_aplist(dev, info, dwrq, extra);
+		WL_ERROR(("%s error\n", __FUNCTION__));
+		return 0;
 	}
 
 	buf = iscan->list_hdr;
@@ -2048,35 +2556,26 @@
 static int
 wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
 {
-	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
-	wl_iscan_params_t *params;
 	int err = 0;
 
-	WL_TRACE(("%s: start\n", __func__));
+	iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
+	iscan->iscan_ex_params_p->action = htod16(action);
+	iscan->iscan_ex_params_p->scan_duration = htod16(0);
 
-	if (ssid && ssid->SSID_len) {
-		params_size += sizeof(wlc_ssid_t);
-	}
-	params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
-	if (params == NULL) {
-		return -ENOMEM;
-	}
-	memset(params, 0, params_size);
-	ASSERT(params_size < WLC_IOCTL_SMLEN);
+	WL_SCAN(("%s : nprobes=%d\n", __FUNCTION__, iscan->iscan_ex_params_p->params.nprobes));
+	WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
+	WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
+	WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
+	WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
+	WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type));
 
-	err = wl_iw_iscan_prep(&params->params, ssid);
-
-	if (!err) {
-		params->version = htod32(ISCAN_REQ_VERSION);
-		params->action = htod16(action);
-		params->scan_duration = htod16(0);
-
-		
-		(void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
-			iscan->ioctlbuf, WLC_IOCTL_SMLEN);
+	
+	if ((err = dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \
+		iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
+			WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
+			err = -1;
 	}
 
-	kfree(params);
 	return err;
 }
 
@@ -2087,7 +2586,7 @@
 	if (iscan) {
 		iscan->timer_on = 0;
 		if (iscan->iscan_state != ISCAN_STATE_IDLE) {
-			WL_TRACE(("timer trigger\n"));
+			WL_SCAN(("timer trigger\n"));
 			up(&iscan->sysioc_sem);
 		}
 	}
@@ -2113,6 +2612,7 @@
 	wl_iscan_results_t list;
 	wl_scan_results_t *results;
 	uint32 status;
+	int res;
 
 	mutex_lock(&wl_cache_lock);
 	if (iscan->list_cur) {
@@ -2147,20 +2647,25 @@
 
 	memset(&list, 0, sizeof(list));
 	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
-	(void) dev_iw_iovar_getbuf(
+	res = dev_iw_iovar_getbuf(
 		iscan->dev,
 		"iscanresults",
 		&list,
 		WL_ISCAN_RESULTS_FIXED_SIZE,
 		buf->iscan_buf,
 		WLC_IW_ISCAN_MAXLEN);
-	results->buflen = dtoh32(results->buflen);
-	results->version = dtoh32(results->version);
-	results->count = dtoh32(results->count);
-	WL_TRACE(("results->count = %d\n", results->count));
+	if (res == 0) {
+		results->buflen = dtoh32(results->buflen);
+		results->version = dtoh32(results->version);
+		results->count = dtoh32(results->count);
+		WL_SCAN(("results->count = %d\n", results->count));
 
-	WL_TRACE(("results->buflen = %d\n", results->buflen));
-	status = dtoh32(list_buf->status);
+		WL_SCAN(("results->buflen = %d\n", results->buflen));
+		status = dtoh32(list_buf->status);
+	} else {
+		WL_ERROR(("%s returns error %d\n", __FUNCTION__, res));
+		status = WL_SCAN_RESULTS_NO_MEM;
+	}
 	mutex_unlock(&wl_cache_lock);
 	return status;
 }
@@ -2203,13 +2708,15 @@
 	status = WL_SCAN_RESULTS_PARTIAL;
 	while (down_interruptible(&iscan->sysioc_sem) == 0) {
 
+		net_os_wake_lock(iscan->dev);
+
 #if defined(SOFTAP)
 		if (ap_cfg_running) {
-			WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
+			WL_SCAN(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
+			net_os_wake_unlock(iscan->dev);
 			continue;
 		}
 #endif
-		net_os_wake_lock(iscan->dev);
 
 		if (iscan->timer_on) {
 			iscan->timer_on = 0;
@@ -2225,7 +2732,7 @@
 #endif
 
 		if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
-			WL_TRACE(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
+			WL_SCAN(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
 			wl_iw_send_scan_complete(iscan);
 			iscan_pass_abort = FALSE;
 			status  = -1;
@@ -2233,7 +2740,7 @@
 
 		switch (status) {
 			case WL_SCAN_RESULTS_PARTIAL:
-				WL_TRACE(("iscanresults incomplete\n"));
+				WL_SCAN(("iscanresults incomplete\n"));
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 				rtnl_lock();
 #endif
@@ -2247,18 +2754,18 @@
 				iscan->timer_on = 1;
 				break;
 			case WL_SCAN_RESULTS_SUCCESS:
-				WL_TRACE(("iscanresults complete\n"));
+				WL_SCAN(("iscanresults complete\n"));
 				iscan->iscan_state = ISCAN_STATE_IDLE;
 				wl_iw_send_scan_complete(iscan);
 				break;
 			case WL_SCAN_RESULTS_PENDING:
-				WL_TRACE(("iscanresults pending\n"));
+				WL_SCAN(("iscanresults pending\n"));
 
 				mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
 				iscan->timer_on = 1;
 				break;
 			case WL_SCAN_RESULTS_ABORTED:
-				WL_TRACE(("iscanresults aborted\n"));
+				WL_SCAN(("iscanresults aborted\n"));
 				iscan->iscan_state = ISCAN_STATE_IDLE;
 				if (g_scan_specified_ssid == 0)
 					wl_iw_send_scan_complete(iscan);
@@ -2268,11 +2775,11 @@
 				}
 				break;
 			case WL_SCAN_RESULTS_NO_MEM:
-				WL_TRACE(("iscanresults can't alloc memory: skip\n"));
+				WL_SCAN(("iscanresults can't alloc memory: skip\n"));
 				iscan->iscan_state = ISCAN_STATE_IDLE;
 				break;
 			default:
-				WL_TRACE(("iscanresults returned unknown status %d\n", status));
+				WL_SCAN(("iscanresults returned unknown status %d\n", status));
 				break;
 		}
 
@@ -2288,6 +2795,7 @@
 }
 #endif 
 
+#if !defined(CSCAN)
 
 static void
 wl_iw_set_ss_cache_timer_flag(void)
@@ -2453,18 +2961,14 @@
 		if (node) {
 			continue;
 		}
-		leaf = kmalloc(WLC_IW_SS_CACHE_MAXLEN, GFP_KERNEL);
+		leaf = kmalloc(bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
 		if (!leaf) {
+			WL_ERROR(("Memory alloc failure %d\n", \
+				bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
 			mutex_unlock(&wl_cache_lock);
 			return -ENOMEM;
 		}
 
-		if (bi->length > WLC_IW_BSS_INFO_MAXLEN) {
-			WL_TRACE(("bss info length is too long : %d\n", bi->length));
-			kfree(leaf);
-			continue;
-		}
-
 		memcpy(leaf->bss_info, bi, bi->length);
 		leaf->next = NULL;
 		leaf->dirty = 1;
@@ -2544,6 +3048,7 @@
 	return 0;
 }
 
+#endif
 
 
 static int
@@ -2557,6 +3062,11 @@
 	int error;
 	WL_TRACE(("%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name));
 
+#if defined(CSCAN)
+	WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
+	return -EINVAL;
+#endif 
+
 #if defined(SOFTAP)
 	if (ap_cfg_running) {
 		WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
@@ -2603,7 +3113,7 @@
 	
 	if ((error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)))) {
 		WL_TRACE(("#### Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error));
-		g_scan_specified_ssid = 0; /* Clean to allow future ISCAN */
+		g_scan_specified_ssid = 0;
 		return -EBUSY;
 	}
 
@@ -2626,11 +3136,6 @@
 		return 0;
 	}
 
-	memset(&ssid, 0, sizeof(ssid));
-
-	iscan->list_cur = iscan->list_hdr;
-	iscan->iscan_state = ISCAN_STATE_SCANING;
-
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 	if (flag)
 		rtnl_lock();
@@ -2640,7 +3145,14 @@
 	wl_iw_set_event_mask(dev);
 
 	WL_TRACE(("+++: Set Broadcast ISCAN\n"));
+	
+	memset(&ssid, 0, sizeof(ssid));
 
+	iscan->list_cur = iscan->list_hdr;
+	iscan->iscan_state = ISCAN_STATE_SCANING;
+
+	memset(&iscan->iscan_ex_params_p->params, 0, iscan->iscan_ex_param_size);
+	wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid);
 	wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
@@ -2654,6 +3166,7 @@
 
 	return 0;
 }
+
 static int
 wl_iw_iscan_set_scan(
 	struct net_device *dev,
@@ -2664,31 +3177,45 @@
 {
 	wlc_ssid_t ssid;
 	iscan_info_t *iscan = g_iscan;
+	int ret = 0;
 
 	WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
 
+#if defined(CSCAN)
+	WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
+	return -EINVAL;
+#endif
+
+	net_os_wake_lock(dev);
+
 #if defined(SOFTAP)
 	if (ap_cfg_running) {
 		WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
-		return 0;
+		goto set_scan_end;
 	}
 #endif
 
 	if (g_onoff == G_WLAN_SET_OFF) {
 		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
-		return 0;
+		goto set_scan_end;
 	}
 
+#ifdef PNO_SUPPORT
+	if  (dhd_dev_get_pno_status(dev)) {
+		WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
+	}
+#endif
+
 	if ((!iscan) || (iscan->sysioc_pid < 0)) {
-		WL_TRACE(("%s use backup if iscan thread is not successful\n", \
-			 __FUNCTION__));
-		return wl_iw_set_scan(dev, info, wrqu, extra);
+		WL_ERROR(("%s error\n", __FUNCTION__));
+		goto set_scan_end;
 	}
 
 	if (g_scan_specified_ssid) {
 		WL_TRACE(("%s Specific SCAN already running ignoring BC scan\n", \
 				__FUNCTION__));
-		return EBUSY;
+		ret = EBUSY;
+		goto set_scan_end;
 	}
 
 	memset(&ssid, 0, sizeof(ssid));
@@ -2699,32 +3226,47 @@
 		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
 			int as = 0;
 			struct iw_scan_req *req = (struct iw_scan_req *)extra;
-			if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
-				WL_TRACE(("%s First ISCAN in progress : ignoring SC = %s\n", \
-					 __FUNCTION__, req->essid));
-				return -EBUSY;
-			}
 			ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
 			memcpy(ssid.SSID, req->essid, ssid.SSID_len);
 			ssid.SSID_len = htod32(ssid.SSID_len);
 			dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
 			wl_iw_set_event_mask(dev);
-			return wl_iw_set_scan(dev, info, wrqu, extra);
+			ret = wl_iw_set_scan(dev, info, wrqu, extra);
+			goto set_scan_end;
 		}
 		else {
 			g_scan_specified_ssid = 0;
 
 			if (iscan->iscan_state == ISCAN_STATE_SCANING) {
 				WL_TRACE(("%s ISCAN already in progress \n", __FUNCTION__));
-				return 0;
+				goto set_scan_end;
 			}
 		}
 	}
 #endif 
 
+#if !defined(CSCAN)
+	if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
+		if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
+
+			WL_ERROR(("%s Clean up First scan flag which is %d\n", \
+				 __FUNCTION__, g_first_broadcast_scan));
+			g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
+		}
+		else {
+			WL_ERROR(("%s Ignoring Broadcast Scan:First Scan is not done yet %d\n", \
+					__FUNCTION__, g_first_counter_scans));
+			ret = -EBUSY;
+			goto set_scan_end;
+		}
+	}
+#endif
+
 	wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
 
-	return 0;
+set_scan_end:
+	net_os_wake_unlock(dev);
+	return ret;
 }
 #endif 
 
@@ -2766,6 +3308,32 @@
 }
 #endif 
 
+static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
+	size_t len, int uppercase)
+{
+	size_t i;
+	char *pos = buf, *end = buf + buf_size;
+	int ret;
+	if (buf_size == 0)
+		return 0;
+	for (i = 0; i < len; i++) {
+		ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
+			data[i]);
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return pos - buf;
+		}
+		pos += ret;
+	}
+	end[-1] = '\0';
+	return pos - buf;
+}
+
+
+int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
+{
+	return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
+}
 
 static int
 wl_iw_handle_scanresults_ies(char **event_p, char *end,
@@ -2774,6 +3342,8 @@
 #if WIRELESS_EXT > 17
 	struct iw_event	iwe;
 	char *event;
+	char *buf;
+	int custom_event_len;
 
 	event = *event_p;
 	if (bi->ie_length) {
@@ -2812,6 +3382,35 @@
 			}
 		}
 
+		ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+		ptr_len = bi->ie_length;
+
+		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) {
+			WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__));
+#ifdef WAPI_IE_USE_GENIE
+			iwe.cmd = IWEVGENIE;
+			iwe.u.data.length = ie->len + 2;
+			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+#else 
+			iwe.cmd = IWEVCUSTOM;
+			custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2);
+			iwe.u.data.length = custom_event_len;
+
+			buf = kmalloc(custom_event_len+1, GFP_KERNEL);
+			if (buf == NULL)
+			{
+				WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len));
+				break;
+			}
+
+			memcpy(buf, "wapi_ie=", 8);
+			wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1);
+			wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
+			wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
+			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
+#endif 
+			break;
+		}
 	*event_p = event;
 	}
 #endif 
@@ -2819,6 +3418,7 @@
 	return 0;
 }
 
+#ifndef CSCAN
 static uint
 wl_iw_get_scan_prep(
 	wl_scan_results_t *list,
@@ -2931,12 +3531,16 @@
 	uint buflen_from_user = dwrq->length;
 	uint len =  G_SCAN_RESULTS;
 	__u16 len_ret = 0;
+#if !defined(CSCAN)
 	__u16 merged_len = 0;
+#endif
 #if defined(WL_IW_USE_ISCAN)
 	iscan_info_t *iscan = g_iscan;
 	iscan_buf_t * p_buf;
+#if  !defined(CSCAN)
 	uint32 counter = 0;
 #endif
+#endif
 	WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user));
 
 	if (!extra) {
@@ -2951,6 +3555,7 @@
 	if (ci.scan_channel)
 		return -EAGAIN;
 
+#if !defined(CSCAN)
 	if (g_ss_cache_ctrl.m_timer_expired) {
 		wl_iw_free_ss_cache();
 		g_ss_cache_ctrl.m_timer_expired ^= 1;
@@ -2968,7 +3573,7 @@
 	else {
 		g_ss_cache_ctrl.m_cons_br_scan_cnt++;
 	}
-
+#endif
 
 	if (g_scan_specified_ssid) {
 		
@@ -2983,10 +3588,12 @@
 	memset(list, 0, len);
 	list->buflen = htod32(len);
 	if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len))) {
-		WL_TRACE(("%s: %s : Scan_results ERROR %d\n", dev->name, __FUNCTION__, len));
+		WL_ERROR(("%s: %s : Scan_results ERROR %d\n", dev->name, __FUNCTION__, error));
 		dwrq->length = len;
-		if (g_scan_specified_ssid)
+		if (g_scan_specified_ssid) {
+			g_scan_specified_ssid = 0;
 			kfree(list);
+		}
 		return 0;
 	}
 	list->buflen = dtoh32(list->buflen);
@@ -3003,6 +3610,7 @@
 		return -EINVAL;
 	}
 
+#if !defined(CSCAN)
 	if (g_scan_specified_ssid) {
 		
 		wl_iw_add_bss_to_ss_cache(list);
@@ -3038,6 +3646,37 @@
 	len_ret += merged_len;
 	wl_iw_run_ss_cache_timer(0);
 	wl_iw_run_ss_cache_timer(1);
+#else
+
+	if (g_scan_specified_ssid) {
+		WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count));
+		len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
+		kfree(list);
+
+#if defined(WL_IW_USE_ISCAN)
+		p_buf = iscan->list_hdr;
+		
+		while (p_buf != iscan->list_cur) {
+			list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
+			WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
+			if (list_merge->count > 0)
+				len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
+				    extra+len_ret, buflen_from_user -len_ret);
+			p_buf = p_buf->next;
+		}
+#else
+		list_merge = (wl_scan_results_t *) g_scan;
+		WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
+		if (list_merge->count > 0)
+			len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret,
+				buflen_from_user -len_ret);
+#endif
+	}
+	else {
+		list = (wl_scan_results_t *) g_scan;
+		len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
+	}
+#endif
 
 #if defined(WL_IW_USE_ISCAN)
 	
@@ -3053,6 +3692,7 @@
 	WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, list->count));
 	return 0;
 }
+#endif
 
 #if defined(WL_IW_USE_ISCAN)
 static int
@@ -3072,8 +3712,11 @@
 	iscan_info_t *iscan = g_iscan;
 	iscan_buf_t * p_buf;
 	uint32  counter = 0;
+	uint8   channel;
+#if !defined(CSCAN)
 	__u16 merged_len = 0;
 	uint buflen_from_user = dwrq->length;
+#endif
 
 	WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
 
@@ -3094,12 +3737,13 @@
 			 dev->name, __FUNCTION__));
 		return -EAGAIN;
 	}
-	
+
 	if ((!iscan) || (iscan->sysioc_pid < 0)) {
-		WL_TRACE(("%ssysioc_pid\n", __FUNCTION__));
-		return wl_iw_get_scan(dev, info, dwrq, extra);
+		WL_ERROR(("%ssysioc_pid\n", __FUNCTION__));
+		return -EAGAIN;
 	}
 
+#if !defined(CSCAN)
 	if (g_ss_cache_ctrl.m_timer_expired) {
 		wl_iw_free_ss_cache();
 		g_ss_cache_ctrl.m_timer_expired ^= 1;
@@ -3119,6 +3763,7 @@
 		g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
 		g_ss_cache_ctrl.m_cons_br_scan_cnt++;
 	}
+#endif
 
 	WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name));
 	apcnt = 0;
@@ -3169,8 +3814,9 @@
 
 		
 		iwe.cmd = SIOCGIWFREQ;
-		iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
-			CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
+		channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
+		iwe.u.freq.m = wf_channel2mhz(channel,
+			channel <= CH_MAX_2G_CHANNEL ?
 			WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
 		iwe.u.freq.e = 6;
 		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
@@ -3217,18 +3863,16 @@
 	dwrq->length = event - extra;
 	dwrq->flags = 0;	
 
+#if !defined(CSCAN)
 	wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len);
 	dwrq->length += merged_len;
 	wl_iw_run_ss_cache_timer(0);
 	wl_iw_run_ss_cache_timer(1);
-	
+#endif /* CSCAN */
 	g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
 
 	WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
 
-	if (!dwrq->length)
-		return -EAGAIN;
-
 	return 0;
 }
 #endif 
@@ -3242,6 +3886,8 @@
 )
 {
 	int error;
+	wl_join_params_t join_params;
+	int join_params_size;
 
 	WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
 
@@ -3262,11 +3908,24 @@
 		g_ssid.SSID_len = 0;
 	}
 	g_ssid.SSID_len = htod32(g_ssid.SSID_len);
-	if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &g_ssid, sizeof(g_ssid))))
+
+	memset(&join_params, 0, sizeof(join_params));
+	join_params_size = sizeof(join_params.ssid);
+
+	memcpy(&join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
+	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
+	memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
+
+	if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
+		WL_ERROR(("Invalid ioctl data=%d\n", error));
 		return error;
+	}
 
 	if (g_ssid.SSID_len) {
-		WL_TRACE(("%s: join SSID=%s\n", __FUNCTION__,  g_ssid.SSID));
+		WL_TRACE(("%s: join SSID=%s ch=%d\n", __FUNCTION__, \
+			g_ssid.SSID,  g_wl_iw_params.target_channel));
 	}
 	return 0;
 }
@@ -3294,7 +3953,6 @@
 
 	ssid.SSID_len = dtoh32(ssid.SSID_len);
 
-	
 	memcpy(extra, ssid.SSID, ssid.SSID_len);
 
 	dwrq->length = ssid.SSID_len;
@@ -3319,7 +3977,6 @@
 	if (!extra)
 		return -EINVAL;
 
-	
 	if (dwrq->length > sizeof(iw->nickname))
 		return -E2BIG;
 
@@ -3889,11 +4546,21 @@
 	char *extra
 )
 {
+	uchar buf[WLC_IOCTL_SMLEN] = {0};
+	uchar *p = buf;
+	int wapi_ie_size;
 
 	WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
 
 	CHECK_EXTRA_FOR_NULL(extra);
 
+	if (extra[0] == DOT11_MNG_WAPI_ID)
+	{
+		wapi_ie_size = iwp->length;
+		memcpy(p, extra, iwp->length);
+		dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size);
+	}
+	else
 		dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
 
 	return 0;
@@ -4010,6 +4677,12 @@
 			case IW_ENCODE_ALG_CCMP:
 				key.algo = CRYPTO_ALGO_AES_CCM;
 				break;
+			case IW_ENCODE_ALG_SM4:
+				key.algo = CRYPTO_ALGO_SMS4;
+				if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+					key.flags &= ~WL_PRIMARY_KEY;
+				}
+				break;
 			default:
 				break;
 		}
@@ -4193,6 +4866,8 @@
 		else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
 			val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
 #endif 
+		else if (paramval & IW_AUTH_WAPI_VERSION_1)
+			val = WPA_AUTH_WAPI;
 		WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
 		if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
 			return error;
@@ -4207,6 +4882,8 @@
 			val = TKIP_ENABLED;
 		if (paramval & IW_AUTH_CIPHER_CCMP)
 			val = AES_ENABLED;
+		if (paramval & IW_AUTH_CIPHER_SMS4)
+			val = SMS4_ENABLED;
 
 		if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
 			iw->pwsec = val;
@@ -4254,9 +4931,12 @@
 				val = WPA2_AUTH_UNSPECIFIED;
 		}
 #endif 
+		if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT))
+			val = WPA_AUTH_WAPI;
 		WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
 		if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
 			return error;
+
 		break;
 	case IW_AUTH_TKIP_COUNTERMEASURES:
 		dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
@@ -4339,6 +5019,24 @@
 		break;
 	}
 #endif
+	case IW_AUTH_WAPI_ENABLED:
+		if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
+			return error;
+		if (paramval) {
+			val |= SMS4_ENABLED;
+			if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
+				WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n",
+					__FUNCTION__, val, error));
+				return error;
+			}
+			if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WPA_AUTH_WAPI))) {
+				WL_ERROR(("%s: setting wpa_auth(WPA_AUTH_WAPI) returned %d\n",
+					__FUNCTION__, error));
+				return error;
+			}
+		}
+
+		break;
 	default:
 		break;
 	}
@@ -4574,6 +5272,7 @@
 }
 
 
+#ifndef AP_ONLY
 static int wl_bssiovar_mkbuf(
 			const char *iovar,
 			int bssidx,
@@ -4616,6 +5315,7 @@
 	*perr = 0;
 	return iolen;
 }
+#endif 
 
 
 int get_user_params(char *user_params, struct iw_point *dwrq)
@@ -4634,7 +5334,414 @@
 }
 
 
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+
+#if defined(CSCAN)
+
+static int
+wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, int nchan)
+{
+	int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+	int err = 0;
+	char *p;
+	int i;
+	iscan_info_t *iscan = g_iscan;
+
+	WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
+
+	if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) {
+		WL_ERROR(("%s error exit\n", __FUNCTION__));
+		err = -1;
+		goto exit;
+	}
+
+#ifdef PNO_SUPPORT
+	if  (dhd_dev_get_pno_status(dev)) {
+		WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
+	}
+#endif
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+
+	if (nssid > 0) {
+		i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
+		i = ROUNDUP(i, sizeof(uint32));
+		if (i + nssid * sizeof(wlc_ssid_t) > params_size) {
+			printf("additional ssids exceed params_size\n");
+			err = -1;
+			goto exit;
+		}
+
+		p = ((char*)&iscan->iscan_ex_params_p->params) + i;
+		memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t));
+		p += nssid * sizeof(wlc_ssid_t);
+	} else {
+		p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
+	}
+
+	
+	iscan->iscan_ex_params_p->params.channel_num = \
+		htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
+					(nchan & WL_SCAN_PARAMS_COUNT_MASK));
+
+	nssid = \
+	(uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \
+		               WL_SCAN_PARAMS_COUNT_MASK);
+
+	
+	params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t));
+	iscan->iscan_ex_param_size = params_size;
+
+	iscan->list_cur = iscan->list_hdr;
+	iscan->iscan_state = ISCAN_STATE_SCANING;
+	wl_iw_set_event_mask(dev);
+	mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
+
+	iscan->timer_on = 1;
+
+#ifdef SCAN_DUMP
+	{
+		int i;
+		WL_SCAN(("\n### List of SSIDs to scan ###\n"));
+		for (i = 0; i < nssid; i++) {
+			if (!ssids_local[i].SSID_len)
+				WL_SCAN(("%d: Broadcast scan\n", i));
+			else
+			WL_SCAN(("%d: scan  for  %s size =%d\n", i, \
+				ssids_local[i].SSID, ssids_local[i].SSID_len));
+		}
+		WL_SCAN(("### List of channels to scan ###\n"));
+		for (i = 0; i < nchan; i++)
+		{
+			WL_SCAN(("%d ", iscan->iscan_ex_params_p->params.channel_list[i]));
+		}
+		WL_SCAN(("\nnprobes=%d\n", iscan->iscan_ex_params_p->params.nprobes));
+		WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
+		WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
+		WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
+		WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
+		WL_SCAN(("\n###################\n"));
+	}
+#endif 
+
+	if (params_size > WLC_IOCTL_MEDLEN) {
+			WL_ERROR(("Set ISCAN for %s due to params_size=%d  \n", \
+				__FUNCTION__, params_size));
+			err = -1;
+	}
+
+	if ((err = dev_iw_iovar_setbuf(dev, "iscan", iscan->iscan_ex_params_p, \
+			iscan->iscan_ex_param_size, \
+			iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
+			WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
+			err = -1;
+	}
+
+exit:
+
+	return err;
+}
+
+
+static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, \
+				union iwreq_data *wrqu, char *ext)
+{
+	int res = 0;
+	char  *extra = NULL;
+	iscan_info_t *iscan = g_iscan;
+	wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
+	int nssid = 0;
+	int nchan = 0;
+
+	WL_TRACE(("\%s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
+		__FUNCTION__, info->cmd, info->flags,
+		wrqu->data.pointer, wrqu->data.length));
+
+	if (g_onoff == G_WLAN_SET_OFF) {
+		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+		return -1;
+	}
+
+	if (wrqu->data.length != 0) {
+
+		char *str_ptr;
+
+		if (!iscan->iscan_ex_params_p) {
+			return -EFAULT;
+		}
+
+		if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
+			return -ENOMEM;
+
+		if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
+			kfree(extra);
+			return -EFAULT;
+		}
+
+		extra[wrqu->data.length] = 0;
+		WL_ERROR(("Got str param in iw_point:\n %s\n", extra));
+
+		str_ptr = extra;
+
+		if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) {
+			WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__));
+			goto exit_proc;
+		}
+		str_ptr += strlen(GET_SSID);
+		nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \
+						WL_SCAN_PARAMS_SSID_MAX);
+		if (nssid == -1) {
+			WL_ERROR(("%s wrong ssid list", __FUNCTION__));
+			return -1;
+		}
+
+		memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
+		ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN);
+
+		
+		wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
+		iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
+		iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
+		iscan->iscan_ex_params_p->scan_duration = htod16(0);
+
+		
+		if ((nchan = wl_iw_parse_channel_list(&str_ptr, \
+					&iscan->iscan_ex_params_p->params.channel_list[0], \
+					WL_NUMCHANNELS)) == -1) {
+			WL_ERROR(("%s missing channel list\n", __FUNCTION__));
+			return -1;
+		}
+
+		
+		get_parmeter_from_string(&str_ptr, \
+				GET_NPROBE, PTYPE_INTDEC, \
+				&iscan->iscan_ex_params_p->params.nprobes, 2);
+
+		get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC, \
+						&iscan->iscan_ex_params_p->params.active_time, 4);
+
+		get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC, \
+						&iscan->iscan_ex_params_p->params.passive_time, 4);
+
+		get_parmeter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC, \
+					&iscan->iscan_ex_params_p->params.home_time, 4);
+
+		get_parmeter_from_string(&str_ptr, GET_SCAN_TYPE, PTYPE_INTDEC, \
+					&iscan->iscan_ex_params_p->params.scan_type, 1);
+
+		res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
+
+	} else {
+		  WL_ERROR(("IWPRIV argument len = 0 \n"));
+		  return -1;
+	}
+
+exit_proc:
+
+	kfree(extra);
+
+	return res;
+}
+
+
+static int
+wl_iw_set_cscan(
+	struct net_device *dev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra
+)
+{
+	int res = -1;
+	iscan_info_t *iscan = g_iscan;
+	wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
+	int nssid = 0;
+	int nchan = 0;
+	cscan_tlv_t *cscan_tlv_temp;
+	char type;
+	char *str_ptr;
+	int tlv_size_left;
+#ifdef TLV_DEBUG
+	int i;
+	char tlv_in_example[] = {			'C', 'S', 'C', 'A', 'N', ' ', \
+							0x53, 0x01, 0x00, 0x00,
+							'S',	  
+							0x00, 
+							'S',    
+							0x04, 
+							'B', 'R', 'C', 'M',
+							'C',
+							0x06, 
+							'P', 
+							0x94,
+							0x11,
+							'T',     
+							0x01  
+							};
+#endif 
+
+	WL_TRACE(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
+		__FUNCTION__, info->cmd, info->flags,
+		wrqu->data.pointer, wrqu->data.length));
+
+	net_os_wake_lock(dev);
+
+	if (g_onoff == G_WLAN_SET_OFF) {
+		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+		goto exit_proc;
+	}
+
+
+	if (wrqu->data.length < (strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))) {
+		WL_ERROR(("%s aggument=%d  less %d\n", __FUNCTION__, \
+			wrqu->data.length, strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t)));
+		goto exit_proc;
+	}
+
+#ifdef TLV_DEBUG
+	memcpy(extra, tlv_in_example, sizeof(tlv_in_example));
+	wrqu->data.length = sizeof(tlv_in_example);
+	for (i = 0; i < wrqu->data.length; i++)
+		printf("%02X ", extra[i]);
+	printf("\n");
+#endif 
+
+	str_ptr = extra;
+	str_ptr +=  strlen(CSCAN_COMMAND);
+	tlv_size_left = wrqu->data.length - strlen(CSCAN_COMMAND);
+
+	cscan_tlv_temp = (cscan_tlv_t *)str_ptr;
+	memset(ssids_local, 0, sizeof(ssids_local));
+	
+	if ((cscan_tlv_temp->prefix == CSCAN_TLV_PREFIX) && \
+		(cscan_tlv_temp->version == CSCAN_TLV_VERSION) && \
+		(cscan_tlv_temp->subver == CSCAN_TLV_SUBVERSION))
+	{
+		str_ptr += sizeof(cscan_tlv_t);
+		tlv_size_left  -= sizeof(cscan_tlv_t);
+
+		
+		if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \
+				WL_SCAN_PARAMS_SSID_MAX, &tlv_size_left)) <= 0) {
+			WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
+			goto exit_proc;
+		}
+		else {
+			
+			memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
+
+			
+			wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
+			iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
+			iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
+			iscan->iscan_ex_params_p->scan_duration = htod16(0);
+
+			
+			while (tlv_size_left > 0)
+			{
+			type = str_ptr[0];
+			switch (type) {
+				case CSCAN_TLV_TYPE_CHANNEL_IE:
+					
+					if ((nchan = wl_iw_parse_channel_list_tlv(&str_ptr, \
+					&iscan->iscan_ex_params_p->params.channel_list[0], \
+					WL_NUMCHANNELS, &tlv_size_left)) == -1) {
+					WL_ERROR(("%s missing channel list\n", \
+						 __FUNCTION__));
+						goto exit_proc;
+					}
+				break;
+				case CSCAN_TLV_TYPE_NPROBE_IE:
+					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+						&iscan->iscan_ex_params_p->params.nprobes, \
+						sizeof(iscan->iscan_ex_params_p->params.nprobes), \
+						type, sizeof(char), &tlv_size_left)) == -1) {
+						WL_ERROR(("%s return %d\n", \
+							__FUNCTION__, res));
+							goto exit_proc;
+					}
+				break;
+				case CSCAN_TLV_TYPE_ACTIVE_IE:
+					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+					&iscan->iscan_ex_params_p->params.active_time, \
+					sizeof(iscan->iscan_ex_params_p->params.active_time), \
+					type, sizeof(short), &tlv_size_left)) == -1) {
+						WL_ERROR(("%s return %d\n", \
+						__FUNCTION__, res));
+						goto exit_proc;
+					}
+				break;
+				case CSCAN_TLV_TYPE_PASSIVE_IE:
+					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+					&iscan->iscan_ex_params_p->params.passive_time, \
+					sizeof(iscan->iscan_ex_params_p->params.passive_time), \
+					type, sizeof(short), &tlv_size_left)) == -1) {
+						WL_ERROR(("%s return %d\n", \
+						__FUNCTION__, res));
+						goto exit_proc;
+					}
+				break;
+				case CSCAN_TLV_TYPE_HOME_IE:
+					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+					&iscan->iscan_ex_params_p->params.home_time, \
+					sizeof(iscan->iscan_ex_params_p->params.home_time), \
+					type, sizeof(short), &tlv_size_left)) == -1) {
+						WL_ERROR(("%s return %d\n", \
+						__FUNCTION__, res));
+						goto exit_proc;
+					}
+				break;
+				case CSCAN_TLV_TYPE_STYPE_IE:
+					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+					&iscan->iscan_ex_params_p->params.scan_type, \
+					sizeof(iscan->iscan_ex_params_p->params.scan_type), \
+					type, sizeof(char), &tlv_size_left)) == -1) {
+					WL_ERROR(("%s return %d\n", \
+						__FUNCTION__, res));
+						goto exit_proc;
+					}
+				break;
+
+				default :
+					WL_ERROR(("%s get unkwown type %X\n", \
+						__FUNCTION__, type));
+					goto exit_proc;
+				break;
+				}
+			} 
+			}
+		}
+		else {
+			WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
+			goto exit_proc;
+		}
+
+		if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
+			if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
+
+				WL_ERROR(("%s Clean up First scan flag which is %d\n", \
+						 __FUNCTION__, g_first_broadcast_scan));
+				g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
+			}
+			else {
+				WL_ERROR(("%s Ignoring CSCAN : First Scan is not done yet %d\n", \
+						__FUNCTION__, g_first_counter_scans));
+				res = -EBUSY;
+				goto exit_proc;
+			}
+		}
+
+		res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
+
+exit_proc:
+	net_os_wake_unlock(dev);
+	return res;
+}
+
+#endif 
+
 #ifdef SOFTAP
+#ifndef AP_ONLY
 
 static int thr_wait_for_2nd_eth_dev(void *data)
 {
@@ -4670,7 +5777,10 @@
 
 	return ret;
 }
-
+#endif 
+#ifndef AP_ONLY
+static int last_auto_channel = 6;
+#endif
 static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
 {
 	int chosen = 0;
@@ -4681,12 +5791,30 @@
 	int ret = 0;
 	wlc_ssid_t null_ssid;
 	int res = 0;
-
+#ifndef AP_ONLY
+	int iolen = 0;
+	int mkvar_err = 0;
+	int bsscfg_index = 1;
+	char buf[WLC_IOCTL_SMLEN];
+#endif
 	WL_SOFTAP(("Enter %s\n", __FUNCTION__));
+
+#ifndef AP_ONLY
+	if (ap_cfg_running) {
+		ap->channel = last_auto_channel;
+		return res;
+	}
+#endif
 	memset(&null_ssid, 0, sizeof(wlc_ssid_t));
 	res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
+#ifdef AP_ONLY
 	res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
-
+#else
+	iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid), \
+		null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
+	ASSERT(iolen);
+	res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
+#endif
 	auto_channel_retry:
 			request.count = htod32(0);
 			ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
@@ -4716,6 +5844,11 @@
 				WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res));
 				goto fail;
 			}
+#ifndef AP_ONLY
+	if (!res)
+		last_auto_channel = ap->channel;
+#endif
+
 fail :
 	return res;
 }
@@ -4728,21 +5861,23 @@
 
 	wlc_ssid_t ap_ssid;
 	int max_assoc = 8;
-	int mpc = 0;
 
 	int res = 0;
 	int apsta_var = 0;
+#ifndef AP_ONLY
+	int mpc = 0;
 	int iolen = 0;
 	int mkvar_err = 0;
 	int bsscfg_index = 1;
 	char buf[WLC_IOCTL_SMLEN];
+#endif
 
 	if (!dev) {
 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
 		return -1;
 	}
 
-    net_os_wake_lock(dev);
+	net_os_wake_lock(dev);
 
 	WL_SOFTAP(("wl_iw: set ap profile:\n"));
 	WL_SOFTAP(("	ssid = '%s'\n", ap->ssid));
@@ -4752,8 +5887,17 @@
 	WL_SOFTAP(("	channel = %d\n", ap->channel));
 	WL_SOFTAP(("	max scb = %d\n", ap->max_scb));
 
+#ifdef AP_ONLY
+	if (ap_cfg_running) {
+		wl_iw_softap_deassoc_stations(dev);
+		ap_cfg_running = FALSE;
+	}
+#endif	
+
 	if (ap_cfg_running == FALSE) {
 
+#ifndef AP_ONLY
+
 		sema_init(&ap_eth_sema, 0);
 
 		mpc = 0;
@@ -4761,6 +5905,7 @@
 			WL_ERROR(("%s fail to set mpc\n", __FUNCTION__));
 			goto fail;
 		}
+#endif
 
 		updown = 0;
 		if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown)))) {
@@ -4845,6 +5990,15 @@
 	ap_ssid.SSID_len = strlen(ap->ssid);
 	strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
 
+#ifdef AP_ONLY
+	if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
+		WL_ERROR(("ERROR:%d in:%s, wl_iw_set_ap_security is skipped\n", \
+		res, __FUNCTION__));
+		goto fail;
+	}
+	wl_iw_send_priv_event(dev, "ASCII_CMD=AP_BSS_START");
+	ap_cfg_running = TRUE;
+#else
 	iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid),
 		ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
 	ASSERT(iolen);
@@ -4874,12 +6028,13 @@
 			goto fail;
 		}
 	}
+#endif 
 fail:
 	WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res));
 
-    net_os_wake_unlock(dev);
+	net_os_wake_unlock(dev);
 
-    return res;
+	return res;
 }
 
 
@@ -4890,6 +6045,11 @@
 	int res = 0;
 	int i;
 	char *ptr;
+#ifdef AP_ONLY
+	int mpc = 0;
+	wlc_ssid_t ap_ssid;
+#endif
+	wl_wsec_key_t key;
 
 	WL_SOFTAP(("\nsetting SOFTAP security mode:\n"));
 	WL_SOFTAP(("wl_iw: set ap profile:\n"));
@@ -4912,7 +6072,6 @@
 
 	} else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
 
-		wl_wsec_key_t key;
 		memset(&key, 0, sizeof(key));
 
 		wsec = WEP_ENABLED;
@@ -5030,6 +6189,16 @@
 		WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res));
 	}
 
+#ifdef AP_ONLY
+		ap_ssid.SSID_len = strlen(ap->ssid);
+		strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
+		res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid));
+		mpc = 0;
+		res |= dev_wlc_intvar_set(dev, "mpc", mpc);
+		if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
+			res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+		}
+#endif
 	return res;
 }
 
@@ -5045,7 +6214,7 @@
 	char  *param_str_end;
 	char  *orig_str = *str_ptr;
 
-	if (!strncmp(*str_ptr, token, strlen(token))) {
+	if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) {
 
 		strsep(str_ptr, "=,");
 		param_str_begin = *str_ptr;
@@ -5163,13 +6332,17 @@
 		return res;
 	}
 
-    net_os_wake_lock(dev);
+	net_os_wake_lock(dev);
 
 	if ((ap_cfg_running == TRUE)) {
-        wl_iw_softap_deassoc_stations(ap_net_dev);
+#ifdef AP_ONLY
+		 wl_iw_softap_deassoc_stations(dev);
+#else
+		 wl_iw_softap_deassoc_stations(ap_net_dev);
 
 		if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0)
 			WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res));
+#endif
 
 		bcm_mdelay(100);
 
@@ -5181,9 +6354,9 @@
 
 	WL_SOFTAP(("%s Done with %d\n", __FUNCTION__, res));
 
-    net_os_wake_unlock(dev);
+	net_os_wake_unlock(dev);
 
-    return res;
+	return res;
 }
 
 
@@ -5293,10 +6466,11 @@
 		return -1;
 	}
 
-    net_os_wake_lock(dev);
+	net_os_wake_lock(dev);
 
 	WL_TRACE(("%s: rcvd IWPRIV IOCTL:  for dev:%s\n", __FUNCTION__, dev->name));
 
+#ifndef AP_ONLY
 	if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
 		WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res));
 	}
@@ -5307,9 +6481,10 @@
 			bcm_mdelay(100);
 	}
 
+#endif 
 	WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res));
 
-    net_os_wake_unlock(dev);
+	net_os_wake_unlock(dev);
 
 	return res;
 }
@@ -5440,6 +6615,7 @@
 
 		WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name));
 
+#ifndef AP_ONLY
 		if (ap_net_dev == NULL) {
 			printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n");
 		} else {
@@ -5447,15 +6623,21 @@
 				WL_ERROR(("%s line %d fail to set bss up\n", \
 					__FUNCTION__, __LINE__));
 		}
-
+#else
+		if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0)
+				WL_ERROR(("%s line %d fail to set bss up\n", \
+					__FUNCTION__, __LINE__));
+#endif
 	} else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) {
 		/* no code yet */
 	} else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) {
 		WL_SOFTAP((" \n temp DOWN SOFTAP\n"));
+#ifndef AP_ONLY
 		if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
 				WL_ERROR(("%s line %d fail to set bss down\n", \
 					__FUNCTION__, __LINE__));
 		}
+#endif
 	}
 
 	return ret;
@@ -5520,6 +6702,28 @@
 			ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
 		else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
 			ret = wl_iw_control_wl_off(dev, info);
+	    else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
+			ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
+	    else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
+			ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra);
+	    else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0)
+			ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
+	    else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
+			ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
+	    else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
+			ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
+#if defined(PNO_SUPPORT)
+	    else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
+			ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
+	    else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0)
+			ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra);
+	    else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0)
+			ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
+#endif
+#if defined(CSCAN)
+	    else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
+			ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
+#endif 
 #ifdef CUSTOMER_HW2
 		else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
 			ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
@@ -5529,6 +6733,8 @@
 		else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
 			ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
 #endif
+		else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
+			ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
 #ifdef SOFTAP
 		else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
 			wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
@@ -5677,8 +6883,13 @@
 	(iw_handler)iwpriv_softap_stop,
 
 	NULL,
-	(iw_handler)iwpriv_fw_reload
+	(iw_handler)iwpriv_fw_reload,
 #endif
+#if defined(CSCAN)
+
+	NULL,
+	(iw_handler)iwpriv_set_cscan
+#endif 	
 };
 
 static const struct iw_priv_args wl_iw_priv_args[] = {
@@ -5775,6 +6986,14 @@
 		"WL_FW_RELOAD"
 	},
 #endif
+#if defined(CSCAN)
+	{
+		WL_COMBO_SCAN,
+		IW_PRIV_TYPE_CHAR | 1024,
+		0,
+		"CSCAN"
+	},
+#endif
 };
 
 const struct iw_handler_def wl_iw_handler_def =
@@ -5805,11 +7024,14 @@
 	char *extra = NULL;
 	int token_size = 1, max_tokens = 0, ret = 0;
 
+	net_os_wake_lock(dev);
+
 	WL_TRACE(("%s: cmd:%x alled via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd));
 	if (cmd < SIOCIWFIRST ||
 		IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
 		!(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) {
 			WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd));
+			net_os_wake_unlock(dev);
 			return -EOPNOTSUPP;
 	}
 
@@ -5874,14 +7096,18 @@
 		if (wrq->u.data.length > max_tokens) {
 			WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d  > max_tokens=%d\n", \
 				__FUNCTION__, cmd, wrq->u.data.length, max_tokens));
-			return -E2BIG;
+			ret = -E2BIG;
+			goto wl_iw_ioctl_done;
 		}
-		if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL)))
-			return -ENOMEM;
+		if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) {
+			ret = -ENOMEM;
+			goto wl_iw_ioctl_done;
+		}
 
 		if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
 			kfree(extra);
-			return -EFAULT;
+			ret = -EFAULT;
+			goto wl_iw_ioctl_done;
 		}
 	}
 
@@ -5893,12 +7119,17 @@
 	if (extra) {
 		if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
 			kfree(extra);
-			return -EFAULT;
+			ret = -EFAULT;
+			goto wl_iw_ioctl_done;
 		}
 
 		kfree(extra);
 	}
 
+wl_iw_ioctl_done:
+
+	net_os_wake_unlock(dev);
+
 	return ret;
 }
 
@@ -6015,6 +7246,8 @@
 	uint32 datalen = ntoh32(e->datalen);
 	uint32 status =  ntoh32(e->status);
 	uint32 toto;
+	static uint32 roam_no_success = 0;
+	static bool roam_no_success_send = FALSE;
 
 	memset(&wrqu, 0, sizeof(wrqu));
 	memset(extra, 0, sizeof(extra));
@@ -6024,7 +7257,7 @@
 		return;
 	}
 
-    net_os_wake_lock(dev);
+	net_os_wake_lock(dev);
 
 	WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type));
 
@@ -6071,20 +7304,41 @@
 		WL_SOFTAP(("STA connect received %d\n", event_type));
 		if (ap_cfg_running) {
 			wl_iw_send_priv_event(priv_dev, "STA_JOIN");
-            goto wl_iw_event_end;
+			goto wl_iw_event_end;
 		}
 #endif
 		memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
 		wrqu.addr.sa_family = ARPHRD_ETHER;
 		cmd = IWEVREGISTERED;
 		break;
+	case WLC_E_ROAM:
+		if (status != WLC_E_STATUS_SUCCESS) {
+			roam_no_success++;
+			if ((roam_no_success == 3) && (roam_no_success_send == FALSE)) {
+
+				roam_no_success_send = TRUE;
+				bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+				bzero(&extra, ETHER_ADDR_LEN);
+				cmd = SIOCGIWAP;
+				WL_ERROR(("%s  ROAMING did not succeeded , send Link Down\n", \
+					__FUNCTION__));
+			} else {
+				WL_TRACE(("##### ROAMING did not succeeded %d\n", roam_no_success));
+				goto wl_iw_event_end;
+			}
+		} else {
+			memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
+			wrqu.addr.sa_family = ARPHRD_ETHER;
+			cmd = SIOCGIWAP;
+		}
+		break;
 	case WLC_E_DEAUTH_IND:
 	case WLC_E_DISASSOC_IND:
 #if defined(SOFTAP)
 		WL_SOFTAP(("STA disconnect received %d\n", event_type));
 		if (ap_cfg_running) {
 			wl_iw_send_priv_event(priv_dev, "STA_LEAVE");
-            goto wl_iw_event_end;
+			goto wl_iw_event_end;
 		}
 #endif
 		cmd = SIOCGIWAP;
@@ -6097,7 +7351,11 @@
 		cmd = SIOCGIWAP;
 		if (!(flags & WLC_EVENT_MSG_LINK)) {
 #ifdef SOFTAP
+#ifdef AP_ONLY
+		if (ap_cfg_running) {
+#else
 		if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
+#endif	
 				WL_SOFTAP(("AP DOWN %d\n", event_type));
 				wl_iw_send_priv_event(priv_dev, "AP_DOWN");
 			} else {
@@ -6111,7 +7369,6 @@
 
 			bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
 			bzero(&extra, ETHER_ADDR_LEN);
-            net_os_wake_lock_timeout_enable(dev);
 		}
 		else {
 			memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
@@ -6120,16 +7377,23 @@
 			memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN);
 
 #ifdef SOFTAP
+#ifdef AP_ONLY
+			if (ap_cfg_running) {
+#else
 			if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
+#endif
 				WL_SOFTAP(("AP UP %d\n", event_type));
 				wl_iw_send_priv_event(priv_dev, "AP_UP");
 			} else {
 				WL_TRACE(("STA_LINK_UP\n"));
+				roam_no_success_send = FALSE;
+				roam_no_success = 0;
 			}
 #endif
 			WL_TRACE(("Link UP\n"));
 
 		}
+		net_os_wake_lock_timeout_enable(dev);
 		wrqu.addr.sa_family = ARPHRD_ETHER;
 		break;
 	case WLC_E_ACTION_FRAME:
@@ -6210,15 +7474,30 @@
 		} else {
 			cmd = SIOCGIWSCAN;
 			wrqu.data.length = strlen(extra);
-			WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan\n"));
+			WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan %d\n", \
+				g_iscan->iscan_state));
 		}
 #else
 		cmd = SIOCGIWSCAN;
 		wrqu.data.length = strlen(extra);
 		WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
-#endif 
+#endif
 		break;
 
+	case WLC_E_PFN_NET_FOUND:
+	{
+		wlc_ssid_t	* ssid;
+		ssid = (wlc_ssid_t *)data;
+		WL_TRACE(("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n", \
+			__FUNCTION__, PNO_EVENT_UP, ssid->SSID, ssid->SSID_len));
+		net_os_wake_lock_timeout_enable(dev);
+		cmd = IWEVCUSTOM;
+		memset(&wrqu, 0, sizeof(wrqu));
+		strcpy(extra, PNO_EVENT_UP);
+		wrqu.data.length = strlen(extra);
+	}
+	break;
+
 	default:
 		
 		WL_TRACE(("Unknown Event %d: ignoring\n", event_type));
@@ -6247,8 +7526,8 @@
 	}
 #endif
 wl_iw_event_end:
-    net_os_wake_unlock(dev);
-#endif 
+	net_os_wake_unlock(dev);
+#endif
 }
 
 int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
@@ -6416,7 +7695,7 @@
 				g_bt->bt_state = BT_DHCP_IDLE;
 				g_bt->timer_on = 0;
 				break;
-		 }
+		}
 
 		net_os_wake_unlock(g_bt->dev);
 	}
@@ -6480,6 +7759,7 @@
 
 int wl_iw_attach(struct net_device *dev, void * dhdp)
 {
+	int params_size;
 	wl_iw_t *iw;
 #if defined(WL_IW_USE_ISCAN)
 	iscan_info_t *iscan = NULL;
@@ -6492,19 +7772,33 @@
 	if (!dev)
 		return 0;
 
+	memset(&g_wl_iw_params, 0, sizeof(wl_iw_extra_params_t));
+
+#ifdef CSCAN
+	params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
+	    (WL_NUMCHANNELS * sizeof(uint16)) + WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+#else
+	params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
+#endif 
 	iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
 	if (!iscan)
 		return -ENOMEM;
 	memset(iscan, 0, sizeof(iscan_info_t));
+	
+	iscan->iscan_ex_params_p = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+	if (!iscan->iscan_ex_params_p)
+		return -ENOMEM;
+	iscan->iscan_ex_param_size = params_size;
 	iscan->sysioc_pid = -1;
 	
 	g_iscan = iscan;
 	iscan->dev = dev;
 	iscan->iscan_state = ISCAN_STATE_IDLE;
 	g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
+	g_first_counter_scans = 0;
 	g_iscan->scan_flag = 0;
 
-	iscan->timer_ms    = 3000;
+	iscan->timer_ms    = 8000;
 	init_timer(&iscan->timer);
 	iscan->timer.data = (ulong)iscan;
 	iscan->timer.function = wl_iw_timerfunc;
@@ -6530,11 +7824,12 @@
 	memset(g_scan, 0, G_SCAN_RESULTS);
 	g_scan_specified_ssid = 0;
 
+#if !defined(CSCAN)
 	wl_iw_init_ss_cache_ctrl();
+#endif
 
 	wl_iw_bt_init(dev);
 
-
 	return 0;
 }
 
@@ -6556,6 +7851,7 @@
 		kfree(iscan->list_hdr);
 		iscan->list_hdr = buf;
 	}
+	kfree(iscan->iscan_ex_params_p);
 	kfree(iscan);
 	g_iscan = NULL;
 	mutex_unlock(&wl_cache_lock);
@@ -6565,7 +7861,9 @@
 		kfree(g_scan);
 
 	g_scan = NULL;
+#if !defined(CSCAN)
 	wl_iw_release_ss_cache_ctrl();
+#endif
 	wl_iw_bt_release();
 #ifdef SOFTAP
 	if (ap_cfg_running) {
diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h
index aea656b..43088cf 100644
--- a/bcm4329/src/wl/sys/wl_iw.h
+++ b/bcm4329/src/wl/sys/wl_iw.h
@@ -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: wl_iw.h,v 1.5.34.1.6.16 2010/04/19 21:32:10 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.36.4.1 2010/09/10 19:24:30 Exp $
  */
 
 
@@ -34,6 +34,32 @@
 #include <proto/ethernet.h>
 #include <wlioctl.h>
 
+#define WL_SCAN_PARAMS_SSID_MAX 	10
+#define GET_SSID			"SSID="
+#define GET_CHANNEL			"CH="
+#define GET_NPROBE 			"NPROBE="
+#define GET_ACTIVE_ASSOC_DWELL  	"ACTIVE="
+#define GET_PASSIVE_ASSOC_DWELL  	"PASSIVE="
+#define GET_HOME_DWELL  		"HOME="
+#define GET_SCAN_TYPE			"TYPE="
+
+#define BAND_GET_CMD				"GETBAND"
+#define BAND_SET_CMD				"SETBAND"
+#define DTIM_SKIP_GET_CMD			"DTIMSKIPGET"
+#define DTIM_SKIP_SET_CMD			"DTIMSKIPSET"
+#define SETSUSPEND_CMD				"SETSUSPENDOPT"
+#define PNOSSIDCLR_SET_CMD			"PNOSSIDCLR"
+#define PNOSETUP_SET_CMD			"PNOSETUP "
+#define PNOENABLE_SET_CMD			"PNOFORCE"
+#define PNODEBUG_SET_CMD			"PNODEBUG"
+
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+
+typedef struct wl_iw_extra_params {
+	int 	target_channel;
+} wl_iw_extra_params_t;
 
 #define	WL_IW_RSSI_MINVAL	-200
 #define	WL_IW_RSSI_NO_SIGNAL	-91
@@ -61,7 +87,7 @@
 #define AP_LPB_CMD              (SIOCIWFIRSTPRIV+23)
 #define WL_AP_STOP              (SIOCIWFIRSTPRIV+25)
 #define WL_FW_RELOAD            (SIOCIWFIRSTPRIV+27)
-#define WL_AP_SPARE2            (SIOCIWFIRSTPRIV+29)
+#define WL_COMBO_SCAN           (SIOCIWFIRSTPRIV+29)
 #define WL_AP_SPARE3            (SIOCIWFIRSTPRIV+31)
 #define G_SCAN_RESULTS		(8*1024)
 #define WE_ADD_EVENT_FIX	0x80
@@ -95,7 +121,7 @@
 #define WLC_IW_BSS_INFO_MAXLEN 				\
 	(WLC_IW_SS_CACHE_MAXLEN - WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN)
 
-typedef struct wl_iw_ss_cache{
+typedef struct wl_iw_ss_cache {
 	uint32 buflen;
 	uint32 version;
 	uint32 count;
@@ -166,6 +192,11 @@
 extern int net_os_wake_unlock(struct net_device *dev);
 extern int net_os_wake_lock_timeout(struct net_device *dev);
 extern int net_os_wake_lock_timeout_enable(struct net_device *dev);
+extern int net_os_set_suspend_disable(struct net_device *dev, int val);
+extern int net_os_set_suspend(struct net_device *dev, int val);
+extern int net_os_set_dtim_skip(struct net_device *dev, int val);
+extern int net_os_set_packet_filter(struct net_device *dev, int val);
+extern int net_os_send_hang_message(struct net_device *dev);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
 #define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
@@ -183,4 +214,65 @@
 	iwe_stream_add_point(stream, ends, iwe, extra)
 #endif
 
-#endif
+extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
+extern int dhd_pno_clean(dhd_pub_t *dhd);
+extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort  scan_fr);
+extern int dhd_pno_get_status(dhd_pub_t *dhd);
+extern int dhd_dev_pno_reset(struct net_device *dev);
+extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, \
+				 int nssid, ushort  scan_fr);
+extern int dhd_dev_pno_enable(struct net_device *dev,  int pfn_enabled);
+extern int dhd_dev_get_pno_status(struct net_device *dev);
+
+#define PNO_TLV_PREFIX			'S'
+#define PNO_TLV_VERSION			1
+#define PNO_TLV_SUBVERSION 		1
+#define PNO_TLV_RESERVED		0
+#define PNO_TLV_TYPE_SSID_IE		'S'
+#define PNO_TLV_TYPE_TIME		'T'
+#define  PNO_EVENT_UP			"PNO_EVENT"
+
+typedef struct cmd_tlv {
+	char prefix;
+	char version;
+	char subver;
+	char reserved;
+} cmd_tlv_t;
+
+#if defined(CSCAN)
+
+typedef struct cscan_tlv {
+	char prefix;
+	char version;
+	char subver;
+	char reserved;
+} cscan_tlv_t;
+
+#define CSCAN_COMMAND				"CSCAN "
+#define CSCAN_TLV_PREFIX 			'S'
+#define CSCAN_TLV_VERSION			1
+#define CSCAN_TLV_SUBVERSION			0
+#define CSCAN_TLV_TYPE_SSID_IE			'S'
+#define CSCAN_TLV_TYPE_CHANNEL_IE		'C'
+#define CSCAN_TLV_TYPE_NPROBE_IE		'N'
+#define CSCAN_TLV_TYPE_ACTIVE_IE		'A'
+#define CSCAN_TLV_TYPE_PASSIVE_IE		'P'
+#define CSCAN_TLV_TYPE_HOME_IE			'H'
+#define CSCAN_TLV_TYPE_STYPE_IE			'T'
+
+extern int wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, \
+					int channel_num, int *bytes_left);
+
+extern int wl_iw_parse_data_tlv(char** list_str, void  *dst, int dst_size, \
+					const char token, int input_size, int *bytes_left);
+
+extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, \
+					int max, int *bytes_left);
+
+extern int wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max);
+
+extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num);
+
+#endif 
+
+#endif