ath11k: add HE radiotap header support
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
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
@@ -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
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(structath11k *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(structath11k *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
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 underspin_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
PATCH v7 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 v7 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