Path: blob/main/sys/contrib/dev/athk/ath12k/dp_htt.c
283313 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/*2* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.3* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.4*/56#include "core.h"7#include "peer.h"8#include "htc.h"9#include "dp_htt.h"10#include "debugfs_htt_stats.h"11#include "debugfs.h"1213static void ath12k_dp_htt_htc_tx_complete(struct ath12k_base *ab,14struct sk_buff *skb)15{16dev_kfree_skb_any(skb);17}1819int ath12k_dp_htt_connect(struct ath12k_dp *dp)20{21struct ath12k_htc_svc_conn_req conn_req = {};22struct ath12k_htc_svc_conn_resp conn_resp = {};23int status;2425conn_req.ep_ops.ep_tx_complete = ath12k_dp_htt_htc_tx_complete;26conn_req.ep_ops.ep_rx_complete = ath12k_dp_htt_htc_t2h_msg_handler;2728/* connect to control service */29conn_req.service_id = ATH12K_HTC_SVC_ID_HTT_DATA_MSG;3031status = ath12k_htc_connect_service(&dp->ab->htc, &conn_req,32&conn_resp);3334if (status)35return status;3637dp->eid = conn_resp.eid;3839return 0;40}4142static int ath12k_get_ppdu_user_index(struct htt_ppdu_stats *ppdu_stats,43u16 peer_id)44{45int i;4647for (i = 0; i < HTT_PPDU_STATS_MAX_USERS - 1; i++) {48if (ppdu_stats->user_stats[i].is_valid_peer_id) {49if (peer_id == ppdu_stats->user_stats[i].peer_id)50return i;51} else {52return i;53}54}5556return -EINVAL;57}5859static int ath12k_htt_tlv_ppdu_stats_parse(struct ath12k_base *ab,60u16 tag, u16 len, const void *ptr,61void *data)62{63const struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *ba_status;64const struct htt_ppdu_stats_usr_cmpltn_cmn *cmplt_cmn;65const struct htt_ppdu_stats_user_rate *user_rate;66struct htt_ppdu_stats_info *ppdu_info;67struct htt_ppdu_user_stats *user_stats;68int cur_user;69u16 peer_id;7071ppdu_info = data;7273switch (tag) {74case HTT_PPDU_STATS_TAG_COMMON:75if (len < sizeof(struct htt_ppdu_stats_common)) {76ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",77len, tag);78return -EINVAL;79}80memcpy(&ppdu_info->ppdu_stats.common, ptr,81sizeof(struct htt_ppdu_stats_common));82break;83case HTT_PPDU_STATS_TAG_USR_RATE:84if (len < sizeof(struct htt_ppdu_stats_user_rate)) {85ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",86len, tag);87return -EINVAL;88}89user_rate = ptr;90peer_id = le16_to_cpu(user_rate->sw_peer_id);91cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,92peer_id);93if (cur_user < 0)94return -EINVAL;95user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];96user_stats->peer_id = peer_id;97user_stats->is_valid_peer_id = true;98memcpy(&user_stats->rate, ptr,99sizeof(struct htt_ppdu_stats_user_rate));100user_stats->tlv_flags |= BIT(tag);101break;102case HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON:103if (len < sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)) {104ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",105len, tag);106return -EINVAL;107}108109cmplt_cmn = ptr;110peer_id = le16_to_cpu(cmplt_cmn->sw_peer_id);111cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,112peer_id);113if (cur_user < 0)114return -EINVAL;115user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];116user_stats->peer_id = peer_id;117user_stats->is_valid_peer_id = true;118memcpy(&user_stats->cmpltn_cmn, ptr,119sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn));120user_stats->tlv_flags |= BIT(tag);121break;122case HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS:123if (len <124sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status)) {125ath12k_warn(ab, "Invalid len %d for the tag 0x%x\n",126len, tag);127return -EINVAL;128}129130ba_status = ptr;131peer_id = le16_to_cpu(ba_status->sw_peer_id);132cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats,133peer_id);134if (cur_user < 0)135return -EINVAL;136user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];137user_stats->peer_id = peer_id;138user_stats->is_valid_peer_id = true;139memcpy(&user_stats->ack_ba, ptr,140sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status));141user_stats->tlv_flags |= BIT(tag);142break;143}144return 0;145}146147int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,148int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,149const void *ptr, void *data),150void *data)151{152const struct htt_tlv *tlv;153const void *begin = ptr;154u16 tlv_tag, tlv_len;155int ret = -EINVAL;156157while (len > 0) {158if (len < sizeof(*tlv)) {159ath12k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",160ptr - begin, len, sizeof(*tlv));161return -EINVAL;162}163tlv = (struct htt_tlv *)ptr;164tlv_tag = le32_get_bits(tlv->header, HTT_TLV_TAG);165tlv_len = le32_get_bits(tlv->header, HTT_TLV_LEN);166ptr += sizeof(*tlv);167len -= sizeof(*tlv);168169if (tlv_len > len) {170ath12k_err(ab, "htt tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",171tlv_tag, ptr - begin, len, tlv_len);172return -EINVAL;173}174ret = iter(ab, tlv_tag, tlv_len, ptr, data);175if (ret == -ENOMEM)176return ret;177178ptr += tlv_len;179len -= tlv_len;180}181return 0;182}183184static void185ath12k_update_per_peer_tx_stats(struct ath12k_pdev_dp *dp_pdev,186struct htt_ppdu_stats *ppdu_stats, u8 user)187{188struct ath12k_dp *dp = dp_pdev->dp;189struct ath12k_base *ab = dp->ab;190struct ath12k_dp_link_peer *peer;191struct htt_ppdu_stats_user_rate *user_rate;192struct ath12k_per_peer_tx_stats *peer_stats = &dp_pdev->peer_tx_stats;193struct htt_ppdu_user_stats *usr_stats = &ppdu_stats->user_stats[user];194struct htt_ppdu_stats_common *common = &ppdu_stats->common;195int ret;196u8 flags, mcs, nss, bw, sgi, dcm, ppdu_type, rate_idx = 0;197u32 v, succ_bytes = 0;198u16 tones, rate = 0, succ_pkts = 0;199u32 tx_duration = 0;200u8 tid = HTT_PPDU_STATS_NON_QOS_TID;201u16 tx_retry_failed = 0, tx_retry_count = 0;202bool is_ampdu = false, is_ofdma;203204if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE)))205return;206207if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) {208is_ampdu =209HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);210tx_retry_failed =211__le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_tried) -212__le16_to_cpu(usr_stats->cmpltn_cmn.mpdu_success);213tx_retry_count =214HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +215HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);216}217218if (usr_stats->tlv_flags &219BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) {220succ_bytes = le32_to_cpu(usr_stats->ack_ba.success_bytes);221succ_pkts = le32_get_bits(usr_stats->ack_ba.info,222HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M);223tid = le32_get_bits(usr_stats->ack_ba.info,224HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM);225}226227if (common->fes_duration_us)228tx_duration = le32_to_cpu(common->fes_duration_us);229230user_rate = &usr_stats->rate;231flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags);232bw = HTT_USR_RATE_BW(user_rate->rate_flags) - 2;233nss = HTT_USR_RATE_NSS(user_rate->rate_flags) + 1;234mcs = HTT_USR_RATE_MCS(user_rate->rate_flags);235sgi = HTT_USR_RATE_GI(user_rate->rate_flags);236dcm = HTT_USR_RATE_DCM(user_rate->rate_flags);237238ppdu_type = HTT_USR_RATE_PPDU_TYPE(user_rate->info1);239is_ofdma = (ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA) ||240(ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA);241242/* Note: If host configured fixed rates and in some other special243* cases, the broadcast/management frames are sent in different rates.244* Firmware rate's control to be skipped for this?245*/246247if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) {248ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);249return;250}251252if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH12K_VHT_MCS_MAX) {253ath12k_warn(ab, "Invalid VHT mcs %d peer stats", mcs);254return;255}256257if (flags == WMI_RATE_PREAMBLE_HT && (mcs > ATH12K_HT_MCS_MAX || nss < 1)) {258ath12k_warn(ab, "Invalid HT mcs %d nss %d peer stats",259mcs, nss);260return;261}262263if (flags == WMI_RATE_PREAMBLE_CCK || flags == WMI_RATE_PREAMBLE_OFDM) {264ret = ath12k_mac_hw_ratecode_to_legacy_rate(mcs,265flags,266&rate_idx,267&rate);268if (ret < 0)269return;270}271272rcu_read_lock();273peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, usr_stats->peer_id);274275if (!peer || !peer->sta) {276rcu_read_unlock();277return;278}279280spin_lock_bh(&dp->dp_lock);281282memset(&peer->txrate, 0, sizeof(peer->txrate));283284peer->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw);285286switch (flags) {287case WMI_RATE_PREAMBLE_OFDM:288peer->txrate.legacy = rate;289break;290case WMI_RATE_PREAMBLE_CCK:291peer->txrate.legacy = rate;292break;293case WMI_RATE_PREAMBLE_HT:294peer->txrate.mcs = mcs + 8 * (nss - 1);295peer->txrate.flags = RATE_INFO_FLAGS_MCS;296if (sgi)297peer->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;298break;299case WMI_RATE_PREAMBLE_VHT:300peer->txrate.mcs = mcs;301peer->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;302if (sgi)303peer->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;304break;305case WMI_RATE_PREAMBLE_HE:306peer->txrate.mcs = mcs;307peer->txrate.flags = RATE_INFO_FLAGS_HE_MCS;308peer->txrate.he_dcm = dcm;309peer->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);310tones = le16_to_cpu(user_rate->ru_end) -311le16_to_cpu(user_rate->ru_start) + 1;312v = ath12k_he_ru_tones_to_nl80211_he_ru_alloc(tones);313peer->txrate.he_ru_alloc = v;314if (is_ofdma)315peer->txrate.bw = RATE_INFO_BW_HE_RU;316break;317case WMI_RATE_PREAMBLE_EHT:318peer->txrate.mcs = mcs;319peer->txrate.flags = RATE_INFO_FLAGS_EHT_MCS;320peer->txrate.he_dcm = dcm;321peer->txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(sgi);322tones = le16_to_cpu(user_rate->ru_end) -323le16_to_cpu(user_rate->ru_start) + 1;324v = ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(tones);325peer->txrate.eht_ru_alloc = v;326if (is_ofdma)327peer->txrate.bw = RATE_INFO_BW_EHT_RU;328break;329}330331peer->tx_retry_failed += tx_retry_failed;332peer->tx_retry_count += tx_retry_count;333peer->txrate.nss = nss;334peer->tx_duration += tx_duration;335memcpy(&peer->last_txrate, &peer->txrate, sizeof(struct rate_info));336337spin_unlock_bh(&dp->dp_lock);338339/* PPDU stats reported for mgmt packet doesn't have valid tx bytes.340* So skip peer stats update for mgmt packets.341*/342if (tid < HTT_PPDU_STATS_NON_QOS_TID) {343memset(peer_stats, 0, sizeof(*peer_stats));344peer_stats->succ_pkts = succ_pkts;345peer_stats->succ_bytes = succ_bytes;346peer_stats->is_ampdu = is_ampdu;347peer_stats->duration = tx_duration;348peer_stats->ba_fails =349HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) +350HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags);351}352353rcu_read_unlock();354}355356static void ath12k_htt_update_ppdu_stats(struct ath12k_pdev_dp *dp_pdev,357struct htt_ppdu_stats *ppdu_stats)358{359u8 user;360361for (user = 0; user < HTT_PPDU_STATS_MAX_USERS - 1; user++)362ath12k_update_per_peer_tx_stats(dp_pdev, ppdu_stats, user);363}364365static366struct htt_ppdu_stats_info *ath12k_dp_htt_get_ppdu_desc(struct ath12k_pdev_dp *dp_pdev,367u32 ppdu_id)368{369struct htt_ppdu_stats_info *ppdu_info;370371lockdep_assert_held(&dp_pdev->ppdu_list_lock);372if (!list_empty(&dp_pdev->ppdu_stats_info)) {373list_for_each_entry(ppdu_info, &dp_pdev->ppdu_stats_info, list) {374if (ppdu_info->ppdu_id == ppdu_id)375return ppdu_info;376}377378if (dp_pdev->ppdu_stat_list_depth > HTT_PPDU_DESC_MAX_DEPTH) {379ppdu_info = list_first_entry(&dp_pdev->ppdu_stats_info,380typeof(*ppdu_info), list);381list_del(&ppdu_info->list);382dp_pdev->ppdu_stat_list_depth--;383ath12k_htt_update_ppdu_stats(dp_pdev, &ppdu_info->ppdu_stats);384kfree(ppdu_info);385}386}387388ppdu_info = kzalloc_obj(*ppdu_info, GFP_ATOMIC);389if (!ppdu_info)390return NULL;391392list_add_tail(&ppdu_info->list, &dp_pdev->ppdu_stats_info);393dp_pdev->ppdu_stat_list_depth++;394395return ppdu_info;396}397398static void ath12k_copy_to_delay_stats(struct ath12k_dp_link_peer *peer,399struct htt_ppdu_user_stats *usr_stats)400{401peer->ppdu_stats_delayba.sw_peer_id = le16_to_cpu(usr_stats->rate.sw_peer_id);402peer->ppdu_stats_delayba.info0 = le32_to_cpu(usr_stats->rate.info0);403peer->ppdu_stats_delayba.ru_end = le16_to_cpu(usr_stats->rate.ru_end);404peer->ppdu_stats_delayba.ru_start = le16_to_cpu(usr_stats->rate.ru_start);405peer->ppdu_stats_delayba.info1 = le32_to_cpu(usr_stats->rate.info1);406peer->ppdu_stats_delayba.rate_flags = le32_to_cpu(usr_stats->rate.rate_flags);407peer->ppdu_stats_delayba.resp_rate_flags =408le32_to_cpu(usr_stats->rate.resp_rate_flags);409410peer->delayba_flag = true;411}412413static void ath12k_copy_to_bar(struct ath12k_dp_link_peer *peer,414struct htt_ppdu_user_stats *usr_stats)415{416usr_stats->rate.sw_peer_id = cpu_to_le16(peer->ppdu_stats_delayba.sw_peer_id);417usr_stats->rate.info0 = cpu_to_le32(peer->ppdu_stats_delayba.info0);418usr_stats->rate.ru_end = cpu_to_le16(peer->ppdu_stats_delayba.ru_end);419usr_stats->rate.ru_start = cpu_to_le16(peer->ppdu_stats_delayba.ru_start);420usr_stats->rate.info1 = cpu_to_le32(peer->ppdu_stats_delayba.info1);421usr_stats->rate.rate_flags = cpu_to_le32(peer->ppdu_stats_delayba.rate_flags);422usr_stats->rate.resp_rate_flags =423cpu_to_le32(peer->ppdu_stats_delayba.resp_rate_flags);424425peer->delayba_flag = false;426}427428static int ath12k_htt_pull_ppdu_stats(struct ath12k_base *ab,429struct sk_buff *skb)430{431struct ath12k_dp *dp = ath12k_ab_to_dp(ab);432struct ath12k_htt_ppdu_stats_msg *msg;433struct htt_ppdu_stats_info *ppdu_info;434struct ath12k_dp_link_peer *peer = NULL;435struct htt_ppdu_user_stats *usr_stats = NULL;436u32 peer_id = 0;437struct ath12k_pdev_dp *dp_pdev;438int ret, i;439u8 pdev_id, pdev_idx;440u32 ppdu_id, len;441442msg = (struct ath12k_htt_ppdu_stats_msg *)skb->data;443len = le32_get_bits(msg->info, HTT_T2H_PPDU_STATS_INFO_PAYLOAD_SIZE);444if (len > (skb->len - struct_size(msg, data, 0))) {445ath12k_warn(ab,446"HTT PPDU STATS event has unexpected payload size %u, should be smaller than %u\n",447len, skb->len);448return -EINVAL;449}450451pdev_id = le32_get_bits(msg->info, HTT_T2H_PPDU_STATS_INFO_PDEV_ID);452ppdu_id = le32_to_cpu(msg->ppdu_id);453454pdev_idx = DP_HW2SW_MACID(pdev_id);455if (pdev_idx >= MAX_RADIOS) {456ath12k_warn(ab, "HTT PPDU STATS invalid pdev id %u", pdev_id);457return -EINVAL;458}459460rcu_read_lock();461462dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);463if (!dp_pdev) {464ret = -EINVAL;465goto exit;466}467468spin_lock_bh(&dp_pdev->ppdu_list_lock);469ppdu_info = ath12k_dp_htt_get_ppdu_desc(dp_pdev, ppdu_id);470if (!ppdu_info) {471spin_unlock_bh(&dp_pdev->ppdu_list_lock);472ret = -EINVAL;473goto exit;474}475476ppdu_info->ppdu_id = ppdu_id;477ret = ath12k_dp_htt_tlv_iter(ab, msg->data, len,478ath12k_htt_tlv_ppdu_stats_parse,479(void *)ppdu_info);480if (ret) {481spin_unlock_bh(&dp_pdev->ppdu_list_lock);482ath12k_warn(ab, "Failed to parse tlv %d\n", ret);483goto exit;484}485486if (ppdu_info->ppdu_stats.common.num_users >= HTT_PPDU_STATS_MAX_USERS) {487spin_unlock_bh(&dp_pdev->ppdu_list_lock);488ath12k_warn(ab,489"HTT PPDU STATS event has unexpected num_users %u, should be smaller than %u\n",490ppdu_info->ppdu_stats.common.num_users,491HTT_PPDU_STATS_MAX_USERS);492ret = -EINVAL;493goto exit;494}495496/* back up data rate tlv for all peers */497if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_DATA &&498(ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON)) &&499ppdu_info->delay_ba) {500for (i = 0; i < ppdu_info->ppdu_stats.common.num_users; i++) {501peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;502peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id);503if (!peer)504continue;505506usr_stats = &ppdu_info->ppdu_stats.user_stats[i];507if (usr_stats->delay_ba)508ath12k_copy_to_delay_stats(peer, usr_stats);509}510}511512/* restore all peers' data rate tlv to mu-bar tlv */513if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_BAR &&514(ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON))) {515for (i = 0; i < ppdu_info->bar_num_users; i++) {516peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;517peer = ath12k_dp_link_peer_find_by_peerid(dp_pdev, peer_id);518if (!peer)519continue;520521usr_stats = &ppdu_info->ppdu_stats.user_stats[i];522if (peer->delayba_flag)523ath12k_copy_to_bar(peer, usr_stats);524}525}526527spin_unlock_bh(&dp_pdev->ppdu_list_lock);528529exit:530rcu_read_unlock();531532return ret;533}534535static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,536struct sk_buff *skb)537{538struct ath12k_htt_mlo_offset_msg *msg;539struct ath12k_pdev *pdev;540struct ath12k *ar;541u8 pdev_id;542543msg = (struct ath12k_htt_mlo_offset_msg *)skb->data;544pdev_id = u32_get_bits(__le32_to_cpu(msg->info),545HTT_T2H_MLO_OFFSET_INFO_PDEV_ID);546547rcu_read_lock();548ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);549if (!ar) {550/* It is possible that the ar is not yet active (started).551* The above function will only look for the active pdev552* and hence %NULL return is possible. Just silently553* discard this message554*/555goto exit;556}557558spin_lock_bh(&ar->data_lock);559pdev = ar->pdev;560561pdev->timestamp.info = __le32_to_cpu(msg->info);562pdev->timestamp.sync_timestamp_lo_us = __le32_to_cpu(msg->sync_timestamp_lo_us);563pdev->timestamp.sync_timestamp_hi_us = __le32_to_cpu(msg->sync_timestamp_hi_us);564pdev->timestamp.mlo_offset_lo = __le32_to_cpu(msg->mlo_offset_lo);565pdev->timestamp.mlo_offset_hi = __le32_to_cpu(msg->mlo_offset_hi);566pdev->timestamp.mlo_offset_clks = __le32_to_cpu(msg->mlo_offset_clks);567pdev->timestamp.mlo_comp_clks = __le32_to_cpu(msg->mlo_comp_clks);568pdev->timestamp.mlo_comp_timer = __le32_to_cpu(msg->mlo_comp_timer);569570spin_unlock_bh(&ar->data_lock);571exit:572rcu_read_unlock();573}574575void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,576struct sk_buff *skb)577{578struct ath12k_dp *dp = ath12k_ab_to_dp(ab);579struct htt_resp_msg *resp = (struct htt_resp_msg *)skb->data;580enum htt_t2h_msg_type type;581u16 peer_id;582u8 vdev_id;583u8 mac_addr[ETH_ALEN];584u16 peer_mac_h16;585u16 ast_hash = 0;586u16 hw_peer_id;587588type = le32_get_bits(resp->version_msg.version, HTT_T2H_MSG_TYPE);589590ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type);591592switch (type) {593case HTT_T2H_MSG_TYPE_VERSION_CONF:594dp->htt_tgt_ver_major = le32_get_bits(resp->version_msg.version,595HTT_T2H_VERSION_CONF_MAJOR);596dp->htt_tgt_ver_minor = le32_get_bits(resp->version_msg.version,597HTT_T2H_VERSION_CONF_MINOR);598complete(&dp->htt_tgt_version_received);599break;600/* TODO: remove unused peer map versions after testing */601case HTT_T2H_MSG_TYPE_PEER_MAP:602vdev_id = le32_get_bits(resp->peer_map_ev.info,603HTT_T2H_PEER_MAP_INFO_VDEV_ID);604peer_id = le32_get_bits(resp->peer_map_ev.info,605HTT_T2H_PEER_MAP_INFO_PEER_ID);606peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,607HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);608ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),609peer_mac_h16, mac_addr);610ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0);611break;612case HTT_T2H_MSG_TYPE_PEER_MAP2:613vdev_id = le32_get_bits(resp->peer_map_ev.info,614HTT_T2H_PEER_MAP_INFO_VDEV_ID);615peer_id = le32_get_bits(resp->peer_map_ev.info,616HTT_T2H_PEER_MAP_INFO_PEER_ID);617peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,618HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);619ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),620peer_mac_h16, mac_addr);621ast_hash = le32_get_bits(resp->peer_map_ev.info2,622HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL);623hw_peer_id = le32_get_bits(resp->peer_map_ev.info1,624HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID);625ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,626hw_peer_id);627break;628case HTT_T2H_MSG_TYPE_PEER_MAP3:629vdev_id = le32_get_bits(resp->peer_map_ev.info,630HTT_T2H_PEER_MAP_INFO_VDEV_ID);631peer_id = le32_get_bits(resp->peer_map_ev.info,632HTT_T2H_PEER_MAP_INFO_PEER_ID);633peer_mac_h16 = le32_get_bits(resp->peer_map_ev.info1,634HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);635ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),636peer_mac_h16, mac_addr);637ast_hash = le32_get_bits(resp->peer_map_ev.info2,638HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL);639hw_peer_id = le32_get_bits(resp->peer_map_ev.info2,640HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID);641ath12k_dp_link_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,642hw_peer_id);643break;644case HTT_T2H_MSG_TYPE_PEER_UNMAP:645case HTT_T2H_MSG_TYPE_PEER_UNMAP2:646peer_id = le32_get_bits(resp->peer_unmap_ev.info,647HTT_T2H_PEER_UNMAP_INFO_PEER_ID);648ath12k_dp_link_peer_unmap_event(ab, peer_id);649break;650case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:651ath12k_htt_pull_ppdu_stats(ab, skb);652break;653case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:654ath12k_debugfs_htt_ext_stats_handler(ab, skb);655break;656case HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:657ath12k_htt_mlo_offset_event_handler(ab, skb);658break;659default:660ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n",661type);662break;663}664665dev_kfree_skb_any(skb);666}667EXPORT_SYMBOL(ath12k_dp_htt_htc_t2h_msg_handler);668669static int670ath12k_dp_tx_get_ring_id_type(struct ath12k_base *ab,671int mac_id, u32 ring_id,672enum hal_ring_type ring_type,673enum htt_srng_ring_type *htt_ring_type,674enum htt_srng_ring_id *htt_ring_id)675{676int ret = 0;677678switch (ring_type) {679case HAL_RXDMA_BUF:680/* for some targets, host fills rx buffer to fw and fw fills to681* rxbuf ring for each rxdma682*/683if (!ab->hw_params->rx_mac_buf_ring) {684if (!(ring_id == HAL_SRNG_SW2RXDMA_BUF0 ||685ring_id == HAL_SRNG_SW2RXDMA_BUF1)) {686ret = -EINVAL;687}688*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;689*htt_ring_type = HTT_SW_TO_HW_RING;690} else {691if (ring_id == HAL_SRNG_SW2RXDMA_BUF0) {692*htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;693*htt_ring_type = HTT_SW_TO_SW_RING;694} else {695*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;696*htt_ring_type = HTT_SW_TO_HW_RING;697}698}699break;700case HAL_RXDMA_DST:701*htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;702*htt_ring_type = HTT_HW_TO_SW_RING;703break;704case HAL_RXDMA_MONITOR_BUF:705*htt_ring_id = HTT_RX_MON_HOST2MON_BUF_RING;706*htt_ring_type = HTT_SW_TO_HW_RING;707break;708case HAL_RXDMA_MONITOR_STATUS:709*htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;710*htt_ring_type = HTT_SW_TO_HW_RING;711break;712case HAL_RXDMA_MONITOR_DST:713*htt_ring_id = HTT_RX_MON_MON2HOST_DEST_RING;714*htt_ring_type = HTT_HW_TO_SW_RING;715break;716case HAL_RXDMA_MONITOR_DESC:717*htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;718*htt_ring_type = HTT_SW_TO_HW_RING;719break;720default:721ath12k_warn(ab, "Unsupported ring type in DP :%d\n", ring_type);722ret = -EINVAL;723}724return ret;725}726727int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id,728int mac_id, enum hal_ring_type ring_type)729{730struct ath12k_dp *dp = ath12k_ab_to_dp(ab);731struct htt_srng_setup_cmd *cmd;732struct hal_srng *srng = &ab->hal.srng_list[ring_id];733struct hal_srng_params params;734struct sk_buff *skb;735u32 ring_entry_sz;736int len = sizeof(*cmd);737dma_addr_t hp_addr, tp_addr;738enum htt_srng_ring_type htt_ring_type;739enum htt_srng_ring_id htt_ring_id;740int ret;741742skb = ath12k_htc_alloc_skb(ab, len);743if (!skb)744return -ENOMEM;745746memset(¶ms, 0, sizeof(params));747ath12k_hal_srng_get_params(ab, srng, ¶ms);748749hp_addr = ath12k_hal_srng_get_hp_addr(ab, srng);750tp_addr = ath12k_hal_srng_get_tp_addr(ab, srng);751752ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,753ring_type, &htt_ring_type,754&htt_ring_id);755if (ret)756goto err_free;757758skb_put(skb, len);759cmd = (struct htt_srng_setup_cmd *)skb->data;760cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_SRING_SETUP,761HTT_SRNG_SETUP_CMD_INFO0_MSG_TYPE);762if (htt_ring_type == HTT_SW_TO_HW_RING ||763htt_ring_type == HTT_HW_TO_SW_RING)764cmd->info0 |= le32_encode_bits(DP_SW2HW_MACID(mac_id),765HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);766else767cmd->info0 |= le32_encode_bits(mac_id,768HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID);769cmd->info0 |= le32_encode_bits(htt_ring_type,770HTT_SRNG_SETUP_CMD_INFO0_RING_TYPE);771cmd->info0 |= le32_encode_bits(htt_ring_id,772HTT_SRNG_SETUP_CMD_INFO0_RING_ID);773774cmd->ring_base_addr_lo = cpu_to_le32(params.ring_base_paddr &775HAL_ADDR_LSB_REG_MASK);776777cmd->ring_base_addr_hi = cpu_to_le32((u64)params.ring_base_paddr >>778HAL_ADDR_MSB_REG_SHIFT);779780ret = ath12k_hal_srng_get_entrysize(ab, ring_type);781if (ret < 0)782goto err_free;783784ring_entry_sz = ret;785786ring_entry_sz >>= 2;787cmd->info1 = le32_encode_bits(ring_entry_sz,788HTT_SRNG_SETUP_CMD_INFO1_RING_ENTRY_SIZE);789cmd->info1 |= le32_encode_bits(params.num_entries * ring_entry_sz,790HTT_SRNG_SETUP_CMD_INFO1_RING_SIZE);791cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),792HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_MSI_SWAP);793cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),794HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_TLV_SWAP);795cmd->info1 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_RING_PTR_SWAP),796HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_HOST_FW_SWAP);797if (htt_ring_type == HTT_SW_TO_HW_RING)798cmd->info1 |= cpu_to_le32(HTT_SRNG_SETUP_CMD_INFO1_RING_LOOP_CNT_DIS);799800cmd->ring_head_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(hp_addr));801cmd->ring_head_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(hp_addr));802803cmd->ring_tail_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(tp_addr));804cmd->ring_tail_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(tp_addr));805806cmd->ring_msi_addr_lo = cpu_to_le32(lower_32_bits(params.msi_addr));807cmd->ring_msi_addr_hi = cpu_to_le32(upper_32_bits(params.msi_addr));808cmd->msi_data = cpu_to_le32(params.msi_data);809810cmd->intr_info =811le32_encode_bits(params.intr_batch_cntr_thres_entries * ring_entry_sz,812HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH);813cmd->intr_info |=814le32_encode_bits(params.intr_timer_thres_us >> 3,815HTT_SRNG_SETUP_CMD_INTR_INFO_INTR_TIMER_THRESH);816817cmd->info2 = 0;818if (params.flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {819cmd->info2 = le32_encode_bits(params.low_threshold,820HTT_SRNG_SETUP_CMD_INFO2_INTR_LOW_THRESH);821}822823ath12k_dbg(ab, ATH12K_DBG_HAL,824"%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n",825__func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,826cmd->msi_data);827828ath12k_dbg(ab, ATH12K_DBG_HAL,829"ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n",830ring_id, ring_type, cmd->intr_info, cmd->info2);831832ret = ath12k_htc_send(&ab->htc, dp->eid, skb);833if (ret)834goto err_free;835836return 0;837838err_free:839dev_kfree_skb_any(skb);840841return ret;842}843844int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab)845{846struct ath12k_dp *dp = ath12k_ab_to_dp(ab);847struct sk_buff *skb;848struct htt_ver_req_cmd *cmd;849int len = sizeof(*cmd);850u32 metadata_version;851int ret;852853init_completion(&dp->htt_tgt_version_received);854855skb = ath12k_htc_alloc_skb(ab, len);856if (!skb)857return -ENOMEM;858859skb_put(skb, len);860cmd = (struct htt_ver_req_cmd *)skb->data;861cmd->ver_reg_info = le32_encode_bits(HTT_H2T_MSG_TYPE_VERSION_REQ,862HTT_OPTION_TAG);863metadata_version = ath12k_ftm_mode ? HTT_OPTION_TCL_METADATA_VER_V1 :864HTT_OPTION_TCL_METADATA_VER_V2;865866cmd->tcl_metadata_version = le32_encode_bits(HTT_TAG_TCL_METADATA_VERSION,867HTT_OPTION_TAG) |868le32_encode_bits(HTT_TCL_METADATA_VER_SZ,869HTT_OPTION_LEN) |870le32_encode_bits(metadata_version,871HTT_OPTION_VALUE);872873ret = ath12k_htc_send(&ab->htc, dp->eid, skb);874if (ret) {875dev_kfree_skb_any(skb);876return ret;877}878879ret = wait_for_completion_timeout(&dp->htt_tgt_version_received,880HTT_TARGET_VERSION_TIMEOUT_HZ);881if (ret == 0) {882ath12k_warn(ab, "htt target version request timed out\n");883return -ETIMEDOUT;884}885886if (dp->htt_tgt_ver_major != HTT_TARGET_VERSION_MAJOR) {887ath12k_err(ab, "unsupported htt major version %d supported version is %d\n",888dp->htt_tgt_ver_major, HTT_TARGET_VERSION_MAJOR);889return -EOPNOTSUPP;890}891892return 0;893}894895int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask)896{897struct ath12k_base *ab = ar->ab;898struct ath12k_dp *dp = ath12k_ab_to_dp(ab);899struct sk_buff *skb;900struct htt_ppdu_stats_cfg_cmd *cmd;901int len = sizeof(*cmd);902u8 pdev_mask;903int ret;904int i;905906for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {907skb = ath12k_htc_alloc_skb(ab, len);908if (!skb)909return -ENOMEM;910911skb_put(skb, len);912cmd = (struct htt_ppdu_stats_cfg_cmd *)skb->data;913cmd->msg = le32_encode_bits(HTT_H2T_MSG_TYPE_PPDU_STATS_CFG,914HTT_PPDU_STATS_CFG_MSG_TYPE);915916pdev_mask = 1 << (i + ar->pdev_idx);917cmd->msg |= le32_encode_bits(pdev_mask, HTT_PPDU_STATS_CFG_PDEV_ID);918cmd->msg |= le32_encode_bits(mask, HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK);919920ret = ath12k_htc_send(&ab->htc, dp->eid, skb);921if (ret) {922dev_kfree_skb_any(skb);923return ret;924}925}926927return 0;928}929930int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id,931int mac_id, enum hal_ring_type ring_type,932int rx_buf_size,933struct htt_rx_ring_tlv_filter *tlv_filter)934{935struct ath12k_dp *dp = ath12k_ab_to_dp(ab);936struct htt_rx_ring_selection_cfg_cmd *cmd;937struct hal_srng *srng = &ab->hal.srng_list[ring_id];938struct hal_srng_params params;939struct sk_buff *skb;940int len = sizeof(*cmd);941enum htt_srng_ring_type htt_ring_type;942enum htt_srng_ring_id htt_ring_id;943int ret;944945skb = ath12k_htc_alloc_skb(ab, len);946if (!skb)947return -ENOMEM;948949memset(¶ms, 0, sizeof(params));950ath12k_hal_srng_get_params(ab, srng, ¶ms);951952ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,953ring_type, &htt_ring_type,954&htt_ring_id);955if (ret)956goto err_free;957958skb_put(skb, len);959cmd = (struct htt_rx_ring_selection_cfg_cmd *)skb->data;960cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG,961HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);962if (htt_ring_type == HTT_SW_TO_HW_RING ||963htt_ring_type == HTT_HW_TO_SW_RING)964cmd->info0 |=965le32_encode_bits(DP_SW2HW_MACID(mac_id),966HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);967else968cmd->info0 |=969le32_encode_bits(mac_id,970HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);971cmd->info0 |= le32_encode_bits(htt_ring_id,972HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);973cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),974HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS);975cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),976HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS);977cmd->info0 |= le32_encode_bits(tlv_filter->offset_valid,978HTT_RX_RING_SELECTION_CFG_CMD_INFO0_OFFSET_VALID);979cmd->info0 |=980le32_encode_bits(tlv_filter->drop_threshold_valid,981HTT_RX_RING_SELECTION_CFG_CMD_INFO0_DROP_THRES_VAL);982cmd->info0 |= le32_encode_bits(!tlv_filter->rxmon_disable,983HTT_RX_RING_SELECTION_CFG_CMD_INFO0_EN_RXMON);984985cmd->info1 = le32_encode_bits(rx_buf_size,986HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE);987cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_mgmt,988HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT);989cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_ctrl,990HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL);991cmd->info1 |= le32_encode_bits(tlv_filter->conf_len_data,992HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA);993cmd->pkt_type_en_flags0 = cpu_to_le32(tlv_filter->pkt_filter_flags0);994cmd->pkt_type_en_flags1 = cpu_to_le32(tlv_filter->pkt_filter_flags1);995cmd->pkt_type_en_flags2 = cpu_to_le32(tlv_filter->pkt_filter_flags2);996cmd->pkt_type_en_flags3 = cpu_to_le32(tlv_filter->pkt_filter_flags3);997cmd->rx_filter_tlv = cpu_to_le32(tlv_filter->rx_filter);998999cmd->info2 = le32_encode_bits(tlv_filter->rx_drop_threshold,1000HTT_RX_RING_SELECTION_CFG_CMD_INFO2_DROP_THRESHOLD);1001cmd->info2 |=1002le32_encode_bits(tlv_filter->enable_log_mgmt_type,1003HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_MGMT_TYPE);1004cmd->info2 |=1005le32_encode_bits(tlv_filter->enable_log_ctrl_type,1006HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_CTRL_TYPE);1007cmd->info2 |=1008le32_encode_bits(tlv_filter->enable_log_data_type,1009HTT_RX_RING_SELECTION_CFG_CMD_INFO2_EN_LOG_DATA_TYPE);10101011cmd->info3 =1012le32_encode_bits(tlv_filter->enable_rx_tlv_offset,1013HTT_RX_RING_SELECTION_CFG_CMD_INFO3_EN_TLV_PKT_OFFSET);1014cmd->info3 |=1015le32_encode_bits(tlv_filter->rx_tlv_offset,1016HTT_RX_RING_SELECTION_CFG_CMD_INFO3_PKT_TLV_OFFSET);10171018if (tlv_filter->offset_valid) {1019cmd->rx_packet_offset =1020le32_encode_bits(tlv_filter->rx_packet_offset,1021HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET);10221023cmd->rx_packet_offset |=1024le32_encode_bits(tlv_filter->rx_header_offset,1025HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET);10261027cmd->rx_mpdu_offset =1028le32_encode_bits(tlv_filter->rx_mpdu_end_offset,1029HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET);10301031cmd->rx_mpdu_offset |=1032le32_encode_bits(tlv_filter->rx_mpdu_start_offset,1033HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET);10341035cmd->rx_msdu_offset =1036le32_encode_bits(tlv_filter->rx_msdu_end_offset,1037HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET);10381039cmd->rx_msdu_offset |=1040le32_encode_bits(tlv_filter->rx_msdu_start_offset,1041HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET);10421043cmd->rx_attn_offset =1044le32_encode_bits(tlv_filter->rx_attn_offset,1045HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET);1046}10471048if (tlv_filter->rx_mpdu_start_wmask > 0 &&1049tlv_filter->rx_msdu_end_wmask > 0) {1050cmd->info2 |=1051le32_encode_bits(true,1052HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET);1053cmd->rx_mpdu_start_end_mask =1054le32_encode_bits(tlv_filter->rx_mpdu_start_wmask,1055HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK);1056/* mpdu_end is not used for any hardwares so far1057* please assign it in future if any chip is1058* using through hal ops1059*/1060cmd->rx_mpdu_start_end_mask |=1061le32_encode_bits(tlv_filter->rx_mpdu_end_wmask,1062HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK);1063cmd->rx_msdu_end_word_mask =1064le32_encode_bits(tlv_filter->rx_msdu_end_wmask,1065HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK);1066}10671068ret = ath12k_htc_send(&ab->htc, dp->eid, skb);1069if (ret)1070goto err_free;10711072return 0;10731074err_free:1075dev_kfree_skb_any(skb);10761077return ret;1078}1079EXPORT_SYMBOL(ath12k_dp_tx_htt_rx_filter_setup);10801081int1082ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,1083struct htt_ext_stats_cfg_params *cfg_params,1084u64 cookie)1085{1086struct ath12k_base *ab = ar->ab;1087struct ath12k_dp *dp = ath12k_ab_to_dp(ab);1088struct sk_buff *skb;1089struct htt_ext_stats_cfg_cmd *cmd;1090int len = sizeof(*cmd);1091int ret;1092u32 pdev_id;10931094skb = ath12k_htc_alloc_skb(ab, len);1095if (!skb)1096return -ENOMEM;10971098skb_put(skb, len);10991100cmd = (struct htt_ext_stats_cfg_cmd *)skb->data;1101memset(cmd, 0, sizeof(*cmd));1102cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;11031104pdev_id = ath12k_mac_get_target_pdev_id(ar);1105cmd->hdr.pdev_mask = 1 << pdev_id;11061107cmd->hdr.stats_type = type;1108cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0);1109cmd->cfg_param1 = cpu_to_le32(cfg_params->cfg1);1110cmd->cfg_param2 = cpu_to_le32(cfg_params->cfg2);1111cmd->cfg_param3 = cpu_to_le32(cfg_params->cfg3);1112cmd->cookie_lsb = cpu_to_le32(lower_32_bits(cookie));1113cmd->cookie_msb = cpu_to_le32(upper_32_bits(cookie));11141115ret = ath12k_htc_send(&ab->htc, dp->eid, skb);1116if (ret) {1117ath12k_warn(ab, "failed to send htt type stats request: %d",1118ret);1119dev_kfree_skb_any(skb);1120return ret;1121}11221123return 0;1124}11251126int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset)1127{1128struct ath12k_base *ab = ar->ab;1129int ret;11301131ret = ath12k_dp_tx_htt_rx_monitor_mode_ring_config(ar, reset);1132if (ret) {1133ath12k_err(ab, "failed to setup rx monitor filter %d\n", ret);1134return ret;1135}11361137return 0;1138}11391140int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset)1141{1142struct ath12k_base *ab = ar->ab;1143struct ath12k_dp *dp = ath12k_ab_to_dp(ab);1144struct htt_rx_ring_tlv_filter tlv_filter = {};1145int ret, ring_id, i;11461147tlv_filter.offset_valid = false;11481149if (!reset) {1150tlv_filter.rx_filter = HTT_RX_MON_FILTER_TLV_FLAGS_MON_DEST_RING;11511152tlv_filter.drop_threshold_valid = true;1153tlv_filter.rx_drop_threshold = HTT_RX_RING_TLV_DROP_THRESHOLD_VALUE;11541155tlv_filter.enable_log_mgmt_type = true;1156tlv_filter.enable_log_ctrl_type = true;1157tlv_filter.enable_log_data_type = true;11581159tlv_filter.conf_len_ctrl = HTT_RX_RING_DEFAULT_DMA_LENGTH;1160tlv_filter.conf_len_mgmt = HTT_RX_RING_DEFAULT_DMA_LENGTH;1161tlv_filter.conf_len_data = HTT_RX_RING_DEFAULT_DMA_LENGTH;11621163tlv_filter.enable_rx_tlv_offset = true;1164tlv_filter.rx_tlv_offset = HTT_RX_RING_PKT_TLV_OFFSET;11651166tlv_filter.pkt_filter_flags0 =1167HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 |1168HTT_RX_MON_MO_MGMT_FILTER_FLAGS0;1169tlv_filter.pkt_filter_flags1 =1170HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 |1171HTT_RX_MON_MO_MGMT_FILTER_FLAGS1;1172tlv_filter.pkt_filter_flags2 =1173HTT_RX_MON_FP_CTRL_FILTER_FLASG2 |1174HTT_RX_MON_MO_CTRL_FILTER_FLASG2;1175tlv_filter.pkt_filter_flags3 =1176HTT_RX_MON_FP_CTRL_FILTER_FLASG3 |1177HTT_RX_MON_MO_CTRL_FILTER_FLASG3 |1178HTT_RX_MON_FP_DATA_FILTER_FLASG3 |1179HTT_RX_MON_MO_DATA_FILTER_FLASG3;1180} else {1181tlv_filter = ath12k_mac_mon_status_filter_default;11821183if (ath12k_debugfs_is_extd_rx_stats_enabled(ar))1184tlv_filter.rx_filter = ath12k_debugfs_rx_filter(ar);1185}11861187if (ab->hw_params->rxdma1_enable) {1188for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {1189ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id;1190ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,1191ar->dp.mac_id + i,1192HAL_RXDMA_MONITOR_DST,1193DP_RXDMA_REFILL_RING_SIZE,1194&tlv_filter);1195if (ret) {1196ath12k_err(ab,1197"failed to setup filter for monitor buf %d\n",1198ret);1199return ret;1200}1201}1202return 0;1203}12041205if (!reset) {1206for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {1207ring_id = dp->rx_mac_buf_ring[i].ring_id;1208ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,1209i,1210HAL_RXDMA_BUF,1211DP_RXDMA_REFILL_RING_SIZE,1212&tlv_filter);1213if (ret) {1214ath12k_err(ab,1215"failed to setup filter for mon rx buf %d\n",1216ret);1217return ret;1218}1219}1220}12211222for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {1223ring_id = dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;1224if (!reset) {1225tlv_filter.rx_filter =1226HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;1227}12281229ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id,1230i,1231HAL_RXDMA_MONITOR_STATUS,1232RX_MON_STATUS_BUF_SIZE,1233&tlv_filter);1234if (ret) {1235ath12k_err(ab,1236"failed to setup filter for mon status buf %d\n",1237ret);1238return ret;1239}1240}12411242return 0;1243}12441245int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id,1246int mac_id, enum hal_ring_type ring_type,1247int tx_buf_size,1248struct htt_tx_ring_tlv_filter *htt_tlv_filter)1249{1250struct ath12k_dp *dp = ath12k_ab_to_dp(ab);1251struct htt_tx_ring_selection_cfg_cmd *cmd;1252struct hal_srng *srng = &ab->hal.srng_list[ring_id];1253struct hal_srng_params params;1254struct sk_buff *skb;1255int len = sizeof(*cmd);1256enum htt_srng_ring_type htt_ring_type;1257enum htt_srng_ring_id htt_ring_id;1258int ret;12591260skb = ath12k_htc_alloc_skb(ab, len);1261if (!skb)1262return -ENOMEM;12631264memset(¶ms, 0, sizeof(params));1265ath12k_hal_srng_get_params(ab, srng, ¶ms);12661267ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id,1268ring_type, &htt_ring_type,1269&htt_ring_id);12701271if (ret)1272goto err_free;12731274skb_put(skb, len);1275cmd = (struct htt_tx_ring_selection_cfg_cmd *)skb->data;1276cmd->info0 = le32_encode_bits(HTT_H2T_MSG_TYPE_TX_MONITOR_CFG,1277HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE);1278if (htt_ring_type == HTT_SW_TO_HW_RING ||1279htt_ring_type == HTT_HW_TO_SW_RING)1280cmd->info0 |=1281le32_encode_bits(DP_SW2HW_MACID(mac_id),1282HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);1283else1284cmd->info0 |=1285le32_encode_bits(mac_id,1286HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID);1287cmd->info0 |= le32_encode_bits(htt_ring_id,1288HTT_TX_RING_SELECTION_CFG_CMD_INFO0_RING_ID);1289cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP),1290HTT_TX_RING_SELECTION_CFG_CMD_INFO0_SS);1291cmd->info0 |= le32_encode_bits(!!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP),1292HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PS);12931294cmd->info1 |=1295le32_encode_bits(tx_buf_size,1296HTT_TX_RING_SELECTION_CFG_CMD_INFO1_RING_BUFF_SIZE);12971298if (htt_tlv_filter->tx_mon_mgmt_filter) {1299cmd->info1 |=1300le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,1301HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);1302cmd->info1 |=1303le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,1304HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT);1305cmd->info2 |=1306le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT,1307HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);1308}13091310if (htt_tlv_filter->tx_mon_data_filter) {1311cmd->info1 |=1312le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,1313HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);1314cmd->info1 |=1315le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,1316HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL);1317cmd->info2 |=1318le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL,1319HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);1320}13211322if (htt_tlv_filter->tx_mon_ctrl_filter) {1323cmd->info1 |=1324le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,1325HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE);1326cmd->info1 |=1327le32_encode_bits(htt_tlv_filter->tx_mon_pkt_dma_len,1328HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA);1329cmd->info2 |=1330le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA,1331HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG);1332}13331334cmd->tlv_filter_mask_in0 =1335cpu_to_le32(htt_tlv_filter->tx_mon_downstream_tlv_flags);1336cmd->tlv_filter_mask_in1 =1337cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags0);1338cmd->tlv_filter_mask_in2 =1339cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags1);1340cmd->tlv_filter_mask_in3 =1341cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags2);13421343ret = ath12k_htc_send(&ab->htc, dp->eid, skb);1344if (ret)1345goto err_free;13461347return 0;13481349err_free:1350dev_kfree_skb_any(skb);1351return ret;1352}135313541355