diff mbox series

[RFC/RFT,4/4] mt76x02: set protection according to ht capabilities

Message ID 1541688430-31855-5-git-send-email-sgruszka@redhat.com (mailing list archive)
State RFC
Delegated to: Kalle Valo
Headers show
Series restore some old mt76x0u behaviour | expand

Commit Message

Stanislaw Gruszka Nov. 8, 2018, 2:47 p.m. UTC
Use information about protection that mac80211 provide to us.
Used protection should be part of ht capabilites that either
remote AP provde to us in STA mode or is set in hostapd.conf
in ht_capab option.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x02_mac.c  | 58 +++++++++++++++++++++++
 drivers/net/wireless/mediatek/mt76/mt76x02_mac.h  |  2 +
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c |  4 ++
 3 files changed, 64 insertions(+)

Comments

Lorenzo Bianconi Nov. 9, 2018, 9:29 a.m. UTC | #1
> Use information about protection that mac80211 provide to us.
> Used protection should be part of ht capabilites that either
> remote AP provde to us in STA mode or is set in hostapd.conf
> in ht_capab option.
> 
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
>  drivers/net/wireless/mediatek/mt76/mt76x02_mac.c  | 58 +++++++++++++++++++++++
>  drivers/net/wireless/mediatek/mt76/mt76x02_mac.h  |  2 +
>  drivers/net/wireless/mediatek/mt76/mt76x02_util.c |  4 ++
>  3 files changed, 64 insertions(+)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
> index 567a7ab47fab..6096efc4119b 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
> @@ -753,6 +753,64 @@ void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val)
>  		 MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
>  }
>  
> +void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
> +				   int ht_mode)
> +{
> +	int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
> +	bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
> +	u32 prot[6];
> +	bool ht_rts[4] = {};
> +	int i;
> +
> +	for (i = 0; i < 6; i++) {

maybe better ARRAY_SIZE() here?

> +		prot[i] = mt76_rr(dev, MT_CCK_PROT_CFG + i * 4);
> +		if (i >= 2)
> +			prot[i] &= ~(MT_PROT_CFG_CTRL | MT_PROT_CFG_RATE);
> +	}
> +
> +	if (legacy_prot) {
> +		prot[1] &= ~MT_PROT_CFG_CTRL;
> +		prot[1] |= MT_PROT_CTRL_CTS2SELF;
> +
> +		prot[2] |= MT_PROT_RATE_CCK_11;
> +		prot[3] |= MT_PROT_RATE_CCK_11;
> +		prot[4] |= MT_PROT_RATE_CCK_11;
> +		prot[5] |= MT_PROT_RATE_CCK_11;
> +	} else {
> +		prot[2] |= MT_PROT_RATE_OFDM_24;
> +		prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
> +		prot[4] |= MT_PROT_RATE_OFDM_24;
> +		prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
> +	}
> +
> +	switch (mode) {
> +	case IEEE80211_HT_OP_MODE_PROTECTION_NONE:

I think you can cover it with 'default' case

> +		break;
> +
> +	case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
> +		ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
> +		break;
> +
> +	case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
> +		ht_rts[1] = ht_rts[3] = true;
> +		break;
> +
> +	case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
> +		ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
> +		break;

this code is duplicated of 'IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER'.
maybe better to have:

	case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
	case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
		ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
		break;

> +	}
> +
> +	if (non_gf)
> +		ht_rts[2] = ht_rts[3] = true;
> +
> +	for (i = 0; i < 4; i++)

ARRAY_SIZE() here?

> +		if (ht_rts[i])
> +			prot[i + 2] |= MT_PROT_CTRL_RTS_CTS;
> +
> +	for (i = 0; i < 6; i++)

ARRAY_SIZE() here?

> +		mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
> +}
> +
>  void mt76x02_update_channel(struct mt76_dev *mdev)
>  {
>  	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
> index 34da8c600db8..9035397ae081 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
> @@ -197,6 +197,8 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
>  			    struct mt76x02_tx_status *stat, u8 *update);
>  int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
>  			   void *rxi);
> +void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
> +				   int ht_mode);
>  void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val);
>  void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr);
>  void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
> index fda67b0923a6..51db4d3dcc13 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
> @@ -682,6 +682,10 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
>  		tasklet_enable(&dev->pre_tbtt_tasklet);
>  	}
>  
> +	if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
> +		mt76x02_mac_set_tx_protection(dev, info->use_cts_prot,
> +					      info->ht_operation_mode);
> +
>  	if (changed & BSS_CHANGED_BASIC_RATES &&
>  	    vif->type == NL80211_IFTYPE_STATION) {
>  		mt76_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates);
> -- 
> 1.9.3
>
diff mbox series

Patch

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 567a7ab47fab..6096efc4119b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -753,6 +753,64 @@  void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val)
 		 MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
 }
 
+void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
+				   int ht_mode)
+{
+	int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+	bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+	u32 prot[6];
+	bool ht_rts[4] = {};
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		prot[i] = mt76_rr(dev, MT_CCK_PROT_CFG + i * 4);
+		if (i >= 2)
+			prot[i] &= ~(MT_PROT_CFG_CTRL | MT_PROT_CFG_RATE);
+	}
+
+	if (legacy_prot) {
+		prot[1] &= ~MT_PROT_CFG_CTRL;
+		prot[1] |= MT_PROT_CTRL_CTS2SELF;
+
+		prot[2] |= MT_PROT_RATE_CCK_11;
+		prot[3] |= MT_PROT_RATE_CCK_11;
+		prot[4] |= MT_PROT_RATE_CCK_11;
+		prot[5] |= MT_PROT_RATE_CCK_11;
+	} else {
+		prot[2] |= MT_PROT_RATE_OFDM_24;
+		prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
+		prot[4] |= MT_PROT_RATE_OFDM_24;
+		prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
+	}
+
+	switch (mode) {
+	case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+		break;
+
+	case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+		ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
+		break;
+
+	case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+		ht_rts[1] = ht_rts[3] = true;
+		break;
+
+	case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+		ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
+		break;
+	}
+
+	if (non_gf)
+		ht_rts[2] = ht_rts[3] = true;
+
+	for (i = 0; i < 4; i++)
+		if (ht_rts[i])
+			prot[i + 2] |= MT_PROT_CTRL_RTS_CTS;
+
+	for (i = 0; i < 6; i++)
+		mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
+}
+
 void mt76x02_update_channel(struct mt76_dev *mdev)
 {
 	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
index 34da8c600db8..9035397ae081 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
@@ -197,6 +197,8 @@  void mt76x02_send_tx_status(struct mt76x02_dev *dev,
 			    struct mt76x02_tx_status *stat, u8 *update);
 int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
 			   void *rxi);
+void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
+				   int ht_mode);
 void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val);
 void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr);
 void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index fda67b0923a6..51db4d3dcc13 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -682,6 +682,10 @@  void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
 		tasklet_enable(&dev->pre_tbtt_tasklet);
 	}
 
+	if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
+		mt76x02_mac_set_tx_protection(dev, info->use_cts_prot,
+					      info->ht_operation_mode);
+
 	if (changed & BSS_CHANGED_BASIC_RATES &&
 	    vif->type == NL80211_IFTYPE_STATION) {
 		mt76_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates);