Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v6.4. Major changes: ath10k * enable threaded napi on WCN3990 ath11k * push MU-MIMO params from hostapd to hardware * tx ack signal support for management packets
This commit is contained in:
commit
4c4ca9f7c4
@ -96,11 +96,13 @@ struct ath_keyval {
|
||||
u8 kv_type;
|
||||
u8 kv_pad;
|
||||
u16 kv_len;
|
||||
u8 kv_val[16]; /* TK */
|
||||
u8 kv_mic[8]; /* Michael MIC key */
|
||||
u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
|
||||
* supports both MIC keys in the same key cache entry;
|
||||
* in that case, kv_mic is the RX key) */
|
||||
struct_group(kv_values,
|
||||
u8 kv_val[16]; /* TK */
|
||||
u8 kv_mic[8]; /* Michael MIC key */
|
||||
u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
|
||||
* supports both MIC keys in the same key cache entry;
|
||||
* in that case, kv_mic is the RX key) */
|
||||
);
|
||||
};
|
||||
|
||||
enum ath_cipher {
|
||||
|
@ -77,45 +77,6 @@ static inline u32 shadow_sr_wr_ind_addr(struct ath10k *ar,
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline u32 shadow_dst_wr_ind_addr(struct ath10k *ar,
|
||||
struct ath10k_ce_pipe *ce_state)
|
||||
{
|
||||
u32 ce_id = ce_state->id;
|
||||
u32 addr = 0;
|
||||
|
||||
switch (ce_id) {
|
||||
case 1:
|
||||
addr = 0x00032034;
|
||||
break;
|
||||
case 2:
|
||||
addr = 0x00032038;
|
||||
break;
|
||||
case 5:
|
||||
addr = 0x00032044;
|
||||
break;
|
||||
case 7:
|
||||
addr = 0x0003204C;
|
||||
break;
|
||||
case 8:
|
||||
addr = 0x00032050;
|
||||
break;
|
||||
case 9:
|
||||
addr = 0x00032054;
|
||||
break;
|
||||
case 10:
|
||||
addr = 0x00032058;
|
||||
break;
|
||||
case 11:
|
||||
addr = 0x0003205C;
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "invalid CE id: %d", ce_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ath10k_set_ring_byte(unsigned int offset,
|
||||
struct ath10k_hw_ce_regs_addr_map *addr_map)
|
||||
@ -438,19 +399,6 @@ static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
|
||||
host_ie_addr & ~(wm_regs->wm_mask));
|
||||
}
|
||||
|
||||
static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
|
||||
u32 ce_ctrl_addr)
|
||||
{
|
||||
struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
|
||||
|
||||
u32 misc_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
|
||||
ar->hw_ce_regs->misc_ie_addr);
|
||||
|
||||
ath10k_ce_write32(ar,
|
||||
ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
|
||||
misc_ie_addr | misc_regs->err_mask);
|
||||
}
|
||||
|
||||
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
|
||||
u32 ce_ctrl_addr)
|
||||
{
|
||||
|
@ -6030,7 +6030,6 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
changed_flags &= SUPPORTED_FILTERS;
|
||||
*total_flags &= SUPPORTED_FILTERS;
|
||||
ar->filter_flags = *total_flags;
|
||||
|
||||
|
@ -927,6 +927,7 @@ static int ath10k_snoc_hif_start(struct ath10k *ar)
|
||||
|
||||
bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);
|
||||
|
||||
dev_set_threaded(&ar->napi_dev, true);
|
||||
ath10k_core_napi_enable(ar);
|
||||
ath10k_snoc_irq_enable(ar);
|
||||
ath10k_snoc_rx_post(ar);
|
||||
|
@ -874,11 +874,11 @@ static int ath11k_ahb_setup_msi_resources(struct ath11k_base *ab)
|
||||
ab->pci.msi.ep_base_data = int_prop + 32;
|
||||
|
||||
for (i = 0; i < ab->pci.msi.config->total_vectors; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
ret = platform_get_irq(pdev, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ab->pci.msi.irqs[i] = res->start;
|
||||
ab->pci.msi.irqs[i] = ret;
|
||||
}
|
||||
|
||||
set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
|
||||
@ -1174,7 +1174,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
* to a new space for accessing them.
|
||||
*/
|
||||
ab->mem_ce = ioremap(ce_remap->base, ce_remap->size);
|
||||
if (IS_ERR(ab->mem_ce)) {
|
||||
if (!ab->mem_ce) {
|
||||
dev_err(&pdev->dev, "ce ioremap error\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_core_free;
|
||||
|
@ -201,6 +201,7 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
|
||||
config->twt_ap_pdev_count = ab->num_radios;
|
||||
config->twt_ap_sta_count = 1000;
|
||||
config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64;
|
||||
config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI;
|
||||
}
|
||||
|
||||
static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw,
|
||||
|
@ -2699,6 +2699,117 @@ static int ath11k_setup_peer_smps(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
ath11k_smps_map[smps]);
|
||||
}
|
||||
|
||||
static bool ath11k_mac_set_he_txbf_conf(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
u32 param, value;
|
||||
int ret;
|
||||
|
||||
if (!arvif->vif->bss_conf.he_support)
|
||||
return true;
|
||||
|
||||
param = WMI_VDEV_PARAM_SET_HEMU_MODE;
|
||||
value = 0;
|
||||
if (arvif->vif->bss_conf.he_su_beamformer) {
|
||||
value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
|
||||
if (arvif->vif->bss_conf.he_mu_beamformer &&
|
||||
arvif->vdev_type == WMI_VDEV_TYPE_AP)
|
||||
value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE);
|
||||
}
|
||||
|
||||
if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
|
||||
value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
|
||||
|
||||
if (arvif->vif->bss_conf.he_full_ul_mumimo)
|
||||
value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE);
|
||||
|
||||
if (arvif->vif->bss_conf.he_su_beamformee)
|
||||
value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
|
||||
value = FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) |
|
||||
FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE,
|
||||
HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE);
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param, value);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta_he_cap *he_cap)
|
||||
{
|
||||
struct ath11k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ieee80211_he_cap_elem he_cap_elem = {0};
|
||||
struct ieee80211_sta_he_cap *cap_band = NULL;
|
||||
struct cfg80211_chan_def def;
|
||||
u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE;
|
||||
u32 hemode = 0;
|
||||
int ret;
|
||||
|
||||
if (!vif->bss_conf.he_support)
|
||||
return true;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return false;
|
||||
|
||||
if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
|
||||
return false;
|
||||
|
||||
if (def.chan->band == NL80211_BAND_2GHZ)
|
||||
cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap;
|
||||
else
|
||||
cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap;
|
||||
|
||||
memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem));
|
||||
|
||||
if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) {
|
||||
if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
|
||||
hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
|
||||
if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
|
||||
hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE);
|
||||
}
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_MESH_POINT) {
|
||||
hemode |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
|
||||
|
||||
if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info))
|
||||
if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info))
|
||||
hemode |= FIELD_PREP(HE_MODE_UL_MUMIMO,
|
||||
HE_UL_MUMIMO_ENABLE);
|
||||
|
||||
if (FIELD_GET(HE_MODE_MU_TX_BFEE, hemode))
|
||||
hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
|
||||
|
||||
if (FIELD_GET(HE_MODE_MU_TX_BFER, hemode))
|
||||
hemode |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, hemode);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n",
|
||||
hemode, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
@ -2709,6 +2820,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *ap_sta;
|
||||
struct ath11k_peer *peer;
|
||||
bool is_auth = false;
|
||||
struct ieee80211_sta_he_cap he_cap;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
@ -2726,6 +2838,9 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
return;
|
||||
}
|
||||
|
||||
/* he_cap here is updated at assoc success for sta mode only */
|
||||
he_cap = ap_sta->deflink.he_cap;
|
||||
|
||||
ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
|
||||
|
||||
rcu_read_unlock();
|
||||
@ -2753,6 +2868,12 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) {
|
||||
ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n",
|
||||
arvif->vdev_id, bss_conf->bssid);
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_ON(arvif->is_up);
|
||||
|
||||
arvif->aid = vif->cfg.aid;
|
||||
@ -3202,6 +3323,8 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
ether_addr_copy(arvif->bssid, info->bssid);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (info->enable_beacon)
|
||||
ath11k_mac_set_he_txbf_conf(arvif);
|
||||
ath11k_control_beaconing(arvif, info);
|
||||
|
||||
if (arvif->is_up && vif->bss_conf.he_support &&
|
||||
@ -5360,6 +5483,43 @@ static __le16 ath11k_mac_setup_he_6ghz_cap(struct ath11k_pdev_cap *pcap,
|
||||
return cpu_to_le16(bcap->he_6ghz_capa);
|
||||
}
|
||||
|
||||
static void ath11k_mac_set_hemcsmap(struct ath11k *ar,
|
||||
struct ath11k_pdev_cap *cap,
|
||||
struct ieee80211_sta_he_cap *he_cap,
|
||||
int band)
|
||||
{
|
||||
u16 txmcs_map, rxmcs_map;
|
||||
u32 i;
|
||||
|
||||
rxmcs_map = 0;
|
||||
txmcs_map = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i < ar->num_tx_chains &&
|
||||
(ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
|
||||
txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
|
||||
else
|
||||
txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
|
||||
|
||||
if (i < ar->num_rx_chains &&
|
||||
(ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
|
||||
rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
|
||||
else
|
||||
rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
|
||||
}
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80 =
|
||||
cpu_to_le16(rxmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80 =
|
||||
cpu_to_le16(txmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_160 =
|
||||
cpu_to_le16(rxmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_160 =
|
||||
cpu_to_le16(txmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
|
||||
cpu_to_le16(rxmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
|
||||
cpu_to_le16(txmcs_map & 0xffff);
|
||||
}
|
||||
|
||||
static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
||||
struct ath11k_pdev_cap *cap,
|
||||
struct ieee80211_sband_iftype_data *data,
|
||||
@ -5392,6 +5552,10 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
||||
|
||||
he_cap_elem->mac_cap_info[1] &=
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
|
||||
he_cap_elem->phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
he_cap_elem->phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[5] &=
|
||||
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
|
||||
@ -5417,18 +5581,7 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
||||
break;
|
||||
}
|
||||
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80 =
|
||||
cpu_to_le16(band_cap->he_mcs & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80 =
|
||||
cpu_to_le16(band_cap->he_mcs & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_160 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_160 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
ath11k_mac_set_hemcsmap(ar, cap, he_cap, band);
|
||||
|
||||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
@ -6026,69 +6179,6 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
|
||||
}
|
||||
}
|
||||
|
||||
static u32
|
||||
ath11k_mac_prepare_he_mode(struct ath11k_pdev *pdev, u32 viftype)
|
||||
{
|
||||
struct ath11k_pdev_cap *pdev_cap = &pdev->cap;
|
||||
struct ath11k_band_cap *cap_band = NULL;
|
||||
u32 *hecap_phy_ptr = NULL;
|
||||
u32 hemode = 0;
|
||||
|
||||
if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP)
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
|
||||
else
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
|
||||
|
||||
hecap_phy_ptr = &cap_band->he_cap_phy_info[0];
|
||||
|
||||
hemode = FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_SU_TX_BFER, HECAP_PHY_SUBFMR_GET(hecap_phy_ptr)) |
|
||||
FIELD_PREP(HE_MODE_UL_MUMIMO, HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr));
|
||||
|
||||
/* TODO WDS and other modes */
|
||||
if (viftype == NL80211_IFTYPE_AP) {
|
||||
hemode |= FIELD_PREP(HE_MODE_MU_TX_BFER,
|
||||
HECAP_PHY_MUBFMR_GET(hecap_phy_ptr)) |
|
||||
FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
|
||||
} else {
|
||||
hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE);
|
||||
}
|
||||
|
||||
return hemode;
|
||||
}
|
||||
|
||||
static int ath11k_set_he_mu_sounding_mode(struct ath11k *ar,
|
||||
struct ath11k_vif *arvif)
|
||||
{
|
||||
u32 param_id, param_value;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
int ret = 0;
|
||||
|
||||
param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
|
||||
param_value = ath11k_mac_prepare_he_mode(ar->pdev, arvif->vif->type);
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, param_value);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n",
|
||||
arvif->vdev_id, ret, param_value);
|
||||
return ret;
|
||||
}
|
||||
param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
|
||||
param_value =
|
||||
FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) |
|
||||
FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE,
|
||||
HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE);
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, param_value);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -6757,7 +6847,6 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct wmi_vdev_start_req_arg arg = {};
|
||||
const struct cfg80211_chan_def *chandef = &ctx->def;
|
||||
int he_support = arvif->vif->bss_conf.he_support;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
@ -6798,15 +6887,6 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
arg.regdomain = ar->ab->dfs_region;
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
if (he_support) {
|
||||
ret = ath11k_set_he_mu_sounding_mode(ar, arvif);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set he mode vdev %i\n",
|
||||
arg.vdev_id);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
|
||||
@ -9094,6 +9174,11 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
goto err_free_if_combs;
|
||||
}
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
|
||||
ar->hw->queues = ATH11K_HW_MAX_QUEUES;
|
||||
ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN;
|
||||
ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1;
|
||||
|
@ -382,22 +382,23 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr);
|
||||
if (peer) {
|
||||
if (peer->vdev_id == param->vdev_id) {
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Assume sta is transitioning to another band.
|
||||
* Remove here the peer from rhash.
|
||||
*/
|
||||
mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
ath11k_peer_rhash_delete(ar->ab, peer);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
}
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
|
||||
ret = ath11k_wmi_send_peer_create_cmd(ar, param);
|
||||
if (ret) {
|
||||
|
@ -613,13 +613,19 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
{
|
||||
struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL;
|
||||
struct cur_reg_rule *reg_rule;
|
||||
u8 i = 0, j = 0;
|
||||
u8 i = 0, j = 0, k = 0;
|
||||
u8 num_rules;
|
||||
u16 max_bw;
|
||||
u32 flags;
|
||||
char alpha2[3];
|
||||
|
||||
num_rules = reg_info->num_5g_reg_rules + reg_info->num_2g_reg_rules;
|
||||
num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules;
|
||||
|
||||
/* FIXME: Currently taking reg rules for 6 GHz only from Indoor AP mode list.
|
||||
* This can be updated after complete 6 GHz regulatory support is added.
|
||||
*/
|
||||
if (reg_info->is_ext_reg_event)
|
||||
num_rules += reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP];
|
||||
|
||||
if (!num_rules)
|
||||
goto ret;
|
||||
@ -640,24 +646,24 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
tmp_regd->dfs_region = ath11k_map_fw_dfs_region(reg_info->dfs_region);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\r\nCountry %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n",
|
||||
"Country %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n",
|
||||
alpha2, ath11k_reg_get_regdom_str(tmp_regd->dfs_region),
|
||||
reg_info->dfs_region, num_rules);
|
||||
/* Update reg_rules[] below. Firmware is expected to
|
||||
* send these rules in order(2G rules first and then 5G)
|
||||
* send these rules in order(2 GHz rules first and then 5 GHz)
|
||||
*/
|
||||
for (; i < num_rules; i++) {
|
||||
if (reg_info->num_2g_reg_rules &&
|
||||
(i < reg_info->num_2g_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_2g_ptr + i;
|
||||
if (reg_info->num_2ghz_reg_rules &&
|
||||
(i < reg_info->num_2ghz_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_2ghz_ptr + i;
|
||||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_2g);
|
||||
reg_info->max_bw_2ghz);
|
||||
flags = 0;
|
||||
} else if (reg_info->num_5g_reg_rules &&
|
||||
(j < reg_info->num_5g_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_5g_ptr + j++;
|
||||
} else if (reg_info->num_5ghz_reg_rules &&
|
||||
(j < reg_info->num_5ghz_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_5ghz_ptr + j++;
|
||||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_5g);
|
||||
reg_info->max_bw_5ghz);
|
||||
|
||||
/* FW doesn't pass NL80211_RRF_AUTO_BW flag for
|
||||
* BW Auto correction, we can enable this by default
|
||||
@ -666,6 +672,14 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
* per other BW rule flags we pass from here
|
||||
*/
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
} else if (reg_info->is_ext_reg_event &&
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] &&
|
||||
(k < reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP])) {
|
||||
reg_rule = reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP] +
|
||||
k++;
|
||||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP]);
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -693,12 +707,21 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
continue;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
|
||||
i + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
|
||||
tmp_regd->reg_rules[i].dfs_cac_ms,
|
||||
flags);
|
||||
if (reg_info->is_ext_reg_event) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n",
|
||||
i + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
|
||||
tmp_regd->reg_rules[i].dfs_cac_ms, flags,
|
||||
reg_rule->psd_flag, reg_rule->psd_eirp);
|
||||
} else {
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
|
||||
i + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
|
||||
tmp_regd->reg_rules[i].dfs_cac_ms,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
tmp_regd->n_reg_rules = i;
|
||||
|
@ -105,6 +105,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
||||
= { .min_len = sizeof(struct wmi_vdev_stopped_event) },
|
||||
[WMI_TAG_REG_CHAN_LIST_CC_EVENT]
|
||||
= { .min_len = sizeof(struct wmi_reg_chan_list_cc_event) },
|
||||
[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]
|
||||
= { .min_len = sizeof(struct wmi_reg_chan_list_cc_ext_event) },
|
||||
[WMI_TAG_MGMT_RX_HDR]
|
||||
= { .min_len = sizeof(struct wmi_mgmt_rx_hdr) },
|
||||
[WMI_TAG_MGMT_TX_COMPL_EVENT]
|
||||
@ -2068,6 +2070,12 @@ void ath11k_wmi_start_scan_init(struct ath11k *ar,
|
||||
WMI_SCAN_EVENT_FOREIGN_CHAN |
|
||||
WMI_SCAN_EVENT_DEQUEUED;
|
||||
arg->scan_flags |= WMI_SCAN_CHAN_STAT_EVENT;
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
arg->scan_ctrl_flags_ext |=
|
||||
WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE;
|
||||
|
||||
arg->num_bssid = 1;
|
||||
|
||||
/* fill bssid_list[0] with 0xff, otherwise bssid and RA will be
|
||||
@ -2149,6 +2157,8 @@ ath11k_wmi_copy_scan_event_cntrl_flags(struct wmi_start_scan_cmd *cmd,
|
||||
/* for adaptive scan mode using 3 bits (21 - 23 bits) */
|
||||
WMI_SCAN_SET_DWELL_MODE(cmd->scan_ctrl_flags,
|
||||
param->adaptive_dwell_time_mode);
|
||||
|
||||
cmd->scan_ctrl_flags_ext = param->scan_ctrl_flags_ext;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
@ -3966,6 +3976,10 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
|
||||
wmi_cfg->sched_params = tg_cfg->sched_params;
|
||||
wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count;
|
||||
wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count;
|
||||
wmi_cfg->host_service_flags &=
|
||||
~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
|
||||
wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported <<
|
||||
WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
|
||||
}
|
||||
|
||||
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
|
||||
@ -4184,6 +4198,10 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
|
||||
ab->hw_params.hw_ops->wmi_init_config(ab, &config);
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
|
||||
ab->wmi_ab.svc_map))
|
||||
config.is_reg_cc_ext_event_supported = 1;
|
||||
|
||||
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
|
||||
|
||||
init_param.res_cfg = &wmi_sc->wlan_resource_config;
|
||||
@ -4907,6 +4925,26 @@ static int ath11k_pull_vdev_start_resp_tlv(struct ath11k_base *ab, struct sk_buf
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_print_reg_rule(struct ath11k_base *ab, const char *band,
|
||||
u32 num_reg_rules,
|
||||
struct cur_reg_rule *reg_rule_ptr)
|
||||
{
|
||||
struct cur_reg_rule *reg_rule = reg_rule_ptr;
|
||||
u32 count;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "number of reg rules in %s band: %d\n",
|
||||
band, num_reg_rules);
|
||||
|
||||
for (count = 0; count < num_reg_rules; count++) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"reg rule %d: (%d - %d @ %d) (%d, %d) (FLAGS %d)\n",
|
||||
count + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
reg_rule->max_bw, reg_rule->ant_gain,
|
||||
reg_rule->reg_power, reg_rule->flags);
|
||||
reg_rule++;
|
||||
}
|
||||
}
|
||||
|
||||
static struct cur_reg_rule
|
||||
*create_reg_rules_from_wmi(u32 num_reg_rules,
|
||||
struct wmi_regulatory_rule_struct *wmi_reg_rule)
|
||||
@ -4951,7 +4989,7 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
const void **tb;
|
||||
const struct wmi_reg_chan_list_cc_event *chan_list_event_hdr;
|
||||
struct wmi_regulatory_rule_struct *wmi_reg_rule;
|
||||
u32 num_2g_reg_rules, num_5g_reg_rules;
|
||||
u32 num_2ghz_reg_rules, num_5ghz_reg_rules;
|
||||
int ret;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory channel list\n");
|
||||
@ -4970,10 +5008,10 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
reg_info->num_2g_reg_rules = chan_list_event_hdr->num_2g_reg_rules;
|
||||
reg_info->num_5g_reg_rules = chan_list_event_hdr->num_5g_reg_rules;
|
||||
reg_info->num_2ghz_reg_rules = chan_list_event_hdr->num_2ghz_reg_rules;
|
||||
reg_info->num_5ghz_reg_rules = chan_list_event_hdr->num_5ghz_reg_rules;
|
||||
|
||||
if (!(reg_info->num_2g_reg_rules + reg_info->num_5g_reg_rules)) {
|
||||
if (!(reg_info->num_2ghz_reg_rules + reg_info->num_5ghz_reg_rules)) {
|
||||
ath11k_warn(ab, "No regulatory rules available in the event info\n");
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
@ -4987,61 +5025,68 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
reg_info->phy_id = chan_list_event_hdr->phy_id;
|
||||
reg_info->ctry_code = chan_list_event_hdr->country_id;
|
||||
reg_info->reg_dmn_pair = chan_list_event_hdr->domain_code;
|
||||
if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_PASS)
|
||||
reg_info->status_code = REG_SET_CC_STATUS_PASS;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_CURRENT_ALPHA2_NOT_FOUND)
|
||||
reg_info->status_code = REG_CURRENT_ALPHA2_NOT_FOUND;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_INIT_ALPHA2_NOT_FOUND)
|
||||
reg_info->status_code = REG_INIT_ALPHA2_NOT_FOUND;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_CHANGE_NOT_ALLOWED)
|
||||
reg_info->status_code = REG_SET_CC_CHANGE_NOT_ALLOWED;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_NO_MEMORY)
|
||||
reg_info->status_code = REG_SET_CC_STATUS_NO_MEMORY;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_FAIL)
|
||||
reg_info->status_code = REG_SET_CC_STATUS_FAIL;
|
||||
|
||||
reg_info->min_bw_2g = chan_list_event_hdr->min_bw_2g;
|
||||
reg_info->max_bw_2g = chan_list_event_hdr->max_bw_2g;
|
||||
reg_info->min_bw_5g = chan_list_event_hdr->min_bw_5g;
|
||||
reg_info->max_bw_5g = chan_list_event_hdr->max_bw_5g;
|
||||
|
||||
num_2g_reg_rules = reg_info->num_2g_reg_rules;
|
||||
num_5g_reg_rules = reg_info->num_5g_reg_rules;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"%s:cc %s dsf %d BW: min_2g %d max_2g %d min_5g %d max_5g %d",
|
||||
__func__, reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2g, reg_info->max_bw_2g,
|
||||
reg_info->min_bw_5g, reg_info->max_bw_5g);
|
||||
"status_code %s",
|
||||
ath11k_cc_status_to_str(reg_info->status_code));
|
||||
|
||||
reg_info->status_code =
|
||||
ath11k_wmi_cc_setting_code_to_reg(chan_list_event_hdr->status_code);
|
||||
|
||||
reg_info->is_ext_reg_event = false;
|
||||
|
||||
reg_info->min_bw_2ghz = chan_list_event_hdr->min_bw_2ghz;
|
||||
reg_info->max_bw_2ghz = chan_list_event_hdr->max_bw_2ghz;
|
||||
reg_info->min_bw_5ghz = chan_list_event_hdr->min_bw_5ghz;
|
||||
reg_info->max_bw_5ghz = chan_list_event_hdr->max_bw_5ghz;
|
||||
|
||||
num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules;
|
||||
num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"%s: num_2g_reg_rules %d num_5g_reg_rules %d", __func__,
|
||||
num_2g_reg_rules, num_5g_reg_rules);
|
||||
"cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d",
|
||||
reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2ghz, reg_info->max_bw_2ghz,
|
||||
reg_info->min_bw_5ghz, reg_info->max_bw_5ghz);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"num_2ghz_reg_rules %d num_5ghz_reg_rules %d",
|
||||
num_2ghz_reg_rules, num_5ghz_reg_rules);
|
||||
|
||||
wmi_reg_rule =
|
||||
(struct wmi_regulatory_rule_struct *)((u8 *)chan_list_event_hdr
|
||||
+ sizeof(*chan_list_event_hdr)
|
||||
+ sizeof(struct wmi_tlv));
|
||||
|
||||
if (num_2g_reg_rules) {
|
||||
reg_info->reg_rules_2g_ptr = create_reg_rules_from_wmi(num_2g_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_2g_ptr) {
|
||||
if (num_2ghz_reg_rules) {
|
||||
reg_info->reg_rules_2ghz_ptr =
|
||||
create_reg_rules_from_wmi(num_2ghz_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_2ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 2g rules\n");
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "2 GHz",
|
||||
num_2ghz_reg_rules,
|
||||
reg_info->reg_rules_2ghz_ptr);
|
||||
}
|
||||
|
||||
if (num_5g_reg_rules) {
|
||||
wmi_reg_rule += num_2g_reg_rules;
|
||||
reg_info->reg_rules_5g_ptr = create_reg_rules_from_wmi(num_5g_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_5g_ptr) {
|
||||
if (num_5ghz_reg_rules) {
|
||||
wmi_reg_rule += num_2ghz_reg_rules;
|
||||
reg_info->reg_rules_5ghz_ptr =
|
||||
create_reg_rules_from_wmi(num_5ghz_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_5ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 5g rules\n");
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "5 GHz",
|
||||
num_5ghz_reg_rules,
|
||||
reg_info->reg_rules_5ghz_ptr);
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory channel list\n");
|
||||
@ -5050,6 +5095,429 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cur_reg_rule
|
||||
*create_ext_reg_rules_from_wmi(u32 num_reg_rules,
|
||||
struct wmi_regulatory_ext_rule *wmi_reg_rule)
|
||||
{
|
||||
struct cur_reg_rule *reg_rule_ptr;
|
||||
u32 count;
|
||||
|
||||
reg_rule_ptr = kcalloc(num_reg_rules, sizeof(*reg_rule_ptr), GFP_ATOMIC);
|
||||
|
||||
if (!reg_rule_ptr)
|
||||
return NULL;
|
||||
|
||||
for (count = 0; count < num_reg_rules; count++) {
|
||||
reg_rule_ptr[count].start_freq =
|
||||
u32_get_bits(wmi_reg_rule[count].freq_info,
|
||||
REG_RULE_START_FREQ);
|
||||
reg_rule_ptr[count].end_freq =
|
||||
u32_get_bits(wmi_reg_rule[count].freq_info,
|
||||
REG_RULE_END_FREQ);
|
||||
reg_rule_ptr[count].max_bw =
|
||||
u32_get_bits(wmi_reg_rule[count].bw_pwr_info,
|
||||
REG_RULE_MAX_BW);
|
||||
reg_rule_ptr[count].reg_power =
|
||||
u32_get_bits(wmi_reg_rule[count].bw_pwr_info,
|
||||
REG_RULE_REG_PWR);
|
||||
reg_rule_ptr[count].ant_gain =
|
||||
u32_get_bits(wmi_reg_rule[count].bw_pwr_info,
|
||||
REG_RULE_ANT_GAIN);
|
||||
reg_rule_ptr[count].flags =
|
||||
u32_get_bits(wmi_reg_rule[count].flag_info,
|
||||
REG_RULE_FLAGS);
|
||||
reg_rule_ptr[count].psd_flag =
|
||||
u32_get_bits(wmi_reg_rule[count].psd_power_info,
|
||||
REG_RULE_PSD_INFO);
|
||||
reg_rule_ptr[count].psd_eirp =
|
||||
u32_get_bits(wmi_reg_rule[count].psd_power_info,
|
||||
REG_RULE_PSD_EIRP);
|
||||
}
|
||||
|
||||
return reg_rule_ptr;
|
||||
}
|
||||
|
||||
static u8
|
||||
ath11k_invalid_5ghz_reg_ext_rules_from_wmi(u32 num_reg_rules,
|
||||
const struct wmi_regulatory_ext_rule *rule)
|
||||
{
|
||||
u8 num_invalid_5ghz_rules = 0;
|
||||
u32 count, start_freq;
|
||||
|
||||
for (count = 0; count < num_reg_rules; count++) {
|
||||
start_freq = u32_get_bits(rule[count].freq_info,
|
||||
REG_RULE_START_FREQ);
|
||||
|
||||
if (start_freq >= ATH11K_MIN_6G_FREQ)
|
||||
num_invalid_5ghz_rules++;
|
||||
}
|
||||
|
||||
return num_invalid_5ghz_rules;
|
||||
}
|
||||
|
||||
static int ath11k_pull_reg_chan_list_ext_update_ev(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
struct cur_regulatory_info *reg_info)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_reg_chan_list_cc_ext_event *ev;
|
||||
struct wmi_regulatory_ext_rule *ext_wmi_reg_rule;
|
||||
u32 num_2ghz_reg_rules, num_5ghz_reg_rules;
|
||||
u32 num_6ghz_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 num_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 total_reg_rules = 0;
|
||||
int ret, i, j, num_invalid_5ghz_ext_rules = 0;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory ext channel list\n");
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT];
|
||||
if (!ev) {
|
||||
ath11k_warn(ab, "failed to fetch reg chan list ext update ev\n");
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
reg_info->num_2ghz_reg_rules = ev->num_2ghz_reg_rules;
|
||||
reg_info->num_5ghz_reg_rules = ev->num_5ghz_reg_rules;
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->num_6ghz_reg_rules_ap_lpi;
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->num_6ghz_reg_rules_ap_sp;
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->num_6ghz_reg_rules_ap_vlp;
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->num_6ghz_reg_rules_client_lpi[i];
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->num_6ghz_reg_rules_client_sp[i];
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->num_6ghz_reg_rules_client_vlp[i];
|
||||
}
|
||||
|
||||
num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules;
|
||||
num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules;
|
||||
|
||||
total_reg_rules += num_2ghz_reg_rules;
|
||||
total_reg_rules += num_5ghz_reg_rules;
|
||||
|
||||
if ((num_2ghz_reg_rules > MAX_REG_RULES) ||
|
||||
(num_5ghz_reg_rules > MAX_REG_RULES)) {
|
||||
ath11k_warn(ab, "Num reg rules for 2.4 GHz/5 GHz exceeds max limit (num_2ghz_reg_rules: %d num_5ghz_reg_rules: %d max_rules: %d)\n",
|
||||
num_2ghz_reg_rules, num_5ghz_reg_rules, MAX_REG_RULES);
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
|
||||
num_6ghz_reg_rules_ap[i] = reg_info->num_6ghz_rules_ap[i];
|
||||
|
||||
if (num_6ghz_reg_rules_ap[i] > MAX_6GHZ_REG_RULES) {
|
||||
ath11k_warn(ab, "Num 6 GHz reg rules for AP mode(%d) exceeds max limit (num_6ghz_reg_rules_ap: %d, max_rules: %d)\n",
|
||||
i, num_6ghz_reg_rules_ap[i], MAX_6GHZ_REG_RULES);
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
total_reg_rules += num_6ghz_reg_rules_ap[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
num_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i];
|
||||
total_reg_rules += num_6ghz_client[WMI_REG_INDOOR_AP][i];
|
||||
|
||||
num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i];
|
||||
total_reg_rules += num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i];
|
||||
|
||||
num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i];
|
||||
total_reg_rules += num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i];
|
||||
|
||||
if ((num_6ghz_client[WMI_REG_INDOOR_AP][i] > MAX_6GHZ_REG_RULES) ||
|
||||
(num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] >
|
||||
MAX_6GHZ_REG_RULES) ||
|
||||
(num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] >
|
||||
MAX_6GHZ_REG_RULES)) {
|
||||
ath11k_warn(ab,
|
||||
"Num 6 GHz client reg rules exceeds max limit, for client(type: %d)\n",
|
||||
i);
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!total_reg_rules) {
|
||||
ath11k_warn(ab, "No reg rules available\n");
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN);
|
||||
|
||||
reg_info->dfs_region = ev->dfs_region;
|
||||
reg_info->phybitmap = ev->phybitmap;
|
||||
reg_info->num_phy = ev->num_phy;
|
||||
reg_info->phy_id = ev->phy_id;
|
||||
reg_info->ctry_code = ev->country_id;
|
||||
reg_info->reg_dmn_pair = ev->domain_code;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"status_code %s",
|
||||
ath11k_cc_status_to_str(reg_info->status_code));
|
||||
|
||||
reg_info->status_code =
|
||||
ath11k_wmi_cc_setting_code_to_reg(ev->status_code);
|
||||
|
||||
reg_info->is_ext_reg_event = true;
|
||||
|
||||
reg_info->min_bw_2ghz = ev->min_bw_2ghz;
|
||||
reg_info->max_bw_2ghz = ev->max_bw_2ghz;
|
||||
reg_info->min_bw_5ghz = ev->min_bw_5ghz;
|
||||
reg_info->max_bw_5ghz = ev->max_bw_5ghz;
|
||||
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->min_bw_6ghz_ap_lpi;
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->max_bw_6ghz_ap_lpi;
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->min_bw_6ghz_ap_sp;
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->max_bw_6ghz_ap_sp;
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->min_bw_6ghz_ap_vlp;
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->max_bw_6ghz_ap_vlp;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz AP BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n",
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP],
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP],
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP],
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP],
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP],
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP]);
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->min_bw_6ghz_client_lpi[i];
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->max_bw_6ghz_client_lpi[i];
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->min_bw_6ghz_client_sp[i];
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->max_bw_6ghz_client_sp[i];
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->min_bw_6ghz_client_vlp[i];
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->max_bw_6ghz_client_vlp[i];
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz %s BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n",
|
||||
ath11k_6ghz_client_type_to_str(i),
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i],
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i],
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i],
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i],
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i],
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i]);
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d",
|
||||
reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2ghz, reg_info->max_bw_2ghz,
|
||||
reg_info->min_bw_5ghz, reg_info->max_bw_5ghz);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"num_2ghz_reg_rules %d num_5ghz_reg_rules %d",
|
||||
num_2ghz_reg_rules, num_5ghz_reg_rules);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"num_6ghz_reg_rules_ap_lpi: %d num_6ghz_reg_rules_ap_sp: %d num_6ghz_reg_rules_ap_vlp: %d",
|
||||
num_6ghz_reg_rules_ap[WMI_REG_INDOOR_AP],
|
||||
num_6ghz_reg_rules_ap[WMI_REG_STANDARD_POWER_AP],
|
||||
num_6ghz_reg_rules_ap[WMI_REG_VERY_LOW_POWER_AP]);
|
||||
|
||||
j = WMI_REG_DEFAULT_CLIENT;
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz Regular client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d",
|
||||
num_6ghz_client[WMI_REG_INDOOR_AP][j],
|
||||
num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j],
|
||||
num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]);
|
||||
|
||||
j = WMI_REG_SUBORDINATE_CLIENT;
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz Subordinate client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d",
|
||||
num_6ghz_client[WMI_REG_INDOOR_AP][j],
|
||||
num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j],
|
||||
num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]);
|
||||
|
||||
ext_wmi_reg_rule =
|
||||
(struct wmi_regulatory_ext_rule *)((u8 *)ev + sizeof(*ev) +
|
||||
sizeof(struct wmi_tlv));
|
||||
if (num_2ghz_reg_rules) {
|
||||
reg_info->reg_rules_2ghz_ptr =
|
||||
create_ext_reg_rules_from_wmi(num_2ghz_reg_rules,
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_2ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "2 GHz",
|
||||
num_2ghz_reg_rules,
|
||||
reg_info->reg_rules_2ghz_ptr);
|
||||
}
|
||||
|
||||
ext_wmi_reg_rule += num_2ghz_reg_rules;
|
||||
|
||||
/* Firmware might include 6 GHz reg rule in 5 GHz rule list
|
||||
* for few countries along with separate 6 GHz rule.
|
||||
* Having same 6 GHz reg rule in 5 GHz and 6 GHz rules list
|
||||
* causes intersect check to be true, and same rules will be
|
||||
* shown multiple times in iw cmd.
|
||||
* Hence, avoid parsing 6 GHz rule from 5 GHz reg rule list
|
||||
*/
|
||||
num_invalid_5ghz_ext_rules =
|
||||
ath11k_invalid_5ghz_reg_ext_rules_from_wmi(num_5ghz_reg_rules,
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (num_invalid_5ghz_ext_rules) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"CC: %s 5 GHz reg rules number %d from fw, %d number of invalid 5 GHz rules",
|
||||
reg_info->alpha2, reg_info->num_5ghz_reg_rules,
|
||||
num_invalid_5ghz_ext_rules);
|
||||
|
||||
num_5ghz_reg_rules = num_5ghz_reg_rules - num_invalid_5ghz_ext_rules;
|
||||
reg_info->num_5ghz_reg_rules = num_5ghz_reg_rules;
|
||||
}
|
||||
|
||||
if (num_5ghz_reg_rules) {
|
||||
reg_info->reg_rules_5ghz_ptr =
|
||||
create_ext_reg_rules_from_wmi(num_5ghz_reg_rules,
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_5ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "5 GHz",
|
||||
num_5ghz_reg_rules,
|
||||
reg_info->reg_rules_5ghz_ptr);
|
||||
}
|
||||
|
||||
/* We have adjusted the number of 5 GHz reg rules above. But still those
|
||||
* many rules needs to be adjusted in ext_wmi_reg_rule.
|
||||
*
|
||||
* NOTE: num_invalid_5ghz_ext_rules will be 0 for rest other cases.
|
||||
*/
|
||||
ext_wmi_reg_rule += (num_5ghz_reg_rules + num_invalid_5ghz_ext_rules);
|
||||
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
|
||||
reg_info->reg_rules_6ghz_ap_ptr[i] =
|
||||
create_ext_reg_rules_from_wmi(num_6ghz_reg_rules_ap[i],
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_6ghz_ap_ptr[i]) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 6 GHz AP rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, ath11k_6ghz_ap_type_to_str(i),
|
||||
num_6ghz_reg_rules_ap[i],
|
||||
reg_info->reg_rules_6ghz_ap_ptr[i]);
|
||||
|
||||
ext_wmi_reg_rule += num_6ghz_reg_rules_ap[i];
|
||||
}
|
||||
|
||||
for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz AP type %s", ath11k_6ghz_ap_type_to_str(j));
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->reg_rules_6ghz_client_ptr[j][i] =
|
||||
create_ext_reg_rules_from_wmi(num_6ghz_client[j][i],
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_6ghz_client_ptr[j][i]) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 6 GHz client rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab,
|
||||
ath11k_6ghz_client_type_to_str(i),
|
||||
num_6ghz_client[j][i],
|
||||
reg_info->reg_rules_6ghz_client_ptr[j][i]);
|
||||
|
||||
ext_wmi_reg_rule += num_6ghz_client[j][i];
|
||||
}
|
||||
}
|
||||
|
||||
reg_info->client_type = ev->client_type;
|
||||
reg_info->rnr_tpe_usable = ev->rnr_tpe_usable;
|
||||
reg_info->unspecified_ap_usable =
|
||||
ev->unspecified_ap_usable;
|
||||
reg_info->domain_code_6ghz_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->domain_code_6ghz_ap_lpi;
|
||||
reg_info->domain_code_6ghz_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->domain_code_6ghz_ap_sp;
|
||||
reg_info->domain_code_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->domain_code_6ghz_ap_vlp;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz reg info client type %s rnr_tpe_usable %d unspecified_ap_usable %d AP sub domain: lpi %s, sp %s, vlp %s\n",
|
||||
ath11k_6ghz_client_type_to_str(reg_info->client_type),
|
||||
reg_info->rnr_tpe_usable,
|
||||
reg_info->unspecified_ap_usable,
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_lpi),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_sp),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_vlp));
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->domain_code_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->domain_code_6ghz_client_lpi[i];
|
||||
reg_info->domain_code_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->domain_code_6ghz_client_sp[i];
|
||||
reg_info->domain_code_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->domain_code_6ghz_client_vlp[i];
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz client type %s client sub domain: lpi %s, sp %s, vlp %s\n",
|
||||
ath11k_6ghz_client_type_to_str(i),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_lpi[i]),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_sp[i]),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_vlp[i])
|
||||
);
|
||||
}
|
||||
|
||||
reg_info->domain_code_6ghz_super_id = ev->domain_code_6ghz_super_id;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz client_type %s 6 GHz super domain %s",
|
||||
ath11k_6ghz_client_type_to_str(reg_info->client_type),
|
||||
ath11k_super_reg_6ghz_to_str(reg_info->domain_code_6ghz_super_id));
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory ext channel list\n");
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pull_peer_del_resp_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
struct wmi_peer_delete_resp_event *peer_del_resp)
|
||||
{
|
||||
@ -5221,8 +5689,8 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
u32 status)
|
||||
static int wmi_process_mgmt_tx_comp(struct ath11k *ar,
|
||||
struct wmi_mgmt_tx_compl_event *tx_compl_param)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
@ -5230,24 +5698,29 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
int num_mgmt;
|
||||
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
msdu = idr_find(&ar->txmgmt_idr, desc_id);
|
||||
msdu = idr_find(&ar->txmgmt_idr, tx_compl_param->desc_id);
|
||||
|
||||
if (!msdu) {
|
||||
ath11k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n",
|
||||
desc_id);
|
||||
tx_compl_param->desc_id);
|
||||
spin_unlock_bh(&ar->txmgmt_idr_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
idr_remove(&ar->txmgmt_idr, desc_id);
|
||||
idr_remove(&ar->txmgmt_idr, tx_compl_param->desc_id);
|
||||
spin_unlock_bh(&ar->txmgmt_idr_lock);
|
||||
|
||||
skb_cb = ATH11K_SKB_CB(msdu);
|
||||
dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status)
|
||||
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) &&
|
||||
!tx_compl_param->status) {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
info->status.ack_signal = tx_compl_param->ack_rssi;
|
||||
}
|
||||
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
|
||||
@ -5259,7 +5732,7 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"wmi mgmt tx comp pending %d desc id %d\n",
|
||||
num_mgmt, desc_id);
|
||||
num_mgmt, tx_compl_param->desc_id);
|
||||
|
||||
if (!num_mgmt)
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
@ -5292,6 +5765,7 @@ static int ath11k_pull_mgmt_tx_compl_param_tlv(struct ath11k_base *ab,
|
||||
param->pdev_id = ev->pdev_id;
|
||||
param->desc_id = ev->desc_id;
|
||||
param->status = ev->status;
|
||||
param->ack_rssi = ev->ack_rssi;
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
@ -6491,12 +6965,14 @@ static bool ath11k_reg_is_world_alpha(char *alpha)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
enum wmi_reg_chan_list_cmd_type id)
|
||||
{
|
||||
struct cur_regulatory_info *reg_info = NULL;
|
||||
struct ieee80211_regdomain *regd = NULL;
|
||||
bool intersect = false;
|
||||
int ret = 0, pdev_idx;
|
||||
int ret = 0, pdev_idx, i, j;
|
||||
struct ath11k *ar;
|
||||
|
||||
reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
|
||||
@ -6505,7 +6981,11 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info);
|
||||
if (id == WMI_REG_CHAN_LIST_CC_ID)
|
||||
ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info);
|
||||
else
|
||||
ret = ath11k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to extract regulatory info from received event\n");
|
||||
goto fallback;
|
||||
@ -6605,8 +7085,16 @@ fallback:
|
||||
WARN_ON(1);
|
||||
mem_free:
|
||||
if (reg_info) {
|
||||
kfree(reg_info->reg_rules_2g_ptr);
|
||||
kfree(reg_info->reg_rules_5g_ptr);
|
||||
kfree(reg_info->reg_rules_2ghz_ptr);
|
||||
kfree(reg_info->reg_rules_5ghz_ptr);
|
||||
if (reg_info->is_ext_reg_event) {
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++)
|
||||
kfree(reg_info->reg_rules_6ghz_ap_ptr[i]);
|
||||
|
||||
for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++)
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++)
|
||||
kfree(reg_info->reg_rules_6ghz_client_ptr[j][i]);
|
||||
}
|
||||
kfree(reg_info);
|
||||
}
|
||||
return ret;
|
||||
@ -7062,13 +7550,12 @@ static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *s
|
||||
goto exit;
|
||||
}
|
||||
|
||||
wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id,
|
||||
tx_compl_param.status);
|
||||
wmi_process_mgmt_tx_comp(ar, &tx_compl_param);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MGMT,
|
||||
"mgmt tx compl ev pdev_id %d, desc_id %d, status %d",
|
||||
"mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d",
|
||||
tx_compl_param.pdev_id, tx_compl_param.desc_id,
|
||||
tx_compl_param.status);
|
||||
tx_compl_param.status, tx_compl_param.ack_rssi);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
@ -8039,7 +8526,10 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
ath11k_service_ready_ext2_event(ab, skb);
|
||||
break;
|
||||
case WMI_REG_CHAN_LIST_CC_EVENTID:
|
||||
ath11k_reg_chan_list_event(ab, skb);
|
||||
ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_ID);
|
||||
break;
|
||||
case WMI_REG_CHAN_LIST_CC_EXT_EVENTID:
|
||||
ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_EXT_ID);
|
||||
break;
|
||||
case WMI_READY_EVENTID:
|
||||
ath11k_ready_event(ab, skb);
|
||||
|
@ -797,6 +797,7 @@ enum wmi_tlv_event_id {
|
||||
WMI_RMC_NEW_LEADER_EVENTID = WMI_TLV_CMD(WMI_GRP_RMC),
|
||||
WMI_REG_CHAN_LIST_CC_EVENTID = WMI_TLV_CMD(WMI_GRP_REGULATORY),
|
||||
WMI_11D_NEW_COUNTRY_EVENTID,
|
||||
WMI_REG_CHAN_LIST_CC_EXT_EVENTID,
|
||||
WMI_NDI_CAP_RSP_EVENTID = WMI_TLV_CMD(WMI_GRP_PROTOTYPE),
|
||||
WMI_NDP_INITIATOR_RSP_EVENTID,
|
||||
WMI_NDP_RESPONDER_RSP_EVENTID,
|
||||
@ -1865,6 +1866,8 @@ enum wmi_tlv_tag {
|
||||
WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
|
||||
WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD,
|
||||
WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
|
||||
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
|
||||
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
|
||||
WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8,
|
||||
WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD,
|
||||
WMI_TAG_MAX
|
||||
@ -2093,9 +2096,11 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_EXT2_MSG = 220,
|
||||
WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
|
||||
WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
|
||||
WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263,
|
||||
|
||||
/* The second 128 bits */
|
||||
WMI_MAX_EXT_SERVICE = 256,
|
||||
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
|
||||
WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326,
|
||||
|
||||
/* The third 128 bits */
|
||||
@ -2310,6 +2315,9 @@ struct wmi_init_cmd {
|
||||
} __packed;
|
||||
|
||||
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
|
||||
#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
|
||||
|
||||
#define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4
|
||||
|
||||
struct wmi_resource_config {
|
||||
u32 tlv_header;
|
||||
@ -2370,6 +2378,15 @@ struct wmi_resource_config {
|
||||
u32 sched_params;
|
||||
u32 twt_ap_pdev_count;
|
||||
u32 twt_ap_sta_count;
|
||||
u32 max_nlo_ssids;
|
||||
u32 num_pkt_filters;
|
||||
u32 num_max_sta_vdevs;
|
||||
u32 max_bssid_indicator;
|
||||
u32 ul_resp_config;
|
||||
u32 msdu_flow_override_config0;
|
||||
u32 msdu_flow_override_config1;
|
||||
u32 flags2;
|
||||
u32 host_service_flags;
|
||||
} __packed;
|
||||
|
||||
struct wmi_service_ready_event {
|
||||
@ -2852,36 +2869,40 @@ struct rx_reorder_queue_remove_params {
|
||||
#define REG_RULE_MAX_BW 0x0000ffff
|
||||
#define REG_RULE_REG_PWR 0x00ff0000
|
||||
#define REG_RULE_ANT_GAIN 0xff000000
|
||||
#define REG_RULE_PSD_INFO BIT(0)
|
||||
#define REG_RULE_PSD_EIRP 0xff0000
|
||||
|
||||
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
|
||||
#define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1)
|
||||
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
|
||||
#define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
|
||||
|
||||
#define HECAP_PHYDWORD_0 0
|
||||
#define HECAP_PHYDWORD_1 1
|
||||
#define HECAP_PHYDWORD_2 2
|
||||
#define HE_PHYCAP_BYTE_0 0
|
||||
#define HE_PHYCAP_BYTE_1 1
|
||||
#define HE_PHYCAP_BYTE_2 2
|
||||
#define HE_PHYCAP_BYTE_3 3
|
||||
#define HE_PHYCAP_BYTE_4 4
|
||||
|
||||
#define HECAP_PHY_SU_BFER BIT(31)
|
||||
#define HECAP_PHY_SU_BFER BIT(7)
|
||||
#define HECAP_PHY_SU_BFEE BIT(0)
|
||||
#define HECAP_PHY_MU_BFER BIT(1)
|
||||
#define HECAP_PHY_UL_MUMIMO BIT(22)
|
||||
#define HECAP_PHY_UL_MUOFDMA BIT(23)
|
||||
#define HECAP_PHY_UL_MUMIMO BIT(6)
|
||||
#define HECAP_PHY_UL_MUOFDMA BIT(7)
|
||||
|
||||
#define HECAP_PHY_SUBFMR_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HECAP_PHYDWORD_0])
|
||||
FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HE_PHYCAP_BYTE_3])
|
||||
|
||||
#define HECAP_PHY_SUBFME_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HECAP_PHYDWORD_1])
|
||||
FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HE_PHYCAP_BYTE_4])
|
||||
|
||||
#define HECAP_PHY_MUBFMR_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HECAP_PHYDWORD_1])
|
||||
FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HE_PHYCAP_BYTE_4])
|
||||
|
||||
#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HECAP_PHYDWORD_0])
|
||||
FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HE_PHYCAP_BYTE_2])
|
||||
|
||||
#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HECAP_PHYDWORD_0])
|
||||
FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HE_PHYCAP_BYTE_2])
|
||||
|
||||
#define HE_MODE_SU_TX_BFEE BIT(0)
|
||||
#define HE_MODE_SU_TX_BFER BIT(1)
|
||||
@ -2894,8 +2915,11 @@ struct rx_reorder_queue_remove_params {
|
||||
#define HE_DL_MUOFDMA_ENABLE 1
|
||||
#define HE_UL_MUOFDMA_ENABLE 1
|
||||
#define HE_DL_MUMIMO_ENABLE 1
|
||||
#define HE_UL_MUMIMO_ENABLE 1
|
||||
#define HE_MU_BFEE_ENABLE 1
|
||||
#define HE_SU_BFEE_ENABLE 1
|
||||
#define HE_MU_BFER_ENABLE 1
|
||||
#define HE_SU_BFER_ENABLE 1
|
||||
|
||||
#define HE_VHT_SOUNDING_MODE_ENABLE 1
|
||||
#define HE_SU_MU_SOUNDING_MODE_ENABLE 1
|
||||
@ -3223,6 +3247,7 @@ struct wmi_start_scan_cmd {
|
||||
|
||||
#define WMI_SCAN_DWELL_MODE_MASK 0x00E00000
|
||||
#define WMI_SCAN_DWELL_MODE_SHIFT 21
|
||||
#define WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE 0x00000800
|
||||
|
||||
enum {
|
||||
WMI_SCAN_DWELL_MODE_DEFAULT = 0,
|
||||
@ -3270,6 +3295,7 @@ struct scan_req_params {
|
||||
};
|
||||
u32 scan_events;
|
||||
};
|
||||
u32 scan_ctrl_flags_ext;
|
||||
u32 dwell_time_active;
|
||||
u32 dwell_time_active_2g;
|
||||
u32 dwell_time_passive;
|
||||
@ -4040,6 +4066,7 @@ struct wmi_he_rate_set {
|
||||
|
||||
#define MAX_REG_RULES 10
|
||||
#define REG_ALPHA2_LEN 2
|
||||
#define MAX_6GHZ_REG_RULES 5
|
||||
|
||||
enum wmi_start_event_param {
|
||||
WMI_VDEV_START_RESP_EVENT = 0,
|
||||
@ -4070,16 +4097,6 @@ enum wmi_vdev_start_resp_status_code {
|
||||
WMI_VDEV_START_RESPONSE_INVALID_REGDOMAIN = 4,
|
||||
};
|
||||
|
||||
;
|
||||
enum cc_setting_code {
|
||||
REG_SET_CC_STATUS_PASS = 0,
|
||||
REG_CURRENT_ALPHA2_NOT_FOUND = 1,
|
||||
REG_INIT_ALPHA2_NOT_FOUND = 2,
|
||||
REG_SET_CC_CHANGE_NOT_ALLOWED = 3,
|
||||
REG_SET_CC_STATUS_NO_MEMORY = 4,
|
||||
REG_SET_CC_STATUS_FAIL = 5,
|
||||
};
|
||||
|
||||
/* Regaulatory Rule Flags Passed by FW */
|
||||
#define REGULATORY_CHAN_DISABLED BIT(0)
|
||||
#define REGULATORY_CHAN_NO_IR BIT(1)
|
||||
@ -4093,15 +4110,216 @@ enum cc_setting_code {
|
||||
#define REGULATORY_CHAN_NO_20MHZ BIT(11)
|
||||
#define REGULATORY_CHAN_NO_10MHZ BIT(12)
|
||||
|
||||
enum {
|
||||
enum wmi_reg_chan_list_cmd_type {
|
||||
WMI_REG_CHAN_LIST_CC_ID = 0,
|
||||
WMI_REG_CHAN_LIST_CC_EXT_ID = 1,
|
||||
};
|
||||
|
||||
enum wmi_reg_cc_setting_code {
|
||||
WMI_REG_SET_CC_STATUS_PASS = 0,
|
||||
WMI_REG_CURRENT_ALPHA2_NOT_FOUND = 1,
|
||||
WMI_REG_INIT_ALPHA2_NOT_FOUND = 2,
|
||||
WMI_REG_SET_CC_CHANGE_NOT_ALLOWED = 3,
|
||||
WMI_REG_SET_CC_STATUS_NO_MEMORY = 4,
|
||||
WMI_REG_SET_CC_STATUS_FAIL = 5,
|
||||
|
||||
/* add new setting code above, update in
|
||||
* @enum cc_setting_code as well.
|
||||
* Also handle it in ath11k_wmi_cc_setting_code_to_reg()
|
||||
*/
|
||||
};
|
||||
|
||||
enum cc_setting_code {
|
||||
REG_SET_CC_STATUS_PASS = 0,
|
||||
REG_CURRENT_ALPHA2_NOT_FOUND = 1,
|
||||
REG_INIT_ALPHA2_NOT_FOUND = 2,
|
||||
REG_SET_CC_CHANGE_NOT_ALLOWED = 3,
|
||||
REG_SET_CC_STATUS_NO_MEMORY = 4,
|
||||
REG_SET_CC_STATUS_FAIL = 5,
|
||||
|
||||
/* add new setting code above, update in
|
||||
* @enum wmi_reg_cc_setting_code as well.
|
||||
* Also handle it in ath11k_cc_status_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline enum cc_setting_code
|
||||
ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code)
|
||||
{
|
||||
switch (status_code) {
|
||||
case WMI_REG_SET_CC_STATUS_PASS:
|
||||
return REG_SET_CC_STATUS_PASS;
|
||||
case WMI_REG_CURRENT_ALPHA2_NOT_FOUND:
|
||||
return REG_CURRENT_ALPHA2_NOT_FOUND;
|
||||
case WMI_REG_INIT_ALPHA2_NOT_FOUND:
|
||||
return REG_INIT_ALPHA2_NOT_FOUND;
|
||||
case WMI_REG_SET_CC_CHANGE_NOT_ALLOWED:
|
||||
return REG_SET_CC_CHANGE_NOT_ALLOWED;
|
||||
case WMI_REG_SET_CC_STATUS_NO_MEMORY:
|
||||
return REG_SET_CC_STATUS_NO_MEMORY;
|
||||
case WMI_REG_SET_CC_STATUS_FAIL:
|
||||
return REG_SET_CC_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return REG_SET_CC_STATUS_FAIL;
|
||||
}
|
||||
|
||||
static inline const char *ath11k_cc_status_to_str(enum cc_setting_code code)
|
||||
{
|
||||
switch (code) {
|
||||
case REG_SET_CC_STATUS_PASS:
|
||||
return "REG_SET_CC_STATUS_PASS";
|
||||
case REG_CURRENT_ALPHA2_NOT_FOUND:
|
||||
return "REG_CURRENT_ALPHA2_NOT_FOUND";
|
||||
case REG_INIT_ALPHA2_NOT_FOUND:
|
||||
return "REG_INIT_ALPHA2_NOT_FOUND";
|
||||
case REG_SET_CC_CHANGE_NOT_ALLOWED:
|
||||
return "REG_SET_CC_CHANGE_NOT_ALLOWED";
|
||||
case REG_SET_CC_STATUS_NO_MEMORY:
|
||||
return "REG_SET_CC_STATUS_NO_MEMORY";
|
||||
case REG_SET_CC_STATUS_FAIL:
|
||||
return "REG_SET_CC_STATUS_FAIL";
|
||||
}
|
||||
|
||||
return "Unknown CC status";
|
||||
}
|
||||
|
||||
enum wmi_reg_6ghz_ap_type {
|
||||
WMI_REG_INDOOR_AP = 0,
|
||||
WMI_REG_STANDARD_POWER_AP = 1,
|
||||
WMI_REG_VERY_LOW_POWER_AP = 2,
|
||||
|
||||
/* add AP type above, handle in ath11k_6ghz_ap_type_to_str()
|
||||
*/
|
||||
WMI_REG_CURRENT_MAX_AP_TYPE,
|
||||
WMI_REG_MAX_AP_TYPE = 7,
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_6ghz_ap_type_to_str(enum wmi_reg_6ghz_ap_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case WMI_REG_INDOOR_AP:
|
||||
return "INDOOR AP";
|
||||
case WMI_REG_STANDARD_POWER_AP:
|
||||
return "STANDARD POWER AP";
|
||||
case WMI_REG_VERY_LOW_POWER_AP:
|
||||
return "VERY LOW POWER AP";
|
||||
case WMI_REG_CURRENT_MAX_AP_TYPE:
|
||||
return "CURRENT_MAX_AP_TYPE";
|
||||
case WMI_REG_MAX_AP_TYPE:
|
||||
return "MAX_AP_TYPE";
|
||||
}
|
||||
|
||||
return "unknown 6 GHz AP type";
|
||||
}
|
||||
|
||||
enum wmi_reg_6ghz_client_type {
|
||||
WMI_REG_DEFAULT_CLIENT = 0,
|
||||
WMI_REG_SUBORDINATE_CLIENT = 1,
|
||||
WMI_REG_MAX_CLIENT_TYPE = 2,
|
||||
|
||||
/* add client type above, handle it in
|
||||
* ath11k_6ghz_client_type_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_6ghz_client_type_to_str(enum wmi_reg_6ghz_client_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case WMI_REG_DEFAULT_CLIENT:
|
||||
return "DEFAULT CLIENT";
|
||||
case WMI_REG_SUBORDINATE_CLIENT:
|
||||
return "SUBORDINATE CLIENT";
|
||||
case WMI_REG_MAX_CLIENT_TYPE:
|
||||
return "MAX_CLIENT_TYPE";
|
||||
}
|
||||
|
||||
return "unknown 6 GHz client type";
|
||||
}
|
||||
|
||||
enum reg_subdomains_6ghz {
|
||||
EMPTY_6GHZ = 0x0,
|
||||
FCC1_CLIENT_LPI_REGULAR_6GHZ = 0x01,
|
||||
FCC1_CLIENT_SP_6GHZ = 0x02,
|
||||
FCC1_AP_LPI_6GHZ = 0x03,
|
||||
FCC1_CLIENT_LPI_SUBORDINATE = FCC1_AP_LPI_6GHZ,
|
||||
FCC1_AP_SP_6GHZ = 0x04,
|
||||
ETSI1_LPI_6GHZ = 0x10,
|
||||
ETSI1_VLP_6GHZ = 0x11,
|
||||
ETSI2_LPI_6GHZ = 0x12,
|
||||
ETSI2_VLP_6GHZ = 0x13,
|
||||
APL1_LPI_6GHZ = 0x20,
|
||||
APL1_VLP_6GHZ = 0x21,
|
||||
|
||||
/* add sub-domain above, handle it in
|
||||
* ath11k_sub_reg_6ghz_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_sub_reg_6ghz_to_str(enum reg_subdomains_6ghz sub_id)
|
||||
{
|
||||
switch (sub_id) {
|
||||
case EMPTY_6GHZ:
|
||||
return "N/A";
|
||||
case FCC1_CLIENT_LPI_REGULAR_6GHZ:
|
||||
return "FCC1_CLIENT_LPI_REGULAR_6GHZ";
|
||||
case FCC1_CLIENT_SP_6GHZ:
|
||||
return "FCC1_CLIENT_SP_6GHZ";
|
||||
case FCC1_AP_LPI_6GHZ:
|
||||
return "FCC1_AP_LPI_6GHZ/FCC1_CLIENT_LPI_SUBORDINATE";
|
||||
case FCC1_AP_SP_6GHZ:
|
||||
return "FCC1_AP_SP_6GHZ";
|
||||
case ETSI1_LPI_6GHZ:
|
||||
return "ETSI1_LPI_6GHZ";
|
||||
case ETSI1_VLP_6GHZ:
|
||||
return "ETSI1_VLP_6GHZ";
|
||||
case ETSI2_LPI_6GHZ:
|
||||
return "ETSI2_LPI_6GHZ";
|
||||
case ETSI2_VLP_6GHZ:
|
||||
return "ETSI2_VLP_6GHZ";
|
||||
case APL1_LPI_6GHZ:
|
||||
return "APL1_LPI_6GHZ";
|
||||
case APL1_VLP_6GHZ:
|
||||
return "APL1_VLP_6GHZ";
|
||||
}
|
||||
|
||||
return "unknown sub reg id";
|
||||
}
|
||||
|
||||
enum reg_super_domain_6ghz {
|
||||
FCC1_6GHZ = 0x01,
|
||||
ETSI1_6GHZ = 0x02,
|
||||
ETSI2_6GHZ = 0x03,
|
||||
APL1_6GHZ = 0x04,
|
||||
FCC1_6GHZ_CL = 0x05,
|
||||
|
||||
/* add super domain above, handle it in
|
||||
* ath11k_super_reg_6ghz_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_super_reg_6ghz_to_str(enum reg_super_domain_6ghz domain_id)
|
||||
{
|
||||
switch (domain_id) {
|
||||
case FCC1_6GHZ:
|
||||
return "FCC1_6GHZ";
|
||||
case ETSI1_6GHZ:
|
||||
return "ETSI1_6GHZ";
|
||||
case ETSI2_6GHZ:
|
||||
return "ETSI2_6GHZ";
|
||||
case APL1_6GHZ:
|
||||
return "APL1_6GHZ";
|
||||
case FCC1_6GHZ_CL:
|
||||
return "FCC1_6GHZ_CL";
|
||||
}
|
||||
|
||||
return "unknown domain id";
|
||||
}
|
||||
|
||||
struct cur_reg_rule {
|
||||
u16 start_freq;
|
||||
u16 end_freq;
|
||||
@ -4109,6 +4327,8 @@ struct cur_reg_rule {
|
||||
u8 reg_power;
|
||||
u8 ant_gain;
|
||||
u16 flags;
|
||||
bool psd_flag;
|
||||
s8 psd_eirp;
|
||||
};
|
||||
|
||||
struct cur_regulatory_info {
|
||||
@ -4120,14 +4340,30 @@ struct cur_regulatory_info {
|
||||
u8 alpha2[REG_ALPHA2_LEN + 1];
|
||||
u32 dfs_region;
|
||||
u32 phybitmap;
|
||||
u32 min_bw_2g;
|
||||
u32 max_bw_2g;
|
||||
u32 min_bw_5g;
|
||||
u32 max_bw_5g;
|
||||
u32 num_2g_reg_rules;
|
||||
u32 num_5g_reg_rules;
|
||||
struct cur_reg_rule *reg_rules_2g_ptr;
|
||||
struct cur_reg_rule *reg_rules_5g_ptr;
|
||||
u32 min_bw_2ghz;
|
||||
u32 max_bw_2ghz;
|
||||
u32 min_bw_5ghz;
|
||||
u32 max_bw_5ghz;
|
||||
u32 num_2ghz_reg_rules;
|
||||
u32 num_5ghz_reg_rules;
|
||||
struct cur_reg_rule *reg_rules_2ghz_ptr;
|
||||
struct cur_reg_rule *reg_rules_5ghz_ptr;
|
||||
bool is_ext_reg_event;
|
||||
enum wmi_reg_6ghz_client_type client_type;
|
||||
bool rnr_tpe_usable;
|
||||
bool unspecified_ap_usable;
|
||||
u8 domain_code_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u8 domain_code_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 domain_code_6ghz_super_id;
|
||||
u32 min_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 max_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 min_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 max_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 num_6ghz_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 num_6ghz_rules_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
struct cur_reg_rule *reg_rules_6ghz_ap_ptr[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
struct cur_reg_rule *reg_rules_6ghz_client_ptr
|
||||
[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
};
|
||||
|
||||
struct wmi_reg_chan_list_cc_event {
|
||||
@ -4139,12 +4375,12 @@ struct wmi_reg_chan_list_cc_event {
|
||||
u32 domain_code;
|
||||
u32 dfs_region;
|
||||
u32 phybitmap;
|
||||
u32 min_bw_2g;
|
||||
u32 max_bw_2g;
|
||||
u32 min_bw_5g;
|
||||
u32 max_bw_5g;
|
||||
u32 num_2g_reg_rules;
|
||||
u32 num_5g_reg_rules;
|
||||
u32 min_bw_2ghz;
|
||||
u32 max_bw_2ghz;
|
||||
u32 min_bw_5ghz;
|
||||
u32 max_bw_5ghz;
|
||||
u32 num_2ghz_reg_rules;
|
||||
u32 num_5ghz_reg_rules;
|
||||
} __packed;
|
||||
|
||||
struct wmi_regulatory_rule_struct {
|
||||
@ -4154,6 +4390,61 @@ struct wmi_regulatory_rule_struct {
|
||||
u32 flag_info;
|
||||
};
|
||||
|
||||
#define WMI_REG_CLIENT_MAX 4
|
||||
|
||||
struct wmi_reg_chan_list_cc_ext_event {
|
||||
u32 status_code;
|
||||
u32 phy_id;
|
||||
u32 alpha2;
|
||||
u32 num_phy;
|
||||
u32 country_id;
|
||||
u32 domain_code;
|
||||
u32 dfs_region;
|
||||
u32 phybitmap;
|
||||
u32 min_bw_2ghz;
|
||||
u32 max_bw_2ghz;
|
||||
u32 min_bw_5ghz;
|
||||
u32 max_bw_5ghz;
|
||||
u32 num_2ghz_reg_rules;
|
||||
u32 num_5ghz_reg_rules;
|
||||
u32 client_type;
|
||||
u32 rnr_tpe_usable;
|
||||
u32 unspecified_ap_usable;
|
||||
u32 domain_code_6ghz_ap_lpi;
|
||||
u32 domain_code_6ghz_ap_sp;
|
||||
u32 domain_code_6ghz_ap_vlp;
|
||||
u32 domain_code_6ghz_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 domain_code_6ghz_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 domain_code_6ghz_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
u32 domain_code_6ghz_super_id;
|
||||
u32 min_bw_6ghz_ap_sp;
|
||||
u32 max_bw_6ghz_ap_sp;
|
||||
u32 min_bw_6ghz_ap_lpi;
|
||||
u32 max_bw_6ghz_ap_lpi;
|
||||
u32 min_bw_6ghz_ap_vlp;
|
||||
u32 max_bw_6ghz_ap_vlp;
|
||||
u32 min_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 max_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 min_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 max_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 min_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
u32 max_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
u32 num_6ghz_reg_rules_ap_sp;
|
||||
u32 num_6ghz_reg_rules_ap_lpi;
|
||||
u32 num_6ghz_reg_rules_ap_vlp;
|
||||
u32 num_6ghz_reg_rules_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 num_6ghz_reg_rules_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 num_6ghz_reg_rules_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
} __packed;
|
||||
|
||||
struct wmi_regulatory_ext_rule {
|
||||
u32 tlv_header;
|
||||
u32 freq_info;
|
||||
u32 bw_pwr_info;
|
||||
u32 flag_info;
|
||||
u32 psd_power_info;
|
||||
} __packed;
|
||||
|
||||
struct wmi_vdev_delete_resp_event {
|
||||
u32 vdev_id;
|
||||
} __packed;
|
||||
@ -4542,6 +4833,8 @@ struct wmi_mgmt_tx_compl_event {
|
||||
u32 desc_id;
|
||||
u32 status;
|
||||
u32 pdev_id;
|
||||
u32 ppdu_id;
|
||||
u32 ack_rssi;
|
||||
} __packed;
|
||||
|
||||
struct wmi_scan_event {
|
||||
@ -5347,6 +5640,7 @@ struct target_resource_config {
|
||||
u32 sched_params;
|
||||
u32 twt_ap_pdev_count;
|
||||
u32 twt_ap_sta_count;
|
||||
u8 is_reg_cc_ext_event_supported;
|
||||
};
|
||||
|
||||
enum wmi_debug_log_param {
|
||||
|
@ -946,7 +946,7 @@ int ath12k_ce_alloc_pipes(struct ath12k_base *ab)
|
||||
|
||||
ret = ath12k_ce_alloc_pipe(ab, i);
|
||||
if (ret) {
|
||||
/* Free any parial successful allocation */
|
||||
/* Free any partial successful allocation */
|
||||
ath12k_ce_free_pipes(ab);
|
||||
return ret;
|
||||
}
|
||||
|
@ -691,7 +691,7 @@ struct ath12k_base {
|
||||
|
||||
/* Below regd's are protected by ab->data_lock */
|
||||
/* This is the regd set for every radio
|
||||
* by the firmware during initializatin
|
||||
* by the firmware during initialization
|
||||
*/
|
||||
struct ieee80211_regdomain *default_regd[MAX_RADIOS];
|
||||
/* This regd is set during dynamic country setting
|
||||
|
@ -1429,7 +1429,7 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab)
|
||||
}
|
||||
|
||||
if (dp->spt_info[i].paddr & ATH12K_SPT_4K_ALIGN_CHECK) {
|
||||
ath12k_warn(ab, "SPT allocated memoty is not 4K aligned");
|
||||
ath12k_warn(ab, "SPT allocated memory is not 4K aligned");
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
@ -1461,15 +1461,12 @@ static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab)
|
||||
dp->reoq_lut.vaddr = dma_alloc_coherent(ab->dev,
|
||||
DP_REOQ_LUT_SIZE,
|
||||
&dp->reoq_lut.paddr,
|
||||
GFP_KERNEL);
|
||||
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!dp->reoq_lut.vaddr) {
|
||||
ath12k_warn(ab, "failed to allocate memory for reoq table");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(dp->reoq_lut.vaddr, 0, DP_REOQ_LUT_SIZE);
|
||||
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab),
|
||||
dp->reoq_lut.paddr);
|
||||
return 0;
|
||||
|
@ -371,7 +371,7 @@ struct ath12k_dp {
|
||||
|
||||
#define HTT_TX_WBM_COMP_STATUS_OFFSET 8
|
||||
|
||||
/* HTT tx completion is overlayed in wbm_release_ring */
|
||||
/* HTT tx completion is overlaid in wbm_release_ring */
|
||||
#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13)
|
||||
#define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0)
|
||||
#define HTT_TX_WBM_COMP_INFO1_EXCEPTION_FRAME BIT(4)
|
||||
@ -545,7 +545,7 @@ enum htt_srng_ring_id {
|
||||
* 3'b010: 4 usec
|
||||
* 3'b011: 8 usec (default)
|
||||
* 3'b100: 16 usec
|
||||
* Others: Reserverd
|
||||
* Others: Reserved
|
||||
* b'19 - response_required:
|
||||
* Host needs HTT_T2H_MSG_TYPE_SRING_SETUP_DONE as response
|
||||
* b'20:31 - reserved: reserved for future use
|
||||
@ -1126,7 +1126,7 @@ struct htt_tx_ring_selection_cfg_cmd {
|
||||
__le32 tlv_filter_mask_in1;
|
||||
__le32 tlv_filter_mask_in2;
|
||||
__le32 tlv_filter_mask_in3;
|
||||
__le32 reserverd[3];
|
||||
__le32 reserved[3];
|
||||
} __packed;
|
||||
|
||||
#define HTT_TX_RING_TLV_FILTER_MGMT_DMA_LEN GENMASK(3, 0)
|
||||
|
@ -529,12 +529,12 @@ static void ath12k_dp_mon_parse_he_sig_su(u8 *tlv_data,
|
||||
case 3:
|
||||
if (he_dcm && he_stbc) {
|
||||
he_gi = HE_GI_0_8;
|
||||
he_ltf = HE_LTF_4_X;
|
||||
he_ltf = HE_LTF_4_X;
|
||||
} else {
|
||||
he_gi = HE_GI_3_2;
|
||||
he_ltf = HE_LTF_4_X;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ppdu_info->gi = he_gi;
|
||||
value = he_gi << HE_GI_SHIFT;
|
||||
@ -813,7 +813,7 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!msdu)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
return HAL_RX_MON_STATUS_PPDU_NOT_DONE;
|
||||
}
|
||||
@ -1124,7 +1124,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
||||
|
||||
/* PN for multicast packets are not validate in HW,
|
||||
* so skip 802.3 rx path
|
||||
* Also, fast_rx expectes the STA to be authorized, hence
|
||||
* Also, fast_rx expects the STA to be authorized, hence
|
||||
* eapol packets are sent in slow path.
|
||||
*/
|
||||
if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol_tkip &&
|
||||
@ -1268,7 +1268,8 @@ int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
|
||||
struct sk_buff *skb;
|
||||
struct hal_srng *srng;
|
||||
dma_addr_t paddr;
|
||||
u32 cookie, buf_id;
|
||||
u32 cookie;
|
||||
int buf_id;
|
||||
|
||||
srng = &ab->hal.srng_list[buf_ring->refill_buf_ring.ring_id];
|
||||
spin_lock_bh(&srng->lock);
|
||||
@ -1917,7 +1918,7 @@ ath12k_dp_mon_tx_parse_status_tlv(struct ath12k_base *ab,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!msdu)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
return DP_MON_TX_STATUS_PPDU_NOT_DONE;
|
||||
}
|
||||
@ -2110,7 +2111,7 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int mac_id, int *budget,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!skb)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
goto move_next;
|
||||
}
|
||||
@ -2511,7 +2512,7 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!skb)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
goto move_next;
|
||||
}
|
||||
|
@ -2443,7 +2443,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
|
||||
|
||||
/* PN for multicast packets are not validate in HW,
|
||||
* so skip 802.3 rx path
|
||||
* Also, fast_rx expectes the STA to be authorized, hence
|
||||
* Also, fast_rx expects the STA to be authorized, hence
|
||||
* eapol packets are sent in slow path.
|
||||
*/
|
||||
if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol &&
|
||||
@ -2611,7 +2611,7 @@ try_again:
|
||||
if (!desc_info) {
|
||||
desc_info = ath12k_dp_get_rx_desc(ab, cookie);
|
||||
if (!desc_info) {
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrival");
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrieval");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -3297,7 +3297,7 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
|
||||
if (!desc_info) {
|
||||
desc_info = ath12k_dp_get_rx_desc(ab, cookie);
|
||||
if (!desc_info) {
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrival");
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrieval");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -3494,11 +3494,14 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
|
||||
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
|
||||
peer_id = ath12k_dp_rx_h_peer_id(ab, desc);
|
||||
|
||||
spin_lock(&ab->base_lock);
|
||||
if (!ath12k_peer_find_by_id(ab, peer_id)) {
|
||||
spin_unlock(&ab->base_lock);
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n",
|
||||
peer_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_unlock(&ab->base_lock);
|
||||
|
||||
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 */
|
||||
@ -3718,7 +3721,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
||||
if (!desc_info) {
|
||||
desc_info = ath12k_dp_get_rx_desc(ab, err_info.cookie);
|
||||
if (!desc_info) {
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrival");
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrieval");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ tcl_ring_sel:
|
||||
skb_ext_desc->len, DMA_TO_DEVICE);
|
||||
ret = dma_mapping_error(ab->dev, ti.paddr);
|
||||
if (ret) {
|
||||
kfree(skb_ext_desc);
|
||||
kfree_skb(skb_ext_desc);
|
||||
goto fail_unmap_dma;
|
||||
}
|
||||
|
||||
|
@ -609,7 +609,7 @@ static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
|
||||
HAL_WBM0_RELEASE_RING_BASE_LSB(ab);
|
||||
s->reg_size[1] = HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP;
|
||||
|
||||
/* Some LMAC rings are not accesed from the host:
|
||||
/* Some LMAC rings are not accessed from the host:
|
||||
* RXDMA_BUG, RXDMA_DST, RXDMA_MONITOR_BUF, RXDMA_MONITOR_STATUS,
|
||||
* RXDMA_MONITOR_DST, RXDMA_MONITOR_DESC, RXDMA_DIR_BUF_SRC,
|
||||
* RXDMA_RX_MONITOR_BUF, TX_MONITOR_BUF, TX_MONITOR_DST, SW2RXDMA
|
||||
|
@ -270,7 +270,7 @@ struct ath12k_base;
|
||||
#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN BIT(5)
|
||||
#define HAL_WBM_SW_COOKIE_CONV_CFG_GLOBAL_EN BIT(8)
|
||||
|
||||
/* TCL ring feild mask and offset */
|
||||
/* TCL ring field mask and offset */
|
||||
#define HAL_TCL1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
|
||||
#define HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
|
||||
#define HAL_TCL1_RING_ID_ENTRY_SIZE GENMASK(7, 0)
|
||||
@ -296,7 +296,7 @@ struct ath12k_base;
|
||||
#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP6 GENMASK(20, 18)
|
||||
#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP7 GENMASK(23, 21)
|
||||
|
||||
/* REO ring feild mask and offset */
|
||||
/* REO ring field mask and offset */
|
||||
#define HAL_REO1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
|
||||
#define HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
|
||||
#define HAL_REO1_RING_ID_RING_ID GENMASK(15, 8)
|
||||
@ -738,7 +738,7 @@ struct hal_srng {
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Interrupt mitigation - Batch threshold in terms of numer of frames */
|
||||
/* Interrupt mitigation - Batch threshold in terms of number of frames */
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_TX 256
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_RX 128
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_OTHER 1
|
||||
@ -813,7 +813,7 @@ enum hal_rx_buf_return_buf_manager {
|
||||
#define HAL_REO_CMD_FLG_UNBLK_RESOURCE BIT(7)
|
||||
#define HAL_REO_CMD_FLG_UNBLK_CACHE BIT(8)
|
||||
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* feilds */
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* fields */
|
||||
#define HAL_REO_CMD_UPD0_RX_QUEUE_NUM BIT(8)
|
||||
#define HAL_REO_CMD_UPD0_VLD BIT(9)
|
||||
#define HAL_REO_CMD_UPD0_ALDC BIT(10)
|
||||
@ -838,7 +838,7 @@ enum hal_rx_buf_return_buf_manager {
|
||||
#define HAL_REO_CMD_UPD0_PN_VALID BIT(29)
|
||||
#define HAL_REO_CMD_UPD0_PN BIT(30)
|
||||
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* feilds */
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* fields */
|
||||
#define HAL_REO_CMD_UPD1_VLD BIT(16)
|
||||
#define HAL_REO_CMD_UPD1_ALDC GENMASK(18, 17)
|
||||
#define HAL_REO_CMD_UPD1_DIS_DUP_DETECTION BIT(19)
|
||||
@ -854,7 +854,7 @@ enum hal_rx_buf_return_buf_manager {
|
||||
#define HAL_REO_CMD_UPD1_PN_HANDLE_ENABLE BIT(30)
|
||||
#define HAL_REO_CMD_UPD1_IGNORE_AMPDU_FLG BIT(31)
|
||||
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* feilds */
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* fields */
|
||||
#define HAL_REO_CMD_UPD2_SVLD BIT(10)
|
||||
#define HAL_REO_CMD_UPD2_SSN GENMASK(22, 11)
|
||||
#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(23)
|
||||
|
@ -706,7 +706,7 @@ struct rx_msdu_desc {
|
||||
*
|
||||
* msdu_continuation
|
||||
* When set, this MSDU buffer was not able to hold the entire MSDU.
|
||||
* The next buffer will therefor contain additional information
|
||||
* The next buffer will therefore contain additional information
|
||||
* related to this MSDU.
|
||||
*
|
||||
* msdu_length
|
||||
@ -1294,7 +1294,7 @@ struct hal_tcl_data_cmd {
|
||||
* link descriptor.
|
||||
*
|
||||
* tcl_cmd_type
|
||||
* used to select the type of TCL Command decriptor
|
||||
* used to select the type of TCL Command descriptor
|
||||
*
|
||||
* desc_type
|
||||
* Indicates the type of address provided in the buf_addr_info.
|
||||
@ -1408,7 +1408,7 @@ struct hal_tcl_data_cmd {
|
||||
* index_loop_override
|
||||
* When set, address search and packet routing is forced to use
|
||||
* 'search_index' instead of following the register configuration
|
||||
* seleced by Bank_id.
|
||||
* selected by Bank_id.
|
||||
*
|
||||
* ring_id
|
||||
* The buffer pointer ring ID.
|
||||
@ -1990,7 +1990,7 @@ struct hal_wbm_release_ring {
|
||||
* Producer: SW/TQM/RXDMA/REO/SWITCH
|
||||
* Consumer: WBM/SW/FW
|
||||
*
|
||||
* HTT tx status is overlayed on wbm_release ring on 4-byte words 2, 3, 4 and 5
|
||||
* HTT tx status is overlaid on wbm_release ring on 4-byte words 2, 3, 4 and 5
|
||||
* for software based completions.
|
||||
*
|
||||
* buf_addr_info
|
||||
@ -2552,7 +2552,7 @@ struct hal_reo_status_hdr {
|
||||
* commands.
|
||||
*
|
||||
* execution_time (in us)
|
||||
* The amount of time REO took to excecute the command. Note that
|
||||
* The amount of time REO took to execute the command. Note that
|
||||
* this time does not include the duration of the command waiting
|
||||
* in the command ring, before the execution started.
|
||||
*
|
||||
|
@ -119,6 +119,30 @@ static const char *irq_name[ATH12K_IRQ_NUM_MAX] = {
|
||||
"tcl2host-status-ring",
|
||||
};
|
||||
|
||||
static int ath12k_pci_bus_wake_up(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
|
||||
}
|
||||
|
||||
static void ath12k_pci_bus_release(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
|
||||
}
|
||||
|
||||
static const struct ath12k_pci_ops ath12k_pci_ops_qcn9274 = {
|
||||
.wakeup = NULL,
|
||||
.release = NULL,
|
||||
};
|
||||
|
||||
static const struct ath12k_pci_ops ath12k_pci_ops_wcn7850 = {
|
||||
.wakeup = ath12k_pci_bus_wake_up,
|
||||
.release = ath12k_pci_bus_release,
|
||||
};
|
||||
|
||||
static void ath12k_pci_select_window(struct ath12k_pci *ab_pci, u32 offset)
|
||||
{
|
||||
struct ath12k_base *ab = ab_pci->ab;
|
||||
@ -989,13 +1013,14 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
u32 val, window_start;
|
||||
int ret = 0;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup MHI to access.
|
||||
*/
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup)
|
||||
ret = ab_pci->pci_ops->wakeup(ab);
|
||||
|
||||
if (offset < WINDOW_START) {
|
||||
val = ioread32(ab->mem + offset);
|
||||
@ -1023,9 +1048,9 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset)
|
||||
}
|
||||
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
|
||||
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->release &&
|
||||
!ret)
|
||||
ab_pci->pci_ops->release(ab);
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -1033,13 +1058,14 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
u32 window_start;
|
||||
int ret = 0;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup MHI to access.
|
||||
*/
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup)
|
||||
ret = ab_pci->pci_ops->wakeup(ab);
|
||||
|
||||
if (offset < WINDOW_START) {
|
||||
iowrite32(value, ab->mem + offset);
|
||||
@ -1067,8 +1093,9 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
|
||||
}
|
||||
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->release &&
|
||||
!ret)
|
||||
ab_pci->pci_ops->release(ab);
|
||||
}
|
||||
|
||||
int ath12k_pci_power_up(struct ath12k_base *ab)
|
||||
@ -1182,6 +1209,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
||||
case QCN9274_DEVICE_ID:
|
||||
ab_pci->msi_config = &ath12k_msi_config[0];
|
||||
ab->static_window_map = true;
|
||||
ab_pci->pci_ops = &ath12k_pci_ops_qcn9274;
|
||||
ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
|
||||
&soc_hw_version_minor);
|
||||
switch (soc_hw_version_major) {
|
||||
@ -1202,6 +1230,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
||||
ab_pci->msi_config = &ath12k_msi_config[0];
|
||||
ab->static_window_map = false;
|
||||
ab->hw_rev = ATH12K_HW_WCN7850_HW20;
|
||||
ab_pci->pci_ops = &ath12k_pci_ops_wcn7850;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -86,6 +86,11 @@ enum ath12k_pci_flags {
|
||||
ATH12K_PCI_ASPM_RESTORE,
|
||||
};
|
||||
|
||||
struct ath12k_pci_ops {
|
||||
int (*wakeup)(struct ath12k_base *ab);
|
||||
void (*release)(struct ath12k_base *ab);
|
||||
};
|
||||
|
||||
struct ath12k_pci {
|
||||
struct pci_dev *pdev;
|
||||
struct ath12k_base *ab;
|
||||
@ -103,6 +108,7 @@ struct ath12k_pci {
|
||||
/* enum ath12k_pci_flags */
|
||||
unsigned long flags;
|
||||
u16 link_ctl;
|
||||
const struct ath12k_pci_ops *pci_ops;
|
||||
};
|
||||
|
||||
static inline struct ath12k_pci *ath12k_pci_priv(struct ath12k_base *ab)
|
||||
|
@ -1072,7 +1072,7 @@ struct rx_msdu_end_qcn9274 {
|
||||
*
|
||||
* l4_offset
|
||||
* Depending upon mode bit, this field either indicates the
|
||||
* L4 offset nin bytes from the start of RX_HEADER (only valid
|
||||
* L4 offset in bytes from the start of RX_HEADER (only valid
|
||||
* if either ipv4_proto or ipv6_proto is set to 1) or indicates
|
||||
* the offset in bytes to the start of TCP or UDP header from
|
||||
* the start of the IP header after decapsulation (Only valid if
|
||||
|
@ -494,7 +494,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
|
||||
|
||||
/* tx/rx chainmask reported from fw depends on the actual hw chains used,
|
||||
* For example, for 4x4 capable macphys, first 4 chains can be used for first
|
||||
* mac and the remaing 4 chains can be used for the second mac or vice-versa.
|
||||
* mac and the remaining 4 chains can be used for the second mac or vice-versa.
|
||||
* In this case, tx/rx chainmask 0xf will be advertised for first mac and 0xf0
|
||||
* will be advertised for second mac or vice-versa. Compute the shift value
|
||||
* for tx/rx chainmask which will be used to advertise supported ht/vht rates to
|
||||
@ -1743,7 +1743,7 @@ int ath12k_wmi_vdev_install_key(struct ath12k *ar,
|
||||
int ret, len, key_len_aligned;
|
||||
|
||||
/* WMI_TAG_ARRAY_BYTE needs to be aligned with 4, the actual key
|
||||
* length is specifed in cmd->key_len.
|
||||
* length is specified in cmd->key_len.
|
||||
*/
|
||||
key_len_aligned = roundup(arg->key_len, 4);
|
||||
|
||||
@ -5995,7 +5995,7 @@ static void ath12k_service_available_event(struct ath12k_base *ab, struct sk_buf
|
||||
}
|
||||
|
||||
/* TODO: Use wmi_service_segment_offset information to get the service
|
||||
* especially when more services are advertised in multiple sevice
|
||||
* especially when more services are advertised in multiple service
|
||||
* available events.
|
||||
*/
|
||||
for (i = 0, j = WMI_MAX_SERVICE;
|
||||
|
@ -4002,7 +4002,7 @@ struct ath12k_wmi_pdev_radar_event {
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_temperature_event {
|
||||
/* temperature value in Celcius degree */
|
||||
/* temperature value in Celsius degree */
|
||||
a_sle32 temp;
|
||||
__le32 pdev_id;
|
||||
} __packed;
|
||||
@ -4192,7 +4192,7 @@ enum wmi_sta_ps_param_tx_wake_threshold {
|
||||
*/
|
||||
enum wmi_sta_ps_param_pspoll_count {
|
||||
WMI_STA_PS_PSPOLL_COUNT_NO_MAX = 0,
|
||||
/* Values greater than 0 indicate the maximum numer of PS-Poll frames
|
||||
/* Values greater than 0 indicate the maximum number of PS-Poll frames
|
||||
* FW will send before waking up.
|
||||
*/
|
||||
};
|
||||
|
@ -113,15 +113,13 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no IRQ resource found\n");
|
||||
ret = -ENXIO;
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq);
|
||||
ret = irq;
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
irq = res->start;
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
|
||||
if (hw == NULL) {
|
||||
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
|
||||
|
@ -529,7 +529,7 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
|
||||
ee->ee_n_piers[mode]++;
|
||||
|
||||
freq2 = (val >> 8) & 0xff;
|
||||
if (!freq2)
|
||||
if (!freq2 || i >= max)
|
||||
break;
|
||||
|
||||
pc[i++].freq = ath5k_eeprom_bin2freq(ee,
|
||||
|
@ -246,7 +246,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
size = sizeof(cid) + sizeof(addr) + sizeof(param);
|
||||
size = sizeof(cid) + sizeof(addr) + sizeof(*param);
|
||||
if (size > ar->bmi.max_cmd_size) {
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
|
@ -960,8 +960,8 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
|
||||
* Thus the possibility of ar->htc_target being NULL
|
||||
* via ath6kl_recv_complete -> ath6kl_usb_io_comp_work.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!target)) {
|
||||
ath6kl_err("Target not yet initialized\n");
|
||||
if (!target) {
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC, "Target not yet initialized\n");
|
||||
status = -EINVAL;
|
||||
goto free_skb;
|
||||
}
|
||||
|
@ -534,6 +534,24 @@ static struct ath9k_htc_hif hif_usb = {
|
||||
.send = hif_usb_send,
|
||||
};
|
||||
|
||||
/* Need to free remain_skb allocated in ath9k_hif_usb_rx_stream
|
||||
* in case ath9k_hif_usb_rx_stream wasn't called next time to
|
||||
* process the buffer and subsequently free it.
|
||||
*/
|
||||
static void ath9k_hif_usb_free_rx_remain_skb(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hif_dev->rx_lock, flags);
|
||||
if (hif_dev->remain_skb) {
|
||||
dev_kfree_skb_any(hif_dev->remain_skb);
|
||||
hif_dev->remain_skb = NULL;
|
||||
hif_dev->rx_remain_len = 0;
|
||||
RX_STAT_INC(hif_dev, skb_dropped);
|
||||
}
|
||||
spin_unlock_irqrestore(&hif_dev->rx_lock, flags);
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -868,6 +886,7 @@ err:
|
||||
static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
usb_kill_anchored_urbs(&hif_dev->rx_submitted);
|
||||
ath9k_hif_usb_free_rx_remain_skb(hif_dev);
|
||||
}
|
||||
|
||||
static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
|
||||
|
@ -503,7 +503,7 @@ int ath_key_config(struct ath_common *common,
|
||||
|
||||
hk.kv_len = key->keylen;
|
||||
if (key->keylen)
|
||||
memcpy(hk.kv_val, key->key, key->keylen);
|
||||
memcpy(&hk.kv_values, key->key, key->keylen);
|
||||
|
||||
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
switch (vif->type) {
|
||||
|
@ -475,8 +475,8 @@ out:
|
||||
|
||||
#define PREPARE_HAL_BUF(send_buf, msg_body) \
|
||||
do { \
|
||||
memset(send_buf, 0, msg_body.header.len); \
|
||||
memcpy(send_buf, &msg_body, sizeof(msg_body)); \
|
||||
memcpy_and_pad(send_buf, msg_body.header.len, \
|
||||
&msg_body, sizeof(msg_body), 0); \
|
||||
} while (0) \
|
||||
|
||||
#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user