Johannes Berg says:

====================
The usual features/cleanups/etc., notably:

 - rtw88: IBSS mode for SDIO devices
 - rtw89:
   - BT coex for MLO/WiFi7
   - work on station + P2P concurrency
 - ath: fix W=2 export.h warnings
 - ath12k: fix scan on multi-radio devices
 - cfg80211/mac80211: MLO statistics
 - mac80211: S1G aggregation
 - cfg80211/mac80211: per-radio RTS threshold

* tag 'wireless-next-2025-06-25' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (171 commits)
  wifi: iwlwifi: dvm: fix potential overflow in rs_fill_link_cmd()
  iwlwifi: Add missing check for alloc_ordered_workqueue
  wifi: iwlwifi: Fix memory leak in iwl_mvm_init()
  iwlwifi: api: delete repeated words
  iwlwifi: remove unused no_sleep_autoadjust declaration
  iwlwifi: Fix comment typo
  iwlwifi: use DECLARE_BITMAP macro
  iwlwifi: fw: simplify the iwl_fw_dbg_collect_trig()
  wifi: iwlwifi: mld: ftm: fix switch end indentation
  MAINTAINERS: update iwlwifi git link
  wifi: iwlwifi: pcie: fix non-MSIX handshake register
  wifi: iwlwifi: mld: don't exit EMLSR when we shouldn't
  wifi: iwlwifi: move _iwl_trans_set_bits_mask utilities
  wifi: iwlwifi: mld: make iwl_mld_add_all_rekeys void
  wifi: iwlwifi: move iwl_trans_pcie_write_mem to iwl-trans.c
  wifi: iwlwifi: pcie: move iwl_trans_pcie_dump_regs() to utils.c
  wifi: iwlwifi: mld: advertise support for TTLM changes
  wifi: iwlwifi: mld: Block EMLSR when scanning on P2P Device
  wifi: iwlwifi: mld: use the correct struct size for tracing
  wifi: iwlwifi: support RZL platform device ID
  ...
====================

Link: https://patch.msgid.link/20250625120135.41933-55-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2025-06-25 10:28:13 -07:00
291 changed files with 5840 additions and 1906 deletions

View File

@@ -12521,7 +12521,7 @@ M: Miri Korenblit <miriam.rachel.korenblit@intel.com>
L: linux-wireless@vger.kernel.org
S: Supported
W: https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
T: git https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git/
F: drivers/net/wireless/intel/iwlwifi/
INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER

View File

@@ -1293,7 +1293,7 @@ static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid)
ADM8211_CSR_WRITE(ABDA1, reg);
}
static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
static int adm8211_config(struct ieee80211_hw *dev, int radio_idx, u32 changed)
{
struct adm8211_priv *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;

View File

@@ -1083,7 +1083,8 @@ static void ar5523_stop(struct ieee80211_hw *hw, bool suspend)
mutex_unlock(&ar->mutex);
}
static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
u32 value)
{
struct ar5523 *ar = hw->priv;
int ret;
@@ -1137,7 +1138,7 @@ static void ar5523_remove_interface(struct ieee80211_hw *hw,
ar->vif = NULL;
}
static int ar5523_hwconfig(struct ieee80211_hw *hw, u32 changed)
static int ar5523_hwconfig(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct ar5523 *ar = hw->priv;

View File

@@ -3,8 +3,10 @@
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2014,2016-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include "bmi.h"
#include "hif.h"
#include "debug.h"

View File

@@ -4,8 +4,10 @@
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include "hif.h"
#include "ce.h"
#include "debug.h"

View File

@@ -4,8 +4,10 @@
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/of.h>
@@ -2606,7 +2608,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
set_coverage_class_work);
if (ar->hw_params.hw_ops->set_coverage_class)
ar->hw_params.hw_ops->set_coverage_class(ar, -1);
ar->hw_params.hw_ops->set_coverage_class(ar, -1, -1);
}
static int ath10k_core_init_firmware_features(struct ath10k *ar)

View File

@@ -3,11 +3,13 @@
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "coredump.h"
#include <linux/devcoredump.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/utsname.h>

View File

@@ -4,10 +4,12 @@
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/export.h>
#include <linux/vmalloc.h>
#include <linux/crc32.h>
#include <linux/firmware.h>

View File

@@ -3,8 +3,11 @@
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include "core.h"
#include "hif.h"
#include "debug.h"

View File

@@ -4,8 +4,11 @@
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include "core.h"
#include "htc.h"
#include "htt.h"

View File

@@ -3,8 +3,10 @@
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/etherdevice.h>
#include "htt.h"
#include "mac.h"

View File

@@ -590,6 +590,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
* function monitors and modifies the corresponding MAC registers.
*/
static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar,
int radio_idx,
s16 value)
{
u32 slottime_reg;

View File

@@ -646,7 +646,7 @@ struct htt_rx_ring_rx_desc_offsets;
/* Defines needed for Rx descriptor abstraction */
struct ath10k_hw_ops {
void (*set_coverage_class)(struct ath10k *ar, s16 value);
void (*set_coverage_class)(struct ath10k *ar, int radio_idx, s16 value);
int (*enable_pll_clk)(struct ath10k *ar);
int (*tx_data_rssi_pad_bytes)(struct htt_resp *htt);
int (*is_rssi_enable)(struct htt_resp *resp);

View File

@@ -9,6 +9,7 @@
#include "mac.h"
#include <linux/export.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
@@ -4820,7 +4821,8 @@ void ath10k_halt(struct ath10k *ar)
spin_unlock_bh(&ar->data_lock);
}
static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
static int ath10k_get_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 *tx_ant, u32 *rx_ant)
{
struct ath10k *ar = hw->priv;
@@ -5067,7 +5069,8 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
return 0;
}
static int ath10k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
static int ath10k_set_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 tx_ant, u32 rx_ant)
{
struct ath10k *ar = hw->priv;
int ret;
@@ -5437,7 +5440,7 @@ static int ath10k_config_ps(struct ath10k *ar)
return ret;
}
static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
static int ath10k_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct ath10k *ar = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
@@ -6336,7 +6339,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}
static void ath10k_mac_op_set_coverage_class(struct ieee80211_hw *hw, s16 value)
static void ath10k_mac_op_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
s16 value)
{
struct ath10k *ar = hw->priv;
@@ -6347,7 +6351,7 @@ static void ath10k_mac_op_set_coverage_class(struct ieee80211_hw *hw, s16 value)
WARN_ON_ONCE(1);
return;
}
ar->hw_params.hw_ops->set_coverage_class(ar, value);
ar->hw_params.hw_ops->set_coverage_class(ar, -1, value);
}
struct ath10k_mac_tdls_iter_data {
@@ -8035,7 +8039,8 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw,
* in ath10k, but device-specific in mac80211.
*/
static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
u32 value)
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif;
@@ -8058,7 +8063,8 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
static int ath10k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
static int ath10k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,
int radio_idx, u32 value)
{
/* Even though there's a WMI enum for fragmentation threshold no known
* firmware actually implements it. Moreover it is not possible to rely

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2012 Qualcomm Atheros, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/module.h>
#define CREATE_TRACE_POINTS

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include "dp_rx.h"
#include "debug.h"
#include "hif.h"

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/remoteproc.h>

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/devcoredump.h>
#include <linux/export.h>
#include "hif.h"
#include "coredump.h"
#include "debug.h"

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/vmalloc.h>
#include "core.h"
#include "debug.h"

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/vmalloc.h>
#include "debugfs.h"

View File

@@ -2,9 +2,11 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <crypto/hash.h>
#include <linux/export.h>
#include "core.h"
#include "dp_tx.h"
#include "hal_tx.h"

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include "core.h"
#include "debug.h"

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/dma-mapping.h>
#include <linux/export.h>
#include "hal_tx.h"
#include "debug.h"
#include "hal_desc.h"

View File

@@ -1283,7 +1283,7 @@ static int ath11k_mac_config_ps(struct ath11k *ar)
return ret;
}
static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
static int ath11k_mac_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct ath11k *ar = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
@@ -7044,7 +7044,8 @@ static void ath11k_mac_op_configure_filter(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}
static int ath11k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
static int ath11k_mac_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 *tx_ant, u32 *rx_ant)
{
struct ath11k *ar = hw->priv;
@@ -7058,7 +7059,8 @@ static int ath11k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *
return 0;
}
static int ath11k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
static int ath11k_mac_op_set_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 tx_ant, u32 rx_ant)
{
struct ath11k *ar = hw->priv;
int ret;
@@ -8182,7 +8184,8 @@ ath11k_set_vdev_param_to_all_vifs(struct ath11k *ar, int param, u32 value)
/* mac80211 stores device specific RTS/Fragmentation threshold value,
* this is set interface specific to firmware from ath11k driver
*/
static int ath11k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int ath11k_mac_op_set_rts_threshold(struct ieee80211_hw *hw,
int radio_idx, u32 value)
{
struct ath11k *ar = hw->priv;
int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
@@ -8190,7 +8193,8 @@ static int ath11k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ath11k_set_vdev_param_to_all_vifs(ar, param_id, value);
}
static int ath11k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
static int ath11k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,
int radio_idx, u32 value)
{
/* Even though there's a WMI vdev param for fragmentation threshold no
* known firmware actually implements it. Moreover it is not possible to

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include "core.h"
#include "pcic.h"
#include "debug.h"

View File

@@ -2,9 +2,11 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/elf.h>
#include <linux/export.h>
#include "qmi.h"
#include "core.h"

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/module.h>
#define CREATE_TRACE_POINTS

View File

@@ -2,8 +2,10 @@
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/remoteproc.h>
@@ -1409,6 +1411,7 @@ void ath12k_core_halt(struct ath12k *ar)
ath12k_mac_peer_cleanup_all(ar);
cancel_delayed_work_sync(&ar->scan.timeout);
cancel_work_sync(&ar->regd_update_work);
cancel_work_sync(&ar->regd_channel_update_work);
cancel_work_sync(&ab->rfkill_work);
cancel_work_sync(&ab->update_11d_work);
@@ -1472,6 +1475,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
complete(&ar->vdev_setup_done);
complete(&ar->vdev_delete_done);
complete(&ar->bss_survey_done);
complete(&ar->regd_update_completed);
wake_up(&ar->dp.tx_empty_waitq);
idr_for_each(&ar->txmgmt_idr,
@@ -1511,6 +1515,9 @@ static void ath12k_update_11d(struct work_struct *work)
ar = pdev->ar;
memcpy(&ar->alpha2, &arg.alpha2, 2);
reinit_completion(&ar->regd_update_completed);
ret = ath12k_wmi_send_set_current_country_cmd(ar, &arg);
if (ret)
ath12k_warn(ar->ab,

View File

@@ -345,6 +345,10 @@ struct ath12k_link_vif {
bool is_sta_assoc_link;
struct ath12k_reg_tpc_power_info reg_tpc_info;
bool group_key_valid;
struct wmi_vdev_install_key_arg group_key;
bool pairwise_key_done;
};
struct ath12k_vif {
@@ -380,9 +384,7 @@ struct ath12k_vif {
struct ath12k_link_vif __rcu *link[ATH12K_NUM_MAX_LINKS];
struct ath12k_vif_cache *cache[IEEE80211_MLD_MAX_NUM_LINKS];
/* indicates bitmap of link vif created in FW */
u16 links_map;
u8 last_scan_link;
u32 links_map;
/* Must be last - ends in a flexible-array member.
*
* FIXME: Driver should not copy struct ieee80211_chanctx_conf,
@@ -719,7 +721,7 @@ struct ath12k {
/* protects the radio specific data like debug stats, ppdu_stats_info stats,
* vdev_stop_status info, scan data, ath12k_sta info, ath12k_link_vif info,
* channel context data, survey info, test mode data.
* channel context data, survey info, test mode data, regd_channel_update_queue.
*/
spinlock_t data_lock;
@@ -778,6 +780,8 @@ struct ath12k {
struct completion bss_survey_done;
struct work_struct regd_update_work;
struct work_struct regd_channel_update_work;
struct list_head regd_channel_update_queue;
struct wiphy_work wmi_mgmt_tx_work;
struct sk_buff_head wmi_mgmt_tx_queue;
@@ -811,6 +815,7 @@ struct ath12k {
enum ath12k_11d_state state_11d;
u8 alpha2[REG_ALPHA2_LEN];
bool regdom_set_by_user;
struct completion regd_update_completed;
struct completion fw_stats_complete;
struct completion fw_stats_done;

View File

@@ -84,6 +84,7 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr)
ret = ath12k_dp_rx_peer_frag_setup(ar, addr, vdev_id);
if (ret) {
ath12k_warn(ab, "failed to setup rx defrag context\n");
tid--;
goto peer_clean;
}

View File

@@ -3761,7 +3761,6 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget,
ath12k_hal_srng_access_begin(ab, srng);
while (likely(*budget)) {
*budget -= 1;
mon_dst_desc = ath12k_hal_srng_dst_peek(ab, srng);
if (unlikely(!mon_dst_desc))
break;

View File

@@ -2533,31 +2533,15 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
struct ath12k_dp_rx_info *rx_info)
{
struct ath12k_base *ab = ar->ab;
static const struct ieee80211_radiotap_he known = {
.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN),
.data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN),
};
struct ieee80211_radiotap_he *he;
struct ieee80211_rx_status *rx_status;
struct ieee80211_sta *pubsta;
struct ath12k_peer *peer;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
struct ieee80211_rx_status *status = rx_info->rx_status;
u8 decap = DP_RX_DECAP_TYPE_RAW;
u8 decap = rx_info->decap_type;
bool is_mcbc = rxcb->is_mcbc;
bool is_eapol = rxcb->is_eapol;
if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) &&
!(status->flag & RX_FLAG_SKIP_MONITOR)) {
he = skb_push(msdu, sizeof(known));
memcpy(he, &known, sizeof(known));
status->flag |= RX_FLAG_RADIOTAP_HE;
}
if (!(status->flag & RX_FLAG_ONLY_MONITOR))
decap = rx_info->decap_type;
spin_lock_bh(&ab->base_lock);
peer = ath12k_dp_rx_h_find_peer(ab, msdu, rx_info);

