network: wireless: bcm4329: Update to Version 4.218.238
authorGreg Goldman <ggoldman@broadcom.com>
Thu, 3 Jun 2010 17:58:51 +0000 (10:58 -0700)
committerColin Cross <ccross@android.com>
Thu, 30 Sep 2010 00:49:36 +0000 (17:49 -0700)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
17 files changed:
drivers/net/wireless/bcm4329/Makefile
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_bus.h
drivers/net/wireless/bcm4329/dhd_cdc.c
drivers/net/wireless/bcm4329/dhd_common.c
drivers/net/wireless/bcm4329/dhd_dbg.h
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/dhd_proto.h
drivers/net/wireless/bcm4329/dhd_sdio.c
drivers/net/wireless/bcm4329/include/dhdioctl.h
drivers/net/wireless/bcm4329/include/epivers.h
drivers/net/wireless/bcm4329/include/hndrte_cons.h
drivers/net/wireless/bcm4329/include/proto/802.11.h
drivers/net/wireless/bcm4329/include/proto/ethernet.h
drivers/net/wireless/bcm4329/include/wlioctl.h
drivers/net/wireless/bcm4329/linux_osl.c
drivers/net/wireless/bcm4329/wl_iw.c

index 6d71341d3c3551df46537c92a93aae46228c25b9..a7c0267dfcfca9c236063480b65590895b446710 100644 (file)
@@ -5,6 +5,7 @@ DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2         \
        -DSHOW_EVENTS -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS      \
        -Wall -Wstrict-prototypes -Werror -DOOB_INTR_ONLY -DCUSTOMER_HW2      \
        -DDHD_USE_STATIC_BUF -DMMC_SDIO_ABORT -DDHD_DEBUG_TRAP -DSOFTAP       \
+       -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT        \
        -Idrivers/net/wireless/bcm4329 -Idrivers/net/wireless/bcm4329/include
 
 DHDOFILES = dhd_linux.o linux_osl.o bcmutils.o dhd_common.o dhd_custom_gpio.o \
index 845a316240812990d7ce41d03284dbbde9d05dd4..a6c9ba3d6683853761337313fa25738708e44361 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.29 2010/02/23 06:58:21 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.43 2010/05/18 05:48:53 Exp $
  */
 
 /****************
@@ -150,7 +150,13 @@ typedef struct dhd_pub {
        /* Last error from dongle */
        int dongle_error;
 
+       /* Pkt filter defination */
+       char * pktfilter[100];
+       int pktfilter_count;
+
        uint8 country_code[WLC_CNTRY_BUF_SZ];
+       char eventmask[WL_EVENTING_MASK_LEN];
+
 } dhd_pub_t;
 
        #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
@@ -169,10 +175,10 @@ typedef struct dhd_pub {
 
        #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
        #define SPINWAIT_SLEEP(a, exp, us) do { \
-               uint countdown = (us) + 9; \
-               while ((exp) && (countdown >= 10)) { \
+               uint countdown = (us) + 9999; \
+               while ((exp) && (countdown >= 10000)) { \
                        wait_event_interruptible_timeout(a, FALSE, HZ/100); \
-                       countdown -= 10; \
+                       countdown -= 10000; \
                } \
        } while (0)
 
@@ -270,6 +276,9 @@ extern void dhd_customer_gpio_wlan_ctrl(int onoff);
 extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
 extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
 extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
+#ifdef DHD_DEBUG
+extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size);
+#endif /* DHD_DEBUG */
 #if defined(OOB_INTR_ONLY)
 extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
 #endif /* defined(OOB_INTR_ONLY) */
@@ -316,6 +325,7 @@ extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag);
 extern uint dhd_bus_status(dhd_pub_t *dhdp);
 extern int  dhd_bus_start(dhd_pub_t *dhdp);
 
+extern void print_buf(void *pbuf, int len, int bytes_per_line);
 
 
 typedef enum cust_gpio_modes {
@@ -336,7 +346,7 @@ extern uint dhd_watchdog_ms;
 #if defined(DHD_DEBUG)
 /* Console output poll interval */
 extern uint dhd_console_ms;
-#endif
+#endif /* defined(DHD_DEBUG) */
 
 /* Use interrupts */
 extern uint dhd_intr;
@@ -344,6 +354,27 @@ extern uint dhd_intr;
 /* Use polling */
 extern uint dhd_poll;
 
+/* ARP offload agent mode */
+extern uint dhd_arp_mode;
+
+/* ARP offload enable */
+extern uint dhd_arp_enable;
+
+/* Pkt filte enable control */
+extern uint dhd_pkt_filter_enable;
+
+/*  Pkt filter init setup */
+extern uint dhd_pkt_filter_init;
+
+/* Pkt filter mode control */
+extern uint dhd_master_mode;
+
+/* Roaming mode control */
+extern uint dhd_roam;
+
+/* Roaming mode control */
+extern uint dhd_radio_up;
+
 /* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
 extern int dhd_idletime;
 #define DHD_IDLETIME_TICKS 1
index 93392f98348c6304ba816524dd58ae4445c115cf..9e29fb955444611dad6cd1bc0840963ee68d0359 100644 (file)
@@ -4,7 +4,7 @@
  * Provides type definitions and function prototypes used to link the
  * DHD OS, bus, and protocol modules.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -24,7 +24,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd_bus.h,v 1.4.6.3.2.3.6.5 2009/06/02 21:56:30 Exp $
+ * $Id: dhd_bus.h,v 1.4.6.3.2.3.6.6 2010/05/17 18:18:13 Exp $
  */
 
 #ifndef _dhd_bus_h_
@@ -60,6 +60,10 @@ extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen);
 /* Watchdog timer function */
 extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
 
+#ifdef DHD_DEBUG
+/* Device console input function */
+extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#endif
 
 /* Deferred processing for the bus, return TRUE requests reschedule */
 extern bool dhd_bus_dpc(struct dhd_bus *bus);
index 43b21c389926f9a43e3f2c67f3939f60c56edf64..835b30a9f8f31c7dd241c1c0bb9bc3f11eb5655a 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_cdc.c,v 1.22.4.2.4.7.2.34 2010/01/21 22:08:34 Exp $
+ * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.36 2010/04/14 12:09:11 Exp $
  *
  * BDC is like CDC, except it includes a header for data packets to convey
  * packet priority over the bus, and flags (e.g. to indicate checksum status
 #include <dhd_bus.h>
 #include <dhd_dbg.h>
 
+#ifdef CUSTOMER_HW2
+int wifi_get_mac_addr(unsigned char *buf);
+#endif
+
+extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
 
 /* Packet alignment for most efficient SDIO (can change based on platform) */
 #ifndef DHD_SDALIGN
@@ -193,7 +198,7 @@ done:
        return ret;
 }
 
-static int
+int
 dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 {
        dhd_prot_t *prot = dhd->prot;
@@ -510,270 +515,49 @@ dhd_prot_dstats(dhd_pub_t *dhd)
        return;
 }
 
-int dhd_set_suspend(int value, dhd_pub_t *dhd)
-{
-       int power_mode = PM_MAX;
-       wl_pkt_filter_enable_t  enable_parm;
-       char iovbuf[32];
-       int bcn_li_dtim = 3;
-#ifdef CUSTOMER_HW2
-       uint roamvar = 1;
-#endif /* CUSTOMER_HW2 */
-
-#define htod32(i) i
-
-       if (dhd && dhd->up) {
-               dhd_os_proto_block(dhd);
-               if (value) {
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
-                               (char *)&power_mode, sizeof(power_mode));
-                       /* Enable packet filter, only allow unicast packet to send up */
-                       enable_parm.id = htod32(100);
-                       enable_parm.enable = htod32(1);
-                       bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
-                               sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-                       /* set bcn_li_dtim */
-                       bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
-                               4, iovbuf, sizeof(iovbuf));
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
-                       /* Disable build-in roaming to allowed ext supplicant to take of romaing */
-                       bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#endif /* CUSTOMER_HW2 */
-               } else {
-                       power_mode = PM_FAST;
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
-                               sizeof(power_mode));
-                       /* disable pkt filter */
-                       enable_parm.id = htod32(100);
-                       enable_parm.enable = htod32(0);
-                       bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
-                               sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-                       /* set bcn_li_dtim */
-                       bcn_li_dtim = 0;
-                       bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
-                               4, iovbuf, sizeof(iovbuf));
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
-                       roamvar = 0;
-                       bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-#endif /* CUSTOMER_HW2 */
-               }
-               dhd_os_proto_unblock(dhd);
-       }
-
-       return 0;
-}
-
-#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
-
-/* Convert user's input in hex pattern to byte-size mask */
-static int
-wl_pattern_atoh(char *src, char *dst)
-{
-       int i;
-       if (strncmp(src, "0x", 2) != 0 &&
-           strncmp(src, "0X", 2) != 0) {
-               printf("Mask invalid format. Needs to start with 0x\n");
-               return -1;
-       }
-       src = src + 2; /* Skip past 0x */
-       if (strlen(src) % 2 != 0) {
-               printf("Mask invalid format. Needs to be of even length\n");
-               return -1;
-       }
-       for (i = 0; *src != '\0'; i++) {
-               char num[3];
-               strncpy(num, src, 2);
-               num[2] = '\0';
-               dst[i] = (uint8)strtoul(num, NULL, 16);
-               src += 2;
-       }
-       return i;
-}
-
 int
