[PATCH 3/3] Add missed beacon support
Eugene Krasnikov
k.eugene.e at gmail.com
Tue Jul 2 08:11:10 EDT 2013
In BMPS mode if FW lost connection to AP it will report
WCN36XX_HAL_MISSED_BEACON_IND. Notify mac8021 about connection
lost in this case.
Signed-off-by: Eugene Krasnikov <k.eugene.e at gmail.com>
---
hal.h | 2 +-
main.c | 17 +++++++++++++++++
smd.c | 28 ++++++++++++++++++++++++++++
wcn36xx.h | 6 ++++++
4 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/hal.h b/hal.h
index 122e077..83b9f49 100644
--- a/hal.h
+++ b/hal.h
@@ -2956,7 +2956,7 @@ struct wcn36xx_hal_missed_beacon_ind_msg {
struct wcn36xx_hal_msg_header header;
u8 bss_index;
-};
+} __packed;
/* Beacon Filtering data structures */
diff --git a/main.c b/main.c
index cf0d270..0cc3e02 100644
--- a/main.c
+++ b/main.c
@@ -725,22 +725,36 @@ static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
drv_priv);
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend");
+ mutex_lock(&wcn->pm_mutex);
/* Enter BMPS only in connected state */
if (wcn->aid > 0)
wcn36xx_smd_enter_bmps(wcn, vif->bss_conf.sync_tsf);
+ wcn->is_suspended = true;
+ wcn->is_con_lost_pending = false;
flush_work(&wcn->rx_ready_work);
flush_work(&wcn->smd_work);
+ mutex_unlock(&wcn->pm_mutex);
return 0;
}
static int wcn36xx_resume(struct ieee80211_hw *hw)
{
struct wcn36xx *wcn = hw->priv;
+ struct ieee80211_vif *vif = container_of((void *)wcn->current_vif,
+ struct ieee80211_vif,
+ drv_priv);
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume");
+ wcn->is_suspended = false;
if (wcn->aid > 0)
wcn36xx_smd_exit_bmps(wcn);
+
+ if (wcn->is_con_lost_pending) {
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "report connection lost");
+ ieee80211_connection_loss(vif);
+ }
+
return 0;
}
#endif
@@ -929,6 +943,8 @@ static int __init wcn36xx_init(void)
wcn->aid = 0;
wcn->current_vif = NULL;
wcn->is_joining = false;
+
+ mutex_init(&wcn->pm_mutex);
wcn->hw->wiphy->n_addresses = ARRAY_SIZE(wcn->addresses);
wcn->hw->wiphy->addresses = wcn->addresses;
@@ -985,6 +1001,7 @@ static void __exit wcn36xx_exit(void)
struct ieee80211_hw *hw = private_hw;
struct wcn36xx *wcn = hw->priv;
+ mutex_destroy(&wcn->pm_mutex);
ieee80211_unregister_hw(hw);
destroy_workqueue(wcn->wq);
iounmap(wcn->mmio);
diff --git a/smd.c b/smd.c
index c1ab351..ce09563 100644
--- a/smd.c
+++ b/smd.c
@@ -1085,6 +1085,31 @@ static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
return 0;
}
+static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
+ void *buf,
+ size_t len)
+{
+ struct ieee80211_vif *vif = container_of((void *)wcn->current_vif,
+ struct ieee80211_vif,
+ drv_priv);
+ mutex_lock(&wcn->pm_mutex);
+ /*
+ * In suspended state mac80211 is still sleeping and that means we
+ * cannot notify it about connection lost. Wait until resume and
+ * then notify mac80211 about it.
+ */
+ if (wcn->is_suspended) {
+ wcn36xx_dbg(WCN36XX_DBG_HAL,
+ "postpone connection lost notification");
+ wcn->is_con_lost_pending = true;
+ } else {
+ wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed");
+ ieee80211_connection_loss(vif);
+ }
+ mutex_unlock(&wcn->pm_mutex);
+ return 0;
+}
+
static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
{
struct wcn36xx_hal_msg_header *msg_header = buf;
@@ -1138,6 +1163,9 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
case WCN36XX_HAL_OTA_TX_COMPL_IND:
wcn36xx_smd_tx_compl_ind(wcn, buf, len);
break;
+ case WCN36XX_HAL_MISSED_BEACON_IND:
+ wcn36xx_smd_missed_beacon_ind(wcn, buf, len);
+ break;
default:
wcn36xx_error("SMD_EVENT (%d) not supported", msg_header->msg_type);
}
diff --git a/wcn36xx.h b/wcn36xx.h
index fd98807..2c72349 100644
--- a/wcn36xx.h
+++ b/wcn36xx.h
@@ -113,6 +113,12 @@ struct wcn36xx {
u16 beacon_interval;
u8 dtim_period;
enum ani_ed_type encrypt_type;
+
+ /* WoW related*/
+ struct mutex pm_mutex;
+ bool is_suspended;
+ bool is_con_lost_pending;
+
u8 fw_revision;
u8 fw_version;
u8 fw_minor;
--
1.7.11.3
More information about the wcn36xx
mailing list