View File

@@ -13,10 +13,9 @@
#include "mac.h"
static enum hal_tcl_encap_type
ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb)
ath12k_dp_tx_get_encap_type(struct ath12k_base *ab, struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath12k_base *ab = arvif->ar->ab;
if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
return HAL_TCL_ENCAP_TYPE_RAW;
@@ -305,7 +304,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM);
}
ti.encap_type = ath12k_dp_tx_get_encap_type(arvif, skb);
ti.encap_type = ath12k_dp_tx_get_encap_type(ab, skb);
ti.addr_search_flags = arvif->hal_addr_search_flags;
ti.search_type = arvif->search_type;
ti.type = HAL_TCL_DESC_TYPE_BUFFER;

View File

@@ -1478,7 +1478,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.download_calib = true,
.supports_suspend = false,
.tcl_ring_retry = true,
.reoq_lut_support = false,
.reoq_lut_support = true,
.supports_shadow_regs = false,
.num_tcl_banks = 48,

View File

@@ -693,6 +693,9 @@ static void ath12k_get_arvif_iter(void *data, u8 *mac,
if (WARN_ON(!arvif))
continue;
if (!arvif->is_created)
continue;
if (arvif->vdev_id == arvif_iter->vdev_id &&
arvif->ar == arvif_iter->ar) {
arvif_iter->arvif = arvif;
@@ -1392,7 +1395,7 @@ int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif)
return ret;
}
static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
static int ath12k_mac_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
return 0;
}
@@ -1755,7 +1758,7 @@ static void ath12k_mac_handle_beacon_iter(void *data, u8 *mac,
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif = &ahvif->deflink;
if (vif->type != NL80211_IFTYPE_STATION)
if (vif->type != NL80211_IFTYPE_STATION || !arvif->is_created)
return;
if (!ether_addr_equal(mgmt->bssid, vif->bss_conf.bssid))
@@ -1778,16 +1781,16 @@ static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
u32 *vdev_id = data;
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k *ar = arvif->ar;
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
struct ieee80211_hw *hw;
if (arvif->vdev_id != *vdev_id)
if (!arvif->is_created || arvif->vdev_id != *vdev_id)
return;
if (!arvif->is_up)
return;
ieee80211_beacon_loss(vif);
hw = ath12k_ar_to_hw(arvif->ar);
/* Firmware doesn't report beacon loss events repeatedly. If AP probe
* (done by mac80211) succeeds but beacons do not resume then it
@@ -3496,7 +3499,7 @@ static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah,
/* If this is the first link arvif being created for an ML VIF
* use the preallocated deflink memory except for scan arvifs
*/
if (!ahvif->links_map && link_id != ATH12K_DEFAULT_SCAN_LINK) {
if (!ahvif->links_map && link_id < ATH12K_FIRST_SCAN_LINK) {
arvif = &ahvif->deflink;
if (vif->type == NL80211_IFTYPE_STATION)
@@ -4149,8 +4152,9 @@ ath12k_mac_select_scan_device(struct ieee80211_hw *hw,
band = NL80211_BAND_6GHZ;
for_each_ar(ah, ar, i) {
/* TODO 5 GHz low high split changes */
if (ar->mac.sbands[band].channels)
if (ar->mac.sbands[band].channels &&
center_freq >= KHZ_TO_MHZ(ar->freq_range.start_freq) &&
center_freq <= KHZ_TO_MHZ(ar->freq_range.end_freq))
return ar;
}
@@ -4274,6 +4278,23 @@ static void ath12k_scan_timeout_work(struct work_struct *work)
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
}
static void ath12k_mac_scan_send_complete(struct ath12k *ar,
struct cfg80211_scan_info *info)
{
struct ath12k_hw *ah = ar->ah;
struct ath12k *partner_ar;
int i;
lockdep_assert_wiphy(ah->hw->wiphy);
for_each_ar(ah, partner_ar, i)
if (partner_ar != ar &&
partner_ar->scan.state == ATH12K_SCAN_RUNNING)
return;
ieee80211_scan_completed(ah->hw, info);
}
static void ath12k_scan_vdev_clean_work(struct wiphy *wiphy, struct wiphy_work *work)
{
struct ath12k *ar = container_of(work, struct ath12k,
@@ -4312,7 +4333,7 @@ static void ath12k_scan_vdev_clean_work(struct wiphy *wiphy, struct wiphy_work *
ATH12K_SCAN_STARTING)),
};
ieee80211_scan_completed(ar->ah->hw, &info);
ath12k_mac_scan_send_complete(ar, &info);
}
ar->scan.state = ATH12K_SCAN_IDLE;
@@ -4488,11 +4509,12 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
struct ath12k_link_vif *arvif;
struct ath12k_hw *ah = ahvif->ah;
unsigned long links = ahvif->links_map;
unsigned long scan_links_map;
u8 link_id;
lockdep_assert_wiphy(ah->hw->wiphy);
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
for_each_set_bit(link_id, &links, ATH12K_NUM_MAX_LINKS) {
arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
if (!arvif || !arvif->is_created)
@@ -4502,18 +4524,30 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
return link_id;
}
/* input ar is not assigned to any of the links of ML VIF, use scan
* link (15) for scan vdev creation.
/* input ar is not assigned to any of the links of ML VIF, use next
* available scan link for scan vdev creation. There are cases where
* single scan req needs to be split in driver and initiate separate
* scan requests to firmware based on device.
*/
return ATH12K_DEFAULT_SCAN_LINK;
/* Unset all non-scan links (0-14) of scan_links_map so that ffs() will
* choose an available link among scan links (i.e link id >= 15)
*/
scan_links_map = ~ahvif->links_map & ATH12K_SCAN_LINKS_MASK;
if (scan_links_map)
return __ffs(scan_links_map);
return ATH12K_FIRST_SCAN_LINK;
}
static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
static int ath12k_mac_initiate_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req,
int n_channels,
struct ieee80211_channel **chan_list,
struct ath12k *ar)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif;
struct cfg80211_scan_request *req = &hw_req->req;
@@ -4527,18 +4561,18 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
arvif = &ahvif->deflink;
/* Since the targeted scan device could depend on the frequency
* requested in the hw_req, select the corresponding radio
*/
ar = ath12k_mac_select_scan_device(hw, vif, hw_req->req.channels[0]->center_freq);
if (!ar)
return -EINVAL;
/* check if any of the links of ML VIF is already started on
* radio(ar) corresponding to given scan frequency and use it,
* if not use scan link (link 15) for scan purpose.
* if not use scan link (link id >= 15) for scan purpose.
*/
link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar);
/* All scan links are occupied. ideally this shouldn't happen as
* mac80211 won't schedule scan for same band until ongoing scan is
* completed, don't try to exceed max links just in case if it happens.
*/
if (link_id >= ATH12K_NUM_MAX_LINKS)
return -EBUSY;
arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac link ID %d selected for scan",
@@ -4629,8 +4663,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
arg->scan_f_passive = 1;
}
if (req->n_channels) {
arg->num_chan = req->n_channels;
if (n_channels) {
arg->num_chan = n_channels;
arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
GFP_KERNEL);
if (!arg->chan_list) {
@@ -4639,7 +4673,7 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
}
for (i = 0; i < arg->num_chan; i++)
arg->chan_list[i] = req->channels[i]->center_freq;
arg->chan_list[i] = chan_list[i]->center_freq;
}
ret = ath12k_start_scan(ar, arg);
@@ -4658,13 +4692,6 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac scan started");
/* As per cfg80211/mac80211 scan design, it allows only one
* scan at a time. Hence last_scan link id is used for
* tracking the link id on which the scan is been done on
* this vif.
*/
ahvif->last_scan_link = arvif->link_id;
/* Add a margin to account for event/command processing */
ieee80211_queue_delayed_work(ath12k_ar_to_hw(ar), &ar->scan.timeout,
msecs_to_jiffies(arg->max_scan_time +
@@ -4685,25 +4712,108 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
return ret;
}
static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ieee80211_channel **chan_list, *chan;
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
unsigned long links_map, link_id;
struct ath12k_link_vif *arvif;
struct ath12k *ar, *scan_ar;
int i, j, ret = 0;
lockdep_assert_wiphy(hw->wiphy);
chan_list = kcalloc(hw_req->req.n_channels, sizeof(*chan_list), GFP_KERNEL);
if (!chan_list)
return -ENOMEM;
/* There could be channels that belong to multiple underlying radio
* in same scan request as mac80211 sees it as single band. In that
* case split the hw_req based on frequency range and schedule scans to
* corresponding radio.
*/
for_each_ar(ah, ar, i) {
int n_chans = 0;
for (j = 0; j < hw_req->req.n_channels; j++) {
chan = hw_req->req.channels[j];
scan_ar = ath12k_mac_select_scan_device(hw, vif,
chan->center_freq);
if (!scan_ar) {
ath12k_hw_warn(ah, "unable to select scan device for freq %d\n",
chan->center_freq);
ret = -EINVAL;
goto abort;
}
if (ar != scan_ar)
continue;
chan_list[n_chans++] = chan;
}
if (n_chans) {
ret = ath12k_mac_initiate_hw_scan(hw, vif, hw_req, n_chans,
chan_list, ar);
if (ret)
goto abort;
}
}
abort:
/* If any of the parallel scans initiated fails, abort all and
* remove the scan interfaces created. Return complete scan
* failure as mac80211 assumes this as single scan request.
*/
if (ret) {
ath12k_hw_warn(ah, "Scan failed %d , cleanup all scan vdevs\n", ret);
links_map = ahvif->links_map;
for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) {
arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
if (!arvif)
continue;
ar = arvif->ar;
if (ar->scan.arvif == arvif) {
wiphy_work_cancel(hw->wiphy, &ar->scan.vdev_clean_wk);
spin_lock_bh(&ar->data_lock);
ar->scan.arvif = NULL;
ar->scan.state = ATH12K_SCAN_IDLE;
ar->scan_channel = NULL;
ar->scan.roc_freq = 0;
spin_unlock_bh(&ar->data_lock);
}
if (link_id >= ATH12K_FIRST_SCAN_LINK) {
ath12k_mac_remove_link_interface(hw, arvif);
ath12k_mac_unassign_link_vif(arvif);
}
}
}
kfree(chan_list);
return ret;
}
static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
u16 link_id = ahvif->last_scan_link;
unsigned long link_id, links_map = ahvif->links_map;
struct ath12k_link_vif *arvif;
struct ath12k *ar;
lockdep_assert_wiphy(hw->wiphy);
arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
if (!arvif || arvif->is_started)
return;
for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) {
arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
if (!arvif || arvif->is_started)
continue;
ar = arvif->ar;
ar = arvif->ar;
ath12k_scan_abort(ar);
ath12k_scan_abort(ar);
cancel_delayed_work_sync(&ar->scan.timeout);
cancel_delayed_work_sync(&ar->scan.timeout);
}
}
static int ath12k_install_key(struct ath12k_link_vif *arvif,
@@ -4719,14 +4829,13 @@ static int ath12k_install_key(struct ath12k_link_vif *arvif,
.key_len = key->keylen,
.key_data = key->key,
.key_flags = flags,
.ieee80211_key_cipher = key->cipher,
.macaddr = macaddr,
};
struct ath12k_vif *ahvif = arvif->ahvif;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->install_key_done);
if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
return 0;
@@ -4735,7 +4844,7 @@ static int ath12k_install_key(struct ath12k_link_vif *arvif,
/* arg.key_cipher = WMI_CIPHER_NONE; */
arg.key_len = 0;
arg.key_data = NULL;
goto install;
goto check_order;
}
switch (key->cipher) {
@@ -4763,19 +4872,82 @@ static int ath12k_install_key(struct ath12k_link_vif *arvif,
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
install:
ret = ath12k_wmi_vdev_install_key(arvif->ar, &arg);
check_order:
if (ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
arg.key_flags == WMI_KEY_GROUP) {
if (cmd == SET_KEY) {
if (arvif->pairwise_key_done) {
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"vdev %u pairwise key done, go install group key\n",
arg.vdev_id);
goto install;
} else {
/* WCN7850 firmware requires pairwise key to be installed
* before group key. In case group key comes first, cache
* it and return. Will revisit it once pairwise key gets
* installed.
*/
arvif->group_key = arg;
arvif->group_key_valid = true;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"vdev %u group key before pairwise key, cache and skip\n",
arg.vdev_id);
ret = 0;
goto out;
}
} else {
arvif->group_key_valid = false;
}
}
install:
reinit_completion(&ar->install_key_done);
ret = ath12k_wmi_vdev_install_key(arvif->ar, &arg);
if (ret)
return ret;
if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))
return -ETIMEDOUT;
if (ether_addr_equal(macaddr, arvif->bssid))
ahvif->key_cipher = key->cipher;
if (ether_addr_equal(arg.macaddr, arvif->bssid))
ahvif->key_cipher = arg.ieee80211_key_cipher;
return ar->install_key_status ? -EINVAL : 0;
if (ar->install_key_status) {
ret = -EINVAL;
goto out;
}
if (ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
arg.key_flags == WMI_KEY_PAIRWISE) {
if (cmd == SET_KEY) {
arvif->pairwise_key_done = true;
if (arvif->group_key_valid) {
/* Install cached GTK */
arvif->group_key_valid = false;
arg = arvif->group_key;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"vdev %u pairwise key done, group key ready, go install\n",
arg.vdev_id);
goto install;
}
} else {
arvif->pairwise_key_done = false;
}
}
out:
if (ret) {
/* In case of failure userspace may not do DISABLE_KEY
* but triggers re-connection directly, so manually reset
* status here.
*/
arvif->group_key_valid = false;
arvif->pairwise_key_done = false;
}
return ret;
}
static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif,
@@ -4869,9 +5041,9 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
}
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
flags |= WMI_KEY_PAIRWISE;
flags = WMI_KEY_PAIRWISE;
else
flags |= WMI_KEY_GROUP;
flags = WMI_KEY_GROUP;
ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags);
if (ret) {
@@ -8114,7 +8286,17 @@ static int ath12k_mac_start(struct ath12k *ar)
/* TODO: Do we need to enable ANI? */
ath12k_reg_update_chan_list(ar, false);
ret = ath12k_reg_update_chan_list(ar, false);
/* The ar state alone can be turned off for non supported country
* without returning the error value. As we need to update the channel
* for the next ar.
*/
if (ret) {
if (ret == -EINVAL)
ret = 0;
goto err;
}
ar->num_started_vdevs = 0;
ar->num_created_vdevs = 0;
@@ -8286,6 +8468,7 @@ static void ath12k_mac_stop(struct ath12k *ar)
{
struct ath12k_hw *ah = ar->ah;
struct htt_ppdu_stats_info *ppdu_stats, *tmp;
struct ath12k_wmi_scan_chan_list_arg *arg;
int ret;
lockdep_assert_held(&ah->hw_mutex);
@@ -8300,6 +8483,7 @@ static void ath12k_mac_stop(struct ath12k *ar)
cancel_delayed_work_sync(&ar->scan.timeout);
wiphy_work_cancel(ath12k_ar_to_hw(ar)->wiphy, &ar->scan.vdev_clean_wk);
cancel_work_sync(&ar->regd_channel_update_work);
cancel_work_sync(&ar->regd_update_work);
cancel_work_sync(&ar->ab->rfkill_work);
cancel_work_sync(&ar->ab->update_11d_work);
@@ -8307,10 +8491,18 @@ static void ath12k_mac_stop(struct ath12k *ar)
complete(&ar->completed_11d_scan);
spin_lock_bh(&ar->data_lock);
list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
list_del(&ppdu_stats->list);
kfree(ppdu_stats);
}
while ((arg = list_first_entry_or_null(&ar->regd_channel_update_queue,
struct ath12k_wmi_scan_chan_list_arg,
list))) {
list_del(&arg->list);
kfree(arg);
}
spin_unlock_bh(&ar->data_lock);
rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);
@@ -9055,7 +9247,8 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
struct ath12k_hw *ah = hw->priv;
struct ath12k *ar;
struct ath12k_base *ab;
u8 link_id = arvif->link_id;
u8 link_id = arvif->link_id, scan_link_id;
unsigned long scan_link_map;
int ret;
lockdep_assert_wiphy(hw->wiphy);
@@ -9074,12 +9267,16 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
* and now we want to create for actual usage.
*/
if (ieee80211_vif_is_mld(vif)) {
scan_arvif = wiphy_dereference(hw->wiphy,
ahvif->link[ATH12K_DEFAULT_SCAN_LINK]);
if (scan_arvif && scan_arvif->ar == ar) {
ar->scan.arvif = NULL;
ath12k_mac_remove_link_interface(hw, scan_arvif);
ath12k_mac_unassign_link_vif(scan_arvif);
scan_link_map = ahvif->links_map & ATH12K_SCAN_LINKS_MASK;
for_each_set_bit(scan_link_id, &scan_link_map, ATH12K_NUM_MAX_LINKS) {
scan_arvif = wiphy_dereference(hw->wiphy,
ahvif->link[scan_link_id]);
if (scan_arvif && scan_arvif->ar == ar) {
ar->scan.arvif = NULL;
ath12k_mac_remove_link_interface(hw, scan_arvif);
ath12k_mac_unassign_link_vif(scan_arvif);
break;
}
}
}
@@ -9314,7 +9511,7 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
.aborted = true,
};
ieee80211_scan_completed(ar->ah->hw, &info);
ath12k_mac_scan_send_complete(ar, &info);
}
ar->scan.state = ATH12K_SCAN_IDLE;
@@ -9354,7 +9551,8 @@ static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
ar->filter_flags = *total_flags;
}
static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 *tx_ant, u32 *rx_ant)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
int antennas_rx = 0, antennas_tx = 0;
@@ -9374,7 +9572,8 @@ static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *
return 0;
}
static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 tx_ant, u32 rx_ant)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
@@ -9818,7 +10017,7 @@ ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
if (WARN_ON(!arvif))
continue;
if (arvif->ar != arg->ar)
if (!arvif->is_created || arvif->ar != arg->ar)
continue;
link_conf = wiphy_dereference(ahvif->ah->hw->wiphy,
@@ -9853,7 +10052,7 @@ ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
if (WARN_ON(!arvif))
continue;
if (arvif->ar != arg->ar)
if (!arvif->is_created || arvif->ar != arg->ar)
continue;
link_conf = wiphy_dereference(ahvif->ah->hw->wiphy,
@@ -10735,7 +10934,8 @@ ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
/* mac80211 stores device specific RTS/Fragmentation threshold value,
* this is set interface specific to firmware from ath12k driver
*/
static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw,
int radio_idx, u32 value)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
@@ -10760,7 +10960,8 @@ static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,
int radio_idx, u32 value)
{
/* Even though there's a WMI vdev param for fragmentation threshold no
* known firmware actually implements it. Moreover it is not possible to
@@ -11246,6 +11447,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
struct wmi_set_current_country_arg arg = {};
memcpy(&arg.alpha2, ar->alpha2, 2);
reinit_completion(&ar->regd_update_completed);
ath12k_wmi_send_set_current_country_cmd(ar, &arg);
}
@@ -11757,6 +11959,32 @@ static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band)
return 0;
}
static int ath12k_mac_update_band(struct ath12k *ar,
struct ieee80211_supported_band *orig_band,
struct ieee80211_supported_band *new_band)
{
int i;
if (!orig_band || !new_band)
return -EINVAL;
if (orig_band->band != new_band->band)
return -EINVAL;
for (i = 0; i < new_band->n_channels; i++) {
if (new_band->channels[i].flags & IEEE80211_CHAN_DISABLED)
continue;
/* An enabled channel in new_band should not be already enabled
* in the orig_band
*/
if (WARN_ON(!(orig_band->channels[i].flags &
IEEE80211_CHAN_DISABLED)))
return -EINVAL;
orig_band->channels[i].flags &= ~IEEE80211_CHAN_DISABLED;
}
return 0;
}
static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
u32 supported_bands,
struct ieee80211_supported_band *bands[])
@@ -11767,6 +11995,7 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
u32 phy_id, freq_low, freq_high;
struct ath12k_hw *ah = ar->ah;
void *channels;
int ret;
BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +
ARRAY_SIZE(ath12k_5ghz_channels) +
@@ -11788,7 +12017,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
band->channels = channels;
band->n_bitrates = ath12k_g_rates_size;
band->bitrates = ath12k_g_rates;
bands[NL80211_BAND_2GHZ] = band;
if (ab->hw_params->single_pdev_only) {
phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2GHZ_CAP);
@@ -11805,6 +12033,22 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
reg_cap->high_2ghz_chan);
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
if (!bands[NL80211_BAND_2GHZ]) {
bands[NL80211_BAND_2GHZ] = band;
} else {
/* Split mac in same band under same wiphy */
ret = ath12k_mac_update_band(ar, bands[NL80211_BAND_2GHZ], band);
if (ret) {
kfree(channels);
band->channels = NULL;
return ret;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 2 GHz split mac with start freq %d end freq %d",
ar->pdev->pdev_id,
KHZ_TO_MHZ(ar->freq_range.start_freq),
KHZ_TO_MHZ(ar->freq_range.end_freq));
}
}
if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
@@ -11823,7 +12067,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
band->channels = channels;
band->n_bitrates = ath12k_a_rates_size;
band->bitrates = ath12k_a_rates;
bands[NL80211_BAND_6GHZ] = band;
freq_low = max(reg_cap->low_5ghz_chan,
ab->reg_freq_6ghz.start_freq);
@@ -11836,6 +12079,26 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
ah->use_6ghz_regd = true;
if (!bands[NL80211_BAND_6GHZ]) {
bands[NL80211_BAND_6GHZ] = band;
} else {
/* Split mac in same band under same wiphy */
ret = ath12k_mac_update_band(ar,
bands[NL80211_BAND_6GHZ],
band);
if (ret) {
kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
kfree(channels);
band->channels = NULL;
return ret;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 6 GHz split mac with start freq %d end freq %d",
ar->pdev->pdev_id,
KHZ_TO_MHZ(ar->freq_range.start_freq),
KHZ_TO_MHZ(ar->freq_range.end_freq));
}
}
if (reg_cap->low_5ghz_chan < ATH12K_MIN_6GHZ_FREQ) {
@@ -11854,7 +12117,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
band->channels = channels;
band->n_bitrates = ath12k_a_rates_size;
band->bitrates = ath12k_a_rates;
bands[NL80211_BAND_5GHZ] = band;
if (ab->hw_params->single_pdev_only) {
phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5GHZ_CAP);
@@ -11871,6 +12133,28 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
reg_cap->high_5ghz_chan);
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
if (!bands[NL80211_BAND_5GHZ]) {
bands[NL80211_BAND_5GHZ] = band;
} else {
/* Split mac in same band under same wiphy */
ret = ath12k_mac_update_band(ar,
bands[NL80211_BAND_5GHZ],
band);
if (ret) {
kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
kfree(channels);
band->channels = NULL;
return ret;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 5 GHz split mac with start freq %d end freq %d",
ar->pdev->pdev_id,
KHZ_TO_MHZ(ar->freq_range.start_freq),
KHZ_TO_MHZ(ar->freq_range.end_freq));
}
}
}
@@ -12204,6 +12488,7 @@ static void ath12k_mac_hw_unregister(struct ath12k_hw *ah)
int i;
for_each_ar(ah, ar, i) {
cancel_work_sync(&ar->regd_channel_update_work);
cancel_work_sync(&ar->regd_update_work);
ath12k_debugfs_unregister(ar);
ath12k_fw_stats_reset(ar);
@@ -12462,6 +12747,16 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
goto err_cleanup_if_combs;
}
/* Boot-time regulatory updates have already been processed.
* Mark them as complete now, because after registration,
* cfg80211 will notify us again if there are any pending hints.
* We need to wait for those hints to be processed, so it's
* important to mark the boot-time updates as complete before
* proceeding with registration.
*/
for_each_ar(ah, ar, i)
complete(&ar->regd_update_completed);
ret = ieee80211_register_hw(hw);
if (ret) {
ath12k_err(ab, "ieee80211 registration failed: %d\n", ret);
@@ -12489,6 +12784,9 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
memcpy(&current_cc.alpha2, ab->new_alpha2, 2);
memcpy(&ar->alpha2, ab->new_alpha2, 2);
reinit_completion(&ar->regd_update_completed);
ret = ath12k_wmi_send_set_current_country_cmd(ar, &current_cc);
if (ret)
ath12k_warn(ar->ab,
@@ -12561,9 +12859,12 @@ static void ath12k_mac_setup(struct ath12k *ar)
init_completion(&ar->scan.on_channel);
init_completion(&ar->mlo_setup_done);
init_completion(&ar->completed_11d_scan);
init_completion(&ar->regd_update_completed);
INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);
wiphy_work_init(&ar->scan.vdev_clean_wk, ath12k_scan_vdev_clean_work);
INIT_WORK(&ar->regd_channel_update_work, ath12k_regd_update_chan_list_work);
INIT_LIST_HEAD(&ar->regd_channel_update_queue);
INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work);
wiphy_work_init(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);

View File

@@ -51,8 +51,11 @@ struct ath12k_generic_iter {
/* Default link after the IEEE802.11 defined Max link id limit
* for driver usage purpose.
*/
#define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS
#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1)
#define ATH12K_FIRST_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS
#define ATH12K_SCAN_MAX_LINKS ATH12K_GROUP_MAX_RADIO
/* Define 1 scan link for each radio for parallel scan purposes */
#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + ATH12K_SCAN_MAX_LINKS)
#define ATH12K_SCAN_LINKS_MASK GENMASK(ATH12K_NUM_MAX_LINKS, IEEE80211_MLD_MAX_NUM_LINKS)
#define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <net/mac80211.h>
@@ -124,7 +125,7 @@ static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
WARN_ON(!rcu_read_lock_any_held());
arvif = &ahvif->deflink;
if (arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
if (!arvif->is_created || arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
return;
ath12k_p2p_noa_update(arvif, arg->noa);

View File

@@ -65,7 +65,7 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
for_each_ar(ah, ar, i) {
ret = ath12k_reg_update_chan_list(ar, true);
if (ret) {
if (ret && ret != -EINVAL) {
ath12k_warn(ar->ab,
"failed to update chan list for pdev %u, ret %d\n",
i, ret);
@@ -102,6 +102,8 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
/* Send the reg change request to all the radios */
for_each_ar(ah, ar, i) {
reinit_completion(&ar->regd_update_completed);
if (ar->ab->hw_params->current_cc_support) {
memcpy(&current_arg.alpha2, request->alpha2, 2);
memcpy(&ar->alpha2, &current_arg.alpha2, 2);
@@ -137,32 +139,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
struct ath12k_wmi_channel_arg *ch;
enum nl80211_band band;
int num_channels = 0;
int i, ret, left;
if (wait && ar->state_11d == ATH12K_11D_RUNNING) {
left = wait_for_completion_timeout(&ar->completed_11d_scan,
ATH12K_SCAN_TIMEOUT_HZ);
if (!left) {
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"failed to receive 11d scan complete: timed out\n");
ar->state_11d = ATH12K_11D_IDLE;
}
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"reg 11d scan wait left time %d\n", left);
}
if (wait &&
(ar->scan.state == ATH12K_SCAN_STARTING ||
ar->scan.state == ATH12K_SCAN_RUNNING)) {
left = wait_for_completion_timeout(&ar->scan.completed,
ATH12K_SCAN_TIMEOUT_HZ);
if (!left)
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"failed to receive hw scan complete: timed out\n");
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"reg hw scan wait left time %d\n", left);
}
int i, ret = 0;
if (ar->ah->state == ATH12K_HW_STATE_RESTARTING)
return 0;
@@ -176,13 +153,22 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
if (bands[band]->channels[i].flags &
IEEE80211_CHAN_DISABLED)
continue;
/* Skip Channels that are not in current radio's range */
if (bands[band]->channels[i].center_freq <
KHZ_TO_MHZ(ar->freq_range.start_freq) ||
bands[band]->channels[i].center_freq >
KHZ_TO_MHZ(ar->freq_range.end_freq))
continue;
num_channels++;
}
}
if (WARN_ON(!num_channels))
if (!num_channels) {
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"pdev is not supported for this country\n");
return -EINVAL;
}
arg = kzalloc(struct_size(arg, channel, num_channels), GFP_KERNEL);
@@ -204,6 +190,13 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
if (channel->flags & IEEE80211_CHAN_DISABLED)
continue;
/* Skip Channels that are not in current radio's range */
if (bands[band]->channels[i].center_freq <
KHZ_TO_MHZ(ar->freq_range.start_freq) ||
bands[band]->channels[i].center_freq >
KHZ_TO_MHZ(ar->freq_range.end_freq))
continue;
/* TODO: Set to true/false based on some condition? */
ch->allow_ht = true;
ch->allow_vht = true;
@@ -244,6 +237,16 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
}
}
if (wait) {
spin_lock_bh(&ar->data_lock);
list_add_tail(&arg->list, &ar->regd_channel_update_queue);
spin_unlock_bh(&ar->data_lock);
queue_work(ar->ab->workqueue, &ar->regd_channel_update_work);
return 0;
}
ret = ath12k_wmi_send_scan_chan_list_cmd(ar, arg);
kfree(arg);
@@ -272,9 +275,19 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
struct ieee80211_regdomain *regd, *regd_copy = NULL;
int ret, regd_len, pdev_id;
struct ath12k_base *ab;
long time_left;
ab = ar->ab;
time_left = wait_for_completion_timeout(&ar->regd_update_completed,
ATH12K_REG_UPDATE_TIMEOUT_HZ);
if (time_left == 0) {
ath12k_warn(ab, "Timeout while waiting for regulatory update");
/* Even though timeout has occurred, still continue since at least boot
* time data would be there to process
*/
}
supported_bands = ar->pdev->cap.supported_bands;
reg_cap = &ab->hal_reg_cap[ar->pdev_idx];
@@ -764,6 +777,54 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
return new_regd;
}
void ath12k_regd_update_chan_list_work(struct work_struct *work)
{
struct ath12k *ar = container_of(work, struct ath12k,
regd_channel_update_work);
struct ath12k_wmi_scan_chan_list_arg *arg;
struct list_head local_update_list;
int left;
INIT_LIST_HEAD(&local_update_list);
spin_lock_bh(&ar->data_lock);
list_splice_tail_init(&ar->regd_channel_update_queue, &local_update_list);
spin_unlock_bh(&ar->data_lock);
while ((arg = list_first_entry_or_null(&local_update_list,
struct ath12k_wmi_scan_chan_list_arg,
list))) {
if (ar->state_11d != ATH12K_11D_IDLE) {
left = wait_for_completion_timeout(&ar->completed_11d_scan,
ATH12K_SCAN_TIMEOUT_HZ);
if (!left) {
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"failed to receive 11d scan complete: timed out\n");
ar->state_11d = ATH12K_11D_IDLE;
}
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"reg 11d scan wait left time %d\n", left);
}
if ((ar->scan.state == ATH12K_SCAN_STARTING ||
ar->scan.state == ATH12K_SCAN_RUNNING)) {
left = wait_for_completion_timeout(&ar->scan.completed,
ATH12K_SCAN_TIMEOUT_HZ);
if (!left)
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"failed to receive hw scan complete: timed out\n");
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"reg hw scan wait left time %d\n", left);
}
ath12k_wmi_send_scan_chan_list_cmd(ar, arg);
list_del(&arg->list);
kfree(arg);
}
}
void ath12k_regd_update_work(struct work_struct *work)
{
struct ath12k *ar = container_of(work, struct ath12k,

View File

@@ -13,6 +13,8 @@
struct ath12k_base;
struct ath12k;
#define ATH12K_REG_UPDATE_TIMEOUT_HZ (3 * HZ)
#define ATH12K_2GHZ_MAX_FREQUENCY 2495
#define ATH12K_5GHZ_MAX_FREQUENCY 5920
@@ -113,6 +115,7 @@ int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
struct ath12k_reg_info *reg_info,
enum wmi_vdev_type vdev_type,
enum ieee80211_ap_reg_power power_type);
void ath12k_regd_update_chan_list_work(struct work_struct *work);
enum wmi_reg_6g_ap_type
ath12k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type);
enum ath12k_reg_status ath12k_reg_validate_reg_info(struct ath12k_base *ab,

View File

@@ -6445,9 +6445,16 @@ static int freq_to_idx(struct ath12k *ar, int freq)
if (!sband)
continue;
for (ch = 0; ch < sband->n_channels; ch++, idx++)
for (ch = 0; ch < sband->n_channels; ch++, idx++) {
if (sband->channels[ch].center_freq <
KHZ_TO_MHZ(ar->freq_range.start_freq) ||
sband->channels[ch].center_freq >
KHZ_TO_MHZ(ar->freq_range.end_freq))
continue;
if (sband->channels[ch].center_freq == freq)
goto exit;
}
}
exit:
@@ -6677,7 +6684,8 @@ static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab,
static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)
{
struct ath12k_reg_info *reg_info;
u8 pdev_idx;
struct ath12k *ar = NULL;
u8 pdev_idx = 255;
int ret;
reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
@@ -6732,7 +6740,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
kfree(reg_info);
if (ret == ATH12K_REG_STATUS_VALID)
return ret;
goto out;
fallback:
/* Fallback to older reg (by sending previous country setting
@@ -6746,6 +6754,18 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
WARN_ON(1);
out:
/* In some error cases, even a valid pdev_idx might not be available */
if (pdev_idx != 255)
ar = ab->pdevs[pdev_idx].ar;
/* During the boot-time update, 'ar' might not be allocated,
* so the completion cannot be marked at that point.
* This boot-time update is handled in ath12k_mac_hw_register()
* before registering the hardware.
*/
if (ar)
complete(&ar->regd_update_completed);
return ret;
}

