net: wireless: bcm4329: Update to Version 4.218.248
authorGreg Goldman <ggoldman@broadcom.com>
Tue, 24 Aug 2010 00:21:26 +0000 (17:21 -0700)
committerColin Cross <ccross@android.com>
Thu, 30 Sep 2010 00:49:45 +0000 (17:49 -0700)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
14 files changed:
drivers/net/wireless/bcm4329/bcmpcispi.c
drivers/net/wireless/bcm4329/bcmsdh_linux.c
drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c
drivers/net/wireless/bcm4329/bcmsdstd.c
drivers/net/wireless/bcm4329/bcmsdstd_linux.c
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_cdc.c
drivers/net/wireless/bcm4329/dhd_common.c
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/dhd_sdio.c
drivers/net/wireless/bcm4329/include/epivers.h
drivers/net/wireless/bcm4329/include/wlioctl.h
drivers/net/wireless/bcm4329/wl_iw.c
drivers/net/wireless/bcm4329/wl_iw.h

index c0a66f1aa3e4aabe9da3615ef165df84c106e6b4..1a8b6717f9244028e9f6e86ad5aa95dd2a845174 100644 (file)
@@ -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++;
index 0555f87fac9c1ab7bcef7cbb7d66c037a6a43e72..910b6d0afdcf949457b3cdd39085f1968701bb2a 100644 (file)
@@ -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,8 @@ 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;
 };
 static bcmsdh_hc_t *sdhcinfo = NULL;
 
@@ -225,6 +226,7 @@ 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.. */
 
        /* chain SDIO Host Controller info together */
        sdhc->next = sdhcinfo;
@@ -338,7 +340,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 +367,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 +442,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),
@@ -592,14 +595,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,6 +616,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);
+       sdhcinfo->oob_irq_registered = FALSE;
 }
 
 void bcmsdh_oob_intr_set(bool enable)
index 196ad4fc1d98fc7eeadf47268d63321ce595e259..8992a4267f9f78ab6047a3f929dc4fef3a9f55d5 100644 (file)
@@ -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>
 
 #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 */                         },
 };
 
index 0b1b575d9629f28e39de3b467dd3e5061c00bfb2..0ca1f8ff8a24f4c8561a028b0edc41ebfa32c4a6 100644 (file)
@@ -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;
 
index ad6d6603fccd5fd23a338c8f57bce619f70dab0f..a8b98e2054a040b65b3063053c83b6ee89d2bfbb 100644 (file)
@@ -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);
index 727760885fbc09f0b28ac3d7872ffa6545a1a4f1..cc7e8cb286b843ec6c64fb75a25df41d092f30ec 100644 (file)
@@ -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 $
  */
 
 /****************
@@ -151,8 +151,12 @@ typedef struct dhd_pub {
        int dongle_error;
 
        /* Suspend disable flag and "in suspend" flag */
-       int suspend_disable_flag;
-       int in_suspend;
+       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];
@@ -412,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);
index 070e95ef773e9ad25a212200140a423494a0dbdb..61f6a6f393a977e96351b669f91204f67c4067d7 100644 (file)
@@ -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);
index ebdff86691912951e04e62be10f6d967a339e4d8..e3e8dcc1a51071543d5e18916444c90cefd7fccc 100644 (file)
@@ -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;
 
@@ -1251,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;
@@ -1398,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;
@@ -1561,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;
@@ -1581,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],
@@ -1760,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;
@@ -1784,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;
                }
 
@@ -1796,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);
                }
 
@@ -1816,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;
@@ -1902,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;
                        }
@@ -1912,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]));
index d8621ae0680ac761d6824560af136ba1449c9da9..eb00dbd1e9b9b90fdf02185afb0ebffdd5564feb 100644 (file)
@@ -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
@@ -217,16 +217,16 @@ print_tainted()
 #include <wl_iw.h>
 #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
 
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
-
 /* Interface control information */
 typedef struct dhd_if {
        struct dhd_info *info;                  /* back pointer to dhd_info */
@@ -502,8 +502,8 @@ extern int unregister_pm_notifier(struct notifier_block *nb);
 
 static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
 {
-       DHD_TRACE(("%s: %d\n", __func__, value));
 #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) {
@@ -518,6 +518,7 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
 #endif
 }
 
+#if defined(CONFIG_HAS_EARLYSUSPEND)
 static int dhd_set_suspend(int value, dhd_pub_t *dhd)
 {
        int power_mode = PM_MAX;
@@ -528,19 +529,29 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
        uint roamvar = 1;
 #endif /* CUSTOMER_HW2 */
 
-       DHD_TRACE(("%s: enter, value = %d\n", __FUNCTION__, value));
+       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);
 
-                       /* set bcn_li_dtim */
+                               /* 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));
@@ -552,6 +563,8 @@ static 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));
@@ -559,11 +572,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
                        /* disable pkt filter */
                        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));
