2014-12-10 12:44:19

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 0/5] ath10k: a bunch of STA-related fixes


Michal Kazior (5):
ath10k: improve 11b coex
ath10k: fix STA u-APSD
ath10k: prevent invalid ps timeout config
ath10k: enable per-vif sta powersave
ath10k: advertise p2p dev support

drivers/net/wireless/ath/ath10k/core.c | 6 ---
drivers/net/wireless/ath/ath10k/mac.c | 89 ++++++++++++++++++++++++++++------
2 files changed, 74 insertions(+), 21 deletions(-)

--
1.8.5.3



2014-12-10 12:44:21

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 1/5] ath10k: improve 11b coex

Some firmware revisions need peer phymode to be
specified as MODE_11B when associating as station
to a 11b AP. Otherwise they can starve other
stations.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/mac.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fe61201..950322d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1416,6 +1416,12 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
}
}

+static bool ath10k_mac_sta_has_11g_rates(struct ieee80211_sta *sta)
+{
+ /* First 4 rates in ath10k_rates are CCK (11b) rates. */
+ return sta->supp_rates[IEEE80211_BAND_2GHZ] >> 4;
+}
+
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -1430,8 +1436,10 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
phymode = MODE_11NG_HT40;
else
phymode = MODE_11NG_HT20;
- } else {
+ } else if (ath10k_mac_sta_has_11g_rates(sta)) {
phymode = MODE_11G;
+ } else {
+ phymode = MODE_11B;
}

break;
@@ -4724,6 +4732,9 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
CHAN5G(165, 5825, 0),
};

+/* Note: Be careful if you re-order these. There is code which depends on this
+ * ordering.
+ */
static struct ieee80211_rate ath10k_rates[] = {
/* CCK */
RATETAB_ENT(10, 0x82, 0),
--
1.8.5.3


2014-12-10 12:44:25

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 5/5] ath10k: advertise p2p dev support

Firmware doesn't allow precise tx rate control so
P2P wasn't entirely spec compliant (it was using
CCK rates in some cases).

The only way to make sure firmware doesn't use CCK
rates is to have a vdev with P2P subtype used for
scanning and tx. This can be done via a special
dedicated P2P device interface support.

This also removes the ancient hack from ath10k in
favor of p2pdev.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/core.c | 6 ------
drivers/net/wireless/ath/ath10k/mac.c | 12 +++++++++---
2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 577a3d7..c83f1e7 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -32,17 +32,14 @@

unsigned int ath10k_debug_mask;
static bool uart_print;
-static unsigned int ath10k_p2p;
static bool skip_otp;

module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param(uart_print, bool, 0644);
-module_param_named(p2p, ath10k_p2p, uint, 0644);
module_param(skip_otp, bool, 0644);

MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
-MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");

static const struct ath10k_hw_params ath10k_hw_params_list[] = {
@@ -1290,10 +1287,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,

ar->ath_common.priv = ar;
ar->ath_common.hw = ar->hw;
-
- ar->p2p = !!ath10k_p2p;
ar->dev = dev;
-
ar->hif.ops = hif_ops;
ar->hif.bus = bus;

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e84397d..22d2046 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2935,10 +2935,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
arvif->vdev_id = bit;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;

- if (ar->p2p)
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
-
switch (vif->type) {
+ case NL80211_IFTYPE_P2P_DEVICE:
+ arvif->vdev_type = WMI_VDEV_TYPE_STA;
+ arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
+ break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
@@ -4830,6 +4831,10 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
.types = BIT(NL80211_IFTYPE_P2P_GO)
},
{
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+ },
+ {
.max = 7,
.types = BIT(NL80211_IFTYPE_AP)
},
@@ -5049,6 +5054,7 @@ int ath10k_mac_register(struct ath10k *ar)

if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
ar->hw->wiphy->interface_modes |=
+ BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);

--
1.8.5.3


2014-12-12 11:54:33

by Michal Kazior

[permalink] [raw]
Subject: [PATCH v2 3/5] ath10k: prevent invalid ps timeout config

Setting 0 ps timeout to firmware yields very poor
latency and traffic issues. This is the case when
multi-vif is active.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/mac.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 13c2bad..2804952 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1105,10 +1105,12 @@ static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
+ struct ieee80211_vif *vif = arvif->vif;
struct ieee80211_conf *conf = &ar->hw->conf;
enum wmi_sta_powersave_param param;
enum wmi_sta_ps_mode psmode;
int ret;
+ int ps_timeout;

lockdep_assert_held(&arvif->ar->conf_mutex);

@@ -1119,8 +1121,15 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;

