1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. 4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 5 */ 6 7 #include "core.h" 8 #include "dp_tx.h" 9 #include "debug.h" 10 #include "debugfs.h" 11 #include "hw.h" 12 #include "peer.h" 13 #include "mac.h" 14 15 enum hal_tcl_encap_type 16 ath12k_dp_tx_get_encap_type(struct ath12k_base *ab, struct sk_buff *skb) 17 { 18 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 19 20 if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) 21 return HAL_TCL_ENCAP_TYPE_RAW; 22 23 if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) 24 return HAL_TCL_ENCAP_TYPE_ETHERNET; 25 26 return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI; 27 } 28 EXPORT_SYMBOL(ath12k_dp_tx_get_encap_type); 29 30 void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb) 31 { 32 struct ieee80211_hdr *hdr = (void *)skb->data; 33 u8 *qos_ctl; 34 35 if (!ieee80211_is_data_qos(hdr->frame_control)) 36 return; 37 38 qos_ctl = ieee80211_get_qos_ctl(hdr); 39 memmove(skb->data + IEEE80211_QOS_CTL_LEN, 40 skb->data, (void *)qos_ctl - (void *)skb->data); 41 skb_pull(skb, IEEE80211_QOS_CTL_LEN); 42 43 hdr = (void *)skb->data; 44 hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA); 45 } 46 EXPORT_SYMBOL(ath12k_dp_tx_encap_nwifi); 47 48 u8 ath12k_dp_tx_get_tid(struct sk_buff *skb) 49 { 50 struct ieee80211_hdr *hdr = (void *)skb->data; 51 struct ath12k_skb_cb *cb = ATH12K_SKB_CB(skb); 52 53 if (cb->flags & ATH12K_SKB_HW_80211_ENCAP) 54 return skb->priority & IEEE80211_QOS_CTL_TID_MASK; 55 else if (!ieee80211_is_data_qos(hdr->frame_control)) 56 return HAL_DESC_REO_NON_QOS_TID; 57 else 58 return skb->priority & IEEE80211_QOS_CTL_TID_MASK; 59 } 60 EXPORT_SYMBOL(ath12k_dp_tx_get_tid); 61 62 enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher) 63 { 64 switch (cipher) { 65 case WLAN_CIPHER_SUITE_WEP40: 66 return HAL_ENCRYPT_TYPE_WEP_40; 67 case WLAN_CIPHER_SUITE_WEP104: 68 return HAL_ENCRYPT_TYPE_WEP_104; 69 case WLAN_CIPHER_SUITE_TKIP: 70 return HAL_ENCRYPT_TYPE_TKIP_MIC; 71 case WLAN_CIPHER_SUITE_CCMP: 72 return HAL_ENCRYPT_TYPE_CCMP_128; 73 case WLAN_CIPHER_SUITE_CCMP_256: 74 return HAL_ENCRYPT_TYPE_CCMP_256; 75 case WLAN_CIPHER_SUITE_GCMP: 76 return HAL_ENCRYPT_TYPE_GCMP_128; 77 case WLAN_CIPHER_SUITE_GCMP_256: 78 return HAL_ENCRYPT_TYPE_AES_GCMP_256; 79 default: 80 return HAL_ENCRYPT_TYPE_OPEN; 81 } 82 } 83 EXPORT_SYMBOL(ath12k_dp_tx_get_encrypt_type); 84 85 u8 ath12k_dp_tx_crypto_iv_len(enum hal_encrypt_type enc_type) 86 { 87 switch (enc_type) { 88 case HAL_ENCRYPT_TYPE_TKIP_NO_MIC: 89 case HAL_ENCRYPT_TYPE_TKIP_MIC: 90 return IEEE80211_TKIP_IV_LEN; 91 case HAL_ENCRYPT_TYPE_CCMP_128: 92 return IEEE80211_CCMP_HDR_LEN; 93 case HAL_ENCRYPT_TYPE_CCMP_256: 94 return IEEE80211_CCMP_256_HDR_LEN; 95 case HAL_ENCRYPT_TYPE_GCMP_128: 96 case HAL_ENCRYPT_TYPE_AES_GCMP_256: 97 return IEEE80211_GCMP_HDR_LEN; 98 case HAL_ENCRYPT_TYPE_WEP_40: 99 case HAL_ENCRYPT_TYPE_WEP_104: 100 case HAL_ENCRYPT_TYPE_WEP_128: 101 return IEEE80211_WEP_IV_LEN; 102 default: 103 return 0; 104 } 105 } 106 EXPORT_SYMBOL(ath12k_dp_tx_crypto_iv_len); 107 108 u8 ath12k_dp_tx_crypto_icv_len(enum hal_encrypt_type enc_type) 109 { 110 switch (enc_type) { 111 case HAL_ENCRYPT_TYPE_CCMP_128: 112 return IEEE80211_CCMP_MIC_LEN; 113 case HAL_ENCRYPT_TYPE_CCMP_256: 114 return IEEE80211_CCMP_256_MIC_LEN; 115 case HAL_ENCRYPT_TYPE_GCMP_128: 116 case HAL_ENCRYPT_TYPE_AES_GCMP_256: 117 return IEEE80211_GCMP_MIC_LEN; 118 case HAL_ENCRYPT_TYPE_TKIP_NO_MIC: 119 case HAL_ENCRYPT_TYPE_TKIP_MIC: 120 return IEEE80211_TKIP_ICV_LEN; 121 case HAL_ENCRYPT_TYPE_WEP_40: 122 case HAL_ENCRYPT_TYPE_WEP_104: 123 case HAL_ENCRYPT_TYPE_WEP_128: 124 return IEEE80211_WEP_ICV_LEN; 125 default: 126 return 0; 127 } 128 } 129 EXPORT_SYMBOL(ath12k_dp_tx_crypto_icv_len); 130 131 void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, 132 struct ath12k_tx_desc_info *tx_desc, 133 u8 pool_id) 134 { 135 spin_lock_bh(&dp->tx_desc_lock[pool_id]); 136 tx_desc->skb_ext_desc = NULL; 137 list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[pool_id]); 138 spin_unlock_bh(&dp->tx_desc_lock[pool_id]); 139 } 140 EXPORT_SYMBOL(ath12k_dp_tx_release_txbuf); 141 142 struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp, 143 u8 pool_id) 144 { 145 struct ath12k_tx_desc_info *desc; 146 147 spin_lock_bh(&dp->tx_desc_lock[pool_id]); 148 desc = list_first_entry_or_null(&dp->tx_desc_free_list[pool_id], 149 struct ath12k_tx_desc_info, 150 list); 151 if (!desc) { 152 spin_unlock_bh(&dp->tx_desc_lock[pool_id]); 153 ath12k_warn(dp->ab, "failed to allocate data Tx buffer\n"); 154 return NULL; 155 } 156 157 list_move_tail(&desc->list, &dp->tx_desc_used_list[pool_id]); 158 spin_unlock_bh(&dp->tx_desc_lock[pool_id]); 159 160 return desc; 161 } 162 EXPORT_SYMBOL(ath12k_dp_tx_assign_buffer); 163 164 void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len) 165 { 166 struct sk_buff *tail; 167 void *metadata; 168 169 if (unlikely(skb_cow_data(skb, tail_len, &tail) < 0)) 170 return NULL; 171 172 metadata = pskb_put(skb, tail, tail_len); 173 memset(metadata, 0, tail_len); 174 return metadata; 175 } 176 EXPORT_SYMBOL(ath12k_dp_metadata_align_skb); 177 178 static void ath12k_dp_tx_move_payload(struct sk_buff *skb, 179 unsigned long delta, 180 bool head) 181 { 182 unsigned long len = skb->len; 183 184 if (head) { 185 skb_push(skb, delta); 186 memmove(skb->data, skb->data + delta, len); 187 skb_trim(skb, len); 188 } else { 189 skb_put(skb, delta); 190 memmove(skb->data + delta, skb->data, len); 191 skb_pull(skb, delta); 192 } 193 } 194 195 int ath12k_dp_tx_align_payload(struct ath12k_dp *dp, struct sk_buff **pskb) 196 { 197 u32 iova_mask = dp->hw_params->iova_mask; 198 unsigned long offset, delta1, delta2; 199 struct sk_buff *skb2, *skb = *pskb; 200 unsigned int headroom = skb_headroom(skb); 201 int tailroom = skb_tailroom(skb); 202 int ret = 0; 203 204 offset = (unsigned long)skb->data & iova_mask; 205 delta1 = offset; 206 delta2 = iova_mask - offset + 1; 207 208 if (headroom >= delta1) { 209 ath12k_dp_tx_move_payload(skb, delta1, true); 210 } else if (tailroom >= delta2) { 211 ath12k_dp_tx_move_payload(skb, delta2, false); 212 } else { 213 skb2 = skb_realloc_headroom(skb, iova_mask); 214 if (!skb2) { 215 ret = -ENOMEM; 216 goto out; 217 } 218 219 dev_kfree_skb_any(skb); 220 221 offset = (unsigned long)skb2->data & iova_mask; 222 if (offset) 223 ath12k_dp_tx_move_payload(skb2, offset, true); 224 *pskb = skb2; 225 } 226 227 out: 228 return ret; 229 } 230 EXPORT_SYMBOL(ath12k_dp_tx_align_payload); 231 232 void ath12k_dp_tx_free_txbuf(struct ath12k_dp *dp, 233 struct dp_tx_ring *tx_ring, 234 struct ath12k_tx_desc_params *desc_params) 235 { 236 struct ath12k_pdev_dp *dp_pdev; 237 struct sk_buff *msdu = desc_params->skb; 238 struct ath12k_skb_cb *skb_cb; 239 u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(dp->hw_params, desc_params->mac_id); 240 241 skb_cb = ATH12K_SKB_CB(msdu); 242 243 dma_unmap_single(dp->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); 244 if (skb_cb->paddr_ext_desc) { 245 dma_unmap_single(dp->dev, skb_cb->paddr_ext_desc, 246 desc_params->skb_ext_desc->len, DMA_TO_DEVICE); 247 dev_kfree_skb_any(desc_params->skb_ext_desc); 248 } 249 250 guard(rcu)(); 251 252 dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx); 253 254 ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu); 255 256 if (atomic_dec_and_test(&dp_pdev->num_tx_pending)) 257 wake_up(&dp_pdev->tx_empty_waitq); 258 } 259 EXPORT_SYMBOL(ath12k_dp_tx_free_txbuf); 260