net: wireless: bcmdhd: Update to Version 5.90.195.98
authorDmitry Shmidt <dimitrysh@google.com>
Wed, 22 Aug 2012 18:29:44 +0000 (11:29 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Wed, 22 Aug 2012 19:32:00 +0000 (12:32 -0700)
Change-Id: I2854300bc03b133d8276bea2f36f4c5253c551a1
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
17 files changed:
drivers/net/wireless/bcmdhd/bcmsdh.c
drivers/net/wireless/bcmdhd/bcmsdh_linux.c
drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c
drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_cfg80211.c
drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
drivers/net/wireless/bcmdhd/dhd_linux.c
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd/include/epivers.h
drivers/net/wireless/bcmdhd/include/sbchipc.h
drivers/net/wireless/bcmdhd/include/sdioh.h
drivers/net/wireless/bcmdhd/wl_cfg80211.c
drivers/net/wireless/bcmdhd/wl_cfg80211.h
drivers/net/wireless/bcmdhd/wl_cfgp2p.c
drivers/net/wireless/bcmdhd/wl_cfgp2p.h
drivers/net/wireless/bcmdhd/wldev_common.c

index f67b13a03a1c5c85f81347228e2f8fa2f27b651a..89320b6f53d45e9a17de1253f12b8fd76ad9d469 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: bcmsdh.c 300445 2011-12-03 05:37:20Z $
+ * $Id: bcmsdh.c 344235 2012-07-11 23:47:18Z $
  */
 
 /**
@@ -362,9 +362,10 @@ bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length)
                }
                bcopy(cis, tmp_buf, length);
                for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); tmp_ptr++) {
-                       ptr += sprintf((char*)ptr, "%.2x ", *tmp_ptr & 0xff);
+                       ptr += snprintf((char*)ptr, (cis + length - ptr - 4),
+                               "%.2x ", *tmp_ptr & 0xff);
                        if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
-                               ptr += sprintf((char *)ptr, "\n");
+                               ptr += snprintf((char *)ptr, (cis + length - ptr -4), "\n");
                }
                MFREE(bcmsdh->osh, tmp_buf, length);
        }
index d257ddab84a3f8450891625dab152cff9914413a..edecb5f2f4c8cb42755879b3442b6ae72e56b995 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: bcmsdh_linux.c 312788 2012-02-03 23:06:32Z $
+ * $Id: bcmsdh_linux.c 343302 2012-07-06 13:07:38Z $
  */
 
 /**
@@ -684,6 +684,11 @@ extern int sd_uhsimode;
 module_param(sd_uhsimode, int, 0);
 #endif
 
+#ifdef BCMSDIOH_TXGLOM
+extern uint sd_txglom;
+module_param(sd_txglom, uint, 0);
+#endif
+
 #ifdef BCMSDH_MODULE
 EXPORT_SYMBOL(bcmsdh_attach);
 EXPORT_SYMBOL(bcmsdh_detach);
index 374154fb12961d9ba2a961e13aca7f2ff4c75a13..67c2fbf5ea18cd008216743509d3792d0c6148da 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: bcmsdh_sdmmc.c 314904 2012-02-14 21:36:04Z $
+ * $Id: bcmsdh_sdmmc.c 344243 2012-07-12 00:06:23Z $
  */
 #include <typedefs.h>
 
@@ -799,41 +799,49 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
 #if defined(MMC_SDIO_ABORT)
                        /* to allow abort command through F1 */
                        else if (regaddr == SDIOD_CCCR_IOABORT) {
-                               sdio_claim_host(gInstance->func[func]);
-                               /*
-                               * this sdio_f0_writeb() can be replaced with another api
-                               * depending upon MMC driver change.
-                               * As of this time, this is temporaray one
-                               */
-                               sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
-                               sdio_release_host(gInstance->func[func]);
+                               if (gInstance->func[func]) {
+                                       sdio_claim_host(gInstance->func[func]);
+                                       /*
+                                       * this sdio_f0_writeb() can be replaced with another api
+                                       * depending upon MMC driver change.
+                                       * As of this time, this is temporaray one
+                                       */
+                                       sdio_writeb(gInstance->func[func],
+                                               *byte, regaddr, &err_ret);
+                                       sdio_release_host(gInstance->func[func]);
+                               }
                        }
 #endif /* MMC_SDIO_ABORT */
                        else if (regaddr < 0xF0) {
                                sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
                        } else {
                                /* Claim host controller, perform F0 write, and release */
-                               sdio_claim_host(gInstance->func[func]);
-                               sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
-                               sdio_release_host(gInstance->func[func]);
+                               if (gInstance->func[func]) {
+                                       sdio_claim_host(gInstance->func[func]);
+                                       sdio_f0_writeb(gInstance->func[func],
+                                               *byte, regaddr, &err_ret);
+                                       sdio_release_host(gInstance->func[func]);
+                               }
                        }
                } else {
                        /* Claim host controller, perform Fn write, and release */
-                       sdio_claim_host(gInstance->func[func]);
-                       sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
-                       sdio_release_host(gInstance->func[func]);
+                       if (gInstance->func[func]) {
+                               sdio_claim_host(gInstance->func[func]);
+                               sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
+                               sdio_release_host(gInstance->func[func]);
+                       }
                }
        } else { /* CMD52 Read */
                /* Claim host controller, perform Fn read, and release */
-               sdio_claim_host(gInstance->func[func]);
-
-               if (func == 0) {
-                       *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
-               } else {
-                       *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
+               if (gInstance->func[func]) {
+                       sdio_claim_host(gInstance->func[func]);
+                       if (func == 0) {
+                               *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
+                       } else {
+                               *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
+                       }
+                       sdio_release_host(gInstance->func[func]);
                }
-
-               sdio_release_host(gInstance->func[func]);
        }
 
        if (err_ret) {
index a78faebe2e7ac7e7fbea1dd4ecf00d6a71e99863..c93e41c6fb40fa9528b357fd1a80447101e79f83 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: bcmsdh_sdmmc_linux.c 312783 2012-02-03 22:53:56Z $
+ * $Id: bcmsdh_sdmmc_linux.c 331154 2012-05-04 00:41:40Z $
  */
 
 #include <typedefs.h>
@@ -188,7 +188,6 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev)
 
        if (dhd_os_check_wakelock(bcmsdh_get_drvdata()))
                return -EBUSY;
-
        sdio_flags = sdio_get_host_pm_caps(func);
 
        if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
@@ -202,7 +201,6 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev)
                sd_err(("%s: error while trying to keep power\n", __FUNCTION__));
                return ret;
        }