+ ps_timeout = conf->dynamic_ps_timeout;
+ if (ps_timeout == 0) {
+ /* Firmware doesn't like 0 */
+ ps_timeout = ieee80211_tu_to_usec(
+ vif->bss_conf.beacon_int) / 1000;
+ }
+
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
- conf->dynamic_ps_timeout);
+ ps_timeout);
if (ret) {
ath10k_warn(ar, "failed to set inactivity time for vdev %d: %i\n",
arvif->vdev_id, ret);
--
1.8.5.3


2014-12-16 07:27:52

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 0/5] ath10k: a bunch of STA-related fixes

Michal Kazior <[email protected]> writes:

> Michal Kazior (5):
> ath10k: improve 11b coex
> ath10k: fix STA u-APSD
> ath10k: prevent invalid ps timeout config
> ath10k: enable per-vif sta powersave
> ath10k: advertise p2p dev support

Thanks, all five patches applied.

--
Kalle Valo

2014-12-12 11:54:32

by Michal Kazior

[permalink] [raw]
Subject: [PATCH v2 1/5] ath10k: improve 11b coex

Some firmware revisions need peer phymode to be
specified as MODE_11B when associating as station
to a 11b AP. Otherwise they can starve other
stations.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/mac.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fe61201..950322d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1416,6 +1416,12 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
}
}

+static bool ath10k_mac_sta_has_11g_rates(struct ieee80211_sta *sta)
+{
+ /* First 4 rates in ath10k_rates are CCK (11b) rates. */
+ return sta->supp_rates[IEEE80211_BAND_2GHZ] >> 4;
+}
+
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -1430,8 +1436,10 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
phymode = MODE_11NG_HT40;
else
phymode = MODE_11NG_HT20;
- } else {
+ } else if (ath10k_mac_sta_has_11g_rates(sta)) {
phymode = MODE_11G;
+ } else {
+ phymode = MODE_11B;
}

break;
@@ -4724,6 +4732,9 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
CHAN5G(165, 5825, 0),
};

+/* Note: Be careful if you re-order these. There is code which depends on this
+ * ordering.
+ */
static struct ieee80211_rate ath10k_rates[] = {
/* CCK */
RATETAB_ENT(10, 0x82, 0),
--
1.8.5.3


2014-12-12 11:54:35

by Michal Kazior

[permalink] [raw]
Subject: [PATCH v2 4/5] ath10k: enable per-vif sta powersave

Per-vif bss_conf.ps should be used to configure
powersave.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/mac.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 2804952..19ddbc6 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1099,9 +1099,6 @@ static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
return 0;
}

-/*
- * Review this when mac80211 gains per-interface powersave support.
- */
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
@@ -1117,7 +1114,7 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
if (arvif->vif->type != NL80211_IFTYPE_STATION)
return 0;

- if (conf->flags & IEEE80211_CONF_PS) {
+ if (vif->bss_conf.ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;

@@ -3378,6 +3375,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
}

+ if (changed & BSS_CHANGED_PS) {
+ ret = ath10k_mac_vif_setup_ps(arvif);
+ if (ret)
+ ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ }
+
mutex_unlock(&ar->conf_mutex);
}

--
1.8.5.3


2014-12-12 11:54:32

by Michal Kazior

[permalink] [raw]
Subject: [PATCH v2 2/5] ath10k: fix STA u-APSD

To comply with WMM-PS the device shouldn't wake up
with a NullFunc frame pair when tx-ing. Instead PM
bit on each tx frame should be used.

To make this work correctly firmware needs to be
told to use a different STA PS wake threshold when
u-APSD is enabled.

Signed-off-by: Michal Kazior <[email protected]>
---

Notes:
v2:
* fix Rx performance
* fix error handling (use goto instead of return)

drivers/net/wireless/ath/ath10k/mac.c | 79 ++++++++++++++++++++++++++++++-----
drivers/net/wireless/ath/ath10k/wmi.h | 7 ++++
2 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 950322d..13c2bad 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1048,6 +1048,57 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
arvif->vdev_id, ret);
}