-dhd_preinit_ioctls(dhd_pub_t *dhd)
+dhd_prot_init(dhd_pub_t *dhd)
 {
-       char eventmask[WL_EVENTING_MASK_LEN];
-       char iovbuf[WL_EVENTING_MASK_LEN + 12]; /*  Room for "event_msgs" + '\0' + bitvec  */
-       int ret;
-       uint up = 0;
+       int ret = 0;
+       char buf[128];
 #ifdef CUSTOMER_HW2
-       uint roamvar = 0;
-#else
-       uint roamvar = 1;
+       struct ether_addr ea_addr;
 #endif
-       uint power_mode = PM_FAST;
-       uint32 dongle_align = DHD_SDALIGN;
-       uint32 glom = 0;
-
-       uint bcn_timeout = 3;
-       int arpoe = 1;
-       int arp_ol = 0xf;
-       int scan_assoc_time = 40;
-       int scan_unassoc_time = 80;
-       const char                              *str;
-       wl_pkt_filter_t         pkt_filter;
-       wl_pkt_filter_t         *pkt_filterp;
-       int                                             buf_len;
-       int                                             str_len;
-       uint32                                  mask_size;
-       uint32                                  pattern_size;
-       char buf[256];
-       uint filter_mode = 1;
+       DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
        dhd_os_proto_block(dhd);
-       /* Get the device MAC address */
-       strcpy(iovbuf, "cur_etheraddr");
-       if ((ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
-               DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
-               dhd_os_proto_unblock(dhd);
-               return BCME_NOTUP;
-       }
-       memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
 
-       /* Set Country code */
-       if (dhd->country_code[0] != 0) {
-               if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
-                       dhd->country_code, sizeof(dhd->country_code)) < 0) {
-                       DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
+#ifdef CUSTOMER_HW2
+       /* Set the device MAC address if applicable */
+       ret = wifi_get_mac_addr(ea_addr.octet);
+       if (!ret) {
+               bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
+               ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+               if (ret < 0) {
+                       DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+                       goto fail;
                }
        }
+#endif
 
-       /* Set PowerSave mode */
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode));
-
-       /* Match Host and Dongle rx alignment */
-       bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-       /* disable glom option per default */
-       bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-       /* Setup timeout if Beacons are lost and roam is off to report link down */
-       if (roamvar) {
-               bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
-               dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-       }
-
-       /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */
-       bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-       /* Force STA UP */
-       dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
-
-       /* Setup event_msgs */
-       bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
-       dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
-       bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
-
-       setbit(eventmask, WLC_E_SET_SSID);
-       setbit(eventmask, WLC_E_PRUNE);
-       setbit(eventmask, WLC_E_AUTH);
-       setbit(eventmask, WLC_E_REASSOC);
-       setbit(eventmask, WLC_E_REASSOC_IND);
-       setbit(eventmask, WLC_E_DEAUTH_IND);
-       setbit(eventmask, WLC_E_DISASSOC_IND);
-       setbit(eventmask, WLC_E_DISASSOC);
-       setbit(eventmask, WLC_E_JOIN);
-       setbit(eventmask, WLC_E_ASSOC_IND);
-       setbit(eventmask, WLC_E_PSK_SUP);
-       setbit(eventmask, WLC_E_LINK);
-       setbit(eventmask, WLC_E_NDIS_LINK);
-       setbit(eventmask, WLC_E_MIC_ERROR);
-       setbit(eventmask, WLC_E_PMKID_CACHE);
-       setbit(eventmask, WLC_E_TXFAIL);
-       setbit(eventmask, WLC_E_JOIN_START);
-       setbit(eventmask, WLC_E_SCAN_COMPLETE);
-
-       bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
-               sizeof(scan_assoc_time));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
-               sizeof(scan_unassoc_time));
-
-       /* Set ARP offload */
-       bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-       bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-       /* add a default packet filter pattern */
-       str = "pkt_filter_add";
-       str_len = strlen(str);
-       strncpy(buf, str, str_len);
-       buf[ str_len ] = '\0';
-       buf_len = str_len + 1;
-
-       pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
-
-       /* Parse packet filter id. */
-       pkt_filter.id = htod32(100);
-
-       /* Parse filter polarity. */
-       pkt_filter.negate_match = htod32(0);
-
-       /* Parse filter type. */
-       pkt_filter.type = htod32(0);
-
-       /* Parse pattern filter offset. */
-       pkt_filter.u.pattern.offset = htod32(0);
-
-       /* Parse pattern filter mask. */
-       mask_size =     htod32(wl_pattern_atoh("0xff",
-               (char *) pkt_filterp->u.pattern.mask_and_pattern));
-
-       /* Parse pattern filter pattern. */
-       pattern_size = htod32(wl_pattern_atoh("0x00",
-               (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
-
-       if (mask_size != pattern_size) {
-               DHD_ERROR(("Mask and pattern not the same size\n"));
-               dhd_os_proto_unblock(dhd);
-               return -EINVAL;
+       /* Get the device MAC address */
+       strcpy(buf, "cur_etheraddr");
+       ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+       if (ret < 0) {
+               goto fail;
        }
+       memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
 
-       pkt_filter.u.pattern.size_bytes = mask_size;
-       buf_len += WL_PKT_FILTER_FIXED_LEN;
-       buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
-
-       /* Keep-alive attributes are set in local       variable (keep_alive_pkt), and
-       ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
-       ** guarantee that the buffer is properly aligned.
-       */
-       memcpy((char *)pkt_filterp, &pkt_filter,
-               WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
-
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
-
-       /* set mode to allow pattern */
-       bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf));
-       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-       dhd_os_proto_unblock(dhd);
-       return 0;
-}
-
-int
-dhd_prot_init(dhd_pub_t *dhd)
-{
-       int ret = 0;
-       DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-
+#ifdef EMBEDDED_PLATFORM
        ret = dhd_preinit_ioctls(dhd);
+#endif /* EMBEDDED_PLATFORM */
 
        /* Always assumes wl for now */
        dhd->iswl = TRUE;
 
+fail:
+       dhd_os_proto_unblock(dhd);
+
        return ret;
 }
 
index a0e6a7370d5d41405a3d5d245401f068301dc419..1fd07215fe9b5e2a869986e37f9b1a8d4539bb07 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.41 2010/02/24 01:52:41 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.60 2010/05/26 03:36:55 Exp $
  */
 #include <typedefs.h>
 #include <osl.h>
@@ -38,6 +38,8 @@
 #include <msgtrace.h>
 
 
+#include <wlioctl.h>
+
 int dhd_msg_level;
 
 char fw_path[MOD_PARAM_PATHLEN];
@@ -48,6 +50,25 @@ uint32 dhd_conn_event;
 uint32 dhd_conn_status;
 uint32 dhd_conn_reason;
 
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+
+extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
+extern void dhd_ind_scan_confirm(void *h, bool status);
+extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen);
+void dhd_iscan_lock(void);
+void dhd_iscan_unlock(void);
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#ifndef DHD_SDALIGN
+#define DHD_SDALIGN    32
+#endif
+#if !ISPOWEROF2(DHD_SDALIGN)
+#error DHD_SDALIGN is not a power of 2!
+#endif
+
 #ifdef DHD_DEBUG
 const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on "
        __DATE__ " at " __TIME__;
@@ -57,7 +78,6 @@ const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
 
 void dhd_set_timer(void *bus, uint wdtick);
 
-
 /* IOVar table */
 enum {
        IOV_VERSION = 1,
@@ -66,6 +86,10 @@ enum {
        IOV_BCMERROR,
        IOV_WDTICK,
        IOV_DUMP,
+#ifdef DHD_DEBUG
+       IOV_CONS,
+       IOV_DCONSOLE_POLL,
+#endif
        IOV_CLEARCOUNTS,
        IOV_LOGDUMP,
        IOV_LOGCAL,
@@ -84,6 +108,10 @@ const bcm_iovar_t dhd_iovars[] = {
        {"bcmerror",    IOV_BCMERROR,   0,      IOVT_INT8,      0 },
        {"wdtick",      IOV_WDTICK, 0,  IOVT_UINT32,    0 },
        {"dump",        IOV_DUMP,       0,      IOVT_BUFFER,    DHD_IOCTL_MAXLEN },
+#ifdef DHD_DEBUG
+       {"dconpoll",    IOV_DCONSOLE_POLL, 0,   IOVT_UINT32,    0 },
+       {"cons",        IOV_CONS,       0,      IOVT_BUFFER,    0 },
+#endif
        {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID,  0 },
        {"gpioob",      IOV_GPIOOB,     0,      IOVT_UINT32,    0 },
        {"ioctl_timeout",       IOV_IOCTLTIMEOUT,       0,      IOVT_UINT32,    0 },
@@ -223,6 +251,21 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
                bcmerror = dhd_dump(dhd_pub, arg, len);
                break;
 
+#ifdef DHD_DEBUG
+       case IOV_GVAL(IOV_DCONSOLE_POLL):
+               int_val = (int32)dhd_console_ms;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_DCONSOLE_POLL):
+               dhd_console_ms = (uint)int_val;
+               break;
+
+       case IOV_SVAL(IOV_CONS):
+               if (len > 0)
+                       bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+               break;
+#endif
 
        case IOV_SVAL(IOV_CLEARCOUNTS):
                dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
@@ -892,3 +935,759 @@ wl_event_to_host_order(wl_event_msg_t *evt)
        evt->datalen = ntoh32(evt->datalen);
        evt->version = ntoh16(evt->version);
 }
+
+void print_buf(void *pbuf, int len, int bytes_per_line)
+{
+       int i, j = 0;
+       unsigned char *buf = pbuf;
+
+       if (bytes_per_line == 0) {
+               bytes_per_line = len;
+       }
+
+       for (i = 0; i < len; i++) {
+               printf("%2.2x", *buf++);
+               j++;
+               if (j == bytes_per_line) {
+                       printf("\n");
+                       j = 0;
+               } else {
+                       printf(":");
+               }
+       }
+       printf("\n");
+}
+
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+
+/* Convert user's input in hex pattern to byte-size mask */
+static int
+wl_pattern_atoh(char *src, char *dst)
+{
+       int i;
+       if (strncmp(src, "0x", 2) != 0 &&
+           strncmp(src, "0X", 2) != 0) {
+               DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
+               return -1;
+       }
+       src = src + 2; /* Skip past 0x */
+       if (strlen(src) % 2 != 0) {
+               DHD_ERROR(("Mask invalid format. Needs to be of even length\n"));
+               return -1;
+       }
+       for (i = 0; *src != '\0'; i++) {
+               char num[3];
+               strncpy(num, src, 2);
+               num[2] = '\0';
+               dst[i] = (uint8)strtoul(num, NULL, 16);
+               src += 2;
+       }
+       return i;
+}
+
+void
+dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode)
+{
+       char                            *argv[8];
+       int                                     i = 0;
+       const char                      *str;
+       int                                     buf_len;
+       int                                     str_len;
+       char                            *arg_save = 0, *arg_org = 0;
+       int                                     rc;
+       char                            buf[128];
+       wl_pkt_filter_enable_t  enable_parm;
+       wl_pkt_filter_enable_t  * pkt_filterp;
+
+       if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
+               DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+               goto fail;
+       }
+       arg_org = arg_save;
+       memcpy(arg_save, arg, strlen(arg) + 1);
+
+       argv[i] = bcmstrtok(&arg_save, " ", 0);
+
+       i = 0;
+       if (NULL == argv[i]) {
+               DHD_ERROR(("No args provided\n"));
+               goto fail;
+       }
+
+       str = "pkt_filter_enable";
+       str_len = strlen(str);
+       strncpy(buf, str, str_len);
+       buf[str_len] = '\0';
+       buf_len = str_len + 1;
+
+       pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1);
+
+       /* Parse packet filter id. */
+       enable_parm.id = htod32(strtoul(argv[i], NULL, 0));
+
+       /* Parse enable/disable value. */
+       enable_parm.enable = htod32(enable);
+
+       buf_len += sizeof(enable_parm);
+       memcpy((char *)pkt_filterp,
+              &enable_parm,
+              sizeof(enable_parm));
+
+       /* Enable/disable the specified filter. */
+       rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+       rc = rc >= 0 ? 0 : rc;
+       if (rc)
+               DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+               __FUNCTION__, arg, rc));
+       else
+               DHD_TRACE(("%s: successfully added pktfilter %s\n",
+               __FUNCTION__, arg));
+
+       /* Contorl the master mode */
+       bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, sizeof(buf));
+       rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+       rc = rc >= 0 ? 0 : rc;
+       if (rc)
+               DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+               __FUNCTION__, arg, rc));
+
+fail:
+       if (arg_org)
+               MFREE(dhd->osh, arg_org, strlen(arg) + 1);
+}
+
+void
+dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
+{
+       const char                      *str;
+       wl_pkt_filter_t         pkt_filter;
+       wl_pkt_filter_t         *pkt_filterp;
+       int                                     buf_len;
+       int                                     str_len;
+       int                             rc;
+       uint32                          mask_size;
+       uint32                          pattern_size;
+       char                            *argv[8], * buf = 0;
+       int                                     i = 0;
+       char                            *arg_save = 0, *arg_org = 0;
+#define BUF_SIZE               2048
+
+       if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
+               DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+               goto fail;
+       }
+
+       arg_org = arg_save;
+
+       if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) {
+               DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+               goto fail;
+       }
+
+       memcpy(arg_save, arg, strlen(arg) + 1);
+
+       if (strlen(arg) > BUF_SIZE) {
+               DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf)));
+               goto fail;
+       }
+
+       argv[i] = bcmstrtok(&arg_save, " ", 0);
+       while (argv[i++])
+               argv[i] = bcmstrtok(&arg_save, " ", 0);
+
+       i = 0;
+       if (NULL == argv[i]) {
+               DHD_ERROR(("No args provided\n"));
+               goto fail;
+       }
+
+       str = "pkt_filter_add";
+       str_len = strlen(str);
+       strncpy(buf, str, str_len);
+       buf[ str_len ] = '\0';
+       buf_len = str_len + 1;
+
+       pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+
+       /* Parse packet filter id. */
+       pkt_filter.id = htod32(strtoul(argv[i], NULL, 0));
+
+       if (NULL == argv[++i]) {
+               DHD_ERROR(("Polarity not provided\n"));
+               goto fail;
+       }
+
+       /* Parse filter polarity. */
+       pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0));
+
+       if (NULL == argv[++i]) {
+               DHD_ERROR(("Filter type not provided\n"));
+               goto fail;
+       }
+
+       /* Parse filter type. */
+       pkt_filter.type = htod32(strtoul(argv[i], NULL, 0));
+
+       if (NULL == argv[++i]) {
+               DHD_ERROR(("Offset not provided\n"));
+               goto fail;
+       }
+
+       /* Parse pattern filter offset. */
+       pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0));
+
+       if (NULL == argv[++i]) {
+               DHD_ERROR(("Bitmask not provided\n"));
+               goto fail;
+       }
+
+       /* Parse pattern filter mask. */
+       mask_size =
+               htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern));
+
+       if (NULL == argv[++i]) {
+               DHD_ERROR(("Pattern not provided\n"));
+               goto fail;
+       }
+
+       /* Parse pattern filter pattern. */
+       pattern_size =
+               htod32(wl_pattern_atoh(argv[i],
+                (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
+
+       if (mask_size != pattern_size) {
+               DHD_ERROR(("Mask and pattern not the same size\n"));
+               goto fail;
+       }
+
+       pkt_filter.u.pattern.size_bytes = mask_size;
+       buf_len += WL_PKT_FILTER_FIXED_LEN;
+       buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
+
+       /* Keep-alive attributes are set in local       variable (keep_alive_pkt), and
+       ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
+       ** guarantee that the buffer is properly aligned.
+       */
+       memcpy((char *)pkt_filterp,
+              &pkt_filter,
+              WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+
+       rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+       rc = rc >= 0 ? 0 : rc;
+
+       if (rc)
+               DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+               __FUNCTION__, arg, rc));
+       else
+               DHD_TRACE(("%s: successfully added pktfilter %s\n",
+               __FUNCTION__, arg));
+
+fail:
+       if (arg_org)
+               MFREE(dhd->osh, arg_org, strlen(arg) + 1);
+
+       if (buf)
+               MFREE(dhd->osh, buf, BUF_SIZE);
+}
+
+void
+dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode)
+{
+       char iovbuf[32];
+       int retcode;
+
+       bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+       retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+       retcode = retcode >= 0 ? 0 : retcode;
+       if (retcode)
+               DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n",
+               __FUNCTION__, arp_mode, retcode));
+       else
+               DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
+               __FUNCTION__, arp_mode));
+}
+
+void
+dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
+{
+       char iovbuf[32];
+       int retcode;
+
+       bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
+       retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+       retcode = retcode >= 0 ? 0 : retcode;
+       if (retcode)
+               DHD_TRACE(("%s: failed to enabe ARP offload to %d, retcode = %d\n",
+               __FUNCTION__, arp_enable, retcode));
+       else
+               DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
+               __FUNCTION__, arp_enable));
+}
+
+int
+dhd_preinit_ioctls(dhd_pub_t *dhd)
+{
+       char iovbuf[WL_EVENTING_MASK_LEN + 12]; /*  Room for "event_msgs" + '\0' + bitvec  */
+       uint up = 0;
+       char buf[128], *ptr;
+       uint power_mode = PM_FAST;
+       uint32 dongle_align = DHD_SDALIGN;
+       uint32 glom = 0;
+       uint bcn_timeout = 3;
+       int scan_assoc_time = 40;
+       int scan_unassoc_time = 80;
+
+       /* Set Country code */
+       if (dhd->country_code[0] != 0) {
+               if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
+                       dhd->country_code, sizeof(dhd->country_code)) < 0) {
+                       DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
+               }
+       }
+
+       /* query for 'ver' to get version info from firmware */
+       memset(buf, 0, sizeof(buf));
+       ptr = buf;
+       bcm_mkiovar("ver", 0, 0, buf, sizeof(buf));
+       dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+       bcmstrtok(&ptr, "\n", 0);
+       /* Print fw version info */
+       DHD_ERROR(("Firmware version = %s\n", buf));
+
+       /* Set PowerSave mode */
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode));
+
+       /* Match Host and Dongle rx alignment */
+       bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+       /* disable glom option per default */
+       bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+       /* Setup timeout if Beacons are lost and roam is off to report link down */
+       bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+       /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */
+       bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf));
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+       /* Force STA UP */
+       if (dhd_radio_up)
+               dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+
+       /* Setup event_msgs */
+       bcm_mkiovar("event_msgs", dhd->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
+               sizeof(scan_assoc_time));
+       dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
+               sizeof(scan_unassoc_time));
+
+#ifdef ARP_OFFLOAD_SUPPORT
+       /* Set and enable ARP offload feature */
+       if (dhd_arp_enable)
+               dhd_arp_offload_set(dhd, dhd_arp_mode);
+       dhd_arp_offload_enable(dhd, dhd_arp_enable);
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+#ifdef PKT_FILTER_SUPPORT
+       {
+               int i;
+               /* Set up pkt filter */
+               if (dhd_pkt_filter_enable) {
+                       for (i = 0; i < dhd->pktfilter_count; i++) {
+                               dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
+                               dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
+                                       dhd_pkt_filter_init, dhd_master_mode);
+                       }
+               }
+       }
+#endif /* PKT_FILTER_SUPPORT */
+
+       return 0;
+}
+
+#ifdef SIMPLE_ISCAN
+
+uint iscan_thread_id;
+iscan_buf_t * iscan_chain = 0;
+
+iscan_buf_t *
+dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
+{
+       iscan_buf_t *iscanbuf_alloc = 0;
+       iscan_buf_t *iscanbuf_head;
+
+       dhd_iscan_lock();
+
+       iscanbuf_alloc = (iscan_buf_t*)MALLOC(dhd->osh, sizeof(iscan_buf_t));
+       if (iscanbuf_alloc == NULL)
+               goto fail;
+
+       iscanbuf_alloc->next = NULL;
+       iscanbuf_head = *iscanbuf;
+
+       DHD_ISCAN(("%s: addr of allocated node = 0x%X, addr of iscanbuf_head \
+               = 0x%X dhd = 0x%X\n", __FUNCTION__, iscanbuf_alloc,
+               iscanbuf_head, dhd));
+
+       if (iscanbuf_head == NULL) {
+               *iscanbuf = iscanbuf_alloc;
+               DHD_ISCAN(("%s: Head is allocated\n", __FUNCTION__));
+               goto fail;
+       }
+
+       while (iscanbuf_head->next)
+               iscanbuf_head = iscanbuf_head->next;
+
+       iscanbuf_head->next = iscanbuf_alloc;
+
+fail:
+       dhd_iscan_unlock();
+       return iscanbuf_alloc;
+}
+
+void
+dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
+{
+       iscan_buf_t *iscanbuf_free = 0;
+       iscan_buf_t *iscanbuf_prv = 0;
+       iscan_buf_t *iscanbuf_cur = iscan_chain;
+       dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+
+       dhd_iscan_lock();
+       /* If iscan_delete is null then delete the entire 
+        * chain or else delete specific one provided
+        */
+       if (!iscan_delete) {
+               while (iscanbuf_cur) {
+                       iscanbuf_free = iscanbuf_cur;
+                       iscanbuf_cur = iscanbuf_cur->next;
+                       iscanbuf_free->next = 0;
+                       MFREE(dhd->osh, iscanbuf_free, sizeof(iscan_buf_t));
+               }
+               iscan_chain = 0;
+       } else {
+               while (iscanbuf_cur) {
+                       if (iscanbuf_cur == iscan_delete)
+                               break;
+                       iscanbuf_prv = iscanbuf_cur;
+                       iscanbuf_cur = iscanbuf_cur->next;
+               }
+               if (iscanbuf_prv)
+                       iscanbuf_prv->next = iscan_delete->next;
+
+               iscan_delete->next = 0;
+               MFREE(dhd->osh, iscan_delete, sizeof(iscan_buf_t));
+
+               if (!iscanbuf_prv)
+                       iscan_chain = 0;
+       }
+       dhd_iscan_unlock();
+}
+
+iscan_buf_t *
+dhd_iscan_result_buf(void)
+{
+       return iscan_chain;
+}
+
+
+
+/*
+* print scan cache
+* print partial iscan_skip list differently
+*/
+int
+dhd_iscan_print_cache(iscan_buf_t *iscan_skip)
+{
+       int i = 0, l = 0;
+       iscan_buf_t *iscan_cur;
+       wl_iscan_results_t *list;
+       wl_scan_results_t *results;
+       wl_bss_info_t UNALIGNED *bi;
+
+       dhd_iscan_lock();
+
+       iscan_cur = dhd_iscan_result_buf();
+
+       while (iscan_cur) {
+               list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+               if (!list)
+                       break;
+
+               results = (wl_scan_results_t *)&list->results;
+               if (!results)
+                       break;
+
+               if (results->version != WL_BSS_INFO_VERSION) {
+                       DHD_ISCAN(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+                               __FUNCTION__, results->version));
+                       goto done;
+               }
+
+               bi = results->bss_info;
+               for (i = 0; i < results->count; i++) {
+                       if (!bi)
+                               break;
+
+                       DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
+                               iscan_cur != iscan_skip?"BSS":"bss", l, i,
+                               bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+                               bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5]));
+
+                       bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+               }
+               iscan_cur = iscan_cur->next;
+               l++;
+       }
+
+done:
+       dhd_iscan_unlock();
+       return 0;
+}
+
+/*
+* delete disappeared AP from specific scan cache but skip partial list in iscan_skip
+*/
+int
+dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
+{
+       int i = 0, j = 0, l = 0;
+       iscan_buf_t *iscan_cur;
+       wl_iscan_results_t *list;
+       wl_scan_results_t *results;
+       wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+
+       uchar *s_addr = addr;
+
+       dhd_iscan_lock();
+       DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n",
+               __FUNCTION__, s_addr[0], s_addr[1], s_addr[2],
+               s_addr[3], s_addr[4], s_addr[5]));
+
+       iscan_cur = dhd_iscan_result_buf();
+
+       while (iscan_cur) {
+               if (iscan_cur != iscan_skip) {
+                       list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+                       if (!list)
+                               break;
+
+                       results = (wl_scan_results_t *)&list->results;
+                       if (!results)
+                               break;
+
+                       if (results->version != WL_BSS_INFO_VERSION) {
+                               DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+                               __FUNCTION__, results->version));
+                               goto done;
+                       }
+
+                       bi = results->bss_info;
+                       for (i = 0; i < results->count; i++) {
+                               if (!bi)
+                                       break;
+
+                               if (!memcmp(bi->BSSID.octet, addr, ETHER_ADDR_LEN)) {
+                                       DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n", \
+                                       __FUNCTION__, l, i, bi->BSSID.octet[0], \
+                                       bi->BSSID.octet[1], bi->BSSID.octet[2], \
+                                       bi->BSSID.octet[3], bi->BSSID.octet[4], \
+                                       bi->BSSID.octet[5]));
+
+                                       bi_new = bi;
+                                       bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+/*
+                                       if(bi && bi_new) {
+                                               bcopy(bi, bi_new, results->buflen -
+                                               dtoh32(bi_new->length));
+                                               results->buflen -= dtoh32(bi_new->length);
+                                       }
+*/
+                                       results->buflen -= dtoh32(bi_new->length);
+                                       results->count--;
+
+                                       for (j = i; j < results->count; j++) {
+                                               if (bi && bi_new) {
+                                                       DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d] \
+                                                       %X:%X:%X:%X:%X:%X\n",
+                                                       __FUNCTION__, l, j, bi->BSSID.octet[0],
+                                                       bi->BSSID.octet[1], bi->BSSID.octet[2],
+                                                       bi->BSSID.octet[3], bi->BSSID.octet[4],
+                                                       bi->BSSID.octet[5]));
+
+                                                       bi_next = (wl_bss_info_t *)((uintptr)bi +
+                                                               dtoh32(bi->length));
+                                                       bcopy(bi, bi_new, dtoh32(bi->length));
+                                                       bi_new = (wl_bss_info_t *)((uintptr)bi_new +
+                                                               dtoh32(bi_new->length));
+                                                       bi = bi_next;
+                                               }
+                                       }
+
+                                       if (results->count == 0) {
+                                               /* Prune now empty partial scan list */
+                                               dhd_iscan_free_buf(dhdp, iscan_cur);
+                                               goto done;
+                                       }
+                                       break;
+                               }
+                               bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+                       }
+               }
+               iscan_cur = iscan_cur->next;
+               l++;
+       }
+
+done:
+       dhd_iscan_unlock();
+       return 0;
+}
+
+int
+dhd_iscan_remove_duplicates(void * dhdp, iscan_buf_t *iscan_cur)
+{
+       int i = 0;
+       wl_iscan_results_t *list;
+       wl_scan_results_t *results;
+       wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+
+       dhd_iscan_lock();
+
+       DHD_ISCAN(("%s: Scan cache before delete\n",
+               __FUNCTION__));
+       dhd_iscan_print_cache(iscan_cur);
+
+       if (!iscan_cur)
+               goto done;
+
+       list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+       if (!list)
+               goto done;
+
+       results = (wl_scan_results_t *)&list->results;
+       if (!results)
+               goto done;
+
+       if (results->version != WL_BSS_INFO_VERSION) {
+               DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+                       __FUNCTION__, results->version));
+               goto done;
+       }
+
+       bi = results->bss_info;
+       for (i = 0; i < results->count; i++) {
+               if (!bi)
+                       break;
+
+               DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n",
+                       __FUNCTION__, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+                       bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5]));
+
+               dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
+
+               bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+       }
+
+done:
+       DHD_ISCAN(("%s: Scan cache after delete\n", __FUNCTION__));
+       dhd_iscan_print_cache(iscan_cur);
+       dhd_iscan_unlock();
+       return 0;
+}
+
+void
+dhd_iscan_ind_scan_confirm(void *dhdp, bool status)
+{
+
+       dhd_ind_scan_confirm(dhdp, status);
+}
+
+int
+dhd_iscan_request(void * dhdp, uint16 action)
+{
+       int rc;
+       wl_iscan_params_t params;
+       dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+       char buf[WLC_IOCTL_SMLEN];
+
+
+       memset(&params, 0, sizeof(wl_iscan_params_t));
+       memcpy(&params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+       params.params.bss_type = DOT11_BSSTYPE_ANY;
+       params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
+
+       params.params.nprobes = htod32(-1);
+       params.params.active_time = htod32(-1);
+       params.params.passive_time = htod32(-1);
+       params.params.home_time = htod32(-1);
+       params.params.channel_num = htod32(0);
+
+       params.version = htod32(ISCAN_REQ_VERSION);
+       params.action = htod16(action);
+       params.scan_duration = htod16(0);
+
+       bcm_mkiovar("iscan", (char *)&params, sizeof(wl_iscan_params_t), buf, WLC_IOCTL_SMLEN);
+       rc = dhd_wl_ioctl(dhdp, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN);
+
+       return rc;
+}
+
+static int
+dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
+{
+       wl_iscan_results_t *list_buf;
+       wl_iscan_results_t list;
+       wl_scan_results_t *results;
+       iscan_buf_t *iscan_cur;
+       int status = -1;
+       dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+       int rc;
+
+
+       iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain);
+       if (!iscan_cur) {
+               DHD_ERROR(("%s: Failed to allocate node\n", __FUNCTION__));
+               dhd_iscan_free_buf(dhdp, 0);
+               dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT);
+               goto fail;
+       }
+
+       dhd_iscan_lock();
+
+       memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
+       list_buf = (wl_iscan_results_t*)iscan_cur->iscan_buf;
+       results = &list_buf->results;
+       results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+       results->version = 0;
+       results->count = 0;
+
+       memset(&list, 0, sizeof(list));
+       list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+       bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
+               iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
+       rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
+
+       results->buflen = dtoh32(results->buflen);
+       results->version = dtoh32(results->version);
+       *scan_count = results->count = dtoh32(results->count);
+       status = dtoh32(list_buf->status);
+
+       dhd_iscan_unlock();
+
+       if (!(*scan_count))
+               dhd_iscan_free_buf(dhdp, iscan_cur);
+       else
+               dhd_iscan_remove_duplicates(dhdp, iscan_cur);
+
+
+fail:
+       return status;
+}
+
+#endif 
index e6d18f7abfb15d4233f614b286a050c6c2d8d790..b48c1d70f1441c8dde928f24ac7d9b3823d50d93 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_dbg.h,v 1.5.6.2.4.2.14.4 2009/12/11 01:13:49 Exp $
+ * $Id: dhd_dbg.h,v 1.5.6.2.4.2.14.10 2010/05/21 21:49:38 Exp $
  */
 
 #ifndef _dhd_dbg_