-
 #if defined(OOB_INTR_ONLY)
        bcmsdh_oob_intr_set(0);
 #endif /* defined(OOB_INTR_ONLY) */
index 725a909273dc024616922261012a915fa904bee2..6106555f131467d04816218920c89a710cf824e1 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 333052 2012-05-12 02:09:28Z $
+ * $Id: dhd.h 344123 2012-07-11 09:33:49Z $
  */
 
 /****************
index 970216efc7a7a4dbd6c2e0ef26fe5aae8c5351eb..351c372ffa8179854df626d5f7d5df6b66841908 100644 (file)
@@ -69,6 +69,9 @@ s32 dhd_cfg80211_down(struct wl_priv *wl)
        return 0;
 }
 
+/*
+ * dhd_cfg80211_set_p2p_info : gets called when GO or GC created
+ */
 s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
 {
        dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
@@ -83,7 +86,7 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
        dhd_arp_offload_set(dhd, 0);
        dhd_arp_offload_enable(dhd, false);
 #endif /* ARP_OFFLOAD_SUPPORT */
-
+       /* diable all filtering in p2p mode */
        dhd_os_set_packet_filter(dhd, 0);
 
        /* Setup timeout if Beacons are lost and roam is off to report link down */
@@ -94,6 +97,9 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
        return 0;
 }
 
