ath11k: add HE radiotap header support
v8 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 v8:
- move ieee80211_tx_status_ext out of spin lock
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 | 25 +- 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(+), 82 deletions(-)
Signature · 7 lines
2.17.1 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH v8 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 | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
drivers/net/wireless/ath/ath11k/dp_tx.c +19 -6
@@ -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,23 @@ 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; + } +spin_unlock_bh (&ab->base_lock); +rcu_read_unlock (); +if (peer) +ieee80211_tx_status_ext (ar->hw, &status); +else +dev_kfree_skb_any (msdu); +return ; exit:rcu_read_unlock (); }
Signature · 7 lines
2.17.1 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
Re: [PATCH V8 1/3] ath11k: switch to using ieee80211_tx_status_ext()
drivers/net/wireless/ath/ath11k/dp_tx.c static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, · line 496
Quoted 10 lines
drivers/net/wireless/ath/ath11k/dp_tx.c +8
-1-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;
Assigning arsta holded last_txrate pointer to status.rate create race condition problem b/w sta delete and ieee80211_tx_status_ext, no ? Hw we ensure that arsta pointer is valid until ieee80211_tx_status_ext() processing?
Instead why don't we have local struct rate_info and assign like below code snippet
struct rate_info rate;
...
rate = arsta->last_txrate;
status.rate = &rate;Thanks,
Karthikeyan P
Signature · 3 lines
ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
Re: [PATCH V8 1/3] ath11k: switch to using ieee80211_tx_status_ext()
Quoted 18 lines · Karthikeyan periyasamy
drivers/net/wireless/ath/ath11k/dp_tx.c static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, · line 496
Quoted 9 lines
drivers/net/wireless/ath/ath11k/dp_tx.c +8
-1-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;Assigning arsta holded
last_txratepointer to status.rate create race condition problem b/w sta delete andieee80211_tx_status_ext, no ? Hw we ensure that arsta pointer is valid untilieee80211_tx_status_ext()processing?Instead why don't we have local struct
rate_infoand assign like below code snippet
Quoted 7 lines
struct rate_info rate; ... rate = arsta->last_txrate; status.rate = &rate;Thanks,
Karthikeyan P
Thanks Karthikeyan, I have addressed this in V9..
PATCH v8 2/3 ath11k: decode HE status tlv
In reply to Pradeep Kumar ChitrapuAdd 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
@@ -2369,7 +2369,7 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *napchar 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
@@ -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
PATCH v8 3/3 ath11k: translate HE status to radiotap format
In reply to Pradeep Kumar ChitrapuTranslate 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
@@ -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