Skip to contentSkip to conversation

ath11k: add HE radiotap header support

PATCH Superseded Pradeep Kumar Chitrapu 2 participants 6 messages Mar 5, 2021 – Mar 18, 2021 Qualcomm Atheros ATH11K wireless driver

v7 of 10 Superseded Latest is v10 →

lore
Share & tools
lore
#0 lore raw

v7 cover ath11k: add HE radiotap header support

This series address review comments from previous revision:
https://patchwork.kernel.org/project/linux-wireless/list/?series=328291&state=%2A&archive=both

Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.4.0.1-01725-QCAHKSWPL_SILICONZ-1

changes in v7:
- use generic radiotap HE fields from

	include/net/ieee80211_radiotap.h

- fix converting gi and ltf enums to match nl80211 enums when updating radiotap headers.
- fix sparse warnings

Pradeep Kumar Chitrapu (3):
ath11k: switch to using ieee80211_tx_status_ext()
ath11k: decode HE status tlv
ath11k: translate HE status to radiotap format

 drivers/net/wireless/ath/ath11k/dp_rx.c    | 114 ++++-
 drivers/net/wireless/ath/ath11k/dp_tx.c    |  26 +-
 drivers/net/wireless/ath/ath11k/hal_desc.h |   1 +
 drivers/net/wireless/ath/ath11k/hal_rx.c   | 470 ++++++++++++++++++---
 drivers/net/wireless/ath/ath11k/hal_rx.h   | 135 +++++-
 5 files changed, 663 insertions(+), 83 deletions(-)
Signature · 7 lines
2.17.1


-- 
ath11k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath11k
#1 lore raw

PATCH v7 1/3 ath11k: switch to using ieee80211_tx_status_ext()

This allows us to pass HE rates down into the stack.

---
 drivers/net/wireless/ath/ath11k/dp_tx.c | 26 ++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)
drivers/net/wireless/ath/ath11k/dp_tx.c +19 -7
index 8bba5234f81f..9b636b4e8521 100644
@@ -417,9 +417,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
 				       struct sk_buff *msdu,
 				       struct hal_tx_status *ts)
 {
+	struct ieee80211_tx_status status = { 0 };
 	struct ath11k_base *ab = ar->ab;
 	struct ieee80211_tx_info *info;
 	struct ath11k_skb_cb *skb_cb;
+	struct ath11k_peer *peer;
+	struct ath11k_sta *arsta;
 
 	if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
 		/* Must not happen */
@@ -483,13 +486,22 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
 		ath11k_dp_tx_cache_peer_stats(ar, msdu, ts);
 	}
 
-	/* NOTE: Tx rate status reporting. Tx completion status does not have
-	 * necessary information (for example nss) to build the tx rate.
-	 * Might end up reporting it out-of-band from HTT stats.
-	 */
-
-	ieee80211_tx_status(ar->hw, msdu);
-
+	spin_lock_bh(&ab->base_lock);
+	peer = ath11k_peer_find_by_id(ab, ts->peer_id);
+	if (peer) {
+		arsta = (struct ath11k_sta *)peer->sta->drv_priv;
+		status.sta = peer->sta;
+		status.skb = msdu;
+		status.info = info;
+		status.rate = &arsta->last_txrate;
+	}
+	rcu_read_unlock();
+	if (peer)
+		ieee80211_tx_status_ext(ar->hw, &status);
+	else
+		dev_kfree_skb_any(msdu);
+	spin_unlock_bh(&ab->base_lock);
+	return;
 exit:
 	rcu_read_unlock();
 }
Signature · 7 lines
2.17.1


-- 
ath11k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath11k
#2 lore raw

Re: [PATCH v7 1/3] ath11k: switch to using ieee80211_tx_status_ext()

Quoted 33 lines
drivers/net/wireless/ath/ath11k/dp_tx.c +3 -0
@@ -417,9 +417,12 @@ static void ath11k_dp_tx_complete_msdu(struct 
 ath11k *ar,
 				       struct sk_buff *msdu,
 				       struct hal_tx_status *ts)
 {
+	struct ieee80211_tx_status status = { 0 };
 	struct ath11k_base *ab = ar->ab;
 	struct ieee80211_tx_info *info;
 	struct ath11k_skb_cb *skb_cb;
+	struct ath11k_peer *peer;
+	struct ath11k_sta *arsta;
 
 	if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
drivers/net/wireless/ath/ath11k/dp_tx.c +5 -7
 		/* Must not happen */
@@ -483,13 +486,22 @@ static void ath11k_dp_tx_complete_msdu(struct 
 ath11k *ar,
 		ath11k_dp_tx_cache_peer_stats(ar, msdu, ts);
 	}
 
-	/* NOTE: Tx rate status reporting. Tx completion status does not have
-	 * necessary information (for example nss) to build the tx rate.
-	 * Might end up reporting it out-of-band from HTT stats.
-	 */
-
-	ieee80211_tx_status(ar->hw, msdu);
-
+	spin_lock_bh(&ab->base_lock);
+	peer = ath11k_peer_find_by_id(ab, ts->peer_id);
+	if (peer) {
+		arsta = (struct ath11k_sta *)peer->sta->drv_priv;
+		status.sta = peer->sta;

drivers/net/wireless/ath/ath11k/dp_tx.c static void ath11k_dp_tx_complete_msdu(struct · line 504

Quoted 10 lines
drivers/net/wireless/ath/ath11k/dp_tx.c +10 -0
+		status.skb = msdu;
+		status.info = info;
+		status.rate = &arsta->last_txrate;
+	}
+	rcu_read_unlock();
+	if (peer)
+		ieee80211_tx_status_ext(ar->hw, &status);
+	else
+		dev_kfree_skb_any(msdu);
+	spin_unlock_bh(&ab->base_lock);

Why ieee80211_tx_status_ext() kept under spin_lock?

Thanks,
Karthikeyan P

Signature · 3 lines
ath11k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath11k
#3 lore raw

Re: [PATCH v7 1/3] ath11k: switch to using ieee80211_tx_status_ext()

Quoted 18 lines
Quoted 5 lines
drivers/net/wireless/ath/ath11k/dp_tx.c +5 -0
+	spin_lock_bh(&ab->base_lock);
+	peer = ath11k_peer_find_by_id(ab, ts->peer_id);
+	if (peer) {
+		arsta = (struct ath11k_sta *)peer->sta->drv_priv;
+		status.sta = peer->sta;

drivers/net/wireless/ath/ath11k/dp_tx.c static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, · line 503

Quoted 10 lines
drivers/net/wireless/ath/ath11k/dp_tx.c +10 -0
+		status.skb = msdu;
+		status.info = info;
+		status.rate = &arsta->last_txrate;
+	}
+	rcu_read_unlock();
+	if (peer)
+		ieee80211_tx_status_ext(ar->hw, &status);
+	else
+		dev_kfree_skb_any(msdu);
+	spin_unlock_bh(&ab->base_lock);

Why ieee80211_tx_status_ext() kept under spin_lock?

Quoted 2 lines

Thanks,
Karthikeyan P

Thanks Karthikeyan for the review..Yes, spin lock could be avoided for ieee80211_tx_status_ext(). I will address this in next revision.

Thanks
pradeep

Signature · 3 lines
ath11k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath11k
#4 lore raw

PATCH v7 2/3 ath11k: decode HE status tlv

In reply to Pradeep Kumar Chitrapu

Add new bitmasks and macro definitions required for parsing HE status tlvs. Decode HE status tlvs, which will used in dumping ppdu stats as well as updating radiotap headers.

---
 drivers/net/wireless/ath/ath11k/dp_rx.c    |  99 ++++++++++++---
 drivers/net/wireless/ath/ath11k/hal_desc.h |   1 +
 drivers/net/wireless/ath/ath11k/hal_rx.h   | 135 ++++++++++++++++++++-
 3 files changed, 214 insertions(+), 21 deletions(-)
drivers/net/wireless/ath/ath11k/dp_rx.c +82 -17
index 1d9aa1bb6b6e..659e0e68444e 100644
@@ -2369,7 +2369,7 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
 	char tid[32];
 
 	status = IEEE80211_SKB_RXCB(msdu);
-	if (status->encoding == RX_ENC_HE) {
+	if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE)) {
 		he = skb_push(msdu, sizeof(known));
 		memcpy(he, &known, sizeof(known));
 		status->flag |= RX_FLAG_RADIOTAP_HE;
@@ -4712,7 +4712,6 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
 {
 	struct ath11k_base *ab = ar->ab;
 	struct sk_buff *msdu, *mpdu_buf, *prev_buf;
-	u32 wifi_hdr_len;
 	struct hal_rx_desc *rx_desc;
 	char *hdr_desc;
 	u8 *dest, decap_format;
@@ -4751,38 +4750,27 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
 
 		skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN);
 	} else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) {
-		__le16 qos_field;
 		u8 qos_pkt = 0;
 
 		rx_desc = (struct hal_rx_desc *)head_msdu->data;
 		hdr_desc = ath11k_dp_rxdesc_get_80211hdr(ab, rx_desc);
 
 		/* Base size */
-		wifi_hdr_len = sizeof(struct ieee80211_hdr_3addr);
 		wh = (struct ieee80211_hdr_3addr *)hdr_desc;
 
 		if (ieee80211_is_data_qos(wh->frame_control)) {
-			struct ieee80211_qos_hdr *qwh =
-					(struct ieee80211_qos_hdr *)hdr_desc;
-
-			qos_field = qwh->qos_ctrl;
 			qos_pkt = 1;
 		}
 		msdu = head_msdu;
 
 		while (msdu) {
-			rx_desc = (struct hal_rx_desc *)msdu->data;
-			hdr_desc = ath11k_dp_rxdesc_get_80211hdr(ab, rx_desc);
-
+			ath11k_dp_rx_msdus_set_payload(ar, msdu);
 			if (qos_pkt) {
 				dest = skb_push(msdu, sizeof(__le16));
 				if (!dest)
 					goto err_merge_fail;
-				memcpy(dest, hdr_desc, wifi_hdr_len);
-				memcpy(dest + wifi_hdr_len,
-				       (u8 *)&qos_field, sizeof(__le16));
+				memcpy(dest, hdr_desc, sizeof(struct ieee80211_qos_hdr));
 			}
-			ath11k_dp_rx_msdus_set_payload(ar, msdu);
 			prev_buf = msdu;
 			msdu = msdu->next;
 		}
@@ -4812,8 +4800,83 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
 	return NULL;
 }
 