+/*
+ * dhd_cfg80211_clean_p2p_info : gets called when GO or GC terminated
+ */
 s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
 {
        dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
@@ -108,7 +114,6 @@ s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
        dhd_arp_offload_set(dhd, dhd_arp_mode);
        dhd_arp_offload_enable(dhd, true);
 #endif /* ARP_OFFLOAD_SUPPORT */
-
        dhd_os_set_packet_filter(dhd, 1);
 
        /* Setup timeout if Beacons are lost and roam is off to report link down */
index 9750eeb23bce2d748f8ab8e8eca212468b31f1ef..de519a57bf8c08eff4e2969a8a2bf8ac99446488 100644 (file)
@@ -20,7 +20,7 @@
 * software in any way with any other Broadcom software provided under a license
 * other than the GPL, without Broadcom's express prior written consent.
 *
-* $Id: dhd_custom_gpio.c,v 1.2.42.1 2010-10-19 00:41:09 Exp $
+* $Id: dhd_custom_gpio.c 339054 2012-06-15 04:56:55Z $
 */
 
 #include <typedefs.h>
@@ -97,13 +97,13 @@ int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
 #endif /* CUSTOMER_HW2 */
 
        if (dhd_oob_gpio_num < 0) {
-               WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
+               WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined\n",
                        __FUNCTION__));
                return (dhd_oob_gpio_num);
        }
 
        WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
-                __FUNCTION__, dhd_oob_gpio_num));
+               __FUNCTION__, dhd_oob_gpio_num));
 
 #if defined CUSTOMER_HW
        host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
index d32ce1135f2c196c1cc31dc5d8ac0b73e493c046..8aa7ed9f43231fb7c36b12d8708a0b68ffd800f9 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 333885 2012-05-18 00:39:03Z $
+ * $Id: dhd_linux.c 344350 2012-07-12 08:35:03Z $
  */
 
 #include <typedefs.h>
@@ -1026,7 +1026,7 @@ dhd_op_if(dhd_if_t *ifp)
 #endif
                        netif_stop_queue(ifp->net);
                        unregister_netdev(ifp->net);
-                       ret = DHD_DEL_IF;
+                       ret = DHD_DEL_IF;       /* Make sure the free_netdev() is called */
 
 #ifdef WL_CFG80211
                        if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
@@ -2648,7 +2648,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
        }
 
        sema_init(&dhd->proto_sem, 1);
+#ifdef DHDTHREAD
        sema_init(&dhd->sdsem, 1);
+#endif
 
 #ifdef PROP_TXSTATUS
        spin_lock_init(&dhd->wlfc_spinlock);
index e578d702ce11f2c06d06e2af139f7f9590e2edb0..ed3da83604b5c739728aa2e8a9cc5a75dcc080e7 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 326662 2012-04-10 06:38:08Z $
+ * $Id: dhd_sdio.c 338148 2012-06-11 20:35:45Z $
  */
 
 #include <typedefs.h>
index 5df25c16b7d9b1930b04bc2581af5b44fc347f3d..19da8f28bc7e8827b9635746317123c8b7d26874 100644 (file)
 
 #define        EPI_RC_NUMBER           195
 
-#define        EPI_INCREMENTAL_NUMBER  75
+#define        EPI_INCREMENTAL_NUMBER  98
 
 #define        EPI_BUILD_NUMBER        0
 
-#define        EPI_VERSION             5, 90, 195, 75
+#define        EPI_VERSION             5, 90, 195, 98
 
-#define        EPI_VERSION_NUM         0x055ac34b
+#define        EPI_VERSION_NUM         0x055ac362
 
 #define EPI_VERSION_DEV                5.90.195
 
 
-#define        EPI_VERSION_STR         "5.90.195.75"
+#define        EPI_VERSION_STR         "5.90.195.98"
 
 #endif 
index aa4df443e1398d31803a6409410c28c206a2d80c..78ced30c502b05b0425e800dc1e7857f9ac62dfd 100644 (file)
@@ -5,7 +5,7 @@
  * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer,
  * GPIO interface, extbus, and support for serial and parallel flashes.
  *
- * $Id: sbchipc.h 333924 2012-05-18 04:48:52Z $
+ * $Id: sbchipc.h 343982 2012-07-11 00:29:37Z $
  *
  * Copyright (C) 1999-2011, Broadcom Corporation
  * 
