Linux-Wireless Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 1/8] ath11k: add RX stats support for radiotap
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
@ 2019-11-25 16:36 ` Kalle Valo
  2019-11-27 15:47   ` Kalle Valo
  2019-11-25 16:36 ` [PATCH 2/8] ath11k: ignore event 0x6017 Kalle Valo
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: John Crispin <john@phrozen.org>

mac80211 expects the definition of what HE rate info is available inside a
struct prepended to the skb.

Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/dp_rx.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 9491a479fab5..c498c4920e11 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -2038,11 +2038,21 @@ static char *ath11k_print_get_tid(struct ieee80211_hdr *hdr, char *out,
 static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *napi,
 				      struct sk_buff *msdu)
 {
+	static const struct ieee80211_radiotap_he known = {
+		.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN),
+		.data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN),
+	};
 	struct ieee80211_rx_status *status;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
+	struct ieee80211_radiotap_he *he = NULL;
 	char tid[32];
 
 	status = IEEE80211_SKB_RXCB(msdu);
+	if (status->encoding == RX_ENC_HE) {
+		he = skb_push(msdu, sizeof(known));
+		memcpy(he, &known, sizeof(known));
+		status->flag |= RX_FLAG_RADIOTAP_HE;
+	}
 
 	ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
 		   "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/8] ath11k: ignore event 0x6017
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
  2019-11-25 16:36 ` [PATCH 1/8] ath11k: add RX stats support for radiotap Kalle Valo
@ 2019-11-25 16:36 ` Kalle Valo
  2019-11-25 16:36 ` [PATCH 3/8] ath11k: convert message from info to dbg Kalle Valo
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: John Crispin <john@phrozen.org>

Everytime a new peer gets associated, we see the following message in the log
- ath11k c000000.wifi1: Unknown eventid: 0x6017
Ignore this event for now. We probably need to handle the event properly when
we add OMI support.

Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/wmi.c |  1 +
 drivers/net/wireless/ath/ath11k/wmi.h | 13 ++++++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 3d1d4d3c3f20..3ec5dd47cdc8 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -5416,6 +5416,7 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
 	/* add Unsupported events here */
 	case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
 	case WMI_VDEV_DELETE_RESP_EVENTID:
+	case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
 		ath11k_dbg(ab, ATH11K_DBG_WMI,
 			   "ignoring unsupported event 0x%x\n", id);
 		break;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 00c51cc83d47..1110da29cfcd 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -288,7 +288,6 @@ enum wmi_tlv_cmd_id {
 	WMI_PEER_REORDER_QUEUE_REMOVE_CMDID,
 	WMI_PEER_SET_RX_BLOCKSIZE_CMDID,
 	WMI_PEER_ANTDIV_INFO_REQ_CMDID,
-	WMI_PEER_OPER_MODE_CHANGE_EVENTID,
 	WMI_BCN_TX_CMDID = WMI_TLV_CMD(WMI_GRP_MGMT),
 	WMI_PDEV_SEND_BCN_CMDID,
 	WMI_BCN_TMPL_CMDID,
@@ -586,6 +585,18 @@ enum wmi_tlv_event_id {
 	WMI_WDS_PEER_EVENTID,
 	WMI_PEER_STA_PS_STATECHG_EVENTID,
 	WMI_PEER_ANTDIV_INFO_EVENTID,
+	WMI_PEER_RESERVED0_EVENTID,
+	WMI_PEER_RESERVED1_EVENTID,
+	WMI_PEER_RESERVED2_EVENTID,
+	WMI_PEER_RESERVED3_EVENTID,
+	WMI_PEER_RESERVED4_EVENTID,
+	WMI_PEER_RESERVED5_EVENTID,
+	WMI_PEER_RESERVED6_EVENTID,
+	WMI_PEER_RESERVED7_EVENTID,
+	WMI_PEER_RESERVED8_EVENTID,
+	WMI_PEER_RESERVED9_EVENTID,
+	WMI_PEER_RESERVED10_EVENTID,
+	WMI_PEER_OPER_MODE_CHANGE_EVENTID,
 	WMI_MGMT_RX_EVENTID = WMI_TLV_CMD(WMI_GRP_MGMT),
 	WMI_HOST_SWBA_EVENTID,
 	WMI_TBTTOFFSET_UPDATE_EVENTID,
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/8] ath11k: convert message from info to dbg
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
  2019-11-25 16:36 ` [PATCH 1/8] ath11k: add RX stats support for radiotap Kalle Valo
  2019-11-25 16:36 ` [PATCH 2/8] ath11k: ignore event 0x6017 Kalle Valo
@ 2019-11-25 16:36 ` Kalle Valo
  2019-11-25 16:36 ` [PATCH 4/8] ath11k: fix missed bw conversion in tx completion Kalle Valo
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: John Crispin <john@phrozen.org>

We can regularly see the following message.
- "ath11k c000000.wifi1: failed to find the peer with peer_id 4"
This happens when the FW starts sending stats for the peer whilst the
peer is not fully associated. Convert this info message to a debug one.

Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/dp_rx.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index c498c4920e11..d5963509419b 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -2621,8 +2621,9 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 		peer = ath11k_peer_find_by_id(ab, ppdu_info.peer_id);
 
 		if (!peer || !peer->sta) {
-			ath11k_warn(ab, "failed to find the peer with peer_id %d\n",
-				    ppdu_info.peer_id);
+			ath11k_dbg(ab, ATH11K_DBG_DATA,
+				   "failed to find the peer with peer_id %d\n",
+				   ppdu_info.peer_id);
 			spin_unlock_bh(&ab->base_lock);
 			rcu_read_unlock();
 			dev_kfree_skb_any(skb);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/8] ath11k: fix missed bw conversion in tx completion
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
                   ` (2 preceding siblings ...)
  2019-11-25 16:36 ` [PATCH 3/8] ath11k: convert message from info to dbg Kalle Valo
@ 2019-11-25 16:36 ` Kalle Valo
  2019-11-25 16:36 ` [PATCH 5/8] ath11k: Remove dead code while handling amsdu packets Kalle Valo
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: Tamizh chelvam <tamizhr@codeaurora.org>

TX rate stats for the retried packets for a station comes through
tx completion events. Assigning hw reported bandwidth information
directly to station's txrate bandwidth will cause below warning.
Fix this warning by converting the hw reported bandwidth to
mac80211 base bandwidth.

[ 134.758190] PC is at cfg80211_calculate_bitrate+0x1bc/0x214 [cfg80211]
[ 134.765730] LR is at cfg80211_calculate_bitrate+0x1bc/0x214 [cfg80211]
[ 134.875014] [<ffffffbffca8d708>] cfg80211_calculate_bitrate+0x1bc/0x214 [cfg80211]
[ 134.877192] [<ffffffbffcaa9704>] nl80211_put_sta_rate+0x54/0xf24 [cfg80211]
[ 134.884829] [<ffffffbffcaa9d48>] nl80211_put_sta_rate+0x698/0xf24 [cfg80211]
[ 134.891687] [<ffffffbffcaaa490>] nl80211_put_sta_rate+0xde0/0xf24 [cfg80211]
[ 134.898975] [<ffffffc0004de748>] genl_lock_dumpit+0x30/0x4c
[ 134.905998] [<ffffffc0004dc264>] netlink_dump+0xf4/0x248
[ 134.911291] [<ffffffc0004dc910>] __netlink_dump_start+0xe0/0x174
[ 134.916850] [<ffffffc0004df114>] genl_family_rcv_msg+0x130/0x2c0

Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/debugfs_sta.c |  2 +-
 drivers/net/wireless/ath/ath11k/dp_rx.c       | 30 ++++-----------------------
 drivers/net/wireless/ath/ath11k/mac.c         | 22 ++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/mac.h         |  1 +
 4 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/debugfs_sta.c b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
index b392117eff3c..3c5f931e22a9 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
@@ -192,7 +192,7 @@ void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar,
 	}
 
 	arsta->txrate.nss = arsta->last_txrate.nss;