@@ -42,6 +42,7 @@
 #define DHD_GLOM(args)         do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0)
 #define DHD_EVENT(args)                do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0)
 #define DHD_BTA(args)          do {if (dhd_msg_level & DHD_BTA_VAL) printf args;} while (0)
+#define DHD_ISCAN(args)                do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0)
 
 #define DHD_ERROR_ON()         (dhd_msg_level & DHD_ERROR_VAL)
 #define DHD_TRACE_ON()         (dhd_msg_level & DHD_TRACE_VAL)
@@ -55,6 +56,7 @@
 #define DHD_GLOM_ON()          (dhd_msg_level & DHD_GLOM_VAL)
 #define DHD_EVENT_ON()         (dhd_msg_level & DHD_EVENT_VAL)
 #define DHD_BTA_ON()           (dhd_msg_level & DHD_BTA_VAL)
+#define DHD_ISCAN_ON()         (dhd_msg_level & DHD_ISCAN_VAL)
 
 #else /* DHD_DEBUG */
 
@@ -70,6 +72,7 @@
 #define DHD_GLOM(args)
 #define DHD_EVENT(args)
 #define DHD_BTA(args)
+#define DHD_ISCAN(args)
 
 #define DHD_ERROR_ON()         0
 #define DHD_TRACE_ON()         0
