wireless-next patches for v6.7
The third, and most likely the last, features pull request for v6.7. Fixes all over and only few small new features. Major changes: iwlwifi * more Multi-Link Operation (MLO) work ath12k * QCN9274: mesh support ath11k * firmware-2.bin container file format support -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmU6KqgRHGt2YWxvQGtl cm5lbC5vcmcACgkQbhckVSbrbZtyMwf7B/BqV0LCNzBxtrWl3WYtgQgULgWFmEJt 83/Vo8pXelZzzMMERwvZtPCwEUm/L/vOO/a/k0oSz/XQbt4PTIBGnWA7JwYZGY++ 1Kc79oMyXxG4Q4RCnKG/qQMzCnyL54RHUfFQrNaa3Bkgp7vGobU+ixH4NaqHI3M9 OFmyhCklk9AO0VTtT6vQQBM6wM3UC1adneZMVlb8xD2Wi5rkrRk4PX5msgaYrStR ketZE6IPnnX8DziqGZPlTz1SSuOSnwGTOramdeGLKIUUlZbPWHTSBZ8lh/xnvGUB 561mp3/iguFtq2NvduPBqItotBzLGvnJZbLDrBPxB/v99q+7/cziSA== =Xf7b -----END PGP SIGNATURE----- Merge tag 'wireless-next-2023-10-26' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Kalle Valo says: ==================== wireless-next patches for v6.7 The third, and most likely the last, features pull request for v6.7. Fixes all over and only few small new features. Major changes: iwlwifi - more Multi-Link Operation (MLO) work ath12k - QCN9274: mesh support ath11k - firmware-2.bin container file format support * tag 'wireless-next-2023-10-26' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (155 commits) wifi: ray_cs: Remove unnecessary (void*) conversions Revert "wifi: ath11k: call ath11k_mac_fils_discovery() without condition" wifi: ath12k: Introduce and use ath12k_sta_to_arsta() wifi: ath12k: fix htt mlo-offset event locking wifi: ath12k: fix dfs-radar and temperature event locking wifi: ath11k: fix gtk offload status event locking wifi: ath11k: fix htt pktlog locking wifi: ath11k: fix dfs radar event locking wifi: ath11k: fix temperature event locking wifi: ath12k: rename the sc naming convention to ab wifi: ath12k: rename the wmi_sc naming convention to wmi_ab wifi: ath11k: add firmware-2.bin support wifi: ath11k: qmi: refactor ath11k_qmi_m3_load() wifi: rtw89: cleanup firmware elements parsing wifi: rt2x00: rework MT7620 PA/LNA RF calibration wifi: rt2x00: rework MT7620 channel config function wifi: rt2x00: improve MT7620 register initialization MAINTAINERS: wifi: rt2x00: drop Helmut Schaa wifi: wlcore: main: replace deprecated strncpy with strscpy wifi: wlcore: boot: replace deprecated strncpy with strscpy ... ==================== Link: https://lore.kernel.org/r/20231026090411.B2426C433CB@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
edd68156bc
|
|
@ -120,7 +120,7 @@ functions/definitions
|
|||
ieee80211_rx
|
||||
ieee80211_rx_ni
|
||||
ieee80211_rx_irqsafe
|
||||
ieee80211_tx_status
|
||||
ieee80211_tx_status_skb
|
||||
ieee80211_tx_status_ni
|
||||
ieee80211_tx_status_irqsafe
|
||||
ieee80211_rts_get
|
||||
|
|
|
|||
|
|
@ -17943,7 +17943,6 @@ F: arch/mips/boot/dts/ralink/mt7621*
|
|||
|
||||
RALINK RT2X00 WIRELESS LAN DRIVER
|
||||
M: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
M: Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/ralink/rt2x00/
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ ath11k-y += core.o \
|
|||
peer.o \
|
||||
dbring.o \
|
||||
hw.o \
|
||||
pcic.o
|
||||
pcic.o \
|
||||
fw.o
|
||||
|
||||
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
|
||||
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
|
@ -1084,19 +1085,12 @@ static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
|
|||
static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ath11k_base *ab;
|
||||
const struct of_device_id *of_id;
|
||||
const struct ath11k_hif_ops *hif_ops;
|
||||
const struct ath11k_pci_ops *pci_ops;
|
||||
enum ath11k_hw_rev hw_rev;
|
||||
int ret;
|
||||
|
||||
of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev);
|
||||
if (!of_id) {
|
||||
dev_err(&pdev->dev, "failed to find matching device tree id\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw_rev = (uintptr_t)of_id->data;
|
||||
hw_rev = (uintptr_t)device_get_match_data(&pdev->dev);
|
||||
|
||||
switch (hw_rev) {
|
||||
case ATH11K_HW_IPQ8074:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "wow.h"
|
||||
#include "fw.h"
|
||||
|
||||
unsigned int ath11k_debug_mask;
|
||||
EXPORT_SYMBOL(ath11k_debug_mask);
|
||||
|
|
@ -1317,6 +1318,7 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
|
|||
{
|
||||
char *boardname = NULL, *fallback_boardname = NULL, *chip_id_boardname = NULL;
|
||||
char *filename, filepath[100];
|
||||
int bd_api;
|
||||
int ret = 0;
|
||||
|
||||
filename = ATH11K_BOARD_API2_FILE;
|
||||
|
|
@ -1332,7 +1334,7 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
ab->bd_api = 2;
|
||||
bd_api = 2;
|
||||
ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname,
|
||||
ATH11K_BD_IE_BOARD,
|
||||
ATH11K_BD_IE_BOARD_NAME,
|
||||
|
|
@ -1381,7 +1383,7 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
|
|||
if (!ret)
|
||||
goto exit;
|
||||
|
||||
ab->bd_api = 1;
|
||||
bd_api = 1;
|
||||
ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE);
|
||||
if (ret) {
|
||||
ath11k_core_create_firmware_path(ab, filename,
|
||||
|
|
@ -1405,7 +1407,7 @@ exit:
|
|||
kfree(chip_id_boardname);
|
||||
|
||||
if (!ret)
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api);
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", bd_api);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -2071,6 +2073,12 @@ int ath11k_core_pre_init(struct ath11k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_fw_pre_init(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to pre init firmware: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_pre_init);
|
||||
|
|
@ -2101,6 +2109,7 @@ void ath11k_core_deinit(struct ath11k_base *ab)
|
|||
ath11k_hif_power_down(ab);
|
||||
ath11k_mac_destroy(ab);
|
||||
ath11k_core_soc_destroy(ab);
|
||||
ath11k_fw_destroy(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_deinit);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/average.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "qmi.h"
|
||||
#include "htc.h"
|
||||
#include "wmi.h"
|
||||
|
|
@ -29,6 +31,7 @@
|
|||
#include "dbring.h"
|
||||
#include "spectral.h"
|
||||
#include "wow.h"
|
||||
#include "fw.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
|
||||
|
|
@ -906,7 +909,6 @@ struct ath11k_base {
|
|||
struct ath11k_targ_cap target_caps;
|
||||
u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE];
|
||||
bool pdevs_macaddr_valid;
|
||||
int bd_api;
|
||||
|
||||
struct ath11k_hw_params hw_params;
|
||||
|
||||
|
|
@ -982,6 +984,18 @@ struct ath11k_base {
|
|||
const struct ath11k_pci_ops *ops;
|
||||
} pci;
|
||||
|
||||
struct {
|
||||
u32 api_version;
|
||||
|
||||
const struct firmware *fw;
|
||||
const u8 *amss_data;
|
||||
size_t amss_len;
|
||||
const u8 *m3_data;
|
||||
size_t m3_len;
|
||||
|
||||
DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT);
|
||||
} fw;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
struct {
|
||||
u32 data_pos;
|
||||
|
|
@ -1223,6 +1237,11 @@ static inline struct ath11k_vif *ath11k_vif_to_arvif(struct ieee80211_vif *vif)
|
|||
return (struct ath11k_vif *)vif->drv_priv;
|
||||
}
|
||||
|
||||
static inline struct ath11k_sta *ath11k_sta_to_arsta(struct ieee80211_sta *sta)
|
||||
{
|
||||
return (struct ath11k_sta *)sta->drv_priv;
|
||||
}
|
||||
|
||||
static inline struct ath11k *ath11k_ab_to_ar(struct ath11k_base *ab,
|
||||
int mac_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1459,7 +1459,7 @@ static void ath11k_reset_peer_ps_duration(void *data,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath11k *ar = data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
arsta->ps_total_duration = 0;
|
||||
|
|
@ -1510,7 +1510,7 @@ static void ath11k_peer_ps_state_disable(void *data,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath11k *ar = data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
|
||||
|
|
@ -1591,10 +1591,10 @@ static const struct file_operations fops_ps_state_enable = {
|
|||
int ath11k_debugfs_register(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
char pdev_name[5];
|
||||
char pdev_name[10];
|
||||
char buf[100] = {0};
|
||||
|
||||
snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
|
||||
snprintf(pdev_name, sizeof(pdev_name), "%s%u", "mac", ar->pdev_idx);
|
||||
|
||||
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
|
||||
if (IS_ERR(ar->debug.debugfs_pdev))
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
struct ath11k_htt_data_stats *stats;
|
||||
static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
|
||||
|
|
@ -243,7 +243,7 @@ static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
|
||||
int len = 0, i, retval = 0;
|
||||
|
|
@ -340,7 +340,7 @@ static int
|
|||
ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ieee80211_sta *sta = inode->i_private;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
struct debug_htt_stats_req *stats_req;
|
||||
int type = ar->debug.htt_stats.type;
|
||||
|
|
@ -376,7 +376,7 @@ static int
|
|||
ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ieee80211_sta *sta = inode->i_private;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
|
@ -413,7 +413,7 @@ static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
int ret, enable;
|
||||
|
||||
|
|
@ -453,7 +453,7 @@ static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
char buf[32] = {0};
|
||||
int len;
|
||||
|
|
@ -480,7 +480,7 @@ static ssize_t ath11k_dbg_sta_write_delba(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
u32 tid, initiator, reason;
|
||||
int ret;
|
||||
|
|
@ -531,7 +531,7 @@ static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
u32 tid, status;
|
||||
int ret;
|
||||
|
|
@ -581,7 +581,7 @@ static ssize_t ath11k_dbg_sta_write_addba(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
u32 tid, buf_size;
|
||||
int ret;
|
||||
|
|
@ -632,7 +632,7 @@ static ssize_t ath11k_dbg_sta_read_aggr_mode(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
char buf[64];
|
||||
int len = 0;
|
||||
|
|
@ -652,7 +652,7 @@ static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
u32 aggr_mode;
|
||||
int ret;
|
||||
|
|
@ -697,7 +697,7 @@ ath11k_write_htt_peer_stats_reset(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
struct htt_ext_stats_cfg_params cfg_params = { 0 };
|
||||
int ret;
|
||||
|
|
@ -756,7 +756,7 @@ static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
char buf[20];
|
||||
int len;
|
||||
|
|
@ -783,7 +783,7 @@ static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
|
|||
loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
u64 time_since_station_in_power_save;
|
||||
char buf[20];
|
||||
|
|
@ -817,7 +817,7 @@ static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
char buf[20];
|
||||
u64 power_save_duration;
|
||||
|
|
|
|||
|
|
@ -1099,7 +1099,7 @@ int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
|
|||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_sta *arsta = (void *)params->sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(params->sta);
|
||||
int vdev_id = arsta->arvif->vdev_id;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1117,7 +1117,7 @@ int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
|
|||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k_sta *arsta = (void *)params->sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(params->sta);
|
||||
int vdev_id = arsta->arvif->vdev_id;
|
||||
dma_addr_t paddr;
|
||||
bool active;
|
||||
|
|
@ -1456,7 +1456,7 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
|
|||
}
|
||||
|
||||
sta = peer->sta;
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
|
||||
|
||||
|
|
@ -1618,14 +1618,20 @@ static void ath11k_htt_pktlog(struct ath11k_base *ab, struct sk_buff *skb)
|
|||
u8 pdev_id;
|
||||
|
||||
pdev_id = FIELD_GET(HTT_T2H_PPDU_STATS_INFO_PDEV_ID, data->hdr);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath11k_mac_get_ar_by_pdev_id(ab, pdev_id);
|
||||
if (!ar) {
|
||||
ath11k_warn(ab, "invalid pdev id %d on htt pktlog\n", pdev_id);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
trace_ath11k_htt_pktlog(ar, data->payload, hdr->size,
|
||||
ar->ab->pktlog_defs_checksum);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab,
|
||||
|
|
@ -5242,7 +5248,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
|||
goto next_skb;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(peer->sta);
|
||||
ath11k_dp_rx_update_peer_stats(arsta, ppdu_info);
|
||||
|
||||
if (ath11k_debugfs_is_pktlog_peer_valid(ar, peer->addr))
|
||||
|
|
|
|||
|
|
@ -467,7 +467,7 @@ void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts)
|
|||
}
|
||||
|
||||
sta = peer->sta;
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
|
||||
pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE,
|
||||
|
|
@ -627,7 +627,7 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
|
|||
ieee80211_free_txskb(ar->hw, msdu);
|
||||
return;
|
||||
}
|
||||
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(peer->sta);
|
||||
status.sta = peer->sta;
|
||||
status.skb = msdu;
|
||||
status.info = info;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static int ath11k_fw_request_firmware_api_n(struct ath11k_base *ab,
|
||||
const char *name)
|
||||
{
|
||||
size_t magic_len, len, ie_len;
|
||||
int ie_id, i, index, bit, ret;
|
||||
struct ath11k_fw_ie *hdr;
|
||||
const u8 *data;
|
||||
__le32 *timestamp;
|
||||
|
||||
ab->fw.fw = ath11k_core_firmware_request(ab, name);
|
||||
if (IS_ERR(ab->fw.fw)) {
|
||||
ret = PTR_ERR(ab->fw.fw);
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to load %s: %d\n", name, ret);
|
||||
ab->fw.fw = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = ab->fw.fw->data;
|
||||
len = ab->fw.fw->size;
|
||||
|
||||
/* magic also includes the null byte, check that as well */
|
||||
magic_len = strlen(ATH11K_FIRMWARE_MAGIC) + 1;
|
||||
|
||||
if (len < magic_len) {
|
||||
ath11k_err(ab, "firmware image too small to contain magic: %zu\n",
|
||||
len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(data, ATH11K_FIRMWARE_MAGIC, magic_len) != 0) {
|
||||
ath11k_err(ab, "Invalid firmware magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* jump over the padding */
|
||||
magic_len = ALIGN(magic_len, 4);
|
||||
|
||||
/* make sure there's space for padding */
|
||||
if (magic_len > len) {
|
||||
ath11k_err(ab, "No space for padding after magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
len -= magic_len;
|
||||
data += magic_len;
|
||||
|
||||
/* loop elements */
|
||||
while (len > sizeof(struct ath11k_fw_ie)) {
|
||||
hdr = (struct ath11k_fw_ie *)data;
|
||||
|
||||
ie_id = le32_to_cpu(hdr->id);
|
||||
ie_len = le32_to_cpu(hdr->len);
|
||||
|
||||
len -= sizeof(*hdr);
|
||||
data += sizeof(*hdr);
|
||||
|
||||
if (len < ie_len) {
|
||||
ath11k_err(ab, "Invalid length for FW IE %d (%zu < %zu)\n",
|
||||
ie_id, len, ie_len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH11K_FW_IE_TIMESTAMP:
|
||||
if (ie_len != sizeof(u32))
|
||||
break;
|
||||
|
||||
timestamp = (__le32 *)data;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "found fw timestamp %d\n",
|
||||
le32_to_cpup(timestamp));
|
||||
break;
|
||||
case ATH11K_FW_IE_FEATURES:
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT,
|
||||
"found firmware features ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
for (i = 0; i < ATH11K_FW_FEATURE_COUNT; i++) {
|
||||
index = i / 8;
|
||||
bit = i % 8;
|
||||
|
||||
if (index == ie_len)
|
||||
break;
|
||||
|
||||
if (data[index] & (1 << bit))
|
||||
__set_bit(i, ab->fw.fw_features);
|
||||
}
|
||||
|
||||
ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "features", "",
|
||||
ab->fw.fw_features,
|
||||
sizeof(ab->fw.fw_features));
|
||||
break;
|
||||
case ATH11K_FW_IE_AMSS_IMAGE:
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT,
|
||||
"found fw image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ab->fw.amss_data = data;
|
||||
ab->fw.amss_len = ie_len;
|
||||
break;
|
||||
case ATH11K_FW_IE_M3_IMAGE:
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT,
|
||||
"found m3 image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ab->fw.m3_data = data;
|
||||
ab->fw.m3_len = ie_len;
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ab, "Unknown FW IE: %u\n", ie_id);
|
||||
break;
|
||||
}
|
||||
|
||||
/* jump over the padding */
|
||||
ie_len = ALIGN(ie_len, 4);
|
||||
|
||||
/* make sure there's space for padding */
|
||||
if (ie_len > len)
|
||||
break;
|
||||
|
||||
len -= ie_len;
|
||||
data += ie_len;
|
||||
};
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
release_firmware(ab->fw.fw);
|
||||
ab->fw.fw = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_fw_pre_init(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_fw_request_firmware_api_n(ab, ATH11K_FW_API2_FILE);
|
||||
if (ret == 0) {
|
||||
ab->fw.api_version = 2;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ab->fw.api_version = 1;
|
||||
|
||||
out:
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "using fw api %d\n",
|
||||
ab->fw.api_version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath11k_fw_destroy(struct ath11k_base *ab)
|
||||
{
|
||||
release_firmware(ab->fw.fw);
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_FW_H
|
||||
#define ATH11K_FW_H
|
||||
|
||||
#define ATH11K_FW_API2_FILE "firmware-2.bin"
|
||||
#define ATH11K_FIRMWARE_MAGIC "QCOM-ATH11K-FW"
|
||||
|
||||
enum ath11k_fw_ie_type {
|
||||
ATH11K_FW_IE_TIMESTAMP = 0,
|
||||
ATH11K_FW_IE_FEATURES = 1,
|
||||
ATH11K_FW_IE_AMSS_IMAGE = 2,
|
||||
ATH11K_FW_IE_M3_IMAGE = 3,
|
||||
};
|
||||
|
||||
enum ath11k_fw_features {
|
||||
/* keep last */
|
||||
ATH11K_FW_FEATURE_COUNT,
|
||||
};
|
||||
|
||||
int ath11k_fw_pre_init(struct ath11k_base *ab);
|
||||
void ath11k_fw_destroy(struct ath11k_base *ab);
|
||||
|
||||
#endif /* ATH11K_FW_H */
|
||||
|
|
@ -9,18 +9,18 @@
|
|||
#include "core.h"
|
||||
|
||||
struct ath11k_hif_ops {
|
||||
u32 (*read32)(struct ath11k_base *sc, u32 address);
|
||||
void (*write32)(struct ath11k_base *sc, u32 address, u32 data);
|
||||
u32 (*read32)(struct ath11k_base *ab, u32 address);
|
||||
void (*write32)(struct ath11k_base *ab, u32 address, u32 data);
|
||||
int (*read)(struct ath11k_base *ab, void *buf, u32 start, u32 end);
|
||||
void (*irq_enable)(struct ath11k_base *sc);
|
||||
void (*irq_disable)(struct ath11k_base *sc);
|
||||
int (*start)(struct ath11k_base *sc);
|
||||
void (*stop)(struct ath11k_base *sc);
|
||||
int (*power_up)(struct ath11k_base *sc);
|
||||
void (*power_down)(struct ath11k_base *sc);
|
||||
void (*irq_enable)(struct ath11k_base *ab);
|
||||
void (*irq_disable)(struct ath11k_base *ab);
|
||||
int (*start)(struct ath11k_base *ab);
|
||||
void (*stop)(struct ath11k_base *ab);
|
||||
int (*power_up)(struct ath11k_base *ab);
|
||||
void (*power_down)(struct ath11k_base *ab);
|
||||
int (*suspend)(struct ath11k_base *ab);
|
||||
int (*resume)(struct ath11k_base *ab);
|
||||
int (*map_service_to_pipe)(struct ath11k_base *sc, u16 service_id,
|
||||
int (*map_service_to_pipe)(struct ath11k_base *ab, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe);
|
||||
int (*get_user_msi_vector)(struct ath11k_base *ab, char *user_name,
|
||||
int *num_vectors, u32 *user_base_data,
|
||||
|
|
@ -44,34 +44,34 @@ static inline void ath11k_hif_ce_irq_disable(struct ath11k_base *ab)
|
|||
ab->hif.ops->ce_irq_disable(ab);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_start(struct ath11k_base *sc)
|
||||
static inline int ath11k_hif_start(struct ath11k_base *ab)
|
||||
{
|
||||
return sc->hif.ops->start(sc);
|
||||
return ab->hif.ops->start(ab);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_stop(struct ath11k_base *sc)
|
||||
static inline void ath11k_hif_stop(struct ath11k_base *ab)
|
||||
{
|
||||
sc->hif.ops->stop(sc);
|
||||
ab->hif.ops->stop(ab);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_irq_enable(struct ath11k_base *sc)
|
||||
static inline void ath11k_hif_irq_enable(struct ath11k_base *ab)
|
||||
{
|
||||
sc->hif.ops->irq_enable(sc);
|
||||
ab->hif.ops->irq_enable(ab);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_irq_disable(struct ath11k_base *sc)
|
||||
static inline void ath11k_hif_irq_disable(struct ath11k_base *ab)
|
||||
{
|
||||
sc->hif.ops->irq_disable(sc);
|
||||
ab->hif.ops->irq_disable(ab);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_power_up(struct ath11k_base *sc)
|
||||
static inline int ath11k_hif_power_up(struct ath11k_base *ab)
|
||||
{
|
||||
return sc->hif.ops->power_up(sc);
|
||||
return ab->hif.ops->power_up(ab);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_power_down(struct ath11k_base *sc)
|
||||
static inline void ath11k_hif_power_down(struct ath11k_base *ab)
|
||||
{
|
||||
sc->hif.ops->power_down(sc);
|
||||
ab->hif.ops->power_down(ab);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_suspend(struct ath11k_base *ab)
|
||||
|
|
@ -90,14 +90,14 @@ static inline int ath11k_hif_resume(struct ath11k_base *ab)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 ath11k_hif_read32(struct ath11k_base *sc, u32 address)
|
||||
static inline u32 ath11k_hif_read32(struct ath11k_base *ab, u32 address)
|
||||
{
|
||||
return sc->hif.ops->read32(sc, address);
|
||||
return ab->hif.ops->read32(ab, address);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_write32(struct ath11k_base *sc, u32 address, u32 data)
|
||||
static inline void ath11k_hif_write32(struct ath11k_base *ab, u32 address, u32 data)
|
||||
{
|
||||
sc->hif.ops->write32(sc, address, data);
|
||||
ab->hif.ops->write32(ab, address, data);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_read(struct ath11k_base *ab, void *buf,
|
||||
|
|
@ -109,10 +109,10 @@ static inline int ath11k_hif_read(struct ath11k_base *ab, void *buf,
|
|||
return ab->hif.ops->read(ab, buf, start, end);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *sc, u16 service_id,
|
||||
static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe)
|
||||
{
|
||||
return sc->hif.ops->map_service_to_pipe(sc, service_id, ul_pipe, dl_pipe);
|
||||
return ab->hif.ops->map_service_to_pipe(ab, service_id, ul_pipe, dl_pipe);
|
||||
}
|
||||
|
||||
static inline int ath11k_get_user_msi_vector(struct ath11k_base *ab, char *user_name,
|
||||
|
|
|
|||
|
|
@ -156,18 +156,6 @@ struct ath11k_htc_record {
|
|||
};
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* note: the trailer offset is dynamic depending
|
||||
* on payload length. this is only a struct layout draft
|
||||
*/
|
||||
struct ath11k_htc_frame {
|
||||
struct ath11k_htc_hdr hdr;
|
||||
union {
|
||||
struct ath11k_htc_msg msg;
|
||||
u8 payload[0];
|
||||
};
|
||||
struct ath11k_htc_record trailer[0];
|
||||
} __packed __aligned(4);
|
||||
|
||||
enum ath11k_htc_svc_gid {
|
||||
ATH11K_HTC_SVC_GRP_RSVD = 0,
|
||||
ATH11K_HTC_SVC_GRP_WMI = 1,
|
||||
|
|
|
|||
|
|
@ -2832,7 +2832,7 @@ static void ath11k_peer_assoc_prepare(struct ath11k *ar,
|
|||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
memset(arg, 0, sizeof(*arg));
|
||||
|
||||
|
|
@ -4315,7 +4315,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
|
||||
|
||||
if (sta) {
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
|
|
@ -4906,7 +4906,7 @@ static int ath11k_mac_station_add(struct ath11k *ar,
|
|||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct peer_create_params peer_param;
|
||||
int ret;
|
||||
|
||||
|
|
@ -5030,7 +5030,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k_peer *peer;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -5196,7 +5196,7 @@ static void ath11k_mac_op_sta_set_4addr(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *sta, bool enabled)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
if (enabled && !arsta->use_4addr_set) {
|
||||
ieee80211_queue_work(ar->hw, &arsta->set_4addr_wk);
|
||||
|
|
@ -5210,7 +5210,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
|
|||
u32 changed)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
struct ath11k_peer *peer;
|
||||
u32 bw, smps;
|
||||
|
|
@ -6203,7 +6203,7 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
if (control->sta)
|
||||
arsta = (struct ath11k_sta *)control->sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(control->sta);
|
||||
|
||||
ret = ath11k_dp_tx(ar, arvif, arsta, skb);
|
||||
if (unlikely(ret)) {
|
||||
|
|
@ -8235,7 +8235,7 @@ static void ath11k_mac_set_bitrate_mask_iter(void *data,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath11k_vif *arvif = data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arvif->ar;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
|
@ -8639,7 +8639,7 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
s8 signal;
|
||||
bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/ioport.h>
|
||||
|
|
@ -390,16 +391,23 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
|||
if (!mhi_ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
ath11k_core_create_firmware_path(ab, ATH11K_AMSS_FILE,
|
||||
ab_pci->amss_path,
|
||||
sizeof(ab_pci->amss_path));
|
||||
|
||||
ab_pci->mhi_ctrl = mhi_ctrl;
|
||||
mhi_ctrl->cntrl_dev = ab->dev;
|
||||
mhi_ctrl->fw_image = ab_pci->amss_path;
|
||||
mhi_ctrl->regs = ab->mem;
|
||||
mhi_ctrl->reg_len = ab->mem_len;
|
||||
|
||||
if (ab->fw.amss_data && ab->fw.amss_len > 0) {
|
||||
/* use MHI firmware file from firmware-N.bin */
|
||||
mhi_ctrl->fw_data = ab->fw.amss_data;
|
||||
mhi_ctrl->fw_sz = ab->fw.amss_len;
|
||||
} else {
|
||||
/* use the old separate mhi.bin MHI firmware file */
|
||||
ath11k_core_create_firmware_path(ab, ATH11K_AMSS_FILE,
|
||||
ab_pci->amss_path,
|
||||
sizeof(ab_pci->amss_path));
|
||||
mhi_ctrl->fw_image = ab_pci->amss_path;
|
||||
}
|
||||
|
||||
ret = ath11k_mhi_get_msi(ab_pci);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to get msi for mhi\n");
|
||||
|
|
|
|||
|
|
@ -422,14 +422,14 @@ static void ath11k_pcic_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
|
|||
disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
}
|
||||
|
||||
static void __ath11k_pcic_ext_irq_disable(struct ath11k_base *sc)
|
||||
static void __ath11k_pcic_ext_irq_disable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags);
|
||||
clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
ath11k_pcic_ext_grp_disable(irq_grp);
|
||||
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
|||
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
|
||||
|
||||
if (sta) {
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) |
|
||||
FIELD_PREP(HTT_TCL_META_DATA_PEER_ID,
|
||||
peer->peer_id);
|
||||
|
|
|
|||
|
|
@ -2502,38 +2502,56 @@ out:
|
|||
static int ath11k_qmi_m3_load(struct ath11k_base *ab)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
const struct firmware *fw;
|
||||
const struct firmware *fw = NULL;
|
||||
const void *m3_data;
|
||||
char path[100];
|
||||
size_t m3_len;
|
||||
int ret;
|
||||
|
||||
fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE);
|
||||
if (IS_ERR(fw)) {
|
||||
ret = PTR_ERR(fw);
|
||||
ath11k_core_create_firmware_path(ab, ATH11K_M3_FILE,
|
||||
path, sizeof(path));
|
||||
ath11k_err(ab, "failed to load %s: %d\n", path, ret);
|
||||
return ret;
|
||||
if (m3_mem->vaddr)
|
||||
/* m3 firmware buffer is already available in the DMA buffer */
|
||||
return 0;
|
||||
|
||||
if (ab->fw.m3_data && ab->fw.m3_len > 0) {
|
||||
/* firmware-N.bin had a m3 firmware file so use that */
|
||||
m3_data = ab->fw.m3_data;
|
||||
m3_len = ab->fw.m3_len;
|
||||
} else {
|
||||
/* No m3 file in firmware-N.bin so try to request old
|
||||
* separate m3.bin.
|
||||
*/
|
||||
fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE);
|
||||
if (IS_ERR(fw)) {
|
||||
ret = PTR_ERR(fw);
|
||||
ath11k_core_create_firmware_path(ab, ATH11K_M3_FILE,
|
||||
path, sizeof(path));
|
||||
ath11k_err(ab, "failed to load %s: %d\n", path, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
m3_data = fw->data;
|
||||
m3_len = fw->size;
|
||||
}
|
||||
|
||||
if (m3_mem->vaddr || m3_mem->size)
|
||||
goto skip_m3_alloc;
|
||||
|
||||
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
|
||||
fw->size, &m3_mem->paddr,
|
||||
m3_len, &m3_mem->paddr,
|
||||
GFP_KERNEL);
|
||||
if (!m3_mem->vaddr) {
|
||||
ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
|
||||
fw->size);
|
||||
release_firmware(fw);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
skip_m3_alloc:
|
||||
memcpy(m3_mem->vaddr, fw->data, fw->size);
|
||||
m3_mem->size = fw->size;
|
||||
memcpy(m3_mem->vaddr, m3_data, m3_len);
|
||||
m3_mem->size = m3_len;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_qmi_m3_free(struct ath11k_base *ab)
|
||||
|
|
|
|||
|
|
@ -352,6 +352,16 @@ static u32 ath11k_map_fw_reg_flags(u16 reg_flags)
|
|||
return flags;
|
||||
}
|
||||
|
||||
static u32 ath11k_map_fw_phy_flags(u32 phy_flags)
|
||||
{
|
||||
u32 flags = 0;
|
||||
|
||||
if (phy_flags & ATH11K_REG_PHY_BITMAP_NO11AX)
|
||||
flags |= NL80211_RRF_NO_HE;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static bool
|
||||
ath11k_reg_can_intersect(struct ieee80211_reg_rule *rule1,
|
||||
struct ieee80211_reg_rule *rule2)
|
||||
|
|
@ -685,6 +695,7 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
|||
}
|
||||
|
||||
flags |= ath11k_map_fw_reg_flags(reg_rule->flags);
|
||||
flags |= ath11k_map_fw_phy_flags(reg_info->phybitmap);
|
||||
|
||||
ath11k_reg_update_rule(tmp_regd->reg_rules + i,
|
||||
reg_rule->start_freq,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ enum ath11k_dfs_region {
|
|||
ATH11K_DFS_REG_UNDEF,
|
||||
};
|
||||
|
||||
/* Phy bitmaps */
|
||||
#define ATH11K_REG_PHY_BITMAP_NO11AX BIT(5)
|
||||
|
||||
/* ATH11K Regulatory API's */
|
||||
void ath11k_reg_init(struct ath11k *ar);
|
||||
void ath11k_reg_free(struct ath11k_base *ab);
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ ATTRIBUTE_GROUPS(ath11k_hwmon);
|
|||
|
||||
int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state)
|
||||
{
|
||||
struct ath11k_base *sc = ar->ab;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct thermal_mitigation_params param;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -147,14 +147,14 @@ int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state)
|
|||
|
||||
ret = ath11k_wmi_send_thermal_mitigation_param_cmd(ar, ¶m);
|
||||
if (ret) {
|
||||
ath11k_warn(sc, "failed to send thermal mitigation duty cycle %u ret %d\n",
|
||||
ath11k_warn(ab, "failed to send thermal mitigation duty cycle %u ret %d\n",
|
||||
throttle_state, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_thermal_register(struct ath11k_base *sc)
|
||||
int ath11k_thermal_register(struct ath11k_base *ab)
|
||||
{
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct device *hwmon_dev;
|
||||
|
|
@ -162,8 +162,8 @@ int ath11k_thermal_register(struct ath11k_base *sc)
|
|||
struct ath11k_pdev *pdev;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < sc->num_radios; i++) {
|
||||
pdev = &sc->pdevs[i];
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
if (!ar)
|
||||
continue;
|
||||
|
|
@ -172,7 +172,7 @@ int ath11k_thermal_register(struct ath11k_base *sc)
|
|||
&ath11k_thermal_ops);
|
||||
|
||||
if (IS_ERR(cdev)) {
|
||||
ath11k_err(sc, "failed to setup thermal device result: %ld\n",
|
||||
ath11k_err(ab, "failed to setup thermal device result: %ld\n",
|
||||
PTR_ERR(cdev));
|
||||
ret = -EINVAL;
|
||||
goto err_thermal_destroy;
|
||||
|
|
@ -183,7 +183,7 @@ int ath11k_thermal_register(struct ath11k_base *sc)
|
|||
ret = sysfs_create_link(&ar->hw->wiphy->dev.kobj, &cdev->device.kobj,
|
||||
"cooling_device");
|
||||
if (ret) {
|
||||
ath11k_err(sc, "failed to create cooling device symlink\n");
|
||||
ath11k_err(ab, "failed to create cooling device symlink\n");
|
||||
goto err_thermal_destroy;
|
||||
}
|
||||
|
||||
|
|
@ -204,18 +204,18 @@ int ath11k_thermal_register(struct ath11k_base *sc)
|
|||
return 0;
|
||||
|
||||
err_thermal_destroy:
|
||||
ath11k_thermal_unregister(sc);
|
||||
ath11k_thermal_unregister(ab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath11k_thermal_unregister(struct ath11k_base *sc)
|
||||
void ath11k_thermal_unregister(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev *pdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->num_radios; i++) {
|
||||
pdev = &sc->pdevs[i];
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
if (!ar)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -26,17 +26,17 @@ struct ath11k_thermal {
|
|||
};
|
||||
|
||||
#if IS_REACHABLE(CONFIG_THERMAL)
|
||||
int ath11k_thermal_register(struct ath11k_base *sc);
|
||||
void ath11k_thermal_unregister(struct ath11k_base *sc);
|
||||
int ath11k_thermal_register(struct ath11k_base *ab);
|
||||
void ath11k_thermal_unregister(struct ath11k_base *ab);
|
||||
int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state);
|
||||
void ath11k_thermal_event_temperature(struct ath11k *ar, int temperature);
|
||||
#else
|
||||
static inline int ath11k_thermal_register(struct ath11k_base *sc)
|
||||
static inline int ath11k_thermal_register(struct ath11k_base *ab)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath11k_thermal_unregister(struct ath11k_base *sc)
|
||||
static inline void ath11k_thermal_unregister(struct ath11k_base *ab)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -292,18 +292,18 @@ err_pull:
|
|||
int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
|
||||
u32 cmd_id)
|
||||
{
|
||||
struct ath11k_wmi_base *wmi_sc = wmi->wmi_ab;
|
||||
struct ath11k_wmi_base *wmi_ab = wmi->wmi_ab;
|
||||
int ret = -EOPNOTSUPP;
|
||||
struct ath11k_base *ab = wmi_sc->ab;
|
||||
struct ath11k_base *ab = wmi_ab->ab;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (ab->hw_params.credit_flow) {
|
||||
wait_event_timeout(wmi_sc->tx_credits_wq, ({
|
||||
wait_event_timeout(wmi_ab->tx_credits_wq, ({
|
||||
ret = ath11k_wmi_cmd_send_nowait(wmi, skb, cmd_id);
|
||||
|
||||
if (ret && test_bit(ATH11K_FLAG_CRASH_FLUSH,
|
||||
&wmi_sc->ab->dev_flags))
|
||||
&wmi_ab->ab->dev_flags))
|
||||
ret = -ESHUTDOWN;
|
||||
|
||||
(ret != -EAGAIN);
|
||||
|
|
@ -313,7 +313,7 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
|
|||
ret = ath11k_wmi_cmd_send_nowait(wmi, skb, cmd_id);
|
||||
|
||||
if (ret && test_bit(ATH11K_FLAG_CRASH_FLUSH,
|
||||
&wmi_sc->ab->dev_flags))
|
||||
&wmi_ab->ab->dev_flags))
|
||||
ret = -ESHUTDOWN;
|
||||
|
||||
(ret != -ENOBUFS);
|
||||
|
|
@ -321,10 +321,10 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
ath11k_warn(wmi_sc->ab, "wmi command %d timeout\n", cmd_id);
|
||||
ath11k_warn(wmi_ab->ab, "wmi command %d timeout\n", cmd_id);
|
||||
|
||||
if (ret == -ENOBUFS)
|
||||
ath11k_warn(wmi_sc->ab, "ce desc not available for wmi command %d\n",
|
||||
ath11k_warn(wmi_ab->ab, "ce desc not available for wmi command %d\n",
|
||||
cmd_id);
|
||||
|
||||
return ret;
|
||||
|
|
@ -611,10 +611,10 @@ static int ath11k_service_ready_event(struct ath11k_base *ab, struct sk_buff *sk
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len)
|
||||
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_ab, u32 len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct ath11k_base *ab = wmi_sc->ab;
|
||||
struct ath11k_base *ab = wmi_ab->ab;
|
||||
u32 round_len = roundup(len, 4);
|
||||
|
||||
skb = ath11k_htc_alloc_skb(ab, WMI_SKB_HEADROOM + round_len);
|
||||
|
|
@ -4291,7 +4291,7 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
|
|||
|
||||
int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_wmi_base *wmi_sc = &ab->wmi_ab;
|
||||
struct ath11k_wmi_base *wmi_ab = &ab->wmi_ab;
|
||||
struct wmi_init_cmd_param init_param;
|
||||
struct target_resource_config config;
|
||||
|
||||
|
|
@ -4304,12 +4304,12 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
|||
ab->wmi_ab.svc_map))
|
||||
config.is_reg_cc_ext_event_supported = 1;
|
||||
|
||||
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
|
||||
memcpy(&wmi_ab->wlan_resource_config, &config, sizeof(config));
|
||||
|
||||
init_param.res_cfg = &wmi_sc->wlan_resource_config;
|
||||
init_param.num_mem_chunks = wmi_sc->num_mem_chunks;
|
||||
init_param.hw_mode_id = wmi_sc->preferred_hw_mode;
|
||||
init_param.mem_chunks = wmi_sc->mem_chunks;
|
||||
init_param.res_cfg = &wmi_ab->wlan_resource_config;
|
||||
init_param.num_mem_chunks = wmi_ab->num_mem_chunks;
|
||||
init_param.hw_mode_id = wmi_ab->preferred_hw_mode;
|
||||
init_param.mem_chunks = wmi_ab->mem_chunks;
|
||||
|
||||
if (ab->hw_params.single_pdev_only)
|
||||
init_param.hw_mode_id = WMI_HOST_HW_MODE_MAX;
|
||||
|
|
@ -4317,7 +4317,7 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
|||
init_param.num_band_to_mac = ab->num_radios;
|
||||
ath11k_fill_band_to_mac_param(ab, init_param.band_to_mac);
|
||||
|
||||
return ath11k_init_cmd_send(&wmi_sc->wmi[0], &init_param);
|
||||
return ath11k_init_cmd_send(&wmi_ab->wmi[0], &init_param);
|
||||
}
|
||||
|
||||
int ath11k_wmi_vdev_spectral_conf(struct ath11k *ar,
|
||||
|
|
@ -5440,10 +5440,11 @@ static int ath11k_pull_reg_chan_list_ext_update_ev(struct ath11k_base *ab,
|
|||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d",
|
||||
"cc_ext %s dfs %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d phy_bitmap 0x%x",
|
||||
reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2ghz, reg_info->max_bw_2ghz,
|
||||
reg_info->min_bw_5ghz, reg_info->max_bw_5ghz);
|
||||
reg_info->min_bw_5ghz, reg_info->max_bw_5ghz,
|
||||
reg_info->phybitmap);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"num_2ghz_reg_rules %d num_5ghz_reg_rules %d",
|
||||
|
|
@ -6452,7 +6453,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
|
||||
ARRAY_SIZE(stats_rssi->rssi_avg_beacon));
|
||||
|
|
@ -6540,7 +6541,7 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab,
|
|||
arvif->bssid,
|
||||
NULL);
|
||||
if (sta) {
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
arsta->rssi_beacon = src->beacon_snr;
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"stats vdev id %d snr %d\n",
|
||||
|
|
@ -7467,7 +7468,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
|
|
@ -8335,6 +8336,8 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
|
|||
ev->detector_id, ev->segment_id, ev->timestamp, ev->is_chirp,
|
||||
ev->freq_offset, ev->sidx);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
||||
|
||||
if (!ar) {
|
||||
|
|
@ -8352,6 +8355,8 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
|
|||
ieee80211_radar_detected(ar->hw);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
|
|
@ -8381,15 +8386,19 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
|
|||
ath11k_dbg(ab, ATH11K_DBG_WMI, "event pdev temperature ev temp %d pdev_id %d\n",
|
||||
ev->temp, ev->pdev_id);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
||||
if (!ar) {
|
||||
ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev->pdev_id);
|
||||
kfree(tb);
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath11k_thermal_event_temperature(ar, ev->temp);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
|
|
@ -8609,12 +8618,13 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
|
|||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
arvif = ath11k_mac_get_arvif_by_vdev_id(ab, ev->vdev_id);
|
||||
if (!arvif) {
|
||||
ath11k_warn(ab, "failed to get arvif for vdev_id:%d\n",
|
||||
ev->vdev_id);
|
||||
kfree(tb);
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "event gtk offload refresh_cnt %d\n",
|
||||
|
|
@ -8631,6 +8641,8 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
|
|||
|
||||
ieee80211_gtk_rekey_notify(arvif->vif, arvif->bssid,
|
||||
(void *)&replay_ctr_be, GFP_ATOMIC);
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree(tb);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,6 +360,7 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
|
|||
int ath12k_core_fetch_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
|
||||
{
|
||||
char boardname[BOARD_NAME_SIZE];
|
||||
int bd_api;
|
||||
int ret;
|
||||
|
||||
ret = ath12k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
|
||||
|
|
@ -368,12 +369,12 @@ int ath12k_core_fetch_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ab->bd_api = 2;
|
||||
bd_api = 2;
|
||||
ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname);
|
||||
if (!ret)
|
||||
goto success;
|
||||
|
||||
ab->bd_api = 1;
|
||||
bd_api = 1;
|
||||
ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_DEFAULT_BOARD_FILE);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n",
|
||||
|
|
@ -382,7 +383,7 @@ int ath12k_core_fetch_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
|
|||
}
|
||||
|
||||
success:
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "using board api %d\n", ab->bd_api);
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "using board api %d\n", bd_api);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -960,6 +961,7 @@ static void ath12k_core_reset(struct work_struct *work)
|
|||
ATH12K_RECOVER_START_TIMEOUT_HZ);
|
||||
|
||||
ath12k_hif_power_down(ab);
|
||||
ath12k_qmi_free_resource(ab);
|
||||
ath12k_hif_power_up(ab);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n");
|
||||
|
|
|
|||
|
|
@ -737,7 +737,6 @@ struct ath12k_base {
|
|||
struct ath12k_wmi_target_cap_arg target_caps;
|
||||
u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE];
|
||||
bool pdevs_macaddr_valid;
|
||||
int bd_api;
|
||||
|
||||
const struct ath12k_hw_params *hw_params;
|
||||
|
||||
|
|
@ -853,6 +852,11 @@ static inline struct ath12k_vif *ath12k_vif_to_arvif(struct ieee80211_vif *vif)
|
|||
return (struct ath12k_vif *)vif->drv_priv;
|
||||
}
|
||||
|
||||
static inline struct ath12k_sta *ath12k_sta_to_arsta(struct ieee80211_sta *sta)
|
||||
{
|
||||
return (struct ath12k_sta *)sta->drv_priv;
|
||||
}
|
||||
|
||||
static inline struct ath12k *ath12k_ab_to_ar(struct ath12k_base *ab,
|
||||
int mac_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2374,7 +2374,7 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
|
|||
return;
|
||||
}
|
||||
|
||||
arsta = (struct ath12k_sta *)peer->sta->drv_priv;
|
||||
arsta = ath12k_sta_to_arsta(peer->sta);
|
||||
rx_stats = arsta->rx_stats;
|
||||
|
||||
if (!rx_stats)
|
||||
|
|
@ -2550,7 +2550,7 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
|
|||
}
|
||||
|
||||
if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
|
||||
arsta = (struct ath12k_sta *)peer->sta->drv_priv;
|
||||
arsta = ath12k_sta_to_arsta(peer->sta);
|
||||
ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta,
|
||||
ppdu_info);
|
||||
} else if ((ppdu_info->fc_valid) &&
|
||||
|
|
|
|||
|
|
@ -1054,7 +1054,7 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
|
|||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_sta *arsta = (void *)params->sta->drv_priv;
|
||||
struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
|
||||
int vdev_id = arsta->arvif->vdev_id;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1072,7 +1072,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
|
|||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_peer *peer;
|
||||
struct ath12k_sta *arsta = (void *)params->sta->drv_priv;
|
||||
struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
|
||||
int vdev_id = arsta->arvif->vdev_id;
|
||||
bool active;
|
||||
int ret;
|
||||
|
|
@ -1410,7 +1410,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
|
|||
}
|
||||
|
||||
sta = peer->sta;
|
||||
arsta = (struct ath12k_sta *)sta->drv_priv;
|
||||
arsta = ath12k_sta_to_arsta(sta);
|
||||
|
||||
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
|
||||
|
||||
|
|
@ -1658,11 +1658,12 @@ static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,
|
|||
msg = (struct ath12k_htt_mlo_offset_msg *)skb->data;
|
||||
pdev_id = u32_get_bits(__le32_to_cpu(msg->info),
|
||||
HTT_T2H_MLO_OFFSET_INFO_PDEV_ID);
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);
|
||||
|
||||
rcu_read_lock();
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);
|
||||
if (!ar) {
|
||||
ath12k_warn(ab, "invalid pdev id %d on htt mlo offset\n", pdev_id);
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
|
@ -1678,6 +1679,8 @@ static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,
|
|||
pdev->timestamp.mlo_comp_timer = __le32_to_cpu(msg->mlo_comp_timer);
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
|
|||
}
|
||||
}
|
||||
|
||||
ieee80211_tx_status(ar->hw, msdu);
|
||||
ieee80211_tx_status_skb(ar->hw, msdu);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -498,7 +498,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
|
|||
* Might end up reporting it out-of-band from HTT stats.
|
||||
*/
|
||||
|
||||
ieee80211_tx_status(ar->hw, msdu);
|
||||
ieee80211_tx_status_skb(ar->hw, msdu);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
|
|
|||
|
|
@ -713,8 +713,6 @@ void ath12k_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
|
|||
{
|
||||
struct hal_rx_reo_queue_ext *ext_desc;
|
||||
|
||||
memset(qdesc, 0, sizeof(*qdesc));
|
||||
|
||||
ath12k_hal_reo_set_desc_hdr(&qdesc->desc_hdr, HAL_DESC_REO_OWNED,
|
||||
HAL_DESC_REO_QUEUE_DESC,
|
||||
REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0);
|
||||
|
|
|
|||
|
|
@ -10,17 +10,17 @@
|
|||
#include "core.h"
|
||||
|
||||
struct ath12k_hif_ops {
|
||||
u32 (*read32)(struct ath12k_base *sc, u32 address);
|
||||
void (*write32)(struct ath12k_base *sc, u32 address, u32 data);
|
||||
void (*irq_enable)(struct ath12k_base *sc);
|
||||
void (*irq_disable)(struct ath12k_base *sc);
|
||||
int (*start)(struct ath12k_base *sc);
|
||||
void (*stop)(struct ath12k_base *sc);
|
||||
int (*power_up)(struct ath12k_base *sc);
|
||||
void (*power_down)(struct ath12k_base *sc);
|
||||
u32 (*read32)(struct ath12k_base *ab, u32 address);
|
||||
void (*write32)(struct ath12k_base *ab, u32 address, u32 data);
|
||||
void (*irq_enable)(struct ath12k_base *ab);
|
||||
void (*irq_disable)(struct ath12k_base *ab);
|
||||
int (*start)(struct ath12k_base *ab);
|
||||
void (*stop)(struct ath12k_base *ab);
|
||||
int (*power_up)(struct ath12k_base *ab);
|
||||
void (*power_down)(struct ath12k_base *ab);
|
||||
int (*suspend)(struct ath12k_base *ab);
|
||||
int (*resume)(struct ath12k_base *ab);
|
||||
int (*map_service_to_pipe)(struct ath12k_base *sc, u16 service_id,
|
||||
int (*map_service_to_pipe)(struct ath12k_base *ab, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe);
|
||||
int (*get_user_msi_vector)(struct ath12k_base *ab, char *user_name,
|
||||
int *num_vectors, u32 *user_base_data,
|
||||
|
|
|
|||
|
|
@ -886,7 +886,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.vdev_start_delay = false,
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = false,
|
||||
|
||||
.idle_ps = false,
|
||||
|
|
@ -911,6 +912,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
|
||||
.rddm_size = 0,
|
||||
},
|
||||
{
|
||||
.name = "wcn7850 hw2.0",
|
||||
|
|
@ -972,6 +975,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.rfkill_pin = 48,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 1,
|
||||
|
||||
.rddm_size = 0x780000,
|
||||
},
|
||||
{
|
||||
.name = "qcn9274 hw2.0",
|
||||
|
|
@ -1006,7 +1011,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.vdev_start_delay = false,
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = false,
|
||||
|
||||
.idle_ps = false,
|
||||
|
|
@ -1031,6 +1037,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.rfkill_pin = 0,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 0,
|
||||
|
||||
.rddm_size = 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -190,6 +190,8 @@ struct ath12k_hw_params {
|
|||
u32 rfkill_pin;
|
||||
u32 rfkill_cfg;
|
||||
u32 rfkill_on_level;
|
||||
|
||||
u32 rddm_size;
|
||||
};
|
||||
|
||||
struct ath12k_hw_ops {
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ static void ath12k_get_arvif_iter(void *data, u8 *mac,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath12k_vif_iter *arvif_iter = data;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
|
||||
if (arvif->vdev_id == arvif_iter->vdev_id)
|
||||
arvif_iter->arvif = arvif;
|
||||
|
|
@ -1208,7 +1208,7 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
|
|||
struct ieee80211_sta *sta,
|
||||
struct ath12k_wmi_peer_assoc_arg *arg)
|
||||
{
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
u32 aid;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
|
@ -1236,7 +1236,7 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
|
|||
struct ieee80211_bss_conf *info = &vif->bss_conf;
|
||||
struct cfg80211_chan_def def;
|
||||
struct cfg80211_bss *bss;
|
||||
struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
const u8 *rsnie = NULL;
|
||||
const u8 *wpaie = NULL;
|
||||
|
||||
|
|
@ -1294,7 +1294,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
|
|||
struct ieee80211_sta *sta,
|
||||
struct ath12k_wmi_peer_assoc_arg *arg)
|
||||
{
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
|
||||
struct cfg80211_chan_def def;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
|
|
@ -1357,7 +1357,7 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
|
|||
struct ath12k_wmi_peer_assoc_arg *arg)
|
||||
{
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
const u8 *ht_mcs_mask;
|
||||
|
|
@ -1518,7 +1518,7 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
|
|||
struct ath12k_wmi_peer_assoc_arg *arg)
|
||||
{
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
const u16 *vht_mcs_mask;
|
||||
|
|
@ -1793,7 +1793,7 @@ static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
|
|||
struct ieee80211_sta *sta,
|
||||
struct ath12k_wmi_peer_assoc_arg *arg)
|
||||
{
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
|
||||
switch (arvif->vdev_type) {
|
||||
case WMI_VDEV_TYPE_AP:
|
||||
|
|
@ -1991,7 +1991,7 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
|
|||
struct ieee80211_sta *sta,
|
||||
struct ath12k_wmi_peer_assoc_arg *arg)
|
||||
{
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
const u8 *ht_mcs_mask;
|
||||
|
|
@ -2140,7 +2140,7 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
|
|||
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
|
||||
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
|
||||
const struct ieee80211_eht_mcs_nss_supp_bw *bw;
|
||||
struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
u32 *rx_mcs, *tx_mcs;
|
||||
|
||||
if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
|
||||
|
|
@ -2266,7 +2266,7 @@ static void ath12k_bss_assoc(struct ieee80211_hw *hw,
|
|||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_wmi_peer_assoc_arg peer_arg;
|
||||
struct ieee80211_sta *ap_sta;
|
||||
struct ath12k_peer *peer;
|
||||
|
|
@ -2360,7 +2360,7 @@ static void ath12k_bss_disassoc(struct ieee80211_hw *hw,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
|
@ -2407,7 +2407,7 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
|
|||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_chan_def *def)
|
||||
{
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u8 basic_rate_idx;
|
||||
int hw_rate_code;
|
||||
|
|
@ -3247,7 +3247,7 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);
|
||||
|
||||
if (sta) {
|
||||
arsta = (struct ath12k_sta *)sta->drv_priv;
|
||||
arsta = ath12k_sta_to_arsta(sta);
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
|
|
@ -3420,7 +3420,7 @@ static int ath12k_station_disassoc(struct ath12k *ar,
|
|||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
|
@ -3637,7 +3637,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
|
|||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
||||
struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
|
||||
struct ath12k_wmi_peer_create_arg peer_param;
|
||||
int ret;
|
||||
|
||||
|
|
@ -3744,7 +3744,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
||||
struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
|
||||
struct ath12k_peer *peer;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -3856,7 +3856,7 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
int ret;
|
||||
s16 txpwr;
|
||||
|
||||
|
|
@ -3892,8 +3892,8 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
|
|||
u32 changed)
|
||||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_peer *peer;
|
||||
u32 bw, smps;
|
||||
|
||||
|
|
@ -4019,7 +4019,7 @@ static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
|
|||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct wmi_wmm_params_arg *p = NULL;
|
||||
int ret;
|
||||
|
||||
|
|
@ -4554,6 +4554,48 @@ static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_mac_filter_eht_cap_mesh(struct ieee80211_eht_cap_elem_fixed
|
||||
*eht_cap_elem)
|
||||
{
|
||||
u8 m;
|
||||
|
||||
m = IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS;
|
||||
eht_cap_elem->mac_cap_info[0] &= ~m;
|
||||
|
||||
m = IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO;
|
||||
eht_cap_elem->phy_cap_info[0] &= ~m;
|
||||
|
||||
m = IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK;
|
||||
eht_cap_elem->phy_cap_info[3] &= ~m;
|
||||
|
||||
m = IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
|
||||
IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI;
|
||||
eht_cap_elem->phy_cap_info[4] &= ~m;
|
||||
|
||||
m = IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
|
||||
IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK;
|
||||
eht_cap_elem->phy_cap_info[5] &= ~m;
|
||||
|
||||
m = IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK;
|
||||
eht_cap_elem->phy_cap_info[6] &= ~m;
|
||||
|
||||
m = IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ;
|
||||
eht_cap_elem->phy_cap_info[7] &= ~m;
|
||||
}
|
||||
|
||||
static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
|
||||
struct ath12k_band_cap *band_cap,
|
||||
struct ieee80211_he_cap_elem *he_cap_elem,
|
||||
|
|
@ -4592,6 +4634,9 @@ static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
|
|||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
ath12k_mac_filter_eht_cap_mesh(eht_cap_elem);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -6123,7 +6168,7 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
|
|||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
arvif = (void *)vifs[i].vif->drv_priv;
|
||||
arvif = ath12k_vif_to_arvif(vifs[i].vif);
|
||||
|
||||
if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR)
|
||||
monitor_vif = true;
|
||||
|
|
@ -6157,7 +6202,7 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
|
|||
/* TODO: Update ar->rx_channel */
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
arvif = (void *)vifs[i].vif->drv_priv;
|
||||
arvif = ath12k_vif_to_arvif(vifs[i].vif);
|
||||
|
||||
if (WARN_ON(!arvif->is_started))
|
||||
continue;
|
||||
|
|
@ -6271,7 +6316,7 @@ static int ath12k_start_vdev_delay(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(arvif->is_started))
|
||||
|
|
@ -6307,7 +6352,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
int ret;
|
||||
struct ath12k_wmi_peer_create_arg param;
|
||||
|
||||
|
|
@ -6386,7 +6431,7 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
|
@ -6717,7 +6762,7 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath12k_vif *arvif = data;
|
||||
struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
||||
struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
|
||||
struct ath12k *ar = arvif->ar;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
|
@ -6749,7 +6794,7 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
|
|||
struct ieee80211_vif *vif,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
struct ath12k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct cfg80211_chan_def def;
|
||||
struct ath12k *ar = arvif->ar;
|
||||
enum nl80211_band band;
|
||||
|
|
@ -7006,7 +7051,7 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
||||
struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
|
||||
|
||||
sinfo->rx_duration = arsta->rx_duration;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
|
|||
mhi_ctrl->fw_image = ab_pci->amss_path;
|
||||
mhi_ctrl->regs = ab->mem;
|
||||
mhi_ctrl->reg_len = ab->mem_len;
|
||||
mhi_ctrl->rddm_size = ab->hw_params->rddm_size;
|
||||
|
||||
ret = ath12k_mhi_get_msi(ab_pci);
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -424,12 +424,12 @@ static void ath12k_pci_ext_grp_disable(struct ath12k_ext_irq_grp *irq_grp)
|
|||
disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
}
|
||||
|
||||
static void __ath12k_pci_ext_irq_disable(struct ath12k_base *sc)
|
||||
static void __ath12k_pci_ext_irq_disable(struct ath12k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath12k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
|
||||
struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
ath12k_pci_ext_grp_disable(irq_grp);
|
||||
|
||||
|
|
|
|||
|
|
@ -2540,6 +2540,7 @@ static void ath12k_qmi_m3_free(struct ath12k_base *ab)
|
|||
dma_free_coherent(ab->dev, m3_mem->size,
|
||||
m3_mem->vaddr, m3_mem->paddr);
|
||||
m3_mem->vaddr = NULL;
|
||||
m3_mem->size = 0;
|
||||
}
|
||||
|
||||
static int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
|
||||
|
|
@ -3093,3 +3094,9 @@ void ath12k_qmi_deinit_service(struct ath12k_base *ab)
|
|||
ath12k_qmi_m3_free(ab);
|
||||
ath12k_qmi_free_target_mem_chunk(ab);
|
||||
}
|
||||
|
||||
void ath12k_qmi_free_resource(struct ath12k_base *ab)
|
||||
{
|
||||
ath12k_qmi_free_target_mem_chunk(ab);
|
||||
ath12k_qmi_m3_free(ab);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -564,5 +564,6 @@ int ath12k_qmi_firmware_start(struct ath12k_base *ab,
|
|||
void ath12k_qmi_firmware_stop(struct ath12k_base *ab);
|
||||
void ath12k_qmi_deinit_service(struct ath12k_base *ab);
|
||||
int ath12k_qmi_init_service(struct ath12k_base *ab);
|
||||
void ath12k_qmi_free_resource(struct ath12k_base *ab);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -314,6 +314,19 @@ static u32 ath12k_map_fw_reg_flags(u16 reg_flags)
|
|||
return flags;
|
||||
}
|
||||
|
||||
static u32 ath12k_map_fw_phy_flags(u32 phy_flags)
|
||||
{
|
||||
u32 flags = 0;
|
||||
|
||||
if (phy_flags & ATH12K_REG_PHY_BITMAP_NO11AX)
|
||||
flags |= NL80211_RRF_NO_HE;
|
||||
|
||||
if (phy_flags & ATH12K_REG_PHY_BITMAP_NO11BE)
|
||||
flags |= NL80211_RRF_NO_EHT;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static bool
|
||||
ath12k_reg_can_intersect(struct ieee80211_reg_rule *rule1,
|
||||
struct ieee80211_reg_rule *rule2)
|
||||
|
|
@ -638,6 +651,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
|
|||
}
|
||||
|
||||
flags |= ath12k_map_fw_reg_flags(reg_rule->flags);
|
||||
flags |= ath12k_map_fw_phy_flags(reg_info->phybitmap);
|
||||
|
||||
ath12k_reg_update_rule(tmp_regd->reg_rules + i,
|
||||
reg_rule->start_freq,
|
||||
|
|
|
|||
|
|
@ -83,6 +83,12 @@ struct ath12k_reg_info {
|
|||
[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
};
|
||||
|
||||
/* Phy bitmaps */
|
||||
enum ath12k_reg_phy_bitmap {
|
||||
ATH12K_REG_PHY_BITMAP_NO11AX = BIT(5),
|
||||
ATH12K_REG_PHY_BITMAP_NO11BE = BIT(6),
|
||||
};
|
||||
|
||||
void ath12k_reg_init(struct ath12k *ar);
|
||||
void ath12k_reg_free(struct ath12k_base *ab);
|
||||
void ath12k_regd_update_work(struct work_struct *work);
|
||||
|
|
|
|||
|
|
@ -408,22 +408,22 @@ err_pull:
|
|||
int ath12k_wmi_cmd_send(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb,
|
||||
u32 cmd_id)
|
||||
{
|
||||
struct ath12k_wmi_base *wmi_sc = wmi->wmi_ab;
|
||||
struct ath12k_wmi_base *wmi_ab = wmi->wmi_ab;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
might_sleep();
|
||||
|
||||
wait_event_timeout(wmi_sc->tx_credits_wq, ({
|
||||
wait_event_timeout(wmi_ab->tx_credits_wq, ({
|
||||
ret = ath12k_wmi_cmd_send_nowait(wmi, skb, cmd_id);
|
||||
|
||||
if (ret && test_bit(ATH12K_FLAG_CRASH_FLUSH, &wmi_sc->ab->dev_flags))
|
||||
if (ret && test_bit(ATH12K_FLAG_CRASH_FLUSH, &wmi_ab->ab->dev_flags))
|
||||
ret = -ESHUTDOWN;
|
||||
|
||||
(ret != -EAGAIN);
|
||||
}), WMI_SEND_TIMEOUT_HZ);
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
ath12k_warn(wmi_sc->ab, "wmi command %d timeout\n", cmd_id);
|
||||
ath12k_warn(wmi_ab->ab, "wmi command %d timeout\n", cmd_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -727,10 +727,10 @@ static int ath12k_service_ready_event(struct ath12k_base *ab, struct sk_buff *sk
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len)
|
||||
struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_ab, u32 len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct ath12k_base *ab = wmi_sc->ab;
|
||||
struct ath12k_base *ab = wmi_ab->ab;
|
||||
u32 round_len = roundup(len, 4);
|
||||
|
||||
skb = ath12k_htc_alloc_skb(ab, WMI_SKB_HEADROOM + round_len);
|
||||
|
|
@ -3471,7 +3471,7 @@ int ath12k_wmi_set_hw_mode(struct ath12k_base *ab,
|
|||
|
||||
int ath12k_wmi_cmd_init(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_wmi_base *wmi_sc = &ab->wmi_ab;
|
||||
struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;
|
||||
struct ath12k_wmi_init_cmd_arg arg = {};
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
|
||||
|
|
@ -3480,9 +3480,9 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab)
|
|||
|
||||
ab->hw_params->wmi_init(ab, &arg.res_cfg);
|
||||
|
||||
arg.num_mem_chunks = wmi_sc->num_mem_chunks;
|
||||
arg.hw_mode_id = wmi_sc->preferred_hw_mode;
|
||||
arg.mem_chunks = wmi_sc->mem_chunks;
|
||||
arg.num_mem_chunks = wmi_ab->num_mem_chunks;
|
||||
arg.hw_mode_id = wmi_ab->preferred_hw_mode;
|
||||
arg.mem_chunks = wmi_ab->mem_chunks;
|
||||
|
||||
if (ab->hw_params->single_pdev_only)
|
||||
arg.hw_mode_id = WMI_HOST_HW_MODE_MAX;
|
||||
|
|
@ -3490,7 +3490,7 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab)
|
|||
arg.num_band_to_mac = ab->num_radios;
|
||||
ath12k_fill_band_to_mac_param(ab, arg.band_to_mac);
|
||||
|
||||
return ath12k_init_cmd_send(&wmi_sc->wmi[0], &arg);
|
||||
return ath12k_init_cmd_send(&wmi_ab->wmi[0], &arg);
|
||||
}
|
||||
|
||||
int ath12k_wmi_vdev_spectral_conf(struct ath12k *ar,
|
||||
|
|
@ -4611,10 +4611,11 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
|
|||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI,
|
||||
"%s:cc_ext %s dsf %d BW: min_2g %d max_2g %d min_5g %d max_5g %d",
|
||||
"%s:cc_ext %s dfs %d BW: min_2g %d max_2g %d min_5g %d max_5g %d phy_bitmap 0x%x",
|
||||
__func__, reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2g, reg_info->max_bw_2g,
|
||||
reg_info->min_bw_5g, reg_info->max_bw_5g);
|
||||
reg_info->min_bw_5g, reg_info->max_bw_5g,
|
||||
reg_info->phybitmap);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI,
|
||||
"num_2g_reg_rules %d num_5g_reg_rules %d",
|
||||
|
|
@ -6514,6 +6515,8 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
|
|||
ev->detector_id, ev->segment_id, ev->timestamp, ev->is_chirp,
|
||||
ev->freq_offset, ev->sidx);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(ev->pdev_id));
|
||||
|
||||
if (!ar) {
|
||||
|
|
@ -6531,6 +6534,8 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
|
|||
ieee80211_radar_detected(ar->hw);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
|
|
@ -6549,11 +6554,16 @@ ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,
|
|||
ath12k_dbg(ab, ATH12K_DBG_WMI,
|
||||
"pdev temperature ev temp %d pdev_id %d\n", ev.temp, ev.pdev_id);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(ev.pdev_id));
|
||||
if (!ar) {
|
||||
ath12k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id);
|
||||
return;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ath12k_fils_discovery_event(struct ath12k_base *ab,
|
||||
|
|
|
|||
|
|
@ -1770,7 +1770,7 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
|
|||
ah->stats.antenna_tx[0]++; /* invalid */
|
||||
|
||||
trace_ath5k_tx_complete(ah, skb, txq, ts);
|
||||
ieee80211_tx_status(ah->hw, skb);
|
||||
ieee80211_tx_status_skb(ah->hw, skb);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -131,8 +131,7 @@ ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led,
|
|||
int err;
|
||||
|
||||
led->ah = ah;
|
||||
strncpy(led->name, name, sizeof(led->name));
|
||||
led->name[sizeof(led->name)-1] = 0;
|
||||
strscpy(led->name, name, sizeof(led->name));
|
||||
led->led_dev.name = led->name;
|
||||
led->led_dev.default_trigger = trigger;
|
||||
led->led_dev.brightness_set = ath5k_led_brightness_set;
|
||||
|
|
|
|||
|
|
@ -1677,7 +1677,7 @@ static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len)
|
|||
|
||||
/* add "..." to the end of string */
|
||||
trunc_len = strlen(trunc) + 1;
|
||||
strncpy(buf + buf_len - trunc_len, trunc, trunc_len);
|
||||
memcpy(buf + buf_len - trunc_len, trunc, trunc_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ struct hif_device_usb {
|
|||
struct usb_anchor reg_in_submitted;
|
||||
struct usb_anchor mgmt_submitted;
|
||||
struct sk_buff *remain_skb;
|
||||
char fw_name[32];
|
||||
char fw_name[64];
|
||||
int fw_minor_index;
|
||||
int rx_remain_len;
|
||||
int rx_pkt_len;
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ send_mac80211:
|
|||
}
|
||||
|
||||
/* Send status to mac80211 */
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
ieee80211_tx_status_skb(priv->hw, skb);
|
||||
}
|
||||
|
||||
static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ static void ath_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
|
||||
if (info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_STATUS_EOSP)) {
|
||||
ieee80211_tx_status(hw, skb);
|
||||
ieee80211_tx_status_skb(hw, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1531,9 +1531,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
|||
ring->nr_failed_tx_packets++;
|
||||
ring->nr_total_packet_tries += status->frame_count;
|
||||
#endif /* DEBUG */
|
||||
ieee80211_tx_status(dev->wl->hw, meta->skb);
|
||||
ieee80211_tx_status_skb(dev->wl->hw, meta->skb);
|
||||
|
||||
/* skb will be freed by ieee80211_tx_status().
|
||||
/* skb will be freed by ieee80211_tx_status_skb().
|
||||
* Poison our pointer. */
|
||||
meta->skb = B43_DMA_PTR_POISON;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
|
|||
q->buffer_used -= total_len;
|
||||
q->free_packet_slots += 1;
|
||||
|
||||
ieee80211_tx_status(dev->wl->hw, pack->skb);
|
||||
ieee80211_tx_status_skb(dev->wl->hw, pack->skb);
|
||||
pack->skb = NULL;
|
||||
list_add(&pack->list, &q->packets_list);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#define BRCMF_FW_MAX_NVRAM_SIZE 64000
|
||||
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 20 /* pcie/1/4/ + \0 */
|
||||
#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff"
|
||||
#define BRCMF_FW_MACADDR_FMT "macaddr=%pM"
|
||||
#define BRCMF_FW_MACADDR_LEN (7 + ETH_ALEN * 3)
|
||||
|
|
@ -238,9 +238,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
|||
u16 bus_nr)
|
||||
{
|
||||
/* Device path with a leading '=' key-value separator */
|
||||
char pci_path[] = "=pci/?/?";
|
||||
char pci_path[20];
|
||||
size_t pci_len;
|
||||
char pcie_path[] = "=pcie/?/?";
|
||||
char pcie_path[20];
|
||||
size_t pcie_len;
|
||||
|
||||
u32 i, j;
|
||||
|
|
|
|||
|
|
@ -317,8 +317,6 @@ static int ipw2100_get_firmware(struct ipw2100_priv *priv,
|
|||
struct ipw2100_fw *fw);
|
||||
static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
|
||||
size_t max);
|
||||
static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
|
||||
size_t max);
|
||||
static void ipw2100_release_firmware(struct ipw2100_priv *priv,
|
||||
struct ipw2100_fw *fw);
|
||||
static int ipw2100_ucode_download(struct ipw2100_priv *priv,
|
||||
|
|
@ -5894,17 +5892,14 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
|||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
char fw_ver[64], ucode_ver[64];
|
||||
char fw_ver[64];
|
||||
|
||||
strscpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
strscpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
|
||||
ipw2100_get_fwversion(priv, fw_ver, sizeof(fw_ver));
|
||||
ipw2100_get_ucodeversion(priv, ucode_ver, sizeof(ucode_ver));
|
||||
|
||||
snprintf(info->fw_version, sizeof(info->fw_version), "%s:%d:%s",
|
||||
fw_ver, priv->eeprom_version, ucode_ver);
|
||||
|
||||
strscpy(info->fw_version, fw_ver, sizeof(info->fw_version));
|
||||
strscpy(info->bus_info, pci_name(priv->pci_dev),
|
||||
sizeof(info->bus_info));
|
||||
}
|
||||
|
|
@ -8406,17 +8401,6 @@ static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
|
||||
size_t max)
|
||||
{
|
||||
u32 ver;
|
||||
u32 len = sizeof(ver);
|
||||
/* microcode version is a 32 bit integer */
|
||||
if (ipw2100_get_ordinal(priv, IPW_ORD_UCODE_VERSION, &ver, &len))
|
||||
return -EIO;
|
||||
return snprintf(buf, max, "%08X", ver);
|
||||
}
|
||||
|
||||
/*
|
||||
* On exit, the firmware will have been freed from the fw list
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -9656,31 +9656,30 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
|
|||
mutex_lock(&priv->mutex);
|
||||
switch (priv->ieee->mode) {
|
||||
case IEEE_A:
|
||||
strncpy(extra, "802.11a (1)", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "802.11a (1)", MAX_WX_STRING);
|
||||
break;
|
||||
case IEEE_B:
|
||||
strncpy(extra, "802.11b (2)", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "802.11b (2)", MAX_WX_STRING);
|
||||
break;
|
||||
case IEEE_A | IEEE_B:
|
||||
strncpy(extra, "802.11ab (3)", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "802.11ab (3)", MAX_WX_STRING);
|
||||
break;
|
||||
case IEEE_G:
|
||||
strncpy(extra, "802.11g (4)", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "802.11g (4)", MAX_WX_STRING);
|
||||
break;
|
||||
case IEEE_A | IEEE_G:
|
||||
strncpy(extra, "802.11ag (5)", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "802.11ag (5)", MAX_WX_STRING);
|
||||
break;
|
||||
case IEEE_B | IEEE_G:
|
||||
strncpy(extra, "802.11bg (6)", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "802.11bg (6)", MAX_WX_STRING);
|
||||
break;
|
||||
case IEEE_A | IEEE_B | IEEE_G:
|
||||
strncpy(extra, "802.11abg (7)", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "802.11abg (7)", MAX_WX_STRING);
|
||||
break;
|
||||
default:
|
||||
strncpy(extra, "unknown", MAX_WX_STRING);
|
||||
strscpy_pad(extra, "unknown", MAX_WX_STRING);
|
||||
break;
|
||||
}
|
||||
extra[MAX_WX_STRING - 1] = '\0';
|
||||
|
||||
IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
|
||||
|
||||
|
|
@ -10378,7 +10377,6 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
|||
{
|
||||
struct ipw_priv *p = libipw_priv(dev);
|
||||
char vers[64];
|
||||
char date[32];
|
||||
u32 len;
|
||||
|
||||
strscpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
|
|
@ -10386,11 +10384,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
|||
|
||||
len = sizeof(vers);
|
||||
ipw_get_ordinal(p, IPW_ORD_STAT_FW_VERSION, vers, &len);
|
||||
len = sizeof(date);
|
||||
ipw_get_ordinal(p, IPW_ORD_STAT_FW_DATE, date, &len);
|
||||
|
||||
snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)",
|
||||
vers, date);
|
||||
strscpy(info->fw_version, vers, sizeof(info->fw_version));
|
||||
strscpy(info->bus_info, pci_name(p->pci_dev),
|
||||
sizeof(info->bus_info));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_AX210_UCODE_API_MAX 83
|
||||
#define IWL_AX210_UCODE_API_MAX 86
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_AX210_UCODE_API_MIN 59
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MAX 83
|
||||
#define IWL_BZ_UCODE_API_MAX 86
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_BZ_UCODE_API_MIN 80
|
||||
|
|
@ -158,7 +158,7 @@ const struct iwl_cfg iwl_cfg_bz = {
|
|||
.fw_name_mac = "bz",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
|
||||
};
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ const struct iwl_cfg iwl_cfg_gl = {
|
|||
.fw_name_mac = "gl",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MAX 83
|
||||
#define IWL_SC_UCODE_API_MAX 86
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_SC_UCODE_API_MIN 82
|
||||
|
|
@ -151,7 +151,7 @@ const struct iwl_cfg iwl_cfg_sc = {
|
|||
.fw_name_mac = "sc",
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_SC,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_SC_EHT,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1464,7 +1464,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
|
||||
snprintf(priv->hw->wiphy->fw_version,
|
||||
sizeof(priv->hw->wiphy->fw_version),
|
||||
"%s", fw->fw_version);
|
||||
"%.31s", fw->fw_version);
|
||||
|
||||
priv->new_scan_threshold_behaviour =
|
||||
!!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -1169,7 +1170,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb)
|
|||
iwlagn_check_ratid_empty(priv, sta_id, tid);
|
||||
}
|
||||
|
||||
iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs);
|
||||
iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs, false);
|
||||
|
||||
freed = 0;
|
||||
|
||||
|
|
@ -1247,7 +1248,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb)
|
|||
|
||||
while (!skb_queue_empty(&skbs)) {
|
||||
skb = __skb_dequeue(&skbs);
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
ieee80211_tx_status_skb(priv->hw, skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1315,7 +1316,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
* block-ack window (we assume that they've been successfully
|
||||
* transmitted ... if not, it's too late anyway). */
|
||||
iwl_trans_reclaim(priv->trans, scd_flow, ba_resp_scd_ssn,
|
||||
&reclaimed_skbs);
|
||||
&reclaimed_skbs, false);
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
|
||||
"sta_id = %d\n",
|
||||
|
|
@ -1384,6 +1385,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
|
||||
while (!skb_queue_empty(&reclaimed_skbs)) {
|
||||
skb = __skb_dequeue(&reclaimed_skbs);
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
ieee80211_tx_status_skb(priv->hw, skb);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1015,15 +1015,25 @@ __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
|
|||
__le32 config_bitmap = 0;
|
||||
|
||||
/*
|
||||
** Evaluate func 'DSM_FUNC_ENABLE_INDONESIA_5G2'
|
||||
* Evaluate func 'DSM_FUNC_ENABLE_INDONESIA_5G2'.
|
||||
* Setting config_bitmap Indonesia bit is valid only for HR/JF.
|
||||
*/
|
||||
ret = iwl_acpi_get_dsm_u8(fwrt->dev, 0,
|
||||
DSM_FUNC_ENABLE_INDONESIA_5G2,
|
||||
&iwl_guid, &value);
|
||||
switch (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_HR1:
|
||||
case IWL_CFG_RF_TYPE_HR2:
|
||||
case IWL_CFG_RF_TYPE_JF1:
|
||||
case IWL_CFG_RF_TYPE_JF2:
|
||||
ret = iwl_acpi_get_dsm_u8(fwrt->dev, 0,
|
||||
DSM_FUNC_ENABLE_INDONESIA_5G2,
|
||||
&iwl_guid, &value);
|
||||
|
||||
if (!ret && value == DSM_VALUE_INDONESIA_ENABLE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
|
||||
if (!ret && value == DSM_VALUE_INDONESIA_ENABLE)
|
||||
config_bitmap |=
|
||||
cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** Evaluate func 'DSM_FUNC_DISABLE_SRD'
|
||||
|
|
|
|||
|
|
@ -138,7 +138,8 @@ enum iwl_dsm_funcs_rev_0 {
|
|||
DSM_FUNC_11AX_ENABLEMENT = 6,
|
||||
DSM_FUNC_ENABLE_UNII4_CHAN = 7,
|
||||
DSM_FUNC_ACTIVATE_CHANNEL = 8,
|
||||
DSM_FUNC_FORCE_DISABLE_CHANNELS = 9
|
||||
DSM_FUNC_FORCE_DISABLE_CHANNELS = 9,
|
||||
DSM_FUNC_ENERGY_DETECTION_THRESHOLD = 10,
|
||||
};
|
||||
|
||||
enum iwl_dsm_values_srd {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
* @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from
|
||||
* &enum iwl_regulatory_and_nvm_subcmd_ids
|
||||
* @DEBUG_GROUP: Debug group, uses command IDs from &enum iwl_debug_cmds
|
||||
* @STATISTICS_GROUP: Statistics group, uses command IDs from
|
||||
* &enum iwl_statistics_subcmd_ids
|
||||
*/
|
||||
enum iwl_mvm_command_groups {
|
||||
LEGACY_GROUP = 0x0,
|
||||
|
|
@ -44,6 +46,7 @@ enum iwl_mvm_command_groups {
|
|||
PROT_OFFLOAD_GROUP = 0xb,
|
||||
REGULATORY_AND_NVM_GROUP = 0xc,
|
||||
DEBUG_GROUP = 0xf,
|
||||
STATISTICS_GROUP = 0x10,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -616,10 +619,37 @@ enum iwl_system_subcmd_ids {
|
|||
*/
|
||||
SYSTEM_FEATURES_CONTROL_CMD = 0xd,
|
||||
|
||||
/**
|
||||
* @SYSTEM_STATISTICS_CMD: &struct iwl_system_statistics_cmd
|
||||
*/
|
||||
SYSTEM_STATISTICS_CMD = 0xf,
|
||||
|
||||
/**
|
||||
* @SYSTEM_STATISTICS_END_NOTIF: &struct iwl_system_statistics_end_notif
|
||||
*/
|
||||
SYSTEM_STATISTICS_END_NOTIF = 0xfd,
|
||||
|
||||
/**
|
||||
* @RFI_DEACTIVATE_NOTIF: &struct iwl_rfi_deactivate_notif
|
||||
*/
|
||||
RFI_DEACTIVATE_NOTIF = 0xff,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_statistics_subcmd_ids - Statistics group command IDs
|
||||
*/
|
||||
enum iwl_statistics_subcmd_ids {
|
||||
/**
|
||||
* @STATISTICS_OPER_NOTIF: Notification about operational
|
||||
* statistics &struct iwl_system_statistics_notif_oper
|
||||
*/
|
||||
STATISTICS_OPER_NOTIF = 0x0,
|
||||
|
||||
/**
|
||||
* @STATISTICS_OPER_PART1_NOTIF: Notification about operational part1
|
||||
* statistics &struct iwl_system_statistics_part1_notif_oper
|
||||
*/
|
||||
STATISTICS_OPER_PART1_NOTIF = 0x1,
|
||||
};
|
||||
|
||||
#endif /* __iwl_fw_api_commands_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_fw_dbg_tlv_h__
|
||||
#define __iwl_fw_dbg_tlv_h__
|
||||
|
|
@ -42,6 +42,30 @@ struct iwl_fw_ini_header {
|
|||
/* followed by the data */
|
||||
} __packed; /* FW_TLV_DEBUG_HEADER_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_addr_size - Base address and size that defines
|
||||
* a chunk of memory
|
||||
*
|
||||
* @addr: the base address (fixed size - 4 bytes)
|
||||
* @size: the size to read
|
||||
*/
|
||||
struct iwl_fw_ini_addr_size {
|
||||
__le32 addr;
|
||||
__le32 size;
|
||||
} __packed; /* FW_TLV_DEBUG_ADDR_SIZE_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_dev_addr_range - Configuration to read
|
||||
* device address range
|
||||
*
|
||||
* @offset: offset to add to the base address of each chunk
|
||||
* The addrs[] array will be treated as an array of &iwl_fw_ini_addr_size -
|
||||
* an array of (addr, size) pairs.
|
||||
*/
|
||||
struct iwl_fw_ini_region_dev_addr_range {
|
||||
__le32 offset;
|
||||
} __packed; /* FW_TLV_DEBUG_DEVICE_ADDR_RANGE_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_dev_addr - Configuration to read device addresses
|
||||
*
|
||||
|
|
@ -135,6 +159,10 @@ struct iwl_fw_ini_region_internal_buffer {
|
|||
* &IWL_FW_INI_REGION_PAGING, &IWL_FW_INI_REGION_CSR,
|
||||
* &IWL_FW_INI_REGION_DRAM_IMR and &IWL_FW_INI_REGION_PCI_IOSF_CONFIG
|
||||
* &IWL_FW_INI_REGION_DBGI_SRAM, &FW_TLV_DEBUG_REGION_TYPE_DBGI_SRAM,
|
||||
* &IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP,
|
||||
* @dev_addr_range: device address range configuration. Used by
|
||||
* &IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE and
|
||||
* &IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE
|
||||
* @fifos: fifos configuration. Used by &IWL_FW_INI_REGION_TXF and
|
||||
* &IWL_FW_INI_REGION_RXF
|
||||
* @err_table: error table configuration. Used by
|
||||
|
|
@ -157,6 +185,7 @@ struct iwl_fw_ini_region_tlv {
|
|||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
union {
|
||||
struct iwl_fw_ini_region_dev_addr dev_addr;
|
||||
struct iwl_fw_ini_region_dev_addr_range dev_addr_range;
|
||||
struct iwl_fw_ini_region_fifos fifos;
|
||||
struct iwl_fw_ini_region_err_table err_table;
|
||||
struct iwl_fw_ini_region_internal_buffer internal_buffer;
|
||||
|
|
@ -362,6 +391,9 @@ enum iwl_fw_ini_buffer_location {
|
|||
* @IWL_FW_INI_REGION_PCI_IOSF_CONFIG: PCI/IOSF config
|
||||
* @IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY: special device memory
|
||||
* @IWL_FW_INI_REGION_DBGI_SRAM: periphery registers of DBGI SRAM
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE: a range of periphery registers of MAC
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE: a range of periphery registers of PHY
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP: periphery registers of SNPS DPHYIP
|
||||
* @IWL_FW_INI_REGION_NUM: number of region types
|
||||
*/
|
||||
enum iwl_fw_ini_region_type {
|
||||
|
|
@ -384,6 +416,9 @@ enum iwl_fw_ini_region_type {
|
|||
IWL_FW_INI_REGION_PCI_IOSF_CONFIG,
|
||||
IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY,
|
||||
IWL_FW_INI_REGION_DBGI_SRAM,
|
||||
IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE,
|
||||
IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE,
|
||||
IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP,
|
||||
IWL_FW_INI_REGION_NUM
|
||||
}; /* FW_TLV_DEBUG_REGION_TYPE_API_E */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -57,6 +57,14 @@ enum iwl_mac_conf_subcmd_ids {
|
|||
* @STA_DISABLE_TX_CMD: &struct iwl_mvm_sta_disable_tx_cmd
|
||||
*/
|
||||
STA_DISABLE_TX_CMD = 0xD,
|
||||
/**
|
||||
* @ROC_CMD: &struct iwl_roc_req
|
||||
*/
|
||||
ROC_CMD = 0xE,
|
||||
/**
|
||||
* @ROC_NOTIF: &struct iwl_roc_notif
|
||||
*/
|
||||
ROC_NOTIF = 0xF8,
|
||||
/**
|
||||
* @SESSION_PROTECTION_NOTIF: &struct iwl_mvm_session_prot_notif
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
|
|||
* &struct iwl_lari_config_change_cmd_v2,
|
||||
* &struct iwl_lari_config_change_cmd_v3,
|
||||
* &struct iwl_lari_config_change_cmd_v4,
|
||||
* &struct iwl_lari_config_change_cmd_v5 or
|
||||
* &struct iwl_lari_config_change_cmd_v6
|
||||
* &struct iwl_lari_config_change_cmd_v5,
|
||||
* &struct iwl_lari_config_change_cmd_v6 or
|
||||
* &struct iwl_lari_config_change_cmd_v7
|
||||
*/
|
||||
LARI_CONFIG_CHANGE = 0x1,
|
||||
|
||||
|
|
@ -43,6 +44,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
|
|||
*/
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD = 0x4,
|
||||
|
||||
/**
|
||||
* @UATS_TABLE_CMD: &struct iwl_uats_table_cmd
|
||||
*/
|
||||
UATS_TABLE_CMD = 0x5,
|
||||
|
||||
/**
|
||||
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
|
||||
*/
|
||||
|
|
@ -602,6 +608,45 @@ struct iwl_lari_config_change_cmd_v6 {
|
|||
__le32 force_disable_channels_bitmap;
|
||||
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_lari_config_change_cmd_v7 - change LARI configuration
|
||||
* This structure is used also for lari cmd version 8.
|
||||
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
|
||||
* different predefined FW config operation.
|
||||
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
|
||||
* @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate the value to use.
|
||||
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
|
||||
* per country, one to indicate whether to override and the other to
|
||||
* indicate allow/disallow unii4 channels.
|
||||
* @chan_state_active_bitmap: Bitmap to enable different bands per country
|
||||
* or region.
|
||||
* Each bit represents a country or region, and a band to activate
|
||||
* according to the BIOS definitions.
|
||||
* For LARI cmd version 7 - bits 0:3 are supported.
|
||||
* For LARI cmd version 8 - bits 0:4 are supported.
|
||||
* @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
|
||||
* Each bit represents a set of channels in a specific band that should be
|
||||
* disabled
|
||||
* @edt_bitmap: Bitmap of energy detection threshold table.
|
||||
* Disable/enable the EDT optimization method for different band.
|
||||
*/
|
||||
struct iwl_lari_config_change_cmd_v7 {
|
||||
__le32 config_bitmap;
|
||||
__le32 oem_uhb_allow_bitmap;
|
||||
__le32 oem_11ax_allow_bitmap;
|
||||
__le32 oem_unii4_allow_bitmap;
|
||||
__le32 chan_state_active_bitmap;
|
||||
__le32 force_disable_channels_bitmap;
|
||||
__le32 edt_bitmap;
|
||||
} __packed;
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_7 */
|
||||
/* LARI_CHANGE_CONF_CMD_S_VER_8 */
|
||||
|
||||
/* Activate UNII-1 (5.2GHz) for World Wide */
|
||||
#define ACTIVATE_5G2_IN_WW_MASK BIT(4)
|
||||
|
||||
/**
|
||||
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
|
||||
* @status: PNVM image loading status
|
||||
|
|
@ -610,4 +655,17 @@ struct iwl_pnvm_init_complete_ntfy {
|
|||
__le32 status;
|
||||
} __packed; /* PNVM_INIT_COMPLETE_NTFY_S_VER_1 */
|
||||
|
||||
#define UATS_TABLE_ROW_SIZE 26
|
||||
#define UATS_TABLE_COL_SIZE 13
|
||||
|
||||
/**
|
||||
* struct iwl_uats_table_cmd - struct for UATS_TABLE_CMD
|
||||
* @offset_map: mapping a mcc to UHB AP type support (UATS) allowed
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_uats_table_cmd {
|
||||
u8 offset_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE];
|
||||
__le16 reserved;
|
||||
} __packed; /* UATS_TABLE_CMD_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_nvm_reg_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -25,8 +25,8 @@
|
|||
* For legacy set bit means upper channel, otherwise lower.
|
||||
* For VHT - bit-2 marks if the control is lower/upper relative to center-freq
|
||||
* bits-1:0 mark the distance from the center freq. for 20Mhz, offset is 0.
|
||||
* center_freq
|
||||
* For EHT - bit-3 is used for extended distance
|
||||
* center_freq
|
||||
* |
|
||||
* 40Mhz |____|____|
|
||||
* 80Mhz |____|____|____|____|
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020 - 2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020 - 2021, 2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_stats_h__
|
||||
#define __iwl_fw_api_stats_h__
|
||||
#include "mac.h"
|
||||
#include "mac-cfg.h"
|
||||
|
||||
struct mvm_statistics_dbg {
|
||||
__le32 burst_check;
|
||||
|
|
@ -411,6 +412,49 @@ struct iwl_statistics_cmd {
|
|||
|
||||
#define MAX_BCAST_FILTER_NUM 8
|
||||
|
||||
/**
|
||||
* enum iwl_statistics_notify_type_id - type_id used in system statistics
|
||||
* command
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER: request legacy statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART1: request operational part1 statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART2: request operational part2 statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART3: request operational part3 statistics
|
||||
* @IWL_STATS_NTFY_TYPE_ID_OPER_PART4: request operational part4 statistics
|
||||
*/
|
||||
enum iwl_statistics_notify_type_id {
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER = BIT(0),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART1 = BIT(1),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART2 = BIT(2),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART3 = BIT(3),
|
||||
IWL_STATS_NTFY_TYPE_ID_OPER_PART4 = BIT(4),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_statistics_cfg_flags - cfg_mask used in system statistics command
|
||||
* @IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK: 0 for enable, 1 for disable
|
||||
* @IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK: 0 for periodic, 1 for on-demand
|
||||
* @IWL_STATS_CFG_FLG_RESET_MSK: 0 for reset statistics after
|
||||
* sending the notification, 1 for do not reset statistics after sending
|
||||
* the notification
|
||||
*/
|
||||
enum iwl_statistics_cfg_flags {
|
||||
IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK = BIT(0),
|
||||
IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK = BIT(1),
|
||||
IWL_STATS_CFG_FLG_RESET_MSK = BIT(2),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_cmd - system statistics command
|
||||
* @cfg_mask: configuration mask, &enum iwl_statistics_cfg_flags
|
||||
* @config_time_sec: time in sec for periodic notification
|
||||
* @type_id_mask: type_id masks, &enum iwl_statistics_notify_type_id
|
||||
*/
|
||||
struct iwl_system_statistics_cmd {
|
||||
__le32 cfg_mask;
|
||||
__le32 config_time_sec;
|
||||
__le32 type_id_mask;
|
||||
} __packed; /* STATISTICS_FW_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_statistics_type
|
||||
*
|
||||
|
|
@ -447,7 +491,49 @@ struct iwl_statistics_ntfy_hdr {
|
|||
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_mac
|
||||
* struct iwl_stats_ntfy_per_link
|
||||
*
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
* @air_time: air time
|
||||
* @beacon_counter: all beacons (both filtered and not filtered)
|
||||
* @beacon_average_energy: Average energy [-dBm] of all beacons
|
||||
* (both filtered and not filtered)
|
||||
* @beacon_rssi_a: beacon RSSI on antenna A
|
||||
* @beacon_rssi_b: beacon RSSI on antenna B
|
||||
* @rx_bytes: RX byte count
|
||||
*/
|
||||
struct iwl_stats_ntfy_per_link {
|
||||
__le32 beacon_filter_average_energy;
|
||||
__le32 air_time;
|
||||
__le32 beacon_counter;
|
||||
__le32 beacon_average_energy;
|
||||
__le32 beacon_rssi_a;
|
||||
__le32 beacon_rssi_b;
|
||||
__le32 rx_bytes;
|
||||
} __packed; /* STATISTICS_NTFY_PER_LINK_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_stats_ntfy_part1_per_link
|
||||
*
|
||||
* @rx_time: rx time
|
||||
* @tx_time: tx time
|
||||
* @rx_action: action frames handled by FW
|
||||
* @tx_action: action frames generated and transmitted by FW
|
||||
* @cca_defers: cca defer count
|
||||
* @beacon_filtered: filtered out beacons
|
||||
*/
|
||||
struct iwl_stats_ntfy_part1_per_link {
|
||||
__le64 rx_time;
|
||||
__le64 tx_time;
|
||||
__le32 rx_action;
|
||||
__le32 tx_action;
|
||||
__le32 cca_defers;
|
||||
__le32 beacon_filtered;
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_PER_LINK_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_stats_ntfy_per_mac
|
||||
*
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
|
|
@ -459,7 +545,7 @@ struct iwl_statistics_ntfy_hdr {
|
|||
* @beacon_rssi_b: beacon RSSI on antenna B
|
||||
* @rx_bytes: RX byte count
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_mac {
|
||||
struct iwl_stats_ntfy_per_mac {
|
||||
__le32 beacon_filter_average_energy;
|
||||
__le32 air_time;
|
||||
__le32 beacon_counter;
|
||||
|
|
@ -470,7 +556,7 @@ struct iwl_statistics_ntfy_per_mac {
|
|||
} __packed; /* STATISTICS_NTFY_PER_MAC_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_BW_INDEX 5
|
||||
/** struct iwl_statistics_ntfy_per_phy
|
||||
/** struct iwl_stats_ntfy_per_phy
|
||||
* @channel_load: channel load
|
||||
* @channel_load_by_us: device contribution to MCLM
|
||||
* @channel_load_not_by_us: other devices' contribution to MCLM
|
||||
|
|
@ -485,7 +571,7 @@ struct iwl_statistics_ntfy_per_mac {
|
|||
* per channel BW. note BACK counted as 1
|
||||
* @last_tx_ch_width_indx: last txed frame channel width index
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_phy {
|
||||
struct iwl_stats_ntfy_per_phy {
|
||||
__le32 channel_load;
|
||||
__le32 channel_load_by_us;
|
||||
__le32 channel_load_not_by_us;
|
||||
|
|
@ -499,23 +585,62 @@ struct iwl_statistics_ntfy_per_phy {
|
|||
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_sta
|
||||
* struct iwl_stats_ntfy_per_sta
|
||||
*
|
||||
* @average_energy: in fact it is minus the energy..
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_sta {
|
||||
struct iwl_stats_ntfy_per_sta {
|
||||
__le32 average_energy;
|
||||
} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_PHY_OPERTINAL 3
|
||||
#define IWL_STATS_MAX_PHY_OPERATIONAL 3
|
||||
#define IWL_STATS_MAX_FW_LINKS (IWL_MVM_FW_MAX_LINK_ID + 1)
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_notif_oper
|
||||
*
|
||||
* @time_stamp: time when the notification is sent from firmware
|
||||
* @per_link: per link statistics, &struct iwl_stats_ntfy_per_link
|
||||
* @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy
|
||||
* @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta
|
||||
*/
|
||||
struct iwl_system_statistics_notif_oper {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_per_link per_link[IWL_STATS_MAX_FW_LINKS];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_part1_notif_oper
|
||||
*
|
||||
* @time_stamp: time when the notification is sent from firmware
|
||||
* @per_link: per link statistics &struct iwl_stats_ntfy_part1_per_link
|
||||
* @per_phy_crc_error_stats: per phy crc error statistics
|
||||
*/
|
||||
struct iwl_system_statistics_part1_notif_oper {
|
||||
__le32 time_stamp;
|
||||
struct iwl_stats_ntfy_part1_per_link per_link[IWL_STATS_MAX_FW_LINKS];
|
||||
__le32 per_phy_crc_error_stats[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */
|
||||
|
||||
/**
|
||||
* struct iwl_system_statistics_end_notif
|
||||
*
|
||||
* @time_stamp: time when the notification is sent from firmware
|
||||
*/
|
||||
struct iwl_system_statistics_end_notif {
|
||||
__le32 time_stamp;
|
||||
} __packed; /* STATISTICS_FW_NTFY_END_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_operational_ntfy
|
||||
*
|
||||
* @hdr: general statistics header
|
||||
* @flags: bitmap of possible notification structures
|
||||
* @per_mac_stats: per mac statistics, &struct iwl_statistics_ntfy_per_mac
|
||||
* @per_phy_stats: per phy statistics, &struct iwl_statistics_ntfy_per_phy
|
||||
* @per_sta_stats: per sta statistics, &struct iwl_statistics_ntfy_per_sta
|
||||
* @per_mac: per mac statistics, &struct iwl_stats_ntfy_per_mac
|
||||
* @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy
|
||||
* @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta
|
||||
* @rx_time: rx time
|
||||
* @tx_time: usec the radio is transmitting.
|
||||
* @on_time_rf: The total time in usec the RF is awake.
|
||||
|
|
@ -524,9 +649,9 @@ struct iwl_statistics_ntfy_per_sta {
|
|||
struct iwl_statistics_operational_ntfy {
|
||||
struct iwl_statistics_ntfy_hdr hdr;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac per_mac_stats[MAC_INDEX_AUX];
|
||||
struct iwl_statistics_ntfy_per_phy per_phy_stats[IWL_STATS_MAX_PHY_OPERTINAL];
|
||||
struct iwl_statistics_ntfy_per_sta per_sta_stats[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_stats_ntfy_per_mac per_mac[MAC_INDEX_AUX];
|
||||
struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL];
|
||||
struct iwl_stats_ntfy_per_sta per_sta[IWL_MVM_STATION_COUNT_MAX];
|
||||
__le64 rx_time;
|
||||
__le64 tx_time;
|
||||
__le64 on_time_rf;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2020, 2022-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -335,6 +335,63 @@ struct iwl_hs20_roc_res {
|
|||
__le32 status;
|
||||
} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
|
||||
|
||||
/*
|
||||
* Activity types for the ROC command
|
||||
* @ROC_ACTIVITY_HOTSPOT: ROC for hs20 activity
|
||||
* @ROC_ACTIVITY_P2P_DISC: ROC for p2p discoverability activity
|
||||
* @ROC_ACTIVITY_P2P_TXRX: ROC for p2p action frames activity
|
||||
*/
|
||||
enum iwl_roc_activity {
|
||||
ROC_ACTIVITY_HOTSPOT,
|
||||
ROC_ACTIVITY_P2P_DISC,
|
||||
ROC_ACTIVITY_P2P_TXRX,
|
||||
ROC_NUM_ACTIVITIES
|
||||
}; /* ROC_ACTIVITY_API_E_VER_1 */
|
||||
|
||||
/*
|
||||
* ROC command
|
||||
*
|
||||
* Command requests the firmware to remain on a channel for a certain duration.
|
||||
*
|
||||
* ( MAC_CONF_GROUP 0x3, ROC_CMD 0xE )
|
||||
*
|
||||
* @action: action to perform, see &enum iwl_ctxt_action
|
||||
* @activity: type of activity, see &enum iwl_roc_activity
|
||||
* @sta_id: station id, resumed during "Remain On Channel" activity.
|
||||
* @channel_info: &struct iwl_fw_channel_info
|
||||
* @node_addr: node MAC address for Rx filtering
|
||||
* @reserved: align to a dword
|
||||
* @max_delay: max delay the ROC can start in TU
|
||||
* @duration: remain on channel duration in TU
|
||||
*/
|
||||
struct iwl_roc_req {
|
||||
__le32 action;
|
||||
__le32 activity;
|
||||
__le32 sta_id;
|
||||
struct iwl_fw_channel_info channel_info;
|
||||
u8 node_addr[ETH_ALEN];
|
||||
__le16 reserved;
|
||||
__le32 max_delay;
|
||||
__le32 duration;
|
||||
} __packed; /* ROC_CMD_API_S_VER_3 */
|
||||
|
||||
/*
|
||||
* ROC notification
|
||||
*
|
||||
* Notification when ROC startes and when ROC ended.
|
||||
*
|
||||
* ( MAC_CONF_GROUP 0x3, ROC_NOTIF 0xf8 )
|
||||
*
|
||||
* @status: true if ROC succeeded to start
|
||||
* @start_end: true if ROC started, false if ROC ended
|
||||
* @activity: notification to which activity - &enum iwl_roc_activity
|
||||
*/
|
||||
struct iwl_roc_notif {
|
||||
__le32 success;
|
||||
__le32 started;
|
||||
__le32 activity;
|
||||
} __packed; /* ROC_NOTIF_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_session_prot_conf_id - session protection's configurations
|
||||
* @SESSION_PROTECT_CONF_ASSOC: Start a session protection for association.
|
||||
|
|
@ -375,8 +432,8 @@ enum iwl_mvm_session_prot_conf_id {
|
|||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_cmd - configure a session protection
|
||||
* @id_and_color: the id and color of the mac for which this session protection
|
||||
* is sent
|
||||
* @id_and_color: the id and color of the link (or mac, for command version 1)
|
||||
* for which this session protection is sent
|
||||
* @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE,
|
||||
* see &enum iwl_ctxt_action
|
||||
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
|
||||
|
|
@ -397,11 +454,15 @@ struct iwl_mvm_session_prot_cmd {
|
|||
__le32 duration_tu;
|
||||
__le32 repetition_count;
|
||||
__le32 interval;
|
||||
} __packed; /* SESSION_PROTECTION_CMD_API_S_VER_1 */
|
||||
} __packed;
|
||||
/* SESSION_PROTECTION_CMD_API_S_VER_1 and
|
||||
* SESSION_PROTECTION_CMD_API_S_VER_2
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_notif - session protection started / ended
|
||||
* @mac_id: the mac id for which the session protection started / ended
|
||||
* @mac_link_id: the mac id (or link id, for notif ver > 2) for which the
|
||||
* session protection started / ended
|
||||
* @status: 1 means success, 0 means failure
|
||||
* @start: 1 means the session protection started, 0 means it ended
|
||||
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
|
||||
|
|
@ -410,10 +471,13 @@ struct iwl_mvm_session_prot_cmd {
|
|||
* and end even the firmware could not schedule it.
|
||||
*/
|
||||
struct iwl_mvm_session_prot_notif {
|
||||
__le32 mac_id;
|
||||
__le32 mac_link_id;
|
||||
__le32 status;
|
||||
__le32 start;
|
||||
__le32 conf_id;
|
||||
} __packed; /* SESSION_PROTECTION_NOTIFICATION_API_S_VER_2 */
|
||||
} __packed;
|
||||
/* SESSION_PROTECTION_NOTIFICATION_API_S_VER_2 and
|
||||
* SESSION_PROTECTION_NOTIFICATION_API_S_VER_3
|
||||
*/
|
||||
|
||||
#endif /* __iwl_fw_api_time_event_h__ */
|
||||
|
|
|
|||
|
|
@ -1021,22 +1021,18 @@ struct iwl_dump_ini_region_data {
|
|||
struct iwl_fwrt_dump_data *dump_data;
|
||||
};
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
static int iwl_dump_ini_prph_mac_iter_common(struct iwl_fw_runtime *fwrt,
|
||||
void *range_ptr, u32 addr,
|
||||
__le32 size)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
__le32 *val = range->data;
|
||||
u32 prph_val;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]) +
|
||||
le32_to_cpu(reg->dev_addr.offset);
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->dev_addr.size;
|
||||
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
|
||||
range->range_data_size = size;
|
||||
for (i = 0; i < le32_to_cpu(size); i += 4) {
|
||||
prph_val = iwl_read_prph(fwrt->trans, addr + i);
|
||||
if (iwl_trans_is_hw_error_value(prph_val))
|
||||
return -EBUSY;
|
||||
|
|
@ -1047,38 +1043,61 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
|
|||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
|
||||
iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]) +
|
||||
le32_to_cpu(reg->dev_addr.offset);
|
||||
|
||||
return iwl_dump_ini_prph_mac_iter_common(fwrt, range_ptr, addr,
|
||||
reg->dev_addr.size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_mac_block_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
|
||||
u32 addr = le32_to_cpu(reg->dev_addr_range.offset) +
|
||||
le32_to_cpu(pairs[idx].addr);
|
||||
|
||||
return iwl_dump_ini_prph_mac_iter_common(fwrt, range_ptr, addr,
|
||||
pairs[idx].size);
|
||||
}
|
||||
|
||||
static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
|
||||
void *range_ptr, u32 addr,
|
||||
__le32 size, __le32 offset)
|
||||
{
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
__le32 *val = range->data;
|
||||
u32 indirect_wr_addr = WMAL_INDRCT_RD_CMD1;
|
||||
u32 indirect_rd_addr = WMAL_MRSPF_1;
|
||||
u32 prph_val;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]);
|
||||
u32 dphy_state;
|
||||
u32 dphy_addr;
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->dev_addr.size;
|
||||
range->range_data_size = size;
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
indirect_wr_addr = WMAL_INDRCT_CMD1;
|
||||
|
||||
indirect_wr_addr += le32_to_cpu(reg->dev_addr.offset);
|
||||
indirect_rd_addr += le32_to_cpu(reg->dev_addr.offset);
|
||||
indirect_wr_addr += le32_to_cpu(offset);
|
||||
indirect_rd_addr += le32_to_cpu(offset);
|
||||
|
||||
if (!iwl_trans_grab_nic_access(fwrt->trans))
|
||||
return -EBUSY;
|
||||
|
||||
dphy_addr = (reg->dev_addr.offset) ? WFPM_LMAC2_PS_CTL_RW :
|
||||
WFPM_LMAC1_PS_CTL_RW;
|
||||
dphy_addr = (offset) ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW;
|
||||
dphy_state = iwl_read_umac_prph_no_grab(fwrt->trans, dphy_addr);
|
||||
|
||||
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
|
||||
for (i = 0; i < le32_to_cpu(size); i += 4) {
|
||||
if (dphy_state == HBUS_TIMEOUT ||
|
||||
(dphy_state & WFPM_PS_CTL_RW_PHYRF_PD_FSM_CURSTATE_MSK) !=
|
||||
WFPM_PHYRF_STATE_ON) {
|
||||
|
|
@ -1097,6 +1116,33 @@ iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
|
|||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]);
|
||||
|
||||
return iwl_dump_ini_prph_phy_iter_common(fwrt, range_ptr, addr,
|
||||
reg->dev_addr.size,
|
||||
reg->dev_addr.offset);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_phy_block_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
|
||||
u32 addr = le32_to_cpu(pairs[idx].addr);
|
||||
|
||||
return iwl_dump_ini_prph_phy_iter_common(fwrt, range_ptr, addr,
|
||||
pairs[idx].size,
|
||||
reg->dev_addr_range.offset);
|
||||
}
|
||||
|
||||
static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
|
|
@ -1370,6 +1416,53 @@ out:
|
|||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data,
|
||||
void *range_ptr, u32 range_len, int idx)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_error_dump_range *range = range_ptr;
|
||||
__le32 *val = range->data;
|
||||
__le32 offset = reg->dev_addr.offset;
|
||||
u32 indirect_rd_wr_addr = DPHYIP_INDIRECT;
|
||||
u32 addr = le32_to_cpu(reg->addrs[idx]);
|
||||
u32 dphy_state, dphy_addr, prph_val;
|
||||
int i;
|
||||
|
||||
range->internal_base_addr = cpu_to_le32(addr);
|
||||
range->range_data_size = reg->dev_addr.size;
|
||||
|
||||
if (!iwl_trans_grab_nic_access(fwrt->trans))
|
||||
return -EBUSY;
|
||||
|
||||
indirect_rd_wr_addr += le32_to_cpu(offset);
|
||||
|
||||
dphy_addr = offset ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW;
|
||||
dphy_state = iwl_read_umac_prph_no_grab(fwrt->trans, dphy_addr);
|
||||
|
||||
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
|
||||
if (dphy_state == HBUS_TIMEOUT ||
|
||||
(dphy_state & WFPM_PS_CTL_RW_PHYRF_PD_FSM_CURSTATE_MSK) !=
|
||||
WFPM_PHYRF_STATE_ON) {
|
||||
*val++ = cpu_to_le32(WFPM_DPHY_OFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
iwl_write_prph_no_grab(fwrt->trans, indirect_rd_wr_addr,
|
||||
addr + i);
|
||||
/* wait a bit for value to be ready in register */
|
||||
udelay(1);
|
||||
prph_val = iwl_read_prph_no_grab(fwrt->trans,
|
||||
indirect_rd_wr_addr);
|
||||
*val++ = cpu_to_le32((prph_val & DPHYIP_INDIRECT_RD_MSK) >>
|
||||
DPHYIP_INDIRECT_RD_SHIFT);
|
||||
}
|
||||
|
||||
iwl_trans_release_nic_access(fwrt->trans);
|
||||
return sizeof(*range) + le32_to_cpu(range->range_data_size);
|
||||
}
|
||||
|
||||
struct iwl_ini_rxf_data {
|
||||
u32 fifo_num;
|
||||
u32 size;
|
||||
|
|
@ -1781,6 +1874,16 @@ static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
|
|||
return iwl_tlv_array_len(reg_data->reg_tlv, reg, addrs);
|
||||
}
|
||||
|
||||
static u32
|
||||
iwl_dump_ini_mem_block_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
size_t size = sizeof(struct iwl_fw_ini_addr_size);
|
||||
|
||||
return iwl_tlv_array_len_with_size(reg_data->reg_tlv, reg, size);
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
{
|
||||
|
|
@ -1866,6 +1969,25 @@ static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt,
|
|||
(size + sizeof(struct iwl_fw_ini_error_dump_range));
|
||||
}
|
||||
|
||||
static u32
|
||||
iwl_dump_ini_mem_block_get_size(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
|
||||
u32 ranges = iwl_dump_ini_mem_block_ranges(fwrt, reg_data);
|
||||
u32 size = sizeof(struct iwl_fw_ini_error_dump);
|
||||
int range;
|
||||
|
||||
if (!ranges)
|
||||
return 0;
|
||||
|
||||
for (range = 0; range < ranges; range++)
|
||||
size += le32_to_cpu(pairs[range].size);
|
||||
|
||||
return size + ranges * sizeof(struct iwl_fw_ini_error_dump_range);
|
||||
}
|
||||
|
||||
static u32
|
||||
iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dump_ini_region_data *reg_data)
|
||||
|
|
@ -2413,6 +2535,18 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
|
|||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_phy_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE] = {
|
||||
.get_num_of_ranges = iwl_dump_ini_mem_block_ranges,
|
||||
.get_size = iwl_dump_ini_mem_block_get_size,
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_mac_block_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE] = {
|
||||
.get_num_of_ranges = iwl_dump_ini_mem_block_ranges,
|
||||
.get_size = iwl_dump_ini_mem_block_get_size,
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_phy_block_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_AUX] = {},
|
||||
[IWL_FW_INI_REGION_PAGING] = {
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
|
|
@ -2450,6 +2584,12 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
|
|||
.fill_mem_hdr = iwl_dump_ini_mon_dbgi_fill_header,
|
||||
.fill_range = iwl_dump_ini_dbgi_sram_iter,
|
||||
},
|
||||
[IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP] = {
|
||||
.get_num_of_ranges = iwl_dump_ini_mem_ranges,
|
||||
.get_size = iwl_dump_ini_mem_get_size,
|
||||
.fill_mem_hdr = iwl_dump_ini_mem_fill_header,
|
||||
.fill_range = iwl_dump_ini_prph_snps_dphyip_iter,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
|
|
@ -2492,7 +2632,9 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
|||
if (reg_type >= ARRAY_SIZE(iwl_dump_ini_region_ops))
|
||||
continue;
|
||||
|
||||
if (reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY &&
|
||||
if ((reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY ||
|
||||
reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE ||
|
||||
reg_type == IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP) &&
|
||||
tp_id != IWL_FW_INI_TIME_POINT_FW_ASSERT) {
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: trying to collect phy prph at time point: %d, skipping\n",
|
||||
|
|
|
|||
|
|
@ -141,7 +141,11 @@ static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
event_cfg.enabled_severities = cpu_to_le32(enabled_severities);
|
||||
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
if (fwrt->ops && fwrt->ops->send_hcmd)
|
||||
ret = fwrt->ops->send_hcmd(fwrt->ops_ctx, &hcmd);
|
||||
else
|
||||
ret = -EPERM;
|
||||
|
||||
IWL_INFO(fwrt,
|
||||
"sent host event cfg with enabled_severities: %u, ret: %d\n",
|
||||
enabled_severities, ret);
|
||||
|
|
|
|||
|
|
@ -975,4 +975,6 @@ static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
|
|||
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), \
|
||||
sizeof(_struct_ptr->_memb[0]))
|
||||
|
||||
#define iwl_tlv_array_len_with_size(_tlv_ptr, _struct_ptr, _size) \
|
||||
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), _size)
|
||||
#endif /* __iwl_fw_file_h__ */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -198,7 +198,7 @@ struct iwl_dump_exclude {
|
|||
struct iwl_fw {
|
||||
u32 ucode_ver;
|
||||
|
||||
char fw_version[64];
|
||||
char fw_version[128];
|
||||
|
||||
/* ucode images */
|
||||
struct fw_img img[IWL_UCODE_TYPE_MAX];
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ struct iwl_txf_iter_data {
|
|||
* @cur_fw_img: current firmware image, must be maintained by
|
||||
* the driver by calling &iwl_fw_set_current_image()
|
||||
* @dump: debug dump data
|
||||
* @uats_enabled: VLP or AFC AP is enabled
|
||||
* @uats_table: AP type table
|
||||
*/
|
||||
struct iwl_fw_runtime {
|
||||
struct iwl_trans *trans;
|
||||
|
|
@ -171,6 +173,8 @@ struct iwl_fw_runtime {
|
|||
struct iwl_sar_offset_mapping_cmd sgom_table;
|
||||
bool sgom_enabled;
|
||||
u8 reduced_power_flags;
|
||||
bool uats_enabled;
|
||||
struct iwl_uats_table_cmd uats_table;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -388,4 +388,54 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
|||
kfree(data);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table);
|
||||
|
||||
static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
if (uats_data->revision != 1)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(fwrt->uats_table.offset_map, uats_data->offset_map,
|
||||
sizeof(fwrt->uats_table.offset_map));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct uefi_cnv_wlan_uats_data *data;
|
||||
unsigned long package_size;
|
||||
int ret;
|
||||
|
||||
data = iwl_uefi_get_variable(IWL_UEFI_UATS_NAME, &IWL_EFI_VAR_GUID,
|
||||
&package_size);
|
||||
if (IS_ERR(data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"UATS UEFI variable not found 0x%lx\n",
|
||||
PTR_ERR(data));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (package_size < sizeof(*data)) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Invalid UATS table UEFI variable len (%lu)\n",
|
||||
package_size);
|
||||
kfree(data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read UATS from UEFI with size %lu\n",
|
||||
package_size);
|
||||
|
||||
ret = iwl_uefi_uats_parse(data, fwrt);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_FW(trans, "Cannot read UATS table. rev is invalid\n");
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@
|
|||
#define IWL_UEFI_REDUCED_POWER_NAME L"UefiCnvWlanReducedPower"
|
||||
#define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping"
|
||||
#define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP"
|
||||
#define IWL_UEFI_UATS_NAME L"CnvUefiWlanUATS"
|
||||
|
||||
#define IWL_SGOM_MAP_SIZE 339
|
||||
#define IWL_UATS_MAP_SIZE 339
|
||||
|
||||
struct pnvm_sku_package {
|
||||
u8 rev;
|
||||
|
|
@ -25,6 +27,11 @@ struct uefi_cnv_wlan_sgom_data {
|
|||
u8 offset_map[IWL_SGOM_MAP_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_wlan_uats_data {
|
||||
u8 revision;
|
||||
u8 offset_map[IWL_UATS_MAP_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_common_step_data {
|
||||
u8 revision;
|
||||
u8 step_mode;
|
||||
|
|
@ -82,10 +89,20 @@ iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
|
|||
|
||||
#if defined(CONFIG_EFI) && defined(CONFIG_ACPI)
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt);
|
||||
#else
|
||||
static inline
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* __iwl_fw_uefi__ */
|
||||
|
|
|
|||
|
|
@ -86,10 +86,7 @@ enum iwl_nvm_type {
|
|||
#define IWL_DEFAULT_MAX_TX_POWER 22
|
||||
#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\
|
||||
NETIF_F_TSO | NETIF_F_TSO6)
|
||||
#define IWL_TX_CSUM_NETIF_FLAGS_BZ (NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6)
|
||||
#define IWL_CSUM_NETIF_FLAGS_MASK (IWL_TX_CSUM_NETIF_FLAGS | \
|
||||
IWL_TX_CSUM_NETIF_FLAGS_BZ | \
|
||||
NETIF_F_RXCSUM)
|
||||
#define IWL_CSUM_NETIF_FLAGS_MASK (IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM)
|
||||
|
||||
/* Antenna presence definitions */
|
||||
#define ANT_NONE 0x0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -313,6 +313,7 @@ enum {
|
|||
SILICON_C_STEP,
|
||||
SILICON_D_STEP,
|
||||
SILICON_E_STEP,
|
||||
SILICON_TC_STEP = 0xe,
|
||||
SILICON_Z_STEP = 0xf,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,17 +3,19 @@
|
|||
*
|
||||
* Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(C) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018, 2023 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __IWLWIFI_DEVICE_TRACE
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "iwl-trans.h"
|
||||
#if !defined(__IWLWIFI_DEVICE_TRACE)
|
||||
static inline bool iwl_trace_data(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
int offs = 24; /* start with normal header length */
|
||||
|
|
@ -21,6 +23,10 @@ static inline bool iwl_trace_data(struct sk_buff *skb)
|
|||
if (!ieee80211_is_data(fc))
|
||||
return false;
|
||||
|
||||
/* If upper layers wanted TX status it's an important frame */
|
||||
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
|
||||
return false;
|
||||
|
||||
/* Try to determine if the frame is EAPOL. This might have false
|
||||
* positives (if there's no RFC 1042 header and we compare to some
|
||||
* payload instead) but since we're only doing tracing that's not
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -162,6 +162,8 @@ static inline char iwl_drv_get_step(int step)
|
|||
{
|
||||
if (step == SILICON_Z_STEP)
|
||||
return 'z';
|
||||
if (step == SILICON_TC_STEP)
|
||||
return 'a';
|
||||
return 'a' + step;
|
||||
}
|
||||
|
||||
|
|
@ -178,6 +180,8 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
|
|||
|
||||
mac_step = iwl_drv_get_step(trans->hw_rev_step);
|
||||
|
||||
rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
|
||||
|
||||
switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
|
||||
case IWL_CFG_RF_TYPE_HR1:
|
||||
case IWL_CFG_RF_TYPE_HR2:
|
||||
|
|
@ -196,7 +200,13 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
|
|||
rf = "fm";
|
||||
break;
|
||||
case IWL_CFG_RF_TYPE_WH:
|
||||
rf = "wh";
|
||||
if (SILICON_Z_STEP ==
|
||||
CSR_HW_RFID_STEP(trans->hw_rf_id)) {
|
||||
rf = "whtc";
|
||||
rf_step = 'a';
|
||||
} else {
|
||||
rf = "wh";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return "unknown-rf";
|
||||
|
|
@ -204,8 +214,6 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
|
|||
|
||||
cdb = CSR_HW_RFID_IS_CDB(trans->hw_rf_id) ? "4" : "";
|
||||
|
||||
rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
|
||||
|
||||
scnprintf(buf, FW_NAME_PRE_BUFSIZE,
|
||||
"iwlwifi-%s-%c0-%s%s-%c0",
|
||||
trans->cfg->fw_name_mac, mac_step,
|
||||
|
|
@ -1303,10 +1311,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
case IWL_UCODE_TLV_CURRENT_PC:
|
||||
if (tlv_len < sizeof(struct iwl_pc_data))
|
||||
goto invalid_tlv_len;
|
||||
drv->trans->dbg.num_pc =
|
||||
tlv_len / sizeof(struct iwl_pc_data);
|
||||
drv->trans->dbg.pc_data =
|
||||
kmemdup(tlv_data, tlv_len, GFP_KERNEL);
|
||||
if (!drv->trans->dbg.pc_data)
|
||||
return -ENOMEM;
|
||||
drv->trans->dbg.num_pc =
|
||||
tlv_len / sizeof(struct iwl_pc_data);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
|
||||
|
|
@ -1415,6 +1425,9 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
|||
struct iwl_op_mode *op_mode = NULL;
|
||||
int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;
|
||||
|
||||
/* also protects start/stop from racing against each other */
|
||||
lockdep_assert_held(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
for (retry = 0; retry <= max_retry; retry++) {
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
|
@ -1429,6 +1442,9 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
|||
if (op_mode)
|
||||
return op_mode;
|
||||
|
||||
if (test_bit(STATUS_TRANS_DEAD, &drv->trans->status))
|
||||
break;
|
||||
|
||||
IWL_ERR(drv, "retry init count %d\n", retry);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
|
@ -1442,6 +1458,9 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
|||
|
||||
static void _iwl_op_mode_stop(struct iwl_drv *drv)
|
||||
{
|
||||
/* also protects start/stop from racing against each other */
|
||||
lockdep_assert_held(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (drv->op_mode) {
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
|
|
@ -1725,11 +1744,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
}
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
/*
|
||||
* Complete the firmware request last so that
|
||||
* a driver unbind (stop) doesn't run while we
|
||||
* are doing the start() above.
|
||||
*/
|
||||
complete(&drv->request_firmware_complete);
|
||||
|
||||
/*
|
||||
|
|
@ -1834,11 +1848,12 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
|||
{
|
||||
wait_for_completion(&drv->request_firmware_complete);
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
|
||||
_iwl_op_mode_stop(drv);
|
||||
|
||||
iwl_dealloc_ucode(drv);
|
||||
|
||||
mutex_lock(&iwlwifi_opmode_table_mtx);
|
||||
/*
|
||||
* List is empty (this item wasn't added)
|
||||
* when firmware loading failed -- in that
|
||||
|
|
|
|||
|
|
@ -671,7 +671,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
|
|||
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
|
||||
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 |
|
||||
IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC,
|
||||
.phy_cap_info[0] =
|
||||
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
|
||||
|
|
|
|||
|
|
@ -348,8 +348,8 @@
|
|||
#define RFIC_REG_RD 0xAD0470
|
||||
#define WFPM_CTRL_REG 0xA03030
|
||||
#define WFPM_OTP_CFG1_ADDR 0x00a03098
|
||||
#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4)
|
||||
#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5)
|
||||
#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(5)
|
||||
#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(4)
|
||||
#define WFPM_OTP_BZ_BNJ_JACKET_BIT 5
|
||||
#define WFPM_OTP_BZ_BNJ_CDB_BIT 4
|
||||
#define WFPM_OTP_CFG1_IS_JACKET(_val) (((_val) & 0x00000020) >> WFPM_OTP_BZ_BNJ_JACKET_BIT)
|
||||
|
|
@ -365,7 +365,6 @@
|
|||
#define DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK 0x00000FFF
|
||||
|
||||
enum {
|
||||
ENABLE_WFPM = BIT(31),
|
||||
WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK = 0x80000000,
|
||||
};
|
||||
|
||||
|
|
@ -383,7 +382,7 @@ enum {
|
|||
#define PREG_PRPH_WPROT_22000 0xA04D00
|
||||
|
||||
#define SB_MODIFY_CFG_FLAG 0xA03088
|
||||
#define SB_CFG_RESIDES_IN_OTP_MASK 0x10
|
||||
#define SB_CFG_RESIDES_IN_ROM 0x80
|
||||
#define SB_CPU_1_STATUS 0xA01E30
|
||||
#define SB_CPU_2_STATUS 0xA01E34
|
||||
#define UMAG_SB_CPU_1_STATUS 0xA038C0
|
||||
|
|
@ -424,14 +423,14 @@ enum {
|
|||
* reserved: bits 12-18
|
||||
* slave_exist: bit 19
|
||||
* dash: bits 20-23
|
||||
* step: bits 24-26
|
||||
* flavor: bits 27-31
|
||||
* step: bits 24-27
|
||||
* flavor: bits 28-31
|
||||
*/
|
||||
#define REG_CRF_ID_TYPE(val) (((val) & 0x00000FFF) >> 0)
|
||||
#define REG_CRF_ID_SLAVE(val) (((val) & 0x00080000) >> 19)
|
||||
#define REG_CRF_ID_DASH(val) (((val) & 0x00F00000) >> 20)
|
||||
#define REG_CRF_ID_STEP(val) (((val) & 0x07000000) >> 24)
|
||||
#define REG_CRF_ID_FLAVOR(val) (((val) & 0xF8000000) >> 27)
|
||||
#define REG_CRF_ID_STEP(val) (((val) & 0x0F000000) >> 24)
|
||||
#define REG_CRF_ID_FLAVOR(val) (((val) & 0xF0000000) >> 28)
|
||||
|
||||
#define UREG_CHICK (0xA05C00)
|
||||
#define UREG_CHICK_MSI_ENABLE BIT(24)
|
||||
|
|
@ -517,4 +516,8 @@ enum {
|
|||
#define WFPM_LMAC2_PD_NOTIFICATION 0xA033CC
|
||||
#define WFPM_LMAC2_PD_RE_READ BIT(31)
|
||||
|
||||
#define DPHYIP_INDIRECT 0xA2D800
|
||||
#define DPHYIP_INDIRECT_RD_MSK 0xFF000000
|
||||
#define DPHYIP_INDIRECT_RD_SHIFT 24
|
||||
|
||||
#endif /* __iwl_prph_h__ */
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
|
|||
#define IWL_MGMT_TID 15
|
||||
#define IWL_FRAME_LIMIT 64
|
||||
#define IWL_MAX_RX_HW_QUEUES 16
|
||||
#define IWL_9000_MAX_RX_HW_QUEUES 6
|
||||
#define IWL_9000_MAX_RX_HW_QUEUES 1
|
||||
|
||||
/**
|
||||
* enum iwl_wowlan_status - WoWLAN image/device status
|
||||
|
|
@ -589,7 +589,7 @@ struct iwl_trans_ops {
|
|||
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_tx_cmd *dev_cmd, int queue);
|
||||
void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
|
||||
struct sk_buff_head *skbs);
|
||||
struct sk_buff_head *skbs, bool is_flush);
|
||||
|
||||
void (*set_q_ptrs)(struct iwl_trans *trans, int queue, int ptr);
|
||||
|
||||
|
|
@ -1274,14 +1274,15 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
|
||||
int ssn, struct sk_buff_head *skbs)
|
||||
int ssn, struct sk_buff_head *skbs,
|
||||
bool is_flush)
|
||||
{
|
||||
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
|
||||
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
|
||||
return;
|
||||
}
|
||||
|
||||
trans->ops->reclaim(trans, queue, ssn, skbs);
|
||||
trans->ops->reclaim(trans, queue, ssn, skbs, is_flush);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2021 - 2022 Intel Corporation
|
||||
* Copyright (C) 2021-2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __iwl_mei_h__
|
||||
|
|
@ -493,7 +493,7 @@ static inline void iwl_mei_set_power_limit(__le16 *power_limit)
|
|||
|
||||
static inline int iwl_mei_register(void *priv,
|
||||
const struct iwl_mei_ops *ops)
|
||||
{ return 0; }
|
||||
{ return -EOPNOTSUPP; }
|
||||
|
||||
static inline void iwl_mei_start_unregister(void)
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -119,5 +119,6 @@
|
|||
#define IWL_MVM_DISABLE_AP_FILS false
|
||||
#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */
|
||||
#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */
|
||||
#define IWL_MVM_AUTO_EML_ENABLE true
|
||||
|
||||
#endif /* __MVM_CONSTANTS_H */
|
||||
|
|
|
|||
|
|
@ -818,7 +818,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
|
||||
|
||||
if (iwl_mvm_is_lar_supported(mvm) && iwl_mvm_init_fw_regd(mvm))
|
||||
if (iwl_mvm_is_lar_supported(mvm) && iwl_mvm_init_fw_regd(mvm, false))
|
||||
IWL_ERR(mvm, "Failed to initialize D3 LAR information\n");
|
||||
|
||||
return 0;
|
||||
|
|
@ -2031,6 +2031,16 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
|
|||
if (IS_ERR(key_config))
|
||||
return false;
|
||||
ieee80211_set_key_rx_seq(key_config, 0, &seq);
|
||||
|
||||
if (key_config->keyidx == 4 || key_config->keyidx == 5) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
|
||||
struct iwl_mvm_vif_link_info *mvm_link =
|
||||
mvmvif->link[link_id];
|
||||
|
||||
mvm_link->igtk = key_config;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -699,19 +699,11 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
|
|||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
|
||||
|
||||
|
||||
void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct dentry *dbgfs_dir = vif->debugfs_dir;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
char buf[100];
|
||||
|
||||
/*
|
||||
* Check if debugfs directory already exist before creating it.
|
||||
* This may happen when, for example, resetting hw or suspend-resume
|
||||
*/
|
||||
if (!dbgfs_dir || mvmvif->dbgfs_dir)
|
||||
return;
|
||||
|
||||
mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
|
||||
if (IS_ERR_OR_NULL(mvmvif->dbgfs_dir)) {
|
||||
|
|
@ -737,6 +729,17 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
|
||||
mvmvif == mvm->bf_allowed_vif)
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, 0600);
|
||||
}
|
||||
|
||||
void iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct dentry *dbgfs_dir = vif->debugfs_dir;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
char buf[100];
|
||||
|
||||
/* this will happen in monitor mode */
|
||||
if (!dbgfs_dir)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Create symlink for convenience pointing to interface specific
|
||||
|
|
@ -745,21 +748,62 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
* find
|
||||
* netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
|
||||
*/
|
||||
snprintf(buf, 100, "../../../%pd3/%pd",
|
||||
dbgfs_dir,
|
||||
mvmvif->dbgfs_dir);
|
||||
snprintf(buf, 100, "../../../%pd3/iwlmvm", dbgfs_dir);
|
||||
|
||||
mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
|
||||
mvm->debugfs_dir, buf);
|
||||
}
|
||||
|
||||
void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
void iwl_mvm_vif_dbgfs_rm_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
debugfs_remove(mvmvif->dbgfs_slink);
|
||||
mvmvif->dbgfs_slink = NULL;
|
||||
|
||||
debugfs_remove_recursive(mvmvif->dbgfs_dir);
|
||||
mvmvif->dbgfs_dir = NULL;
|
||||
}
|
||||
|
||||
#define MVM_DEBUGFS_WRITE_LINK_FILE_OPS(name, bufsz) \
|
||||
_MVM_DEBUGFS_WRITE_FILE_OPS(link_##name, bufsz, \
|
||||
struct ieee80211_bss_conf)
|
||||
#define MVM_DEBUGFS_READ_WRITE_LINK_FILE_OPS(name, bufsz) \
|
||||
_MVM_DEBUGFS_READ_WRITE_FILE_OPS(link_##name, bufsz, \
|
||||
struct ieee80211_bss_conf)
|
||||
#define MVM_DEBUGFS_ADD_LINK_FILE(name, parent, mode) \
|
||||
debugfs_create_file(#name, mode, parent, link_conf, \
|
||||
&iwl_dbgfs_link_##name##_ops)
|
||||
|
||||
static void iwl_mvm_debugfs_add_link_files(struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct dentry *mvm_dir)
|
||||
{
|
||||
/* Add per-link files here*/
|
||||
}
|
||||
|
||||
void iwl_mvm_link_add_debugfs(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct dentry *dir)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
unsigned int link_id = link_conf->link_id;
|
||||
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
|
||||
struct dentry *mvm_dir;
|
||||
|
||||
if (WARN_ON(!link_info) || !dir)
|
||||
return;
|
||||
|
||||
if (dir == vif->debugfs_dir) {
|
||||
WARN_ON(!mvmvif->dbgfs_dir);
|
||||
mvm_dir = mvmvif->dbgfs_dir;
|
||||
} else {
|
||||
mvm_dir = debugfs_create_dir("iwlmvm", dir);
|
||||
if (IS_ERR_OR_NULL(mvm_dir)) {
|
||||
IWL_ERR(mvm, "Failed to create debugfs directory under %pd\n",
|
||||
dir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_mvm_debugfs_add_link_files(vif, link_conf, mvm_dir);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,18 @@ static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
bool force;
|
||||
|
||||
if (!iwl_mvm_is_ctdp_supported(mvm))
|
||||
if (!kstrtobool(buf, &force))
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"force start is %d [0=disabled, 1=enabled]\n",
|
||||
force);
|
||||
|
||||
/* we allow skipping cap support check and force stop ctdp
|
||||
* statistics collection and with guerantee that it is
|
||||
* safe to use.
|
||||
*/
|
||||
if (!force && !iwl_mvm_is_ctdp_supported(mvm))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm) ||
|
||||
|
|
@ -65,6 +75,36 @@ static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
|
|||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_start_ctdp_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
bool force;
|
||||
|
||||
if (!kstrtobool(buf, &force))
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"force start is %d [0=disabled, 1=enabled]\n",
|
||||
force);
|
||||
|
||||
/* we allow skipping cap support check and force enable ctdp
|
||||
* for statistics collection and with guerantee that it is
|
||||
* safe to use.
|
||||
*/
|
||||
if (!force && !iwl_mvm_is_ctdp_supported(mvm))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm) ||
|
||||
mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START, 0);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
|
@ -965,6 +1005,13 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
|
|||
char *buf;
|
||||
int ret;
|
||||
size_t bufsz;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(SYSTEM_GROUP,
|
||||
SYSTEM_STATISTICS_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (iwl_mvm_has_new_rx_stats_api(mvm))
|
||||
bufsz = ((sizeof(struct mvm_statistics_rx) /
|
||||
|
|
@ -1144,6 +1191,101 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
|
|||
}
|
||||
#undef PRINT_STAT_LE32
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_system_stats_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *buff, *pos, *endpos;
|
||||
int ret;
|
||||
size_t bufsz;
|
||||
int i;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
struct ieee80211_vif *vif;
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(SYSTEM_GROUP,
|
||||
SYSTEM_STATISTICS_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
/* in case of a wrong cmd version, allocate buffer only for error msg */
|
||||
bufsz = (cmd_ver == 1) ? 4096 : 64;
|
||||
|
||||
buff = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = buff;
|
||||
endpos = pos + bufsz;
|
||||
|
||||
if (cmd_ver != 1) {
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"System stats not supported:%d\n", cmd_ver);
|
||||
goto send_out;
|
||||
}
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (iwl_mvm_firmware_running(mvm))
|
||||
iwl_mvm_request_statistics(mvm, false);
|
||||
|
||||
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
|
||||
if (!vif)
|
||||
continue;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == NUM_MAC_INDEX_DRIVER || !vif) {
|
||||
pos += scnprintf(pos, endpos - pos, "vif is NULL\n");
|
||||
goto release_send_out;
|
||||
}
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
if (!mvmvif) {
|
||||
pos += scnprintf(pos, endpos - pos, "mvmvif is NULL\n");
|
||||
goto release_send_out;
|
||||
}
|
||||
|
||||
for_each_mvm_vif_valid_link(mvmvif, i) {
|
||||
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[i];
|
||||
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"link_id %d", i);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
" num_beacons %d",
|
||||
link_info->beacon_stats.num_beacons);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
" accu_num_beacons %d",
|
||||
link_info->beacon_stats.accu_num_beacons);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
" avg_signal %d\n",
|
||||
link_info->beacon_stats.avg_signal);
|
||||
}
|
||||
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"radio_stats.rx_time %lld\n",
|
||||
mvm->radio_stats.rx_time);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"radio_stats.tx_time %lld\n",
|
||||
mvm->radio_stats.tx_time);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"accu_radio_stats.rx_time %lld\n",
|
||||
mvm->accu_radio_stats.rx_time);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"accu_radio_stats.tx_time %lld\n",
|
||||
mvm->accu_radio_stats.tx_time);
|
||||
|
||||
release_send_out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
send_out:
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
|
||||
kfree(buff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
|
||||
char __user *user_buf, size_t count,
|
||||
loff_t *ppos,
|
||||
|
|
@ -1998,6 +2140,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
|
|||
/* Device wide debugfs entries */
|
||||
MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(start_ctdp, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
|
||||
|
|
@ -2012,6 +2155,7 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
|
|||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(fw_system_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(tas_get_status);
|
||||
|
|
@ -2210,6 +2354,7 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
|
|||
MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(stop_ctdp, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(start_ctdp, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(force_ctkill, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(stations, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_notif, mvm->debugfs_dir, 0400);
|
||||
|
|
@ -2218,6 +2363,7 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
|
|||
MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_system_stats, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, 0200);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
* Copyright (C) 2012-2014 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
*/
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
|
@ -302,7 +302,12 @@ static void iwl_mvm_resp_del_pasn_sta(struct iwl_mvm *mvm,
|
|||
struct iwl_mvm_pasn_sta *sta)
|
||||
{
|
||||
list_del(&sta->list);
|
||||
iwl_mvm_rm_sta_id(mvm, vif, sta->int_sta.sta_id);
|
||||
|
||||
if (iwl_mvm_has_mld_api(mvm->fw))
|
||||
iwl_mvm_mld_rm_sta_id(mvm, sta->int_sta.sta_id);
|
||||
else
|
||||
iwl_mvm_rm_sta_id(mvm, vif, sta->int_sta.sta_id);
|
||||
|
||||
iwl_mvm_dealloc_int_sta(mvm, &sta->int_sta);
|
||||
kfree(sta);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "iwl-prph.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/pnvm.h"
|
||||
#include "fw/uefi.h"
|
||||
|
||||
#include "mvm.h"
|
||||
#include "fw/dbg.h"
|
||||
|
|
@ -23,12 +24,15 @@
|
|||
#include "iwl-nvm-parse.h"
|
||||
#include "time-sync.h"
|
||||
|
||||
#define MVM_UCODE_ALIVE_TIMEOUT (HZ)
|
||||
#define MVM_UCODE_ALIVE_TIMEOUT (2 * HZ)
|
||||
#define MVM_UCODE_CALIB_TIMEOUT (2 * HZ)
|
||||
|
||||
#define IWL_TAS_US_MCC 0x5553
|
||||
#define IWL_TAS_CANADA_MCC 0x4341
|
||||
|
||||
#define IWL_UATS_VLP_AP_SUPPORTED BIT(29)
|
||||
#define IWL_UATS_AFC_AP_SUPPORTED BIT(30)
|
||||
|
||||
struct iwl_mvm_alive_data {
|
||||
bool valid;
|
||||
u32 scd_base_addr;
|
||||
|
|
@ -487,6 +491,52 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
#if defined(CONFIG_ACPI) && defined(CONFIG_EFI)
|
||||
static void iwl_mvm_uats_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
int ret;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
UATS_TABLE_CMD),
|
||||
.flags = 0,
|
||||
.data[0] = &mvm->fwrt.uats_table,
|
||||
.len[0] = sizeof(mvm->fwrt.uats_table),
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
};
|
||||
|
||||
if (!(mvm->trans->trans_cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_AX210)) {
|
||||
IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mvm->fwrt.uats_enabled) {
|
||||
IWL_DEBUG_RADIO(mvm, "UATS feature is disabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd.id,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
if (cmd_ver != 1) {
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"UATS_TABLE_CMD ver %d not supported\n",
|
||||
cmd_ver);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(mvm, "failed to read UATS table (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret < 0)
|
||||
IWL_ERR(mvm, "failed to send UATS_TABLE_CMD (%d)\n", ret);
|
||||
else
|
||||
IWL_DEBUG_RADIO(mvm, "UATS_TABLE_CMD sent to FW\n");
|
||||
}
|
||||
|
||||
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
|
|
@ -526,6 +576,10 @@ static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_uats_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
|
|
@ -596,7 +650,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
|
|||
if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
|
||||
sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG);
|
||||
/* if needed, we'll reset this on our way out later */
|
||||
mvm->pldr_sync = !(sb_cfg & SB_CFG_RESIDES_IN_OTP_MASK);
|
||||
mvm->pldr_sync = sb_cfg == SB_CFG_RESIDES_IN_ROM;
|
||||
if (mvm->pldr_sync && iwl_mei_pldr_req())
|
||||
return -EBUSY;
|
||||
}
|
||||
|
|
@ -1101,6 +1155,12 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
},
|
||||
},
|
||||
{ .ident = "GOOGLE-HP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSI",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
|
||||
|
|
@ -1226,7 +1286,10 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
|||
{
|
||||
int ret;
|
||||
u32 value;
|
||||
struct iwl_lari_config_change_cmd_v6 cmd = {};
|
||||
struct iwl_lari_config_change_cmd_v7 cmd = {};
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE), 1);
|
||||
|
||||
cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt);
|
||||
|
||||
|
|
@ -1244,8 +1307,11 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
|||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ACTIVATE_CHANNEL,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
if (cmd_ver < 8)
|
||||
value &= ~ACTIVATE_5G2_IN_WW_MASK;
|
||||
cmd.chan_state_active_bitmap = cpu_to_le32(value);
|
||||
}
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ENABLE_6E,
|
||||
|
|
@ -1259,18 +1325,26 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
|||
if (!ret)
|
||||
cmd.force_disable_channels_bitmap = cpu_to_le32(value);
|
||||
|
||||
ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
|
||||
DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
|
||||
&iwl_guid, &value);
|
||||
if (!ret)
|
||||
cmd.edt_bitmap = cpu_to_le32(value);
|
||||
|
||||
if (cmd.config_bitmap ||
|
||||
cmd.oem_uhb_allow_bitmap ||
|
||||
cmd.oem_11ax_allow_bitmap ||
|
||||
cmd.oem_unii4_allow_bitmap ||
|
||||
cmd.chan_state_active_bitmap ||
|
||||
cmd.force_disable_channels_bitmap) {
|
||||
cmd.force_disable_channels_bitmap ||
|
||||
cmd.edt_bitmap) {
|
||||
size_t cmd_size;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE),
|
||||
1);
|
||||
|
||||
switch (cmd_ver) {
|
||||
case 8:
|
||||
case 7:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v7);
|
||||
break;
|
||||
case 6:
|
||||
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6);
|
||||
break;
|
||||
|
|
@ -1304,6 +1378,9 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
|||
"sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd.oem_uhb_allow_bitmap),
|
||||
le32_to_cpu(cmd.force_disable_channels_bitmap));
|
||||
IWL_DEBUG_RADIO(mvm,
|
||||
"sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x\n",
|
||||
le32_to_cpu(cmd.edt_bitmap));
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
LARI_CONFIG_CHANGE),
|
||||
|
|
@ -1313,6 +1390,10 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
|||
"Failed to send LARI_CONFIG_CHANGE (%d)\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
if (le32_to_cpu(cmd.oem_uhb_allow_bitmap) & IWL_UATS_VLP_AP_SUPPORTED ||
|
||||
le32_to_cpu(cmd.oem_uhb_allow_bitmap) & IWL_UATS_AFC_AP_SUPPORTED)
|
||||
mvm->fwrt.uats_enabled = TRUE;
|
||||
}
|
||||
|
||||
void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
||||
|
|
@ -1516,8 +1597,6 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
|
|||
int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret, i;
|
||||
struct ieee80211_channel *chan;
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct ieee80211_supported_band *sband = NULL;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
|
@ -1642,21 +1721,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
goto error;
|
||||
}
|
||||
|
||||
chan = &sband->channels[0];
|
||||
|
||||
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
/*
|
||||
* The channel used here isn't relevant as it's
|
||||
* going to be overwritten in the other flows.
|
||||
* For now use the first channel we have.
|
||||
*/
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, &mvm->phy_ctxts[i],
|
||||
&chandef, 1, 1);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (iwl_mvm_is_tt_in_fw(mvm)) {
|
||||
/* in order to give the responsibility of ct-kill and
|
||||
* TX backoff to FW we need to send empty temperature reporting
|
||||
|
|
@ -1739,6 +1803,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
|
||||
iwl_mvm_tas_init(mvm);
|
||||
iwl_mvm_leds_sync(mvm);
|
||||
iwl_mvm_uats_init(mvm);
|
||||
|
||||
if (iwl_rfi_supported(mvm)) {
|
||||
if (iwl_mvm_eval_dsm_rfi(mvm) == DSM_VALUE_RFI_ENABLE)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
unsigned int link_id = link_conf->link_id;
|
||||
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
|
||||
struct iwl_link_config_cmd cmd = {};
|
||||
struct iwl_mvm_phy_ctxt *phyctxt;
|
||||
|
||||
if (WARN_ON_ONCE(!link_info))
|
||||
return -EINVAL;
|
||||
|
|
@ -61,7 +60,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) {
|
||||
link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm,
|
||||
mvmvif);
|
||||
if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)
|
||||
if (link_info->fw_link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf))
|
||||
return -EINVAL;
|
||||
|
||||
rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id],
|
||||
|
|
@ -77,12 +76,8 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
|
||||
cmd.mac_id = cpu_to_le32(mvmvif->id);
|
||||
cmd.spec_link_id = link_conf->link_id;
|
||||
/* P2P-Device already has a valid PHY context during add */
|
||||
phyctxt = link_info->phy_ctxt;
|
||||
if (phyctxt)
|
||||
cmd.phy_id = cpu_to_le32(phyctxt->id);
|
||||
else
|
||||
cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
|
||||
WARN_ON_ONCE(link_info->phy_ctxt);
|
||||
cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
|
||||
|
||||
memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN);
|
||||
|
||||
|
|
@ -194,11 +189,14 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
flags_mask |= LINK_FLG_MU_EDCA_CW;
|
||||
}
|
||||
|
||||
if (link_conf->eht_puncturing && !iwlwifi_mod_params.disable_11be)
|
||||
cmd.puncture_mask = cpu_to_le16(link_conf->eht_puncturing);
|
||||
else
|
||||
/* This flag can be set only if the MAC has eht support */
|
||||
changes &= ~LINK_CONTEXT_MODIFY_EHT_PARAMS;
|
||||
if (changes & LINK_CONTEXT_MODIFY_EHT_PARAMS) {
|
||||
if (iwlwifi_mod_params.disable_11be ||
|
||||
!link_conf->eht_support)
|
||||
changes &= ~LINK_CONTEXT_MODIFY_EHT_PARAMS;
|
||||
else
|
||||
cmd.puncture_mask =
|
||||
cpu_to_le16(link_conf->eht_puncturing);
|
||||
}
|
||||
|
||||
cmd.bss_color = link_conf->he_bss_color.color;
|
||||
|
||||
|
|
@ -244,9 +242,10 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
struct iwl_link_config_cmd cmd = {};
|
||||
int ret;
|
||||
|
||||
/* mac80211 thought we have the link, but it was never configured */
|
||||
if (WARN_ON(!link_info ||
|
||||
link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
|
||||
return -EINVAL;
|
||||
link_info->fw_link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf)))
|
||||
return 0;
|
||||
|
||||
RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
|
||||
NULL);
|
||||
|
|
@ -254,6 +253,7 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
|
||||
link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
|
||||
cmd.spec_link_id = link_conf->link_id;
|
||||
cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
|
||||
|
||||
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);
|
||||
|
||||
|
|
|
|||
|
|
@ -286,6 +286,10 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
INIT_LIST_HEAD(&mvmvif->time_event_data.list);
|
||||
mvmvif->time_event_data.id = TE_MAX;
|
||||
|
||||
mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
|
||||
|
||||
/* No need to allocate data queues to P2P Device MAC and NAN.*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
return 0;
|
||||
|
|
@ -300,10 +304,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
|
||||
}
|
||||
|
||||
mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
|
||||
|
||||
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
|
||||
mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm,
|
|||
MCC_SOURCE_OLD_FW, changed);
|
||||
}
|
||||
|
||||
int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
|
||||
int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm, bool force_regd_sync)
|
||||
{
|
||||
enum iwl_mcc_source used_src;
|
||||
struct ieee80211_regdomain *regd;
|
||||
|
|
@ -213,8 +213,10 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
|
|||
if (IS_ERR_OR_NULL(regd))
|
||||
return -EIO;
|
||||
|
||||
/* update cfg80211 if the regdomain was changed */
|
||||
if (changed)
|
||||
/* update cfg80211 if the regdomain was changed or the caller explicitly
|
||||
* asked to update regdomain
|
||||
*/
|
||||
if (changed || force_regd_sync)
|
||||
ret = regulatory_set_wiphy_regd_sync(mvm->hw->wiphy, regd);
|
||||
else
|
||||
ret = 0;
|
||||
|
|
@ -376,7 +378,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
}
|
||||
|
||||
if (iwl_mvm_has_new_rx_api(mvm))
|
||||
/* We want to use the mac80211's reorder buffer for 9000 */
|
||||
if (iwl_mvm_has_new_rx_api(mvm) &&
|
||||
mvm->trans->trans_cfg->device_family > IWL_DEVICE_FAMILY_9000)
|
||||
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
|
|
@ -1535,6 +1539,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
|
|
@ -1551,8 +1556,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
/* make sure that beacon statistics don't go backwards with FW reset */
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||
mvmvif->deflink.beacon_stats.accu_num_beacons +=
|
||||
mvmvif->deflink.beacon_stats.num_beacons;
|
||||
for_each_mvm_vif_valid_link(mvmvif, i)
|
||||
mvmvif->link[i]->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->link[i]->beacon_stats.num_beacons;
|
||||
|
||||
/* Allocate resources for the MAC context, and add it to the fw */
|
||||
ret = iwl_mvm_mac_ctxt_init(mvm, vif);
|
||||
|
|
@ -1580,7 +1586,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
*/
|
||||
if (vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
iwl_mvm_vif_dbgfs_register(mvm, vif);
|
||||
iwl_mvm_vif_dbgfs_add_link(mvm, vif);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1607,32 +1613,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
}
|
||||
|
||||
/*
|
||||
* P2P_DEVICE interface does not have a channel context assigned to it,
|
||||
* so a dedicated PHY context is allocated to it and the corresponding
|
||||
* MAC context is bound to it at this stage.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
|
||||
mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
|
||||
if (!mvmvif->deflink.phy_ctxt) {
|
||||
ret = -ENOSPC;
|
||||
goto out_free_bf;
|
||||
}
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
ret = iwl_mvm_binding_add_vif(mvm, vif);
|
||||
if (ret)
|
||||
goto out_unref_phy;
|
||||
|
||||
ret = iwl_mvm_add_p2p_bcast_sta(mvm, vif);
|
||||
if (ret)
|
||||
goto out_unbind;
|
||||
|
||||
/* Save a pointer to p2p device vif, so it can later be used to
|
||||
* update the p2p device MAC when a GO is started/stopped */
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
mvm->p2p_device_vif = vif;
|
||||
}
|
||||
|
||||
iwl_mvm_tcm_add_vif(mvm, vif);
|
||||
INIT_DELAYED_WORK(&mvmvif->csa_work,
|
||||
|
|
@ -1644,7 +1626,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
iwl_mvm_chandef_get_primary_80(&vif->bss_conf.chandef);
|
||||
}
|
||||
|
||||
iwl_mvm_vif_dbgfs_register(mvm, vif);
|
||||
iwl_mvm_vif_dbgfs_add_link(mvm, vif);
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
|
||||
|
|
@ -1661,16 +1643,6 @@ out:
|
|||
|
||||
goto out_unlock;
|
||||
|
||||
out_unbind:
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
out_unref_phy:
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
out_free_bf:
|
||||
if (mvm->bf_allowed_vif == mvmvif) {
|
||||
mvm->bf_allowed_vif = NULL;
|
||||
vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI);
|
||||
}
|
||||
out_remove_mac:
|
||||
mvmvif->deflink.phy_ctxt = NULL;
|
||||
iwl_mvm_mac_ctxt_remove(mvm, vif);
|
||||
|
|
@ -1732,7 +1704,7 @@ static bool iwl_mvm_mac_remove_interface_common(struct ieee80211_hw *hw,
|
|||
if (vif->bss_conf.ftm_responder)
|
||||
memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
|
||||
|
||||
iwl_mvm_vif_dbgfs_clean(mvm, vif);
|
||||
iwl_mvm_vif_dbgfs_rm_link(mvm, vif);
|
||||
|
||||
/*
|
||||
* For AP/GO interface, the tear down of the resources allocated to the
|
||||
|
|
@ -1762,12 +1734,17 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
if (iwl_mvm_mac_remove_interface_common(hw, vif))
|
||||
goto out;
|
||||
|
||||
/* Before the interface removal, mac80211 would cancel the ROC, and the
|
||||
* ROC worker would be scheduled if needed. The worker would be flushed
|
||||
* in iwl_mvm_prepare_mac_removal() and thus at this point there is no
|
||||
* binding etc. so nothing needs to be done here.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
if (mvmvif->deflink.phy_ctxt) {
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
mvmvif->deflink.phy_ctxt = NULL;
|
||||
}
|
||||
mvm->p2p_device_vif = NULL;
|
||||
iwl_mvm_rm_p2p_bcast_sta(mvm, vif);
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
mvmvif->deflink.phy_ctxt = NULL;
|
||||
}
|
||||
|
||||
iwl_mvm_mac_ctxt_remove(mvm, vif);
|
||||
|
|
@ -2491,7 +2468,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
u32 duration_override)
|
||||
u32 duration_override, unsigned int link_id)
|
||||
{
|
||||
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
|
||||
u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
|
||||
|
|
@ -2511,7 +2488,8 @@ void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
|
||||
iwl_mvm_schedule_session_protection(mvm, vif, 900,
|
||||
min_duration, false);
|
||||
min_duration, false,
|
||||
link_id);
|
||||
else
|
||||
iwl_mvm_protect_session(mvm, vif, duration,
|
||||
min_duration, 500, false);
|
||||
|
|
@ -2605,6 +2583,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
|||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Re-calculate the tsf id, as the leader-follower relations depend
|
||||
|
|
@ -2651,8 +2630,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
|||
if (vif->cfg.assoc) {
|
||||
/* clear statistics to get clean beacon counter */
|
||||
iwl_mvm_request_statistics(mvm, true);
|
||||
memset(&mvmvif->deflink.beacon_stats, 0,
|
||||
sizeof(mvmvif->deflink.beacon_stats));
|
||||
for_each_mvm_vif_valid_link(mvmvif, i)
|
||||
memset(&mvmvif->link[i]->beacon_stats, 0,
|
||||
sizeof(mvmvif->link[i]->beacon_stats));
|
||||
|
||||
/* add quota for this interface */
|
||||
ret = iwl_mvm_update_quotas(mvm, true, NULL);
|
||||
|
|
@ -2699,7 +2679,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
|||
* time could be small without us having heard
|
||||
* a beacon yet.
|
||||
*/
|
||||
iwl_mvm_protect_assoc(mvm, vif, 0);
|
||||
iwl_mvm_protect_assoc(mvm, vif, 0, 0);
|
||||
}
|
||||
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
|
|
@ -3065,22 +3045,6 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
|
|||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u64 changes)
|
||||
{
|
||||
static const struct iwl_mvm_bss_info_changed_ops callbacks = {
|
||||
.bss_info_changed_sta = iwl_mvm_bss_info_changed_station,
|
||||
.bss_info_changed_ap_ibss = iwl_mvm_bss_info_changed_ap_ibss,
|
||||
};
|
||||
|
||||
iwl_mvm_bss_info_changed_common(hw, vif, bss_conf, &callbacks,
|
||||
changes);
|
||||
}
|
||||
|
||||
void
|
||||
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
const struct iwl_mvm_bss_info_changed_ops *callbacks,
|
||||
u64 changes)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
|
|
@ -3091,12 +3055,11 @@ iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
|
|||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
callbacks->bss_info_changed_sta(mvm, vif, bss_conf, changes);
|
||||
iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
callbacks->bss_info_changed_ap_ibss(mvm, vif, bss_conf,
|
||||
changes);
|
||||
iwl_mvm_bss_info_changed_ap_ibss(mvm, vif, bss_conf, changes);
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
if (changes & BSS_CHANGED_MU_GROUPS)
|
||||
|
|
@ -3803,12 +3766,25 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
|
|||
|
||||
callbacks->mac_ctxt_changed(mvm, vif, false);
|
||||
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
|
||||
|
||||
/* when client is authorized (AP station marked as such),
|
||||
* try to enable more links
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||
iwl_mvm_mld_select_links(mvm, vif, false);
|
||||
}
|
||||
|
||||
mvm_sta->authorized = true;
|
||||
|
||||
iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
|
||||
|
||||
/* MFP is set by default before the station is authorized.
|
||||
* Clear it here in case it's not used.
|
||||
*/
|
||||
if (!sta->mfp)
|
||||
return callbacks->update_sta(mvm, vif, sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4042,7 +4018,7 @@ void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
|
|||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_protect_assoc(mvm, vif, info->duration);
|
||||
iwl_mvm_protect_assoc(mvm, vif, info->duration, info->link_id);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
|
|
@ -4179,12 +4155,21 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
* GTK on AP interface is a TX-only key, return 0;
|
||||
* on IBSS they're per-station and because we're lazy
|
||||
* we don't support them for RX, so do the same.
|
||||
* CMAC/GMAC in AP/IBSS modes must be done in software.
|
||||
* CMAC/GMAC in AP/IBSS modes must be done in software
|
||||
* on older NICs.
|
||||
*
|
||||
* Except, of course, beacon protection - it must be
|
||||
* offloaded since we just set a beacon template.
|
||||
* offloaded since we just set a beacon template, and
|
||||
* then we must also offload the IGTK (not just BIGTK)
|
||||
* for firmware reasons.
|
||||
*
|
||||
* So just check for beacon protection - if we don't
|
||||
* have it we cannot get here with keyidx >= 6, and
|
||||
* if we do have it we need to send the key to FW in
|
||||
* all cases (CMAC/GMAC).
|
||||
*/
|
||||
if (keyidx < 6 &&
|
||||
if (!wiphy_ext_feature_isset(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION) &&
|
||||
(key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
|
||||
key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
|
||||
key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)) {
|
||||
|
|
@ -4413,6 +4398,39 @@ static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
|
|||
#define AUX_ROC_MAX_DELAY MSEC_TO_TU(600)
|
||||
#define AUX_ROC_SAFETY_BUFFER MSEC_TO_TU(20)
|
||||
#define AUX_ROC_MIN_SAFETY_BUFFER MSEC_TO_TU(10)
|
||||
|
||||
static void iwl_mvm_roc_duration_and_delay(struct ieee80211_vif *vif,
|
||||
u32 duration_ms,
|
||||
u32 *duration_tu,
|
||||
u32 *delay)
|
||||
{
|
||||
u32 dtim_interval = vif->bss_conf.dtim_period *
|
||||
vif->bss_conf.beacon_int;
|
||||
|
||||
*delay = AUX_ROC_MIN_DELAY;
|
||||
*duration_tu = MSEC_TO_TU(duration_ms);
|
||||
|
||||
/*
|
||||
* If we are associated we want the delay time to be at least one
|
||||
* dtim interval so that the FW can wait until after the DTIM and
|
||||
* then start the time event, this will potentially allow us to
|
||||
* remain off-channel for the max duration.
|
||||
* Since we want to use almost a whole dtim interval we would also
|
||||
* like the delay to be for 2-3 dtim intervals, in case there are
|
||||
* other time events with higher priority.
|
||||
*/
|
||||
if (vif->cfg.assoc) {
|
||||
*delay = min_t(u32, dtim_interval * 3, AUX_ROC_MAX_DELAY);
|
||||
/* We cannot remain off-channel longer than the DTIM interval */
|
||||
if (dtim_interval <= *duration_tu) {
|
||||
*duration_tu = dtim_interval - AUX_ROC_SAFETY_BUFFER;
|
||||
if (*duration_tu <= AUX_ROC_MIN_DURATION)
|
||||
*duration_tu = dtim_interval -
|
||||
AUX_ROC_MIN_SAFETY_BUFFER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
||||
struct ieee80211_channel *channel,
|
||||
struct ieee80211_vif *vif,
|
||||
|
|
@ -4423,8 +4441,6 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
|||
struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
|
||||
static const u16 time_event_response[] = { HOT_SPOT_CMD };
|
||||
struct iwl_notification_wait wait_time_event;
|
||||
u32 dtim_interval = vif->bss_conf.dtim_period *
|
||||
vif->bss_conf.beacon_int;
|
||||
u32 req_dur, delay;
|
||||
struct iwl_hs20_roc_req aux_roc_req = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
|
|
@ -4445,29 +4461,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
|||
/* Set the time and duration */
|
||||
tail->apply_time = cpu_to_le32(iwl_mvm_get_systime(mvm));
|
||||
|
||||
delay = AUX_ROC_MIN_DELAY;
|
||||
req_dur = MSEC_TO_TU(duration);
|
||||
|
||||
/*
|
||||
* If we are associated we want the delay time to be at least one
|
||||
* dtim interval so that the FW can wait until after the DTIM and
|
||||
* then start the time event, this will potentially allow us to
|
||||
* remain off-channel for the max duration.
|
||||
* Since we want to use almost a whole dtim interval we would also
|
||||
* like the delay to be for 2-3 dtim intervals, in case there are
|
||||
* other time events with higher priority.
|
||||
*/
|
||||
if (vif->cfg.assoc) {
|
||||
delay = min_t(u32, dtim_interval * 3, AUX_ROC_MAX_DELAY);
|
||||
/* We cannot remain off-channel longer than the DTIM interval */
|
||||
if (dtim_interval <= req_dur) {
|
||||
req_dur = dtim_interval - AUX_ROC_SAFETY_BUFFER;
|
||||
if (req_dur <= AUX_ROC_MIN_DURATION)
|
||||
req_dur = dtim_interval -
|
||||
AUX_ROC_MIN_SAFETY_BUFFER;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_mvm_roc_duration_and_delay(vif, duration, &req_dur, &delay);
|
||||
tail->duration = cpu_to_le32(req_dur);
|
||||
tail->apply_time_max_delay = cpu_to_le32(delay);
|
||||
|
||||
|
|
@ -4475,8 +4469,8 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
|||
"ROC: Requesting to remain on channel %u for %ums\n",
|
||||
channel->hw_value, req_dur);
|
||||
IWL_DEBUG_TE(mvm,
|
||||
"\t(requested = %ums, max_delay = %ums, dtim_interval = %ums)\n",
|
||||
duration, delay, dtim_interval);
|
||||
"\t(requested = %ums, max_delay = %ums)\n",
|
||||
duration, delay);
|
||||
|
||||
/* Set the node address */
|
||||
memcpy(tail->node_addr, vif->addr, ETH_ALEN);
|
||||
|
|
@ -4534,6 +4528,48 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
|||
return res;
|
||||
}
|
||||
|
||||
static int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
|
||||
struct ieee80211_channel *channel,
|
||||
struct ieee80211_vif *vif,
|
||||
int duration, u32 activity)
|
||||
{
|
||||
int res;
|
||||
u32 duration_tu, delay;
|
||||
struct iwl_roc_req roc_req = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.activity = cpu_to_le32(activity),
|
||||
.sta_id = cpu_to_le32(mvm->aux_sta.sta_id),
|
||||
};
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* Set the channel info data */
|
||||
iwl_mvm_set_chan_info(mvm, &roc_req.channel_info,
|
||||
channel->hw_value,
|
||||
iwl_mvm_phy_band_from_nl80211(channel->band),
|
||||
IWL_PHY_CHANNEL_MODE20, 0);
|
||||
|
||||
iwl_mvm_roc_duration_and_delay(vif, duration, &duration_tu,
|
||||
&delay);
|
||||
roc_req.duration = cpu_to_le32(duration_tu);
|
||||
roc_req.max_delay = cpu_to_le32(delay);
|
||||
|
||||
IWL_DEBUG_TE(mvm,
|
||||
"\t(requested = %ums, max_delay = %ums)\n",
|
||||
duration, delay);
|
||||
IWL_DEBUG_TE(mvm,
|
||||
"Requesting to remain on channel %u for %utu\n",
|
||||
channel->hw_value, duration_tu);
|
||||
|
||||
/* Set the node address */
|
||||
memcpy(roc_req.node_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
res = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
|
||||
0, sizeof(roc_req), &roc_req);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -4554,30 +4590,20 @@ static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_roc_switch_binding(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_phy_ctxt *new_phy_ctxt)
|
||||
static int iwl_mvm_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* Unbind the P2P_DEVICE from the current PHY context,
|
||||
* and if the PHY context is not used remove it.
|
||||
*/
|
||||
ret = iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
|
||||
ret = iwl_mvm_binding_add_vif(mvm, vif);
|
||||
if (WARN(ret, "Failed binding P2P_DEVICE\n"))
|
||||
return ret;
|
||||
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
|
||||
/* Bind the P2P_DEVICE to the current PHY Context */
|
||||
mvmvif->deflink.phy_ctxt = new_phy_ctxt;
|
||||
|
||||
ret = iwl_mvm_binding_add_vif(mvm, vif);
|
||||
WARN(ret, "Failed binding P2P_DEVICE\n");
|
||||
return ret;
|
||||
/* The station and queue allocation must be done only after the binding
|
||||
* is done, as otherwise the FW might incorrectly configure its state.
|
||||
*/
|
||||
return iwl_mvm_add_p2p_bcast_sta(mvm, vif);
|
||||
}
|
||||
|
||||
static int iwl_mvm_roc(struct ieee80211_hw *hw,
|
||||
|
|
@ -4588,12 +4614,81 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
|
|||
{
|
||||
static const struct iwl_mvm_roc_ops ops = {
|
||||
.add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20,
|
||||
.switch_phy_ctxt = iwl_mvm_roc_switch_binding,
|
||||
.link = iwl_mvm_roc_link,
|
||||
};
|
||||
|
||||
return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
|
||||
}
|
||||
|
||||
static int iwl_mvm_roc_station(struct iwl_mvm *mvm,
|
||||
struct ieee80211_channel *channel,
|
||||
struct ieee80211_vif *vif,
|
||||
int duration)
|
||||
{
|
||||
int ret;
|
||||
u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, ROC_CMD);
|
||||
u8 fw_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
if (fw_ver == IWL_FW_CMD_VER_UNKNOWN) {
|
||||
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, vif, duration);
|
||||
} else if (fw_ver == 3) {
|
||||
ret = iwl_mvm_roc_add_cmd(mvm, channel, vif, duration,
|
||||
ROC_ACTIVITY_HOTSPOT);
|
||||
} else {
|
||||
ret = -EOPNOTSUPP;
|
||||
IWL_ERR(mvm, "ROC command version %d mismatch!\n", fw_ver);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_p2p_find_phy_ctxt(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct cfg80211_chan_def chandef;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (mvmvif->deflink.phy_ctxt &&
|
||||
channel == mvmvif->deflink.phy_ctxt->channel)
|
||||
return 0;
|
||||
|
||||
/* Try using a PHY context that is already in use */
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[i];
|
||||
|
||||
if (!phy_ctxt->ref || mvmvif->deflink.phy_ctxt == phy_ctxt)
|
||||
continue;
|
||||
|
||||
if (channel == phy_ctxt->channel) {
|
||||
if (mvmvif->deflink.phy_ctxt)
|
||||
iwl_mvm_phy_ctxt_unref(mvm,
|
||||
mvmvif->deflink.phy_ctxt);
|
||||
|
||||
mvmvif->deflink.phy_ctxt = phy_ctxt;
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We already have a phy_ctxt, but it's not on the right channel */
|
||||
if (mvmvif->deflink.phy_ctxt)
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
|
||||
mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
|
||||
if (!mvmvif->deflink.phy_ctxt)
|
||||
return -ENOSPC;
|
||||
|
||||
cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
|
||||
|
||||
return iwl_mvm_phy_ctxt_add(mvm, mvmvif->deflink.phy_ctxt,
|
||||
&chandef, 1, 1);
|
||||
}
|
||||
|
||||
/* Execute the common part for MLD and non-MLD modes */
|
||||
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *channel, int duration,
|
||||
|
|
@ -4601,12 +4696,8 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
const struct iwl_mvm_roc_ops *ops)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||
bool band_change_removal;
|
||||
int ret, i;
|
||||
u32 lmac_id;
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
|
||||
duration, type);
|
||||
|
|
@ -4626,89 +4717,27 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
/* Use aux roc framework (HS20) */
|
||||
ret = ops->add_aux_sta_for_hs20(mvm, lmac_id);
|
||||
if (!ret)
|
||||
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
|
||||
vif, duration);
|
||||
ret = iwl_mvm_roc_station(mvm, channel, vif, duration);
|
||||
goto out_unlock;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
/* handle below */
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
|
||||
IWL_ERR(mvm, "ROC: Invalid vif type=%u\n", vif->type);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_PHY_CTX; i++) {
|
||||
phy_ctxt = &mvm->phy_ctxts[i];
|
||||
if (phy_ctxt->ref == 0 || mvmvif->deflink.phy_ctxt == phy_ctxt)
|
||||
continue;
|
||||
|
||||
if (phy_ctxt->ref && channel == phy_ctxt->channel) {
|
||||
ret = ops->switch_phy_ctxt(mvm, vif, phy_ctxt);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
ret = iwl_mvm_p2p_find_phy_ctxt(mvm, vif, channel);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
goto schedule_time_event;
|
||||
}
|
||||
}
|
||||
ret = ops->link(mvm, vif);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
/* Need to update the PHY context only if the ROC channel changed */
|
||||
if (channel == mvmvif->deflink.phy_ctxt->channel)
|
||||
goto schedule_time_event;
|
||||
|
||||
cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
|
||||
|
||||
/*
|
||||
* Check if the remain-on-channel is on a different band and that
|
||||
* requires context removal, see iwl_mvm_phy_ctxt_changed(). If
|
||||
* so, we'll need to release and then re-configure here, since we
|
||||
* must not remove a PHY context that's part of a binding.
|
||||
*/
|
||||
band_change_removal =
|
||||
fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
|
||||
mvmvif->deflink.phy_ctxt->channel->band != chandef.chan->band;
|
||||
|
||||
if (mvmvif->deflink.phy_ctxt->ref == 1 && !band_change_removal) {
|
||||
/*
|
||||
* Change the PHY context configuration as it is currently
|
||||
* referenced only by the P2P Device MAC (and we can modify it)
|
||||
*/
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->deflink.phy_ctxt,
|
||||
&chandef, 1, 1);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
} else {
|
||||
/*
|
||||
* The PHY context is shared with other MACs (or we're trying to
|
||||
* switch bands), so remove the P2P Device from the binding,
|
||||
* allocate an new PHY context and create a new binding.
|
||||
*/
|
||||
phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
|
||||
if (!phy_ctxt) {
|
||||
ret = -ENOSPC;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chandef,
|
||||
1, 1);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to change PHY context\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = ops->switch_phy_ctxt(mvm, vif, phy_ctxt);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
}
|
||||
|
||||
schedule_time_event:
|
||||
/* Schedule the time events */
|
||||
ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
IWL_DEBUG_MAC80211(mvm, "leave\n");
|
||||
|
|
@ -4780,15 +4809,14 @@ static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def,
|
||||
ctx->rx_chains_static,
|
||||
ctx->rx_chains_dynamic);
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, def,
|
||||
ctx->rx_chains_static,
|
||||
ctx->rx_chains_dynamic);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to add PHY context\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt);
|
||||
*phy_ctxt_id = phy_ctxt->id;
|
||||
out:
|
||||
return ret;
|
||||
|
|
@ -5253,8 +5281,8 @@ int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw)
|
|||
return mvm->ibss_manager;
|
||||
}
|
||||
|
||||
int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set)
|
||||
static int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
|
@ -5655,7 +5683,8 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
}
|
||||
|
||||
if (drop) {
|
||||
if (iwl_mvm_flush_sta(mvm, mvmsta, false))
|
||||
if (iwl_mvm_flush_sta(mvm, mvmsta->deflink.sta_id,
|
||||
mvmsta->tfd_queue_msk))
|
||||
IWL_ERR(mvm, "flush request fail\n");
|
||||
} else {
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
|
|
@ -5677,22 +5706,21 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
int i;
|
||||
struct iwl_mvm_link_sta *mvm_link_sta;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
int link_id;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct ieee80211_sta *tmp;
|
||||
|
||||
tmp = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (tmp != sta)
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!mvm_link_sta)
|
||||
continue;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
if (iwl_mvm_flush_sta(mvm, mvmsta, false))
|
||||
if (iwl_mvm_flush_sta(mvm, mvm_link_sta->sta_id,
|
||||
mvmsta->tfd_queue_msk))
|
||||
IWL_ERR(mvm, "flush request fail\n");
|
||||
}
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
|
@ -5702,7 +5730,11 @@ int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
struct survey_info *survey)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
int ret;
|
||||
int ret = 0;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(SYSTEM_GROUP,
|
||||
SYSTEM_STATISTICS_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
memset(survey, 0, sizeof(*survey));
|
||||
|
||||
|
|
@ -5722,13 +5754,8 @@ int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
goto out;
|
||||
}
|
||||
|
||||
survey->filled = SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_SCAN;
|
||||
survey->time = mvm->accu_radio_stats.on_time_rf +
|
||||
mvm->radio_stats.on_time_rf;
|
||||
do_div(survey->time, USEC_PER_MSEC);
|
||||
survey->filled = SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_TX;
|
||||
|
||||
survey->time_rx = mvm->accu_radio_stats.rx_time +
|
||||
mvm->radio_stats.rx_time;
|
||||
|
|
@ -5738,11 +5765,20 @@ int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
mvm->radio_stats.tx_time;
|
||||
do_div(survey->time_tx, USEC_PER_MSEC);
|
||||
|
||||
/* the new fw api doesn't support the following fields */
|
||||
if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
|
||||
goto out;
|
||||
|
||||
survey->filled |= SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_SCAN;
|
||||
survey->time = mvm->accu_radio_stats.on_time_rf +
|
||||
mvm->radio_stats.on_time_rf;
|
||||
do_div(survey->time, USEC_PER_MSEC);
|
||||
|
||||
survey->time_scan = mvm->accu_radio_stats.on_time_scan +
|
||||
mvm->radio_stats.on_time_scan;
|
||||
do_div(survey->time_scan, USEC_PER_MSEC);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return ret;
|
||||
|
|
@ -5891,6 +5927,7 @@ void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
|
|||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
int i;
|
||||
|
||||
if (mvmsta->deflink.avg_energy) {
|
||||
sinfo->signal_avg = -(s8)mvmsta->deflink.avg_energy;
|
||||
|
|
@ -5919,8 +5956,11 @@ void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
|
|||
if (iwl_mvm_request_statistics(mvm, false))
|
||||
goto unlock;
|
||||
|
||||
sinfo->rx_beacon = mvmvif->deflink.beacon_stats.num_beacons +
|
||||
mvmvif->deflink.beacon_stats.accu_num_beacons;
|
||||
sinfo->rx_beacon = 0;
|
||||
for_each_mvm_vif_valid_link(mvmvif, i)
|
||||
sinfo->rx_beacon += mvmvif->link[i]->beacon_stats.num_beacons +
|
||||
mvmvif->link[i]->beacon_stats.accu_num_beacons;
|
||||
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX);
|
||||
if (mvmvif->deflink.beacon_stats.avg_signal) {
|
||||
/* firmware only reports a value after RXing a few beacons */
|
||||
|
|
@ -6309,6 +6349,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
|
|||
|
||||
.can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
.vif_add_debugfs = iwl_mvm_vif_add_debugfs,
|
||||
.link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
|
||||
#endif
|
||||
.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
|
||||
|
|
|
|||
|
|
@ -24,10 +24,15 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* AP group keys are per link and should be on the mcast STA */
|
||||
/* AP group keys are per link and should be on the mcast/bcast STA */
|
||||
if (vif->type == NL80211_IFTYPE_AP &&
|
||||
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
/* IGTK/BIGTK to bcast STA */
|
||||
if (keyconf->keyidx >= 4)
|
||||
return BIT(link_info->bcast_sta.sta_id);
|
||||
/* GTK for data to mcast STA */
|
||||
return BIT(link_info->mcast_sta.sta_id);
|
||||
}
|
||||
|
||||
/* for client mode use the AP STA also for group keys */
|
||||
if (!sta && vif->type == NL80211_IFTYPE_STATION)
|
||||
|
|
@ -91,7 +96,12 @@ u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
|
|||
if (!sta && vif->type == NL80211_IFTYPE_STATION)
|
||||
sta = mvmvif->ap_sta;
|
||||
|
||||
if (!IS_ERR_OR_NULL(sta) && sta->mfp)
|
||||
/* Set the MFP flag also for an AP interface where the key is an IGTK
|
||||
* key as in such a case the station would always be NULL
|
||||
*/
|
||||
if ((!IS_ERR_OR_NULL(sta) && sta->mfp) ||
|
||||
(vif->type == NL80211_IFTYPE_AP &&
|
||||
(keyconf->keyidx == 4 || keyconf->keyidx == 5)))
|
||||
flags |= IWL_SEC_KEY_FLAG_MFP;
|
||||
|
||||
return flags;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
|||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
|
|
@ -22,8 +23,9 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
/* make sure that beacon statistics don't go backwards with FW reset */
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||
mvmvif->deflink.beacon_stats.accu_num_beacons +=
|
||||
mvmvif->deflink.beacon_stats.num_beacons;
|
||||
for_each_mvm_vif_valid_link(mvmvif, i)
|
||||
mvmvif->link[i]->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->link[i]->beacon_stats.num_beacons;
|
||||
|
||||
/* Allocate resources for the MAC context, and add it to the fw */
|
||||
ret = iwl_mvm_mac_ctxt_init(mvm, vif);
|
||||
|
|
@ -56,43 +58,15 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
|||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
}
|
||||
|
||||
/*
|
||||
* P2P_DEVICE interface does not have a channel context assigned to it,
|
||||
* so a dedicated PHY context is allocated to it and the corresponding
|
||||
* MAC context is bound to it at this stage.
|
||||
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
|
||||
if (ret)
|
||||
goto out_free_bf;
|
||||
|
||||
/* Save a pointer to p2p device vif, so it can later be used to
|
||||
* update the p2p device MAC when a GO is started/stopped
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
|
||||
if (!mvmvif->deflink.phy_ctxt) {
|
||||
ret = -ENOSPC;
|
||||
goto out_free_bf;
|
||||
}
|
||||
|
||||
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
|
||||
if (ret)
|
||||
goto out_unref_phy;
|
||||
|
||||
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
|
||||
LINK_CONTEXT_MODIFY_ACTIVE |
|
||||
LINK_CONTEXT_MODIFY_RATES_INFO,
|
||||
true);
|
||||
if (ret)
|
||||
goto out_remove_link;
|
||||
|
||||
ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
|
||||
if (ret)
|
||||
goto out_remove_link;
|
||||
|
||||
/* Save a pointer to p2p device vif, so it can later be used to
|
||||
* update the p2p device MAC when a GO is started/stopped
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
mvm->p2p_device_vif = vif;
|
||||
} else {
|
||||
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
|
||||
if (ret)
|
||||
goto out_free_bf;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_power_update_mac(mvm);
|
||||
if (ret)
|
||||
|
|
@ -107,7 +81,7 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
|||
ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
|
||||
}
|
||||
|
||||
iwl_mvm_vif_dbgfs_register(mvm, vif);
|
||||
iwl_mvm_vif_dbgfs_add_link(mvm, vif);
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
|
||||
|
|
@ -119,10 +93,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
goto out_unlock;
|
||||
|
||||
out_remove_link:
|
||||
iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
|
||||
out_unref_phy:
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
out_free_bf:
|
||||
if (mvm->bf_allowed_vif == mvmvif) {
|
||||
mvm->bf_allowed_vif = NULL;
|
||||
|
|
@ -130,7 +100,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
|||
IEEE80211_VIF_SUPPORTS_CQM_RSSI);
|
||||
}
|
||||
out_remove_mac:
|
||||
mvmvif->deflink.phy_ctxt = NULL;
|
||||
mvmvif->link[0] = NULL;
|
||||
iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
|
||||
out_unlock:
|
||||
|
|
@ -168,7 +137,7 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
if (vif->bss_conf.ftm_responder)
|
||||
memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats));
|
||||
|
||||
iwl_mvm_vif_dbgfs_clean(mvm, vif);
|
||||
iwl_mvm_vif_dbgfs_rm_link(mvm, vif);
|
||||
|
||||
/* For AP/GO interface, the tear down of the resources allocated to the
|
||||
* interface is be handled as part of the stop_ap flow.
|
||||
|
|
@ -185,14 +154,18 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
iwl_mvm_power_update_mac(mvm);
|
||||
|
||||
/* Before the interface removal, mac80211 would cancel the ROC, and the
|
||||
* ROC worker would be scheduled if needed. The worker would be flushed
|
||||
* in iwl_mvm_prepare_mac_removal() and thus at this point the link is
|
||||
* not active. So need only to remove the link.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
if (mvmvif->deflink.phy_ctxt) {
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
mvmvif->deflink.phy_ctxt = NULL;
|
||||
}
|
||||
mvm->p2p_device_vif = NULL;
|
||||
|
||||
/* P2P device uses only one link */
|
||||
iwl_mvm_mld_rm_bcast_sta(mvm, vif, &vif->bss_conf);
|
||||
iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
mvmvif->deflink.phy_ctxt = NULL;
|
||||
iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
|
||||
} else {
|
||||
iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
|
||||
}
|
||||
|
|
@ -240,8 +213,8 @@ static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
|
|||
|
||||
mvmvif->esr_active = true;
|
||||
|
||||
/* Disable SMPS overrideing by user */
|
||||
vif->driver_flags |= IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
|
||||
/* Indicate to mac80211 that EML is enabled */
|
||||
vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
|
||||
|
||||
iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
|
||||
IEEE80211_SMPS_OFF);
|
||||
|
|
@ -399,7 +372,7 @@ static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
|
|||
|
||||
mvmvif->esr_active = false;
|
||||
|
||||
vif->driver_flags &= ~IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
|
||||
vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
|
||||
|
||||
iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
|
||||
IEEE80211_SMPS_AUTOMATIC);
|
||||
|
|
@ -489,10 +462,17 @@ static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
__iwl_mvm_mld_unassign_vif_chanctx(mvm, vif, link_conf, ctx, false);
|
||||
/* in the non-MLD case, remove/re-add the link to clean up FW state */
|
||||
if (!ieee80211_vif_is_mld(vif) && !mvmvif->ap_sta &&
|
||||
!WARN_ON_ONCE(vif->cfg.assoc)) {
|
||||
iwl_mvm_remove_link(mvm, vif, link_conf);
|
||||
iwl_mvm_add_link(mvm, vif, link_conf);
|
||||
}
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
|
|
@ -623,6 +603,126 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
|
|||
&callbacks);
|
||||
}
|
||||
|
||||
struct iwl_mvm_link_sel_data {
|
||||
u8 link_id;
|
||||
enum nl80211_band band;
|
||||
bool active;
|
||||
};
|
||||
|
||||
static bool iwl_mvm_mld_valid_link_pair(struct iwl_mvm_link_sel_data *a,
|
||||
struct iwl_mvm_link_sel_data *b)
|
||||
{
|
||||
return a->band != b->band;
|
||||
}
|
||||
|
||||
void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool valid_links_changed)
|
||||
{
|
||||
struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
u32 max_active_links = iwl_mvm_max_active_links(mvm, vif);
|
||||
u16 new_active_links;
|
||||
u8 link_id, n_data = 0, i, j;
|
||||
|
||||
if (!IWL_MVM_AUTO_EML_ENABLE)
|
||||
return;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif) || usable_links == 1)
|
||||
return;
|
||||
|
||||
/* The logic below is a simple version that doesn't suit more than 2
|
||||
* links
|
||||
*/
|
||||
WARN_ON_ONCE(max_active_links > 2);
|
||||
|
||||
/* if only a single active link is supported, assume that the one
|
||||
* selected by higher layer for connection establishment is the best.
|
||||
*/
|
||||
if (max_active_links == 1 && !valid_links_changed)
|
||||
return;
|
||||
|
||||
/* If we are already using the maximal number of active links, don't do
|
||||
* any change. This can later be optimized to pick a 'better' link pair.
|
||||
*/
|
||||
if (hweight16(vif->active_links) == max_active_links)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_bss_conf *link_conf =
|
||||
rcu_dereference(vif->link_conf[link_id]);
|
||||
|
||||
if (WARN_ON_ONCE(!link_conf))
|
||||
continue;
|
||||
|
||||
data[n_data].link_id = link_id;
|
||||
data[n_data].band = link_conf->chandef.chan->band;
|
||||
data[n_data].active = vif->active_links & BIT(link_id);
|
||||
n_data++;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
/* this is expected to be the current active link */
|
||||
if (n_data == 1)
|
||||
return;
|
||||
|
||||
new_active_links = 0;
|
||||
|
||||
/* Assume that after association only a single link is active, thus,
|
||||
* select only the 2nd link
|
||||
*/
|
||||
if (!valid_links_changed) {
|
||||
for (i = 0; i < n_data; i++) {
|
||||
if (data[i].active)
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(i == n_data))
|
||||
return;
|
||||
|
||||
for (j = 0; j < n_data; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
if (iwl_mvm_mld_valid_link_pair(&data[i], &data[j]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (j != n_data)
|
||||
new_active_links = BIT(data[i].link_id) |
|
||||
BIT(data[j].link_id);
|
||||
} else {
|
||||
/* Try to find a valid link pair for EMLSR operation. If a pair
|
||||
* is not found continue using the current active link.
|
||||
*/
|
||||
for (i = 0; i < n_data; i++) {
|
||||
for (j = 0; j < n_data; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
if (iwl_mvm_mld_valid_link_pair(&data[i],
|
||||
&data[j]))
|
||||
break;
|
||||
}
|
||||
|
||||
/* found a valid pair for EMLSR, use it */
|
||||
if (j != n_data) {
|
||||
new_active_links = BIT(data[i].link_id) |
|
||||
BIT(data[j].link_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(!new_active_links))
|
||||
return;
|
||||
|
||||
if (vif->active_links != new_active_links)
|
||||
ieee80211_set_active_links_async(vif, new_active_links);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
|
|
@ -653,7 +753,7 @@ iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
/* Update EHT Puncturing info */
|
||||
if (changes & BSS_CHANGED_EHT_PUNCTURING && vif->cfg.assoc && has_eht)
|
||||
if (changes & BSS_CHANGED_EHT_PUNCTURING && vif->cfg.assoc)
|
||||
link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
|
||||
|
||||
if (link_changes) {
|
||||
|
|
@ -667,6 +767,9 @@ iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
|
|||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
|
||||
|
||||
if (changes & BSS_CHANGED_MLD_VALID_LINKS)
|
||||
iwl_mvm_mld_select_links(mvm, vif, true);
|
||||
|
||||
memcpy(mvmvif->link[link_conf->link_id]->bssid, link_conf->bssid,
|
||||
ETH_ALEN);
|
||||
|
||||
|
|
@ -757,6 +860,12 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
|
|||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
protect) {
|
||||
/* We are in assoc so only one link is active-
|
||||
* The association link
|
||||
*/
|
||||
unsigned int link_id =
|
||||
ffs(vif->active_links) - 1;
|
||||
|
||||
/* If we're not restarting and still haven't
|
||||
* heard a beacon (dtim period unknown) then
|
||||
* make sure we still have enough minimum time
|
||||
|
|
@ -766,7 +875,7 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
|
|||
* time could be small without us having heard
|
||||
* a beacon yet.
|
||||
*/
|
||||
iwl_mvm_protect_assoc(mvm, vif, 0);
|
||||
iwl_mvm_protect_assoc(mvm, vif, 0, link_id);
|
||||
}
|
||||
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
|
|
@ -968,36 +1077,29 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_link_switch_phy_ctx(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_phy_ctxt *new_phy_ctxt)
|
||||
static int iwl_mvm_mld_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* Inorder to change the phy_ctx of a link, the link needs to be
|
||||
* inactive. Therefore, first deactivate the link, then change its
|
||||
* phy_ctx, and then activate it again.
|
||||
*/
|
||||
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
|
||||
LINK_CONTEXT_MODIFY_ACTIVE, false);
|
||||
if (WARN(ret, "Failed to deactivate link\n"))
|
||||
return ret;
|
||||
|
||||
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
|
||||
|
||||
mvmvif->deflink.phy_ctxt = new_phy_ctxt;
|
||||
|
||||
/* The PHY context ID might have changed so need to set it */
|
||||
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
|
||||
if (WARN(ret, "Failed to deactivate link\n"))
|
||||
if (WARN(ret, "Failed to set PHY context ID\n"))
|
||||
return ret;
|
||||
|
||||
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
|
||||
LINK_CONTEXT_MODIFY_ACTIVE, true);
|
||||
WARN(ret, "Failed binding P2P_DEVICE\n");
|
||||
return ret;
|
||||
LINK_CONTEXT_MODIFY_ACTIVE |
|
||||
LINK_CONTEXT_MODIFY_RATES_INFO,
|
||||
true);
|
||||
|
||||
if (WARN(ret, "Failed linking P2P_DEVICE\n"))
|
||||
return ret;
|
||||
|
||||
/* The station and queue allocation must be done only after the linking
|
||||
* is done, as otherwise the FW might incorrectly configure its state.
|
||||
*/
|
||||
return iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
|
@ -1006,7 +1108,7 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
{
|
||||
static const struct iwl_mvm_roc_ops ops = {
|
||||
.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
|
||||
.switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx,
|
||||
.link = iwl_mvm_mld_roc_link,
|
||||
};
|
||||
|
||||
return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
|
||||
|
|
@ -1173,8 +1275,6 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
|
|||
|
||||
.tx_last_beacon = iwl_mvm_tx_last_beacon,
|
||||
|
||||
.set_tim = iwl_mvm_set_tim,
|
||||
|
||||
.channel_switch = iwl_mvm_channel_switch,
|
||||
.pre_channel_switch = iwl_mvm_pre_channel_switch,
|
||||
.post_channel_switch = iwl_mvm_post_channel_switch,
|
||||
|
|
@ -1209,6 +1309,8 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
|
|||
.abort_pmsr = iwl_mvm_abort_pmsr,
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
.vif_add_debugfs = iwl_mvm_vif_add_debugfs,
|
||||
.link_add_debugfs = iwl_mvm_link_add_debugfs,
|
||||
.link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
|
||||
#endif
|
||||
.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ static int iwl_mvm_mld_rm_int_sta(struct iwl_mvm *mvm,
|
|||
return -EINVAL;
|
||||
|
||||
if (flush)
|
||||
iwl_mvm_flush_sta(mvm, int_sta, true);
|
||||
iwl_mvm_flush_sta(mvm, int_sta->sta_id, int_sta->tfd_queue_msk);
|
||||
|
||||
iwl_mvm_mld_disable_txq(mvm, BIT(int_sta->sta_id), queuptr, tid);
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ struct iwl_mvm_time_event_data {
|
|||
* if the te is in the time event list or not (when id == TE_MAX)
|
||||
*/
|
||||
u32 id;
|
||||
u8 link_id;
|
||||
};
|
||||
|
||||
/* Power management */
|
||||
|
|
@ -646,18 +647,9 @@ struct iwl_mvm_tcm {
|
|||
* @queue: queue of this reorder buffer
|
||||
* @last_amsdu: track last ASMDU SN for duplication detection
|
||||
* @last_sub_index: track ASMDU sub frame index for duplication detection
|
||||
* @reorder_timer: timer for frames are in the reorder buffer. For AMSDU
|
||||
* it is the time of last received sub-frame
|
||||
* @removed: prevent timer re-arming
|
||||
* @valid: reordering is valid for this queue
|
||||
* @lock: protect reorder buffer internal state
|
||||
* @mvm: mvm pointer, needed for frame timer context
|
||||
* @consec_oldsn_drops: consecutive drops due to old SN
|
||||
* @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track
|
||||
* when to apply old SN consecutive drop workaround
|
||||
* @consec_oldsn_prev_drop: track whether or not an MPDU
|
||||
* that was single/part of the previous A-MPDU was
|
||||
* dropped due to old SN
|
||||
*/
|
||||
struct iwl_mvm_reorder_buffer {
|
||||
u16 head_sn;
|
||||
|
|
@ -666,33 +658,21 @@ struct iwl_mvm_reorder_buffer {
|
|||
int queue;
|
||||
u16 last_amsdu;
|
||||
u8 last_sub_index;
|
||||
struct timer_list reorder_timer;
|
||||
bool removed;
|
||||
bool valid;
|
||||
spinlock_t lock;
|
||||
struct iwl_mvm *mvm;
|
||||
unsigned int consec_oldsn_drops;
|
||||
u32 consec_oldsn_ampdu_gp2;
|
||||
unsigned int consec_oldsn_prev_drop:1;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
/**
|
||||
* struct _iwl_mvm_reorder_buf_entry - reorder buffer entry per-queue/per-seqno
|
||||
* struct iwl_mvm_reorder_buf_entry - reorder buffer entry per-queue/per-seqno
|
||||
* @frames: list of skbs stored
|
||||
* @reorder_time: time the packet was stored in the reorder buffer
|
||||
*/
|
||||
struct _iwl_mvm_reorder_buf_entry {
|
||||
struct sk_buff_head frames;
|
||||
unsigned long reorder_time;
|
||||
};
|
||||
|
||||
/* make this indirection to get the aligned thing */
|
||||
struct iwl_mvm_reorder_buf_entry {
|
||||
struct _iwl_mvm_reorder_buf_entry e;
|
||||
struct sk_buff_head frames;
|
||||
}
|
||||
#ifndef __CHECKER__
|
||||
/* sparse doesn't like this construct: "bad integer constant expression" */
|
||||
__aligned(roundup_pow_of_two(sizeof(struct _iwl_mvm_reorder_buf_entry)))
|
||||
__aligned(roundup_pow_of_two(sizeof(struct sk_buff_head)))
|
||||
#endif
|
||||
;
|
||||
|
||||
|
|
@ -1214,6 +1194,8 @@ struct iwl_mvm {
|
|||
struct iwl_time_sync_data time_sync;
|
||||
|
||||
struct iwl_mei_scan_filter mei_scan_filter;
|
||||
|
||||
bool statistics_clear;
|
||||
};
|
||||
|
||||
/* Extract MVM priv from op_mode and _hw */
|
||||
|
|
@ -1674,7 +1656,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status);
|
|||
static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }
|
||||
#endif
|
||||
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk);
|
||||
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal);
|
||||
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, u32 sta_id, u32 tfd_queue_mask);
|
||||
int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids);
|
||||
|
||||
/* Utils to extract sta related data */
|
||||
|
|
@ -1705,6 +1687,16 @@ static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm)
|
|||
}
|
||||
|
||||
/* Statistics */
|
||||
void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
static inline void
|
||||
iwl_mvm_handle_rx_system_end_stats_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt);
|
||||
void iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
|
||||
|
|
@ -1921,41 +1913,10 @@ void iwl_mvm_stop_ap_ibss_common(struct iwl_mvm *mvm,
|
|||
struct ieee80211_vif *vif);
|
||||
|
||||
/* BSS Info */
|
||||
/**
|
||||
* struct iwl_mvm_bss_info_changed_ops - callbacks for the bss_info_changed()
|
||||
*
|
||||
* Since the only difference between both MLD and
|
||||
* non-MLD versions of bss_info_changed() is these function calls,
|
||||
* each version will send its specific function calls to
|
||||
* %iwl_mvm_bss_info_changed_common().
|
||||
*
|
||||
* @bss_info_changed_sta: pointer to the function that handles changes
|
||||
* in bss_info in sta mode
|
||||
* @bss_info_changed_ap_ibss: pointer to the function that handles changes
|
||||
* in bss_info in ap and ibss modes
|
||||
*/
|
||||
struct iwl_mvm_bss_info_changed_ops {
|
||||
void (*bss_info_changed_sta)(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u64 changes);
|
||||
void (*bss_info_changed_ap_ibss)(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u64 changes);
|
||||
};
|
||||
|
||||
void
|
||||
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
const struct iwl_mvm_bss_info_changed_ops *callbacks,
|
||||
u64 changes);
|
||||
void
|
||||
iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
u64 changes);
|
||||
void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
u64 changes);
|
||||
void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u64 changes);
|
||||
|
|
@ -1971,13 +1932,12 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
|
|||
*
|
||||
* @add_aux_sta_for_hs20: pointer to the function that adds an aux sta
|
||||
* for Hot Spot 2.0
|
||||
* @switch_phy_ctxt: pointer to the function that switches a vif from one
|
||||
* phy_ctx to another
|
||||
* @link: For a P2P Device interface, pointer to a function that links the
|
||||
* MAC/Link to the PHY context
|
||||
*/
|
||||
struct iwl_mvm_roc_ops {
|
||||
int (*add_aux_sta_for_hs20)(struct iwl_mvm *mvm, u32 lmac_id);
|
||||
int (*switch_phy_ctxt)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_phy_ctxt *new_phy_ctxt);
|
||||
int (*link)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
};
|
||||
|
||||
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
|
@ -1988,7 +1948,7 @@ int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
|
|||
struct ieee80211_vif *vif);
|
||||
/*Session Protection */
|
||||
void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
u32 duration_override);
|
||||
u32 duration_override, unsigned int link_id);
|
||||
|
||||
/* Quota management */
|
||||
static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm)
|
||||
|
|
@ -2048,18 +2008,19 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
|
|||
/* MVM debugfs */
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_vif_dbgfs_rm_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
#else
|
||||
static inline void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
static inline void
|
||||
iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
}
|
||||
static inline void
|
||||
iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
iwl_mvm_vif_dbgfs_rm_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
|
|
@ -2292,7 +2253,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
|
|||
bool *changed);
|
||||
struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm,
|
||||
bool *changed);
|
||||
int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm, bool force_regd_sync);
|
||||
void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm);
|
||||
|
||||
/* smart fifo */
|
||||
|
|
@ -2345,7 +2306,8 @@ void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm);
|
|||
void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool sta_added);
|
||||
void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
struct ieee80211_vif *vif,
|
||||
unsigned int link_id);
|
||||
int iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u8 oper_class,
|
||||
|
|
@ -2364,7 +2326,6 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
|
|||
enum iwl_mvm_rxq_notif_type type,
|
||||
bool sync,
|
||||
const void *data, u32 size);
|
||||
void iwl_mvm_reorder_timer_expired(struct timer_list *t);
|
||||
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
|
||||
struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid);
|
||||
bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm);
|
||||
|
|
@ -2404,6 +2365,10 @@ void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw,
|
|||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct dentry *dir);
|
||||
void iwl_mvm_link_add_debugfs(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct dentry *dir);
|
||||
#endif
|
||||
|
||||
/* new MLD related APIs */
|
||||
|
|
@ -2713,8 +2678,6 @@ void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
|
|||
void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx, u32 changed);
|
||||
int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw);
|
||||
int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set);
|
||||
void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw);
|
||||
int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
|
|
@ -2758,4 +2721,6 @@ int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
|
|||
int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
bool iwl_mvm_enable_fils(struct iwl_mvm *mvm,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool valid_links_changed);
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
|
|
|||
|
|
@ -573,7 +573,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
|
|||
* try to replay the last set MCC to FW. If it doesn't exist,
|
||||
* queue an update to cfg80211 to retrieve the default alpha2 from FW.
|
||||
*/
|
||||
retval = iwl_mvm_init_fw_regd(mvm);
|
||||
retval = iwl_mvm_init_fw_regd(mvm, true);
|
||||
if (retval != -ENOENT)
|
||||
return retval;
|
||||
|
||||
|
|
|
|||
|
|
@ -322,6 +322,19 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
RX_HANDLER_NO_SIZE(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics,
|
||||
RX_HANDLER_ASYNC_LOCKED),
|
||||
|
||||
RX_HANDLER_GRP(STATISTICS_GROUP, STATISTICS_OPER_NOTIF,
|
||||
iwl_mvm_handle_rx_system_oper_stats,
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_system_statistics_notif_oper),
|
||||
RX_HANDLER_GRP(STATISTICS_GROUP, STATISTICS_OPER_PART1_NOTIF,
|
||||
iwl_mvm_handle_rx_system_oper_part1_stats,
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_system_statistics_part1_notif_oper),
|
||||
RX_HANDLER_GRP(SYSTEM_GROUP, SYSTEM_STATISTICS_END_NOTIF,
|
||||
iwl_mvm_handle_rx_system_end_stats_notif,
|
||||
RX_HANDLER_ASYNC_LOCKED,
|
||||
struct iwl_system_statistics_end_notif),
|
||||
|
||||
RX_HANDLER(BA_WINDOW_STATUS_NOTIFICATION_ID,
|
||||
iwl_mvm_window_status_notif, RX_HANDLER_SYNC,
|
||||
struct iwl_ba_window_status_notif),
|
||||
|
|
@ -426,6 +439,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION,
|
||||
iwl_mvm_time_sync_msmt_confirm_event, RX_HANDLER_SYNC,
|
||||
struct iwl_time_msmt_cfm_notify),
|
||||
RX_HANDLER_GRP(MAC_CONF_GROUP, ROC_NOTIF,
|
||||
iwl_mvm_rx_roc_notif, RX_HANDLER_SYNC,
|
||||
struct iwl_roc_notif),
|
||||
};
|
||||
#undef RX_HANDLER
|
||||
#undef RX_HANDLER_GRP
|
||||
|
|
@ -535,6 +551,8 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
|||
HCMD_NAME(RFI_GET_FREQ_TABLE_CMD),
|
||||
HCMD_NAME(SYSTEM_FEATURES_CONTROL_CMD),
|
||||
HCMD_NAME(RFI_DEACTIVATE_NOTIF),
|
||||
HCMD_NAME(SYSTEM_STATISTICS_CMD),
|
||||
HCMD_NAME(SYSTEM_STATISTICS_END_NOTIF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
|
|
@ -549,6 +567,8 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
|
|||
HCMD_NAME(AUX_STA_CMD),
|
||||
HCMD_NAME(STA_REMOVE_CMD),
|
||||
HCMD_NAME(STA_DISABLE_TX_CMD),
|
||||
HCMD_NAME(ROC_CMD),
|
||||
HCMD_NAME(ROC_NOTIF),
|
||||
HCMD_NAME(SESSION_PROTECTION_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),
|
||||
};
|
||||
|
|
@ -586,6 +606,14 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(RX_QUEUES_NOTIFICATION),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_statistics_names[] = {
|
||||
HCMD_NAME(STATISTICS_OPER_NOTIF),
|
||||
HCMD_NAME(STATISTICS_OPER_PART1_NOTIF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
|
|
@ -640,6 +668,7 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
|
|||
[PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names),
|
||||
[REGULATORY_AND_NVM_GROUP] =
|
||||
HCMD_ARR(iwl_mvm_regulatory_and_nvm_names),
|
||||
[STATISTICS_GROUP] = HCMD_ARR(iwl_mvm_statistics_names),
|
||||
};
|
||||
|
||||
/* this forward declaration can avoid to export the function */
|
||||
|
|
@ -1304,7 +1333,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
|
||||
snprintf(mvm->hw->wiphy->fw_version,
|
||||
sizeof(mvm->hw->wiphy->fw_version),
|
||||
"%s", fw->fw_version);
|
||||
"%.31s", fw->fw_version);
|
||||
|
||||
trans_cfg.fw_reset_handshake = fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE);
|
||||
|
|
@ -1950,9 +1979,6 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode, bool sync)
|
|||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
if (mvm->pldr_sync)
|
||||
return;
|
||||
|
||||
if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) &&
|
||||
!test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
|
||||
&mvm->status))
|
||||
|
|
|
|||
|
|
@ -192,6 +192,9 @@ int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd.rlc.rx_chain_info,
|
||||
chains_static, chains_dynamic);
|
||||
|
||||
IWL_DEBUG_FW(mvm, "Send RLC command: phy=%d, rx_chain_info=0x%x\n",
|
||||
ctxt->id, cmd.rlc.rx_chain_info);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(RLC_CONFIG_CMD,
|
||||
DATA_PATH_GROUP, 2),
|
||||
0, sizeof(cmd), &cmd);
|
||||
|
|
@ -265,6 +268,8 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
struct cfg80211_chan_def *chandef,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
ctxt->ref);
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
|
@ -273,9 +278,16 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
ctxt->width = chandef->width;
|
||||
ctxt->center_freq1 = chandef->center_freq1;
|
||||
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
FW_CTXT_ACTION_ADD);
|
||||
ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
FW_CTXT_ACTION_ADD);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctxt->ref++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -285,6 +297,11 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||
{
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* If we were taking the first ref, we should have
|
||||
* called iwl_mvm_phy_ctxt_add.
|
||||
*/
|
||||
WARN_ON(!ctxt->ref);
|
||||
ctxt->ref++;
|
||||
}
|
||||
|
||||
|
|
@ -301,7 +318,11 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, RLC_CONFIG_CMD), 0) >= 2 &&
|
||||
if (WARN_ON_ONCE(!ctxt->ref))
|
||||
return -EINVAL;
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD), 0) >= 2 &&
|
||||
ctxt->channel == chandef->chan &&
|
||||
ctxt->width == chandef->width &&
|
||||
ctxt->center_freq1 == chandef->center_freq1)
|
||||
|
|
@ -335,6 +356,7 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
|||
|
||||
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||
{
|
||||
struct cfg80211_chan_def chandef;
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (WARN_ON_ONCE(!ctxt))
|
||||
|
|
@ -342,41 +364,13 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
|||
|
||||
ctxt->ref--;
|
||||
|
||||
/*
|
||||
* Move unused phy's to a default channel. When the phy is moved the,
|
||||
* fw will cleanup immediate quiet bit if it was previously set,
|
||||
* otherwise we might not be able to reuse this phy.
|
||||
*/
|
||||
if (ctxt->ref == 0) {
|
||||
struct ieee80211_channel *chan = NULL;
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum nl80211_band band;
|
||||
int channel;
|
||||
if (ctxt->ref)
|
||||
return;
|
||||
|
||||
for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
|
||||
sband = mvm->hw->wiphy->bands[band];
|
||||
cfg80211_chandef_create(&chandef, ctxt->channel, NL80211_CHAN_NO_HT);
|
||||
|
||||
if (!sband)
|
||||
continue;
|
||||
|
||||
for (channel = 0; channel < sband->n_channels; channel++)
|
||||
if (!(sband->channels[channel].flags &
|
||||
IEEE80211_CHAN_DISABLED)) {
|
||||
chan = &sband->channels[channel];
|
||||
break;
|
||||
}
|
||||
|
||||
if (chan)
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON(!chan))
|
||||
return;
|
||||
|
||||
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
|
||||
iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1);
|
||||
}
|
||||
iwl_mvm_phy_ctxt_apply(mvm, ctxt, &chandef, 1, 1,
|
||||
FW_CTXT_ACTION_REMOVE);
|
||||
}
|
||||
|
||||
static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
|
||||
|
|
|
|||
|
|
@ -553,7 +553,7 @@ struct iwl_mvm_stat_data {
|
|||
struct iwl_mvm_stat_data_all_macs {
|
||||
struct iwl_mvm *mvm;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac *per_mac_stats;
|
||||
struct iwl_stats_ntfy_per_mac *per_mac;
|
||||
};
|
||||
|
||||
static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
|
||||
|
|
@ -658,7 +658,7 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_stat_data_all_macs *data = _data;
|
||||
struct iwl_statistics_ntfy_per_mac *mac_stats;
|
||||
struct iwl_stats_ntfy_per_mac *mac_stats;
|
||||
int sig;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
|
@ -669,7 +669,7 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
|||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
mac_stats = &data->per_mac_stats[vif_id];
|
||||
mac_stats = &data->per_mac[vif_id];
|
||||
|
||||
mvmvif->deflink.beacon_stats.num_beacons =
|
||||
le32_to_cpu(mac_stats->beacon_counter);
|
||||
|
|
@ -759,7 +759,7 @@ iwl_mvm_stats_ver_15(struct iwl_mvm *mvm,
|
|||
struct iwl_mvm_stat_data_all_macs data = {
|
||||
.mvm = mvm,
|
||||
.flags = stats->flags,
|
||||
.per_mac_stats = stats->per_mac_stats,
|
||||
.per_mac = stats->per_mac,
|
||||
};
|
||||
|
||||
ieee80211_iterate_active_interfaces(mvm->hw,
|
||||
|
|
@ -828,6 +828,142 @@ static bool iwl_mvm_verify_stats_len(struct iwl_mvm *mvm,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
|
||||
struct iwl_stats_ntfy_per_link *per_link)
|
||||
{
|
||||
u32 air_time[MAC_INDEX_AUX] = {};
|
||||
u32 rx_bytes[MAC_INDEX_AUX] = {};
|
||||
int fw_link_id;
|
||||
|
||||
for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->link_id_to_link_conf);
|
||||
fw_link_id++) {
|
||||
struct iwl_stats_ntfy_per_link *link_stats;
|
||||
struct ieee80211_bss_conf *bss_conf;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
int link_id;
|
||||
int sig;
|
||||
|
||||
bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id,
|
||||
false);
|
||||
if (!bss_conf)
|
||||
continue;
|
||||
|
||||
if (bss_conf->vif->type != NL80211_IFTYPE_STATION)
|
||||
continue;
|
||||
|
||||
link_id = bss_conf->link_id;
|
||||
if (link_id >= ARRAY_SIZE(mvmvif->link))
|
||||
continue;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(bss_conf->vif);
|
||||
if (!mvmvif || !mvmvif->link[link_id])
|
||||
continue;
|
||||
|
||||
link_stats = &per_link[fw_link_id];
|
||||
|
||||
mvmvif->link[link_id]->beacon_stats.num_beacons =
|
||||
le32_to_cpu(link_stats->beacon_counter);
|
||||
|
||||
/* we basically just use the u8 to store 8 bits and then treat
|
||||
* it as a s8 whenever we take it out to a different type.
|
||||
*/
|
||||
mvmvif->link[link_id]->beacon_stats.avg_signal =
|
||||
-le32_to_cpu(link_stats->beacon_average_energy);
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (mvm->statistics_clear)
|
||||
mvmvif->link[link_id]->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->link[link_id]->beacon_stats.num_beacons;
|
||||
|
||||
sig = -le32_to_cpu(link_stats->beacon_filter_average_energy);
|
||||
iwl_mvm_update_vif_sig(bss_conf->vif, sig);
|
||||
|
||||
if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX,
|
||||
"invalid mvmvif id: %d", mvmvif->id))
|
||||
continue;
|
||||
|
||||
air_time[mvmvif->id] +=
|
||||
le32_to_cpu(per_link[fw_link_id].air_time);
|
||||
rx_bytes[mvmvif->id] +=
|
||||
le32_to_cpu(per_link[fw_link_id].rx_bytes);
|
||||
}
|
||||
|
||||
/* Don't update in case the statistics are not cleared, since
|
||||
* we will end up counting twice the same airtime, once in TCM
|
||||
* request and once in statistics notification.
|
||||
*/
|
||||
if (mvm->statistics_clear) {
|
||||
__le32 air_time_le[MAC_INDEX_AUX];
|
||||
__le32 rx_bytes_le[MAC_INDEX_AUX];
|
||||
int vif_id;
|
||||
|
||||
for (vif_id = 0; vif_id < ARRAY_SIZE(air_time_le); vif_id++) {
|
||||
air_time_le[vif_id] = cpu_to_le32(air_time[vif_id]);
|
||||
rx_bytes_le[vif_id] = cpu_to_le32(rx_bytes[vif_id]);
|
||||
}
|
||||
|
||||
iwl_mvm_update_tcm_from_stats(mvm, air_time_le, rx_bytes_le);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_system_statistics_notif_oper *stats;
|
||||
int i;
|
||||
u32 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_NOTIF, 0);
|
||||
|
||||
if (notif_ver != 3) {
|
||||
IWL_FW_CHECK_FAILED(mvm,
|
||||
"Oper stats notif ver %d is not supported\n",
|
||||
notif_ver);
|
||||
return;
|
||||
}
|
||||
|
||||
stats = (void *)&pkt->data;
|
||||
iwl_mvm_stat_iterator_all_links(mvm, stats->per_link);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] =
|
||||
le32_to_cpu(stats->per_sta[i].average_energy);
|
||||
|
||||
ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter,
|
||||
average_energy);
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_system_statistics_part1_notif_oper *part1_stats;
|
||||
int i;
|
||||
u32 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, STATISTICS_GROUP,
|
||||
STATISTICS_OPER_PART1_NOTIF, 0);
|
||||
|
||||
if (notif_ver != 4) {
|
||||
IWL_FW_CHECK_FAILED(mvm,
|
||||
"Part1 stats notif ver %d is not supported\n",
|
||||
notif_ver);
|
||||
return;
|
||||
}
|
||||
|
||||
part1_stats = (void *)&pkt->data;
|
||||
mvm->radio_stats.rx_time = 0;
|
||||
mvm->radio_stats.tx_time = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(part1_stats->per_link); i++) {
|
||||
mvm->radio_stats.rx_time +=
|
||||
le64_to_cpu(part1_stats->per_link[i].rx_time);
|
||||
mvm->radio_stats.tx_time +=
|
||||
le64_to_cpu(part1_stats->per_link[i].tx_time);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
|
|
@ -887,11 +1023,11 @@ iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] =
|
||||
le32_to_cpu(stats->per_sta_stats[i].average_energy);
|
||||
le32_to_cpu(stats->per_sta[i].average_energy);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(air_time); i++) {
|
||||
air_time[i] = stats->per_mac_stats[i].air_time;
|
||||
rx_bytes[i] = stats->per_mac_stats[i].rx_bytes;
|
||||
air_time[i] = stats->per_mac[i].air_time;
|
||||
rx_bytes[i] = stats->per_mac[i].rx_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -917,6 +1053,13 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
|||
__le32 *bytes, *air_time, flags;
|
||||
int expected_size;
|
||||
u8 *energy;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
|
||||
WIDE_ID(SYSTEM_GROUP,
|
||||
SYSTEM_STATISTICS_CMD),
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
|
||||
return;
|
||||
|
||||
/* From ver 14 and up we use TLV statistics format */
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
|
|
|
|||
|
|
@ -550,44 +550,12 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if sn2 - buffer_size < sn1 < sn2.
|
||||
* To be used only in order to compare reorder buffer head with NSSN.
|
||||
* We fully trust NSSN unless it is behind us due to reorder timeout.
|
||||
* Reorder timeout can only bring us up to buffer_size SNs ahead of NSSN.
|
||||
*/
|
||||
static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
|
||||
{
|
||||
return ieee80211_sn_less(sn1, sn2) &&
|
||||
!ieee80211_sn_less(sn1, sn2 - buffer_size);
|
||||
}
|
||||
|
||||
static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
|
||||
{
|
||||
if (IWL_MVM_USE_NSSN_SYNC) {
|
||||
struct iwl_mvm_nssn_sync_data notif = {
|
||||
.baid = baid,
|
||||
.nssn = nssn,
|
||||
};
|
||||
|
||||
iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NSSN_SYNC, false,
|
||||
¬if, sizeof(notif));
|
||||
}
|
||||
}
|
||||
|
||||
#define RX_REORDER_BUF_TIMEOUT_MQ (HZ / 10)
|
||||
|
||||
enum iwl_mvm_release_flags {
|
||||
IWL_MVM_RELEASE_SEND_RSS_SYNC = BIT(0),
|
||||
IWL_MVM_RELEASE_FROM_RSS_SYNC = BIT(1),
|
||||
};
|
||||
|
||||
static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
struct napi_struct *napi,
|
||||
struct iwl_mvm_baid_data *baid_data,
|
||||
struct iwl_mvm_reorder_buffer *reorder_buf,
|
||||
u16 nssn, u32 flags)
|
||||
u16 nssn)
|
||||
{
|
||||
struct iwl_mvm_reorder_buf_entry *entries =
|
||||
&baid_data->entries[reorder_buf->queue *
|
||||
|
|
@ -596,31 +564,12 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
|||
|
||||
lockdep_assert_held(&reorder_buf->lock);
|
||||
|
||||
/*
|
||||
* We keep the NSSN not too far behind, if we are sync'ing it and it
|
||||
* is more than 2048 ahead of us, it must be behind us. Discard it.
|
||||
* This can happen if the queue that hit the 0 / 2048 seqno was lagging
|
||||
* behind and this queue already processed packets. The next if
|
||||
* would have caught cases where this queue would have processed less
|
||||
* than 64 packets, but it may have processed more than 64 packets.
|
||||
*/
|
||||
if ((flags & IWL_MVM_RELEASE_FROM_RSS_SYNC) &&
|
||||
ieee80211_sn_less(nssn, ssn))
|
||||
goto set_timer;
|
||||
|
||||
/* ignore nssn smaller than head sn - this can happen due to timeout */
|
||||
if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size))
|
||||
goto set_timer;
|
||||
|
||||
while (iwl_mvm_is_sn_less(ssn, nssn, reorder_buf->buf_size)) {
|
||||
while (ieee80211_sn_less(ssn, nssn)) {
|
||||
int index = ssn % reorder_buf->buf_size;
|
||||
struct sk_buff_head *skb_list = &entries[index].e.frames;
|
||||
struct sk_buff_head *skb_list = &entries[index].frames;
|
||||
struct sk_buff *skb;
|
||||
|
||||
ssn = ieee80211_sn_inc(ssn);
|
||||
if ((flags & IWL_MVM_RELEASE_SEND_RSS_SYNC) &&
|
||||
(ssn == 2048 || ssn == 0))
|
||||
iwl_mvm_sync_nssn(mvm, baid_data->baid, ssn);
|
||||
|
||||
/*
|
||||
* Empty the list. Will have more than one frame for A-MSDU.
|
||||
|
|
@ -635,99 +584,6 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
|||
}
|
||||
}
|
||||
reorder_buf->head_sn = nssn;
|
||||
|
||||
set_timer:
|
||||
if (reorder_buf->num_stored && !reorder_buf->removed) {
|
||||
u16 index = reorder_buf->head_sn % reorder_buf->buf_size;
|
||||
|
||||
while (skb_queue_empty(&entries[index].e.frames))
|
||||
index = (index + 1) % reorder_buf->buf_size;
|
||||
/* modify timer to match next frame's expiration time */
|
||||
mod_timer(&reorder_buf->reorder_timer,
|
||||
entries[index].e.reorder_time + 1 +
|
||||
RX_REORDER_BUF_TIMEOUT_MQ);
|
||||
} else {
|
||||
del_timer(&reorder_buf->reorder_timer);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_reorder_timer_expired(struct timer_list *t)
|
||||
{
|
||||
struct iwl_mvm_reorder_buffer *buf = from_timer(buf, t, reorder_timer);
|
||||
struct iwl_mvm_baid_data *baid_data =
|
||||
iwl_mvm_baid_data_from_reorder_buf(buf);
|
||||
struct iwl_mvm_reorder_buf_entry *entries =
|
||||
&baid_data->entries[buf->queue * baid_data->entries_per_queue];
|
||||
int i;
|
||||
u16 sn = 0, index = 0;
|
||||
bool expired = false;
|
||||
bool cont = false;
|
||||
|
||||
spin_lock(&buf->lock);
|
||||
|
||||
if (!buf->num_stored || buf->removed) {
|
||||
spin_unlock(&buf->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < buf->buf_size ; i++) {
|
||||
index = (buf->head_sn + i) % buf->buf_size;
|
||||
|
||||
if (skb_queue_empty(&entries[index].e.frames)) {
|
||||
/*
|
||||
* If there is a hole and the next frame didn't expire
|
||||
* we want to break and not advance SN
|
||||
*/
|
||||
cont = false;
|
||||
continue;
|
||||
}
|
||||
if (!cont &&
|
||||
!time_after(jiffies, entries[index].e.reorder_time +
|
||||
RX_REORDER_BUF_TIMEOUT_MQ))
|
||||
break;
|
||||
|
||||
expired = true;
|
||||
/* continue until next hole after this expired frames */
|
||||
cont = true;
|
||||
sn = ieee80211_sn_add(buf->head_sn, i + 1);
|
||||
}
|
||||
|
||||
if (expired) {
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
u8 sta_id = ffs(baid_data->sta_mask) - 1;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
|
||||
rcu_read_unlock();
|
||||
goto out;
|
||||
}
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
/* SN is set to the last expired frame + 1 */
|
||||
IWL_DEBUG_HT(buf->mvm,
|
||||
"Releasing expired frames for sta %u, sn %d\n",
|
||||
sta_id, sn);
|
||||
iwl_mvm_event_frame_timeout_callback(buf->mvm, mvmsta->vif,
|
||||
sta, baid_data->tid);
|
||||
iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data,
|
||||
buf, sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
/*
|
||||
* If no frame expired and there are stored frames, index is now
|
||||
* pointing to the first unexpired frame - modify timer
|
||||
* accordingly to this frame.
|
||||
*/
|
||||
mod_timer(&buf->reorder_timer,
|
||||
entries[index].e.reorder_time +
|
||||
1 + RX_REORDER_BUF_TIMEOUT_MQ);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&buf->lock);
|
||||
}
|
||||
|
||||
static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
|
||||
|
|
@ -760,10 +616,8 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
|
|||
spin_lock_bh(&reorder_buf->lock);
|
||||
iwl_mvm_release_frames(mvm, sta, NULL, ba_data, reorder_buf,
|
||||
ieee80211_sn_add(reorder_buf->head_sn,
|
||||
reorder_buf->buf_size),
|
||||
0);
|
||||
reorder_buf->buf_size));
|
||||
spin_unlock_bh(&reorder_buf->lock);
|
||||
del_timer_sync(&reorder_buf->reorder_timer);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
|
@ -771,8 +625,7 @@ out:
|
|||
|
||||
static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
||||
struct napi_struct *napi,
|
||||
u8 baid, u16 nssn, int queue,
|
||||
u32 flags)
|
||||
u8 baid, u16 nssn, int queue)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_reorder_buffer *reorder_buf;
|
||||
|
|
@ -790,8 +643,7 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
|||
|
||||
ba_data = rcu_dereference(mvm->baid_map[baid]);
|
||||
if (!ba_data) {
|
||||
WARN(!(flags & IWL_MVM_RELEASE_FROM_RSS_SYNC),
|
||||
"BAID %d not found in map\n", baid);
|
||||
WARN(true, "BAID %d not found in map\n", baid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -805,22 +657,13 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
|||
|
||||
spin_lock_bh(&reorder_buf->lock);
|
||||
iwl_mvm_release_frames(mvm, sta, napi, ba_data,
|
||||
reorder_buf, nssn, flags);
|
||||
reorder_buf, nssn);
|
||||
spin_unlock_bh(&reorder_buf->lock);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void iwl_mvm_nssn_sync(struct iwl_mvm *mvm,
|
||||
struct napi_struct *napi, int queue,
|
||||
const struct iwl_mvm_nssn_sync_data *data)
|
||||
{
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, data->baid,
|
||||
data->nssn, queue,
|
||||
IWL_MVM_RELEASE_FROM_RSS_SYNC);
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
struct iwl_rx_cmd_buffer *rxb, int queue)
|
||||
{
|
||||
|
|
@ -855,14 +698,6 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
break;
|
||||
iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
|
||||
break;
|
||||
case IWL_MVM_RXQ_NSSN_SYNC:
|
||||
if (WARN_ONCE(len != sizeof(struct iwl_mvm_nssn_sync_data),
|
||||
"invalid nssn sync notification size %d (%d)",
|
||||
len, (int)sizeof(struct iwl_mvm_nssn_sync_data)))
|
||||
break;
|
||||
iwl_mvm_nssn_sync(mvm, napi, queue,
|
||||
(void *)internal_notif->data);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
|
||||
}
|
||||
|
|
@ -876,55 +711,6 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_oldsn_workaround(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta, int tid,
|
||||
struct iwl_mvm_reorder_buffer *buffer,
|
||||
u32 reorder, u32 gp2, int queue)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
if (gp2 != buffer->consec_oldsn_ampdu_gp2) {
|
||||
/* we have a new (A-)MPDU ... */
|
||||
|
||||
/*
|
||||
* reset counter to 0 if we didn't have any oldsn in
|
||||
* the last A-MPDU (as detected by GP2 being identical)
|
||||
*/
|
||||
if (!buffer->consec_oldsn_prev_drop)
|
||||
buffer->consec_oldsn_drops = 0;
|
||||
|
||||
/* either way, update our tracking state */
|
||||
buffer->consec_oldsn_ampdu_gp2 = gp2;
|
||||
} else if (buffer->consec_oldsn_prev_drop) {
|
||||
/*
|
||||
* tracking state didn't change, and we had an old SN
|
||||
* indication before - do nothing in this case, we
|
||||
* already noted this one down and are waiting for the
|
||||
* next A-MPDU (by GP2)
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* return unless this MPDU has old SN */
|
||||
if (!(reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN))
|
||||
return;
|
||||
|
||||
/* update state */
|
||||
buffer->consec_oldsn_prev_drop = 1;
|
||||
buffer->consec_oldsn_drops++;
|
||||
|
||||
/* if limit is reached, send del BA and reset state */
|
||||
if (buffer->consec_oldsn_drops == IWL_MVM_AMPDU_CONSEC_DROPS_DELBA) {
|
||||
IWL_WARN(mvm,
|
||||
"reached %d old SN frames from %pM on queue %d, stopping BA session on TID %d\n",
|
||||
IWL_MVM_AMPDU_CONSEC_DROPS_DELBA,
|
||||
sta->addr, queue, tid);
|
||||
ieee80211_stop_rx_ba_session(mvmsta->vif, BIT(tid), sta->addr);
|
||||
buffer->consec_oldsn_prev_drop = 0;
|
||||
buffer->consec_oldsn_drops = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the MPDU was buffered\dropped, false if it should be passed
|
||||
* to upper layer.
|
||||
|
|
@ -936,11 +722,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
struct sk_buff *skb,
|
||||
struct iwl_rx_mpdu_desc *desc)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
|
||||
struct iwl_mvm_baid_data *baid_data;
|
||||
struct iwl_mvm_reorder_buffer *buffer;
|
||||
struct sk_buff *tail;
|
||||
u32 reorder = le32_to_cpu(desc->reorder_data);
|
||||
bool amsdu = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU;
|
||||
bool last_subframe =
|
||||
|
|
@ -957,6 +741,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
baid = (reorder & IWL_RX_MPDU_REORDER_BAID_MASK) >>
|
||||
IWL_RX_MPDU_REORDER_BAID_SHIFT;
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* This also covers the case of receiving a Block Ack Request
|
||||
* outside a BA session; we'll pass it to mac80211 and that
|
||||
|
|
@ -1018,59 +805,18 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
buffer->valid = true;
|
||||
}
|
||||
|
||||
if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
iwl_mvm_release_frames(mvm, sta, napi, baid_data,
|
||||
buffer, nssn, 0);
|
||||
/* drop any duplicated packets */
|
||||
if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_DUPLICATE))
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there was a significant jump in the nssn - adjust.
|
||||
* If the SN is smaller than the NSSN it might need to first go into
|
||||
* the reorder buffer, in which case we just release up to it and the
|
||||
* rest of the function will take care of storing it and releasing up to
|
||||
* the nssn.
|
||||
* This should not happen. This queue has been lagging and it should
|
||||
* have been updated by a IWL_MVM_RXQ_NSSN_SYNC notification. Be nice
|
||||
* and update the other queues.
|
||||
*/
|
||||
if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,
|
||||
buffer->buf_size) ||
|
||||
!ieee80211_sn_less(sn, buffer->head_sn + buffer->buf_size)) {
|
||||
u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn;
|
||||
|
||||
iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer,
|
||||
min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
|
||||
}
|
||||
|
||||
iwl_mvm_oldsn_workaround(mvm, sta, tid, buffer, reorder,
|
||||
rx_status->device_timestamp, queue);
|
||||
|
||||
/* drop any oudated packets */
|
||||
if (ieee80211_sn_less(sn, buffer->head_sn))
|
||||
if (reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN)
|
||||
goto drop;
|
||||
|
||||
/* release immediately if allowed by nssn and no stored frames */
|
||||
if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
|
||||
if (iwl_mvm_is_sn_less(buffer->head_sn, nssn,
|
||||
buffer->buf_size) &&
|
||||
(!amsdu || last_subframe)) {
|
||||
/*
|
||||
* If we crossed the 2048 or 0 SN, notify all the
|
||||
* queues. This is done in order to avoid having a
|
||||
* head_sn that lags behind for too long. When that
|
||||
* happens, we can get to a situation where the head_sn
|
||||
* is within the interval [nssn - buf_size : nssn]
|
||||
* which will make us think that the nssn is a packet
|
||||
* that we already freed because of the reordering
|
||||
* buffer and we will ignore it. So maintain the
|
||||
* head_sn somewhat updated across all the queues:
|
||||
* when it crosses 0 and 2048.
|
||||
*/
|
||||
if (sn == 2048 || sn == 0)
|
||||
iwl_mvm_sync_nssn(mvm, baid, sn);
|
||||
if (!amsdu || last_subframe)
|
||||
buffer->head_sn = nssn;
|
||||
}
|
||||
/* No need to update AMSDU last SN - we are moving the head */
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return false;
|
||||
|
|
@ -1085,37 +831,18 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
* while technically there is no hole and we can move forward.
|
||||
*/
|
||||
if (!buffer->num_stored && sn == buffer->head_sn) {
|
||||
if (!amsdu || last_subframe) {
|
||||
if (sn == 2048 || sn == 0)
|
||||
iwl_mvm_sync_nssn(mvm, baid, sn);
|
||||
if (!amsdu || last_subframe)
|
||||
buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
|
||||
}
|
||||
|
||||
/* No need to update AMSDU last SN - we are moving the head */
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
index = sn % buffer->buf_size;
|
||||
|
||||
/*
|
||||
* Check if we already stored this frame
|
||||
* As AMSDU is either received or not as whole, logic is simple:
|
||||
* If we have frames in that position in the buffer and the last frame
|
||||
* originated from AMSDU had a different SN then it is a retransmission.
|
||||
* If it is the same SN then if the subframe index is incrementing it
|
||||
* is the same AMSDU - otherwise it is a retransmission.
|
||||
*/
|
||||
tail = skb_peek_tail(&entries[index].e.frames);
|
||||
if (tail && !amsdu)
|
||||
goto drop;
|
||||
else if (tail && (sn != buffer->last_amsdu ||
|
||||
buffer->last_sub_index >= sub_frame_idx))
|
||||
goto drop;
|
||||
|
||||
/* put in reorder buffer */
|
||||
__skb_queue_tail(&entries[index].e.frames, skb);
|
||||
index = sn % buffer->buf_size;
|
||||
__skb_queue_tail(&entries[index].frames, skb);
|
||||
buffer->num_stored++;
|
||||
entries[index].e.reorder_time = jiffies;
|
||||
|
||||
if (amsdu) {
|
||||
buffer->last_amsdu = sn;
|
||||
|
|
@ -1135,8 +862,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
*/
|
||||
if (!amsdu || last_subframe)
|
||||
iwl_mvm_release_frames(mvm, sta, napi, baid_data,
|
||||
buffer, nssn,
|
||||
IWL_MVM_RELEASE_SEND_RSS_SYNC);
|
||||
buffer, nssn);
|
||||
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return true;
|
||||
|
|
@ -2617,9 +2343,15 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) &&
|
||||
likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)) &&
|
||||
likely(!iwl_mvm_mei_filter_scan(mvm, skb)))
|
||||
likely(!iwl_mvm_mei_filter_scan(mvm, skb))) {
|
||||
if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
|
||||
(desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) &&
|
||||
!(desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME))
|
||||
rx_status->flag |= RX_FLAG_AMSDU_MORE;
|
||||
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta,
|
||||
link_sta);
|
||||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
@ -2762,7 +2494,7 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, release->baid,
|
||||
le16_to_cpu(release->nssn),
|
||||
queue, 0);
|
||||
queue);
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
|
|
@ -2806,7 +2538,7 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
IWL_DEBUG_DROP(mvm, "Received a BAR, expect packet loss: nssn %d\n",
|
||||
nssn);
|
||||
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue, 0);
|
||||
iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue