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:
Kalle Valo 2023-03-13 15:50:44 +02:00
commit 4c4ca9f7c4
33 changed files with 1223 additions and 326 deletions

View File

@ -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 {

View File

@ -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)
{

View File

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

View File

@ -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);

View File

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

View File

@ -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,

View File

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

View File

@ -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) {

View File

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

View File

@ -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);

View File

@ -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 {

View File

@ -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;
}

View File

@ -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

View File

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

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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.
*

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

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

View File

@ -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.
*/
};

View File

@ -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");

View File

@ -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,

View File

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

View File

@ -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;
}

View File

@ -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)

View File

@ -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) {

View File

@ -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) \