+static void
+ath11k_dp_rx_update_radiotap_he(struct hal_rx_mon_ppdu_info *rx_status,
+				u8 *rtap_buf)
+{
+	u32 rtap_len = 0;
+
+	put_unaligned_le16(rx_status->he_data1, &rtap_buf[rtap_len]);
+	rtap_len += 2;
+
+	put_unaligned_le16(rx_status->he_data2, &rtap_buf[rtap_len]);
+	rtap_len += 2;
+
+	put_unaligned_le16(rx_status->he_data3, &rtap_buf[rtap_len]);
+	rtap_len += 2;
+
+	put_unaligned_le16(rx_status->he_data4, &rtap_buf[rtap_len]);
+	rtap_len += 2;
+
+	put_unaligned_le16(rx_status->he_data5, &rtap_buf[rtap_len]);
+	rtap_len += 2;
+
+	put_unaligned_le16(rx_status->he_data6, &rtap_buf[rtap_len]);
+}
+
+static void
+ath11k_dp_rx_update_radiotap_he_mu(struct hal_rx_mon_ppdu_info *rx_status,
+				   u8 *rtap_buf)
+{
+	u32 rtap_len = 0;
+
+	put_unaligned_le16(rx_status->he_flags1, &rtap_buf[rtap_len]);
+	rtap_len += 2;
+
+	put_unaligned_le16(rx_status->he_flags2, &rtap_buf[rtap_len]);
+	rtap_len += 2;
+
+	rtap_buf[rtap_len] = rx_status->he_RU[0];
+	rtap_len += 1;
+
+	rtap_buf[rtap_len] = rx_status->he_RU[1];
+	rtap_len += 1;
+
+	rtap_buf[rtap_len] = rx_status->he_RU[2];
+	rtap_len += 1;
+
+	rtap_buf[rtap_len] = rx_status->he_RU[3];
+}
+
+static void ath11k_update_radiotap(struct hal_rx_mon_ppdu_info *ppduinfo,
+				   struct sk_buff *mon_skb,
+				   struct ieee80211_rx_status *rxs)
+{
+	u8 *ptr = NULL;
+
+	if (ppduinfo->he_mu_flags) {
+		rxs->flag |= RX_FLAG_RADIOTAP_HE_MU;
+		rxs->encoding = RX_ENC_HE;
+		ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he_mu));
+		ath11k_dp_rx_update_radiotap_he_mu(ppduinfo, ptr);
+	}
+	if (ppduinfo->he_flags) {
+		rxs->flag |= RX_FLAG_RADIOTAP_HE;
+		rxs->encoding = RX_ENC_HE;
+		ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he));
+		ath11k_dp_rx_update_radiotap_he(ppduinfo, ptr);
+	}
+
+	rxs->flag |= RX_FLAG_MACTIME_START;
+	rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR;
+	rxs->nss = ppduinfo->nss;
+
+	rxs->mactime = ppduinfo->tsft;
+}
+
 static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id,
 				    struct sk_buff *head_msdu,