View File

@@ -3760,6 +3760,7 @@ struct wmi_vdev_install_key_arg {
u32 key_idx;
u32 key_flags;
u32 key_cipher;
u32 ieee80211_key_cipher;
u32 key_len;
u32 key_txmic_len;
u32 key_rxmic_len;
@@ -3948,6 +3949,7 @@ struct wmi_stop_scan_cmd {
} __packed;
struct ath12k_wmi_scan_chan_list_arg {
struct list_head list;
u32 pdev_id;
u16 nallchans;
struct ath12k_wmi_channel_arg channel[];

View File

@@ -192,7 +192,7 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
* TODO: Phy disable/diversity etc
*/
static int
ath5k_config(struct ieee80211_hw *hw, u32 changed)
ath5k_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct ath5k_hw *ah = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
@@ -686,6 +686,7 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
* ath5k_set_coverage_class - Set IEEE 802.11 coverage class
*
* @hw: struct ieee80211_hw pointer
* @radio_idx: Radio index
* @coverage_class: IEEE 802.11 coverage class number
*
* Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
@@ -693,7 +694,8 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
* reset.
*/
static void
ath5k_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
ath5k_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
s16 coverage_class)
{
struct ath5k_hw *ah = hw->priv;
@@ -704,7 +706,8 @@ ath5k_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
static int
ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
ath5k_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant,
u32 rx_ant)
{
struct ath5k_hw *ah = hw->priv;
@@ -721,7 +724,8 @@ ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
static int
ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
ath5k_get_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 *tx_ant, u32 *rx_ant)
{
struct ath5k_hw *ah = hw->priv;

View File

@@ -1376,7 +1376,8 @@ void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
GFP_KERNEL);
}
static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx,
u32 changed)
{
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
struct ath6kl_vif *vif;
@@ -1405,6 +1406,7 @@ static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
struct wireless_dev *wdev,
int radio_idx,
enum nl80211_tx_power_setting type,
int mbm)
{
@@ -1441,6 +1443,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy,
struct wireless_dev *wdev,
int radio_idx,
unsigned int link_id,
int *dbm)
{
@@ -3242,7 +3245,7 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
wait, buf, len, no_cck);
}
static int ath6kl_get_antenna(struct wiphy *wiphy,
static int ath6kl_get_antenna(struct wiphy *wiphy, int radio_idx,
u32 *tx_ant, u32 *rx_ant)
{
struct ath6kl *ar = wiphy_priv(wiphy);

View File

@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/export.h>
#include "common.h"
#define FUDGE 2

View File

@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/export.h>
#include "common.h"
static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,

View File

@@ -16,6 +16,7 @@
/* We use the hw_value as an index into our private channel structure */
#include <linux/export.h>
#include "common.h"
#define CHAN2G(_freq, _idx) { \

View File

@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/export.h>
#include <linux/relay.h>
#include <linux/random.h>
#include "ath9k.h"

View File

@@ -18,6 +18,7 @@
* Module for common driver code between ath9k and ath9k_htc
*/
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>

View File

@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/export.h>
#include "ath9k.h"
#include "hw.h"
#include "dynack.h"

View File

@@ -1172,7 +1172,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
}
static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
static int ath9k_htc_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -1737,12 +1737,14 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
}
static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw,
int radio_idx, u32 value)
{
return 0;
}
static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw,
int radio_idx,
s16 coverage_class)
{
struct ath9k_htc_priv *priv = hw->priv;
@@ -1841,8 +1843,8 @@ struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv)
}
static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
u32 *rx_ant)
static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 *tx_ant, u32 *rx_ant)
{
struct ath9k_htc_priv *priv = hw->priv;
struct base_eep_header *pBase = ath9k_htc_get_eeprom_base(priv);

View File

@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/export.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/module.h>

View File

@@ -1484,7 +1484,7 @@ static void ath9k_disable_ps(struct ath_softc *sc)
ath_dbg(common, PS, "PowerSave disabled\n");
}
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
static int ath9k_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
@@ -2114,6 +2114,7 @@ static void ath9k_enable_dynack(struct ath_softc *sc)
}
static void ath9k_set_coverage_class(struct ieee80211_hw *hw,
int radio_idx,
s16 coverage_class)
{
struct ath_softc *sc = hw->priv;
@@ -2338,7 +2339,8 @@ static bool validate_antenna_mask(struct ath_hw *ah, u32 val)
}
}
static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
static int ath9k_set_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 tx_ant, u32 rx_ant)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
@@ -2367,7 +2369,8 @@ static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
return 0;
}
static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
static int ath9k_get_antenna(struct ieee80211_hw *hw, int radio_idx,
u32 *tx_ant, u32 *rx_ant)
{
struct ath_softc *sc = hw->priv;

View File

@@ -890,7 +890,7 @@ static void carl9170_stat_work(struct work_struct *work)
round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
}
static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
static int carl9170_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct ar9170 *ar = hw->priv;
int err = 0;