@@ -83,7 +86,7 @@
 #define DHD_GLOM_ON()          0
 #define DHD_EVENT_ON()         0
 #define DHD_BTA_ON()           0
-
+#define DHD_ISCAN_ON()         0
 #endif /* DHD_DEBUG */
 
 #define DHD_LOG(args)
index a9dcb3ba319276fa283e0d3ec2093b8557eeaa0a..5a0a8892cd1916859ca412d895377d735179ce7b 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.66 2010/04/01 17:01:25 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.86 2010/05/18 05:48:53 Exp $
  */
 
 #ifdef CONFIG_WIFI_CONTROL_FUNC
@@ -115,6 +115,17 @@ int wifi_set_reset(int on, unsigned long msec)
        return 0;
 }
 
+int wifi_get_mac_addr(unsigned char *buf)
+{
+       printk("%s\n", __FUNCTION__);
+       if (!buf)
+               return -EINVAL;
+       if (wifi_control_data && wifi_control_data->get_mac_addr) {
+               return wifi_control_data->get_mac_addr(buf);
+       }
+       return -EOPNOTSUPP;
+}
+
 static int wifi_probe(struct platform_device *pdev)
 {
        struct wifi_platform_data *wifi_ctrl =
@@ -204,10 +215,13 @@ print_tainted()
 /* Linux wireless extension support */
 #if defined(CONFIG_WIRELESS_EXT)
 #include <wl_iw.h>
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 #if defined(CONFIG_HAS_EARLYSUSPEND)
 #include <linux/earlysuspend.h>
+extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
+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) */
 
 /* Interface control information */