@@ -1726,6 +1726,11 @@ typedef volatile struct {
 #define SECI_MODE_SHIFT                4 
 #define SECI_UPD_SECI          (1 << 7)
 
+#define SECI_SLIP_ESC_CHAR     0xDB
+#define SECI_SIGNOFF_0         SECI_SLIP_ESC_CHAR
+#define SECI_SIGNOFF_1         0
+#define SECI_REFRESH_REQ       0xDA
+
 
 #define CLKCTL_STS_SECI_CLK_REQ                (1 << 8)
 #define CLKCTL_STS_SECI_CLK_AVAIL      (1 << 24)
index 5f47d6f88ceae68fa96db6e6c7c1fb40ec9699c2..1d820d1569e73daa2ffb9f2a6bcf6b5af86023e8 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: sdioh.h 300017 2011-12-01 20:30:27Z $
+ * $Id: sdioh.h 345478 2012-07-18 06:45:15Z $
  */
 
 #ifndef        _SDIOH_H
 #define SD3_PresetVal_SDR50            0x06a
 #define SD3_PresetVal_SDR104   0x06c
 #define SD3_PresetVal_DDR50            0x06e
+/* SDIO3.0 Revx specific Registers */
+#define SD3_Tuning_Info_Register 0x0EC
+#define SD3_WL_BT_reset_register 0x0F0
+
 
 /* preset value indices */
 #define SD3_PRESETVAL_INITIAL_IX       0
index 87d971a5e5dd20d705d9ad2f430c776aa6fed5f9..04689546ac8d29287812288de321a21ef71a737f 100644 (file)
@@ -358,6 +358,7 @@ static s32 wl_iscan_done(struct wl_priv *wl);
 static s32 wl_iscan_pending(struct wl_priv *wl);
 static s32 wl_iscan_inprogress(struct wl_priv *wl);
 static s32 wl_iscan_aborted(struct wl_priv *wl);
+static void wl_scan_timeout_process(struct work_struct *work);
 
 /*
  * find most significant bit set
@@ -1518,6 +1519,8 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
        s32 passive_scan;
        wl_scan_results_t *results;
        WL_SCAN(("Enter \n"));
+
+       mutex_lock(&wl->usr_sync);
        wl->escan_info.ndev = ndev;
        wl->escan_info.wiphy = wiphy;
        wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
@@ -1526,7 +1529,7 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
                &passive_scan, sizeof(passive_scan), false);
        if (unlikely(err)) {
                WL_ERR(("error (%d)\n", err));
-               return err;
+               goto exit;
        }
        results = (wl_scan_results_t *) wl->escan_info.escan_buf;
        results->version = 0;
@@ -1534,6 +1537,8 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
        results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
 
        err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
+exit:
+       mutex_unlock(&wl->usr_sync);
        return err;
 }
 
@@ -1580,7 +1585,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
        /* Arm scan timeout timer */
        mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
        iscan_req = false;
-       wl->scan_request = request;
        if (request) {          /* scan bss */
                ssids = request->ssids;
                if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
@@ -1661,6 +1665,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                /* we don't do iscan in ibss */
                ssids = this_ssid;
        }
+       wl->scan_request = request;
        wl_set_drv_status(wl, SCANNING, ndev);
        if (iscan_req) {
                err = wl_do_iscan(wl, request);
@@ -1724,12 +1729,9 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 
 scan_out:
        wl_clr_drv_status(wl, SCANNING, ndev);
-       if (wl->scan_request) {
-               if (timer_pending(&wl->scan_timeout))
-                       del_timer_sync(&wl->scan_timeout);
-               cfg80211_scan_done(wl->scan_request, true);
-               wl->scan_request = NULL;
-       }
+       if (timer_pending(&wl->scan_timeout))
+               del_timer_sync(&wl->scan_timeout);
+       wl->scan_request = NULL;
        return err;
 }
 
@@ -1750,6 +1752,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                        wl->scan_busy_count++;
                        if (wl->scan_busy_count > WL_SCAN_BUSY_MAX) {
                                wl->scan_busy_count = 0;
+                               WL_ERR(("Continuous scan failures!! Exercising FW hang recovery\n"));
                                net_os_send_hang_message(ndev);
                        }
                }
@@ -3069,6 +3072,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
        s32 pm;
        s32 err = 0;
        struct wl_priv *wl = wiphy_priv(wiphy);
+       dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
 
        CHECK_SYS_UP(wl);
 
@@ -3077,7 +3081,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
                return err;
        }
 
-       pm = enabled ? PM_FAST : PM_OFF;
+       pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF;
        pm = htod32(pm);
        err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
        if (unlikely(err)) {
@@ -3511,6 +3515,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
        wifi_p2p_ie_t *p2p_ie;
        wpa_ie_fixed_t *wps_ie;
        scb_val_t scb_val;
+       wifi_wfd_ie_t *wfd_ie;
        const struct ieee80211_mgmt *mgmt;
        struct wl_priv *wl = wiphy_priv(wiphy);
        struct net_device *dev = NULL;
@@ -3518,6 +3523,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
        s32 bssidx = 0;
        u32 p2pie_len = 0;
        u32 wpsie_len = 0;
+       u32 wfdie_len = 0;
        u32 id;
        u32 retry = 0;
        bool ack = false;
@@ -3567,6 +3573,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                                /* Total length of P2P Information Element */
                                p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
                        }
+                       if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)(buf + ie_offset), ie_len))
+                           != NULL) {
+                               /* Total length of WFD Information Element */
+                               wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+                       }
                        if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
                                != NULL) {
                                /* Order of Vendor IE is 1) WPS IE +
@@ -3578,7 +3589,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                                        sizeof(wps_ie->tag);
                                wl_cfgp2p_set_management_ie(wl, dev, bssidx,
                                        VNDR_IE_PRBRSP_FLAG,
-                                       (u8 *)wps_ie, wpsie_len + p2pie_len);
+                                       (u8 *)wps_ie, wpsie_len + p2pie_len+ wfdie_len);
                        }
                        cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
                        goto exit;
@@ -4087,11 +4098,13 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
        wpa_ie_fixed_t *wpa_ie;
        bcm_tlv_t *wpa2_ie;
        wifi_p2p_ie_t *p2p_ie;
+       wifi_wfd_ie_t *wfd_ie;
        bool is_bssup = false;
        bool update_bss = false;
        bool pbc = false;
        u16 wpsie_len = 0;
        u16 p2pie_len = 0;
+       u32 wfdie_len = 0;
        u8 beacon_ie[IE_MAX_LEN];
        s32 ie_offset = 0;
        s32 bssidx = 0;
@@ -4149,10 +4162,24 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
                } else {
                        WL_ERR(("No P2PIE in beacon \n"));
                }
+               /* find the WFD IEs */
+               if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)info->tail, info->tail_len)) != NULL) {
+                       /* Total length of P2P Information Element */
+                       wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+                       if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) {
+                               memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len);
+                       } else {
+                               WL_ERR(("Found WFD IE but there is no space, (%d)(%d)(%d)\n",
+                                       wpsie_len, p2pie_len, wfdie_len));
+                               wfdie_len = 0;
+                       }
+               } else {
+                       WL_ERR(("No WFDIE in beacon \n"));
+               }
                /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
                wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
                wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
-                       beacon_ie, wpsie_len + p2pie_len);
+                       beacon_ie, wpsie_len + p2pie_len + wfdie_len);
 
                /* find the RSN_IE */
                if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
@@ -4714,8 +4741,9 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
        }
        notif_bss_info->rssi = dtoh16(bi->RSSI);
        memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
-       mgmt_type = wl->active_scan ?
-               IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
+       mgmt_type = (bi->flags & WL_BSS_FLAGS_FROM_BEACON) ?
+                        IEEE80211_STYPE_BEACON : IEEE80211_STYPE_PROBE_RESP;
+
        if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
            mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
        }
@@ -4744,7 +4772,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
                return -EINVAL;
        }
 
-       WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM "
+       WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
                        "mgmt_type %d frame_len %d\n", bi->SSID,
                        notif_bss_info->rssi, notif_bss_info->channel,
                        mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
@@ -6018,7 +6046,9 @@ static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
        unsigned long flags;
 
        WL_DBG(("Enter \n"));
-       wl->scan_busy_count = 0;
+       if(!aborted)
+               wl->scan_busy_count = 0;
+
        if (!wl_get_drv_status(wl, SCANNING, ndev)) {
                wl_clr_drv_status(wl, SCANNING, ndev);
                WL_ERR(("Scan complete while device not scanning\n"));
@@ -6175,13 +6205,30 @@ static void wl_scan_timeout(unsigned long data)
 {
        struct wl_priv *wl = (struct wl_priv *)data;
 
+       schedule_work(&wl->work_scan_timeout);
+}
+
+static void wl_scan_timeout_process(struct work_struct *work)
+{
+       struct wl_priv *wl;
+
+       wl = (wl_priv_t *)container_of(work, wl_priv_t, work_scan_timeout);
+
        if (wl->scan_request) {
                WL_ERR(("timer expired\n"));
                if (wl->escan_on)
-                       wl_notify_escan_complete(wl, wl->escan_info.ndev, true, false);
+                       wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
                else
                        wl_notify_iscan_complete(wl_to_iscan(wl), true);
        }
+
+       /* Assume FW is in bad state if there are continuous scan timeouts */
+       wl->scan_busy_count++;
+       if (wl->scan_busy_count > WL_SCAN_BUSY_MAX) {
+               wl->scan_busy_count = 0;
+               WL_ERR(("Continuous scan timeouts!! Exercising FW hang recovery\n"));
+               net_os_send_hang_message(wl->escan_info.ndev);
+       }
 }
 
 static void wl_iscan_timer(unsigned long data)
@@ -6273,7 +6320,9 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl,
 
        WL_DBG(("Enter \n"));
 
-       wl->scan_busy_count = 0;
+       if(!aborted)
+               wl->scan_busy_count = 0;
+
        if (wl->scan_request) {
                if (wl->scan_request->dev == wl->p2p_net)
                        dev = wl_to_prmry_ndev(wl);
@@ -6344,8 +6393,11 @@ static s32 wl_escan_handler(struct wl_priv *wl,
        u32 i;
        wifi_p2p_ie_t * p2p_ie;
        u8 *p2p_dev_addr = NULL;
+
        WL_DBG((" enter event type : %d, status : %d \n",
                ntoh32(e->event_type), ntoh32(e->status)));
+
+       mutex_lock(&wl->usr_sync);
        /* P2P SCAN is coming from primary interface */
        if (wl_get_p2p_status(wl, SCANNING)) {
                if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
@@ -6358,7 +6410,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
                !wl_get_drv_status(wl, SCANNING, ndev)) {
                WL_ERR(("escan is not ready ndev %p wl->escan_on %d drv_status 0x%x\n",
                        ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev)));
-               return err;
+               goto exit;
        }
 
        if (status == WLC_E_STATUS_PARTIAL) {
@@ -6448,7 +6500,6 @@ static s32 wl_escan_handler(struct wl_priv *wl,
                                                bss->RSSI = bi->RSSI;
                                                bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
                                        }
-
                                        goto exit;
                                }
                        }
@@ -6456,7 +6507,6 @@ static s32 wl_escan_handler(struct wl_priv *wl,
                        list->version = dtoh32(bi->version);
                        list->buflen += bi_length;
                        list->count++;
-
                }
 
        }
@@ -6469,12 +6519,10 @@ static s32 wl_escan_handler(struct wl_priv *wl,
                        if (wl->afx_hdl->peer_chan == WL_INVALID)
                                complete(&wl->act_frm_scan);
                } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
-                       mutex_lock(&wl->usr_sync);
                        WL_INFO(("ESCAN COMPLETED\n"));
                        wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
                        wl_inform_bss(wl);
                        wl_notify_escan_complete(wl, ndev, false, false);
-                       mutex_unlock(&wl->usr_sync);
                }
        }
        else if (status == WLC_E_STATUS_ABORT) {
@@ -6486,14 +6534,15 @@ static s32 wl_escan_handler(struct wl_priv *wl,
                        if (wl->afx_hdl->peer_chan == WL_INVALID)
                                complete(&wl->act_frm_scan);
                } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
-                       mutex_lock(&wl->usr_sync);
                        WL_INFO(("ESCAN ABORTED\n"));
                        wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
                        wl_inform_bss(wl);
                        wl_notify_escan_complete(wl, ndev, true, false);
-                       mutex_unlock(&wl->usr_sync);
                }
        }
