2012-02-20 13:38:27

by Raja Mani

[permalink] [raw]
Subject: [PATCH 1/2] ath6kl: Maintain the listen interval per VIF specific

From: Raja Mani <[email protected]>

Firmware has the option to support the listen interval
per vif specific. Fix this.

Listen interval can be set by the TUs or by the number
of beacons. Current code enables the user to configure
the listen interval in the unit of 'number of beacons'
using debugfs entry "listen_interval". Going forward,
we need to alter the listen interval in the unit of TUs
to get good power numbers while going to WOW suspend/resume.

Allowing the user to change the listen interval in
the unit of "number of beacons" in debugfs and changing
listen interval in wow suspend/resume in the unit of
time (TUs) would lead us to confuse.

This patch make sures the listen interval is changed only
in the unit of time (TUs).

Signed-off-by: Raja Mani <[email protected]>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 1 +
drivers/net/wireless/ath/ath6kl/core.c | 2 --
drivers/net/wireless/ath/ath6kl/core.h | 6 +++---
drivers/net/wireless/ath/ath6kl/debug.c | 15 ++++++++++-----
drivers/net/wireless/ath/ath6kl/main.c | 6 ++----
5 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 003f320..6e02a2b 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2943,6 +2943,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
vif->wdev.iftype = type;
vif->fw_vif_idx = fw_vif_idx;
vif->nw_type = vif->next_mode = nw_type;
+ vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;

memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
if (fw_vif_idx != 0)
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index 37c92a1..0db5c73 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -264,9 +264,7 @@ struct ath6kl *ath6kl_core_create(struct device *dev)
clear_bit(SKIP_SCAN, &ar->flag);
clear_bit(DESTROY_IN_PROGRESS, &ar->flag);

- ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL;
ar->tx_pwr = 0;
-
ar->intra_bss = 1;
ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;

diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 808253e..78f53c0 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -60,8 +60,6 @@
#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC)

#define DISCON_TIMER_INTVAL 10000 /* in msec */
-#define A_DEFAULT_LISTEN_INTERVAL 1 /* beacon intervals */
-#define A_MAX_WOW_LISTEN_INTERVAL 1000