@@ -229,7 +243,7 @@ typedef struct dhd_if {
 typedef struct dhd_info {
 #if defined(CONFIG_WIRELESS_EXT)
        wl_iw_t         iw;             /* wireless extensions state (must be first) */
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
        dhd_pub_t pub;
 
@@ -285,7 +299,8 @@ char nvram_path[MOD_PARAM_PATHLEN];
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 struct semaphore dhd_registration_sem;
-#endif 
+#define DHD_REGISTRATION_TIMEOUT  8000  /* msec : allowed time to finished dhd registration */
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
 /* load firmware and/or nvram values from the filesystem */
 module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
 module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
@@ -305,7 +320,27 @@ module_param(dhd_watchdog_ms, uint, 0);
 /* Console poll interval */
 uint dhd_console_ms = 0;
 module_param(dhd_console_ms, uint, 0);
-#endif
+#endif /* DHD_DEBUG */
+
+/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */
+uint dhd_arp_mode = 0xb;
+module_param(dhd_arp_mode, uint, 0);
+
+/* ARP offload enable */
+uint dhd_arp_enable = TRUE;
+module_param(dhd_arp_enable, uint, 0);
+
+/* Global Pkt filter enable control */
+uint dhd_pkt_filter_enable = TRUE;
+module_param(dhd_pkt_filter_enable, uint, 0);
+
+/*  Pkt filter init setup */
+uint dhd_pkt_filter_init = 0;
+module_param(dhd_pkt_filter_init, uint, 0);
+
+/* Pkt filter mode control */
+uint dhd_master_mode = TRUE;
+module_param(dhd_master_mode, uint, 1);
 
 /* Watchdog thread priority, -1 to use kernel timer */
 int dhd_watchdog_prio = 97;
@@ -319,6 +354,16 @@ module_param(dhd_dpc_prio, int, 0);
 extern int dhd_dongle_memsize;
 module_param(dhd_dongle_memsize, int, 0);
 
+/* Contorl fw roaming */
+#ifdef CUSTOMER_HW2
+uint dhd_roam = 0;
+#else
+uint dhd_roam = 1;
+#endif
+
+/* Control radio state */
+uint dhd_radio_up = 1;
+
 /* Network inteface name */
 char iface_name[IFNAMSIZ];
 module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
@@ -404,7 +449,7 @@ static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR
 
 #if defined(CONFIG_WIRELESS_EXT)
 struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 static void dhd_dpc(ulong data);
 /* forward decl */
@@ -448,7 +493,78 @@ extern int unregister_pm_notifier(struct notifier_block *nb);
 
 
 #if defined(CONFIG_HAS_EARLYSUSPEND)
-extern int dhd_set_suspend(int value, dhd_pub_t *dhd);
+
+int dhd_set_suspend(int value, dhd_pub_t *dhd)
+{
+       int power_mode = PM_MAX;
+       /* wl_pkt_filter_enable_t       enable_parm; */
+       char iovbuf[32];
+       int bcn_li_dtim = 3;
+#ifdef CUSTOMER_HW2
+       uint roamvar = 1;
+#endif /* CUSTOMER_HW2 */
+       int i;
+
+#define htod32(i) i
+
+       if (dhd && dhd->up) {
+               dhd_os_proto_block(dhd);
+               if (value) {
+
+                       /* Kernel suspended */
+                       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 */
+                       bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+                               4, iovbuf, sizeof(iovbuf));
+                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#ifdef CUSTOMER_HW2
+                       /* Disable build-in roaming to allowed ext supplicant to take of romaing */
+                       bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#endif /* CUSTOMER_HW2 */
+               } else {
+
+                       /* Kernel resumed  */
+                       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);
+                               }
+                       }
+
+                       /* set bcn_li_dtim */
+                       bcn_li_dtim = 0;
+                       bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+                               4, iovbuf, sizeof(iovbuf));
+                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#ifdef CUSTOMER_HW2
+                       roamvar = 0;
+                       bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+                       dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#endif /* CUSTOMER_HW2 */
+               }
+               dhd_os_proto_unblock(dhd);
+       }
+
+       return 0;
+}
 
 static void dhd_early_suspend(struct early_suspend *h)
 {
@@ -1203,9 +1319,11 @@ dhd_watchdog_thread(void *data)
        while (1) {
                if (down_interruptible (&dhd->watchdog_sem) == 0) {
                        dhd_os_wake_lock(&dhd->pub);
-                       /* Call the bus module watchdog */
-                       dhd_bus_watchdog(&dhd->pub);
 
+                       if (dhd->pub.dongle_reset == FALSE) {
+                               /* Call the bus module watchdog */
+                               dhd_bus_watchdog(&dhd->pub);
+                       }
                        /* Count the tick for reference */
                        dhd->pub.tickcnt++;
 
@@ -1239,12 +1357,8 @@ dhd_watchdog(ulong data)
        dhd->pub.tickcnt++;
 
        /* Reschedule the watchdog */
-#if defined(CONTINUOUS_WATCHDOG)
-       mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-#else
        if (dhd->wd_timer_valid)
                mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-#endif /* defined(CONTINUOUS_WATCHDOG) */
 }
 
 static int
@@ -1545,7 +1659,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
                /* may recurse, do NOT lock */
                return wl_iw_ioctl(net, ifr, cmd);
        }
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
        if (cmd == SIOCETHTOOL)
@@ -1721,7 +1835,7 @@ dhd_osl_detach(osl_t *osh)
        osl_detach(osh);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
        up(&dhd_registration_sem);
-#endif 
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
 }
 
 int
@@ -1869,7 +1983,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
                DHD_ERROR(("wl_iw_attach failed\n"));
                goto fail;
        }
-#endif
+#endif /* defined(CONFIG_WIRELESS_EXT) */
 
        /* Set up the watchdog timer */
        init_timer(&dhd->timer);
@@ -1949,6 +2063,9 @@ dhd_bus_start(dhd_pub_t *dhdp)
 {
        int ret = -1;
        dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
+#ifdef EMBEDDED_PLATFORM
+       char iovbuf[WL_EVENTING_MASK_LEN + 12]; /*  Room for "event_msgs" + '\0' + bitvec  */
+#endif /* EMBEDDED_PLATFORM */
 
        ASSERT(dhd);
 
@@ -1994,6 +2111,35 @@ dhd_bus_start(dhd_pub_t *dhdp)
                return -ENODEV;
        }
 
+#ifdef EMBEDDED_PLATFORM
+       bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+       dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
+       bcopy(iovbuf, dhdp->eventmask, WL_EVENTING_MASK_LEN);
+
+       setbit(dhdp->eventmask, WLC_E_SET_SSID);
+       setbit(dhdp->eventmask, WLC_E_PRUNE);
+       setbit(dhdp->eventmask, WLC_E_AUTH);
+       setbit(dhdp->eventmask, WLC_E_REASSOC);
+       setbit(dhdp->eventmask, WLC_E_REASSOC_IND);
+       setbit(dhdp->eventmask, WLC_E_DEAUTH_IND);
+       setbit(dhdp->eventmask, WLC_E_DISASSOC_IND);
+       setbit(dhdp->eventmask, WLC_E_DISASSOC);
+       setbit(dhdp->eventmask, WLC_E_JOIN);
+       setbit(dhdp->eventmask, WLC_E_ASSOC_IND);
+       setbit(dhdp->eventmask, WLC_E_PSK_SUP);
+       setbit(dhdp->eventmask, WLC_E_LINK);
+       setbit(dhdp->eventmask, WLC_E_NDIS_LINK);
+       setbit(dhdp->eventmask, WLC_E_MIC_ERROR);
+       setbit(dhdp->eventmask, WLC_E_PMKID_CACHE);
+       setbit(dhdp->eventmask, WLC_E_TXFAIL);
+       setbit(dhdp->eventmask, WLC_E_JOIN_START);
+       setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
+
+       dhdp->pktfilter_count = 1;
+       /* Setup filter to allow only unicast */
+       dhdp->pktfilter[0] = "100 0 0 0 0xff 0x00";
+#endif /* EMBEDDED_PLATFORM */
+
        /* Bus is ready, do any protocol initialization */
        if ((ret = dhd_prot_init(&dhd->pub)) < 0)
                return ret;
@@ -2242,6 +2388,19 @@ dhd_detach(dhd_pub_t *dhdp)
        }
 }
 
+static void __exit
+dhd_module_cleanup(void)
+{
+       DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+       dhd_bus_unregister();
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+       wifi_del_dev();
+#endif
+       /* Call customer gpio to turn off power with WL_REG_ON signal */
+       dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+}
+
 static int __init
 dhd_module_init(void)
 {
@@ -2301,7 +2460,7 @@ dhd_module_init(void)
         * It's needed to make sync up exit from dhd insmod  and
         * Kernel MMC sdio device callback registration
         */
-       if (down_timeout(&dhd_registration_sem,  msecs_to_jiffies(10000)) != 0) {
+       if (down_timeout(&dhd_registration_sem,  msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) {
                error = -EINVAL;
                DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__));
                goto fail_2;
@@ -2324,20 +2483,6 @@ fail_0:
        return error;
 }
 
-static void __exit
-dhd_module_cleanup(void)
-{
-       DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
-       dhd_bus_unregister();
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-       wifi_del_dev();
-#endif
-       /* Call customer gpio to turn off power with WL_REG_ON signal */
-       dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
-}
-
-
 module_init(dhd_module_init);
 module_exit(dhd_module_cleanup);
 
@@ -2703,6 +2848,43 @@ dhd_wait_pend8021x(struct net_device *dev)
        return pend;
 }
 
