[PATCH 6/9] wcn36xx: enter BMPS right after DORA is finished
Eugene Krasnikov
k.eugene.e at gmail.com
Fri Sep 6 04:09:18 EDT 2013
This is when wcn36xx can start to save power.
Signed-off-by: Eugene Krasnikov <k.eugene.e at gmail.com>
---
debug.c | 6 +++---
main.c | 47 +++++++++++++++--------------------------------
pmc.c | 35 +++++++++++++++++++++++++++--------
pmc.h | 10 ++++++----
smd.c | 19 ++++++++++++-------
smd.h | 8 +++++---
wcn36xx.h | 5 -----
7 files changed, 68 insertions(+), 62 deletions(-)
diff --git a/debug.c b/debug.c
index 91508f3..f23301e 100644
--- a/debug.c
+++ b/debug.c
@@ -67,13 +67,13 @@ static ssize_t write_file_bool_bmps(struct file *file,
case 'y':
case 'Y':
case '1':
- wcn36xx_enable_keep_alive_null_packet(wcn);
- wcn36xx_pmc_enter_bmps_state(wcn, vif->bss_conf.sync_tsf);
+ wcn36xx_enable_keep_alive_null_packet(wcn, vif);
+ wcn36xx_pmc_enter_bmps_state(wcn, vif);
break;
case 'n':
case 'N':
case '0':
- wcn36xx_pmc_exit_bmps_state(wcn);
+ wcn36xx_pmc_exit_bmps_state(wcn, vif);
break;
}
diff --git a/main.c b/main.c
index d5cf15d..aaa4176 100644
--- a/main.c
+++ b/main.c
@@ -507,6 +507,17 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
wcn->dtim_period = bss_conf->dtim_period;
}
+ if (changed & BSS_CHANGED_PS) {
+ wcn36xx_dbg(WCN36XX_DBG_MAC,
+ "mac bss PS set %d\n",
+ bss_conf->ps);
+ if (bss_conf->ps) {
+ wcn36xx_pmc_enter_bmps_state(wcn, vif);
+ } else {
+ wcn36xx_pmc_exit_bmps_state(wcn, vif);
+ }
+ }
+
if (changed & BSS_CHANGED_BSSID) {
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
bss_conf->bssid);
@@ -656,6 +667,8 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
{
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
+ wcn->current_vif = vif_priv;
+
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
vif, vif->type);
@@ -711,47 +724,19 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
{
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 suspend\n");
- mutex_lock(&wcn->pm_mutex);
-
- /* Enter BMPS only in connected state */
- if ((wcn->aid > 0) &&
- (wcn->pw_state != WCN36XX_BMPS) &&
- (NL80211_IFTYPE_STATION == vif->type))
- wcn36xx_pmc_enter_bmps_state(wcn, vif->bss_conf.sync_tsf);
-
- wcn->is_suspended = true;
- wcn->is_con_lost_pending = false;
-
- mutex_unlock(&wcn->pm_mutex);
-
+ flush_workqueue(wcn->hal_ind_wq);
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\n");
- wcn->is_suspended = false;
-
- if (wcn->pw_state == WCN36XX_BMPS)
- wcn36xx_pmc_exit_bmps_state(wcn);
-
- if (wcn->is_con_lost_pending) {
- wcn36xx_dbg(WCN36XX_DBG_MAC, "report connection lost\n");
- ieee80211_connection_loss(vif);
- }
-
+ flush_workqueue(wcn->hal_ind_wq);
return 0;
}
@@ -946,7 +931,6 @@ static int wcn36xx_probe(struct platform_device *pdev)
wcn->dev = &pdev->dev;
wcn->ctrl_ops = pdev->dev.platform_data;
- mutex_init(&wcn->pm_mutex);
mutex_init(&wcn->hal_mutex);
/* Configuring supported rates */
@@ -986,7 +970,6 @@ static int wcn36xx_remove(struct platform_device *pdev)
struct wcn36xx *wcn = hw->priv;
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
- mutex_destroy(&wcn->pm_mutex);
mutex_destroy(&wcn->hal_mutex);
ieee80211_unregister_hw(hw);
diff --git a/pmc.c b/pmc.c
index f72096e..beffe8b 100644
--- a/pmc.c
+++ b/pmc.c
@@ -24,23 +24,42 @@ int wcn36xx_pmc_init(struct wcn36xx *wcn)
return 0;
}
-int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, u64 tsf)
+int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif)
{
+ int ret = 0;
/* TODO: Make sure the TX chain clean */
- wcn36xx_smd_enter_bmps(wcn, tsf);
- wcn->pw_state = WCN36XX_BMPS;
- return 0;
+ ret = wcn36xx_smd_enter_bmps(wcn, vif);
+ if (!ret) {
+ wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n");
+ wcn->pw_state = WCN36XX_BMPS;
+ } else {
+ /*
+ * One of the reasons why HW will not enter BMPS is because
+ * driver is trying to enter bmps before first beacon was
+ * received just after auth complete
+ */
+ wcn36xx_err("Can not enter BMPS!\n");
+ }
+ return ret;
}
-int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn)
+int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif)
{
- wcn36xx_smd_exit_bmps(wcn);
+ if (WCN36XX_BMPS != wcn->pw_state) {
+ wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n");
+ return -EINVAL;
+ }
+ wcn36xx_smd_exit_bmps(wcn, vif);
wcn->pw_state = WCN36XX_FULL_POWER;
return 0;
}
-int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn)
+int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif)
{
wcn36xx_dbg(WCN36XX_DBG_PMC, "%s\n", __func__);
- return wcn36xx_smd_keep_alive_req(wcn, WCN36XX_HAL_KEEP_ALIVE_NULL_PKT);
+ return wcn36xx_smd_keep_alive_req(wcn, vif,
+ WCN36XX_HAL_KEEP_ALIVE_NULL_PKT);
}
diff --git a/pmc.h b/pmc.h
index b00d425..1f743a9 100644
--- a/pmc.h
+++ b/pmc.h
@@ -25,8 +25,10 @@ enum wcn36xx_power_state {
};
int wcn36xx_pmc_init(struct wcn36xx *wcn);
-int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, u64 tbtt);
-int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn);
-int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn);
-int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn);
+int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif);
+int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif);
+int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif);
#endif /* _WCN36XX_PMC_H_ */
diff --git a/smd.c b/smd.c
index 9ebe859..7fdc001 100644
--- a/smd.c
+++ b/smd.c
@@ -1481,16 +1481,17 @@ out:
return ret;
}
-int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, u64 tbtt)
+int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
{
struct wcn36xx_hal_enter_bmps_req_msg msg_body;
+ struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
int ret = 0;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
- msg_body.bss_index = wcn->current_vif->bss_index;
- msg_body.tbtt = tbtt;
+ msg_body.bss_index = vif_priv->bss_index;
+ msg_body.tbtt = vif->bss_conf.sync_tsf;
msg_body.dtim_period = wcn->dtim_period;
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
@@ -1510,15 +1511,16 @@ out:
return ret;
}
-int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn)
+int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
{
struct wcn36xx_hal_enter_bmps_req_msg msg_body;
+ struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
int ret = 0;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
- msg_body.bss_index = wcn->current_vif->bss_index;
+ msg_body.bss_index = vif_priv->bss_index;
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
@@ -1540,16 +1542,19 @@ out:
/* Notice: This function should be called after associated, or else it
* will be invalid
*/
-int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, int packet_type)
+int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif,
+ int packet_type)
{
struct wcn36xx_hal_keep_alive_req_msg msg_body;
+ struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
int ret = 0;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
- msg_body.bss_index = wcn->current_vif->bss_index;
+ msg_body.bss_index = vif_priv->bss_index;
msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
} else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
diff --git a/smd.h b/smd.h
index a58f4c4..df1a021 100644
--- a/smd.h
+++ b/smd.h
@@ -98,9 +98,11 @@ int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
enum ani_ed_type enc_type,
u8 keyidx);
-int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, u64 tbtt);
-int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn);
-int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, int packet_type);
+int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif);
+int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif);
+int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
+ struct ieee80211_vif *vif,
+ int packet_type);
int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
u32 arg3, u32 arg4, u32 arg5);
int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn);
diff --git a/wcn36xx.h b/wcn36xx.h
index aac9d6a..242edb6 100644
--- a/wcn36xx.h
+++ b/wcn36xx.h
@@ -166,11 +166,6 @@ struct wcn36xx {
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.8.2.2
More information about the wcn36xx
mailing list