/* includes also the null byte */
#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL"
@@ -184,6 +182,8 @@ struct ath6kl_fw_ie {

#define MBOX_YIELD_LIMIT 99

+#define ATH6KL_DEFAULT_LISTEN_INTVAL 100 /* in TUs */
+
/* configuration lags */
/*
* ATH6KL_CONF_IGNORE_ERP_BARKER: Ignore the barker premable in
@@ -495,6 +495,7 @@ struct ath6kl_vif {
bool probe_req_report;
u16 next_chan;
u16 assoc_bss_beacon_int;
+ u16 listen_intvl_t;
u8 assoc_bss_dtim_period;
struct net_device_stats net_stats;
struct target_stats target_stats;
@@ -554,7 +555,6 @@ struct ath6kl {
u8 avail_idx_map;
spinlock_t lock;
struct semaphore sem;
- u16 listen_intvl_b;
u8 lrssi_roam_threshold;
struct ath6kl_version version;
u32 target_type;
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 3d0713d..3092686 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -1628,12 +1628,12 @@ static ssize_t ath6kl_listen_int_write(struct file *file,
if (kstrtou16(buf, 0, &listen_interval))
return -EINVAL;

- if ((listen_interval < 1) || (listen_interval > 50))
+ if ((listen_interval < 15) || (listen_interval > 3000))
return -EINVAL;

- ar->listen_intvl_b = listen_interval;
- ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0,
- ar->listen_intvl_b);
+ vif->listen_intvl_t = listen_interval;
+ ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+ vif->listen_intvl_t, 0);

return count;
}
@@ -1643,10 +1643,15 @@ static ssize_t ath6kl_listen_int_read(struct file *file,
size_t count, loff_t *ppos)
{
struct ath6kl *ar = file->private_data;
+ struct ath6kl_vif *vif;
char buf[32];
int len;

- len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b);
+ vif = ath6kl_vif_first(ar);
+ if (!vif)
+ return -EIO;
+
+ len = scnprintf(buf, sizeof(buf), "%u\n", vif->listen_intvl_t);

return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index d463a18..23a8027 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -589,11 +589,9 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
memcpy(vif->bssid, bssid, sizeof(vif->bssid));
vif->bss_ch = channel;

- if ((vif->nw_type == INFRA_NETWORK)) {
- ar->listen_intvl_b = listen_int;
+ if ((vif->nw_type == INFRA_NETWORK))
ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
- 0, ar->listen_intvl_b);
- }
+ vif->listen_intvl_t, 0);

netif_wake_queue(vif->ndev);

--
1.7.1



2012-02-20 13:38:40

by Raja Mani

[permalink] [raw]
Subject: [PATCH 2/2] ath6kl: Set optimal listen intvl,bmiss,scan params while going to wow suspend

From: Raja Mani <[email protected]>

* In order to save the target power in WOW suspend state,
configure the best optimal values for the below parameters,
- listen interval.
- beacon miss interval.
- scan parameters.

Default values for above attributes are reverted in
wow resume operation.

* The default listen interval is set before the host issue
connect request.

* New function is added to configure beacon miss count.

Signed-off-by: Raja Mani <[email protected]>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 55 +++++++++++++++++++++++++++-
drivers/net/wireless/ath/ath6kl/core.h | 4 ++
drivers/net/wireless/ath/ath6kl/wmi.c | 20 ++++++++++
drivers/net/wireless/ath/ath6kl/wmi.h | 8 ++++
4 files changed, 86 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 6e02a2b..4bd7e78 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -569,6 +569,19 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif->grp_crypto_len, vif->ch_hint);

vif->reconnect_flag = 0;
+
+ if (vif->nw_type == INFRA_NETWORK) {
+ status = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+ max(vif->listen_intvl_t,
+ (u16)ATH6KL_MAX_WOW_LISTEN_INTVAL),
+ 0);
+ if (status) {
+ ath6kl_err("couldn't set listen intervel\n");
+ up(&ar->sem);
+ return status;
+ }
+ }
+
status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
vif->dot11_auth_mode, vif->auth_mode,
vif->prwise_crypto,
@@ -1905,7 +1918,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
struct ath6kl_vif *vif;
int ret, left;
u32 filter = 0;
- u16 i;
+ u16 i, bmiss_time;
u8 index = 0;
__be32 ips[MAX_IP_ADDRS];

@@ -1942,6 +1955,28 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
if (ret)
return ret;

+ if (vif->nw_type != AP_NETWORK) {
+ ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+ ATH6KL_MAX_WOW_LISTEN_INTVAL, 0);
+ if (ret)
+ return ret;
+
+ /* Set listen interval x 15 times as bmiss time */
+ bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTVAL * 15;
+ if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
+ bmiss_time = ATH6KL_MAX_BMISS_TIME;
+
+ ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
+ bmiss_time, 0);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
+ 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0);
+ if (ret)
+ return ret;
+ }
+
ar->state = ATH6KL_STATE_SUSPENDING;

/* Setup own IP addr for ARP agent. */
@@ -2033,6 +2068,23 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
return ret;
}

+ if (vif->nw_type != AP_NETWORK) {
+ ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+ vif->listen_intvl_t, 0);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
+ vif->bmiss_time_t, 0);
+ if (ret)
+ return ret;
+ }
+
ar->state = ATH6KL_STATE_ON;

/* Wake up netdev queue if it's stopped in ath6kl_data_tx() */
@@ -2944,6 +2996,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
vif->fw_vif_idx = fw_vif_idx;
vif->nw_type = vif->next_mode = nw_type;
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
+ vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;

memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
if (fw_vif_idx != 0)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 78f53c0..b7a1042 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -183,6 +183,9 @@ struct ath6kl_fw_ie {
#define MBOX_YIELD_LIMIT 99

#define ATH6KL_DEFAULT_LISTEN_INTVAL 100 /* in TUs */
+#define ATH6KL_DEFAULT_BMISS_TIME 1500
+#define ATH6KL_MAX_WOW_LISTEN_INTVAL 300 /* in TUs */
+#define ATH6KL_MAX_BMISS_TIME 5000

/* configuration lags */
/*
@@ -496,6 +499,7 @@ struct ath6kl_vif {
u16 next_chan;
u16 assoc_bss_beacon_int;
u16 listen_intvl_t;
+ u16 bmiss_time_t;
u8 assoc_bss_dtim_period;
struct net_device_stats net_stats;
struct target_stats target_stats;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index bbbe0a7..0fddf52 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2027,6 +2027,26 @@ int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
return ret;
}

+int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
+ u16 bmiss_time, u16 num_beacons)
+{
+ struct sk_buff *skb;
+ struct wmi_bmiss_time_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_bmiss_time_cmd *) skb->data;
+ cmd->bmiss_time = cpu_to_le16(bmiss_time);
+ cmd->num_beacons = cpu_to_le16(num_beacons);
+
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BMISS_TIME_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode)
{
struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index e7d031b..7b27660 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -998,6 +998,12 @@ struct wmi_listen_int_cmd {
__le16 num_beacons;
} __packed;

+/* WMI_SET_BMISS_TIME_CMDID */
+struct wmi_bmiss_time_cmd {
+ __le16 bmiss_time;
+ __le16 num_beacons;
+};
+
/* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode {
REC_POWER = 0x01,
@@ -2414,6 +2420,8 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
u16 listen_interval,
u16 listen_beacons);
+int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
+ u16 bmiss_time, u16 num_beacons);
int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode);
int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period,
u16 ps_poll_num, u16 dtim_policy,
--
1.7.1


2012-03-01 06:28:40

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/2] ath6kl: Maintain the listen interval per VIF specific

On 02/20/2012 03:38 PM, [email protected] wrote:
> From: Raja Mani <[email protected]>
>
> Firmware has the option to support the listen interval
> per vif specific. Fix this.
>
> Listen interval can be set by the TUs or by the number
> of beacons. Current code enables the user to configure
> the listen interval in the unit of 'number of beacons'
> using debugfs entry "listen_interval". Going forward,
> we need to alter the listen interval in the unit of TUs
> to get good power numbers while going to WOW suspend/resume.
>
> Allowing the user to change the listen interval in
> the unit of "number of beacons" in debugfs and changing
> listen interval in wow suspend/resume in the unit of
> time (TUs) would lead us to confuse.
>
> This patch make sures the listen interval is changed only
> in the unit of time (TUs).
>
> Signed-off-by: Raja Mani <[email protected]>

I think these two patches depend on your 'ath6kl: Check wow state before
sending control and data pkt'? At least I got conflicts and they seem to
point to that patch.

If that's the case, I'll put these two patches on hold until the other
patch is applied.

Kalle

2012-03-07 07:53:01

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/2] ath6kl: Maintain the listen interval per VIF specific

On 02/20/2012 03:38 PM, [email protected] wrote:
> From: Raja Mani <[email protected]>
>
> Firmware has the option to support the listen interval
> per vif specific. Fix this.
>
> Listen interval can be set by the TUs or by the number
> of beacons. Current code enables the user to configure
> the listen interval in the unit of 'number of beacons'
> using debugfs entry "listen_interval". Going forward,
> we need to alter the listen interval in the unit of TUs
> to get good power numbers while going to WOW suspend/resume.
>
> Allowing the user to change the listen interval in
> the unit of "number of beacons" in debugfs and changing
> listen interval in wow suspend/resume in the unit of
> time (TUs) would lead us to confuse.
>
> This patch make sures the listen interval is changed only
> in the unit of time (TUs).
>
> Signed-off-by: Raja Mani <[email protected]>

Thanks, both patches applied. For patch 2 I had to do cosmetic changes
because of the new indentation rules.

Kalle