+#ifdef DHD_DEBUG
+int
+write_to_file(dhd_pub_t *dhd, uint8 *buf, int size)
+{
+       int ret = 0;
+       struct file *fp;
+       mm_segment_t old_fs;
+       loff_t pos = 0;
+
+       /* change to KERNEL_DS address limit */
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       /* open file to write */
+       fp = filp_open("/tmp/mem_dump", O_WRONLY|O_CREAT, 0640);
+       if (!fp) {
+               printf("%s: open file error\n", __FUNCTION__);
+               ret = -1;
+               goto exit;
+       }
+
+       /* Write buf to file */
+       fp->f_op->write(fp, buf, size, &pos);
+
+exit:
+       /* free buf before return */
+       MFREE(dhd->osh, buf, size);
+       /* close file before return */
+       if (fp)
+               filp_close(fp, current->files);
+       /* restore previous address limit */
+       set_fs(old_fs);
+
+       return ret;
+}
+#endif /* DHD_DEBUG */
+
 int dhd_os_wake_lock_timeout(dhd_pub_t *pub)
 {
        dhd_info_t *dhd = (dhd_info_t *)(pub->info);
index 1e2401acd40383c2cfeb5c58133f1defe56c2d32..382785a1ff6b47baf31f1febd2ac54b71bdaa57a 100644 (file)
@@ -4,7 +4,7 @@
  * Provides type definitions and function prototypes used to link the
  * DHD OS, bus, and protocol modules.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -24,7 +24,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd_proto.h,v 1.2.82.1.4.1.16.6 2009/06/17 01:01:55 Exp $
+ * $Id: dhd_proto.h,v 1.2.82.1.4.1.16.7 2010/05/10 12:54:59 Exp $
  */
 
 #ifndef _dhd_proto_h_
 #define IOCTL_RESP_TIMEOUT  2000 /* In milli second */
 #endif
 
+#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
+#define IOCTL_CHIP_ACTIVE_TIMEOUT  10 /* In milli second */
+#endif
+
 /*
  * Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
  */
index d94c70a7b47b19d55e69fc5c06ed8965a4b9f5de..e41c8ef8d7f8a9cf3f31e19785be550456d91c70 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.109.2.2 2010/05/18 01:13:11 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.123 2010/05/18 05:48:53 Exp $
  */
 
 #include <typedefs.h>
@@ -953,7 +953,6 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
                (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
        htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
        htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-       bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 
 #ifdef DHD_DEBUG
        tx_packets[PKTPRIO(pkt)]++;
@@ -1019,6 +1018,9 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
                        }
 
                }
+               if (ret == 0) {
+                       bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+               }
        } while ((ret < 0) && retrydata && retries++ < TXRETRIES);
 
 done:
@@ -1106,7 +1108,8 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
 
                /* Otherwise, send it now */
                BUS_WAKE(bus);
-               dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
+               /* Make sure back plane ht clk is on, no pending allowed */
+               dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
 
 #ifndef SDTEST
                DHD_TRACE(("%s: calling txpkt\n", __FUNCTION__));
@@ -1260,6 +1263,8 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
        htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
        if (!DATAOK(bus)) {
+               DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
+                       __FUNCTION__, bus->tx_max, bus->tx_seq));
                bus->ctrl_frame_stat = TRUE;
                /* Send from dpc */
                bus->ctrl_frame_buf = frame;
@@ -1267,15 +1272,16 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
 
                dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
 
-               if (bus->ctrl_frame_stat == FALSE)
+               if (bus->ctrl_frame_stat == FALSE) {
+                       DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
                        ret = 0;
-               else
+               } else {
+                       DHD_INFO(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
                        ret = -1;
+               }
        }
 
        if (ret == -1) {
-               bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
 #ifdef DHD_DEBUG
                if (DHD_BYTES_ON() && DHD_CTL_ON()) {
                        prhex("Tx Frame", frame, len);
@@ -1285,6 +1291,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
 #endif
 
                do {
+                       bus->ctrl_frame_stat = FALSE;
                        ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
                                                  frame, len, NULL, NULL, NULL);
                        ASSERT(ret != BCME_PENDING);
@@ -1313,6 +1320,9 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
                                }
 
                        }
+                       if (ret == 0) {
+                               bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+                       }
                } while ((ret < 0) && retries++ < TXRETRIES);
        }
 
@@ -1723,83 +1733,7 @@ dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
 
        return BCME_OK;
 }
-#endif
-
-#define CONSOLE_LINE_MAX       192
 
-#ifdef DHD_DEBUG
-static int
-dhdsdio_readconsole(dhd_bus_t *bus)
-{
-       dhd_console_t *c = &bus->console;
-       uint8 line[CONSOLE_LINE_MAX], ch;
-       uint32 n, idx, addr;
-       int rv;
-
-       /* Don't do anything until FWREADY updates console address */
-       if (bus->console_addr == 0)
-               return 0;
-
-       /* Read console log struct */
-       addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
-       if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
-               return rv;
-
-       /* Allocate console buffer (one time only) */
-       if (c->buf == NULL) {
-               c->bufsize = ltoh32(c->log.buf_size);
-               if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
-                       return BCME_NOMEM;
-       }
-
-       idx = ltoh32(c->log.idx);
-
-       /* Protect against corrupt value */
-       if (idx > c->bufsize)
-               return BCME_ERROR;
-
-       /* Skip reading the console buffer if the index pointer has not moved */
-       if (idx == c->last)
-               return BCME_OK;
-
-       /* Read the console buffer */
-       addr = ltoh32(c->log.buf);
-       if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
-               return rv;
-
-       while (c->last != idx) {
-               for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
-                       if (c->last == idx) {
-                               /* This would output a partial line.  Instead, back up
-                                * the buffer pointer and output this line next time around.
-                                */
-                               if (c->last >= n)
-                                       c->last -= n;
-                               else
-                                       c->last = c->bufsize - n;
-                               goto break2;
-                       }
-                       ch = c->buf[c->last];
-                       c->last = (c->last + 1) % c->bufsize;
-                       if (ch == '\n')
-                               break;
-                       line[n] = ch;
-               }
-
-               if (n > 0) {
-                       if (line[n - 1] == '\r')
-                               n--;
-                       line[n] = 0;
-                       printf("CONSOLE: %s\n", line);
-               }
-       }
-break2:
-
-       return BCME_OK;
-}
-#endif
-
-#ifdef DHD_DEBUG_TRAP
 static int
 dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
 {
@@ -1892,7 +1826,7 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
                                goto done;
 
                        bcm_bprintf(&strbuf,
-                       "Dongle trap type 0x%x @ pc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
+                       "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
                        "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
                        "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
                        tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13, tr.r14, tr.pc,
@@ -1923,10 +1857,131 @@ static int
 dhdsdio_mem_dump(dhd_bus_t *bus)
 {
        int ret = 0;
-       return ret;
+       int size; /* Full mem size */
+       int start = 0; /* Start address */
+       int read_size = 0; /* Read size of each iteration */
+       uint8 *buf = NULL, *databuf = NULL;
+
+       /* Get full mem size */
+       size = bus->ramsize;
+       buf = MALLOC(bus->dhd->osh, size);
+       if (!buf) {
+               printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size);
+               return -1;
+       }
+
+       /* Read mem content */
+       printf("Dump dongle memory");
+       databuf = buf;
+       while (size)
+       {
+               read_size = MIN(MEMBLOCK, size);
+               if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size)))
+               {
+                       printf("%s: Error membytes %d\n", __FUNCTION__, ret);
+                       if (buf) {
+                               MFREE(bus->dhd->osh, buf, size);
+                       }
+                       return -1;
+               }
+               printf(".");
+
+               /* Decrement size and increment start address */
+               size -= read_size;
+               start += read_size;
+               databuf += read_size;
+       }
+       printf("Done\n");
+
+#ifdef DHD_DEBUG
+       /* free buf before return !!! */
+       if (write_to_file(bus->dhd, buf, bus->ramsize))
+       {
+               printf("%s: Error writing to files\n", __FUNCTION__);
+               return -1;
+       }
+       /* buf free handled in write_to_file, not here */
+#else
+       MFREE(bus->dhd->osh, buf, size);
+#endif
+       return 0;
 }
 #endif /* DHD_DEBUG_TRAP */
 
+#ifdef DHD_DEBUG
+#define CONSOLE_LINE_MAX       192
+
+static int
+dhdsdio_readconsole(dhd_bus_t *bus)
+{
+       dhd_console_t *c = &bus->console;
+       uint8 line[CONSOLE_LINE_MAX], ch;
+       uint32 n, idx, addr;
+       int rv;
+
+       /* Don't do anything until FWREADY updates console address */
+       if (bus->console_addr == 0)
+               return 0;
+
+       /* Read console log struct */
+       addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
+       if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
+               return rv;
+
+       /* Allocate console buffer (one time only) */
+       if (c->buf == NULL) {
+               c->bufsize = ltoh32(c->log.buf_size);
+               if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
+                       return BCME_NOMEM;
+       }
+
+       idx = ltoh32(c->log.idx);
+
+       /* Protect against corrupt value */
+       if (idx > c->bufsize)
+               return BCME_ERROR;
+
+       /* Skip reading the console buffer if the index pointer has not moved */
+       if (idx == c->last)
+               return BCME_OK;
+
+       /* Read the console buffer */
+       addr = ltoh32(c->log.buf);
+       if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
+               return rv;
+
+       while (c->last != idx) {
+               for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+                       if (c->last == idx) {
+                               /* This would output a partial line.  Instead, back up
+                                * the buffer pointer and output this line next time around.
+                                */
+                               if (c->last >= n)
+                                       c->last -= n;
+                               else
+                                       c->last = c->bufsize - n;
+                               goto break2;
+                       }
+                       ch = c->buf[c->last];
+                       c->last = (c->last + 1) % c->bufsize;
+                       if (ch == '\n')
+                               break;
+                       line[n] = ch;
+               }
+
+               if (n > 0) {
+                       if (line[n - 1] == '\r')
+                               n--;
+                       line[n] = 0;
+                       printf("CONSOLE: %s\n", line);
+               }
+       }
+break2:
+
+       return BCME_OK;
+}
+#endif /* DHD_DEBUG */
+
 int
 dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
 {
@@ -4082,8 +4137,10 @@ dhdsdio_dpc(dhd_bus_t *bus)
 
        BUS_WAKE(bus);
 
-       /* Make sure backplane clock is on */
-       dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
+       /* Make sure backplane clock is on, no pending, 
+       * waste of cycle to wait for the next schedule to send
+       */
+       dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
        if (bus->clkstate == CLK_PENDING)
                goto clkwait;
 
@@ -4174,7 +4231,7 @@ clkwait:
                bcmsdh_intr_enable(sdh);
        }
 