-	arsta->txrate.bw = ts->bw;
+	arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(ts->bw);
 
 	ath11k_accumulate_per_peer_tx_stats(arsta, peer_stats, rate_idx);
 	spin_unlock_bh(&ab->base_lock);
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index d5963509419b..0ff0ff81adeb 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -987,28 +987,6 @@ int ath11k_dp_htt_tlv_iter(struct ath11k_base *ab, const void *ptr, size_t len,
 	return 0;
 }
 
-static u8 ath11k_bw_to_mac80211_bw(u8 bw)
-{
-	u8 ret = 0;
-
-	switch (bw) {
-	case ATH11K_BW_20:
-		ret = RATE_INFO_BW_20;
-		break;
-	case ATH11K_BW_40:
-		ret = RATE_INFO_BW_40;
-		break;
-	case ATH11K_BW_80:
-		ret = RATE_INFO_BW_80;
-		break;
-	case ATH11K_BW_160:
-		ret = RATE_INFO_BW_160;
-		break;
-	}
-
-	return ret;
-}
-
 static u32 ath11k_bw_to_mac80211_bwflags(u8 bw)
 {
 	u32 bwflags = 0;
@@ -1157,7 +1135,7 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
 	}
 
 	arsta->txrate.nss = nss;
-	arsta->txrate.bw = ath11k_bw_to_mac80211_bw(bw);
+	arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw);
 	arsta->tx_info.status.rates[0].flags |= ath11k_bw_to_mac80211_bwflags(bw);
 
 	memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info));
@@ -1934,7 +1912,7 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,
 		rx_status->rate_idx = rate_mcs + (8 * (nss - 1));
 		if (sgi)
 			rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-		rx_status->bw = ath11k_bw_to_mac80211_bw(bw);
+		rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw);
 		break;
 	case RX_MSDU_START_PKT_TYPE_11AC:
 		rx_status->encoding = RX_ENC_VHT;
@@ -1948,7 +1926,7 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,
 		rx_status->nss = nss;
 		if (sgi)
 			rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-		rx_status->bw = ath11k_bw_to_mac80211_bw(bw);
+		rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw);
 		break;
 	case RX_MSDU_START_PKT_TYPE_11AX:
 		rx_status->rate_idx = rate_mcs;
@@ -1960,7 +1938,7 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,
 		}
 		rx_status->encoding = RX_ENC_HE;
 		rx_status->nss = nss;
-		rx_status->bw = ath11k_bw_to_mac80211_bw(bw);
+		rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw);
 		break;
 	}
 }
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index cb025a4a5785..939f5880bce6 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -156,6 +156,28 @@ static const u32 ath11k_smps_map[] = {
 	[WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,
 };
 
+u8 ath11k_mac_bw_to_mac80211_bw(u8 bw)
+{
+	u8 ret = 0;
+
+	switch (bw) {
+	case ATH11K_BW_20:
+		ret = RATE_INFO_BW_20;
+		break;
+	case ATH11K_BW_40:
+		ret = RATE_INFO_BW_40;
+		break;
+	case ATH11K_BW_80:
+		ret = RATE_INFO_BW_80;
+		break;
+	case ATH11K_BW_160:
+		ret = RATE_INFO_BW_160;
+		break;
+	}
+
+	return ret;
+}
+
 int ath11k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,
 					  u16 *rate)
 {
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index f84af1fc4952..8c37573ae5dc 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -142,4 +142,5 @@ struct ath11k *ath11k_mac_get_ar_vdev_stop_status(struct ath11k_base *ab,
 void ath11k_mac_drain_tx(struct ath11k *ar);
 void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
 int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
+u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
 #endif
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/8] ath11k: Remove dead code while handling amsdu packets
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
                   ` (3 preceding siblings ...)
  2019-11-25 16:36 ` [PATCH 4/8] ath11k: fix missed bw conversion in tx completion Kalle Valo
@ 2019-11-25 16:36 ` Kalle Valo
  2019-11-25 16:36 ` [PATCH 6/8] ath11k: add HE support Kalle Valo
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: Tamizh chelvam <tamizhr@codeaurora.org>

Remove unexecuted code while handling amsdu packets.
The same logic is done before calling ath11k_dp_rx_msdu_coalesce

Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/dp_rx.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 0ff0ff81adeb..7aade0314e61 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1349,12 +1349,6 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
 	int rem_len;
 	int buf_len;
 
-	if (!rxcb->is_continuation) {
-		skb_put(first, HAL_RX_DESC_SIZE + l3pad_bytes + msdu_len);
-		skb_pull(first, HAL_RX_DESC_SIZE + l3pad_bytes);
-		return 0;
-	}
-
 	if (WARN_ON_ONCE(msdu_len <= (DP_RX_BUFFER_SIZE -
 			 (HAL_RX_DESC_SIZE + l3pad_bytes)))) {
 		skb_put(first, HAL_RX_DESC_SIZE + l3pad_bytes + msdu_len);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 6/8] ath11k: add HE support
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
                   ` (4 preceding siblings ...)
  2019-11-25 16:36 ` [PATCH 5/8] ath11k: Remove dead code while handling amsdu packets Kalle Valo
@ 2019-11-25 16:36 ` Kalle Valo
  2019-11-25 16:36 ` [PATCH 7/8] ath11k: add TWT support Kalle Valo
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: John Crispin <john@phrozen.org>

Add basic HE support to the driver. The sband_iftype data is generated from
the capabilities read from the FW.

Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.h |   2 +
 drivers/net/wireless/ath/ath11k/mac.c  | 265 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath11k/reg.c  |   1 +
 drivers/net/wireless/ath/ath11k/wmi.c  |   6 +-
 drivers/net/wireless/ath/ath11k/wmi.h  |   6 +-
 5 files changed, 270 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 95447d1be104..065cb9dc880b 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -431,6 +431,8 @@ struct ath11k {
 
 	struct {
 		struct ieee80211_supported_band sbands[NUM_NL80211_BANDS];
+		struct ieee80211_sband_iftype_data
+			iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
 	} mac;
 	unsigned long dev_flags;
 	unsigned int filter_flags;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 939f5880bce6..79c22d86e0fe 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1140,7 +1140,86 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
 				   struct ieee80211_sta *sta,
 				   struct peer_assoc_params *arg)
 {
-	/* TODO: Implementation */
+	const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
+	u16 v;
+
+	if (!he_cap->has_he)
+		return;
+
+	arg->he_flag = true;
+
+	memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
+	       sizeof(arg->peer_he_cap_macinfo));
+	memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
+	       sizeof(arg->peer_he_cap_phyinfo));
+	memcpy(&arg->peer_he_ops, &vif->bss_conf.he_operation,
+	       sizeof(arg->peer_he_ops));
+
+	/* the top most byte is used to indicate BSS color info */
+	arg->peer_he_ops &= 0xffffff;
+
+	if (he_cap->he_cap_elem.phy_cap_info[6] &
+	    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
+		int bit = 7;
+		int nss, ru;
+
+		arg->peer_ppet.numss_m1 = he_cap->ppe_thres[0] &
+					  IEEE80211_PPE_THRES_NSS_MASK;
+		arg->peer_ppet.ru_bit_mask =
+			(he_cap->ppe_thres[0] &
+			 IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>
+			IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;
+
+		for (nss = 0; nss <= arg->peer_ppet.numss_m1; nss++) {
+			for (ru = 0; ru < 4; ru++) {
+				u32 val = 0;
+				int i;
+
+				if ((arg->peer_ppet.ru_bit_mask & BIT(ru)) == 0)
+					continue;
+				for (i = 0; i < 6; i++) {
+					val >>= 1;
+					val |= ((he_cap->ppe_thres[bit / 8] >>
+						 (bit % 8)) & 0x1) << 5;
+					bit++;
+				}
+				arg->peer_ppet.ppet16_ppet8_ru3_ru0[nss] |=
+								val << (ru * 6);
+			}
+		}
+	}
+
+	switch (sta->bandwidth) {
+	case IEEE80211_STA_RX_BW_160:
+		if (he_cap->he_cap_elem.phy_cap_info[0] &
+		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
+			v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
+			arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
+
+			v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
+			arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
+
+			arg->peer_he_mcs_count++;
+		}
+		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
+		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
+
+		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
+		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
+
+		arg->peer_he_mcs_count++;
+		/* fall through */
+
+	default:
+		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
+		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
+
+		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
+		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
+
+		arg->peer_he_mcs_count++;
+		break;
+	}
 }
 
 static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta,
