From c305cc6ea0a030d9a49ec24c0ab38070b09f8f32 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 24 Oct 2012 13:14:48 -0700 Subject: net: wireless: bcmdhd: Fix BSSID report for disassoc Change-Id: I5e3b01a1a471e5983ab934fc9d65802a389ab1af Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/include/bcmutils.h | 2 ++ drivers/net/wireless/bcmdhd/wl_cfg80211.c | 30 ++++++++++++++++++++++---- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 2 ++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h index 6849c26..a570fa2 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h @@ -603,6 +603,8 @@ extern void *_bcmutils_dummy_fn; #define CRC32_INIT_VALUE 0xffffffff #define CRC32_GOOD_VALUE 0xdebb20e3 +#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] typedef struct bcm_bit_desc { uint32 bit; diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 5abe2b3..b4f47d1 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -1867,6 +1867,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, /* Clean BSSID */ bzero(&bssid, sizeof(bssid)); wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID); + wl_update_prof(wl, dev, NULL, params->bssid, WL_PROF_PENDING_BSSID); if (params->ssid) WL_INFO(("SSID: %s\n", params->ssid)); @@ -2338,6 +2339,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, /* Clean BSSID */ bzero(&bssid, sizeof(bssid)); wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID); + wl_update_prof(wl, dev, NULL, sme->bssid, WL_PROF_PENDING_BSSID); if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) { /* we only allow to connect using virtual interface in case of P2P */ @@ -5142,7 +5144,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, WL_DBG(("wl_ibss_join_done succeeded\n")); } else { if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { - printk("wl_bss_connect_done succeeded\n"); + printk("wl_bss_connect_done succeeded with " MACDBG "\n", + MAC2STRDBG((u8*)(&e->addr))); wl_bss_connect_done(wl, ndev, e, data, true); WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) @@ -5191,8 +5194,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, wl_clr_drv_status(wl, DISCONNECTING, ndev); } else if (wl_is_nonetwork(wl, e)) { - printk("connect failed event=%d e->status 0x%x\n", - event, (int)ntoh32(e->status)); + printk("connect failed event=%d e->status %d e->reason %d\n", + event, (int)ntoh32(e->status), (int)ntoh32(e->reason)); /* Clean up any pending scan request */ if (wl->scan_request) { if (wl->escan_on) { @@ -5452,9 +5455,17 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); WL_DBG((" enter\n")); + if (wl->scan_request) { wl_notify_escan_complete(wl, ndev, true, true); } + if (is_zero_ether_addr(curbssid)) { + curbssid = wl_read_prof(wl, ndev, WL_PROF_PENDING_BSSID); + if (is_zero_ether_addr(curbssid)) { + WL_ERR(("Invalid BSSID\n")); + curbssid = NULL; + } + } if (wl_get_drv_status(wl, CONNECTING, ndev)) { wl_clr_drv_status(wl, CONNECTING, ndev); if (completed) { @@ -5471,7 +5482,9 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, - completed ? WLAN_STATUS_SUCCESS : e->reason, + completed ? WLAN_STATUS_SUCCESS : + (e->reason) ? ntoh32(e->reason) : + WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); if (completed) WL_INFO(("Report connect result - connection succeeded\n")); @@ -7469,6 +7482,9 @@ static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item) case WL_PROF_BSSID: rptr = profile->bssid; break; + case WL_PROF_PENDING_BSSID: + rptr = profile->pending_bssid; + break; case WL_PROF_SSID: rptr = &profile->ssid; break; @@ -7505,6 +7521,12 @@ wl_update_prof(struct wl_priv *wl, struct net_device *ndev, else memset(profile->bssid, 0, ETHER_ADDR_LEN); break; + case WL_PROF_PENDING_BSSID: + if (data) + memcpy(profile->pending_bssid, data, ETHER_ADDR_LEN); + else + memset(profile->pending_bssid, 0, ETHER_ADDR_LEN); + break; case WL_PROF_SEC: memcpy(&profile->sec, data, sizeof(profile->sec)); break; diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 39832a5..dfb0d0d 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -183,6 +183,7 @@ enum wl_prof_list { WL_PROF_IBSS, WL_PROF_BAND, WL_PROF_BSSID, + WL_PROF_PENDING_BSSID, WL_PROF_ACT, WL_PROF_BEACONINT, WL_PROF_DTIMPERIOD @@ -285,6 +286,7 @@ struct wl_profile { struct wl_security sec; struct wl_ibss ibss; u8 bssid[ETHER_ADDR_LEN]; + u8 pending_bssid[ETHER_ADDR_LEN]; u16 beacon_interval; u8 dtim_period; bool active; -- cgit v1.1 From 834029ac9d0ad8dea4e6a21bc34877dc3740b9f4 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 23 Oct 2012 11:39:40 -0700 Subject: net: wireless: bcmdhd: Fix WD wakelock behavior Change-Id: I7ebae2be248cbb4bc98e2b448641f65b77a320f4 Signed-off-by: Dmitry Shmidt Conflicts: drivers/net/wireless/bcmdhd/dhd_linux.c --- drivers/net/wireless/bcmdhd/dhd.h | 8 +++-- drivers/net/wireless/bcmdhd/dhd_linux.c | 64 +++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 34616d3..5160ee1 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -301,6 +301,8 @@ extern int dhd_os_wake_unlock(dhd_pub_t *pub); extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); +extern int dhd_os_wd_wake_lock(dhd_pub_t *pub); +extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub); inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) { @@ -323,8 +325,10 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ } -#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) -#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) +#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) +#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) +#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub) +#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub) #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) #define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_rx_timeout_enable(pub, val) #define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_ctrl_timeout_enable(pub, val) diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 0f419a5..d0b4c1c 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -259,6 +259,7 @@ typedef struct dhd_info { struct wake_lock wl_wifi; /* Wifi wakelock */ struct wake_lock wl_rxwake; /* Wifi rx wakelock */ struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */ + struct wake_lock wl_wdwake; /* Wifi wd wakelock */ #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) @@ -270,6 +271,7 @@ typedef struct dhd_info { #endif spinlock_t wakelock_spinlock; int wakelock_counter; + int wakelock_wd_counter; int wakelock_rx_timeout_enable; int wakelock_ctrl_timeout_enable; @@ -1697,7 +1699,6 @@ dhd_watchdog_thread(void *data) dhd_os_spin_unlock(&dhd->pub, flags); } dhd_os_sdunlock(&dhd->pub); - DHD_OS_WAKE_UNLOCK(&dhd->pub); } else { break; } @@ -1711,9 +1712,7 @@ static void dhd_watchdog(ulong data) dhd_info_t *dhd = (dhd_info_t *)data; unsigned long flags; - DHD_OS_WAKE_LOCK(&dhd->pub); if (dhd->pub.dongle_reset) { - DHD_OS_WAKE_UNLOCK(&dhd->pub); return; } @@ -1737,7 +1736,6 @@ static void dhd_watchdog(ulong data) mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); dhd_os_spin_unlock(&dhd->pub, flags); dhd_os_sdunlock(&dhd->pub); - DHD_OS_WAKE_UNLOCK(&dhd->pub); } #ifdef DHDTHREAD @@ -2681,12 +2679,14 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) /* Initialize Wakelock stuff */ spin_lock_init(&dhd->wakelock_spinlock); dhd->wakelock_counter = 0; + dhd->wakelock_wd_counter = 0; dhd->wakelock_rx_timeout_enable = 0; dhd->wakelock_ctrl_timeout_enable = 0; #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); + wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_init(&dhd->dhd_net_if_mutex); @@ -2871,12 +2871,12 @@ dhd_bus_start(dhd_pub_t *dhdp) dhd->wd_timer_valid = FALSE; dhd_os_spin_unlock(&dhd->pub, flags); del_timer_sync(&dhd->timer); - DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__)); #ifdef DHDTHREAD if (dhd->threads_only) dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); return -ENODEV; } @@ -2895,6 +2895,7 @@ dhd_bus_start(dhd_pub_t *dhdp) if (dhd->threads_only) dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); return -ENODEV; } @@ -3787,10 +3788,15 @@ void dhd_detach(dhd_pub_t *dhdp) if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) { #ifdef CONFIG_HAS_WAKELOCK + dhd->wakelock_counter = 0; + dhd->wakelock_wd_counter = 0; + dhd->wakelock_rx_timeout_enable = 0; + dhd->wakelock_ctrl_timeout_enable = 0; wake_lock_destroy(&dhd->wl_wifi); wake_lock_destroy(&dhd->wl_rxwake); wake_lock_destroy(&dhd->wl_ctrlwake); -#endif + wake_lock_destroy(&dhd->wl_wdwake); +#endif /* CONFIG_HAS_WAKELOCK */ } } @@ -3983,11 +3989,18 @@ dhd_os_wd_timer(void *bus, uint wdtick) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + if (!dhd) + return; + + if (wdtick) + DHD_OS_WD_WAKE_LOCK(pub); + flags = dhd_os_spin_lock(pub); /* don't start the wd until fw is loaded */ if (pub->busstate == DHD_BUS_DOWN) { dhd_os_spin_unlock(pub, flags); + DHD_OS_WD_WAKE_UNLOCK(pub); return; } @@ -4000,6 +4013,7 @@ dhd_os_wd_timer(void *bus, uint wdtick) #else del_timer(&dhd->timer); #endif /* DHDTHREAD */ + DHD_OS_WD_WAKE_UNLOCK(pub); return; } @@ -4877,6 +4891,44 @@ int net_os_wake_unlock(struct net_device *dev) return ret; } +int dhd_os_wd_wake_lock(dhd_pub_t *pub) +{ + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + unsigned long flags; + int ret = 0; + + if (dhd) { + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); +#ifdef CONFIG_HAS_WAKELOCK + if (!dhd->wakelock_wd_counter) + wake_lock(&dhd->wl_wdwake); +#endif + dhd->wakelock_wd_counter++; + ret = dhd->wakelock_wd_counter; + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + } + return ret; +} + +int dhd_os_wd_wake_unlock(dhd_pub_t *pub) +{ + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + unsigned long flags; + int ret = 0; + + if (dhd) { + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + if (dhd->wakelock_wd_counter) { + dhd->wakelock_wd_counter = 0; +#ifdef CONFIG_HAS_WAKELOCK + wake_unlock(&dhd->wl_wdwake); +#endif + } + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + } + return ret; +} + int dhd_os_check_if_up(void *dhdp) { dhd_pub_t *pub = (dhd_pub_t *)dhdp; -- cgit v1.1