-       if (DATAOK(bus) && bus->ctrl_frame_stat) {
+       if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
                int ret, i;
 
                ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
@@ -4206,13 +4263,16 @@ clkwait:
                        }
 
                }
+               if (ret == 0) {
+                               bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+               }
+
                printf("Return_dpc value is : %d\n", ret);
-               bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
                bus->ctrl_frame_stat = FALSE;
                dhd_wait_event_wakeup(bus->dhd);
        }
        /* Send queued frames (limit 1 if rx may still be pending) */
-       else if ((bus->clkstate != CLK_PENDING) && !bus->fcstate &&
+       else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
            pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
                framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
                framecnt = dhdsdio_sendfromq(bus, framecnt);
@@ -4227,7 +4287,8 @@ clkwait:
                bus->dhd->busstate = DHD_BUS_DOWN;
                bus->intstatus = 0;
        } else if (bus->clkstate == CLK_PENDING) {
-               /* Awaiting I_CHIPACTIVE; don't resched */
+               DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting \
+                       I_CHIPACTIVE interrupt", __FUNCTION__));
        } else if (bus->intstatus || bus->ipend ||
                   (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
                        PKT_AVAILABLE()) {  /* Read multiple frames */
@@ -4251,7 +4312,6 @@ clkwait:
 bool
 dhd_bus_dpc(struct dhd_bus *bus)
 {
-#ifdef SDIO_ISR_THREAD
        bool resched;
 
        /* Call the DPC directly. */
@@ -4259,9 +4319,6 @@ dhd_bus_dpc(struct dhd_bus *bus)
        resched = dhdsdio_dpc(bus);
 
        return resched;
-#else
-       return dhdsdio_dpc(bus);
-#endif /* SDIO_ISR_THREAD */
 }
 
 void
@@ -4270,6 +4327,8 @@ dhdsdio_isr(void *arg)
        dhd_bus_t *bus = (dhd_bus_t*)arg;
        bcmsdh_info_t *sdh;
 
+       DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
        if (!bus) {
                DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
                return;
@@ -4280,9 +4339,6 @@ dhdsdio_isr(void *arg)
                DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
                return;
        }
-
-       DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
        /* Count the interrupt call */
        bus->intrcount++;
        bus->ipend = TRUE;
@@ -4639,7 +4695,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
                        bus->idlecount = 0;
                        if (bus->activity) {
                                bus->activity = FALSE;
-                       } else {
                                dhdsdio_clkctl(bus, CLK_NONE, FALSE);
                        }
                }
@@ -4650,6 +4705,68 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
        return bus->ipend;
 }
 
+#ifdef DHD_DEBUG
+extern int
+dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
+{
+       dhd_bus_t *bus = dhdp->bus;
+       uint32 addr, val;
+       int rv;
+       void *pkt;
+
+       /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+       if (bus->console_addr == 0)
+               return BCME_UNSUPPORTED;
+
+       /* Exclusive bus access */
+       dhd_os_sdlock(bus->dhd);
+
+       /* Don't allow input if dongle is in reset */
+       if (bus->dhd->dongle_reset) {
+               dhd_os_sdunlock(bus->dhd);
+               return BCME_NOTREADY;
+       }
+
+       /* Request clock to allow SDIO accesses */
+       BUS_WAKE(bus);
+       /* No pend allowed since txpkt is called later, ht clk has to be on */
+       dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+       /* Zero cbuf_index */
+       addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx);
+       val = htol32(0);
+       if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+               goto done;
+
+       /* Write message into cbuf */
+       addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf);
+       if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
+               goto done;
+
+       /* Write length into vcons_in */
+       addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in);
+       val = htol32(msglen);
+       if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+               goto done;
+
+       /* Bump dongle by sending an empty event pkt.
+        * sdpcm_sendup (RX) checks for virtual console input.
+        */
+       if (((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL) &&
+               bus->clkstate == CLK_AVAIL)
+               dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, TRUE);
+
+done:
+       if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+               bus->activity = FALSE;
+               dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+       }
+
+       dhd_os_sdunlock(bus->dhd);
+
+       return rv;
+}
+#endif /* DHD_DEBUG */
 
 #ifdef DHD_DEBUG
 static void
index ee78c3d1949e2eeace145f9ada9a387d47f74fb9..980a1430100362616d75bd93e0b67dd92e329e8d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Definitions subject to change without notice.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -25,7 +25,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.4 2009/09/05 16:50:35 Exp $
+ * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.5 2010/05/21 21:49:38 Exp $
  */
 
 #ifndef _dhdioctl_h_
