Path: blob/main/sys/contrib/dev/athk/ath11k/p2p.c
106751 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/*2* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.3*/45#include "core.h"6#include "wmi.h"7#include "mac.h"8#include "p2p.h"910static void ath11k_p2p_noa_ie_fill(u8 *data, size_t len,11const struct ath11k_wmi_p2p_noa_info *noa)12{13struct ieee80211_p2p_noa_attr *noa_attr;14u8 noa_descriptors, ctwindow;15bool oppps;16__le16 *noa_attr_len;17u16 attr_len;18int i;1920ctwindow = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_CTWIN_TU);21oppps = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS);22noa_descriptors = u32_get_bits(noa->noa_attr,23WMI_P2P_NOA_INFO_DESC_NUM);2425/* P2P IE */26data[0] = WLAN_EID_VENDOR_SPECIFIC;27data[1] = len - 2;28data[2] = (WLAN_OUI_WFA >> 16) & 0xff;29data[3] = (WLAN_OUI_WFA >> 8) & 0xff;30data[4] = (WLAN_OUI_WFA >> 0) & 0xff;31data[5] = WLAN_OUI_TYPE_WFA_P2P;3233/* NOA ATTR */34data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;35noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */36noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];3738noa_attr->index = u32_get_bits(noa->noa_attr,39WMI_P2P_NOA_INFO_INDEX);40noa_attr->oppps_ctwindow = ctwindow;41if (oppps)42noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;4344for (i = 0; i < noa_descriptors; i++) {45noa_attr->desc[i].count = noa->descriptors[i].type_count;46noa_attr->desc[i].duration =47cpu_to_le32(noa->descriptors[i].duration);48noa_attr->desc[i].interval =49cpu_to_le32(noa->descriptors[i].interval);50noa_attr->desc[i].start_time =51cpu_to_le32(noa->descriptors[i].start_time);52}5354attr_len = 2; /* index + oppps_ctwindow */55attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);56*noa_attr_len = __cpu_to_le16(attr_len);57}5859static size_t60ath11k_p2p_noa_ie_len_compute(const struct ath11k_wmi_p2p_noa_info *noa)61{62size_t len = 0;63u8 noa_descriptors = u32_get_bits(noa->noa_attr,64WMI_P2P_NOA_INFO_DESC_NUM);6566if (!(noa_descriptors) &&67!(u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS)))68return 0;6970len += 1 + 1 + 4; /* EID + len + OUI */71len += 1 + 2; /* noa attr + attr len */72len += 1 + 1; /* index + oppps_ctwindow */73len += noa_descriptors *74sizeof(struct ieee80211_p2p_noa_desc);7576return len;77}7879static void ath11k_p2p_noa_ie_assign(struct ath11k_vif *arvif, void *ie,80size_t len)81{82struct ath11k *ar = arvif->ar;8384lockdep_assert_held(&ar->data_lock);8586kfree(arvif->u.ap.noa_data);8788arvif->u.ap.noa_data = ie;89arvif->u.ap.noa_len = len;90}9192static void __ath11k_p2p_noa_update(struct ath11k_vif *arvif,93const struct ath11k_wmi_p2p_noa_info *noa)94{95struct ath11k *ar = arvif->ar;96void *ie;97size_t len;9899lockdep_assert_held(&ar->data_lock);100101ath11k_p2p_noa_ie_assign(arvif, NULL, 0);102103len = ath11k_p2p_noa_ie_len_compute(noa);104if (!len)105return;106107ie = kmalloc(len, GFP_ATOMIC);108if (!ie)109return;110111ath11k_p2p_noa_ie_fill(ie, len, noa);112ath11k_p2p_noa_ie_assign(arvif, ie, len); }113114void ath11k_p2p_noa_update(struct ath11k_vif *arvif,115const struct ath11k_wmi_p2p_noa_info *noa)116{117struct ath11k *ar = arvif->ar;118119spin_lock_bh(&ar->data_lock);120__ath11k_p2p_noa_update(arvif, noa);121spin_unlock_bh(&ar->data_lock);122}123124static void ath11k_p2p_noa_update_vdev_iter(void *data, u8 *mac,125struct ieee80211_vif *vif)126{127struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);128struct ath11k_p2p_noa_arg *arg = data;129130if (arvif->vdev_id != arg->vdev_id)131return;132133ath11k_p2p_noa_update(arvif, arg->noa);134}135136void ath11k_p2p_noa_update_by_vdev_id(struct ath11k *ar, u32 vdev_id,137const struct ath11k_wmi_p2p_noa_info *noa)138{139struct ath11k_p2p_noa_arg arg = {140.vdev_id = vdev_id,141.noa = noa,142};143144ieee80211_iterate_active_interfaces_atomic(ar->hw,145IEEE80211_IFACE_ITER_NORMAL,146ath11k_p2p_noa_update_vdev_iter,147&arg);148}149150151