+       else if (status == WLC_E_STATUS_NEWSCAN) {
+                /* Do Nothing. Ignore this event */
+       }
        else {
                WL_ERR(("unexpected Escan Event %d : abort\n", status));
                wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
@@ -6504,14 +6553,13 @@ static s32 wl_escan_handler(struct wl_priv *wl,
                        if (wl->afx_hdl->peer_chan == WL_INVALID)
                                complete(&wl->act_frm_scan);
                } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
-                       mutex_lock(&wl->usr_sync);
                        wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
                        wl_inform_bss(wl);
                        wl_notify_escan_complete(wl, ndev, true, false);
-                       mutex_unlock(&wl->usr_sync);
                }
        }
 exit:
+       mutex_unlock(&wl->usr_sync);
        return err;
 }
 
@@ -6574,6 +6622,7 @@ static s32 wl_init_priv(struct wl_priv *wl)
                return -ENOMEM;
        wl_init_event_handler(wl);
        mutex_init(&wl->usr_sync);
+       INIT_WORK(&wl->work_scan_timeout, wl_scan_timeout_process);
        err = wl_init_scan(wl);
        if (err)
                return err;
@@ -6593,6 +6642,7 @@ static void wl_deinit_priv(struct wl_priv *wl)
        wl_link_down(wl);
        del_timer_sync(&wl->scan_timeout);
        wl_term_iscan(wl);
+       cancel_work_sync(&wl->work_scan_timeout);
        wl_deinit_priv_mem(wl);
        unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
 }
@@ -7097,6 +7147,10 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
                        band = IEEE80211_BAND_5GHZ;
                        ht40_allowed = (bw_cap == WLC_N_BW_20ALL) ? FALSE : TRUE;
                }
