diff mbox

ath10k: add recalc RTS/CTS protection method

Message ID 1393571908-23734-1-git-send-email-marek.kwaczynski@tieto.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Bartosz Markowski Feb. 28, 2014, 7:18 a.m. UTC
From: Marek Kwaczynski <marek.kwaczynski@tieto.com>

Add recalculation of RTS/CTS protection when one or more legacy
stations are connected to ath10k. In this case enable RTS/CTS
protection and set sw retry profile are needed in the FW.
Without this change legacy station is starved and has very low
throughput.

Signed-off-by: Marek Kwaczynski <marek.kwaczynski@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h |    3 ++
 drivers/net/wireless/ath/ath10k/mac.c  |   57 +++++++++++++++++++++++++-------
 drivers/net/wireless/ath/ath10k/wmi.h  |   13 ++++++++
 3 files changed, 61 insertions(+), 12 deletions(-)

Comments

Ben Greear Feb. 28, 2014, 5:46 p.m. UTC | #1
On 02/27/2014 11:18 PM, bartosz.markowski@tieto.com wrote:
> From: Marek Kwaczynski <marek.kwaczynski@tieto.com>
> 
> Add recalculation of RTS/CTS protection when one or more legacy
> stations are connected to ath10k. In this case enable RTS/CTS
> protection and set sw retry profile are needed in the FW.
> Without this change legacy station is starved and has very low
> throughput.

> -			ath10k_warn("Failed to set CTS prot for VDEV: %d\n",
> -				    arvif->vdev_id);
> +			ath10k_warn("failed to recalc RTS/CTS prot %d\n",
> +				    ret);

Did you remove the vdev ID from the logging message on purpose?

I find having vdev ID in logging messages helps, especially when
trying to compare firmware logs with the driver logs...

Thanks,
Ben
Bartosz Markowski March 3, 2014, 7:35 a.m. UTC | #2
On 28 February 2014 18:46, Ben Greear <greearb@candelatech.com> wrote:
> On 02/27/2014 11:18 PM, bartosz.markowski@tieto.com wrote:
>> From: Marek Kwaczynski <marek.kwaczynski@tieto.com>
>>
>> Add recalculation of RTS/CTS protection when one or more legacy
>> stations are connected to ath10k. In this case enable RTS/CTS
>> protection and set sw retry profile are needed in the FW.
>> Without this change legacy station is starved and has very low
>> throughput.
>
>> -                     ath10k_warn("Failed to set CTS prot for VDEV: %d\n",
>> -                                 arvif->vdev_id);
>> +                     ath10k_warn("failed to recalc RTS/CTS prot %d\n",
>> +                                 ret);
>
> Did you remove the vdev ID from the logging message on purpose?
>
> I find having vdev ID in logging messages helps, especially when
> trying to compare firmware logs with the driver logs...

Not on purpose. Thanks for pointing it out.
Kalle, please ignore this patch, there'll be v2.
diff mbox

Patch

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index d1c5e7a..c0e4fae 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -289,6 +289,9 @@  struct ath10k_vif {
 	u8 fixed_rate;
 	u8 fixed_nss;
 	u8 force_sgi;
+
+	bool use_cts_prot;
+	int num_legacy_stations;
 };
 
 struct ath10k_vif_iter {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 239357f..96b0f59 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -723,6 +723,26 @@  static int ath10k_monitor_destroy(struct ath10k *ar)
 	return ret;
 }
 
+static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
+{
+	struct ath10k *ar = arvif->ar;
+	u32 vdev_param, rts_cts = 0;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	vdev_param = ar->wmi.vdev_param->enable_rtscts;
+
+	if (arvif->use_cts_prot || arvif->num_legacy_stations > 0)
+		rts_cts |= SM(WMI_RTSCTS_ENABLED, WMI_RTSCTS_SET);
+
+	if (arvif->num_legacy_stations > 0)
+		rts_cts |= SM(WMI_RTSCTS_ACROSS_SW_RETRIES,
+			      WMI_RTSCTS_PROFILE);
+
+	return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+					 rts_cts);
+}
+
 static int ath10k_start_cac(struct ath10k *ar)
 {
 	int ret;
@@ -1532,6 +1552,16 @@  static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
 		return ret;
 	}
 
+	if (!sta->wme) {
+		arvif->num_legacy_stations++;
+		ret = ath10k_recalc_rtscts_prot(arvif);
+		if (ret) {
+			ath10k_warn("Failed to recalculate RTS/CTS: %d\n",
+				    ret);
+			return ret;
+		}
+	}
+
 	ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
 	if (ret) {
 		ath10k_warn("could not install peer wep keys (%d)\n", ret);
@@ -1555,6 +1585,16 @@  static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
 
 	lockdep_assert_held(&ar->conf_mutex);
 
+	if (!sta->wme) {
+		arvif->num_legacy_stations--;
+		ret = ath10k_recalc_rtscts_prot(arvif);
+		if (ret) {
+			ath10k_warn("failed to recalc RTS/CTS %d\n",
+				    ret);
+			return ret;
+		}
+	}
+
 	ret = ath10k_clear_peer_keys(arvif, sta->addr);
 	if (ret) {
 		ath10k_warn("could not clear all peer wep keys (%d)\n", ret);
@@ -2838,21 +2878,14 @@  static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
 		ath10k_control_beaconing(arvif, info);
 
 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		u32 cts_prot;
-		if (info->use_cts_prot)
-			cts_prot = 1;
-		else
-			cts_prot = 0;
-
+		arvif->use_cts_prot = info->use_cts_prot;
 		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n",
-			   arvif->vdev_id, cts_prot);
+			   arvif->vdev_id, info->use_cts_prot);
 
-		vdev_param = ar->wmi.vdev_param->enable_rtscts;
-		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-						cts_prot);
+		ret = ath10k_recalc_rtscts_prot(arvif);
 		if (ret)
-			ath10k_warn("Failed to set CTS prot for VDEV: %d\n",
-				    arvif->vdev_id);
+			ath10k_warn("failed to recalc RTS/CTS prot %d\n",
+				    ret);
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4fcc96a..e78a7ad 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2210,6 +2210,19 @@  enum ath10k_protmode {
 	ATH10K_PROT_RTSCTS   = 2,    /* RTS-CTS */
 };
 
+enum wmi_rtscts_profile {
+	WMI_RTSCTS_FOR_NO_RATESERIES = 0,
+	WMI_RTSCTS_FOR_SECOND_RATESERIES,
+	WMI_RTSCTS_ACROSS_SW_RETRIES
+};
+
+#define WMI_RTSCTS_ENABLED		1
+#define WMI_RTSCTS_SET_MASK		0x0f
+#define WMI_RTSCTS_SET_LSB		0
+
+#define WMI_RTSCTS_PROFILE_MASK		0xf0
+#define WMI_RTSCTS_PROFILE_LSB		4
+
 enum wmi_beacon_gen_mode {
 	WMI_BEACON_STAGGERED_MODE = 0,
 	WMI_BEACON_BURST_MODE = 1