@@ -1307,6 +1386,32 @@ static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar,
 	return MODE_UNKNOWN;
 }
 
+static enum wmi_phy_mode ath11k_mac_get_phymode_he(struct ath11k *ar,
+						   struct ieee80211_sta *sta)
+{
+	if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
+		if (sta->he_cap.he_cap_elem.phy_cap_info[0] &
+		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
+			return MODE_11AX_HE160;
+		else if (sta->he_cap.he_cap_elem.phy_cap_info[0] &
+		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
+			return MODE_11AX_HE80_80;
+		/* not sure if this is a valid case? */
+		return MODE_11AX_HE160;
+	}
+
+	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
+		return MODE_11AX_HE80;
+
+	if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
+		return MODE_11AX_HE40;
+
+	if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
+		return MODE_11AX_HE20;
+
+	return MODE_UNKNOWN;
+}
+
 static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
 					struct ieee80211_vif *vif,
 					struct ieee80211_sta *sta,
@@ -1328,7 +1433,14 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
 
 	switch (band) {
 	case NL80211_BAND_2GHZ:
-		if (sta->vht_cap.vht_supported &&
+		if (sta->he_cap.has_he) {
+			if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
+				phymode = MODE_11AX_HE80_2G;
+			else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
+				phymode = MODE_11AX_HE40_2G;
+			else
+				phymode = MODE_11AX_HE20_2G;
+		} else if (sta->vht_cap.vht_supported &&
 		    !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
 			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
 				phymode = MODE_11AC_VHT40;
@@ -1345,12 +1457,12 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
 		} else {
 			phymode = MODE_11B;
 		}
-		/* TODO: HE */
-
 		break;
 	case NL80211_BAND_5GHZ:
-		/* Check VHT first */
-		if (sta->vht_cap.vht_supported &&
+		/* Check HE first */
+		if (sta->he_cap.has_he) {
+			phymode = ath11k_mac_get_phymode_he(ar, sta);
+		} else if (sta->vht_cap.vht_supported &&
 		    !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
 			phymode = ath11k_mac_get_phymode_vht(ar, sta);
 		} else if (sta->ht_cap.ht_supported &&
@@ -1362,7 +1474,6 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
 		} else {
 			phymode = MODE_11A;
 		}
-		/* TODO: HE Phymode */
 		break;
 	default:
 		break;
@@ -3126,6 +3237,142 @@ static int ath11k_check_chain_mask(struct ath11k *ar, u32 ant, bool is_tx_ant)
 	return 0;
 }
 
+static void ath11k_gen_ppe_thresh(struct ath11k_ppe_threshold *fw_ppet,
+				  u8 *he_ppet)
+{
+	int nss, ru;
+	u8 bit = 7;
+
+	he_ppet[0] = fw_ppet->numss_m1 & IEEE80211_PPE_THRES_NSS_MASK;
+	he_ppet[0] |= (fw_ppet->ru_bit_mask <<
+		       IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
+		      IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
+	for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
+		for (ru = 0; ru < 4; ru++) {
+			u8 val;
+			int i;
+
+			if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
+				continue;
+			val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
+			       0x3f;
+			val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
+			for (i = 5; i >= 0; i--) {
+				he_ppet[bit / 8] |=
+					((val >> i) & 0x1) << ((bit % 8));
+				bit++;
+			}
+		}
+	}
+}
+
+static int ath11k_mac_copy_he_cap(struct ath11k *ar,
+				  struct ath11k_pdev_cap *cap,
+				  struct ieee80211_sband_iftype_data *data,
+				  int band)
+{
+	int i, idx = 0;
+
+	for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
+		struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
+		struct ath11k_band_cap *band_cap = &cap->band[band];
+		struct ieee80211_he_cap_elem *he_cap_elem =
+				&he_cap->he_cap_elem;
+
+		switch (i) {
+		case NL80211_IFTYPE_STATION:
+		case NL80211_IFTYPE_AP:
+			break;
+
+		default:
+			continue;
+		}
+
+		data[idx].types_mask = BIT(i);
+		he_cap->has_he = true;
+		memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
+		       sizeof(he_cap_elem->mac_cap_info));
+		memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
+		       sizeof(he_cap_elem->phy_cap_info));
+
+		he_cap_elem->mac_cap_info[1] |=
+			IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
+		he_cap_elem->phy_cap_info[4] &=
+			~IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK;
+		he_cap_elem->phy_cap_info[4] &=
+			~IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK;
+		he_cap_elem->phy_cap_info[4] |= (ar->num_tx_chains - 1) << 2;
+
+		he_cap_elem->phy_cap_info[5] &=
+			~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
+		he_cap_elem->phy_cap_info[5] &=
+			~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
+		he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
+
+		switch (i) {
+		case NL80211_IFTYPE_AP:
+			he_cap_elem->phy_cap_info[9] |=
+				IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
+			break;
+		case NL80211_IFTYPE_STATION:
+			he_cap_elem->mac_cap_info[0] &=
+				~IEEE80211_HE_MAC_CAP0_TWT_RES;
+			he_cap_elem->mac_cap_info[0] |=
+				IEEE80211_HE_MAC_CAP0_TWT_REQ;
+			he_cap_elem->phy_cap_info[9] |=
+				IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
+			break;
+		}
+
+		he_cap->he_mcs_nss_supp.rx_mcs_80 =
+			cpu_to_le16(band_cap->he_mcs & 0xffff);
+		he_cap->he_mcs_nss_supp.tx_mcs_80 =
+			cpu_to_le16(band_cap->he_mcs & 0xffff);
+		he_cap->he_mcs_nss_supp.rx_mcs_160 =
+			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+		he_cap->he_mcs_nss_supp.tx_mcs_160 =
+			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+		he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
+			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+		he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
+			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+
+		memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
+		if (he_cap_elem->phy_cap_info[6] &
+		    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
+			ath11k_gen_ppe_thresh(&band_cap->he_ppet,
+					      he_cap->ppe_thres);
+		idx++;
+	}
+
+	return idx;
+}
+
+static void ath11k_mac_setup_he_cap(struct ath11k *ar,
+				    struct ath11k_pdev_cap *cap)
+{
+	struct ieee80211_supported_band *band = NULL;
+	int count = 0;
+
+	if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
+		count = ath11k_mac_copy_he_cap(ar, cap,
+					       ar->mac.iftype[NL80211_BAND_2GHZ],
+					       NL80211_BAND_2GHZ);
+		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
+		band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
+	}
+
+	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
+		count = ath11k_mac_copy_he_cap(ar, cap,
+					       ar->mac.iftype[NL80211_BAND_5GHZ],
+					       NL80211_BAND_5GHZ);
+		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
+		band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
+	}
+
+	band->n_iftype_data = count;
+}
+
 static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
 {
 	int ret;
@@ -3161,8 +3408,9 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
 		return ret;
 	}
 
-	/* Reload HT/VHT capability */
+	/* Reload HT/VHT/HE capability */
 	ath11k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
+	ath11k_mac_setup_he_cap(ar, &ar->pdev->cap);
 
 	return 0;
 }
@@ -5207,6 +5455,7 @@ static int ath11k_mac_register(struct ath11k *ar)
 		goto err_free;
 
 	ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
