.. | .. |
---|
| 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; |
---|