View File

@@ -16,6 +16,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>

View File

@@ -361,7 +361,7 @@ static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
return;
}
static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
static int wcn36xx_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct wcn36xx *wcn = hw->priv;
int ret;
@@ -965,7 +965,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
}
/* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */
static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
u32 value)
{
struct wcn36xx *wcn = hw->priv;
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);

View File

@@ -1408,7 +1408,8 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
return rc;
}
static int wil_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
static int wil_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx,
u32 changed)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
int rc;

View File

@@ -2002,7 +2002,7 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
return 0;
}
static int at76_config(struct ieee80211_hw *hw, u32 changed)
static int at76_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct at76_priv *priv = hw->priv;

View File

@@ -3975,7 +3975,7 @@ static void b43_set_retry_limits(struct b43_wldev *dev,
long_retry);
}
static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
static int b43_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -5073,7 +5073,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
* may hang the system.
*/
if (!err)
b43_op_config(hw, ~0);
b43_op_config(hw, -1, ~0);
return err;
}
@@ -5248,7 +5248,7 @@ static void b43_chip_reset(struct work_struct *work)
}
/* reload configuration */
b43_op_config(wl->hw, ~0);
b43_op_config(wl->hw, -1, ~0);
if (wl->vif)
b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0);

View File

@@ -2662,7 +2662,7 @@ static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
}
static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
static int b43legacy_op_dev_config(struct ieee80211_hw *hw, int radio_idx,
u32 changed)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);