+	ath11k_mac_setup_he_cap(ar, cap);
 
 	ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask;
 	ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask;
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index 810050b033c4..453aa9c06969 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -141,6 +141,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar)
 			/* TODO: Set to true/false based on some condition? */
 			ch->allow_ht = true;
 			ch->allow_vht = true;
+			ch->allow_he = true;
 
 			ch->dfs_set =
 				!!(channel->flags & IEEE80211_CHAN_RADAR);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 3ec5dd47cdc8..d077ea30f3c1 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -753,6 +753,8 @@ static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan,
 		chan->info |= WMI_CHAN_INFO_ALLOW_HT;
 	if (arg->channel.allow_vht)
 		chan->info |= WMI_CHAN_INFO_ALLOW_VHT;
+	if (arg->channel.allow_he)
+		chan->info |= WMI_CHAN_INFO_ALLOW_HE;
 	if (arg->channel.ht40plus)
 		chan->info |= WMI_CHAN_INFO_HT40_PLUS;
 	if (arg->channel.chan_radar)
@@ -2150,7 +2152,9 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
 
 		if (tchan_info->is_chan_passive)
 			chan_info->info |= WMI_CHAN_INFO_PASSIVE;
-		if (tchan_info->allow_vht)
+		if (tchan_info->allow_he)
+			chan_info->info |= WMI_CHAN_INFO_ALLOW_HE;
+		else if (tchan_info->allow_vht)
 			chan_info->info |= WMI_CHAN_INFO_ALLOW_VHT;
 		else if (tchan_info->allow_ht)
 			chan_info->info |= WMI_CHAN_INFO_ALLOW_HT;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 1110da29cfcd..fd1ffa593a41 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -2445,6 +2445,7 @@ struct channel_param {
 	    is_chan_passive:1,
 	    allow_ht:1,
 	    allow_vht:1,
+	    allow_he:1,
 	    set_agile:1;
 	u32 phy_mode;
 	u32 cfreq1;
@@ -3334,7 +3335,10 @@ struct wmi_vdev_install_key_arg {
 
 #define WMI_MAX_SUPPORTED_RATES			128
 #define WMI_HOST_MAX_HECAP_PHY_SIZE		3
-#define WMI_HOST_MAX_HE_RATE_SET		1
+#define WMI_HOST_MAX_HE_RATE_SET		3
+#define WMI_HECAP_TXRX_MCS_NSS_IDX_80		0
+#define WMI_HECAP_TXRX_MCS_NSS_IDX_160		1
+#define WMI_HECAP_TXRX_MCS_NSS_IDX_80_80	2
 
 struct wmi_rate_set_arg {
 	u32 num_rates;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 7/8] ath11k: add TWT support
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
                   ` (5 preceding siblings ...)
  2019-11-25 16:36 ` [PATCH 6/8] ath11k: add HE support Kalle Valo
@ 2019-11-25 16:36 ` Kalle Valo
  2019-11-25 16:36 ` [PATCH 8/8] ath11k: add spatial reuse support Kalle Valo
       [not found] ` <0101016ea36be2a7-e7459aa6-c762-4f95-bb93-0158f7bb5bfb-000000@us-west-2.amazonses.com>
  8 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: John Crispin <john@phrozen.org>

Add target wait time wmi calls to the driver. En/disable the support
from when the bss_config changes. We ignore the cmd completion events.

Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/mac.c | 12 +++++
 drivers/net/wireless/ath/ath11k/wmi.c | 91 +++++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/wmi.h | 70 +++++++++++++++++++++++++++
 3 files changed, 173 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 79c22d86e0fe..70945d121fba 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1189,6 +1189,11 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
 		}
 	}
 
+	if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_RES)
+		arg->twt_responder = true;
+	if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
+		arg->twt_requester = true;
+
 	switch (sta->bandwidth) {
 	case IEEE80211_STA_RX_BW_160:
 		if (he_cap->he_cap_elem.phy_cap_info[0] &
@@ -1904,6 +1909,13 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
 	    !ath11k_mac_vif_chan(arvif->vif, &def))
 		ath11k_recalculate_mgmt_rate(ar, vif, &def);
 
+	if (changed & BSS_CHANGED_TWT) {
+		if (info->twt_requester || info->twt_responder)
+			ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev_idx);
+		else
+			ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev_idx);
+	}
+
 	mutex_unlock(&ar->conf_mutex);
 }
 
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index d077ea30f3c1..7aa66e8eecb6 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -1622,6 +1622,10 @@ ath11k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
 			cmd->peer_flags |= WMI_PEER_VHT;
 		if (param->he_flag)
 			cmd->peer_flags |= WMI_PEER_HE;
+		if (param->twt_requester)
+			cmd->peer_flags |= WMI_PEER_TWT_REQ;
+		if (param->twt_responder)
+			cmd->peer_flags |= WMI_PEER_TWT_RESP;
 	}
 
 	/* Suppress authorization for all AUTH modes that need 4-way handshake
@@ -2457,6 +2461,86 @@ int ath11k_wmi_pdev_pktlog_disable(struct ath11k *ar)
 	return ret;
 }
 
+int
+ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id)
+{
+	struct ath11k_pdev_wmi *wmi = ar->wmi;
+	struct ath11k_base *ab = wmi->wmi_sc->ab;
+	struct wmi_twt_enable_params_cmd *cmd;
+	struct sk_buff *skb;
+	int ret, len;
+
+	len = sizeof(*cmd);
+
+	skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (void *)skb->data;
+	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TWT_ENABLE_CMD) |
+			  FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
+	cmd->pdev_id = pdev_id;
+	cmd->sta_cong_timer_ms = ATH11K_TWT_DEF_STA_CONG_TIMER_MS;
+	cmd->default_slot_size = ATH11K_TWT_DEF_DEFAULT_SLOT_SIZE;
+	cmd->congestion_thresh_setup = ATH11K_TWT_DEF_CONGESTION_THRESH_SETUP;
+	cmd->congestion_thresh_teardown =
+		ATH11K_TWT_DEF_CONGESTION_THRESH_TEARDOWN;
+	cmd->congestion_thresh_critical =
+		ATH11K_TWT_DEF_CONGESTION_THRESH_CRITICAL;
+	cmd->interference_thresh_teardown =
+		ATH11K_TWT_DEF_INTERFERENCE_THRESH_TEARDOWN;
+	cmd->interference_thresh_setup =
+		ATH11K_TWT_DEF_INTERFERENCE_THRESH_SETUP;
+	cmd->min_no_sta_setup = ATH11K_TWT_DEF_MIN_NO_STA_SETUP;
+	cmd->min_no_sta_teardown = ATH11K_TWT_DEF_MIN_NO_STA_TEARDOWN;
+	cmd->no_of_bcast_mcast_slots = ATH11K_TWT_DEF_NO_OF_BCAST_MCAST_SLOTS;
+	cmd->min_no_twt_slots = ATH11K_TWT_DEF_MIN_NO_TWT_SLOTS;
+	cmd->max_no_sta_twt = ATH11K_TWT_DEF_MAX_NO_STA_TWT;
+	cmd->mode_check_interval = ATH11K_TWT_DEF_MODE_CHECK_INTERVAL;
+	cmd->add_sta_slot_interval = ATH11K_TWT_DEF_ADD_STA_SLOT_INTERVAL;
+	cmd->remove_sta_slot_interval =
+		ATH11K_TWT_DEF_REMOVE_STA_SLOT_INTERVAL;
+	/* TODO add MBSSID support */
+	cmd->mbss_support = 0;
+
+	ret = ath11k_wmi_cmd_send(wmi, skb,
+				  WMI_TWT_ENABLE_CMDID);
+	if (ret) {
+		ath11k_warn(ab, "Failed to send WMI_TWT_ENABLE_CMDID");
+		dev_kfree_skb(skb);
+	}
+	return ret;
+}
+
+int
+ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id)
+{
+	struct ath11k_pdev_wmi *wmi = ar->wmi;
+	struct ath11k_base *ab = wmi->wmi_sc->ab;
+	struct wmi_twt_disable_params_cmd *cmd;
+	struct sk_buff *skb;
+	int ret, len;
+
+	len = sizeof(*cmd);
+
+	skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (void *)skb->data;
+	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TWT_DISABLE_CMD) |
+			  FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
+	cmd->pdev_id = pdev_id;
+
+	ret = ath11k_wmi_cmd_send(wmi, skb,
+				  WMI_TWT_DISABLE_CMDID);
+	if (ret) {
+		ath11k_warn(ab, "Failed to send WMI_TWT_DIeABLE_CMDID");
+		dev_kfree_skb(skb);
+	}
+	return ret;
+}
+
 static void
 ath11k_fill_band_to_mac_param(struct ath11k_base  *soc,
 			      struct wmi_host_pdev_band_to_mac *band_to_mac)
@@ -2548,6 +2632,9 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
 	wmi_cfg->use_pdev_id = tg_cfg->use_pdev_id;
 	wmi_cfg->flag1 = tg_cfg->atf_config;
 	wmi_cfg->peer_map_unmap_v2_support = tg_cfg->peer_map_unmap_v2_support;
+	wmi_cfg->sched_params = tg_cfg->sched_params;
+	wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count;
+	wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count;
 }
 
 static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
@@ -2739,6 +2826,8 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
 	config.beacon_tx_offload_max_vdev = ab->num_radios * TARGET_MAX_BCN_OFFLD;
 	config.rx_batchmode = TARGET_RX_BATCHMODE;
 	config.peer_map_unmap_v2_support = 1;
+	config.twt_ap_pdev_count = 2;
+	config.twt_ap_sta_count = 1000;
 
 	memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
 
@@ -5421,6 +5510,8 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
 	case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
 	case WMI_VDEV_DELETE_RESP_EVENTID:
 	case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
+	case WMI_TWT_ENABLE_EVENTID:
+	case WMI_TWT_DISABLE_EVENTID:
 		ath11k_dbg(ab, ATH11K_DBG_WMI,
 			   "ignoring unsupported event 0x%x\n", id);
 		break;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index fd1ffa593a41..b5c53f2ac5cc 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -169,6 +169,9 @@ enum wmi_cmd_group {
 	WMI_GRP_MONITOR        = 0x39,
 	WMI_GRP_REGULATORY     = 0x3a,
 	WMI_GRP_HW_DATA_FILTER = 0x3b,
+	WMI_GRP_WLM            = 0x3c,
+	WMI_GRP_11K_OFFLOAD    = 0x3d,
+	WMI_GRP_TWT            = 0x3e,
 };
 
 #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1)
@@ -530,6 +533,12 @@ enum wmi_tlv_cmd_id {
 	WMI_NDP_RESPONDER_REQ_CMDID,
 	WMI_NDP_END_REQ_CMDID,
 	WMI_HW_DATA_FILTER_CMDID = WMI_TLV_CMD(WMI_GRP_HW_DATA_FILTER),
+	WMI_TWT_ENABLE_CMDID = WMI_TLV_CMD(WMI_GRP_TWT),
+	WMI_TWT_DISABLE_CMDID,
+	WMI_TWT_ADD_DIALOG_CMDID,
+	WMI_TWT_DEL_DIALOG_CMDID,
+	WMI_TWT_PAUSE_DIALOG_CMDID,
+	WMI_TWT_RESUME_DIALOG_CMDID,
 };
 
 enum wmi_tlv_event_id {
@@ -724,6 +733,13 @@ enum wmi_tlv_event_id {
 	WMI_NDP_INDICATION_EVENTID,
 	WMI_NDP_CONFIRM_EVENTID,
 	WMI_NDP_END_INDICATION_EVENTID,
+
+	WMI_TWT_ENABLE_EVENTID = WMI_TLV_CMD(WMI_GRP_TWT),
+	WMI_TWT_DISABLE_EVENTID,
+	WMI_TWT_ADD_DIALOG_EVENTID,
+	WMI_TWT_DEL_DIALOG_EVENTID,
+	WMI_TWT_PAUSE_DIALOG_EVENTID,
+	WMI_TWT_RESUME_DIALOG_EVENTID,
 };
 
 enum wmi_tlv_pdev_param {
@@ -2183,6 +2199,9 @@ struct wmi_resource_config {
 	u32 max_num_dbs_scan_duty_cycle;
 	u32 max_num_group_keys;
 	u32 peer_map_unmap_v2_support;
+	u32 sched_params;
+	u32 twt_ap_pdev_count;
+	u32 twt_ap_sta_count;
 } __packed;
 
 struct wmi_service_ready_event {
@@ -3401,6 +3420,8 @@ struct peer_assoc_params {
 	u32 peer_he_mcs_count;
 	u32 peer_he_rx_mcs_set[WMI_HOST_MAX_HE_RATE_SET];
 	u32 peer_he_tx_mcs_set[WMI_HOST_MAX_HE_RATE_SET];
+	bool twt_responder;
+	bool twt_requester;
 	struct ath11k_ppe_threshold peer_ppet;
 };
 
@@ -3652,6 +3673,8 @@ struct wmi_unit_test_cmd {
 #define WMI_PEER_DYN_MIMOPS	0x00020000
 #define WMI_PEER_STATIC_MIMOPS	0x00040000
 #define WMI_PEER_SPATIAL_MUX	0x00200000
+#define WMI_PEER_TWT_REQ	0x00400000
+#define WMI_PEER_TWT_RESP	0x00800000
 #define WMI_PEER_VHT		0x02000000
 #define WMI_PEER_80MHZ		0x04000000
 #define WMI_PEER_PMF		0x08000000
@@ -4494,6 +4517,48 @@ struct wmi_wmm_params_all_arg {
 	struct wmi_wmm_params_arg ac_vo;
 };
 
+#define ATH11K_TWT_DEF_STA_CONG_TIMER_MS		5000
+#define ATH11K_TWT_DEF_DEFAULT_SLOT_SIZE		10
+#define ATH11K_TWT_DEF_CONGESTION_THRESH_SETUP		50
+#define ATH11K_TWT_DEF_CONGESTION_THRESH_TEARDOWN	20
+#define ATH11K_TWT_DEF_CONGESTION_THRESH_CRITICAL	100
+#define ATH11K_TWT_DEF_INTERFERENCE_THRESH_TEARDOWN	80
+#define ATH11K_TWT_DEF_INTERFERENCE_THRESH_SETUP	50
+#define ATH11K_TWT_DEF_MIN_NO_STA_SETUP			10
+#define ATH11K_TWT_DEF_MIN_NO_STA_TEARDOWN		2
+#define ATH11K_TWT_DEF_NO_OF_BCAST_MCAST_SLOTS		2
+#define ATH11K_TWT_DEF_MIN_NO_TWT_SLOTS			2
+#define ATH11K_TWT_DEF_MAX_NO_STA_TWT			500
+#define ATH11K_TWT_DEF_MODE_CHECK_INTERVAL		10000
+#define ATH11K_TWT_DEF_ADD_STA_SLOT_INTERVAL		1000
+#define ATH11K_TWT_DEF_REMOVE_STA_SLOT_INTERVAL		5000
+
+struct wmi_twt_enable_params_cmd {
+	u32 tlv_header;
+	u32 pdev_id;
+	u32 sta_cong_timer_ms;
+	u32 mbss_support;
+	u32 default_slot_size;
+	u32 congestion_thresh_setup;
+	u32 congestion_thresh_teardown;
+	u32 congestion_thresh_critical;
+	u32 interference_thresh_teardown;
+	u32 interference_thresh_setup;
+	u32 min_no_sta_setup;
+	u32 min_no_sta_teardown;
+	u32 no_of_bcast_mcast_slots;
+	u32 min_no_twt_slots;
+	u32 max_no_sta_twt;
+	u32 mode_check_interval;
+	u32 add_sta_slot_interval;
+	u32 remove_sta_slot_interval;
+};
+
+struct wmi_twt_disable_params_cmd {
+	u32 tlv_header;
+	u32 pdev_id;
+};
+
 struct target_resource_config {
 	u32 num_vdevs;
 	u32 num_peers;
@@ -4553,6 +4618,9 @@ struct target_resource_config {
 	u32 max_bssid_rx_filters;
 	u32 use_pdev_id;
 	u32 peer_map_unmap_v2_support;
+	u32 sched_params;
+	u32 twt_ap_pdev_count;
+	u32 twt_ap_sta_count;
 };
 
 #define WMI_MAX_MEM_REQS 32
@@ -4676,4 +4744,6 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
 			      struct ath11k_fw_stats *fw_stats, u32 stats_id,
 			      char *buf);
 int ath11k_wmi_simulate_radar(struct ath11k *ar);
+int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id);
+int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id);
 #endif
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 8/8] ath11k: add spatial reuse support
       [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
                   ` (6 preceding siblings ...)
  2019-11-25 16:36 ` [PATCH 7/8] ath11k: add TWT support Kalle Valo
@ 2019-11-25 16:36 ` Kalle Valo
       [not found] ` <0101016ea36be2a7-e7459aa6-c762-4f95-bb93-0158f7bb5bfb-000000@us-west-2.amazonses.com>
  8 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-25 16:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: ath11k

From: John Crispin <john@phrozen.org>

Trigger the WMI call en/disabling OBSS PD when the bss config changes or we
assoc to an AP that broadcasts the IE.

Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/mac.c | 10 ++++++++++
 drivers/net/wireless/ath/ath11k/wmi.c | 35 +++++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/wmi.h | 16 ++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 70945d121fba..c25817c51d87 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1612,6 +1612,12 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
 					1);
 	if (ret)
 		ath11k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret);
+
+	ret = ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
+					   &bss_conf->he_obss_pd);
+	if (ret)
+		ath11k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
+			    arvif->vdev_id, ret);
 }
 
 static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
@@ -1916,6 +1922,10 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
 			ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev_idx);
 	}
 
+	if (changed & BSS_CHANGED_HE_OBSS_PD)
+		ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
+					     &info->he_obss_pd);
+
 	mutex_unlock(&ar->conf_mutex);
 }
 
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 7aa66e8eecb6..2c3c973f5f7c 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -2541,6 +2541,41 @@ ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id)
 	return ret;
 }
 
+int
+ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
+			     struct ieee80211_he_obss_pd *he_obss_pd)
+{
+	struct ath11k_pdev_wmi *wmi = ar->wmi;
+	struct ath11k_base *ab = wmi->wmi_sc->ab;
+	struct wmi_obss_spatial_reuse_params_cmd *cmd;
+	struct sk_buff *skb;
+	int ret, len;
+
+	len = sizeof(*cmd);
+
+	skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (void *)skb->data;
+	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
+				     WMI_TAG_OBSS_SPATIAL_REUSE_SET_CMD) |
+			  FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
+	cmd->vdev_id = vdev_id;
+	cmd->enable = he_obss_pd->enable;
+	cmd->obss_min = he_obss_pd->min_offset;
+	cmd->obss_max = he_obss_pd->max_offset;
+
+	ret = ath11k_wmi_cmd_send(wmi, skb,
+				  WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID);
+	if (ret) {
+		ath11k_warn(ab,
+			    "Failed to send WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID");
+		dev_kfree_skb(skb);
+	}
+	return ret;
+}
+
 static void
 ath11k_fill_band_to_mac_param(struct ath11k_base  *soc,
 			      struct wmi_host_pdev_band_to_mac *band_to_mac)
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index b5c53f2ac5cc..7d5690c65279 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -172,6 +172,8 @@ enum wmi_cmd_group {
 	WMI_GRP_WLM            = 0x3c,
 	WMI_GRP_11K_OFFLOAD    = 0x3d,
 	WMI_GRP_TWT            = 0x3e,
+	WMI_GRP_MOTION_DET     = 0x3f,
+	WMI_GRP_SPATIAL_REUSE  = 0x40,
 };
 
 #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1)
@@ -539,6 +541,9 @@ enum wmi_tlv_cmd_id {
 	WMI_TWT_DEL_DIALOG_CMDID,
 	WMI_TWT_PAUSE_DIALOG_CMDID,
 	WMI_TWT_RESUME_DIALOG_CMDID,
+	WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID =
+				WMI_TLV_CMD(WMI_GRP_SPATIAL_REUSE),
+	WMI_PDEV_OBSS_PD_SPATIAL_REUSE_SET_DEF_OBSS_THRESH_CMDID,
 };
 
 enum wmi_tlv_event_id {
@@ -4559,6 +4564,15 @@ struct wmi_twt_disable_params_cmd {
 	u32 pdev_id;
 };
 
+struct wmi_obss_spatial_reuse_params_cmd {
+	u32 tlv_header;
+	u32 pdev_id;
+	u32 enable;
+	s32 obss_min;
+	s32 obss_max;
+	u32 vdev_id;
+};
+
 struct target_resource_config {
 	u32 num_vdevs;
 	u32 num_peers;
@@ -4746,4 +4760,6 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
 int ath11k_wmi_simulate_radar(struct ath11k *ar);
 int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id);
 int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id);
+int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
+				 struct ieee80211_he_obss_pd *he_obss_pd);
 #endif
-- 
2.7.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 6/8] ath11k: add HE support
       [not found] ` <0101016ea36be2a7-e7459aa6-c762-4f95-bb93-0158f7bb5bfb-000000@us-west-2.amazonses.com>
@ 2019-11-25 18:03   ` John Crispin
  0 siblings, 0 replies; 10+ messages in thread
From: John Crispin @ 2019-11-25 18:03 UTC (permalink / raw)
  To: Kalle Valo, linux-wireless; +Cc: ath11k

On 25/11/2019 17:36, Kalle Valo wrote:
> From: John Crispin <john@phrozen.org>
> 
> Add basic HE support to the driver. The sband_iftype data is generated from
> the capabilities read from the FW.
> 
> Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
> Signed-off-by: John Crispin <john@phrozen.org>
> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

yippie !!

> ---
>   drivers/net/wireless/ath/ath11k/core.h |   2 +
>   drivers/net/wireless/ath/ath11k/mac.c  | 265 ++++++++++++++++++++++++++++++++-
>   drivers/net/wireless/ath/ath11k/reg.c  |   1 +
>   drivers/net/wireless/ath/ath11k/wmi.c  |   6 +-
>   drivers/net/wireless/ath/ath11k/wmi.h  |   6 +-
>   5 files changed, 270 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
> index 95447d1be104..065cb9dc880b 100644
> --- a/drivers/net/wireless/ath/ath11k/core.h
> +++ b/drivers/net/wireless/ath/ath11k/core.h
> @@ -431,6 +431,8 @@ struct ath11k {
>   
>   	struct {
>   		struct ieee80211_supported_band sbands[NUM_NL80211_BANDS];
> +		struct ieee80211_sband_iftype_data
> +			iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
>   	} mac;
>   	unsigned long dev_flags;
>   	unsigned int filter_flags;
> diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
> index 939f5880bce6..79c22d86e0fe 100644
> --- a/drivers/net/wireless/ath/ath11k/mac.c
> +++ b/drivers/net/wireless/ath/ath11k/mac.c
> @@ -1140,7 +1140,86 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
>   				   struct ieee80211_sta *sta,
>   				   struct peer_assoc_params *arg)
>   {
> -	/* TODO: Implementation */
> +	const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
> +	u16 v;
> +
> +	if (!he_cap->has_he)
> +		return;
> +
> +	arg->he_flag = true;
> +
> +	memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
> +	       sizeof(arg->peer_he_cap_macinfo));
> +	memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
> +	       sizeof(arg->peer_he_cap_phyinfo));
> +	memcpy(&arg->peer_he_ops, &vif->bss_conf.he_operation,
> +	       sizeof(arg->peer_he_ops));
> +
> +	/* the top most byte is used to indicate BSS color info */
> +	arg->peer_he_ops &= 0xffffff;
> +
> +	if (he_cap->he_cap_elem.phy_cap_info[6] &
> +	    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
> +		int bit = 7;
> +		int nss, ru;
> +
> +		arg->peer_ppet.numss_m1 = he_cap->ppe_thres[0] &
> +					  IEEE80211_PPE_THRES_NSS_MASK;
> +		arg->peer_ppet.ru_bit_mask =
> +			(he_cap->ppe_thres[0] &
> +			 IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>
> +			IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;
> +
> +		for (nss = 0; nss <= arg->peer_ppet.numss_m1; nss++) {
> +			for (ru = 0; ru < 4; ru++) {
> +				u32 val = 0;
> +				int i;
> +
> +				if ((arg->peer_ppet.ru_bit_mask & BIT(ru)) == 0)
> +					continue;
> +				for (i = 0; i < 6; i++) {
> +					val >>= 1;
> +					val |= ((he_cap->ppe_thres[bit / 8] >>
> +						 (bit % 8)) & 0x1) << 5;
> +					bit++;
> +				}
> +				arg->peer_ppet.ppet16_ppet8_ru3_ru0[nss] |=
> +								val << (ru * 6);
> +			}
> +		}
> +	}
> +
> +	switch (sta->bandwidth) {
> +	case IEEE80211_STA_RX_BW_160:
> +		if (he_cap->he_cap_elem.phy_cap_info[0] &
> +		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
> +			v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
> +			arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
> +
> +			v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
> +			arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
> +
> +			arg->peer_he_mcs_count++;
> +		}
> +		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
> +		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
> +
> +		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
> +		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
> +
> +		arg->peer_he_mcs_count++;
> +		/* fall through */
> +
> +	default:
> +		v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
> +		arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
> +
> +		v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
> +		arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
> +
> +		arg->peer_he_mcs_count++;
> +		break;
> +	}
>   }
>   
>   static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta,
> @@ -1307,6 +1386,32 @@ static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar,
>   	return MODE_UNKNOWN;
>   }
>   
> +static enum wmi_phy_mode ath11k_mac_get_phymode_he(struct ath11k *ar,
> +						   struct ieee80211_sta *sta)
> +{
> +	if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
> +		if (sta->he_cap.he_cap_elem.phy_cap_info[0] &
> +		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
> +			return MODE_11AX_HE160;
> +		else if (sta->he_cap.he_cap_elem.phy_cap_info[0] &
> +		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
> +			return MODE_11AX_HE80_80;
> +		/* not sure if this is a valid case? */
> +		return MODE_11AX_HE160;
> +	}
> +
> +	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
> +		return MODE_11AX_HE80;
> +
> +	if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
> +		return MODE_11AX_HE40;
> +
> +	if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
> +		return MODE_11AX_HE20;
> +
> +	return MODE_UNKNOWN;
> +}
> +
>   static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
>   					struct ieee80211_vif *vif,
>   					struct ieee80211_sta *sta,
> @@ -1328,7 +1433,14 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
>   
>   	switch (band) {
>   	case NL80211_BAND_2GHZ:
> -		if (sta->vht_cap.vht_supported &&
> +		if (sta->he_cap.has_he) {
> +			if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
> +				phymode = MODE_11AX_HE80_2G;
> +			else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
> +				phymode = MODE_11AX_HE40_2G;
> +			else
> +				phymode = MODE_11AX_HE20_2G;
> +		} else if (sta->vht_cap.vht_supported &&
>   		    !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
>   			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
>   				phymode = MODE_11AC_VHT40;
> @@ -1345,12 +1457,12 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
>   		} else {
>   			phymode = MODE_11B;
>   		}
> -		/* TODO: HE */
> -
>   		break;
>   	case NL80211_BAND_5GHZ:
> -		/* Check VHT first */
> -		if (sta->vht_cap.vht_supported &&
> +		/* Check HE first */
> +		if (sta->he_cap.has_he) {
> +			phymode = ath11k_mac_get_phymode_he(ar, sta);
> +		} else if (sta->vht_cap.vht_supported &&
>   		    !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
>   			phymode = ath11k_mac_get_phymode_vht(ar, sta);
>   		} else if (sta->ht_cap.ht_supported &&
> @@ -1362,7 +1474,6 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
>   		} else {
>   			phymode = MODE_11A;
>   		}
> -		/* TODO: HE Phymode */
>   		break;
>   	default:
>   		break;
> @@ -3126,6 +3237,142 @@ static int ath11k_check_chain_mask(struct ath11k *ar, u32 ant, bool is_tx_ant)
>   	return 0;
>   }
>   
> +static void ath11k_gen_ppe_thresh(struct ath11k_ppe_threshold *fw_ppet,
> +				  u8 *he_ppet)
> +{
> +	int nss, ru;
> +	u8 bit = 7;
> +
> +	he_ppet[0] = fw_ppet->numss_m1 & IEEE80211_PPE_THRES_NSS_MASK;
> +	he_ppet[0] |= (fw_ppet->ru_bit_mask <<
> +		       IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
> +		      IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
> +	for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
> +		for (ru = 0; ru < 4; ru++) {
> +			u8 val;
> +			int i;
> +
> +			if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
> +				continue;
> +			val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
> +			       0x3f;
> +			val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
> +			for (i = 5; i >= 0; i--) {
> +				he_ppet[bit / 8] |=
> +					((val >> i) & 0x1) << ((bit % 8));
> +				bit++;
> +			}
> +		}
> +	}
> +}
> +
> +static int ath11k_mac_copy_he_cap(struct ath11k *ar,
> +				  struct ath11k_pdev_cap *cap,
> +				  struct ieee80211_sband_iftype_data *data,
> +				  int band)
> +{
> +	int i, idx = 0;
> +
> +	for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
> +		struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
> +		struct ath11k_band_cap *band_cap = &cap->band[band];
> +		struct ieee80211_he_cap_elem *he_cap_elem =
> +				&he_cap->he_cap_elem;
> +
> +		switch (i) {
> +		case NL80211_IFTYPE_STATION:
> +		case NL80211_IFTYPE_AP:
> +			break;
> +
> +		default:
> +			continue;
> +		}
> +
> +		data[idx].types_mask = BIT(i);
> +		he_cap->has_he = true;
> +		memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
> +		       sizeof(he_cap_elem->mac_cap_info));
> +		memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
> +		       sizeof(he_cap_elem->phy_cap_info));
> +
> +		he_cap_elem->mac_cap_info[1] |=
> +			IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
> +		he_cap_elem->phy_cap_info[4] &=
> +			~IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK;
> +		he_cap_elem->phy_cap_info[4] &=
> +			~IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK;
> +		he_cap_elem->phy_cap_info[4] |= (ar->num_tx_chains - 1) << 2;
> +
> +		he_cap_elem->phy_cap_info[5] &=
> +			~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
> +		he_cap_elem->phy_cap_info[5] &=
> +			~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
> +		he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
> +
> +		switch (i) {
> +		case NL80211_IFTYPE_AP:
> +			he_cap_elem->phy_cap_info[9] |=
> +				IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
> +			break;
> +		case NL80211_IFTYPE_STATION:
> +			he_cap_elem->mac_cap_info[0] &=
> +				~IEEE80211_HE_MAC_CAP0_TWT_RES;
> +			he_cap_elem->mac_cap_info[0] |=
> +				IEEE80211_HE_MAC_CAP0_TWT_REQ;
> +			he_cap_elem->phy_cap_info[9] |=
> +				IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
> +			break;
> +		}
> +
> +		he_cap->he_mcs_nss_supp.rx_mcs_80 =
> +			cpu_to_le16(band_cap->he_mcs & 0xffff);
> +		he_cap->he_mcs_nss_supp.tx_mcs_80 =
> +			cpu_to_le16(band_cap->he_mcs & 0xffff);
> +		he_cap->he_mcs_nss_supp.rx_mcs_160 =
> +			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> +		he_cap->he_mcs_nss_supp.tx_mcs_160 =
> +			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> +		he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
> +			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> +		he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
> +			cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> +
> +		memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
> +		if (he_cap_elem->phy_cap_info[6] &
> +		    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
> +			ath11k_gen_ppe_thresh(&band_cap->he_ppet,
> +					      he_cap->ppe_thres);
> +		idx++;
> +	}
> +
> +	return idx;
> +}
> +
> +static void ath11k_mac_setup_he_cap(struct ath11k *ar,
> +				    struct ath11k_pdev_cap *cap)
> +{
> +	struct ieee80211_supported_band *band = NULL;
> +	int count = 0;
> +
> +	if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
> +		count = ath11k_mac_copy_he_cap(ar, cap,
> +					       ar->mac.iftype[NL80211_BAND_2GHZ],
> +					       NL80211_BAND_2GHZ);
> +		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
> +		band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
> +	}
> +
> +	if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
> +		count = ath11k_mac_copy_he_cap(ar, cap,
> +					       ar->mac.iftype[NL80211_BAND_5GHZ],
> +					       NL80211_BAND_5GHZ);
> +		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
> +		band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
> +	}
> +
> +	band->n_iftype_data = count;
> +}
> +
>   static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
>   {
>   	int ret;
> @@ -3161,8 +3408,9 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
>   		return ret;
>   	}
>   
> -	/* Reload HT/VHT capability */
> +	/* Reload HT/VHT/HE capability */
>   	ath11k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
> +	ath11k_mac_setup_he_cap(ar, &ar->pdev->cap);
>   
>   	return 0;
>   }
> @@ -5207,6 +5455,7 @@ static int ath11k_mac_register(struct ath11k *ar)
>   		goto err_free;
>   
>   	ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
> +	ath11k_mac_setup_he_cap(ar, cap);
>   
>   	ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask;
>   	ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask;
> diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
> index 810050b033c4..453aa9c06969 100644
> --- a/drivers/net/wireless/ath/ath11k/reg.c
> +++ b/drivers/net/wireless/ath/ath11k/reg.c
> @@ -141,6 +141,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar)
>   			/* TODO: Set to true/false based on some condition? */
>   			ch->allow_ht = true;
>   			ch->allow_vht = true;
> +			ch->allow_he = true;
>   
>   			ch->dfs_set =
>   				!!(channel->flags & IEEE80211_CHAN_RADAR);
> diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
> index 3ec5dd47cdc8..d077ea30f3c1 100644
> --- a/drivers/net/wireless/ath/ath11k/wmi.c
> +++ b/drivers/net/wireless/ath/ath11k/wmi.c
> @@ -753,6 +753,8 @@ static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan,
>   		chan->info |= WMI_CHAN_INFO_ALLOW_HT;
>   	if (arg->channel.allow_vht)
>   		chan->info |= WMI_CHAN_INFO_ALLOW_VHT;
> +	if (arg->channel.allow_he)
> +		chan->info |= WMI_CHAN_INFO_ALLOW_HE;
>   	if (arg->channel.ht40plus)
>   		chan->info |= WMI_CHAN_INFO_HT40_PLUS;
>   	if (arg->channel.chan_radar)
> @@ -2150,7 +2152,9 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
>   
>   		if (tchan_info->is_chan_passive)
>   			chan_info->info |= WMI_CHAN_INFO_PASSIVE;
> -		if (tchan_info->allow_vht)
> +		if (tchan_info->allow_he)
> +			chan_info->info |= WMI_CHAN_INFO_ALLOW_HE;
> +		else if (tchan_info->allow_vht)
>   			chan_info->info |= WMI_CHAN_INFO_ALLOW_VHT;
>   		else if (tchan_info->allow_ht)
>   			chan_info->info |= WMI_CHAN_INFO_ALLOW_HT;
> diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
> index 1110da29cfcd..fd1ffa593a41 100644
> --- a/drivers/net/wireless/ath/ath11k/wmi.h
> +++ b/drivers/net/wireless/ath/ath11k/wmi.h
> @@ -2445,6 +2445,7 @@ struct channel_param {
>   	    is_chan_passive:1,
>   	    allow_ht:1,
>   	    allow_vht:1,
> +	    allow_he:1,
>   	    set_agile:1;
>   	u32 phy_mode;
>   	u32 cfreq1;
> @@ -3334,7 +3335,10 @@ struct wmi_vdev_install_key_arg {
>   
>   #define WMI_MAX_SUPPORTED_RATES			128
>   #define WMI_HOST_MAX_HECAP_PHY_SIZE		3
> -#define WMI_HOST_MAX_HE_RATE_SET		1
> +#define WMI_HOST_MAX_HE_RATE_SET		3
> +#define WMI_HECAP_TXRX_MCS_NSS_IDX_80		0
> +#define WMI_HECAP_TXRX_MCS_NSS_IDX_160		1
> +#define WMI_HECAP_TXRX_MCS_NSS_IDX_80_80	2
>   
>   struct wmi_rate_set_arg {
>   	u32 num_rates;
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/8] ath11k: add RX stats support for radiotap
  2019-11-25 16:36 ` [PATCH 1/8] ath11k: add RX stats support for radiotap Kalle Valo
@ 2019-11-27 15:47   ` Kalle Valo
  0 siblings, 0 replies; 10+ messages in thread
From: Kalle Valo @ 2019-11-27 15:47 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, ath11k

Kalle Valo <kvalo@codeaurora.org> wrote:

> mac80211 expects the definition of what HE rate info is available inside a
> struct prepended to the skb.
> 
> Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com>
> Signed-off-by: John Crispin <john@phrozen.org>
> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

8 patches applied to ath-next branch of ath.git, thanks.

e4eb7b5c335c ath11k: add RX stats support for radiotap
9cfbae4632fa ath11k: ignore event 0x6017
2dab7d221e88 ath11k: convert message from info to dbg
39e81c6a2907 ath11k: fix missed bw conversion in tx completion
33782a3c379e ath11k: Remove dead code while handling amsdu packets
9f056ed8ee01 ath11k: add HE support
6d293d447670 ath11k: add TWT support
3f8be640077a ath11k: add spatial reuse support

-- 
https://patchwork.kernel.org/patch/11260591/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, back to index

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1574699772-17938-1-git-send-email-kvalo@codeaurora.org>
2019-11-25 16:36 ` [PATCH 1/8] ath11k: add RX stats support for radiotap Kalle Valo
2019-11-27 15:47   ` Kalle Valo
2019-11-25 16:36 ` [PATCH 2/8] ath11k: ignore event 0x6017 Kalle Valo
2019-11-25 16:36 ` [PATCH 3/8] ath11k: convert message from info to dbg Kalle Valo
2019-11-25 16:36 ` [PATCH 4/8] ath11k: fix missed bw conversion in tx completion Kalle Valo
2019-11-25 16:36 ` [PATCH 5/8] ath11k: Remove dead code while handling amsdu packets Kalle Valo
2019-11-25 16:36 ` [PATCH 6/8] ath11k: add HE support Kalle Valo
2019-11-25 16:36 ` [PATCH 7/8] ath11k: add TWT support Kalle Valo
2019-11-25 16:36 ` [PATCH 8/8] ath11k: add spatial reuse support Kalle Valo
     [not found] ` <0101016ea36be2a7-e7459aa6-c762-4f95-bb93-0158f7bb5bfb-000000@us-west-2.amazonses.com>
2019-11-25 18:03   ` [PATCH 6/8] ath11k: add HE support John Crispin

Linux-Wireless Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-wireless/0 linux-wireless/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-wireless linux-wireless/ https://lore.kernel.org/linux-wireless \
		linux-wireless@vger.kernel.org
	public-inbox-index linux-wireless

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-wireless


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git