+				    struct hal_rx_mon_ppdu_info *ppduinfo,
 				    struct sk_buff *tail_msdu,
 				    struct napi_struct *napi)
 {
@@ -4843,8 +4906,7 @@ static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id,
 		} else {
 			rxs->flag |= RX_FLAG_ALLOW_SAME_PN;
 		}
-		rxs->flag |= RX_FLAG_ONLY_MONITOR;
-
+		ath11k_update_radiotap(ppduinfo, mon_skb, rxs);
 		status = IEEE80211_SKB_RXCB(mon_skb);
 		*status = *rxs;
 
@@ -4920,6 +4982,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id,
 		}
 		if (head_msdu && tail_msdu) {
 			ath11k_dp_rx_mon_deliver(ar, dp->mac_id, head_msdu,
+						 &pmon->mon_ppdu_info,
 						 tail_msdu, napi);
 			rx_mon_stats->dest_mpdu_done++;
 		}
@@ -4966,6 +5029,8 @@ static void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar,
 	while (!skb_queue_empty(&pmon->rx_status_q)) {
 		status_skb = skb_dequeue(&pmon->rx_status_q);
 
+		memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info));
+
 		tlv_status = ath11k_hal_rx_parse_mon_status(ar->ab, ppdu_info,
 							    status_skb);
 		if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
