summaryrefslogtreecommitdiffstats
path: root/bcm4329
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2010-09-01 16:13:20 -0700
committerDmitry Shmidt <dimitrysh@google.com>2010-09-01 16:13:20 -0700
commite7fb557185249a07e3e3205c588ca9085fba5c55 (patch)
tree5f1b7ebf8439302fdc3dbe140b1bd2b9e7794319 /bcm4329
parent127b347242724f8dad5973449802b451d072fd85 (diff)
downloadhardware_broadcom_wlan-e7fb557185249a07e3e3205c588ca9085fba5c55.zip
hardware_broadcom_wlan-e7fb557185249a07e3e3205c588ca9085fba5c55.tar.gz
hardware_broadcom_wlan-e7fb557185249a07e3e3205c588ca9085fba5c55.tar.bz2
bcm4329: Update to Version 4.218.248
Change-Id: I13422de1072aa17fcf935893c4071a492fe7270d Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'bcm4329')
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmpcispi.c11
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_linux.c85
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c2
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c20
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdstd.c21
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c6
-rw-r--r--bcm4329/src/dhd/sys/dhd.h26
-rw-r--r--bcm4329/src/dhd/sys/dhd_cdc.c27
-rw-r--r--bcm4329/src/dhd/sys/dhd_common.c230
-rw-r--r--bcm4329/src/dhd/sys/dhd_linux.c270
-rw-r--r--bcm4329/src/dhd/sys/dhd_proto.h2
-rw-r--r--bcm4329/src/dhd/sys/dhd_sdio.c15
-rw-r--r--bcm4329/src/include/epivers.h10
-rw-r--r--bcm4329/src/include/wlioctl.h4
-rw-r--r--bcm4329/src/wl/sys/wl_iw.c553
-rw-r--r--bcm4329/src/wl/sys/wl_iw.h46
16 files changed, 1056 insertions, 272 deletions
diff --git a/bcm4329/src/bcmsdio/sys/bcmpcispi.c b/bcm4329/src/bcmsdio/sys/bcmpcispi.c
index c0a66f1..1a8b671 100644
--- a/bcm4329/src/bcmsdio/sys/bcmpcispi.c
+++ b/bcm4329/src/bcmsdio/sys/bcmpcispi.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: 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 @@ spi_spinbits(sdioh_info_t *sd)
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_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
index 0555f87..644d6be 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 2010/08/17 16:34:23 Exp $
*/
/**
@@ -75,7 +75,11 @@ struct bcmsdh_hc {
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;
@@ -225,6 +229,10 @@ int bcmsdh_probe(struct device *dev)
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 +346,7 @@ extern uint sd_pci_slot; /* Force detection to a particular PCI */
/* slot only . Allows for having multiple */
/* WL devices at once in a PC */
/* Only one instance of dhd will be */
- /* 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 +373,21 @@ bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
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 +448,7 @@ bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
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 +575,34 @@ bcmsdh_unregister(void)
#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 +620,16 @@ int bcmsdh_register_oob_intr(void * dhdp)
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 (error)
- return -ENODEV;
+ if (!sdhcinfo->oob_irq_registered) {
+ /* 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;
- set_irq_wake(sdhcinfo->oob_irq, 1);
+ set_irq_wake(sdhcinfo->oob_irq, 1);
+ sdhcinfo->oob_irq_registered = TRUE;
+ }
return 0;
}
@@ -611,14 +641,7 @@ void bcmsdh_unregister_oob_intr(void)
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..5a3ca3d 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
@@ -676,6 +676,8 @@ sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
else
data = 4; /* disable hw oob interrupt */
+ data |= 4; /* Active HIGH */
+
status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
return status;
}
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 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func)
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/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 @@ extern void sdstd_wreg16(sdioh_info_t *sd, uint reg, uint16 data);
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 @@ sdstd_or_reg16(sdioh_info_t *sd, uint reg, uint16 val)
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 @@ sdstd_mod_reg16(sdioh_info_t *sd, uint reg, int16 mask, uint16 val)
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 @@ sdstd_rreg(sdioh_info_t *sd, uint reg)
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 @@ sdstd_wreg(sdioh_info_t *sd, uint reg, uint32 data)
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 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd)
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 @@ sdstd_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, uint32 addr, int n
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 @@ set_client_block_size(sdioh_info_t *sd, int func, int block_size)
}
/* 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 ad6d660..a8b98e2 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdstd_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: 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 @@ sdstd_lock(sdioh_info_t *sd)
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/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h
index 9db5c63..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.44 2010/06/03 21:27:48 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.49 2010/08/20 17:32:48 Exp $
*/
/****************
@@ -150,8 +150,13 @@ typedef struct dhd_pub {
/* Last error from dongle */
int dongle_error;
- /* Suspend disable flag */
- int suspend_disable_flag;
+ /* 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];
@@ -162,16 +167,17 @@ typedef struct dhd_pub {
} 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)
@@ -185,7 +191,7 @@ typedef struct dhd_pub {
} \
} while (0)
- #else
+#else
#define DHD_PM_RESUME_WAIT_INIT(a)
#define DHD_PM_RESUME_WAIT(a)
@@ -202,7 +208,8 @@ typedef struct dhd_pub {
} \
} 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 */
@@ -409,9 +416,6 @@ extern char nv_path[MOD_PARAM_PATHLEN];
#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_cdc.c b/bcm4329/src/dhd/sys/dhd_cdc.c
index 070e95e..61f6a6f 100644
--- a/bcm4329/src/dhd/sys/dhd_cdc.c
+++ b/bcm4329/src/dhd/sys/dhd_cdc.c
@@ -323,23 +323,12 @@ dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
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__));
@@ -347,9 +336,6 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf)
#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);
@@ -362,19 +348,6 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf)
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);
diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c
index 8faffcb..e3e8dcc 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.65 2010/07/07 00:05:07 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69 2010/08/20 00:39:21 Exp $
*/
#include <typedefs.h>
#include <osl.h>
@@ -50,9 +50,7 @@ int wifi_get_mac_addr(unsigned char *buf);
int dhd_msg_level;
-#if defined(CSCAN)
#include <wl_iw.h>
-#endif
char fw_path[MOD_PARAM_PATHLEN];
char nv_path[MOD_PARAM_PATHLEN];
@@ -514,9 +512,6 @@ dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
return bcmerror;
}
-#ifdef APSTA_PINGTEST
-struct ether_addr guest_eas[MAX_GUEST];
-#endif
#ifdef SHOW_EVENTS
static void
@@ -625,16 +620,6 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data)
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;
@@ -655,18 +640,6 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data)
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;
@@ -972,6 +945,7 @@ void print_buf(void *pbuf, int len, int bytes_per_line)
#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)
@@ -1201,7 +1175,9 @@ fail:
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)
{
@@ -1235,6 +1211,7 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
__FUNCTION__, arp_enable));
}
+#endif
int
dhd_preinit_ioctls(dhd_pub_t *dhd)
@@ -1247,7 +1224,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint32 glom = 0;
uint bcn_timeout = 3;
int scan_assoc_time = 40;
- int scan_unassoc_time = 80;
+ int scan_unassoc_time = 40;
#ifdef GET_CUSTOM_MAC_ENABLE
int ret;
struct ether_addr ea_addr;
@@ -1394,9 +1371,9 @@ dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
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));
+ 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;
@@ -1557,10 +1534,10 @@ dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
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], \
+ 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;
@@ -1577,8 +1554,8 @@ dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
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",
+ 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],
@@ -1756,15 +1733,166 @@ fail:
#endif
-/* Android ComboSCAN support */
+#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, uchar 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)
+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;
@@ -1780,8 +1908,8 @@ wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token,
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));
+ DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n",
+ __FUNCTION__, token, str[0], *bytes_left));
return -1;
}
@@ -1792,11 +1920,11 @@ wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token,
memcpy(dst, str, input_size);
}
else if (input_size == 2) {
- memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)), \
- input_size);
+ 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)), \
+ memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)),
input_size);
}
@@ -1812,8 +1940,8 @@ wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token,
* 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)
+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;
@@ -1898,7 +2026,7 @@ wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes
/* Get SSID */
if (ssid[idx].SSID_len > *bytes_left) {
- DHD_ERROR(("%s out of memory range len=%d but left=%d\n", \
+ DHD_ERROR(("%s out of memory range len=%d but left=%d\n",
__FUNCTION__, ssid[idx].SSID_len, *bytes_left));
return -1;
}
@@ -1908,8 +2036,8 @@ wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes
*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));
+ 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]));
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index cce87ba..eb00dbd 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.89 2010/07/21 18:07:11 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
@@ -220,9 +220,12 @@ print_tainted()
#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 /* defined(CONFIG_HAS_EARLYSUSPEND) */
+#endif
/* Interface control information */
typedef struct dhd_if {
@@ -276,6 +279,8 @@ typedef struct dhd_info {
int wl_count;
int wl_packet;
+ int hang_was_sent;
+
/* Thread to issue ioctl for multicast */
long sysioc_pid;
struct semaphore sysioc_sem;
@@ -469,18 +474,22 @@ static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
#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 = {
@@ -491,10 +500,26 @@ extern int register_pm_notifier(struct notifier_block *nb);
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;
-#if defined(CONFIG_HAS_EARLYSUSPEND)
+ 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
+}
-int dhd_set_suspend(int value, dhd_pub_t *dhd)
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+static int dhd_set_suspend(int value, dhd_pub_t *dhd)
{
int power_mode = PM_MAX;
/* wl_pkt_filter_enable_t enable_parm; */
@@ -503,28 +528,30 @@ int dhd_set_suspend(int value, dhd_pub_t *dhd)
#ifdef CUSTOMER_HW2
uint roamvar = 1;
#endif /* CUSTOMER_HW2 */
- int i;
-#define htod32(i) i
+ DHD_TRACE(("%s: enter, value = %d in_suspend = %d\n",
+ __FUNCTION__, value, dhd->in_suspend));
- if (dhd && (dhd->up && !dhd->suspend_disable_flag)) {
- dhd_os_proto_block(dhd);
- if (value) {
+ 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 */
- 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],
- 1, dhd_master_mode);
- }
- }
-
- /* set bcn_li_dtim */
+ 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));
@@ -536,54 +563,63 @@ int dhd_set_suspend(int value, dhd_pub_t *dhd)
} 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 */
- 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],
- 0, dhd_master_mode);
- }
- }
+ dhd_set_packet_filter(0, dhd);
- /* 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));
+ /* 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 = 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;
}
+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) */
@@ -1092,7 +1128,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *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__));
- wl_iw_send_priv_event(net, "HANG");
+ net_os_send_hang_message(net);
}
dhd_os_wake_unlock(&dhd->pub);
return -ENODEV;
@@ -1785,7 +1821,7 @@ done:
if ((bcmerror == -ETIMEDOUT) || ((dhd->pub.busstate == DHD_BUS_DOWN) &&
(!dhd->pub.dongle_reset))) {
DHD_ERROR(("%s: Event HANG send up\n", __FUNCTION__));
- wl_iw_send_priv_event(net, "HANG");
+ net_os_send_hang_message(net);
}
if (!bcmerror && buf && ioc.buf) {
@@ -2175,6 +2211,12 @@ dhd_bus_start(dhd_pub_t *dhdp)
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 */
@@ -2305,7 +2347,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
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) && !defined(CSCAN)
+#if defined(CONFIG_WIRELESS_EXT)
#ifdef SOFTAP
if (ifidx == 0)
/* Don't call for SOFTAP Interface in SOFTAP MODE */
@@ -2369,7 +2411,8 @@ dhd_detach(dhd_pub_t *dhdp)
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 */
@@ -2576,14 +2619,17 @@ dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
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;
@@ -2849,12 +2895,70 @@ dhd_dev_reset(struct net_device *dev, uint8 flag)
/* 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)
{
@@ -2863,6 +2967,47 @@ dhd_dev_init_ioctl(struct net_device *dev)
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, uchar 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)
{
@@ -3045,11 +3190,16 @@ int net_os_wake_unlock(struct net_device *dev)
return ret;
}
-int net_os_set_suspend_disable(struct net_device *dev, int val)
+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)
- dhd->pub.suspend_disable_flag = val;
- return 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_proto.h b/bcm4329/src/dhd/sys/dhd_proto.h
index 382785a..7ef6929 100644
--- a/bcm4329/src/dhd/sys/dhd_proto.h
+++ b/bcm4329/src/dhd/sys/dhd_proto.h
@@ -34,7 +34,7 @@
#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
diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c
index 0cf6508..7b54f60 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.126 2010/06/15 23:38:39 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.129 2010/08/19 20:36:22 Exp $
*/
#include <typedefs.h>
@@ -124,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 */
@@ -4218,6 +4218,11 @@ dhdsdio_dpc(dhd_bus_t *bus)
bus->intstatus = intstatus;
clkwait:
+
+#if defined(OOB_INTR_ONLY)
+ bcmsdh_oob_intr_set(1);
+#endif
+
/* Re-enable interrupts to detect new device events (mailbox, rx frame)
* or clock availability. (Allows tx loop to check ipend if desired.)
* (Unless register access seems hosed, as we may not be able to ACK...)
@@ -4694,8 +4699,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
bus->idlecount = 0;
if (bus->activity) {
bus->activity = FALSE;
- dhd_os_wd_timer(bus->dhd,dhd_watchdog_ms);
- } else {
dhdsdio_clkctl(bus, CLK_NONE, FALSE);
}
}
diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h
index 733b133..caceabd 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 246
+#define EPI_RC_NUMBER 248
#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 218, 246, 0
+#define EPI_VERSION 4, 218, 248, 0
-#define EPI_VERSION_NUM 0x04daf600
+#define EPI_VERSION_NUM 0x04daf800
-#define EPI_VERSION_STR "4.218.246.0"
-#define EPI_ROUTER_VERSION_STR "4.219.246.0"
+#define EPI_VERSION_STR "4.218.248.0"
+#define EPI_ROUTER_VERSION_STR "4.219.248.0"
#endif
diff --git a/bcm4329/src/include/wlioctl.h b/bcm4329/src/include/wlioctl.h
index d346945..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.61 2010/05/04 20:26:25 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.62 2010/08/19 01:20:12 Exp $
*/
@@ -1317,6 +1317,8 @@ enum {
#define PFN_VERSION 1
+#define MAX_PFN_LIST_COUNT 16
+
typedef struct wl_pfn_param {
int32 version;
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index 0307ae0..c6b2e8a 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.124 2010/07/27 20:46:02 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142 2010/08/20 19:12:47 Exp $
*/
@@ -109,6 +109,7 @@ static int wl_iw_softap_deassoc_stations(struct net_device *dev);
} 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;
@@ -667,14 +668,20 @@ wl_iw_set_power_mode(
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 {
+
+ /* Enable packet filtering if was turned off */
+ net_os_set_packet_filter(dev, 1);
+
+ } else {
WL_ERROR(("Unkwown yet power setting, ignored\n"));
}
@@ -849,9 +856,25 @@ wl_iw_set_suspend(
)
{
int suspend_flag;
+ int ret_now;
+ int ret = 0;
- suspend_flag = *(extra + strlen("SETSUSPEND") + 1) - '0';
- return net_os_set_suspend_disable(dev, suspend_flag);
+ 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
@@ -890,7 +913,7 @@ wl_iw_get_link_speed(
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;
@@ -900,6 +923,91 @@ wl_iw_get_link_speed(
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;
}
@@ -916,6 +1024,8 @@ wl_iw_get_band(
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));
@@ -923,6 +1033,8 @@ wl_iw_get_band(
wrqu->data.length = p - extra + 1;
}
+
+ net_os_wake_unlock(dev);
return error;
}
@@ -939,9 +1051,11 @@ wl_iw_set_band(
char *p = extra;
uint band;
+ net_os_wake_lock(dev);
+
if (g_onoff == G_WLAN_SET_ON) {
- band = *(extra + strlen(BAND_SET_CMD) + 1) - '0';
+ band = htod32((uint)*(extra + strlen(BAND_SET_CMD) + 1) - '0');
if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
@@ -952,20 +1066,212 @@ wl_iw_set_band(
WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band));
goto exit;
}
- else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \
+ else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \
band, error));
}
- else WL_ERROR(("%s Incorrect band setting, ignored\n", __FUNCTION__));
+ 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, 0x00, 0x00,
+ 'S',
+ 0x04,
+ 'B', 'R', 'C', 'M',
+ 'S',
+ 0x04,
+ 'G', 'O', 'O', 'G',
+ 'T',
+ 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(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;
+ }
+
+ 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,
@@ -981,12 +1287,15 @@ wl_iw_get_rssi(
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);
@@ -1001,6 +1310,7 @@ wl_iw_get_rssi(
p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
wrqu->data.length = p - extra + 1;
+ net_os_wake_unlock(dev);
return error;
}
@@ -1112,6 +1422,8 @@ wl_iw_control_wl_off(
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");
@@ -1138,7 +1450,6 @@ wl_iw_control_wl_on(
wl_iw_send_priv_event(dev, "START");
-#if !defined(CSCAN)
#ifdef SOFTAP
if (!ap_fw_loaded) {
wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
@@ -1146,7 +1457,6 @@ wl_iw_control_wl_on(
#else
wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
#endif
-#endif
WL_TRACE(("Exited %s \n", __FUNCTION__));
@@ -1559,6 +1869,7 @@ wl_iw_set_freq(
if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
return error;
+ g_wl_iw_params.target_channel = chan;
return -EINPROGRESS;
}
@@ -1579,7 +1890,6 @@ wl_iw_get_freq(
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;
@@ -1907,6 +2217,41 @@ wl_iw_get_spy(
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,
@@ -1917,6 +2262,7 @@ wl_iw_set_wap(
{
int error = -EINVAL;
wl_join_params_t join_params;
+ int join_params_size;
WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
@@ -1938,16 +2284,26 @@ wl_iw_set_wap(
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;
@@ -2244,6 +2600,7 @@ wl_iw_iscan_get(iscan_info_t *iscan)
wl_iscan_results_t list;
wl_scan_results_t *results;
uint32 status;
+ int res;
mutex_lock(&wl_cache_lock);
if (iscan->list_cur) {
@@ -2278,20 +2635,25 @@ wl_iw_iscan_get(iscan_info_t *iscan)
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_SCAN(("results->count = %d\n", results->count));
-
- WL_SCAN(("results->buflen = %d\n", results->buflen));
- status = dtoh32(list_buf->status);
+ 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_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;
}
@@ -2316,10 +2678,8 @@ static void wl_iw_send_scan_complete(iscan_info_t *iscan)
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
-#if !defined(CSCAN)
if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
-#endif
WL_TRACE(("Send Event ISCAN complete\n"));
#endif
}
@@ -2591,6 +2951,8 @@ wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
}
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;
}
@@ -2739,7 +3101,7 @@ wl_iw_set_scan(
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;
}
@@ -2753,7 +3115,6 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
wlc_ssid_t ssid;
iscan_info_t *iscan = g_iscan;
-#if !defined(CSCAN)
if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) {
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED;
WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__));
@@ -2762,7 +3123,6 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
return 0;
}
-#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
if (flag)
@@ -2794,6 +3154,7 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
return 0;
}
+
static int
wl_iw_iscan_set_scan(
struct net_device *dev,
@@ -2804,6 +3165,7 @@ wl_iw_iscan_set_scan(
{
wlc_ssid_t ssid;
iscan_info_t *iscan = g_iscan;
+ int ret = 0;
WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
@@ -2812,28 +3174,38 @@ wl_iw_iscan_set_scan(
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);
+ ret = wl_iw_set_scan(dev, info, wrqu, extra);
+ 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));
@@ -2848,7 +3220,8 @@ wl_iw_iscan_set_scan(
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;
+ ret = -EBUSY;
+ goto set_scan_end;
}
#endif
ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
@@ -2856,14 +3229,15 @@ wl_iw_iscan_set_scan(
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;
}
}
}
@@ -2871,7 +3245,9 @@ wl_iw_iscan_set_scan(
wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
- return 0;
+set_scan_end:
+ net_os_wake_unlock(dev);
+ return ret;
}
#endif
@@ -3314,6 +3690,7 @@ wl_iw_iscan_get_scan(
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;
@@ -3333,14 +3710,12 @@ wl_iw_iscan_get_scan(
return -EINVAL;
}
-#if !defined(CSCAN)
if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) {
WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \
dev->name, __FUNCTION__));
return -EAGAIN;
}
-#endif
-
+
if ((!iscan) || (iscan->sysioc_pid < 0)) {
WL_TRACE(("%ssysioc_pid\n", __FUNCTION__));
return wl_iw_get_scan(dev, info, dwrq, extra);
@@ -3417,8 +3792,9 @@ wl_iw_iscan_get_scan(
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);
@@ -3470,9 +3846,8 @@ wl_iw_iscan_get_scan(
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;
-#endif
WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
@@ -3492,6 +3867,8 @@ wl_iw_set_essid(
)
{
int error;
+ wl_join_params_t join_params;
+ int join_params_size;
WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
@@ -3512,11 +3889,24 @@ wl_iw_set_essid(
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;
}
@@ -3544,7 +3934,6 @@ wl_iw_get_essid(
ssid.SSID_len = dtoh32(ssid.SSID_len);
-
memcpy(extra, ssid.SSID, ssid.SSID_len);
dwrq->length = ssid.SSID_len;
@@ -3569,7 +3958,6 @@ wl_iw_set_nick(
if (!extra)
return -EINVAL;
-
if (dwrq->length > sizeof(iw->nickname))
return -E2BIG;
@@ -4945,8 +5333,15 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
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) {
@@ -5115,7 +5510,6 @@ static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info
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 {
@@ -5171,16 +5565,18 @@ wl_iw_set_cscan(
__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__));
- return -1;
+ 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)));
- return -1;
+ goto exit_proc;
}
#ifdef TLV_DEBUG
@@ -5301,10 +5697,16 @@ wl_iw_set_cscan(
goto exit_proc;
}
-
+ if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
+ WL_ERROR(("%s First ISCAN in progress : ignoring\n", __FUNCTION__));
+ 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;
}
@@ -6275,6 +6677,20 @@ static int wl_iw_set_priv(
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);
@@ -6290,8 +6706,6 @@ static int wl_iw_set_priv(
#endif
else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, "SETSUSPEND", strlen("SETSUSPEND")) == 0)
- ret = wl_iw_set_suspend(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);
@@ -6859,20 +7273,29 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
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) {
+ WL_ERROR(("ROAMING did not succeeded, keep status Quo\n"));
+ goto wl_iw_event_end;
+ }
+ 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;
@@ -7016,6 +7439,20 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
#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));
@@ -7290,6 +7727,8 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
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);
@@ -7313,7 +7752,7 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
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;
diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h
index d49ce24..866fbd5 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.24 2010/07/27 20:46:02 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.35 2010/08/20 02:42:33 Exp $
*/
@@ -45,6 +45,21 @@
#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 "SETSUSPEND"
+#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
@@ -178,6 +193,10 @@ 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) \
@@ -195,6 +214,31 @@ extern int net_os_set_suspend_disable(struct net_device *dev, int val);
iwe_stream_add_point(stream, ends, iwe, extra)
#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, uchar 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, uchar 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 0
+#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 {