+static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
+{
+ struct ath10k *ar = arvif->ar;
+ u32 param;
+ u32 value;
+ int ret;
+
+ lockdep_assert_held(&arvif->ar->conf_mutex);
+
+ if (arvif->u.sta.uapsd)
+ value = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
+ else
+ value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
+
+ param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
+ ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, value);
+ if (ret) {
+ ath10k_warn(ar, "failed to submit ps wake threshold %u on vdev %i: %d\n",
+ value, arvif->vdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
+{
+ struct ath10k *ar = arvif->ar;
+ u32 param;
+ u32 value;
+ int ret;
+
+ lockdep_assert_held(&arvif->ar->conf_mutex);
+
+ if (arvif->u.sta.uapsd)
+ value = WMI_STA_PS_PSPOLL_COUNT_UAPSD;
+ else
+ value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
+
+ param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
+ ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
+ param, value);
+ if (ret) {
+ ath10k_warn(ar, "failed to submit ps poll count %u on vdev %i: %d\n",
+ value, arvif->vdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* Review this when mac80211 gains per-interface powersave support.
*/
@@ -3036,22 +3087,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
goto err_peer_delete;
}

- param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
- value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
- ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
- param, value);
+ ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
if (ret) {
- ath10k_warn(ar, "failed to set vdev %i TX wake thresh: %d\n",
+ ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
arvif->vdev_id, ret);
goto err_peer_delete;
}

- param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
- value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
- ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
- param, value);
+ ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
if (ret) {
- ath10k_warn(ar, "failed to set vdev %i PSPOLL count: %d\n",
+ ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
arvif->vdev_id, ret);
goto err_peer_delete;
}
@@ -3818,6 +3863,20 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
if (ret)
ath10k_warn(ar, "failed to set rx wake param: %d\n", ret);

+ ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
+ if (ret) {
+ ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
+ if (ret) {
+ ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
exit:
return ret;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 97f902f..ff2d076 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4015,6 +4015,13 @@ enum wmi_sta_ps_param_pspoll_count {
* Values greater than 0 indicate the maximum numer of PS-Poll frames
* FW will send before waking up.
*/
+
+ /* When u-APSD is enabled the firmware will be very reluctant to exit
+ * STA PS. This could result in very poor Rx performance with STA doing
+ * PS-Poll for each and every buffered frame. This value is a bit
+ * arbitrary.
+ */
+ WMI_STA_PS_PSPOLL_COUNT_UAPSD = 3,
};

/*
--
1.8.5.3


2014-12-12 11:54:35

by Michal Kazior

[permalink] [raw]
Subject: [PATCH v2 5/5] ath10k: advertise p2p dev support

Firmware doesn't allow precise tx rate control so
P2P wasn't entirely spec compliant (it was using
CCK rates in some cases).

The only way to make sure firmware doesn't use CCK
rates is to have a vdev with P2P subtype used for
scanning and tx. This can be done via a special
dedicated P2P device interface support.

This also removes the ancient hack from ath10k in
favor of p2pdev.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/core.c | 6 ------
drivers/net/wireless/ath/ath10k/mac.c | 12 +++++++++---
2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 577a3d7..c83f1e7 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -32,17 +32,14 @@

unsigned int ath10k_debug_mask;
static bool uart_print;
-static unsigned int ath10k_p2p;
static bool skip_otp;

module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param(uart_print, bool, 0644);
-module_param_named(p2p, ath10k_p2p, uint, 0644);
module_param(skip_otp, bool, 0644);

MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
-MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");

static const struct ath10k_hw_params ath10k_hw_params_list[] = {
@@ -1290,10 +1287,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,

ar->ath_common.priv = ar;
ar->ath_common.hw = ar->hw;
-
- ar->p2p = !!ath10k_p2p;
ar->dev = dev;
-
ar->hif.ops = hif_ops;
ar->hif.bus = bus;

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 19ddbc6..42f6a4d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2961,10 +2961,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
arvif->vdev_id = bit;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;

- if (ar->p2p)
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
-
switch (vif->type) {
+ case NL80211_IFTYPE_P2P_DEVICE:
+ arvif->vdev_type = WMI_VDEV_TYPE_STA;
+ arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
+ break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
@@ -4860,6 +4861,10 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
.types = BIT(NL80211_IFTYPE_P2P_GO)
},
{
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+ },
+ {
.max = 7,
.types = BIT(NL80211_IFTYPE_AP)
},
@@ -5079,6 +5084,7 @@ int ath10k_mac_register(struct ath10k *ar)

if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
ar->hw->wiphy->interface_modes |=
+ BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);

--
1.8.5.3


2014-12-10 12:44:23

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 3/5] ath10k: prevent invalid ps timeout config

Setting 0 ps timeout to firmware yields very poor
latency and traffic issues. This is the case when
multi-vif is active.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/mac.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 969d187..d41e3d5 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1079,10 +1079,12 @@ static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
+ struct ieee80211_vif *vif = arvif->vif;
struct ieee80211_conf *conf = &ar->hw->conf;
enum wmi_sta_powersave_param param;
enum wmi_sta_ps_mode psmode;
int ret;
+ int ps_timeout;

lockdep_assert_held(&arvif->ar->conf_mutex);

@@ -1093,8 +1095,15 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;

+ ps_timeout = conf->dynamic_ps_timeout;
+ if (ps_timeout == 0) {
+ /* Firmware doesn't like 0 */
+ ps_timeout = ieee80211_tu_to_usec(
+ vif->bss_conf.beacon_int) / 1000;
+ }
+
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
- conf->dynamic_ps_timeout);
+ ps_timeout);
if (ret) {
ath10k_warn(ar, "failed to set inactivity time for vdev %d: %i\n",
arvif->vdev_id, ret);
--
1.8.5.3


2014-12-10 12:44:22

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 2/5] ath10k: fix STA u-APSD

