aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKobi L <kobi.lev100@gmail.com>2014-12-29 01:24:06 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-01-09 08:47:56 -0500
commite2f1e50f62ae70c7ddde8420ed586c6a1aa1e28c (patch)
treeac6899c92762ba38f8f2eb0c3fc251b09044fec0
parentb8714d1b6a7ee4c4e4730203a90e1db6485d9343 (diff)
wlcore: enable sleep during AP mode operation
Enable ELP authorization in AP mode and enable the use of the wakeup bit in the ELP register. Introduce AP role sleep configuration which is disabled by default. When configured, it allows the AP to sleep when ELP is authorized for it. Signed-off-by: Kobi Leibovitch <kobi.lev100@gmail.com> Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c1
-rw-r--r--drivers/net/wireless/ti/wl18xx/acx.c32
-rw-r--r--drivers/net/wireless/ti/wl18xx/acx.h25
-rw-r--r--drivers/net/wireless/ti/wl18xx/conf.h23
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c7
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h9
-rw-r--r--drivers/net/wireless/ti/wlcore/init.c8
-rw-r--r--drivers/net/wireless/ti/wlcore/ps.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h1
9 files changed, 101 insertions, 11 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index f3cee5ad7026..144d1f8ba473 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1731,6 +1731,7 @@ static struct wlcore_ops wl12xx_ops = {
1731 .lnk_low_prio = wl12xx_lnk_low_prio, 1731 .lnk_low_prio = wl12xx_lnk_low_prio,
1732 .interrupt_notify = NULL, 1732 .interrupt_notify = NULL,
1733 .rx_ba_filter = NULL, 1733 .rx_ba_filter = NULL,
1734 .ap_sleep = NULL,
1734}; 1735};
1735 1736
1736static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { 1737static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c
index 9d4b9aacd037..67f2a0eec854 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.c
+++ b/drivers/net/wireless/ti/wl18xx/acx.c
@@ -24,6 +24,7 @@
24#include "../wlcore/acx.h" 24#include "../wlcore/acx.h"
25 25
26#include "acx.h" 26#include "acx.h"
27#include "wl18xx.h"
27 28
28int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, 29int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
29 u32 sdio_blk_size, u32 extra_mem_blks, 30 u32 sdio_blk_size, u32 extra_mem_blks,
@@ -250,3 +251,34 @@ out:
250 kfree(acx); 251 kfree(acx);
251 return ret; 252 return ret;
252} 253}
254
255int wl18xx_acx_ap_sleep(struct wl1271 *wl)
256{
257 struct wl18xx_priv *priv = wl->priv;
258 struct acx_ap_sleep_cfg *acx;
259 struct conf_ap_sleep_settings *conf = &priv->conf.ap_sleep;
260 int ret;
261
262 wl1271_debug(DEBUG_ACX, "acx config ap sleep");
263
264 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
265 if (!acx) {
266 ret = -ENOMEM;
267 goto out;
268 }
269
270 acx->idle_duty_cycle = conf->idle_duty_cycle;
271 acx->connected_duty_cycle = conf->connected_duty_cycle;
272 acx->max_stations_thresh = conf->max_stations_thresh;
273 acx->idle_conn_thresh = conf->idle_conn_thresh;
274
275 ret = wl1271_cmd_configure(wl, ACX_AP_SLEEP_CFG, acx, sizeof(*acx));
276 if (ret < 0) {
277 wl1271_warning("acx config ap-sleep failed: %d", ret);
278 goto out;
279 }
280
281out:
282 kfree(acx);
283 return ret;
284}
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index 1234bdc6d1b9..4afccd4b9467 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -34,8 +34,8 @@ enum {
34 ACX_AUTO_RX_STREAMING = 0x0055, 34 ACX_AUTO_RX_STREAMING = 0x0055,
35 ACX_PEER_CAP = 0x0056, 35 ACX_PEER_CAP = 0x0056,
36 ACX_INTERRUPT_NOTIFY = 0x0057, 36 ACX_INTERRUPT_NOTIFY = 0x0057,
37 ACX_RX_BA_FILTER = 0x0058 37 ACX_RX_BA_FILTER = 0x0058,
38 38 ACX_AP_SLEEP_CFG = 0x0059
39}; 39};
40 40
41/* numbers of bits the length field takes (add 1 for the actual number) */ 41/* numbers of bits the length field takes (add 1 for the actual number) */
@@ -347,6 +347,26 @@ struct wl18xx_acx_rx_ba_filter {
347 u32 enable; 347 u32 enable;
348}; 348};
349 349
350struct acx_ap_sleep_cfg {
351 struct acx_header header;
352 /* Duty Cycle (20-80% of staying Awake) for IDLE AP
353 * (0: disable)
354 */
355 u8 idle_duty_cycle;
356 /* Duty Cycle (20-80% of staying Awake) for Connected AP
357 * (0: disable)
358 */
359 u8 connected_duty_cycle;
360 /* Maximum stations that are allowed to be connected to AP
361 * (255: no limit)
362 */
363 u8 max_stations_thresh;
364 /* Timeout till enabling the Sleep Mechanism after data stops
365 * [unit: 100 msec]
366 */
367 u8 idle_conn_thresh;
368} __packed;
369
350int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, 370int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
351 u32 sdio_blk_size, u32 extra_mem_blks, 371 u32 sdio_blk_size, u32 extra_mem_blks,
352 u32 len_field_size); 372 u32 len_field_size);
@@ -359,5 +379,6 @@ int wl18xx_acx_set_peer_cap(struct wl1271 *wl,
359 u32 rate_set, u8 hlid); 379 u32 rate_set, u8 hlid);
360int wl18xx_acx_interrupt_notify_config(struct wl1271 *wl, bool action); 380int wl18xx_acx_interrupt_notify_config(struct wl1271 *wl, bool action);
361int wl18xx_acx_rx_ba_filter(struct wl1271 *wl, bool action); 381int wl18xx_acx_rx_ba_filter(struct wl1271 *wl, bool action);
382int wl18xx_acx_ap_sleep(struct wl1271 *wl);
362 383
363#endif /* __WL18XX_ACX_H__ */ 384#endif /* __WL18XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
index e34302e3b51d..71f1ec448ba5 100644
--- a/drivers/net/wireless/ti/wl18xx/conf.h
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -23,7 +23,7 @@
23#define __WL18XX_CONF_H__ 23#define __WL18XX_CONF_H__
24 24
25#define WL18XX_CONF_MAGIC 0x10e100ca 25#define WL18XX_CONF_MAGIC 0x10e100ca
26#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0006) 26#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0007)
27#define WL18XX_CONF_MASK 0x0000ffff 27#define WL18XX_CONF_MASK 0x0000ffff
28#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ 28#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
29 sizeof(struct wl18xx_priv_conf)) 29 sizeof(struct wl18xx_priv_conf))
@@ -110,12 +110,33 @@ struct wl18xx_ht_settings {
110 u8 mode; 110 u8 mode;
111} __packed; 111} __packed;
112 112
113struct conf_ap_sleep_settings {
114 /* Duty Cycle (20-80% of staying Awake) for IDLE AP
115 * (0: disable)
116 */
117 u8 idle_duty_cycle;
118 /* Duty Cycle (20-80% of staying Awake) for Connected AP
119 * (0: disable)
120 */
121 u8 connected_duty_cycle;
122 /* Maximum stations that are allowed to be connected to AP
123 * (255: no limit)
124 */
125 u8 max_stations_thresh;
126 /* Timeout till enabling the Sleep Mechanism after data stops
127 * [unit: 100 msec]
128 */
129 u8 idle_conn_thresh;
130} __packed;
131
113struct wl18xx_priv_conf { 132struct wl18xx_priv_conf {
114 /* Module params structures */ 133 /* Module params structures */
115 struct wl18xx_ht_settings ht; 134 struct wl18xx_ht_settings ht;
116 135
117 /* this structure is copied wholesale to FW */ 136 /* this structure is copied wholesale to FW */
118 struct wl18xx_mac_and_phy_params phy; 137 struct wl18xx_mac_and_phy_params phy;
138
139 struct conf_ap_sleep_settings ap_sleep;
119} __packed; 140} __packed;
120 141
121#endif /* __WL18XX_CONF_H__ */ 142#endif /* __WL18XX_CONF_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 6c1000d1735b..04db941e1913 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -568,6 +568,12 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
568 .high_power_val_2nd = 0xff, 568 .high_power_val_2nd = 0xff,
569 .tx_rf_margin = 1, 569 .tx_rf_margin = 1,
570 }, 570 },
571 .ap_sleep = { /* disabled by default */
572 .idle_duty_cycle = 0,
573 .connected_duty_cycle = 0,
574 .max_stations_thresh = 0,
575 .idle_conn_thresh = 0,
576 },
571}; 577};
572 578
573static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = { 579static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
@@ -1696,6 +1702,7 @@ static struct wlcore_ops wl18xx_ops = {
1696 .smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key, 1702 .smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key,
1697 .interrupt_notify = wl18xx_acx_interrupt_notify_config, 1703 .interrupt_notify = wl18xx_acx_interrupt_notify_config,
1698 .rx_ba_filter = wl18xx_acx_rx_ba_filter, 1704 .rx_ba_filter = wl18xx_acx_rx_ba_filter,
1705 .ap_sleep = wl18xx_acx_ap_sleep,
1699}; 1706};
1700 1707
1701/* HT cap appropriate for wide channels in 2Ghz */ 1708/* HT cap appropriate for wide channels in 2Ghz */
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index c2545ce6b2db..449050b5c750 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -234,6 +234,15 @@ wlcore_hw_rx_ba_filter(struct wl1271 *wl, bool action)
234} 234}
235 235
236static inline int 236static inline int
237wlcore_hw_ap_sleep(struct wl1271 *wl)
238{
239 if (wl->ops->ap_sleep)
240 return wl->ops->ap_sleep(wl);
241
242 return 0;
243}
244
245static inline int
237wlcore_hw_set_peer_cap(struct wl1271 *wl, 246wlcore_hw_set_peer_cap(struct wl1271 *wl,
238 struct ieee80211_sta_ht_cap *ht_cap, 247 struct ieee80211_sta_ht_cap *ht_cap,
239 bool allow_ht_operation, 248 bool allow_ht_operation,
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c
index 199e94120864..5ca1fb161a50 100644
--- a/drivers/net/wireless/ti/wlcore/init.c
+++ b/drivers/net/wireless/ti/wlcore/init.c
@@ -392,6 +392,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
392 if (ret < 0) 392 if (ret < 0)
393 return ret; 393 return ret;
394 394
395 /* configure AP sleep, if enabled */
396 ret = wlcore_hw_ap_sleep(wl);
397 if (ret < 0)
398 return ret;
399
395 return 0; 400 return 0;
396} 401}
397 402
@@ -567,8 +572,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
567 /* consider all existing roles before configuring psm. */ 572 /* consider all existing roles before configuring psm. */
568 573
569 if (wl->ap_count == 0 && is_ap) { /* first AP */ 574 if (wl->ap_count == 0 && is_ap) { /* first AP */
570 /* Configure for power always on */ 575 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
571 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
572 if (ret < 0) 576 if (ret < 0)
573 return ret; 577 return ret;
574 578
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index b52516eed7b2..f3ed543bfe73 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -56,9 +56,6 @@ void wl1271_elp_work(struct work_struct *work)
56 goto out; 56 goto out;
57 57
58 wl12xx_for_each_wlvif(wl, wlvif) { 58 wl12xx_for_each_wlvif(wl, wlvif) {
59 if (wlvif->bss_type == BSS_TYPE_AP_BSS)
60 goto out;
61
62 if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) && 59 if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) &&
63 test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) 60 test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
64 goto out; 61 goto out;
@@ -95,9 +92,6 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
95 return; 92 return;
96 93
97 wl12xx_for_each_wlvif(wl, wlvif) { 94 wl12xx_for_each_wlvif(wl, wlvif) {
98 if (wlvif->bss_type == BSS_TYPE_AP_BSS)
99 return;
100
101 if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) && 95 if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) &&
102 test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) 96 test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
103 return; 97 return;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 7860a4e1d791..c8fe2ae272ac 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -118,6 +118,7 @@ struct wlcore_ops {
118 struct wl1271_link *lnk); 118 struct wl1271_link *lnk);
119 int (*interrupt_notify)(struct wl1271 *wl, bool action); 119 int (*interrupt_notify)(struct wl1271 *wl, bool action);
120 int (*rx_ba_filter)(struct wl1271 *wl, bool action); 120 int (*rx_ba_filter)(struct wl1271 *wl, bool action);
121 int (*ap_sleep)(struct wl1271 *wl);
121 int (*smart_config_start)(struct wl1271 *wl, u32 group_bitmap); 122 int (*smart_config_start)(struct wl1271 *wl, u32 group_bitmap);
122 int (*smart_config_stop)(struct wl1271 *wl); 123 int (*smart_config_stop)(struct wl1271 *wl);
123 int (*smart_config_set_group_key)(struct wl1271 *wl, u16 group_id, 124 int (*smart_config_set_group_key)(struct wl1271 *wl, u16 group_id,