@@ -79,6 +79,7 @@ typedef struct dhd_ioctl {
 #define DHD_GLOM_VAL   0x0400
 #define DHD_EVENT_VAL  0x0800
 #define DHD_BTA_VAL    0x1000
+#define DHD_ISCAN_VAL 0x2000
 
 #ifdef SDTEST
 /* For pktgen iovar */
index a76ea3f85d6e1a73fa4e0df7f38df8570345094b..f27fcc5832b626346c02fb67d3143fec8d81031c 100644 (file)
 
 #define        EPI_MINOR_VERSION       218
 
-#define        EPI_RC_NUMBER           223
+#define        EPI_RC_NUMBER           238
 
-#define        EPI_INCREMENTAL_NUMBER  1
+#define        EPI_INCREMENTAL_NUMBER  0
 
 #define        EPI_BUILD_NUMBER        0
 
-#define        EPI_VERSION             4, 218, 223, 1
+#define        EPI_VERSION             4, 218, 238, 0
 
-#define        EPI_VERSION_NUM         0x04dadf01
+#define        EPI_VERSION_NUM         0x04daee00
 
 
-#define        EPI_VERSION_STR         "4.218.223.1"
-#define        EPI_ROUTER_VERSION_STR  "4.219.223.1"
+#define        EPI_VERSION_STR         "4.218.238.0"
+#define        EPI_ROUTER_VERSION_STR  "4.219.238.0"
 
 #endif 
index f2334a0a3394741b9620c87f20a6378cfc630958..dccafdb55d1f504ed711fac26a8fb3f02fd0fbbd 100644 (file)
 
 #include <typedefs.h>
 
+#ifdef RWL_DONGLE
+/* For Dongle uart tranport max cmd len is 256 bytes + header length (16 bytes)
+ *  In case of ASD commands we are not sure about how much is the command size
+ *  To be on the safe side, input buf len CBUF_LEN is increased to max (512) bytes.
+ */
+#define RWL_MAX_DATA_LEN       (512 + 8)       /* allow some extra bytes for '/n' termination */
+#define CBUF_LEN       (RWL_MAX_DATA_LEN + 64)  /* allow 64 bytes for header ("rwl...") */
+#else
 #define CBUF_LEN       (128)
+#endif
+
+#ifdef WLLMAC
+#define LOG_BUF_LEN    2048
+#else /* WLLMAC */
 #define LOG_BUF_LEN    1024
+#endif /* WLLMAC */
 
 typedef struct {
-       uint32          buf;
+       uint32          buf;            /* Can't be pointer on (64-bit) hosts */
        uint            buf_size;
        uint            idx;
-       char            *_buf_compat;
+       char            *_buf_compat;   /* Redundant pointer for backward compat. */
 } hndrte_log_t;
 
 typedef struct {
+       /* Virtual UART
+        *   When there is no UART (e.g. Quickturn), the host should write a complete
+        *   input line directly into cbuf and then write the length into vcons_in.
+        *   This may also be used when there is a real UART (at risk of conflicting with
+        *   the real UART).  vcons_out is currently unused.
+        */
        volatile uint   vcons_in;
        volatile uint   vcons_out;
+
+       /* Output (logging) buffer
+        *   Console output is written to a ring buffer log_buf at index log_idx.
+        *   The host may read the output when it sees log_idx advance.
+        *   Output will be lost if the output wraps around faster than the host polls.
+        */
        hndrte_log_t    log;
+
+       /* Console input line buffer
+        *   Characters are read one at a time into cbuf until <CR> is received, then
+        *   the buffer is processed as a command line.  Also used for virtual UART.
+        */
        uint            cbuf_idx;
        char            cbuf[CBUF_LEN];
 } hndrte_cons_t;
index 3ef7de2f20e289ea9a61bd0100de8d027ea71b6b..fd26317361da46a41beac9d359d5c8e0b01410d5 100644 (file)
@@ -976,6 +976,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
 #define DOT11_MNG_EXT_CSA_ID                   60      
 #define        DOT11_MNG_HT_ADD                        61      
 #define        DOT11_MNG_EXT_CHANNEL_OFFSET            62      
+#define DOT11_MNG_WAPI_ID                              68      
 #define        DOT11_MNG_HT_BSS_COEXINFO_ID            72      
 #define        DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID      73      
 #define        DOT11_MNG_HT_OBSS_ID                    74      
@@ -1422,6 +1423,8 @@ typedef struct vndr_ie vndr_ie_t;
 #define AES_KEY_SIZE           16      
 #define AES_MIC_SIZE           8       
 
+#define SMS4_KEY_LEN           16
+#define SMS4_WPI_CBC_MAC_LEN   16
 
 
 #include <packed_section_end.h>
index 05530d51b176fd0b1a239990df96cbf5ecd8dbbe..9ad2ea0c70fd3f5d2afd43403301e828b8bd3819 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
  *
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
  * 
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: ethernet.h,v 9.45.56.3 2009/08/15 00:51:27 Exp $
+ * $Id: ethernet.h,v 9.45.56.5 2010/02/22 22:04:36 Exp $
  */
 
 
@@ -67,6 +67,7 @@
 #define ETHER_TYPE_8021Q       0x8100          
 #define        ETHER_TYPE_BRCM         0x886c          
 #define        ETHER_TYPE_802_1X       0x888e          
+#define ETHER_TYPE_WAI         0x88b4          
 #ifdef BCMWPA2
 #define        ETHER_TYPE_802_1X_PREAUTH 0x88c7        
 #endif
index 58a2f6c0ff1eb9b3c2b0c0fd2829ca5cf7f41992..a1507ebe598d44484f4925d725405f3c2d703094 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.60 2010/04/12 05:33:02 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.61 2010/05/04 20:26:25 Exp $
  */
 
 
@@ -288,6 +288,7 @@ typedef enum sup_auth_status {
 #define CRYPTO_ALGO_AES_OCB_MSDU       5
 #define CRYPTO_ALGO_AES_OCB_MPDU       6
 #define CRYPTO_ALGO_NALG               7
+#define CRYPTO_ALGO_SMS4               11
 
 #define WSEC_GEN_MIC_ERROR     0x0001
 #define WSEC_GEN_REPLAY                0x0002
@@ -338,6 +339,7 @@ typedef struct {
 #define AES_ENABLED            0x0004
 #define WSEC_SWFLAG            0x0008
 #define SES_OW_ENABLED         0x0040  
+#define SMS4_ENABLED           0x0100
 
 
 #define WPA_AUTH_DISABLED      0x0000  
@@ -349,6 +351,7 @@ typedef struct {
 #define WPA2_AUTH_PSK          0x0080  
 #define BRCM_AUTH_PSK           0x0100  
 #define BRCM_AUTH_DPT          0x0200  
+#define WPA_AUTH_WAPI          0x0400  
 
 #define WPA_AUTH_PFN_ANY       0xffffffff      
 
index 6383e00498f1100fc50b4026c80bda278ad4b200..d00bd1ca291b89868dfe77b8da7c33f2a464437a 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: linux_osl.c,v 1.125.12.3.8.6 2009/12/09 01:29:03 Exp $
+ * $Id: linux_osl.c,v 1.125.12.3.8.7 2010/05/04 21:10:04 Exp $
  */
 
 
@@ -511,7 +511,7 @@ osl_mfree(osl_t *osh, void *addr, uint size)
 #ifdef DHD_USE_STATIC_BUF
        if (bcm_static_buf)
        {
-               if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr \
+               if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr
                        <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN)))
                {
                        int buf_idx = 0;
index 8fb3963854754a8942b602f21bb0f7ab12e956c8..7ccee377fe01d48e0ab484b13d628006e92b86c3 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.104 2010/04/21 23:21:00 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.108 2010/05/18 00:09:41 Exp $
  */
 
 
@@ -57,7 +57,32 @@ typedef const struct si_pub  si_t;
 #include <wl_iw.h>
 
 
-#define IW_WSEC_ENABLED(wsec)  ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#ifndef IW_ENCODE_ALG_SM4
+#define IW_ENCODE_ALG_SM4 0x20
+#endif
+
+#ifndef IW_AUTH_WAPI_ENABLED
+#define IW_AUTH_WAPI_ENABLED 0x20
+#endif
+
+#ifndef IW_AUTH_WAPI_VERSION_1
+#define IW_AUTH_WAPI_VERSION_1 0x00000008
+#endif
+
+#ifndef IW_AUTH_CIPHER_SMS4
+#define IW_AUTH_CIPHER_SMS4    0x00000020
+#endif
+
+#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
+#define IW_AUTH_KEY_MGMT_WAPI_PSK 4
+#endif
+
+#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
+#define IW_AUTH_KEY_MGMT_WAPI_CERT 8
+#endif
+
+
+#define IW_WSEC_ENABLED(wsec)  ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
 
 #include <linux/rtnetlink.h>
 #include <linux/mutex.h>
@@ -1182,28 +1207,6 @@ static int iwpriv_set_ap_config(struct net_device *dev,
 
 
 #ifdef SOFTAP
-void print_buf(void *pbuf, int len, int bytes_per_line)
-{
-       int i, j = 0;
-       unsigned char *buf = pbuf;
-
-       if (bytes_per_line == 0) {
-               bytes_per_line = len;
-       }
-
-       for (i = 0; i < len; i++) {
-               WL_SOFTAP(("%2.2x", *buf++));
-               j++;
-               if (j == bytes_per_line) {
-                       WL_SOFTAP(("\n"));
-                       j = 0;
-               } else {
-                       WL_SOFTAP((":"));
-               }
-       }
-       WL_SOFTAP(("\n"));
-}
-
 static int iwpriv_get_assoc_list(struct net_device *dev,
                struct iw_request_info *info,
                union iwreq_data *p_iwrq,
@@ -1554,9 +1557,9 @@ wl_iw_get_range(
 )
 {
        struct iw_range *range = (struct iw_range *) extra;
-       int channels[MAXCHANNEL+1];
-       wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
+       wl_uint32_list_t *list;
        wl_rateset_t rateset;
+       int8 *channels;
        int error, i, k;
        uint sf, ch;
 
@@ -1574,14 +1577,23 @@ wl_iw_get_range(
        if (!extra)
                return -EINVAL;
 
+       channels = kmalloc((MAXCHANNEL+1)*4, GFP_KERNEL);
+       if (!channels) {
+               WL_ERROR(("Could not alloc channels\n"));
+               return -ENOMEM;
+       }
+       list = (wl_uint32_list_t *)channels;
+
        dwrq->length = sizeof(struct iw_range);
        memset(range, 0, sizeof(range));
 
        range->min_nwid = range->max_nwid = 0;
 
        list->count = htod32(MAXCHANNEL);
-       if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
+       if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4))) {
+               kfree(channels);
                return error;
+       }
        for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
                range->freq[i].i = dtoh32(list->element[i]);
 
@@ -1613,8 +1625,10 @@ wl_iw_get_range(
        range->avg_qual.noise = 0x100 - 75;     
 #endif 
 
-       if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+       if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) {
+               kfree(channels);
                return error;
+       }
        rateset.count = dtoh32(rateset.count);
        range->num_bitrates = rateset.count;
        for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
@@ -1649,8 +1663,10 @@ wl_iw_get_range(
                }
        }
 
-       if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
+       if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) {
+               kfree(channels);
                return error;
+       }
        i = dtoh32(i);
        if (i == WLC_PHY_TYPE_A)
                range->throughput = 24000000;   
@@ -1719,6 +1735,8 @@ wl_iw_get_range(
 #endif
 #endif 
 
+       kfree(channels);
+
        return 0;
 }
 
@@ -2795,6 +2813,32 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
 }
 #endif 
 
+static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
+       size_t len, int uppercase)
+{
+       size_t i;
+       char *pos = buf, *end = buf + buf_size;
+       int ret;
+       if (buf_size == 0)
+               return 0;
+       for (i = 0; i < len; i++) {
+               ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
+                       data[i]);
+               if (ret < 0 || ret >= end - pos) {
+                       end[-1] = '\0';
+                       return pos - buf;
+               }
+               pos += ret;
+       }
+       end[-1] = '\0';
+       return pos - buf;
+}
+
+
+int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
+{
+       return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
+}
 
 static int
 wl_iw_handle_scanresults_ies(char **event_p, char *end,
@@ -2803,6 +2847,8 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end,
 #if WIRELESS_EXT > 17
        struct iw_event iwe;
        char *event;
+       char *buf;
+       int custom_event_len;
 
        event = *event_p;
        if (bi->ie_length) {
@@ -2841,6 +2887,35 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end,
                        }
                }
 
+               ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+               ptr_len = bi->ie_length;
+
+               while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) {
+                       WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__));
+#ifdef WAPI_IE_USE_GENIE
+                       iwe.cmd = IWEVGENIE;
+                       iwe.u.data.length = ie->len + 2;
+                       event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+#else 
+                       iwe.cmd = IWEVCUSTOM;
+                       custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2);
+                       iwe.u.data.length = custom_event_len;
+
+                       buf = kmalloc(custom_event_len+1, GFP_KERNEL);
+                       if (buf == NULL)
+                       {
+                               WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len));
+                               break;
+                       }
+
+                       memcpy(buf, "wapi_ie=", 8);
+                       wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1);
+                       wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
+                       wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
+                       event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
+#endif 
+                       break;
+               }
        *event_p = event;
        }
 #endif 
@@ -3918,11 +3993,21 @@ wl_iw_set_wpaie(
        char *extra
 )
 {
+       uchar buf[WLC_IOCTL_SMLEN] = {0};
+       uchar *p = buf;
+       int wapi_ie_size;
 
        WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
 
        CHECK_EXTRA_FOR_NULL(extra);
 
+       if (extra[0] == DOT11_MNG_WAPI_ID)
+       {
+               wapi_ie_size = iwp->length;
+               memcpy(p, extra, iwp->length);
+               dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size);
+       }
+       else
                dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
 
        return 0;
@@ -4039,6 +4124,12 @@ wl_iw_set_encodeext(
                        case IW_ENCODE_ALG_CCMP:
                                key.algo = CRYPTO_ALGO_AES_CCM;
                                break;
+                       case IW_ENCODE_ALG_SM4:
+                               key.algo = CRYPTO_ALGO_SMS4;
+                               if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+                                       key.flags &= ~WL_PRIMARY_KEY;
+                               }
+                               break;
                        default:
                                break;
                }
@@ -4222,6 +4313,8 @@ wl_iw_set_wpaauth(
                else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
                        val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
 #endif 
+               else if (paramval & IW_AUTH_WAPI_VERSION_1)
+                       val = WPA_AUTH_WAPI;
                WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
                if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
                        return error;
@@ -4236,6 +4329,8 @@ wl_iw_set_wpaauth(
                        val = TKIP_ENABLED;
                if (paramval & IW_AUTH_CIPHER_CCMP)
                        val = AES_ENABLED;
+               if (paramval & IW_AUTH_CIPHER_SMS4)
+                       val = SMS4_ENABLED;
 
                if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
                        iw->pwsec = val;
@@ -4283,9 +4378,12 @@ wl_iw_set_wpaauth(
                                val = WPA2_AUTH_UNSPECIFIED;
                }
 #endif 
+               if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT))
+                       val = WPA_AUTH_WAPI;
                WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
                if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
                        return error;
+
                break;
        case IW_AUTH_TKIP_COUNTERMEASURES:
                dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
@@ -4368,6 +4466,24 @@ wl_iw_set_wpaauth(
                break;
        }
 #endif
+       case IW_AUTH_WAPI_ENABLED:
+               if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
+                       return error;
+               if (paramval) {
+                       val |= SMS4_ENABLED;
+                       if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
+                               WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n",
+                                       __FUNCTION__, val, error));
+                               return error;
+                       }
+                       if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WPA_AUTH_WAPI))) {
+                               WL_ERROR(("%s: setting wpa_auth(WPA_AUTH_WAPI) returned %d\n",
+                                       __FUNCTION__, error));
+                               return error;
+                       }
+               }
+
+               break;
        default:
                break;
        }