return ab->dp;
}
+static inline struct ath12k *ath12k_pdev_dp_to_ar(struct ath12k_pdev_dp *dp)
+{
+ return container_of(dp, struct ath12k, dp);
+}
#endif /* _CORE_H_ */
void ath12k_dp_pdev_free(struct ath12k_base *ab)
{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k *ar;
int i;
+ for (i = 0; i < ab->num_radios; i++) {
+ ar = ab->pdevs[i].ar;
+ rcu_assign_pointer(dp->dp_pdevs[ar->pdev_idx], NULL);
+ }
+
+ synchronize_rcu();
+
for (i = 0; i < ab->num_radios; i++)
ath12k_dp_rx_pdev_free(ab, i);
}
int ath12k_dp_pdev_alloc(struct ath12k_base *ab)
{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_pdev_dp *dp_pdev;
struct ath12k *ar;
int ret;
int i;
/* TODO: Per-pdev rx ring unlike tx ring which is mapped to different AC's */
for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar;
+
+ dp_pdev = &ar->dp;
+
+ dp_pdev->hw = ar->ah->hw;
+ dp_pdev->dp = dp;
+ dp_pdev->hw_link_id = ar->hw_link_id;
+
ret = ath12k_dp_rx_pdev_alloc(ab, i);
if (ret) {
ath12k_warn(ab, "failed to allocate pdev rx for pdev_id :%d\n",
}
}
+ for (i = 0; i < ab->num_radios; i++) {
+ ar = ab->pdevs[i].ar;
+ rcu_assign_pointer(dp->dp_pdevs[ar->pdev_idx], &ar->dp);
+ }
+
return 0;
err:
ath12k_dp_pdev_free(ab);
u32 mac_id;
atomic_t num_tx_pending;
wait_queue_head_t tx_empty_waitq;
+
+ struct ath12k_dp *dp;
+ struct ieee80211_hw *hw;
+ u8 hw_link_id;
+
struct dp_srng rxdma_mon_dst_ring[MAX_RXDMA_PER_PDEV];
struct dp_srng tx_mon_dst_ring[MAX_RXDMA_PER_PDEV];
const struct ath12k_hw_params *hw_params;
struct device *dev;
+ /* RCU on dp_pdevs[] provides a teardown synchronization mechanism,
+ * ensuring in-flight data path readers complete before reclaim. Writers
+ * update internal fields under their own synchronization, while readers of
+ * internal fields may perform lockless read if occasional inconsistency
+ * is acceptable or use additional synchronization for a coherent view.
+ *
+ * RCU is used for dp_pdevs[] at this stage to align with
+ * ab->pdevs_active[]. However, if the teardown paths ensure quiescence,
+ * both dp_pdevs[] and pdevs_active[] can be converted to plain pointers,
+ * removing RCU synchronize overhead.
+ *
+ * TODO: evaluate removal of RCU from dp_pdevs in the future
+ */
+ struct ath12k_pdev_dp __rcu *dp_pdevs[MAX_RADIOS];
+
struct ath12k_hw_group *ag;
u8 device_id;
return dp->ops->service_srng(dp, irq_grp, budget);
}
+static inline struct ieee80211_hw *
+ath12k_pdev_dp_to_hw(struct ath12k_pdev_dp *pdev)
+{
+ return pdev->hw;
+}
+
+static inline struct ath12k_pdev_dp *
+ath12k_dp_to_pdev_dp(struct ath12k_dp *dp, u8 pdev_idx)
+{
+ RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
+ "ath12k dp to dp pdev called without rcu lock");
+
+ return rcu_dereference(dp->dp_pdevs[pdev_idx]);
+}
+
void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif);
void ath12k_dp_cc_config(struct ath12k_base *ab);
void ath12k_dp_partner_cc_init(struct ath12k_base *ab);
}
static enum hal_rx_mon_status
-ath12k_dp_mon_rx_parse_status_tlv(struct ath12k *ar,
+ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
const struct hal_tlv_64_hdr *tlv)
{
}
static void
-ath12k_dp_mon_fill_rx_stats_info(struct ath12k *ar,
- struct hal_rx_mon_ppdu_info *ppdu_info,
+ath12k_dp_mon_fill_rx_stats_info(struct hal_rx_mon_ppdu_info *ppdu_info,
struct ieee80211_rx_status *rx_status)
{
u32 center_freq = ppdu_info->freq;
}
static void
-ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
+ath12k_dp_mon_fill_rx_rate(struct ath12k_pdev_dp *dp_pdev,
struct hal_rx_mon_ppdu_info *ppdu_info,
struct ieee80211_rx_status *rx_status)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ieee80211_supported_band *sband;
enum rx_msdu_start_pkt_type pkt_type;
u8 rate_mcs, nss, sgi;
case RX_MSDU_START_PKT_TYPE_11B:
is_cck = (pkt_type == RX_MSDU_START_PKT_TYPE_11B);
if (rx_status->band < NUM_NL80211_BANDS) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
sband = &ar->mac.sbands[rx_status->band];
rx_status->rate_idx = ath12k_mac_hw_rate_to_idx(sband, rate_mcs,
is_cck);
case RX_MSDU_START_PKT_TYPE_11N:
rx_status->encoding = RX_ENC_HT;
if (rate_mcs > ATH12K_HT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in HT mode %d\n",
rate_mcs);
break;
rx_status->encoding = RX_ENC_VHT;
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_VHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in VHT mode %d\n",
rate_mcs);
break;
case RX_MSDU_START_PKT_TYPE_11AX:
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_HE_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in HE mode %d\n",
rate_mcs);
break;
case RX_MSDU_START_PKT_TYPE_11BE:
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_EHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"Received with invalid mcs in EHT mode %d\n",
rate_mcs);
break;
rx_status->he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi);
break;
default:
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
"monitor receives invalid preamble type %d",
pkt_type);
break;
}
}
-static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar,
+static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k_base *ab,
struct sk_buff *head_msdu,
struct sk_buff *tail_msdu)
{
u32 rx_pkt_offset, l2_hdr_offset, total_offset;
- rx_pkt_offset = ar->ab->hal.hal_desc_sz;
+ rx_pkt_offset = ab->hal.hal_desc_sz;
l2_hdr_offset =
- ath12k_dp_rx_h_l3pad(ar->ab, (struct hal_rx_desc *)tail_msdu->data);
+ ath12k_dp_rx_h_l3pad(ab, (struct hal_rx_desc *)tail_msdu->data);
- if (ar->ab->hw_params->rxdma1_enable)
+ if (ab->hw_params->rxdma1_enable)
total_offset = ATH12K_MON_RX_PKT_OFFSET;
else
total_offset = rx_pkt_offset + l2_hdr_offset;
}
static struct sk_buff *
-ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
+ath12k_dp_mon_rx_merg_msdus(struct ath12k_pdev_dp *dp_pdev,
struct dp_mon_mpdu *mon_mpdu,
struct hal_rx_mon_ppdu_info *ppdu_info,
struct ieee80211_rx_status *rxs)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct sk_buff *msdu, *mpdu_buf, *prev_buf, *head_frag_list;
struct sk_buff *head_msdu, *tail_msdu;
struct hal_rx_desc *rx_desc;
if (!head_msdu || !tail_msdu)
goto err_merge_fail;
- ath12k_dp_mon_fill_rx_stats_info(ar, ppdu_info, rxs);
+ ath12k_dp_mon_fill_rx_stats_info(ppdu_info, rxs);
if (unlikely(rxs->band == NUM_NL80211_BANDS ||
- !ath12k_ar_to_hw(ar)->wiphy->bands[rxs->band])) {
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ !ath12k_pdev_dp_to_hw(dp_pdev)->wiphy->bands[rxs->band])) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
"sband is NULL for status band %d channel_num %d center_freq %d pdev_id %d\n",
rxs->band, channel_num, ppdu_info->freq, ar->pdev_idx);
rxs->freq = ieee80211_channel_to_frequency(channel_num,
rxs->band);
- ath12k_dp_mon_fill_rx_rate(ar, ppdu_info, rxs);
+ ath12k_dp_mon_fill_rx_rate(dp_pdev, ppdu_info, rxs);
if (decap_format == DP_RX_DECAP_TYPE_RAW) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ab, head_msdu, tail_msdu);
prev_buf = head_msdu;
msdu = head_msdu->next;
head_frag_list = NULL;
while (msdu) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ab, head_msdu, tail_msdu);
if (!head_frag_list)
head_frag_list = msdu;
msdu = head_msdu;
while (msdu) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ab, head_msdu, tail_msdu);
if (qos_pkt) {
dest = skb_push(msdu, sizeof(__le16));
if (!dest)
rtap_buf[rtap_len] = rx_status->he_RU[3];
}
-static void ath12k_dp_mon_update_radiotap(struct ath12k *ar,
+static void ath12k_dp_mon_update_radiotap(struct ath12k_pdev_dp *dp_pdev,
struct hal_rx_mon_ppdu_info *ppduinfo,
struct sk_buff *mon_skb,
struct ieee80211_rx_status *rxs)
{
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
struct ieee80211_supported_band *sband;
s32 noise_floor;
u8 *ptr = NULL;
rxs->encoding = RX_ENC_HT;
rxs->rate_idx = ppduinfo->rate;
} else {
+ struct ath12k *ar;
+
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
rxs->encoding = RX_ENC_LEGACY;
sband = &ar->mac.sbands[rxs->band];
rxs->rate_idx = ath12k_mac_hw_rate_to_idx(sband, ppduinfo->rate,
rxs->mactime = ppduinfo->tsft;
}
-static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
+static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev,
+ struct napi_struct *napi,
struct sk_buff *msdu,
struct ieee80211_rx_status *status,
u8 decap)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
static const struct ieee80211_radiotap_he known = {
.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN),
status->flag |= RX_FLAG_RADIOTAP_HE;
}
- ath12k_wifi7_dp_extract_rx_desc_data(ar->ab, &rx_info, rx_desc, rx_desc);
+ ath12k_wifi7_dp_extract_rx_desc_data(ab, &rx_info, rx_desc, rx_desc);
- spin_lock_bh(&ar->ab->base_lock);
+ spin_lock_bh(&ab->base_lock);
rx_info.addr2_present = false;
- peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, &rx_info);
+ peer = ath12k_dp_rx_h_find_peer(ab, msdu, &rx_info);
if (peer && peer->sta) {
pubsta = peer->sta;
if (pubsta->valid_links) {
}
}
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&ab->base_lock);
- ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
+ ath12k_dbg(ab, ATH12K_DBG_DATA,
"rx skb %p len %u peer %pM %u %s %s%s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
msdu,
msdu->len,
!!(status->flag & RX_FLAG_MMIC_ERROR),
!!(status->flag & RX_FLAG_AMSDU_MORE));
- ath12k_dbg_dump(ar->ab, ATH12K_DBG_DP_RX, NULL, "dp rx msdu: ",
+ ath12k_dbg_dump(ab, ATH12K_DBG_DP_RX, NULL, "dp rx msdu: ",
msdu->data, msdu->len);
rx_status = IEEE80211_SKB_RXCB(msdu);
*rx_status = *status;
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
rx_status->flag |= RX_FLAG_8023;
- ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
+ ieee80211_rx_napi(ath12k_pdev_dp_to_hw(dp_pdev), pubsta, msdu, napi);
}
-static int ath12k_dp_mon_rx_deliver(struct ath12k *ar,
+static int ath12k_dp_mon_rx_deliver(struct ath12k_pdev_dp *dp_pdev,
struct dp_mon_mpdu *mon_mpdu,
struct hal_rx_mon_ppdu_info *ppduinfo,
struct napi_struct *napi)
{
- struct ath12k_pdev_dp *dp = &ar->dp;
struct sk_buff *mon_skb, *skb_next, *header;
- struct ieee80211_rx_status *rxs = &dp->rx_status;
+ struct ieee80211_rx_status *rxs = &dp_pdev->rx_status;
u8 decap = DP_RX_DECAP_TYPE_RAW;
- mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mon_mpdu, ppduinfo, rxs);
+ mon_skb = ath12k_dp_mon_rx_merg_msdus(dp_pdev, mon_mpdu, ppduinfo, rxs);
if (!mon_skb)
goto mon_deliver_fail;
if (!(rxs->flag & RX_FLAG_ONLY_MONITOR))
decap = mon_mpdu->decap_format;
- ath12k_dp_mon_update_radiotap(ar, ppduinfo, mon_skb, rxs);
- ath12k_dp_mon_rx_deliver_msdu(ar, napi, mon_skb, rxs, decap);
+ ath12k_dp_mon_update_radiotap(dp_pdev, ppduinfo, mon_skb, rxs);
+ ath12k_dp_mon_rx_deliver_msdu(dp_pdev, napi, mon_skb, rxs, decap);
mon_skb = skb_next;
} while (mon_skb);
rxs->flag = 0;
}
static int
-ath12k_dp_mon_parse_status_buf(struct ath12k *ar,
+ath12k_dp_mon_parse_status_buf(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
const struct dp_mon_packet_info *packet_info)
{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct dp_rxdma_mon_ring *buf_ring = &dp->rxdma_mon_buf_ring;
struct sk_buff *msdu;
int buf_id;
}
static int
-ath12k_dp_mon_parse_rx_dest_tlv(struct ath12k *ar,
+ath12k_dp_mon_parse_rx_dest_tlv(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
enum hal_rx_mon_status hal_status,
const void *tlv_data)
return -ENOMEM;
break;
case HAL_RX_MON_STATUS_BUF_ADDR:
- return ath12k_dp_mon_parse_status_buf(ar, pmon, tlv_data);
+ return ath12k_dp_mon_parse_status_buf(dp_pdev, pmon, tlv_data);
case HAL_RX_MON_STATUS_MPDU_END:
/* If no MSDU then free empty MPDU */
if (pmon->mon_mpdu->tail) {
}
static enum hal_rx_mon_status
-ath12k_dp_mon_parse_rx_dest(struct ath12k *ar, struct ath12k_mon_data *pmon,
+ath12k_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev, struct ath12k_mon_data *pmon,
struct sk_buff *skb)
{
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
struct hal_tlv_64_hdr *tlv;
struct ath12k_skb_rxcb *rxcb;
enum hal_rx_mon_status hal_status;
else
tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
- hal_status = ath12k_dp_mon_rx_parse_status_tlv(ar, pmon, tlv);
+ hal_status = ath12k_dp_mon_rx_parse_status_tlv(dp_pdev, pmon, tlv);
if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable &&
- ath12k_dp_mon_parse_rx_dest_tlv(ar, pmon, hal_status, tlv->value))
+ ath12k_dp_mon_parse_rx_dest_tlv(dp_pdev, pmon, hal_status,
+ tlv->value))
return HAL_RX_MON_STATUS_PPDU_DONE;
ptr += sizeof(*tlv) + tlv_len;
}
enum hal_rx_mon_status
-ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
+ath12k_dp_mon_rx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
struct sk_buff *skb,
struct napi_struct *napi)
struct dp_mon_mpdu *mon_mpdu = pmon->mon_mpdu;
enum hal_rx_mon_status hal_status;
- hal_status = ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
+ hal_status = ath12k_dp_mon_parse_rx_dest(dp_pdev, pmon, skb);
if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE)
return hal_status;
list_del(&mon_mpdu->list);
if (mon_mpdu->head && mon_mpdu->tail)
- ath12k_dp_mon_rx_deliver(ar, mon_mpdu, ppdu_info, napi);
+ ath12k_dp_mon_rx_deliver(dp_pdev, mon_mpdu, ppdu_info, napi);
kfree(mon_mpdu);
}
}
static void
-ath12k_dp_mon_tx_process_ppdu_info(struct ath12k *ar,
+ath12k_dp_mon_tx_process_ppdu_info(struct ath12k_pdev_dp *dp_pdev,
struct napi_struct *napi,
struct dp_mon_tx_ppdu_info *tx_ppdu_info)
{
list_del(&mon_mpdu->list);
if (mon_mpdu->head)
- ath12k_dp_mon_rx_deliver(ar, mon_mpdu,
+ ath12k_dp_mon_rx_deliver(dp_pdev, mon_mpdu,
&tx_ppdu_info->rx_status, napi);
kfree(mon_mpdu);
}
enum hal_rx_mon_status
-ath12k_dp_mon_tx_parse_mon_status(struct ath12k *ar,
+ath12k_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
struct sk_buff *skb,
struct napi_struct *napi,
u32 ppdu_id)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct dp_mon_tx_ppdu_info *tx_prot_ppdu_info, *tx_data_ppdu_info;
struct hal_tlv_hdr *tlv;
u8 *ptr = skb->data;
break;
} while (tlv_status != DP_MON_TX_FES_STATUS_END);
- ath12k_dp_mon_tx_process_ppdu_info(ar, napi, tx_data_ppdu_info);
- ath12k_dp_mon_tx_process_ppdu_info(ar, napi, tx_prot_ppdu_info);
+ ath12k_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_data_ppdu_info);
+ ath12k_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_prot_ppdu_info);
return tlv_status;
}
stats->rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += len;
}
-static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
- struct ath12k_link_sta *arsta,
+static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k_link_sta *arsta,
struct hal_rx_mon_ppdu_info *ppdu_info)
{
struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
}
static void
-ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
+ath12k_dp_mon_rx_update_user_stats(struct ath12k_base *ab,
struct hal_rx_mon_ppdu_info *ppdu_info,
u32 uid)
{
if (user_stats->ast_index == 0 || user_stats->ast_index == 0xFFFF)
return;
- peer = ath12k_peer_find_by_ast(ar->ab, user_stats->ast_index);
+ peer = ath12k_peer_find_by_ast(ab, user_stats->ast_index);
if (!peer) {
- ath12k_warn(ar->ab, "peer ast idx %d can't be found\n",
+ ath12k_warn(ab, "peer ast idx %d can't be found\n",
user_stats->ast_index);
return;
}
- arsta = ath12k_peer_get_link_sta(ar->ab, peer);
+ arsta = ath12k_peer_get_link_sta(ab, peer);
if (!arsta) {
- ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n",
+ ath12k_warn(ab, "link sta not found on peer %pM id %d\n",
peer->addr, peer->peer_id);
return;
}
}
static void
-ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k *ar,
+ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k_base *ab,
struct hal_rx_mon_ppdu_info *ppdu_info)
{
u32 num_users, i;
num_users = HAL_MAX_UL_MU_USERS;
for (i = 0; i < num_users; i++)
- ath12k_dp_mon_rx_update_user_stats(ar, ppdu_info, i);
+ ath12k_dp_mon_rx_update_user_stats(ab, ppdu_info, i);
}
static void
ppdu_info->peer_id = HAL_INVALID_PEERID;
}
-int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget,
+int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget,
struct napi_struct *napi)
{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_pdev_dp *pdev_dp = &ar->dp;
+ struct ath12k_dp *dp = pdev_dp->dp;
+ struct ath12k_base *ab = dp->ab;
struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&pdev_dp->mon_data;
struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
- struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct hal_mon_dest_desc *mon_dst_desc;
struct sk_buff *skb;
struct ath12k_skb_rxcb *rxcb;
u64 cookie;
int num_buffs_reaped = 0, srng_id, buf_id;
u32 hal_status, end_offset, info0, end_reason;
- u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, ar->pdev_idx);
+ u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, pdev_dp->mac_id);
__skb_queue_head_init(&skb_list);
srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, pdev_idx);
ath12k_dp_mon_rx_memset_ppdu_info(ppdu_info);
while ((skb = __skb_dequeue(&skb_list))) {
- hal_status = ath12k_dp_mon_rx_parse_mon_status(ar, pmon, skb, napi);
+ hal_status = ath12k_dp_mon_rx_parse_mon_status(pdev_dp, pmon, skb, napi);
if (hal_status != HAL_RX_MON_STATUS_PPDU_DONE) {
ppdu_info->ppdu_continuation = true;
dev_kfree_skb_any(skb);
}
if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
- arsta = ath12k_peer_get_link_sta(ar->ab, peer);
+ arsta = ath12k_peer_get_link_sta(ab, peer);
if (!arsta) {
- ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n",
+ ath12k_warn(ab, "link sta not found on peer %pM id %d\n",
peer->addr, peer->peer_id);
spin_unlock_bh(&ab->base_lock);
rcu_read_unlock();
dev_kfree_skb_any(skb);
continue;
}
- ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta,
+ ath12k_dp_mon_rx_update_peer_su_stats(arsta,
ppdu_info);
} else if ((ppdu_info->fc_valid) &&
(ppdu_info->ast_index != HAL_AST_IDX_INVALID)) {
ath12k_dp_mon_rx_process_ulofdma(ppdu_info);
- ath12k_dp_mon_rx_update_peer_mu_stats(ar, ppdu_info);
+ ath12k_dp_mon_rx_update_peer_mu_stats(ab, ppdu_info);
}
next_skb:
tmp_mpdu->tail = tail_msdu;
tmp_mpdu->err_bitmap = pmon->err_bitmap;
tmp_mpdu->decap_format = pmon->decap_format;
- ath12k_dp_mon_rx_deliver(ar, tmp_mpdu,
+ ath12k_dp_mon_rx_deliver(&ar->dp, tmp_mpdu,
&pmon->mon_ppdu_info, napi);
rx_mon_stats->dest_mpdu_done++;
kfree(tmp_mpdu);
memset(ppdu_info, 0, sizeof(*ppdu_info));
ppdu_info->peer_id = HAL_INVALID_PEERID;
- hal_status = ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
+ hal_status = ath12k_dp_mon_parse_rx_dest(&ar->dp, pmon, skb);
if (ar->monitor_started &&
pmon->mon_ppdu_status == DP_PPDU_STATUS_START &&
struct napi_struct *napi, int budget,
enum dp_monitor_mode monitor_mode)
{
- struct ath12k *ar = ath12k_ab_to_ar(ab, mac_id);
+ u8 pdev_idx = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_pdev_dp *dp_pdev;
+ struct ath12k *ar;
int num_buffs_reaped = 0;
+ rcu_read_lock();
+
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
+ if (!dp_pdev) {
+ rcu_read_unlock();
+ return 0;
+ }
+
if (ab->hw_params->rxdma1_enable) {
if (monitor_mode == ATH12K_DP_RX_MONITOR_MODE)
- num_buffs_reaped = ath12k_dp_mon_srng_process(ar, &budget, napi);
+ num_buffs_reaped = ath12k_dp_mon_srng_process(dp_pdev, &budget,
+ napi);
} else {
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
if (ar->monitor_started)
num_buffs_reaped =
__ath12k_dp_mon_process_ring(ar, mac_id, napi, &budget);
}
+ rcu_read_unlock();
+
return num_buffs_reaped;
}
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_MON_H
};
enum hal_rx_mon_status
-ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
+ath12k_dp_mon_rx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
struct sk_buff *skb,
struct napi_struct *napi);
struct hal_tlv_hdr *tx_tlv,
u8 *num_users);
enum hal_rx_mon_status
-ath12k_dp_mon_tx_parse_mon_status(struct ath12k *ar,
+ath12k_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
struct sk_buff *skb,
struct napi_struct *napi,
u32 ppdu_id);
void ath12k_dp_mon_rx_process_ulofdma(struct hal_rx_mon_ppdu_info *ppdu_info);
-int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget, struct napi_struct *napi);
+int ath12k_dp_mon_srng_process(struct ath12k_pdev_dp *pdev_dp, int *budget,
+ struct napi_struct *napi);
#endif
return NULL;
}
-int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype)
+int ath12k_dp_rx_crypto_mic_len(struct ath12k_dp *dp, enum hal_encrypt_type enctype)
{
switch (enctype) {
case HAL_ENCRYPT_TYPE_OPEN:
break;
}
- ath12k_warn(ar->ab, "unsupported encryption type %d for mic len\n", enctype);
+ ath12k_warn(dp->ab, "unsupported encryption type %d for mic len\n", enctype);
return 0;
}
-static int ath12k_dp_rx_crypto_param_len(struct ath12k *ar,
+static int ath12k_dp_rx_crypto_param_len(struct ath12k_pdev_dp *dp_pdev,
enum hal_encrypt_type enctype)
{
switch (enctype) {
break;
}
- ath12k_warn(ar->ab, "unsupported encryption type %d\n", enctype);
+ ath12k_warn(dp_pdev->dp->ab, "unsupported encryption type %d\n", enctype);
return 0;
}
-static int ath12k_dp_rx_crypto_icv_len(struct ath12k *ar,
+static int ath12k_dp_rx_crypto_icv_len(struct ath12k_pdev_dp *dp_pdev,
enum hal_encrypt_type enctype)
{
switch (enctype) {
break;
}
- ath12k_warn(ar->ab, "unsupported encryption type %d\n", enctype);
+ ath12k_warn(dp_pdev->dp->ab, "unsupported encryption type %d\n", enctype);
return 0;
}
-static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar,
+static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
enum hal_encrypt_type enctype,
struct hal_rx_desc_data *rx_info)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN];
struct ieee80211_hdr *hdr;
/* Rebuild crypto header for mac80211 use */
if (!(rx_info->rx_status->flag & RX_FLAG_IV_STRIPPED)) {
- crypto_hdr = skb_push(msdu, ath12k_dp_rx_crypto_param_len(ar, enctype));
- ath12k_dp_rx_desc_get_crypto_header(ar->ab,
+ crypto_hdr = skb_push(msdu,
+ ath12k_dp_rx_crypto_param_len(dp_pdev, enctype));
+ ath12k_dp_rx_desc_get_crypto_header(ab,
rxcb->rx_desc, crypto_hdr,
enctype);
}
memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len);
}
-static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu,
+static void ath12k_dp_rx_h_undecap_raw(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
enum hal_encrypt_type enctype,
struct ieee80211_rx_status *status,
bool decrypted)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
struct ieee80211_hdr *hdr;
size_t hdr_len;
/* Tail */
if (status->flag & RX_FLAG_IV_STRIPPED) {
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_mic_len(ar, enctype));
+ ath12k_dp_rx_crypto_mic_len(dp, enctype));
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_icv_len(ar, enctype));
+ ath12k_dp_rx_crypto_icv_len(dp_pdev, enctype));
} else {
/* MIC */
if (status->flag & RX_FLAG_MIC_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_mic_len(ar, enctype));
+ ath12k_dp_rx_crypto_mic_len(dp, enctype));
/* ICV */
if (status->flag & RX_FLAG_ICV_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_icv_len(ar, enctype));
+ ath12k_dp_rx_crypto_icv_len(dp_pdev, enctype));
}
/* MMIC */
/* Head */
if (status->flag & RX_FLAG_IV_STRIPPED) {
hdr_len = ieee80211_hdrlen(hdr->frame_control);
- crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
+ crypto_len = ath12k_dp_rx_crypto_param_len(dp_pdev, enctype);
memmove(msdu->data + crypto_len, msdu->data, hdr_len);
skb_pull(msdu, crypto_len);
}
}
-static void ath12k_get_dot11_hdr_from_rx_desc(struct ath12k *ar,
+static void ath12k_get_dot11_hdr_from_rx_desc(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
struct ath12k_skb_rxcb *rxcb,
enum hal_encrypt_type enctype,
struct hal_rx_desc_data *rx_info)
{
struct hal_rx_desc *rx_desc = rxcb->rx_desc;
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
size_t hdr_len, crypto_len;
struct ieee80211_hdr hdr;
__le16 qos_ctl;
hdr_len = ieee80211_hdrlen(hdr.frame_control);
if (!(rx_info->rx_status->flag & RX_FLAG_IV_STRIPPED)) {
- crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
+ crypto_len = ath12k_dp_rx_crypto_param_len(dp_pdev, enctype);
crypto_hdr = skb_push(msdu, crypto_len);
ath12k_dp_rx_desc_get_crypto_header(ab, rx_desc, crypto_hdr, enctype);
}
}
}
-static void ath12k_dp_rx_h_undecap_eth(struct ath12k *ar,
+static void ath12k_dp_rx_h_undecap_eth(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
enum hal_encrypt_type enctype,
struct hal_rx_desc_data *rx_info)
skb_pull(msdu, sizeof(*eth));
memcpy(skb_push(msdu, sizeof(rfc)), &rfc,
sizeof(rfc));
- ath12k_get_dot11_hdr_from_rx_desc(ar, msdu, rxcb, enctype, rx_info);
+ ath12k_get_dot11_hdr_from_rx_desc(dp_pdev, msdu, rxcb, enctype, rx_info);
/* original 802.11 header has a different DA and in
* case of 4addr it may also have different SA
ether_addr_copy(ieee80211_get_SA(hdr), sa);
}
-void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
+void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
struct hal_rx_desc *rx_desc,
enum hal_encrypt_type enctype,
bool decrypted,
switch (rx_info->decap_type) {
case DP_RX_DECAP_TYPE_NATIVE_WIFI:
- ath12k_dp_rx_h_undecap_nwifi(ar, msdu, enctype, rx_info);
+ ath12k_dp_rx_h_undecap_nwifi(dp_pdev, msdu, enctype, rx_info);
break;
case DP_RX_DECAP_TYPE_RAW:
- ath12k_dp_rx_h_undecap_raw(ar, msdu, enctype, rx_info->rx_status,
+ ath12k_dp_rx_h_undecap_raw(dp_pdev, msdu, enctype, rx_info->rx_status,
decrypted);
break;
case DP_RX_DECAP_TYPE_ETHERNET2_DIX:
/* mac80211 allows fast path only for authorized STA */
if (ehdr->h_proto == cpu_to_be16(ETH_P_PAE)) {
ATH12K_SKB_RXCB(msdu)->is_eapol = true;
- ath12k_dp_rx_h_undecap_eth(ar, msdu, enctype, rx_info);
+ ath12k_dp_rx_h_undecap_eth(dp_pdev, msdu, enctype, rx_info);
break;
}
* remove eth header and add 802.11 header.
*/
if (ATH12K_SKB_RXCB(msdu)->is_mcbc && decrypted)
- ath12k_dp_rx_h_undecap_eth(ar, msdu, enctype, rx_info);
+ ath12k_dp_rx_h_undecap_eth(dp_pdev, msdu, enctype, rx_info);
break;
case DP_RX_DECAP_TYPE_8023:
/* TODO: Handle undecap for these formats */
return peer;
}
-static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct hal_rx_desc_data *rx_info)
+static void ath12k_dp_rx_h_rate(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_desc_data *rx_info)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ieee80211_supported_band *sband;
struct ieee80211_rx_status *rx_status = rx_info->rx_status;
enum rx_msdu_start_pkt_type pkt_type = rx_info->pkt_type;
u8 bw = rx_info->bw, sgi = rx_info->sgi;
u8 rate_mcs = rx_info->rate_mcs, nss = rx_info->nss;
bool is_cck;
+ struct ath12k *ar;
switch (pkt_type) {
case RX_MSDU_START_PKT_TYPE_11A:
case RX_MSDU_START_PKT_TYPE_11B:
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
is_cck = (pkt_type == RX_MSDU_START_PKT_TYPE_11B);
sband = &ar->mac.sbands[rx_status->band];
rx_status->rate_idx = ath12k_mac_hw_rate_to_idx(sband, rate_mcs,
case RX_MSDU_START_PKT_TYPE_11N:
rx_status->encoding = RX_ENC_HT;
if (rate_mcs > ATH12K_HT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in HT mode %d\n",
rate_mcs);
break;
rx_status->encoding = RX_ENC_VHT;
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_VHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in VHT mode %d\n",
rate_mcs);
break;
case RX_MSDU_START_PKT_TYPE_11AX:
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_HE_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in HE mode %d\n",
rate_mcs);
break;
rx_status->rate_idx = rate_mcs;
if (rate_mcs > ATH12K_EHT_MCS_MAX) {
- ath12k_warn(ar->ab,
+ ath12k_warn(dp->ab,
"Received with invalid mcs in EHT mode %d\n",
rate_mcs);
break;
}
}
-void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc_data *rx_info)
+void ath12k_dp_rx_h_ppdu(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_desc_data *rx_info)
{
struct ieee80211_rx_status *rx_status = rx_info->rx_status;
u8 channel_num;
} else if (channel_num >= 36 && channel_num <= 173) {
rx_status->band = NL80211_BAND_5GHZ;
} else {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
spin_lock_bh(&ar->data_lock);
channel = ar->rx_channel;
if (channel) {
rx_status->freq = ieee80211_channel_to_frequency(channel_num,
rx_status->band);
- ath12k_dp_rx_h_rate(ar, rx_info);
+ ath12k_dp_rx_h_rate(dp_pdev, rx_info);
}
-void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
+void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struct *napi,
struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ieee80211_rx_status *rx_status;
struct ieee80211_sta *pubsta;
struct ath12k_peer *peer;
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
rx_status->flag |= RX_FLAG_8023;
- ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
+ ieee80211_rx_napi(ath12k_pdev_dp_to_hw(dp_pdev), pubsta, msdu, napi);
}
bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
return ret;
}
-void ath12k_dp_rx_h_undecap_frag(struct ath12k *ar, struct sk_buff *msdu,
+void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
enum hal_encrypt_type enctype, u32 flags)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ieee80211_hdr *hdr;
size_t hdr_len;
size_t crypto_len;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
if (!flags)
return;
if (flags & RX_FLAG_MIC_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_mic_len(ar, enctype));
+ ath12k_dp_rx_crypto_mic_len(dp, enctype));
if (flags & RX_FLAG_ICV_STRIPPED)
skb_trim(msdu, msdu->len -
- ath12k_dp_rx_crypto_icv_len(ar, enctype));
+ ath12k_dp_rx_crypto_icv_len(dp_pdev, enctype));
if (flags & RX_FLAG_IV_STRIPPED) {
hdr_len = ieee80211_hdrlen(hdr->frame_control);
- crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
+ crypto_len = ath12k_dp_rx_crypto_param_len(dp_pdev, enctype);
memmove(msdu->data + hal_rx_desc_sz + crypto_len,
msdu->data + hal_rx_desc_sz, hdr_len);
__skb_queue_tail(frag_list, cur_frag);
}
-u64 ath12k_dp_rx_h_get_pn(struct ath12k *ar, struct sk_buff *skb)
+u64 ath12k_dp_rx_h_get_pn(struct ath12k_dp *dp, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
u64 pn = 0;
u8 *ehdr;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
hdr = (struct ieee80211_hdr *)(skb->data + hal_rx_desc_sz);
ehdr = skb->data + hal_rx_desc_sz + ieee80211_hdrlen(hdr->frame_control);
dev_kfree_skb_any(skb);
}
-void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu,
+void ath12k_dp_rx_h_undecap(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
struct hal_rx_desc *rx_desc,
enum hal_encrypt_type enctype,
bool decrypted,
struct hal_rx_desc_data *rx_info);
-void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi,
+void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struct *napi,
struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info);
bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc,
struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info);
-u64 ath12k_dp_rx_h_get_pn(struct ath12k *ar, struct sk_buff *skb);
+u64 ath12k_dp_rx_h_get_pn(struct ath12k_dp *dp, struct sk_buff *skb);
void ath12k_dp_rx_h_sort_frags(struct ath12k_base *ab,
struct sk_buff_head *frag_list,
struct sk_buff *cur_frag);
-void ath12k_dp_rx_h_undecap_frag(struct ath12k *ar, struct sk_buff *msdu,
+void ath12k_dp_rx_h_undecap_frag(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *msdu,
enum hal_encrypt_type enctype, u32 flags);
void ath12k_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
bool rel_link_desc);
struct hal_rx_desc *desc);
u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab,
struct hal_rx_desc *desc);
-int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype);
+int ath12k_dp_rx_crypto_mic_len(struct ath12k_dp *dp, enum hal_encrypt_type enctype);
u32 ath12k_dp_rxdesc_get_ppduid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc);
bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc);
bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc);
-void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc_data *rx_info);
+void ath12k_dp_rx_h_ppdu(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_rx_desc_data *rx_info);
struct sk_buff *ath12k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_list,
struct sk_buff *first);
void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
#include "hif.h"
#include "wow.h"
#include "debugfs_sta.h"
+#include "dp.h"
#define CHAN2G(_channel, _freq, _flags) { \
.band = NL80211_BAND_2GHZ, \
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
enctype = ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
- mic_len = ath12k_dp_rx_crypto_mic_len(ar, enctype);
+ mic_len = ath12k_dp_rx_crypto_mic_len(ab->dp, enctype);
skb_put(skb, mic_len);
}
}
u32 info_flags = info->flags;
struct sk_buff *msdu_copied;
struct ath12k *ar, *tmp_ar;
+ struct ath12k_pdev_dp *dp_pdev, *tmp_dp_pdev;
struct ath12k_peer *peer;
unsigned long links_map;
bool is_mcast = false;
ar = arvif->ar;
skb_cb->link_id = link_id;
+ /* as skb_cb is common currently for dp and mgmt tx processing
+ * set this in the common mac op tx function.
+ */
+ skb_cb->ar = ar;
is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
if (vif->type == NL80211_IFTYPE_AP && vif->p2p)
ath12k_mac_add_p2p_noa_ie(ar, vif, skb, is_prb_rsp);
+ dp_pdev = ath12k_dp_to_pdev_dp(ar->ab->dp, ar->pdev_idx);
+ if (!dp_pdev) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+
/* Checking if it is a DVLAN frame */
if (!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
!(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
if (!vif->valid_links || !is_mcast || is_dvlan ||
(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) ||
test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) {
- ret = ath12k_wifi7_dp_tx(ar, arvif, skb, false, 0, is_mcast);
+ ret = ath12k_wifi7_dp_tx(dp_pdev, arvif, skb, false, 0, is_mcast);
if (unlikely(ret)) {
ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);
ieee80211_free_txskb(ar->ah->hw, skb);
continue;
tmp_ar = tmp_arvif->ar;
+ tmp_dp_pdev = ath12k_dp_to_pdev_dp(tmp_ar->ab->dp,
+ tmp_ar->pdev_idx);
+ if (!tmp_dp_pdev)
+ continue;
msdu_copied = skb_copy(skb, GFP_ATOMIC);
if (!msdu_copied) {
ath12k_err(ar->ab,
skb_cb = ATH12K_SKB_CB(msdu_copied);
skb_cb->link_id = link_id;
skb_cb->vif = vif;
+ skb_cb->ar = tmp_ar;
/* For open mode, skip peer find logic */
if (unlikely(!ahvif->dp_vif.key_cipher))
spin_unlock_bh(&tmp_ar->ab->base_lock);
skip_peer_find:
- ret = ath12k_wifi7_dp_tx(tmp_ar, tmp_arvif,
+ ret = ath12k_wifi7_dp_tx(tmp_dp_pdev, tmp_arvif,
msdu_copied, true, mcbc_gsn, is_mcast);
if (unlikely(ret)) {
if (ret == -ENOMEM) {
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
}
-static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k *ar,
+static void ath12k_wifi7_dp_rx_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
struct hal_rx_desc *rx_desc,
struct hal_rx_desc_data *rx_info)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ath12k_skb_rxcb *rxcb;
enum hal_encrypt_type enctype;
bool is_decrypted = false;
if (rxcb->is_mcbc)
rxcb->peer_id = rx_info->peer_id;
- spin_lock_bh(&ar->ab->base_lock);
- peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, rx_info);
+ spin_lock_bh(&ab->base_lock);
+ peer = ath12k_dp_rx_h_find_peer(ab, msdu, rx_info);
if (peer) {
/* resetting mcbc bit because mcbc packets are unicast
* packets only for AP as STA sends unicast packets.
} else {
enctype = HAL_ENCRYPT_TYPE_OPEN;
}
- spin_unlock_bh(&ar->ab->base_lock);
+ spin_unlock_bh(&ab->base_lock);
if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap)
is_decrypted = rx_info->is_decrypted;
}
ath12k_wifi7_dp_rx_h_csum_offload(msdu, rx_info);
- ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
+ ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,
enctype, is_decrypted, rx_info);
if (!is_decrypted || rx_info->is_mcbc)
}
}
-static int ath12k_wifi7_dp_rx_msdu_coalesce(struct ath12k *ar,
+static int ath12k_wifi7_dp_rx_msdu_coalesce(struct ath12k_dp *dp,
struct sk_buff_head *msdu_list,
struct sk_buff *first, struct sk_buff *last,
u8 l3pad_bytes, int msdu_len,
struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_base *ab = dp->ab;
struct sk_buff *skb;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(first);
int buf_first_hdr_len, buf_first_len;
struct hal_rx_desc *ldesc;
int space_extra, rem_len, buf_len;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
bool is_continuation;
/* As the msdu is spread across multiple rx buffers,
return 0;
}
-static int ath12k_wifi7_dp_rx_process_msdu(struct ath12k *ar,
+static int ath12k_wifi7_dp_rx_process_msdu(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
struct sk_buff_head *msdu_list,
struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct hal_rx_desc *rx_desc, *lrx_desc;
struct ath12k_skb_rxcb *rxcb;
struct sk_buff *last_buf;
u8 l3_pad_bytes;
u16 msdu_len;
int ret;
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
last_buf = ath12k_dp_rx_get_msdu_last_buf(msdu_list, msdu);
if (!last_buf) {
skb_put(msdu, hal_rx_desc_sz + l3_pad_bytes + msdu_len);
skb_pull(msdu, hal_rx_desc_sz + l3_pad_bytes);
} else {
- ret = ath12k_wifi7_dp_rx_msdu_coalesce(ar, msdu_list,
+ ret = ath12k_wifi7_dp_rx_msdu_coalesce(dp, msdu_list,
msdu, last_buf,
l3_pad_bytes, msdu_len,
rx_info);
goto free_out;
}
- ath12k_dp_rx_h_ppdu(ar, rx_info);
- ath12k_wifi7_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_info);
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
+ ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, rx_desc, rx_info);
rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
struct ath12k_skb_rxcb *rxcb;
struct sk_buff *msdu;
struct ath12k *ar;
+ struct ath12k_pdev_dp *dp_pdev;
struct ath12k_hw_link *hw_links = ag->hw_links;
struct ath12k_base *partner_ab;
struct hal_rx_desc_data rx_info;
struct ath12k_dp *partner_dp;
- u8 hw_link_id, pdev_id;
+ u8 hw_link_id, pdev_idx;
int ret;
if (skb_queue_empty(msdu_list))
hw_link_id = rxcb->hw_link_id;
partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp,
hw_links[hw_link_id].device_id);
- pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_dp->hw_params,
- hw_links[hw_link_id].pdev_idx);
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(partner_dp->hw_params,
+ hw_links[hw_link_id].pdev_idx);
partner_ab = partner_dp->ab;
- ar = partner_ab->pdevs[pdev_id].ar;
- if (!rcu_dereference(partner_ab->pdevs_active[pdev_id])) {
+ ar = partner_ab->pdevs[pdev_idx].ar;
+ if (!rcu_dereference(partner_ab->pdevs_active[pdev_idx])) {
dev_kfree_skb_any(msdu);
continue;
}
continue;
}
- ret = ath12k_wifi7_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_info);
+ dp_pdev = ath12k_dp_to_pdev_dp(partner_dp, pdev_idx);
+ if (!dp_pdev) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+
+ ret = ath12k_wifi7_dp_rx_process_msdu(dp_pdev, msdu, msdu_list, &rx_info);
if (ret) {
ath12k_dbg(ab, ATH12K_DBG_DATA,
"Unable to process msdu %d", ret);
continue;
}
- ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
+ ath12k_dp_rx_deliver_msdu(dp_pdev, napi, msdu, &rx_info);
}
rcu_read_unlock();
}
static bool
-ath12k_wifi7_dp_rx_h_defrag_validate_incr_pn(struct ath12k *ar,
+ath12k_wifi7_dp_rx_h_defrag_validate_incr_pn(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_dp_rx_tid *rx_tid,
enum hal_encrypt_type encrypt_type)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct sk_buff *first_frag, *skb;
u64 last_pn;
u64 cur_pn;
encrypt_type != HAL_ENCRYPT_TYPE_AES_GCMP_256)
return true;
- last_pn = ath12k_dp_rx_h_get_pn(ar, first_frag);
+ last_pn = ath12k_dp_rx_h_get_pn(dp, first_frag);
skb_queue_walk(&rx_tid->rx_frags, skb) {
if (skb == first_frag)
continue;
- cur_pn = ath12k_dp_rx_h_get_pn(ar, skb);
+ cur_pn = ath12k_dp_rx_h_get_pn(dp, skb);
if (cur_pn != last_pn + 1)
return false;
last_pn = cur_pn;
return true;
}
-static int ath12k_wifi7_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
+static int ath12k_wifi7_dp_rx_h_defrag_reo_reinject(struct ath12k_dp *dp,
struct ath12k_dp_rx_tid *rx_tid,
struct sk_buff *defrag_skb)
{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_base *ab = dp->ab;
struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)defrag_skb->data;
struct hal_reo_entrance_ring *reo_ent_ring;
struct hal_reo_dest_ring *reo_dest_ring;
return ret;
}
-static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k *ar,
+static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_peer *peer,
enum hal_encrypt_type enctype,
struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(msdu);
struct ieee80211_key_conf *key_conf;
rx_info)))
return -EINVAL;
- ath12k_dp_rx_h_ppdu(ar, rx_info);
- ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
+ ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,
HAL_ENCRYPT_TYPE_TKIP_MIC, true, rx_info);
- ieee80211_rx(ath12k_ar_to_hw(ar), msdu);
+ ieee80211_rx(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
return -EINVAL;
}
-static int ath12k_wifi7_dp_rx_h_defrag(struct ath12k *ar,
+static int ath12k_wifi7_dp_rx_h_defrag(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_peer *peer,
struct ath12k_dp_rx_tid *rx_tid,
struct sk_buff **defrag_skb,
enum hal_encrypt_type enctype,
struct hal_rx_desc_data *rx_info)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct sk_buff *skb, *first_frag, *last_frag;
struct ieee80211_hdr *hdr;
bool is_decrypted = false;
int msdu_len = 0;
int extra_space;
- u32 flags, hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 flags, hal_rx_desc_sz = ab->hal.hal_desc_sz;
first_frag = skb_peek(&rx_tid->rx_frags);
last_frag = skb_peek_tail(&rx_tid->rx_frags);
/* RX fragments are always raw packets */
if (skb != last_frag)
skb_trim(skb, skb->len - FCS_LEN);
- ath12k_dp_rx_h_undecap_frag(ar, skb, enctype, flags);
+ ath12k_dp_rx_h_undecap_frag(dp_pdev, skb, enctype, flags);
if (skb != first_frag)
skb_pull(skb, hal_rx_desc_sz +
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
ATH12K_SKB_RXCB(first_frag)->is_frag = 1;
- if (ath12k_wifi7_dp_rx_h_verify_tkip_mic(ar, peer, enctype, first_frag, rx_info))
+ if (ath12k_wifi7_dp_rx_h_verify_tkip_mic(dp_pdev, peer, enctype, first_frag,
+ rx_info))
first_frag = NULL;
*defrag_skb = first_frag;
return 0;
}
-static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k *ar,
+static int ath12k_wifi7_dp_rx_frag_h_mpdu(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *msdu,
struct hal_reo_dest_ring *ring_desc,
struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ath12k_peer *peer;
struct ath12k_dp_rx_tid *rx_tid;
struct sk_buff *defrag_skb = NULL;
if (!peer)
goto err_frags_cleanup;
- if (!ath12k_wifi7_dp_rx_h_defrag_validate_incr_pn(ar, rx_tid, enctype))
+ if (!ath12k_wifi7_dp_rx_h_defrag_validate_incr_pn(dp_pdev, rx_tid, enctype))
goto err_frags_cleanup;
- if (ath12k_wifi7_dp_rx_h_defrag(ar, peer, rx_tid, &defrag_skb,
+ if (ath12k_wifi7_dp_rx_h_defrag(dp_pdev, peer, rx_tid, &defrag_skb,
enctype, rx_info))
goto err_frags_cleanup;
if (!defrag_skb)
goto err_frags_cleanup;
- if (ath12k_wifi7_dp_rx_h_defrag_reo_reinject(ar, rx_tid, defrag_skb))
+ if (ath12k_wifi7_dp_rx_h_defrag_reo_reinject(dp, rx_tid, defrag_skb))
goto err_frags_cleanup;
ath12k_dp_rx_frags_cleanup(rx_tid, false);
}
static int
-ath12k_wifi7_dp_process_rx_err_buf(struct ath12k *ar,
+ath12k_wifi7_dp_process_rx_err_buf(struct ath12k_pdev_dp *dp_pdev,
struct hal_reo_dest_ring *desc,
struct list_head *used_list,
bool drop, u32 cookie)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct sk_buff *msdu;
struct ath12k_skb_rxcb *rxcb;
struct hal_rx_desc_data rx_info;
list_add_tail(&desc_info->list, used_list);
rxcb = ATH12K_SKB_RXCB(msdu);
- dma_unmap_single(ar->ab->dev, rxcb->paddr,
+ dma_unmap_single(ab->dev, rxcb->paddr,
msdu->len + skb_tailroom(msdu),
DMA_FROM_DEVICE);
msdu_len = rx_info.msdu_len;
if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) {
- ath12k_warn(ar->ab, "invalid msdu leng %u", msdu_len);
- ath12k_dbg_dump(ar->ab, ATH12K_DBG_DATA, NULL, "", rx_desc,
+ ath12k_warn(ab, "invalid msdu leng %u", msdu_len);
+ ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", rx_desc,
sizeof(*rx_desc));
dev_kfree_skb_any(msdu);
goto exit;
skb_put(msdu, hal_rx_desc_sz + msdu_len);
- if (ath12k_wifi7_dp_rx_frag_h_mpdu(ar, msdu, desc, &rx_info)) {
+ if (ath12k_wifi7_dp_rx_frag_h_mpdu(dp_pdev, msdu, desc, &rx_info)) {
dev_kfree_skb_any(msdu);
ath12k_wifi7_dp_rx_link_desc_return(ar->ab, &desc->buf_addr_info,
HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
struct dp_srng *reo_except;
struct ath12k_hw_link *hw_links = ag->hw_links;
struct ath12k_base *partner_ab;
+ struct ath12k_pdev_dp *dp_pdev;
u8 hw_link_id, device_id;
u32 desc_bank, num_msdus;
struct hal_srng *srng;
- struct ath12k *ar;
dma_addr_t paddr;
bool is_frag;
bool drop;
- int pdev_id;
+ int pdev_idx;
struct list_head *used_list;
enum hal_wbm_rel_bm_act act;
partner_dp = ath12k_dp_hw_grp_to_dp(dp_hw_grp, device_id);
partner_ab = partner_dp->ab;
- pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
- hw_links[hw_link_id].pdev_idx);
- ar = partner_ab->pdevs[pdev_id].ar;
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
+ hw_links[hw_link_id].pdev_idx);
link_desc_banks = partner_dp->link_desc_banks;
link_desc_va = link_desc_banks[desc_bank].vaddr +
act);
}
+ rcu_read_lock();
+
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
+ if (!dp_pdev) {
+ rcu_read_unlock();
+ continue;
+ }
+
for (i = 0; i < num_msdus; i++) {
used_list = &rx_desc_used_list[device_id];
- if (!ath12k_wifi7_dp_process_rx_err_buf(ar, reo_desc,
+ if (!ath12k_wifi7_dp_process_rx_err_buf(dp_pdev, reo_desc,
used_list,
drop,
msdu_cookies[i])) {
}
}
+ rcu_read_unlock();
+
if (tot_n_bufs_reaped >= quota) {
tot_n_bufs_reaped = quota;
goto exit;
}
static void
-ath12k_wifi7_dp_rx_null_q_desc_sg_drop(struct ath12k *ar, int msdu_len,
+ath12k_wifi7_dp_rx_null_q_desc_sg_drop(struct ath12k_dp *dp, int msdu_len,
struct sk_buff_head *msdu_list)
{
struct sk_buff *skb, *tmp;
int n_buffs;
n_buffs = DIV_ROUND_UP(msdu_len,
- (DP_RX_BUFFER_SIZE - ar->ab->hal.hal_desc_sz));
+ (DP_RX_BUFFER_SIZE - dp->ab->hal.hal_desc_sz));
skb_queue_walk_safe(msdu_list, skb, tmp) {
rxcb = ATH12K_SKB_RXCB(skb);
}
}
-static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
+static int ath12k_wifi7_dp_rx_h_null_q_desc(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info,
struct sk_buff_head *msdu_list)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
u16 msdu_len = rx_info->msdu_len;
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
u8 l3pad_bytes = rx_info->l3_pad_bytes;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = dp->ab->hal.hal_desc_sz;
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
/* First buffer will be freed by the caller, so deduct it's length */
msdu_len = msdu_len - (DP_RX_BUFFER_SIZE - hal_rx_desc_sz);
- ath12k_wifi7_dp_rx_null_q_desc_sg_drop(ar, msdu_len, msdu_list);
+ ath12k_wifi7_dp_rx_null_q_desc_sg_drop(dp, msdu_len, msdu_list);
return -EINVAL;
}
return -EINVAL;
if (!rx_info->msdu_done) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"msdu_done bit not set in null_q_des processing\n");
__skb_queue_purge(msdu_list);
return -EIO;
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu, rx_info)))
return -EINVAL;
- ath12k_dp_rx_h_ppdu(ar, rx_info);
- ath12k_wifi7_dp_rx_h_mpdu(ar, msdu, desc, rx_info);
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
+ ath12k_wifi7_dp_rx_h_mpdu(dp_pdev, msdu, desc, rx_info);
rxcb->tid = rx_info->tid;
return 0;
}
-static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
+static bool ath12k_wifi7_dp_rx_h_tkip_mic_err(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
u16 msdu_len = rx_info->msdu_len;
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
u8 l3pad_bytes = rx_info->l3_pad_bytes;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
+ u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
rxcb->is_first_msdu = rx_info->is_first_msdu;
rxcb->is_last_msdu = rx_info->is_last_msdu;
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu, rx_info)))
return true;
- ath12k_dp_rx_h_ppdu(ar, rx_info);
+ ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
RX_FLAG_DECRYPTED);
- ath12k_dp_rx_h_undecap(ar, msdu, desc,
+ ath12k_dp_rx_h_undecap(dp_pdev, msdu, desc,
HAL_ENCRYPT_TYPE_TKIP_MIC, false, rx_info);
return false;
}
-static bool ath12k_wifi7_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu,
+static bool ath12k_wifi7_dp_rx_h_rxdma_err(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
bool drop = false;
- ar->ab->device_stats.rxdma_error[rxcb->err_code]++;
+ dp->ab->device_stats.rxdma_error[rxcb->err_code]++;
switch (rxcb->err_code) {
case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR:
case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
if (rx_info->err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
- drop = ath12k_wifi7_dp_rx_h_tkip_mic_err(ar, msdu, rx_info);
+ drop = ath12k_wifi7_dp_rx_h_tkip_mic_err(dp_pdev, msdu, rx_info);
break;
}
fallthrough;
return drop;
}
-static bool ath12k_wifi7_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
+static bool ath12k_wifi7_dp_rx_h_reo_err(struct ath12k_pdev_dp *dp_pdev,
+ struct sk_buff *msdu,
struct hal_rx_desc_data *rx_info,
struct sk_buff_head *msdu_list)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
bool drop = false;
- ar->ab->device_stats.reo_error[rxcb->err_code]++;
+ dp->ab->device_stats.reo_error[rxcb->err_code]++;
switch (rxcb->err_code) {
case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
- if (ath12k_wifi7_dp_rx_h_null_q_desc(ar, msdu, rx_info, msdu_list))
+ if (ath12k_wifi7_dp_rx_h_null_q_desc(dp_pdev, msdu, rx_info, msdu_list))
drop = true;
break;
case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED:
return drop;
}
-static void ath12k_wifi7_dp_rx_wbm_err(struct ath12k *ar,
+static void ath12k_wifi7_dp_rx_wbm_err(struct ath12k_pdev_dp *dp_pdev,
struct napi_struct *napi,
struct sk_buff *msdu,
struct sk_buff_head *msdu_list)
{
+ struct ath12k_dp *dp = dp_pdev->dp;
struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
struct ieee80211_rx_status rxs = {};
rx_info.addr2_present = false;
rx_info.rx_status = &rxs;
- ath12k_wifi7_dp_extract_rx_desc_data(ar->ab, &rx_info, rx_desc, rx_desc);
+ ath12k_wifi7_dp_extract_rx_desc_data(dp->ab, &rx_info, rx_desc, rx_desc);
switch (rxcb->err_rel_src) {
case HAL_WBM_REL_SRC_MODULE_REO:
- drop = ath12k_wifi7_dp_rx_h_reo_err(ar, msdu, &rx_info, msdu_list);
+ drop = ath12k_wifi7_dp_rx_h_reo_err(dp_pdev, msdu, &rx_info, msdu_list);
break;
case HAL_WBM_REL_SRC_MODULE_RXDMA:
- drop = ath12k_wifi7_dp_rx_h_rxdma_err(ar, msdu, &rx_info);
+ drop = ath12k_wifi7_dp_rx_h_rxdma_err(dp_pdev, msdu, &rx_info);
break;
default:
/* msdu will get freed */
rx_info.rx_status->flag |= RX_FLAG_SKIP_MONITOR;
- ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info);
+ ath12k_dp_rx_deliver_msdu(dp_pdev, napi, msdu, &rx_info);
}
void ath12k_wifi7_dp_setup_pn_check_reo_cmd(struct ath12k_hal_reo_cmd *cmd,
{
struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
struct ath12k *ar;
+ struct ath12k_pdev_dp *dp_pdev;
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_hw_group *ag = dp->ag;
struct ath12k_dp_hw_group *dp_hw_grp = &ag->dp_hw_grp;
struct ath12k_rx_desc_info *desc_info;
struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
struct ath12k_hw_link *hw_links = ag->hw_links;
- struct ath12k_base *partner_ab;
u8 hw_link_id, device_id;
- int ret, pdev_id;
+ int ret, pdev_idx;
struct hal_rx_desc *msdu_data;
__skb_queue_head_init(&msdu_list);
continue;
}
- partner_ab = partner_dp->ab;
-
list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
rxcb = ATH12K_SKB_RXCB(msdu);
continue;
}
- hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_ab,
+ hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_dp->ab,
msdu_data);
if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) {
dev_kfree_skb_any(msdu);
continue;
}
- pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_dp->hw_params,
- hw_links[hw_link_id].pdev_idx);
- partner_ab = partner_dp->ab;
- ar = partner_ab->pdevs[pdev_id].ar;
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(partner_dp->hw_params,
+ hw_links[hw_link_id].pdev_idx);
+
+ dp_pdev = ath12k_dp_to_pdev_dp(partner_dp, pdev_idx);
+ if (!dp_pdev) {
+ dev_kfree_skb_any(msdu);
+ continue;
+ }
+ ar = ath12k_pdev_dp_to_ar(dp_pdev);
- if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_id])) {
+ if (!ar || !rcu_dereference(ar->ab->pdevs_active[pdev_idx])) {
dev_kfree_skb_any(msdu);
continue;
}
device_stats->rx_wbm_rel_source[rxcb->err_rel_src][device_id]++;
}
- ath12k_wifi7_dp_rx_wbm_err(ar, napi, msdu, &msdu_list);
+ ath12k_wifi7_dp_rx_wbm_err(dp_pdev, napi, msdu, &msdu_list);
}
rcu_read_unlock();
done:
return 0;
}
-int ath12k_wifi7_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
+int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif,
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
bool is_mcast)
{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct hal_tx_info ti = {};
struct ath12k_tx_desc_info *tx_desc;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool is_diff_encap = false;
bool is_null_frame = false;
- if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
return -ESHUTDOWN;
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
ti.meta_data_flags = dp_link_vif->tcl_metadata;
if (dp_vif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
- test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
+ test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags)) {
if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
ti.encrypt_type =
ath12k_dp_tx_get_encrypt_type(skb_cb->cipher);
goto fail_remove_tx_buf;
}
- if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
+ if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags) &&
!(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
!(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
ieee80211_has_protected(hdr->frame_control)) ||
ti.desc_id = tx_desc->desc_id;
ti.data_len = skb->len;
skb_cb->paddr = ti.paddr;
- skb_cb->ar = ar;
if (msdu_ext_desc) {
skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc));
ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ",
skb->data, skb->len);
- atomic_inc(&ar->dp.num_tx_pending);
+ atomic_inc(&dp_pdev->num_tx_pending);
return 0;
}
}
-static void
-ath12k_wifi7_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status *ts)
+static void ath12k_wifi7_dp_tx_update_txcompl(struct ath12k_pdev_dp *dp_pdev,
+ struct hal_tx_status *ts)
{
- struct ath12k_base *ab = ar->ab;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ath12k_peer *peer;
struct ieee80211_sta *sta;
struct ath12k_sta *ahsta;
spin_unlock_bh(&ab->base_lock);
}
-static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k *ar,
+static void ath12k_wifi7_dp_tx_complete_msdu(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_tx_desc_params *desc_params,
struct hal_tx_status *ts,
int ring)
{
- struct ath12k_base *ab = ar->ab;
- struct ath12k_hw *ah = ar->ah;
+ struct ath12k_dp *dp = dp_pdev->dp;
+ struct ath12k_base *ab = dp->ab;
struct ieee80211_tx_info *info;
struct ath12k_link_vif *arvif;
struct ath12k_skb_cb *skb_cb;
rcu_read_lock();
- if (!rcu_dereference(ab->pdevs_active[ar->pdev_idx])) {
- ieee80211_free_txskb(ah->hw, msdu);
+ if (!rcu_dereference(ab->pdevs_active[dp_pdev->mac_id])) {
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
goto exit;
}
if (!skb_cb->vif) {
- ieee80211_free_txskb(ah->hw, msdu);
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
goto exit;
}
if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
ab->wmi_ab.svc_map)) {
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+
spin_lock_bh(&ar->data_lock);
noise_floor = ath12k_pdev_get_noise_floor(ar);
spin_unlock_bh(&ar->data_lock);
* hence drop the frame; do not update the status of frame to
* the upper layer
*/
- ieee80211_free_txskb(ah->hw, msdu);
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
goto exit;
default:
ath12k_dbg(ab, ATH12K_DBG_DP_TX, "tx frame is not acked status %d\n",
* Might end up reporting it out-of-band from HTT stats.
*/
- ath12k_wifi7_dp_tx_update_txcompl(ar, ts);
+ ath12k_wifi7_dp_tx_update_txcompl(dp_pdev, ts);
spin_lock_bh(&ab->base_lock);
peer = ath12k_peer_find_by_id(ab, ts->peer_id);
"dp_tx: failed to find the peer with peer_id %d\n",
ts->peer_id);
spin_unlock_bh(&ab->base_lock);
- ieee80211_free_txskb(ath12k_ar_to_hw(ar), msdu);
+ ieee80211_free_txskb(ath12k_pdev_dp_to_hw(dp_pdev), msdu);
goto exit;
}
ahsta = ath12k_sta_to_ahsta(peer->sta);
status.rates = &status_rate;
status.n_rates = 1;
- ieee80211_tx_status_ext(ath12k_ar_to_hw(ar), &status);
+ ieee80211_tx_status_ext(ath12k_pdev_dp_to_hw(dp_pdev), &status);
exit:
rcu_read_unlock();
void ath12k_wifi7_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
{
- struct ath12k *ar;
+ struct ath12k_pdev_dp *dp_pdev;
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id;
struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id];
struct ath12k_tx_desc_params desc_params;
struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
struct hal_wbm_release_ring *desc;
- u8 pdev_id;
+ u8 pdev_idx;
u64 desc_va;
enum hal_wbm_rel_src_module buf_rel_source;
enum hal_wbm_tqm_rel_reason rel_status;
continue;
}
- pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, desc_params.mac_id);
- ar = ab->pdevs[pdev_id].ar;
+ pdev_idx = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, desc_params.mac_id);
- if (atomic_dec_and_test(&ar->dp.num_tx_pending))
- wake_up(&ar->dp.tx_empty_waitq);
+ rcu_read_lock();
+
+ dp_pdev = ath12k_dp_to_pdev_dp(dp, pdev_idx);
+ if (!dp_pdev) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ if (atomic_dec_and_test(&dp_pdev->num_tx_pending))
+ wake_up(&dp_pdev->tx_empty_waitq);
- ath12k_wifi7_dp_tx_complete_msdu(ar, &desc_params, &ts,
+ ath12k_wifi7_dp_tx_complete_msdu(dp_pdev, &desc_params, &ts,
tx_ring->tcl_data_ring_id);
+ rcu_read_unlock();
}
}
#ifndef ATH12K_DP_TX_WIFI7_H
#define ATH12K_DP_TX_WIFI7_H
-int ath12k_wifi7_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
+int ath12k_wifi7_dp_tx(struct ath12k_pdev_dp *dp_pdev, struct ath12k_link_vif *arvif,
struct sk_buff *skb, bool gsn_valid, int mcbc_gsn,
bool is_mcast);
void ath12k_wifi7_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id);