drivers/net/wireless/ath/ath11k/hal_desc.h +1 -0
index d54ec6aa6281..e661448136eb 100644
@@ -474,6 +474,7 @@ enum hal_tlv_tag {
 
 #define HAL_TLV_HDR_TAG		GENMASK(9, 1)
 #define HAL_TLV_HDR_LEN		GENMASK(25, 10)
+#define HAL_TLV_USR_ID		GENMASK(31, 26)
 
 #define HAL_TLV_ALIGN	4
 
drivers/net/wireless/ath/ath11k/hal_rx.h +131 -4

212 lines not on this page · raw message

Signature · 7 lines
2.17.1


-- 
ath11k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath11k
#5 lore raw

PATCH v7 3/3 ath11k: translate HE status to radiotap format

In reply to Pradeep Kumar Chitrapu

Translate HE status to radiotap format. This uses HE radiotap definitions from include/net/ieee80211_radiotap.h.

---
 drivers/net/wireless/ath/ath11k/dp_rx.c  |  31 +-
 drivers/net/wireless/ath/ath11k/hal_rx.c | 470 ++++++++++++++++++++---
 2 files changed, 438 insertions(+), 63 deletions(-)
drivers/net/wireless/ath/ath11k/dp_rx.c +23 -8
index 659e0e68444e..073c4bfa79e2 100644
@@ -4848,29 +4848,44 @@ ath11k_dp_rx_update_radiotap_he_mu(struct hal_rx_mon_ppdu_info *rx_status,
 	rtap_buf[rtap_len] = rx_status->he_RU[3];
 }
 
-static void ath11k_update_radiotap(struct hal_rx_mon_ppdu_info *ppduinfo,
+static void ath11k_update_radiotap(struct ath11k *ar,
+				   struct hal_rx_mon_ppdu_info *ppduinfo,
 				   struct sk_buff *mon_skb,
 				   struct ieee80211_rx_status *rxs)
 {
+	struct ieee80211_supported_band *sband;
 	u8 *ptr = NULL;
 
+	rxs->flag |= RX_FLAG_MACTIME_START;
+	rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR;
+
+	if (ppduinfo->nss)
+		rxs->nss = ppduinfo->nss;
+
 	if (ppduinfo->he_mu_flags) {
 		rxs->flag |= RX_FLAG_RADIOTAP_HE_MU;
 		rxs->encoding = RX_ENC_HE;
 		ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he_mu));
 		ath11k_dp_rx_update_radiotap_he_mu(ppduinfo, ptr);
-	}
-	if (ppduinfo->he_flags) {
+	} else if (ppduinfo->he_flags) {
 		rxs->flag |= RX_FLAG_RADIOTAP_HE;
 		rxs->encoding = RX_ENC_HE;
 		ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he));
 		ath11k_dp_rx_update_radiotap_he(ppduinfo, ptr);
+		rxs->rate_idx = ppduinfo->rate;
+	} else if (ppduinfo->vht_flags) {
+		rxs->encoding = RX_ENC_VHT;
+		rxs->rate_idx = ppduinfo->rate;
+	} else if (ppduinfo->ht_flags) {
+		rxs->encoding = RX_ENC_HT;
+		rxs->rate_idx = ppduinfo->rate;
+	} else {
+		rxs->encoding = RX_ENC_LEGACY;
+		sband = &ar->mac.sbands[rxs->band];
+		rxs->rate_idx = ath11k_mac_hw_rate_to_idx(sband, ppduinfo->rate,
+							  ppduinfo->cck_flag);
 	}
 
-	rxs->flag |= RX_FLAG_MACTIME_START;
-	rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR;
-	rxs->nss = ppduinfo->nss;
-
 	rxs->mactime = ppduinfo->tsft;
 }
 
@@ -4906,7 +4921,7 @@ static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id,
 		} else {
 			rxs->flag |= RX_FLAG_ALLOW_SAME_PN;
 		}
-		ath11k_update_radiotap(ppduinfo, mon_skb, rxs);
+		ath11k_update_radiotap(ar, ppduinfo, mon_skb, rxs);
 		status = IEEE80211_SKB_RXCB(mon_skb);
 		*status = *rxs;
 
drivers/net/wireless/ath/ath11k/hal_rx.c +415 -55

590 lines not on this page · raw message

Signature · 7 lines
2.17.1


-- 
ath11k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath11k