+               else {
+                       WL_ERR(("Invalid Channel received %x\n", channel));
+                       continue;
+               }
 
                for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
                        if (band_chan_arr[j].hw_value == channel) {
@@ -7225,7 +7279,7 @@ s32 wl_update_wiphybands(struct wl_priv *wl)
                        wiphy->bands[IEEE80211_BAND_2GHZ] =
                                &__wl_band_2ghz;
                        index = IEEE80211_BAND_2GHZ;
-                       if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL)
+                       if (bw_cap == WLC_N_BW_40ALL)
                                wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
                }
                if ((index >= 0) && nmode) {
index 49bed703062af5da9da3f7901de9d7db428cdef6..974770e0e899db31405a5aa730733c70dc2b402c 100644 (file)
@@ -61,13 +61,24 @@ struct wl_ibss;
 /* 0 invalidates all debug messages.  default is 1 */
 #define WL_DBG_LEVEL 0xFF
 
-#define        WL_ERR(args)                                                                    \
+#if defined(DHD_DEBUG)
+#define        WL_ERR(args)                                                            \
 do {                                                                           \
-       if (wl_dbg_level & WL_DBG_ERR) {                                \
+       if (wl_dbg_level & WL_DBG_ERR) {                                        \
                        printk(KERN_ERR "CFG80211-ERROR) %s : ", __func__);     \
                        printk args;                                            \
                }                                                               \
 } while (0)
+#else /* defined(DHD_DEBUG) */
+#define        WL_ERR(args)                                                            \
+do {                                                                           \
+       if ((wl_dbg_level & WL_DBG_ERR) && net_ratelimit())  {                  \
+                       printk(KERN_INFO "CFG80211-ERROR) %s : ", __func__);    \
+                       printk args;                                            \
+               }                                                               \
+} while (0)
+#endif /* defined(DHD_DEBUG) */
+
 #ifdef WL_INFO
 #undef WL_INFO
 #endif
@@ -387,7 +398,7 @@ struct afx_hdl {
 };
 
 /* private data of cfg80211 interface */
-struct wl_priv {
+typedef struct wl_priv {
        struct wireless_dev *wdev;      /* representing wl cfg80211 device */
 
        struct wireless_dev *p2p_wdev;  /* representing wl cfg80211 device for P2P */
@@ -457,7 +468,9 @@ struct wl_priv {
        u16 hostapd_chan;            /* remember chan requested by framework for hostapd  */
        u16 deauth_reason;           /* Place holder to save deauth/disassoc reasons */
        u16 scan_busy_count;
-};
+       struct work_struct work_scan_timeout;
+} wl_priv_t;
+
 
 static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
 {
index bdcfa95307c759020ffb70b377fe43654691c4aa..f06ae50b12ab58690f6a3a981a3d36958663d0e2 100644 (file)
@@ -641,8 +641,8 @@ wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev,
        }
 set_ie:
        ret = wl_cfgp2p_set_management_ie(wl, dev,
-                   wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE),
-                   VNDR_IE_PRBREQ_FLAG, ie, ie_len);
+                               wl_cfgp2p_find_idx(wl, dev),
+                               VNDR_IE_PRBREQ_FLAG, ie, ie_len);
 
        if (unlikely(ret < 0)) {
                CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
@@ -846,6 +846,11 @@ exit:
 /* Check whether the given IE looks like WFA P2P IE. */
 #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)     wl_cfgp2p_has_ie(ie, tlvs, len, \
                (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
+       /* Check whether the given IE looks like WFA WFDisplay IE. */
+#define WFA_OUI_TYPE_WFD       0x0a                    /* WiFi Display OUI TYPE */
+#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)     wl_cfgp2p_has_ie(ie, tlvs, len, \
+                               (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
+
 /* Delete and Set a management vndr ie to firmware
  * Parameters:
  * @wl       : wl_private data
@@ -970,7 +975,8 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
                                ie_len = ie_buf[pos++];
                                if ((ie_id == DOT11_MNG_VS_ID) &&
                                   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
-                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
+                                       wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
                                        CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :"
                                                "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
                                                ie_buf[pos+1], ie_buf[pos+2]));
@@ -996,7 +1002,8 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
                                ie_len = ie_buf[pos++];
                                if ((ie_id == DOT11_MNG_VS_ID) &&
                                   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
-                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
+                                       wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
                                        CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :"
                                                "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
                                                ie_buf[pos+1], ie_buf[pos+2]));
@@ -1107,6 +1114,19 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
        return NULL;
 }
 
+wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
+{
+       bcm_tlv_t *ie;
+
+       while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+               if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
+                       return (wifi_wfd_ie_t *)ie;
+               }
+       }
+       return NULL;
+}
+
 static s32
 wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
             s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete)
index 05323ed5d48179bf0026b1919ea2a732e5a30c9b..03a645aea31a5b45710fc9455e6a28a1b3b9a433 100644 (file)
@@ -31,6 +31,8 @@
 struct wl_priv;
 extern u32 wl_dbg_level;
 
+typedef struct wifi_p2p_ie wifi_wfd_ie_t;
+
 /* Enumeration of the usages of the BSSCFGs used by the P2P Library.  Do not
  * confuse this with a bsscfg index.  This value is an index into the
  * saved_ie[] array of structures which in turn contains a bsscfg index field.
@@ -192,6 +194,9 @@ wl_cfgp2p_find_wpsie(u8 *parse, u32 len);
 extern wifi_p2p_ie_t *
 wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
 
+extern wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len);
+
 extern s32
 wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
             s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len);
index 51a80645fb349ff945475c18b246982d5a0bf27b..7bea3dcfa71632294308fe4abfb374e2b1de0a3d 100644 (file)
@@ -334,8 +334,11 @@ int wldev_set_country(
        scb_val_t scbval;
        char smbuf[WLC_IOCTL_SMLEN];
 
-       if (!country_code)
+       if (!country_code) {
+               WLDEV_ERROR(("%s: set country failed for %s\n",
+                       __FUNCTION__, country_code));
                return error;
+       }
 
        error = wldev_iovar_getbuf(dev, "country", &cspec, sizeof(cspec),
                smbuf, sizeof(smbuf), NULL);