View File

@@ -1043,6 +1043,21 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
}
}
bool brcmf_is_apmode_operating(struct wiphy *wiphy)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_vif *vif;
bool ret = false;
list_for_each_entry(vif, &cfg->vif_list, list) {
if (brcmf_is_apmode(vif) &&
test_bit(BRCMF_VIF_STATUS_AP_CREATED, &vif->sme_state))
ret = true;
}
return ret;
}
static void brcmf_scan_params_v2_to_v1(struct brcmf_scan_params_v2_le *params_v2_le,
struct brcmf_scan_params_le *params_le)
{
@@ -1622,7 +1637,8 @@ static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
return err;
}
static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx,
u32 changed)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_to_ndev(cfg);
@@ -2630,7 +2646,8 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
static s32
brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, s32 mbm)
int radio_idx, enum nl80211_tx_power_setting type,
s32 mbm)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = cfg_to_ndev(cfg);
@@ -2681,7 +2698,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
static s32
brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
unsigned int link_id, s32 *dbm)
int radio_idx, unsigned int link_id, s32 *dbm)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);
@@ -5416,8 +5433,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev,
bphy_err(drvr, "bss_enable config failed %d\n", err);
}
brcmf_set_mpc(ifp, 1);
brcmf_configure_arp_nd_offload(ifp, true);
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
brcmf_configure_arp_nd_offload(ifp, true);
brcmf_net_setcarrier(ifp, false);
return err;

View File

@@ -487,6 +487,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp, bool aborted,
bool fw_abort);
void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
bool brcmf_is_apmode_operating(struct wiphy *wiphy);
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
void brcmf_cfg80211_free_netdev(struct net_device *ndev);

View File

@@ -98,6 +98,11 @@ void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
s32 err;
u32 mode;
if (enable && brcmf_is_apmode_operating(ifp->drvr->wiphy)) {
brcmf_dbg(TRACE, "Skip ARP/ND offload enable when soft AP is running\n");
return;
}
if (enable)
mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
else

View File

@@ -654,17 +654,19 @@ brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
{
struct brcmf_core *core;
u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
BRCMF_PCIE_CFGREG_PM_CSR,
BRCMF_PCIE_CFGREG_MSI_CAP,
BRCMF_PCIE_CFGREG_MSI_ADDR_L,
BRCMF_PCIE_CFGREG_MSI_ADDR_H,
BRCMF_PCIE_CFGREG_MSI_DATA,
BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,
BRCMF_PCIE_CFGREG_RBAR_CTRL,
BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,
BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,
BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG };
static const u16 cfg_offset[] = {
BRCMF_PCIE_CFGREG_STATUS_CMD,
BRCMF_PCIE_CFGREG_PM_CSR,
BRCMF_PCIE_CFGREG_MSI_CAP,
BRCMF_PCIE_CFGREG_MSI_ADDR_L,
BRCMF_PCIE_CFGREG_MSI_ADDR_H,
BRCMF_PCIE_CFGREG_MSI_DATA,
BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,
BRCMF_PCIE_CFGREG_RBAR_CTRL,
BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,
BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,
BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG
};
u32 i;
u32 val;
u32 lsc;

View File

@@ -525,7 +525,8 @@ brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
spin_unlock_bh(&wl->lock);
}
static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
static int brcms_ops_config(struct ieee80211_hw *hw, int radio_idx,
u32 changed)
{
struct ieee80211_conf *conf = &hw->conf;
struct brcms_info *wl = hw->priv;

View File

@@ -83,7 +83,7 @@ void libipw_networks_age(struct libipw_device *ieee,
{
struct libipw_network *network = NULL;
unsigned long flags;
unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
unsigned long age_jiffies = secs_to_jiffies(age_secs);
spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(network, &ieee->network_list, list) {

View File

@@ -1382,7 +1382,7 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
* we get a thermal update even if the uCode doesn't give us one
*/
mod_timer(&il->stats_periodic,
jiffies + msecs_to_jiffies(recalib_seconds * 1000));
jiffies + secs_to_jiffies(recalib_seconds));
if (unlikely(!test_bit(S_SCANNING, &il->status)) &&
(pkt->hdr.cmd == N_STATS)) {
@@ -1575,8 +1575,11 @@ il4965_tx_cmd_build_rate(struct il_priv *il,
|| rate_idx > RATE_COUNT_LEGACY)
rate_idx = rate_lowest_index(&il->bands[info->band], sta);
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
if (info->band == NL80211_BAND_5GHZ)
if (info->band == NL80211_BAND_5GHZ) {
rate_idx += IL_FIRST_OFDM_RATE;
if (rate_idx > IL_LAST_OFDM_RATE)
rate_idx = IL_LAST_OFDM_RATE;
}
/* Get PLCP rate for tx_cmd->rate_n_flags */
rate_plcp = il_rates[rate_idx].plcp;
/* Zero out flags for this packet */

View File

@@ -4990,7 +4990,7 @@ il_update_qos(struct il_priv *il)
* il_mac_config - mac80211 config callback
*/
int
il_mac_config(struct ieee80211_hw *hw, u32 changed)
il_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct il_priv *il = hw->priv;
const struct il_channel_info *ch_info;

View File

@@ -1956,7 +1956,7 @@ il_get_hw_mode(struct il_priv *il, enum nl80211_band band)
}
/* mac80211 handlers */
int il_mac_config(struct ieee80211_hw *hw, u32 changed);
int il_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed);
void il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, u64 changes);

View File

@@ -97,6 +97,7 @@ config IWLWIFI_OPMODE_MODULAR
default y if IWLDVM=m
default y if IWLMVM=m
default y if IWLMLD=m
default y if IWLWIFI_KUNIT_TESTS=m
comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM or IWLMLD"
depends on IWLDVM=n && IWLMVM=n && IWLMLD=n

View File

@@ -7,9 +7,11 @@ iwlwifi-objs += iwl-debug.o
iwlwifi-objs += iwl-nvm-utils.o
iwlwifi-objs += iwl-utils.o
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o
iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o
# Bus
iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o pcie/utils.o
iwlwifi-objs += pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o
iwlwifi-objs += pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o
CFLAGS_pcie/drv.o += -Wno-override-init

View File

@@ -13,7 +13,7 @@
#define IWL_BZ_UCODE_API_MAX 99
/* Lowest firmware API version supported */
#define IWL_BZ_UCODE_API_MIN 93
#define IWL_BZ_UCODE_API_MIN 94
/* Memory offsets and lengths */
#define IWL_BZ_SMEM_OFFSET 0x400000

View File

@@ -12,7 +12,7 @@
#define IWL_DR_UCODE_API_MAX 99
/* Lowest firmware API version supported */
#define IWL_DR_UCODE_API_MIN 97
#define IWL_DR_UCODE_API_MIN 98
/* Memory offsets and lengths */
#define IWL_DR_SMEM_OFFSET 0x400000

View File

@@ -13,7 +13,7 @@
#define IWL_SC_UCODE_API_MAX 99
/* Lowest firmware API version supported */
#define IWL_SC_UCODE_API_MIN 97
#define IWL_SC_UCODE_API_MIN 98
/* NVM versions */
#define IWL_SC_NVM_VERSION 0x0a1d

View File

@@ -88,7 +88,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
int iwlagn_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed);
void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -397,6 +397,8 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
* returns a (newly allocated) struct containing all the
* relevant values for driver use. The struct must be freed
* later with iwl_free_nvm_data().
*
* Return: the parsed NVM data
*/
struct iwl_nvm_data *
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2023-2024 Intel Corporation
* Copyright (C) 2005-2014, 2023-2025 Intel Corporation
*/
/*
* Please use this file (commands.h) only for uCode API definitions.
@@ -614,7 +614,7 @@ struct iwl_rxon_time_cmd {
* REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
*/
/**
* struct iwl5000_channel_switch_cmd
* struct iwl5000_channel_switch_cmd - channel switch command (5000 series)
* @band: 0- 5.2GHz, 1- 2.4GHz
* @expect_beacon: 0- resume transmits after channel switch
* 1- wait for beacon to resume transmits
@@ -635,7 +635,7 @@ struct iwl5000_channel_switch_cmd {
} __packed;
/**
* struct iwl6000_channel_switch_cmd
* struct iwl6000_channel_switch_cmd - channel switch command (6000 series)
* @band: 0- 5.2GHz, 1- 2.4GHz
* @expect_beacon: 0- resume transmits after channel switch
* 1- wait for beacon to resume transmits
@@ -791,7 +791,7 @@ struct iwl_keyinfo {
} __packed;
/**
* struct sta_id_modify
* struct sta_id_modify - station modify command
* @addr: station's MAC address
* @reserved1: reserved for alignment
* @sta_id: index of station in uCode's station table
@@ -2026,7 +2026,7 @@ struct iwl_spectrum_notification {
u8 channel;
u8 type; /* see enum iwl_measurement_type */
u8 reserved1;
/* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only
/* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only
* valid if applicable for measurement type requested. */
__le32 cca_ofdm; /* cca fraction time in 40Mhz clock periods */
__le32 cca_cck; /* cca fraction time in 44Mhz clock periods */
@@ -2992,7 +2992,7 @@ struct iwl_missed_beacon_notif {
#define SENSITIVITY_CMD_CONTROL_WORK_TABLE cpu_to_le16(1)
/**
* struct iwl_sensitivity_cmd
* struct iwl_sensitivity_cmd - sensitivity configuration command
* @control: (1) updates working table, (0) updates default table
* @table: energy threshold values, use HD_* as index into table
*
@@ -3848,7 +3848,7 @@ struct iwlagn_wowlan_status {
#define IWL_MIN_SLOT_TIME 20
/**
* struct iwl_wipan_slot
* struct iwl_wipan_slot - WiPAN slot configuration
* @width: Time in TU
* @type:
* 0 - BSS
@@ -3868,7 +3868,7 @@ struct iwl_wipan_slot {
#define IWL_WIPAN_PARAMS_FLG_FULL_SLOTTED_MODE BIT(5)
/**
* struct iwl_wipan_params_cmd
* struct iwl_wipan_params_cmd - WiPAN parameters
* @flags:
* bit0: reserved
* bit1: CP leave channel with CTS

View File

@@ -104,7 +104,7 @@ struct iwl_qos_info {
};
/**
* enum iwl_agg_state
* enum iwl_agg_state - aggregation state
*
* The state machine of the BA agreement establishment / tear down.
* These states relate to a specific RA / TID.
@@ -519,7 +519,7 @@ enum iwl_scan_type {
};
/**
* struct iwl_hw_params
* struct iwl_hw_params - HW parameters
*
* Holds the module parameters
*

View File

@@ -55,6 +55,7 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
* iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
* @priv: pointer to iwl_priv data structure
* @tsf_bits: number of bits need to shift for masking)
* Return: low 32 bits of beacon time mask
*/
static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
u16 tsf_bits)
@@ -66,6 +67,7 @@ static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
* iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
* @priv: pointer to iwl_priv data structure
* @tsf_bits: number of bits need to shift for masking)
* Return: high 32 bits of beacon time mask
*/
static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
u16 tsf_bits)

