0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. From 6257c702264c44d74c6b71f0c62a7665da2dc356 Mon Sep 17 00:00:00 2001
  2. From: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
  3. Date: Mon, 17 Apr 2023 13:35:02 +0300
  4. Subject: [PATCH] wifi: ath11k: fix tx status reporting in encap offload mode
  5. ieee80211_tx_status() treats packets in 802.11 frame format and
  6. tries to extract sta address from packet header. When tx encap
  7. offload is enabled, this becomes invalid operation. Hence, switch
  8. to using ieee80211_tx_status_ext() after filling in station
  9. address for handling both 802.11 and 802.3 frames.
  10. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
  11. Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
  12. Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
  13. Link: https://lore.kernel.org/r/20230403195738.25367-2-quic_pradeepc@quicinc.com
  14. ---
  15. drivers/net/wireless/ath/ath11k/dp.h | 4 +++
  16. drivers/net/wireless/ath/ath11k/dp_tx.c | 33 ++++++++++++++++++++++++-
  17. drivers/net/wireless/ath/ath11k/dp_tx.h | 1 +
  18. 3 files changed, 37 insertions(+), 1 deletion(-)
  19. --- a/drivers/net/wireless/ath/ath11k/dp.h
  20. +++ b/drivers/net/wireless/ath/ath11k/dp.h
  21. @@ -303,12 +303,16 @@ struct ath11k_dp {
  22. #define HTT_TX_WBM_COMP_STATUS_OFFSET 8
  23. +#define HTT_INVALID_PEER_ID 0xffff
  24. +
  25. /* HTT tx completion is overlaid in wbm_release_ring */
  26. #define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9)
  27. #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
  28. #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
  29. #define HTT_TX_WBM_COMP_INFO1_ACK_RSSI GENMASK(31, 24)
  30. +#define HTT_TX_WBM_COMP_INFO2_SW_PEER_ID GENMASK(15, 0)
  31. +#define HTT_TX_WBM_COMP_INFO2_VALID BIT(21)
  32. struct htt_tx_wbm_completion {
  33. u32 info0;
  34. --- a/drivers/net/wireless/ath/ath11k/dp_tx.c
  35. +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
  36. @@ -316,10 +316,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
  37. struct dp_tx_ring *tx_ring,
  38. struct ath11k_dp_htt_wbm_tx_status *ts)
  39. {
  40. + struct ieee80211_tx_status status = { 0 };
  41. struct sk_buff *msdu;
  42. struct ieee80211_tx_info *info;
  43. struct ath11k_skb_cb *skb_cb;
  44. struct ath11k *ar;
  45. + struct ath11k_peer *peer;
  46. spin_lock(&tx_ring->tx_idr_lock);
  47. msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id);
  48. @@ -341,6 +343,11 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
  49. dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
  50. + if (!skb_cb->vif) {
  51. + dev_kfree_skb_any(msdu);
  52. + return;
  53. + }
  54. +
  55. memset(&info->status, 0, sizeof(info->status));
  56. if (ts->acked) {
  57. @@ -355,7 +362,23 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
  58. }
  59. }
  60. - ieee80211_tx_status(ar->hw, msdu);
  61. + spin_lock_bh(&ab->base_lock);
  62. + peer = ath11k_peer_find_by_id(ab, ts->peer_id);
  63. + if (!peer || !peer->sta) {
  64. + ath11k_dbg(ab, ATH11K_DBG_DATA,
  65. + "dp_tx: failed to find the peer with peer_id %d\n",
  66. + ts->peer_id);
  67. + spin_unlock_bh(&ab->base_lock);
  68. + dev_kfree_skb_any(msdu);
  69. + return;
  70. + }
  71. + spin_unlock_bh(&ab->base_lock);
  72. +
  73. + status.sta = peer->sta;
  74. + status.info = info;
  75. + status.skb = msdu;
  76. +
  77. + ieee80211_tx_status_ext(ar->hw, &status);
  78. }
  79. static void
  80. @@ -379,7 +402,15 @@ ath11k_dp_tx_process_htt_tx_complete(str
  81. ts.msdu_id = msdu_id;
  82. ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI,
  83. status_desc->info1);
  84. +
  85. + if (FIELD_GET(HTT_TX_WBM_COMP_INFO2_VALID, status_desc->info2))
  86. + ts.peer_id = FIELD_GET(HTT_TX_WBM_COMP_INFO2_SW_PEER_ID,
  87. + status_desc->info2);
  88. + else
  89. + ts.peer_id = HTT_INVALID_PEER_ID;
  90. +
  91. ath11k_dp_tx_htt_tx_complete_buf(ab, tx_ring, &ts);
  92. +
  93. break;
  94. case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
  95. case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
  96. --- a/drivers/net/wireless/ath/ath11k/dp_tx.h
  97. +++ b/drivers/net/wireless/ath/ath11k/dp_tx.h
  98. @@ -13,6 +13,7 @@ struct ath11k_dp_htt_wbm_tx_status {
  99. u32 msdu_id;
  100. bool acked;
  101. int ack_rssi;
  102. + u16 peer_id;
  103. };
  104. void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts);