| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: ISC |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
|---|
| 3 | 4 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
|---|
| 4 | | - * |
|---|
| 5 | | - * Permission to use, copy, modify, and/or distribute this software for any |
|---|
| 6 | | - * purpose with or without fee is hereby granted, provided that the above |
|---|
| 7 | | - * copyright notice and this permission notice appear in all copies. |
|---|
| 8 | | - * |
|---|
| 9 | | - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|---|
| 10 | | - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|---|
| 11 | | - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|---|
| 12 | | - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|---|
| 13 | | - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|---|
| 14 | | - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|---|
| 15 | | - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|---|
| 16 | 5 | */ |
|---|
| 17 | 6 | |
|---|
| 18 | 7 | #include <linux/etherdevice.h> |
|---|
| .. | .. |
|---|
| 498 | 487 | if (htt->tx_mem_allocated) |
|---|
| 499 | 488 | return 0; |
|---|
| 500 | 489 | |
|---|
| 490 | + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
|---|
| 491 | + return 0; |
|---|
| 492 | + |
|---|
| 501 | 493 | ret = ath10k_htt_tx_alloc_buf(htt); |
|---|
| 502 | 494 | if (ret) |
|---|
| 503 | 495 | goto free_idr_pending_tx; |
|---|
| .. | .. |
|---|
| 540 | 532 | htt->tx_mem_allocated = false; |
|---|
| 541 | 533 | } |
|---|
| 542 | 534 | |
|---|
| 535 | +static void ath10k_htt_flush_tx_queue(struct ath10k_htt *htt) |
|---|
| 536 | +{ |
|---|
| 537 | + ath10k_htc_stop_hl(htt->ar); |
|---|
| 538 | + idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); |
|---|
| 539 | +} |
|---|
| 540 | + |
|---|
| 543 | 541 | void ath10k_htt_tx_stop(struct ath10k_htt *htt) |
|---|
| 544 | 542 | { |
|---|
| 545 | | - idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); |
|---|
| 543 | + ath10k_htt_flush_tx_queue(htt); |
|---|
| 546 | 544 | idr_destroy(&htt->pending_tx); |
|---|
| 547 | 545 | } |
|---|
| 548 | 546 | |
|---|
| .. | .. |
|---|
| 552 | 550 | ath10k_htt_tx_destroy(htt); |
|---|
| 553 | 551 | } |
|---|
| 554 | 552 | |
|---|
| 553 | +void ath10k_htt_op_ep_tx_credits(struct ath10k *ar) |
|---|
| 554 | +{ |
|---|
| 555 | + queue_work(ar->workqueue, &ar->bundle_tx_work); |
|---|
| 556 | +} |
|---|
| 557 | + |
|---|
| 555 | 558 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
|---|
| 556 | 559 | { |
|---|
| 560 | + struct ath10k_htt *htt = &ar->htt; |
|---|
| 561 | + struct htt_tx_done tx_done = {0}; |
|---|
| 562 | + struct htt_cmd_hdr *htt_hdr; |
|---|
| 563 | + struct htt_data_tx_desc *desc_hdr = NULL; |
|---|
| 564 | + u16 flags1 = 0; |
|---|
| 565 | + u8 msg_type = 0; |
|---|
| 566 | + |
|---|
| 567 | + if (htt->disable_tx_comp) { |
|---|
| 568 | + htt_hdr = (struct htt_cmd_hdr *)skb->data; |
|---|
| 569 | + msg_type = htt_hdr->msg_type; |
|---|
| 570 | + |
|---|
| 571 | + if (msg_type == HTT_H2T_MSG_TYPE_TX_FRM) { |
|---|
| 572 | + desc_hdr = (struct htt_data_tx_desc *) |
|---|
| 573 | + (skb->data + sizeof(*htt_hdr)); |
|---|
| 574 | + flags1 = __le16_to_cpu(desc_hdr->flags1); |
|---|
| 575 | + } |
|---|
| 576 | + } |
|---|
| 577 | + |
|---|
| 557 | 578 | dev_kfree_skb_any(skb); |
|---|
| 579 | + |
|---|
| 580 | + if ((!htt->disable_tx_comp) || (msg_type != HTT_H2T_MSG_TYPE_TX_FRM)) |
|---|
| 581 | + return; |
|---|
| 582 | + |
|---|
| 583 | + ath10k_dbg(ar, ATH10K_DBG_HTT, |
|---|
| 584 | + "htt tx complete msdu id:%u ,flags1:%x\n", |
|---|
| 585 | + __le16_to_cpu(desc_hdr->id), flags1); |
|---|
| 586 | + |
|---|
| 587 | + if (flags1 & HTT_DATA_TX_DESC_FLAGS1_TX_COMPLETE) |
|---|
| 588 | + return; |
|---|
| 589 | + |
|---|
| 590 | + tx_done.status = HTT_TX_COMPL_STATE_ACK; |
|---|
| 591 | + tx_done.msdu_id = __le16_to_cpu(desc_hdr->id); |
|---|
| 592 | + ath10k_txrx_tx_unref(&ar->htt, &tx_done); |
|---|
| 558 | 593 | } |
|---|
| 559 | 594 | |
|---|
| 560 | 595 | void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
|---|
| .. | .. |
|---|
| 591 | 626 | return 0; |
|---|
| 592 | 627 | } |
|---|
| 593 | 628 | |
|---|
| 594 | | -int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie) |
|---|
| 629 | +int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u32 mask, u32 reset_mask, |
|---|
| 630 | + u64 cookie) |
|---|
| 595 | 631 | { |
|---|
| 596 | 632 | struct ath10k *ar = htt->ar; |
|---|
| 597 | 633 | struct htt_stats_req *req; |
|---|
| .. | .. |
|---|
| 614 | 650 | |
|---|
| 615 | 651 | memset(req, 0, sizeof(*req)); |
|---|
| 616 | 652 | |
|---|
| 617 | | - /* currently we support only max 8 bit masks so no need to worry |
|---|
| 653 | + /* currently we support only max 24 bit masks so no need to worry |
|---|
| 618 | 654 | * about endian support |
|---|
| 619 | 655 | */ |
|---|
| 620 | | - req->upload_types[0] = mask; |
|---|
| 621 | | - req->reset_types[0] = mask; |
|---|
| 656 | + memcpy(req->upload_types, &mask, 3); |
|---|
| 657 | + memcpy(req->reset_types, &reset_mask, 3); |
|---|
| 622 | 658 | req->stat_type = HTT_STATS_REQ_CFG_STAT_TYPE_INVALID; |
|---|
| 623 | 659 | req->cookie_lsb = cpu_to_le32(cookie & 0xffffffff); |
|---|
| 624 | 660 | req->cookie_msb = cpu_to_le32((cookie & 0xffffffff00000000ULL) >> 32); |
|---|
| .. | .. |
|---|
| 937 | 973 | return 0; |
|---|
| 938 | 974 | } |
|---|
| 939 | 975 | |
|---|
| 940 | | -int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, |
|---|
| 941 | | - u8 max_subfrms_ampdu, |
|---|
| 942 | | - u8 max_subfrms_amsdu) |
|---|
| 976 | +static int ath10k_htt_send_rx_ring_cfg_hl(struct ath10k_htt *htt) |
|---|
| 977 | +{ |
|---|
| 978 | + struct ath10k *ar = htt->ar; |
|---|
| 979 | + struct sk_buff *skb; |
|---|
| 980 | + struct htt_cmd *cmd; |
|---|
| 981 | + struct htt_rx_ring_setup_ring32 *ring; |
|---|
| 982 | + const int num_rx_ring = 1; |
|---|
| 983 | + u16 flags; |
|---|
| 984 | + int len; |
|---|
| 985 | + int ret; |
|---|
| 986 | + |
|---|
| 987 | + /* |
|---|
| 988 | + * the HW expects the buffer to be an integral number of 4-byte |
|---|
| 989 | + * "words" |
|---|
| 990 | + */ |
|---|
| 991 | + BUILD_BUG_ON(!IS_ALIGNED(HTT_RX_BUF_SIZE, 4)); |
|---|
| 992 | + BUILD_BUG_ON((HTT_RX_BUF_SIZE & HTT_MAX_CACHE_LINE_SIZE_MASK) != 0); |
|---|
| 993 | + |
|---|
| 994 | + len = sizeof(cmd->hdr) + sizeof(cmd->rx_setup_32.hdr) |
|---|
| 995 | + + (sizeof(*ring) * num_rx_ring); |
|---|
| 996 | + skb = ath10k_htc_alloc_skb(ar, len); |
|---|
| 997 | + if (!skb) |
|---|
| 998 | + return -ENOMEM; |
|---|
| 999 | + |
|---|
| 1000 | + skb_put(skb, len); |
|---|
| 1001 | + |
|---|
| 1002 | + cmd = (struct htt_cmd *)skb->data; |
|---|
| 1003 | + ring = &cmd->rx_setup_32.rings[0]; |
|---|
| 1004 | + |
|---|
| 1005 | + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_RX_RING_CFG; |
|---|
| 1006 | + cmd->rx_setup_32.hdr.num_rings = 1; |
|---|
| 1007 | + |
|---|
| 1008 | + flags = 0; |
|---|
| 1009 | + flags |= HTT_RX_RING_FLAGS_MSDU_PAYLOAD; |
|---|
| 1010 | + flags |= HTT_RX_RING_FLAGS_UNICAST_RX; |
|---|
| 1011 | + flags |= HTT_RX_RING_FLAGS_MULTICAST_RX; |
|---|
| 1012 | + |
|---|
| 1013 | + memset(ring, 0, sizeof(*ring)); |
|---|
| 1014 | + ring->rx_ring_len = __cpu_to_le16(HTT_RX_RING_SIZE_MIN); |
|---|
| 1015 | + ring->rx_ring_bufsize = __cpu_to_le16(HTT_RX_BUF_SIZE); |
|---|
| 1016 | + ring->flags = __cpu_to_le16(flags); |
|---|
| 1017 | + |
|---|
| 1018 | + ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); |
|---|
| 1019 | + if (ret) { |
|---|
| 1020 | + dev_kfree_skb_any(skb); |
|---|
| 1021 | + return ret; |
|---|
| 1022 | + } |
|---|
| 1023 | + |
|---|
| 1024 | + return 0; |
|---|
| 1025 | +} |
|---|
| 1026 | + |
|---|
| 1027 | +static int ath10k_htt_h2t_aggr_cfg_msg_32(struct ath10k_htt *htt, |
|---|
| 1028 | + u8 max_subfrms_ampdu, |
|---|
| 1029 | + u8 max_subfrms_amsdu) |
|---|
| 943 | 1030 | { |
|---|
| 944 | 1031 | struct ath10k *ar = htt->ar; |
|---|
| 945 | 1032 | struct htt_aggr_conf *aggr_conf; |
|---|
| .. | .. |
|---|
| 968 | 1055 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG; |
|---|
| 969 | 1056 | |
|---|
| 970 | 1057 | aggr_conf = &cmd->aggr_conf; |
|---|
| 1058 | + aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu; |
|---|
| 1059 | + aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu; |
|---|
| 1060 | + |
|---|
| 1061 | + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d", |
|---|
| 1062 | + aggr_conf->max_num_amsdu_subframes, |
|---|
| 1063 | + aggr_conf->max_num_ampdu_subframes); |
|---|
| 1064 | + |
|---|
| 1065 | + ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); |
|---|
| 1066 | + if (ret) { |
|---|
| 1067 | + dev_kfree_skb_any(skb); |
|---|
| 1068 | + return ret; |
|---|
| 1069 | + } |
|---|
| 1070 | + |
|---|
| 1071 | + return 0; |
|---|
| 1072 | +} |
|---|
| 1073 | + |
|---|
| 1074 | +static int ath10k_htt_h2t_aggr_cfg_msg_v2(struct ath10k_htt *htt, |
|---|
| 1075 | + u8 max_subfrms_ampdu, |
|---|
| 1076 | + u8 max_subfrms_amsdu) |
|---|
| 1077 | +{ |
|---|
| 1078 | + struct ath10k *ar = htt->ar; |
|---|
| 1079 | + struct htt_aggr_conf_v2 *aggr_conf; |
|---|
| 1080 | + struct sk_buff *skb; |
|---|
| 1081 | + struct htt_cmd *cmd; |
|---|
| 1082 | + int len; |
|---|
| 1083 | + int ret; |
|---|
| 1084 | + |
|---|
| 1085 | + /* Firmware defaults are: amsdu = 3 and ampdu = 64 */ |
|---|
| 1086 | + |
|---|
| 1087 | + if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64) |
|---|
| 1088 | + return -EINVAL; |
|---|
| 1089 | + |
|---|
| 1090 | + if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31) |
|---|
| 1091 | + return -EINVAL; |
|---|
| 1092 | + |
|---|
| 1093 | + len = sizeof(cmd->hdr); |
|---|
| 1094 | + len += sizeof(cmd->aggr_conf_v2); |
|---|
| 1095 | + |
|---|
| 1096 | + skb = ath10k_htc_alloc_skb(ar, len); |
|---|
| 1097 | + if (!skb) |
|---|
| 1098 | + return -ENOMEM; |
|---|
| 1099 | + |
|---|
| 1100 | + skb_put(skb, len); |
|---|
| 1101 | + cmd = (struct htt_cmd *)skb->data; |
|---|
| 1102 | + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG; |
|---|
| 1103 | + |
|---|
| 1104 | + aggr_conf = &cmd->aggr_conf_v2; |
|---|
| 971 | 1105 | aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu; |
|---|
| 972 | 1106 | aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu; |
|---|
| 973 | 1107 | |
|---|
| .. | .. |
|---|
| 1075 | 1209 | int len = 0; |
|---|
| 1076 | 1210 | int msdu_id = -1; |
|---|
| 1077 | 1211 | int res; |
|---|
| 1212 | + const u8 *peer_addr; |
|---|
| 1078 | 1213 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; |
|---|
| 1079 | 1214 | |
|---|
| 1080 | 1215 | len += sizeof(cmd->hdr); |
|---|
| .. | .. |
|---|
| 1090 | 1225 | ieee80211_is_deauth(hdr->frame_control) || |
|---|
| 1091 | 1226 | ieee80211_is_disassoc(hdr->frame_control)) && |
|---|
| 1092 | 1227 | ieee80211_has_protected(hdr->frame_control)) { |
|---|
| 1093 | | - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); |
|---|
| 1228 | + peer_addr = hdr->addr1; |
|---|
| 1229 | + if (is_multicast_ether_addr(peer_addr)) { |
|---|
| 1230 | + skb_put(msdu, sizeof(struct ieee80211_mmie_16)); |
|---|
| 1231 | + } else { |
|---|
| 1232 | + if (skb_cb->ucast_cipher == WLAN_CIPHER_SUITE_GCMP || |
|---|
| 1233 | + skb_cb->ucast_cipher == WLAN_CIPHER_SUITE_GCMP_256) |
|---|
| 1234 | + skb_put(msdu, IEEE80211_GCMP_MIC_LEN); |
|---|
| 1235 | + else |
|---|
| 1236 | + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); |
|---|
| 1237 | + } |
|---|
| 1094 | 1238 | } |
|---|
| 1095 | 1239 | |
|---|
| 1096 | 1240 | txdesc = ath10k_htc_alloc_skb(ar, len); |
|---|
| .. | .. |
|---|
| 1126 | 1270 | return 0; |
|---|
| 1127 | 1271 | |
|---|
| 1128 | 1272 | err_unmap_msdu: |
|---|
| 1129 | | - dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
|---|
| 1273 | + if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) |
|---|
| 1274 | + dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
|---|
| 1130 | 1275 | err_free_txdesc: |
|---|
| 1131 | 1276 | dev_kfree_skb_any(txdesc); |
|---|
| 1132 | 1277 | err_free_msdu_id: |
|---|
| .. | .. |
|---|
| 1134 | 1279 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); |
|---|
| 1135 | 1280 | spin_unlock_bh(&htt->tx_lock); |
|---|
| 1136 | 1281 | err: |
|---|
| 1282 | + return res; |
|---|
| 1283 | +} |
|---|
| 1284 | + |
|---|
| 1285 | +#define HTT_TX_HL_NEEDED_HEADROOM \ |
|---|
| 1286 | + (unsigned int)(sizeof(struct htt_cmd_hdr) + \ |
|---|
| 1287 | + sizeof(struct htt_data_tx_desc) + \ |
|---|
| 1288 | + sizeof(struct ath10k_htc_hdr)) |
|---|
| 1289 | + |
|---|
| 1290 | +static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, |
|---|
| 1291 | + struct sk_buff *msdu) |
|---|
| 1292 | +{ |
|---|
| 1293 | + struct ath10k *ar = htt->ar; |
|---|
| 1294 | + int res, data_len; |
|---|
| 1295 | + struct htt_cmd_hdr *cmd_hdr; |
|---|
| 1296 | + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; |
|---|
| 1297 | + struct htt_data_tx_desc *tx_desc; |
|---|
| 1298 | + struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); |
|---|
| 1299 | + struct sk_buff *tmp_skb; |
|---|
| 1300 | + bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET); |
|---|
| 1301 | + u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu); |
|---|
| 1302 | + u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth); |
|---|
| 1303 | + u8 flags0 = 0; |
|---|
| 1304 | + u16 flags1 = 0; |
|---|
| 1305 | + u16 msdu_id = 0; |
|---|
| 1306 | + |
|---|
| 1307 | + if ((ieee80211_is_action(hdr->frame_control) || |
|---|
| 1308 | + ieee80211_is_deauth(hdr->frame_control) || |
|---|
| 1309 | + ieee80211_is_disassoc(hdr->frame_control)) && |
|---|
| 1310 | + ieee80211_has_protected(hdr->frame_control)) { |
|---|
| 1311 | + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); |
|---|
| 1312 | + } |
|---|
| 1313 | + |
|---|
| 1314 | + data_len = msdu->len; |
|---|
| 1315 | + |
|---|
| 1316 | + switch (txmode) { |
|---|
| 1317 | + case ATH10K_HW_TXRX_RAW: |
|---|
| 1318 | + case ATH10K_HW_TXRX_NATIVE_WIFI: |
|---|
| 1319 | + flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; |
|---|
| 1320 | + fallthrough; |
|---|
| 1321 | + case ATH10K_HW_TXRX_ETHERNET: |
|---|
| 1322 | + flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); |
|---|
| 1323 | + break; |
|---|
| 1324 | + case ATH10K_HW_TXRX_MGMT: |
|---|
| 1325 | + flags0 |= SM(ATH10K_HW_TXRX_MGMT, |
|---|
| 1326 | + HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); |
|---|
| 1327 | + flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; |
|---|
| 1328 | + |
|---|
| 1329 | + if (htt->disable_tx_comp) |
|---|
| 1330 | + flags1 |= HTT_DATA_TX_DESC_FLAGS1_TX_COMPLETE; |
|---|
| 1331 | + break; |
|---|
| 1332 | + } |
|---|
| 1333 | + |
|---|
| 1334 | + if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) |
|---|
| 1335 | + flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT; |
|---|
| 1336 | + |
|---|
| 1337 | + flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); |
|---|
| 1338 | + flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID); |
|---|
| 1339 | + if (msdu->ip_summed == CHECKSUM_PARTIAL && |
|---|
| 1340 | + !test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { |
|---|
| 1341 | + flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD; |
|---|
| 1342 | + flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD; |
|---|
| 1343 | + } |
|---|
| 1344 | + |
|---|
| 1345 | + /* Prepend the HTT header and TX desc struct to the data message |
|---|
| 1346 | + * and realloc the skb if it does not have enough headroom. |
|---|
| 1347 | + */ |
|---|
| 1348 | + if (skb_headroom(msdu) < HTT_TX_HL_NEEDED_HEADROOM) { |
|---|
| 1349 | + tmp_skb = msdu; |
|---|
| 1350 | + |
|---|
| 1351 | + ath10k_dbg(htt->ar, ATH10K_DBG_HTT, |
|---|
| 1352 | + "Not enough headroom in skb. Current headroom: %u, needed: %u. Reallocating...\n", |
|---|
| 1353 | + skb_headroom(msdu), HTT_TX_HL_NEEDED_HEADROOM); |
|---|
| 1354 | + msdu = skb_realloc_headroom(msdu, HTT_TX_HL_NEEDED_HEADROOM); |
|---|
| 1355 | + kfree_skb(tmp_skb); |
|---|
| 1356 | + if (!msdu) { |
|---|
| 1357 | + ath10k_warn(htt->ar, "htt hl tx: Unable to realloc skb!\n"); |
|---|
| 1358 | + res = -ENOMEM; |
|---|
| 1359 | + goto out; |
|---|
| 1360 | + } |
|---|
| 1361 | + } |
|---|
| 1362 | + |
|---|
| 1363 | + if (ar->bus_param.hl_msdu_ids) { |
|---|
| 1364 | + flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED; |
|---|
| 1365 | + res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); |
|---|
| 1366 | + if (res < 0) { |
|---|
| 1367 | + ath10k_err(ar, "msdu_id allocation failed %d\n", res); |
|---|
| 1368 | + goto out; |
|---|
| 1369 | + } |
|---|
| 1370 | + msdu_id = res; |
|---|
| 1371 | + } |
|---|
| 1372 | + |
|---|
| 1373 | + /* As msdu is freed by mac80211 (in ieee80211_tx_status()) and by |
|---|
| 1374 | + * ath10k (in ath10k_htt_htc_tx_complete()) we have to increase |
|---|
| 1375 | + * reference by one to avoid a use-after-free case and a double |
|---|
| 1376 | + * free. |
|---|
| 1377 | + */ |
|---|
| 1378 | + skb_get(msdu); |
|---|
| 1379 | + |
|---|
| 1380 | + skb_push(msdu, sizeof(*cmd_hdr)); |
|---|
| 1381 | + skb_push(msdu, sizeof(*tx_desc)); |
|---|
| 1382 | + cmd_hdr = (struct htt_cmd_hdr *)msdu->data; |
|---|
| 1383 | + tx_desc = (struct htt_data_tx_desc *)(msdu->data + sizeof(*cmd_hdr)); |
|---|
| 1384 | + |
|---|
| 1385 | + cmd_hdr->msg_type = HTT_H2T_MSG_TYPE_TX_FRM; |
|---|
| 1386 | + tx_desc->flags0 = flags0; |
|---|
| 1387 | + tx_desc->flags1 = __cpu_to_le16(flags1); |
|---|
| 1388 | + tx_desc->len = __cpu_to_le16(data_len); |
|---|
| 1389 | + tx_desc->id = __cpu_to_le16(msdu_id); |
|---|
| 1390 | + tx_desc->frags_paddr = 0; /* always zero */ |
|---|
| 1391 | + /* Initialize peer_id to INVALID_PEER because this is NOT |
|---|
| 1392 | + * Reinjection path |
|---|
| 1393 | + */ |
|---|
| 1394 | + tx_desc->peerid = __cpu_to_le32(HTT_INVALID_PEERID); |
|---|
| 1395 | + |
|---|
| 1396 | + res = ath10k_htc_send_hl(&htt->ar->htc, htt->eid, msdu); |
|---|
| 1397 | + |
|---|
| 1398 | +out: |
|---|
| 1137 | 1399 | return res; |
|---|
| 1138 | 1400 | } |
|---|
| 1139 | 1401 | |
|---|
| .. | .. |
|---|
| 1201 | 1463 | case ATH10K_HW_TXRX_RAW: |
|---|
| 1202 | 1464 | case ATH10K_HW_TXRX_NATIVE_WIFI: |
|---|
| 1203 | 1465 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; |
|---|
| 1204 | | - /* fall through */ |
|---|
| 1466 | + fallthrough; |
|---|
| 1205 | 1467 | case ATH10K_HW_TXRX_ETHERNET: |
|---|
| 1206 | 1468 | if (ar->hw_params.continuous_frag_desc) { |
|---|
| 1207 | 1469 | ext_desc_t = htt->frag_desc.vaddr_desc_32; |
|---|
| .. | .. |
|---|
| 1360 | 1622 | u16 msdu_id, flags1 = 0; |
|---|
| 1361 | 1623 | u16 freq = 0; |
|---|
| 1362 | 1624 | dma_addr_t frags_paddr = 0; |
|---|
| 1363 | | - u32 txbuf_paddr; |
|---|
| 1625 | + dma_addr_t txbuf_paddr; |
|---|
| 1364 | 1626 | struct htt_msdu_ext_desc_64 *ext_desc = NULL; |
|---|
| 1365 | 1627 | struct htt_msdu_ext_desc_64 *ext_desc_t = NULL; |
|---|
| 1366 | 1628 | |
|---|
| .. | .. |
|---|
| 1403 | 1665 | case ATH10K_HW_TXRX_RAW: |
|---|
| 1404 | 1666 | case ATH10K_HW_TXRX_NATIVE_WIFI: |
|---|
| 1405 | 1667 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; |
|---|
| 1406 | | - /* fall through */ |
|---|
| 1668 | + fallthrough; |
|---|
| 1407 | 1669 | case ATH10K_HW_TXRX_ETHERNET: |
|---|
| 1408 | 1670 | if (ar->hw_params.continuous_frag_desc) { |
|---|
| 1409 | 1671 | ext_desc_t = htt->frag_desc.vaddr_desc_64; |
|---|
| .. | .. |
|---|
| 1556 | 1818 | .htt_tx = ath10k_htt_tx_32, |
|---|
| 1557 | 1819 | .htt_alloc_txbuff = ath10k_htt_tx_alloc_cont_txbuf_32, |
|---|
| 1558 | 1820 | .htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_32, |
|---|
| 1821 | + .htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_32, |
|---|
| 1559 | 1822 | }; |
|---|
| 1560 | 1823 | |
|---|
| 1561 | 1824 | static const struct ath10k_htt_tx_ops htt_tx_ops_64 = { |
|---|
| .. | .. |
|---|
| 1566 | 1829 | .htt_tx = ath10k_htt_tx_64, |
|---|
| 1567 | 1830 | .htt_alloc_txbuff = ath10k_htt_tx_alloc_cont_txbuf_64, |
|---|
| 1568 | 1831 | .htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_64, |
|---|
| 1832 | + .htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_v2, |
|---|
| 1833 | +}; |
|---|
| 1834 | + |
|---|
| 1835 | +static const struct ath10k_htt_tx_ops htt_tx_ops_hl = { |
|---|
| 1836 | + .htt_send_rx_ring_cfg = ath10k_htt_send_rx_ring_cfg_hl, |
|---|
| 1837 | + .htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32, |
|---|
| 1838 | + .htt_tx = ath10k_htt_tx_hl, |
|---|
| 1839 | + .htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_32, |
|---|
| 1840 | + .htt_flush_tx = ath10k_htt_flush_tx_queue, |
|---|
| 1569 | 1841 | }; |
|---|
| 1570 | 1842 | |
|---|
| 1571 | 1843 | void ath10k_htt_set_tx_ops(struct ath10k_htt *htt) |
|---|
| 1572 | 1844 | { |
|---|
| 1573 | 1845 | struct ath10k *ar = htt->ar; |
|---|
| 1574 | 1846 | |
|---|
| 1575 | | - if (ar->hw_params.target_64bit) |
|---|
| 1847 | + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
|---|
| 1848 | + htt->tx_ops = &htt_tx_ops_hl; |
|---|
| 1849 | + else if (ar->hw_params.target_64bit) |
|---|
| 1576 | 1850 | htt->tx_ops = &htt_tx_ops_64; |
|---|
| 1577 | 1851 | else |
|---|
| 1578 | 1852 | htt->tx_ops = &htt_tx_ops_32; |
|---|