View File

@@ -586,7 +586,7 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
return false;
}
ave_rssi = ieee80211_ave_rssi(ctx->vif);
ave_rssi = ieee80211_ave_rssi(ctx->vif, -1);
if (!ave_rssi) {
/* no rssi data, no changes to reduce tx power */
IWL_DEBUG_COEX(priv, "no rssi data available\n");

View File

@@ -1049,9 +1049,11 @@ static void iwl_bg_restart(struct work_struct *data)
*
*****************************************************************************/
static void iwl_setup_deferred_work(struct iwl_priv *priv)
static int iwl_setup_deferred_work(struct iwl_priv *priv)
{
priv->workqueue = alloc_ordered_workqueue(DRV_NAME, 0);
if (!priv->workqueue)
return -ENOMEM;
INIT_WORK(&priv->restart, iwl_bg_restart);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
@@ -1068,6 +1070,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
timer_setup(&priv->statistics_periodic, iwl_bg_statistics_periodic, 0);
timer_setup(&priv->ucode_trace, iwl_bg_ucode_trace, 0);
return 0;
}
void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -1463,7 +1467,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
/********************
* 6. Setup services
********************/
iwl_setup_deferred_work(priv);
if (iwl_setup_deferred_work(priv))
goto out_uninit_drv;
iwl_setup_rx_handlers(priv);
iwl_power_initialize(priv);
@@ -1502,6 +1508,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
iwl_cancel_deferred_work(priv);
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
out_uninit_drv:
iwl_uninit_drv(priv);
out_free_eeprom_blob:
kfree(priv->eeprom_blob);

View File

@@ -23,6 +23,4 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
void iwl_power_initialize(struct iwl_priv *priv);
extern bool no_sleep_autoadjust;
#endif /* __iwl_power_setting_h__ */

View File

@@ -2899,7 +2899,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
/* Repeat initial/next rate.
* For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
* For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
while (repeat_rate > 0 && index < (LINK_QUAL_MAX_RETRY_NUM - 1)) {
if (is_legacy(tbl_type.lq_type)) {
if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
ant_toggle_cnt++;

View File

@@ -429,7 +429,7 @@ static void iwlagn_rx_statistics(struct iwl_priv *priv,
* thermal update even if the uCode doesn't give
* us one */
mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(reg_recalib_period * 1000));
secs_to_jiffies(reg_recalib_period));
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {

View File

@@ -1149,7 +1149,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
}
}
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
int iwlagn_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx;

View File

@@ -232,6 +232,8 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
* that may be %NULL, for example during TX or key setup. In
* that case, we need to use the broadcast station, so this
* inline wraps that pattern.
*
* Return: station ID for mac80211 station (or broadcast if %NULL)
*/
static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context,
struct ieee80211_sta *sta)

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -19,9 +19,11 @@ enum iwl_d0i3_flags {
/**
* enum iwl_d3_wakeup_flags - D3 manager wakeup flags
* @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert
* @IWL_WAKEUP_D3_HOST_TIMER: wake up on host timer expiry
*/
enum iwl_d3_wakeup_flags {
IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
IWL_WAKEUP_D3_HOST_TIMER = BIT(1),
}; /* D3_MANAGER_WAKEUP_CONFIG_API_E_VER_3 */
/**

View File

@@ -864,7 +864,7 @@ struct iwl_extended_beacon_notif {
/**
* enum iwl_dump_control - dump (flush) control flags
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the FIFO is empty
* and the TFD queues are empty.
*/
enum iwl_dump_control {

View File

@@ -1106,6 +1106,7 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
u32 prph_val;
u32 dphy_state;
u32 dphy_addr;
u32 prph_stts;
int i;
range->internal_base_addr = cpu_to_le32(addr);
@@ -1133,6 +1134,21 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
iwl_write_prph_no_grab(fwrt->trans, indirect_wr_addr,
WMAL_INDRCT_CMD(addr + i));
if (fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF1 &&
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF2 &&
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR1 &&
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR2) {
udelay(2);
prph_stts = iwl_read_prph_no_grab(fwrt->trans,
WMAL_MRSPF_STTS);
/* Abort dump if status is 0xA5A5A5A2 or FIFO1 empty */
if (prph_stts == WMAL_TIMEOUT_VAL ||
!WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(prph_stts))
break;
}
prph_val = iwl_read_prph_no_grab(fwrt->trans,
indirect_rd_addr);
*val++ = cpu_to_le32(prph_val);
@@ -3008,6 +3024,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dump_desc *desc;
unsigned int delay = 0;
bool monitor_only = false;
int ret;
if (trigger) {
u16 occurrences = le16_to_cpu(trigger->occurrences) - 1;
@@ -3038,7 +3055,11 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
desc->trig_desc.type = cpu_to_le32(trig);
memcpy(desc->trig_desc.data, str, len);
return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
ret = iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
if (ret)
kfree(desc);
return ret;
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
@@ -3046,7 +3067,7 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger,
const char *fmt, ...)
{
int ret, len = 0;
int len = 0;
char buf[64];
if (iwl_trans_dbg_ini_valid(fwrt->trans))
@@ -3068,13 +3089,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
len = strlen(buf) + 1;
}
ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
trigger);
if (ret)
return ret;
return 0;
return iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
trigger);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_trig);

View File

@@ -198,7 +198,7 @@ void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay)
iwl_fw_cancel_timestamp(fwrt);
fwrt->timestamp.delay = msecs_to_jiffies(delay * 1000);
fwrt->timestamp.delay = secs_to_jiffies(delay);
schedule_delayed_work(&fwrt->timestamp.wk,
round_jiffies_relative(fwrt->timestamp.delay));

View File

@@ -53,8 +53,8 @@ struct iwl_ucode_capabilities {
u32 num_stations;
u32 num_links;
u32 num_beacons;
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
DECLARE_BITMAP(_api, NUM_IWL_UCODE_TLV_API);
DECLARE_BITMAP(_capa, NUM_IWL_UCODE_TLV_CAPA);
const struct iwl_fw_cmd_version *cmd_versions;
u32 n_cmd_versions;

View File

@@ -332,7 +332,7 @@ iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
ret = iwl_trans_load_pnvm(trans, pnvm_data, capa);
if (ret)
goto free;
IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
IWL_DEBUG_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
set:
iwl_trans_set_pnvm(trans, capa);

View File

@@ -113,6 +113,7 @@
#define CSR_IPC_STATE_RESET_SW_READY 1
#define CSR_IPC_STATE_RESET_TOP_READY 2
#define CSR_IPC_STATE_RESET_TOP_FOLLOWER 3
#define CSR_IPC_STATE_TOP_RESET_REQ BIT(6)
#define CSR_IPC_SLEEP_CONTROL (CSR_BASE + 0x114)
#define CSR_IPC_SLEEP_CONTROL_SUSPEND 0x3

View File

@@ -1276,8 +1276,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(*fseq_ver))
goto invalid_tlv_len;
IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n",
fseq_ver->version);
IWL_DEBUG_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n",
fseq_ver->version);
}
break;
case IWL_UCODE_TLV_FW_NUM_STATIONS:

View File

@@ -160,23 +160,26 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
* @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
* @NVM_CHANNEL_VLP: client support connection to UHB VLP AP
* @NVM_CHANNEL_AFC: client support connection to UHB AFC AP
* @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed,
* Valid only when %NVM_CHANNEL_VLP is enabled.
*/
enum iwl_nvm_channel_flags {
NVM_CHANNEL_VALID = BIT(0),
NVM_CHANNEL_IBSS = BIT(1),
NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2),
NVM_CHANNEL_ACTIVE = BIT(3),
NVM_CHANNEL_RADAR = BIT(4),
NVM_CHANNEL_INDOOR_ONLY = BIT(5),
NVM_CHANNEL_GO_CONCURRENT = BIT(6),
NVM_CHANNEL_UNIFORM = BIT(7),
NVM_CHANNEL_20MHZ = BIT(8),
NVM_CHANNEL_40MHZ = BIT(9),
NVM_CHANNEL_80MHZ = BIT(10),
NVM_CHANNEL_160MHZ = BIT(11),
NVM_CHANNEL_DC_HIGH = BIT(12),
NVM_CHANNEL_VLP = BIT(13),
NVM_CHANNEL_AFC = BIT(14),
NVM_CHANNEL_VALID = BIT(0),
NVM_CHANNEL_IBSS = BIT(1),
NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2),
NVM_CHANNEL_ACTIVE = BIT(3),
NVM_CHANNEL_RADAR = BIT(4),
NVM_CHANNEL_INDOOR_ONLY = BIT(5),
NVM_CHANNEL_GO_CONCURRENT = BIT(6),
NVM_CHANNEL_UNIFORM = BIT(7),
NVM_CHANNEL_20MHZ = BIT(8),
NVM_CHANNEL_40MHZ = BIT(9),
NVM_CHANNEL_80MHZ = BIT(10),
NVM_CHANNEL_160MHZ = BIT(11),
NVM_CHANNEL_DC_HIGH = BIT(12),
NVM_CHANNEL_VLP = BIT(13),
NVM_CHANNEL_AFC = BIT(14),
NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15),
};
/**
@@ -1044,6 +1047,7 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
case IWL_CFG_RF_TYPE_GF:
case IWL_CFG_RF_TYPE_FM:
case IWL_CFG_RF_TYPE_WH:
case IWL_CFG_RF_TYPE_PE:
iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
if (!is_ap)
@@ -1629,8 +1633,7 @@ IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags,
struct iwl_reg_capa reg_capa,
const struct iwl_rf_cfg *cfg)
struct iwl_reg_capa reg_capa)
{
u32 flags = NL80211_RRF_NO_HT40;
@@ -1685,10 +1688,12 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
}
/* Set the AP type for the UHB case. */
if (nvm_flags & NVM_CHANNEL_VLP)
flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
else
if (nvm_flags & NVM_CHANNEL_VLP) {
if (!(nvm_flags & NVM_CHANNEL_VLP_AP_NOT_ALLOWED))
flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
} else {
flags |= NL80211_RRF_NO_6GHZ_VLP_CLIENT;
}
if (!(nvm_flags & NVM_CHANNEL_AFC))
flags |= NL80211_RRF_NO_6GHZ_AFC_CLIENT;
@@ -1815,8 +1820,8 @@ iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
}
reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
ch_flags, reg_capa,
cfg);
ch_flags,
reg_capa);
/* we can't continue the same rule */
if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags ||