To comply with WMM-PS the device shouldn't wake up
with a NullFunc frame pair when tx-ing. Instead PM
bit on each tx frame should be used.

To make this work correctly firmware needs to be
told to use a different STA PS wake threshold when
u-APSD is enabled.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/mac.c | 41 ++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 950322d..969d187 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1048,6 +1048,31 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
arvif->vdev_id, ret);
}

+static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
+{
+ struct ath10k *ar = arvif->ar;
+ u32 param;
+ u32 value;
+ int ret;
+
+ lockdep_assert_held(&arvif->ar->conf_mutex);
+
+ if (arvif->u.sta.uapsd)
+ value = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
+ else
+ value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
+
+ param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
+ ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, value);
+ if (ret) {
+ ath10k_warn(ar, "failed to submit ps wake threshold %u on vdev %i: %d\n",
+ value, arvif->vdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* Review this when mac80211 gains per-interface powersave support.
*/
@@ -3036,14 +3061,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
goto err_peer_delete;
}

- param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
- value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
- ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
- param, value);
+ ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
if (ret) {
- ath10k_warn(ar, "failed to set vdev %i TX wake thresh: %d\n",
+ ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
arvif->vdev_id, ret);
- goto err_peer_delete;
+ return ret;
}

param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
@@ -3818,6 +3840,13 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
if (ret)
ath10k_warn(ar, "failed to set rx wake param: %d\n", ret);

+ ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
+ if (ret) {
+ ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
exit:
return ret;
}
--
1.8.5.3


2014-12-12 11:54:31

by Michal Kazior

[permalink] [raw]
Subject: [PATCH v2 0/5] ath10k: a bunch of STA-related fixes


Michal Kazior (5):
ath10k: improve 11b coex
ath10k: fix STA u-APSD
ath10k: prevent invalid ps timeout config
ath10k: enable per-vif sta powersave
ath10k: advertise p2p dev support

drivers/net/wireless/ath/ath10k/core.c | 6 --
drivers/net/wireless/ath/ath10k/mac.c | 127 ++++++++++++++++++++++++++++-----
drivers/net/wireless/ath/ath10k/wmi.h | 7 ++
3 files changed, 115 insertions(+), 25 deletions(-)

--
1.8.5.3


2014-12-11 09:56:46

by Michal Kazior

[permalink] [raw]
Subject: Re: [PATCH 2/5] ath10k: fix STA u-APSD

On 10 December 2014 at 13:31, Michal Kazior <[email protected]> wrote:
[...]
> @@ -3036,14 +3061,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
> goto err_peer_delete;
> }
>
> - param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
> - value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
> - ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
> - param, value);
> + ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
> if (ret) {
> - ath10k_warn(ar, "failed to set vdev %i TX wake thresh: %d\n",
> + ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
> arvif->vdev_id, ret);
> - goto err_peer_delete;
> + return ret;

Oops. This is wrong. I should keep the goto.

There are also some Rx performance issues related to excessive PS-Poll usage.

I'll re-spin later.


MichaƂ

2014-12-10 12:44:24

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 4/5] ath10k: enable per-vif sta powersave

Per-vif bss_conf.ps should be used to configure
powersave.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/mac.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index d41e3d5..e84397d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1073,9 +1073,6 @@ static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
return 0;
}

-/*
- * Review this when mac80211 gains per-interface powersave support.
- */
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
@@ -1091,7 +1088,7 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
if (arvif->vif->type != NL80211_IFTYPE_STATION)
return 0;

- if (conf->flags & IEEE80211_CONF_PS) {
+ if (vif->bss_conf.ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;

@@ -3355,6 +3352,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
}

+ if (changed & BSS_CHANGED_PS) {
+ ret = ath10k_mac_vif_setup_ps(arvif);
+ if (ret)
+ ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ }
+
mutex_unlock(&ar->conf_mutex);
}

--
1.8.5.3