@@ -575,13 +588,13 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
        return 0;
 }
 
-#if defined(CONFIG_HAS_EARLYSUSPEND)
 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);
@@ -2198,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 */
@@ -2876,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)
 {
@@ -2890,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)
 {
@@ -3072,51 +3190,6 @@ int net_os_wake_unlock(struct net_device *dev)
        return ret;
 }
 
-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)
-{
-       dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-       int ret = 0;
-
-       if (dhd) {
-               dhd_os_proto_block(&dhd->pub);
-               ret = dhd_set_suspend(val, &dhd->pub);
-               dhd_os_proto_unblock(&dhd->pub);
-       }
-       return ret;
-}
-
-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;
-}
-
 int net_os_send_hang_message(struct net_device *dev)
 {
        dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
index b409c8dfe7e265c6fe47f7b2c1d9dc97e34ed9c4..94a17d713f792b23f43bd52e6ee88de8e1abf686 100644 (file)
@@ -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>
 /* 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 < 1000000)
 #undef PMU_MAX_TRANSITION_DLY
index 733b13338e3d2d02917ab52b20eb89d77823cd85..caceabd1194b0e66dbdc1193e70b35363b7ba54f 100644 (file)
 
 #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 
index d346945dec94fb18aa5e39bb9af3c9f9ffcb0612..345ba34b94c096b1f95a357cbce2fc79fa591ebf 100644 (file)
@@ -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;                  
index 7a612d59ce1274edf512e3bee6eecdfc4a959934..c6b2e8a6b6fc7a06d599d16589e46a0bf4db388d 100644 (file)
@@ -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;
 
@@ -855,18 +856,25 @@ wl_iw_set_suspend(
 )
 {
        int suspend_flag;
-       int ret;
+       int ret_now;
+       int ret = 0;
+
+       suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0';
 
-       suspend_flag = *(extra + strlen("SETSUSPEND") + 1) - '0';
        if (suspend_flag != 0)
                suspend_flag = 1;
 
-       ret = net_os_set_suspend_disable(dev, suspend_flag);
-       WL_TRACE(("%s: Suspend Flag %d -> %d\n", __func__, ret, suspend_flag));
+       ret_now = net_os_set_suspend_disable(dev, suspend_flag);
 
-       if (ret != suspend_flag)
-               net_os_set_suspend(dev, ret);
-       return 0;
+       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
@@ -920,6 +928,90 @@ wl_iw_get_link_speed(
 }
 
 
+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,
@@ -988,6 +1080,197 @@ exit:
        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(
@@ -1139,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");
@@ -1584,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;
 }
@@ -1604,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;
@@ -1932,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,
@@ -1942,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));
 
@@ -1963,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;
@@ -2770,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;
        }
 
@@ -2857,6 +3188,12 @@ wl_iw_iscan_set_scan(
                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__));
@@ -3353,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;
@@ -3454,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);
@@ -3528,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));
 
@@ -3548,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;
 }
@@ -3580,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;
@@ -3605,7 +3958,6 @@ wl_iw_set_nick(
        if (!extra)
                return -EINVAL;
 
-       
        if (dwrq->length > sizeof(iw->nickname))
                return -E2BIG;
 
@@ -4984,10 +5336,11 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
                goto exit;
        }
 
-       if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
-               WL_ERROR(("%s First ISCAN in progress : ignoring\n",  __FUNCTION__));
-               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);
 
@@ -5344,6 +5697,12 @@ 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:
@@ -6318,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);
@@ -6333,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);
@@ -6902,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;
@@ -7059,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));
@@ -7333,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);
index 82af0c716b12d4b691fde578b293b42e52035b8a..866fbd55b74f7ff69d679fd7fbebaac63e0978e9 100644 (file)
@@ -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 $
  */
 
 
 
 #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
@@ -179,6 +194,7 @@ 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);
 
@@ -198,6 +214,31 @@ extern int net_os_send_hang_message(struct net_device *dev);
        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 {