View File

@@ -147,6 +147,8 @@ struct iwl_fw_error_dump_mode {
* Op_mode needs to reset its internal state because the device did not
* survive the system state transition. The firmware is no longer running,
* etc...
* @dump: Op_mode needs to collect the firmware dump upon this handler
* being called.
*/
struct iwl_op_mode_ops {
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
@@ -174,6 +176,7 @@ struct iwl_op_mode_ops {
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data);
void (*device_powered_off)(struct iwl_op_mode *op_mode);
void (*dump)(struct iwl_op_mode *op_mode);
};
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
@@ -286,4 +289,11 @@ static inline void iwl_op_mode_device_powered_off(struct iwl_op_mode *op_mode)
op_mode->ops->device_powered_off(op_mode);
}
static inline void iwl_op_mode_dump(struct iwl_op_mode *op_mode)
{
if (!op_mode || !op_mode->ops || !op_mode->ops->dump)
return;
op_mode->ops->dump(op_mode);
}
#endif /* __iwl_op_mode_h__ */

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
* Copyright (C) 2005-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -514,6 +514,14 @@ enum {
#define WMAL_INDRCT_CMD(addr) \
((WMAL_CMD_READ_BURST_ACCESS << WMAL_INDRCT_RD_CMD1_OPMOD_POS) | \
((addr) & WMAL_INDRCT_RD_CMD1_BYTE_ADDRESS_MSK))
#define WMAL_MRSPF_STTS 0xADFC24
#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS 15
#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK 0x8000
#define WMAL_TIMEOUT_VAL 0xA5A5A5A2
#define WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(val) \
(((val) >> (WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS)) & \
((WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK) >> \
(WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS)))
#define WFPM_LMAC1_PS_CTL_RW 0xA03380
#define WFPM_LMAC2_PS_CTL_RW 0xA033C0

View File

@@ -14,8 +14,8 @@
#include "iwl-fh.h"
#include <linux/dmapool.h>
#include "fw/api/commands.h"
#include "pcie/internal.h"
#include "iwl-context-info-v2.h"
#include "pcie/gen1_2/internal.h"
#include "pcie/iwl-context-info-v2.h"
struct iwl_trans_dev_restart_data {
struct list_head list;
@@ -497,7 +497,19 @@ IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
const void *buf, int dwords)
{
return iwl_trans_pcie_write_mem(trans, addr, buf, dwords);
int offs, ret = 0;
const u32 *vals = buf;
if (iwl_trans_grab_nic_access(trans)) {
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
for (offs = 0; offs < dwords; offs++)
iwl_write32(trans, HBUS_TARG_MEM_WDAT,
vals ? vals[offs] : 0);
iwl_trans_release_nic_access(trans);
} else {
ret = -EBUSY;
}
return ret;
}
IWL_EXPORT_SYMBOL(iwl_trans_write_mem);

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2024-2025 Intel Corporation
*/
#include <net/gso.h>
#include <linux/ieee80211.h>
@@ -82,3 +82,114 @@ int iwl_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
}
IWL_EXPORT_SYMBOL(iwl_tx_tso_segment);
#endif /* CONFIG_INET */
static u32 iwl_div_by_db(u32 value, u8 db)
{
/*
* 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping
* at 10 dB and looping instead of using a much larger table.
*
* Using 64 bit math is overkill, but means the helper does not require
* a limit on the input range.
*/
static const u32 db_to_val[] = {
0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89,
0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a,
};
while (value && db > 0) {
u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val));
value = (((u64)value) * db_to_val[change - 1]) >> 32;
db -= change;
}
return value;
}
s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len)
{
int average_magnitude;
u32 average_factor;
int sum_magnitude = -128;
u32 sum_factor = 0;
int i, count = 0;
/*
* To properly average the decibel values (signal values given in dBm)
* we need to do the math in linear space. Doing a linear average of
* dB (dBm) values is a bit annoying though due to the large range of
* at least -10 to -110 dBm that will not fit into a 32 bit integer.
*
* A 64 bit integer should be sufficient, but then we still have the
* problem that there are no directly usable utility functions
* available.
*
* So, lets not deal with that and instead do much of the calculation
* with a 16.16 fixed point integer along with a base in dBm. 16.16 bit
* gives us plenty of head-room for adding up a few values and even
* doing some math on it. And the tail should be accurate enough too
* (1/2^16 is somewhere around -48 dB, so effectively zero).
*
* i.e. the real value of sum is:
* sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW
*
* However, that does mean we need to be able to bring two values to
* a common base, so we need a helper for that.
*
* Note that this function takes an input with unsigned negative dBm
* values but returns a signed dBm (i.e. a negative value).
*/
for (i = 0; i < len; i++) {
int val_magnitude;
u32 val_factor;
/* Assume invalid */
if (neg_dbm_values[i] == 0xff)
continue;
val_factor = 0x10000;
val_magnitude = -neg_dbm_values[i];
if (val_magnitude <= sum_magnitude) {
u8 div_db = sum_magnitude - val_magnitude;
val_factor = iwl_div_by_db(val_factor, div_db);
val_magnitude = sum_magnitude;
} else {
u8 div_db = val_magnitude - sum_magnitude;
sum_factor = iwl_div_by_db(sum_factor, div_db);
sum_magnitude = val_magnitude;
}
sum_factor += val_factor;
count++;
}
/* No valid noise measurement, return a very high noise level */
if (count == 0)
return 0;
average_magnitude = sum_magnitude;
average_factor = sum_factor / count;
/*
* average_factor will be a number smaller than 1.0 (0x10000) at this
* point. What we need to do now is to adjust average_magnitude so that
* average_factor is between -0.5 dB and 0.5 dB.
*
* Just do -1 dB steps and find the point where
* -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB
* = div_by_db(0xe429, i)
* is smaller than average_factor.
*/
for (i = 0; average_factor < iwl_div_by_db(0xe429, i); i++) {
/* nothing */
}
return clamp(average_magnitude - i, -128, 0);
}
IWL_EXPORT_SYMBOL(iwl_average_neg_dbm);

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2024-2025 Intel Corporation
*/
#ifndef __iwl_utils_h__
#define __iwl_utils_h__
@@ -53,4 +53,6 @@ u32 iwl_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
return ie - beacon;
}
s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len);
#endif /* __iwl_utils_h__ */

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2021 - 2022 Intel Corporation
* Copyright (C) 2021 - 2022, 2025 Intel Corporation
*/
#ifndef __sap_h__
@@ -340,12 +340,12 @@ enum iwl_sap_wifi_auth_type {
};
/**
* enum iwl_sap_wifi_cipher_alg
* @SAP_WIFI_CIPHER_ALG_NONE: TBD
* @SAP_WIFI_CIPHER_ALG_TKIP: TBD
* @SAP_WIFI_CIPHER_ALG_CCMP: TBD
* @SAP_WIFI_CIPHER_ALG_GCMP: TBD
* @SAP_WIFI_CIPHER_ALG_GCMP_256: TBD
* enum iwl_sap_wifi_cipher_alg - MEI WiFi cipher algorithm IDs
* @SAP_WIFI_CIPHER_ALG_NONE: No encryption
* @SAP_WIFI_CIPHER_ALG_TKIP: TKIPO
* @SAP_WIFI_CIPHER_ALG_CCMP: CCMP
* @SAP_WIFI_CIPHER_ALG_GCMP: GCMP-128
* @SAP_WIFI_CIPHER_ALG_GCMP_256: GCMP-256
*/
enum iwl_sap_wifi_cipher_alg {
SAP_WIFI_CIPHER_ALG_NONE = IWL_MEI_CIPHER_NONE,
@@ -601,7 +601,7 @@ enum iwl_sap_flex_filter_flags {
};
/**
* struct iwl_sap_flex_filter -
* struct iwl_sap_flex_filter - filter configuration
* @src_port: Source port in network format.
* @dst_port: Destination port in network format.
* @flags: Flags and protocol, see &enum iwl_sap_flex_filter_flags.
@@ -633,7 +633,7 @@ enum iwl_sap_ipv4_filter_flags {
};
/**
* struct iwl_sap_ipv4_filter-
* struct iwl_sap_ipv4_filter - IPv4 filter configuration
* @ipv4_addr: The IP address to filer.
* @flags: See &enum iwl_sap_ipv4_filter_flags.
*/
@@ -643,7 +643,7 @@ struct iwl_sap_ipv4_filter {
} __packed;
/**
* enum iwl_sap_ipv6_filter_flags -
* enum iwl_sap_ipv6_filter_flags - IPv6 filter flags
* @SAP_IPV6_ADDR_FILTER_COPY: Pass packets to the host.
* @SAP_IPV6_ADDR_FILTER_ENABLED: If false, the filter should be ignored.
*/
@@ -653,7 +653,7 @@ enum iwl_sap_ipv6_filter_flags {
};
/**
* struct iwl_sap_ipv6_filter -
* struct iwl_sap_ipv6_filter - IPv6 filter configuration
* @addr_lo24: Lowest 24 bits of the IPv6 address.
* @flags: See &enum iwl_sap_ipv6_filter_flags.
*/
@@ -663,7 +663,7 @@ struct iwl_sap_ipv6_filter {
} __packed;
/**
* enum iwl_sap_icmpv6_filter_flags -
* enum iwl_sap_icmpv6_filter_flags - ICMPv6 filter flags
* @SAP_ICMPV6_FILTER_ENABLED: If false, the filter should be ignored.
* @SAP_ICMPV6_FILTER_COPY: Pass packets to the host.
*/
@@ -673,8 +673,8 @@ enum iwl_sap_icmpv6_filter_flags {
};
/**
* enum iwl_sap_vlan_filter_flags -
* @SAP_VLAN_FILTER_VLAN_ID_MSK: TBD
* enum iwl_sap_vlan_filter_flags - VLAN filter flags
* @SAP_VLAN_FILTER_VLAN_ID_MSK: VLAN ID
* @SAP_VLAN_FILTER_ENABLED: If false, the filter should be ignored.
*/
enum iwl_sap_vlan_filter_flags {
@@ -751,7 +751,7 @@ struct iwl_sap_pldr_data {
} __packed;
/**
* enum iwl_sap_pldr_status -
* enum iwl_sap_pldr_status - product reset status
* @SAP_PLDR_STATUS_SUCCESS: PLDR started/ended successfully
* @SAP_PLDR_STATUS_FAILURE: PLDR failed to start/end
*/

View File

@@ -9,8 +9,4 @@ iwlmld-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
iwlmld-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmld-$(CONFIG_PM_SLEEP) += d3.o
# non-upstream things
iwlmld-$(CONFIG_IWL_VENDOR_CMDS) += vendor-cmd.o
iwlmld-$(CONFIG_IWLMVM_AX_SOFTAP_TESTMODE) += ax-softap-testmode.o
subdir-ccflags-y += -I$(src)/../

Some files were not shown because too many files have changed in this diff Show More