mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-01 08:04:22 +08:00
Major stack changes:
* TC offload support for drivers below mac80211 * reduced neighbor report (RNR) handling for AP mode * mac80211 mesh fast-xmit and fast-rx support * support for another mesh A-MSDU format (seems nobody got the spec right) Major driver changes: Kalle moved the drivers that were just plain C files in drivers/net/wireless/ to legacy/ and virtual/ dirs. hwsim * multi-BSSID support * some FTM support ath11k * MU-MIMO parameters support * ack signal support for management packets rtl8xxxu * support for RTL8710BU aka RTL8188GU chips rtw89 * support for various newer firmware APIs ath10k * enabled threaded NAPI on WCN3990 iwlwifi * lots of work for multi-link/EHT (wifi7) * hardware timestamping support for some devices/firwmares * TX beacon protection on newer hardware -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmQl9gkACgkQ10qiO8sP aACnTw/+KHEjBePPNSiVOziE6tlKSIruabrsSbBBWWx4btFBT0YAnqiwf4Zyp67r VaRWPxRNqjriKMPYDn/bpCrRgkqeN50iCV9n+/xh4TaiLokea0IuA/KDLNM+vBPf 0VJBpNdW8tKLM0YluGWuoWUAlkjujBzjHaW0sKoII/PLh6evLGEIhqdveE8052Bc P3UMu3+FHXg+E1+1tpn/AK+b6bGQeBN3KG3h7uocwR4QE6xROdFPAmXDohbJ98pG 6EmCDuuFiYPwkKu3GsxmKFNbq7NatPoFtghBPQi4Sn9wGgWWlJcK7hlNTDDW5O7c ZqyqY8BiUnh9A1ZcUCKLiHYx+mjxiE2P5wlfDbiZGm7k2JkrBu+AebRvtD4ie/UF db8T321kZJ5XKI89yQT2DXzfrvhbw2D85eFudQpIyRguoPKicICLWOyw84+esNTI 2vqnbPVnYrLQ/X7SzKcdIh74fcSvL8Dj0EiUAzvhPDbgIvexiYDetBXVss8tXBsn bpCRND05tpCqqW+LyulglmYTAbhZdCYOy4DAB+g6dtxHOR8A0eLbUHocm0zlPvqd sc4pYpXHx4x+X3FPHpfxOqKUO87P7SvJ++d3Y3e09/ObLPSkn65ihsGJpMN/fj1e BkJ2yF0KUfJMNhSl5p8VELT3XZevT0EIEKMvwoIgSsWPR8cxqoI= =Zi6X -----END PGP SIGNATURE----- Merge tag 'wireless-next-2023-03-30' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Johannes Berg says: ==================== Major stack changes: * TC offload support for drivers below mac80211 * reduced neighbor report (RNR) handling for AP mode * mac80211 mesh fast-xmit and fast-rx support * support for another mesh A-MSDU format (seems nobody got the spec right) Major driver changes: Kalle moved the drivers that were just plain C files in drivers/net/wireless/ to legacy/ and virtual/ dirs. hwsim * multi-BSSID support * some FTM support ath11k * MU-MIMO parameters support * ack signal support for management packets rtl8xxxu * support for RTL8710BU aka RTL8188GU chips rtw89 * support for various newer firmware APIs ath10k * enabled threaded NAPI on WCN3990 iwlwifi * lots of work for multi-link/EHT (wifi7) * hardware timestamping support for some devices/firwmares * TX beacon protection on newer hardware * tag 'wireless-next-2023-03-30' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (181 commits) wifi: clean up erroneously introduced file wifi: iwlwifi: mvm: correctly use link in iwl_mvm_sta_del() wifi: iwlwifi: separate AP link management queues wifi: iwlwifi: mvm: free probe_resp_data later wifi: iwlwifi: bump FW API to 75 for AX devices wifi: iwlwifi: mvm: move max_agg_bufsize into host TLC lq_sta wifi: iwlwifi: mvm: send full STA during HW restart wifi: iwlwifi: mvm: rework active links counting wifi: iwlwifi: mvm: update mac config when assigning chanctx wifi: iwlwifi: mvm: use the correct link queue wifi: iwlwifi: mvm: clean up mac_id vs. link_id in MLD sta wifi: iwlwifi: mvm: fix station link data leak wifi: iwlwifi: mvm: initialize max_rc_amsdu_len per-link wifi: iwlwifi: mvm: use appropriate link for rate selection wifi: iwlwifi: mvm: use the new lockdep-checking macros wifi: iwlwifi: mvm: remove chanctx WARN_ON wifi: iwlwifi: mvm: avoid sending MAC context for idle wifi: iwlwifi: mvm: remove only link-specific AP keys wifi: iwlwifi: mvm: skip inactive links wifi: iwlwifi: mvm: adjust iwl_mvm_scan_respect_p2p_go_iter() for MLO ... ==================== Link: https://lore.kernel.org/r/20230330205612.921134-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
ce7928f7cf
@ -12276,7 +12276,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git
|
||||
F: Documentation/networking/mac80211-injection.rst
|
||||
F: Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst
|
||||
F: drivers/net/wireless/mac80211_hwsim.[ch]
|
||||
F: drivers/net/wireless/virtual/mac80211_hwsim.[ch]
|
||||
F: include/net/mac80211.h
|
||||
F: net/mac80211/
|
||||
|
||||
@ -17554,7 +17554,7 @@ F: include/ras/ras_event.h
|
||||
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Orphan
|
||||
F: drivers/net/wireless/ray*
|
||||
F: drivers/net/wireless/legacy/ray*
|
||||
|
||||
RC-CORE / LIRC FRAMEWORK
|
||||
M: Sean Young <sean@mess.org>
|
||||
@ -21798,7 +21798,7 @@ USB WIRELESS RNDIS DRIVER (rndis_wlan)
|
||||
M: Jussi Kivilinna <jussi.kivilinna@iki.fi>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/rndis_wlan.c
|
||||
F: drivers/net/wireless/legacy/rndis_wlan.c
|
||||
|
||||
USB XHCI DRIVER
|
||||
M: Mathias Nyman <mathias.nyman@intel.com>
|
||||
@ -22552,7 +22552,7 @@ F: drivers/input/misc/wistron_btns.c
|
||||
WL3501 WIRELESS PCMCIA CARD DRIVER
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Odd fixes
|
||||
F: drivers/net/wireless/wl3501*
|
||||
F: drivers/net/wireless/legacy/wl3501*
|
||||
|
||||
WOLFSON MICROELECTRONICS DRIVERS
|
||||
L: patches@opensource.cirrus.com
|
||||
|
@ -38,79 +38,8 @@ source "drivers/net/wireless/ti/Kconfig"
|
||||
source "drivers/net/wireless/zydas/Kconfig"
|
||||
source "drivers/net/wireless/quantenna/Kconfig"
|
||||
|
||||
config PCMCIA_RAYCS
|
||||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||
depends on PCMCIA
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
help
|
||||
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
|
||||
(PC-card) wireless Ethernet networking card to your computer.
|
||||
Please read the file
|
||||
<file:Documentation/networking/device_drivers/wifi/ray_cs.rst> for
|
||||
details.
|
||||
source "drivers/net/wireless/legacy/Kconfig"
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ray_cs. If unsure, say N.
|
||||
|
||||
config PCMCIA_WL3501
|
||||
tristate "Planet WL3501 PCMCIA cards"
|
||||
depends on CFG80211 && PCMCIA
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
help
|
||||
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
||||
It has basic support for Linux wireless extensions and initial
|
||||
micro support for ethtool.
|
||||
|
||||
config MAC80211_HWSIM
|
||||
tristate "Simulated radio testing tool for mac80211"
|
||||
depends on MAC80211
|
||||
help
|
||||
This driver is a developer testing tool that can be used to test
|
||||
IEEE 802.11 networking stack (mac80211) functionality. This is not
|
||||
needed for normal wireless LAN usage and is only for testing. See
|
||||
Documentation/networking/mac80211_hwsim for more information on how
|
||||
to use this tool.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called mac80211_hwsim. If unsure, say N.
|
||||
|
||||
config USB_NET_RNDIS_WLAN
|
||||
tristate "Wireless RNDIS USB support"
|
||||
depends on USB
|
||||
depends on CFG80211
|
||||
select USB_NET_DRIVERS
|
||||
select USB_USBNET
|
||||
select USB_NET_CDCETHER
|
||||
select USB_NET_RNDIS_HOST
|
||||
help
|
||||
This is a driver for wireless RNDIS devices.
|
||||
These are USB based adapters found in devices such as:
|
||||
|
||||
Buffalo WLI-U2-KG125S
|
||||
U.S. Robotics USR5421
|
||||
Belkin F5D7051
|
||||
Linksys WUSB54GSv2
|
||||
Linksys WUSB54GSC
|
||||
Asus WL169gE
|
||||
Eminent EM4045
|
||||
BT Voyager 1055
|
||||
Linksys WUSB54GSv1
|
||||
U.S. Robotics USR5420
|
||||
BUFFALO WLI-USB-G54
|
||||
|
||||
All of these devices are based on Broadcom 4320 chip which is the
|
||||
only wireless RNDIS chip known to date.
|
||||
|
||||
If you choose to build a module, it'll be called rndis_wlan.
|
||||
|
||||
config VIRT_WIFI
|
||||
tristate "Wifi wrapper for ethernet drivers"
|
||||
depends on CFG80211
|
||||
help
|
||||
This option adds support for ethernet connections to appear as if they
|
||||
are wifi connections through a special rtnetlink device.
|
||||
source "drivers/net/wireless/virtual/Kconfig"
|
||||
|
||||
endif # WLAN
|
||||
|
@ -23,12 +23,5 @@ obj-$(CONFIG_WLAN_VENDOR_ST) += st/
|
||||
obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
|
||||
obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
|
||||
|
||||
# 16-bit wireless PCMCIA client drivers
|
||||
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
|
||||
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
|
||||
|
||||
obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
|
||||
|
||||
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
|
||||
|
||||
obj-$(CONFIG_VIRT_WIFI) += virt_wifi.o
|
||||
obj-$(CONFIG_WLAN) += legacy/
|
||||
obj-$(CONFIG_WLAN) += virtual/
|
||||
|
@ -96,11 +96,13 @@ struct ath_keyval {
|
||||
u8 kv_type;
|
||||
u8 kv_pad;
|
||||
u16 kv_len;
|
||||
u8 kv_val[16]; /* TK */
|
||||
u8 kv_mic[8]; /* Michael MIC key */
|
||||
u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
|
||||
* supports both MIC keys in the same key cache entry;
|
||||
* in that case, kv_mic is the RX key) */
|
||||
struct_group(kv_values,
|
||||
u8 kv_val[16]; /* TK */
|
||||
u8 kv_mic[8]; /* Michael MIC key */
|
||||
u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
|
||||
* supports both MIC keys in the same key cache entry;
|
||||
* in that case, kv_mic is the RX key) */
|
||||
);
|
||||
};
|
||||
|
||||
enum ath_cipher {
|
||||
|
@ -77,45 +77,6 @@ static inline u32 shadow_sr_wr_ind_addr(struct ath10k *ar,
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline u32 shadow_dst_wr_ind_addr(struct ath10k *ar,
|
||||
struct ath10k_ce_pipe *ce_state)
|
||||
{
|
||||
u32 ce_id = ce_state->id;
|
||||
u32 addr = 0;
|
||||
|
||||
switch (ce_id) {
|
||||
case 1:
|
||||
addr = 0x00032034;
|
||||
break;
|
||||
case 2:
|
||||
addr = 0x00032038;
|
||||
break;
|
||||
case 5:
|
||||
addr = 0x00032044;
|
||||
break;
|
||||
case 7:
|
||||
addr = 0x0003204C;
|
||||
break;
|
||||
case 8:
|
||||
addr = 0x00032050;
|
||||
break;
|
||||
case 9:
|
||||
addr = 0x00032054;
|
||||
break;
|
||||
case 10:
|
||||
addr = 0x00032058;
|
||||
break;
|
||||
case 11:
|
||||
addr = 0x0003205C;
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "invalid CE id: %d", ce_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ath10k_set_ring_byte(unsigned int offset,
|
||||
struct ath10k_hw_ce_regs_addr_map *addr_map)
|
||||
@ -438,19 +399,6 @@ static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
|
||||
host_ie_addr & ~(wm_regs->wm_mask));
|
||||
}
|
||||
|
||||
static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
|
||||
u32 ce_ctrl_addr)
|
||||
{
|
||||
struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
|
||||
|
||||
u32 misc_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
|
||||
ar->hw_ce_regs->misc_ie_addr);
|
||||
|
||||
ath10k_ce_write32(ar,
|
||||
ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
|
||||
misc_ie_addr | misc_regs->err_mask);
|
||||
}
|
||||
|
||||
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
|
||||
u32 ce_ctrl_addr)
|
||||
{
|
||||
|
@ -6030,7 +6030,6 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
changed_flags &= SUPPORTED_FILTERS;
|
||||
*total_flags &= SUPPORTED_FILTERS;
|
||||
ar->filter_flags = *total_flags;
|
||||
|
||||
|
@ -927,6 +927,7 @@ static int ath10k_snoc_hif_start(struct ath10k *ar)
|
||||
|
||||
bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);
|
||||
|
||||
dev_set_threaded(&ar->napi_dev, true);
|
||||
ath10k_core_napi_enable(ar);
|
||||
ath10k_snoc_irq_enable(ar);
|
||||
ath10k_snoc_rx_post(ar);
|
||||
|
@ -874,11 +874,11 @@ static int ath11k_ahb_setup_msi_resources(struct ath11k_base *ab)
|
||||
ab->pci.msi.ep_base_data = int_prop + 32;
|
||||
|
||||
for (i = 0; i < ab->pci.msi.config->total_vectors; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
ret = platform_get_irq(pdev, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ab->pci.msi.irqs[i] = res->start;
|
||||
ab->pci.msi.irqs[i] = ret;
|
||||
}
|
||||
|
||||
set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
|
||||
@ -1174,7 +1174,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
* to a new space for accessing them.
|
||||
*/
|
||||
ab->mem_ce = ioremap(ce_remap->base, ce_remap->size);
|
||||
if (IS_ERR(ab->mem_ce)) {
|
||||
if (!ab->mem_ce) {
|
||||
dev_err(&pdev->dev, "ce ioremap error\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_core_free;
|
||||
|
@ -201,6 +201,7 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
|
||||
config->twt_ap_pdev_count = ab->num_radios;
|
||||
config->twt_ap_sta_count = 1000;
|
||||
config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64;
|
||||
config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI;
|
||||
}
|
||||
|
||||
static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw,
|
||||
|
@ -2699,6 +2699,117 @@ static int ath11k_setup_peer_smps(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
ath11k_smps_map[smps]);
|
||||
}
|
||||
|
||||
static bool ath11k_mac_set_he_txbf_conf(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
u32 param, value;
|
||||
int ret;
|
||||
|
||||
if (!arvif->vif->bss_conf.he_support)
|
||||
return true;
|
||||
|
||||
param = WMI_VDEV_PARAM_SET_HEMU_MODE;
|
||||
value = 0;
|
||||
if (arvif->vif->bss_conf.he_su_beamformer) {
|
||||
value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
|
||||
if (arvif->vif->bss_conf.he_mu_beamformer &&
|
||||
arvif->vdev_type == WMI_VDEV_TYPE_AP)
|
||||
value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE);
|
||||
}
|
||||
|
||||
if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
|
||||
value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
|
||||
|
||||
if (arvif->vif->bss_conf.he_full_ul_mumimo)
|
||||
value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE);
|
||||
|
||||
if (arvif->vif->bss_conf.he_su_beamformee)
|
||||
value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
|
||||
value = FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) |
|
||||
FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE,
|
||||
HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE);
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param, value);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta_he_cap *he_cap)
|
||||
{
|
||||
struct ath11k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ieee80211_he_cap_elem he_cap_elem = {0};
|
||||
struct ieee80211_sta_he_cap *cap_band = NULL;
|
||||
struct cfg80211_chan_def def;
|
||||
u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE;
|
||||
u32 hemode = 0;
|
||||
int ret;
|
||||
|
||||
if (!vif->bss_conf.he_support)
|
||||
return true;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return false;
|
||||
|
||||
if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
|
||||
return false;
|
||||
|
||||
if (def.chan->band == NL80211_BAND_2GHZ)
|
||||
cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap;
|
||||
else
|
||||
cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap;
|
||||
|
||||
memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem));
|
||||
|
||||
if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) {
|
||||
if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
|
||||
hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
|
||||
if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
|
||||
hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE);
|
||||
}
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_MESH_POINT) {
|
||||
hemode |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
|
||||
|
||||
if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info))
|
||||
if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info))
|
||||
hemode |= FIELD_PREP(HE_MODE_UL_MUMIMO,
|
||||
HE_UL_MUMIMO_ENABLE);
|
||||
|
||||
if (FIELD_GET(HE_MODE_MU_TX_BFEE, hemode))
|
||||
hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE);
|
||||
|
||||
if (FIELD_GET(HE_MODE_MU_TX_BFER, hemode))
|
||||
hemode |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE);
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, hemode);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n",
|
||||
hemode, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
@ -2709,6 +2820,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *ap_sta;
|
||||
struct ath11k_peer *peer;
|
||||
bool is_auth = false;
|
||||
struct ieee80211_sta_he_cap he_cap;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
@ -2726,6 +2838,9 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
return;
|
||||
}
|
||||
|
||||
/* he_cap here is updated at assoc success for sta mode only */
|
||||
he_cap = ap_sta->deflink.he_cap;
|
||||
|
||||
ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
|
||||
|
||||
rcu_read_unlock();
|
||||
@ -2753,6 +2868,12 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) {
|
||||
ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n",
|
||||
arvif->vdev_id, bss_conf->bssid);
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_ON(arvif->is_up);
|
||||
|
||||
arvif->aid = vif->cfg.aid;
|
||||
@ -3202,6 +3323,8 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
ether_addr_copy(arvif->bssid, info->bssid);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (info->enable_beacon)
|
||||
ath11k_mac_set_he_txbf_conf(arvif);
|
||||
ath11k_control_beaconing(arvif, info);
|
||||
|
||||
if (arvif->is_up && vif->bss_conf.he_support &&
|
||||
@ -5360,6 +5483,43 @@ static __le16 ath11k_mac_setup_he_6ghz_cap(struct ath11k_pdev_cap *pcap,
|
||||
return cpu_to_le16(bcap->he_6ghz_capa);
|
||||
}
|
||||
|
||||
static void ath11k_mac_set_hemcsmap(struct ath11k *ar,
|
||||
struct ath11k_pdev_cap *cap,
|
||||
struct ieee80211_sta_he_cap *he_cap,
|
||||
int band)
|
||||
{
|
||||
u16 txmcs_map, rxmcs_map;
|
||||
u32 i;
|
||||
|
||||
rxmcs_map = 0;
|
||||
txmcs_map = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i < ar->num_tx_chains &&
|
||||
(ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
|
||||
txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
|
||||
else
|
||||
txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
|
||||
|
||||
if (i < ar->num_rx_chains &&
|
||||
(ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
|
||||
rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
|
||||
else
|
||||
rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
|
||||
}
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80 =
|
||||
cpu_to_le16(rxmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80 =
|
||||
cpu_to_le16(txmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_160 =
|
||||
cpu_to_le16(rxmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_160 =
|
||||
cpu_to_le16(txmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
|
||||
cpu_to_le16(rxmcs_map & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
|
||||
cpu_to_le16(txmcs_map & 0xffff);
|
||||
}
|
||||
|
||||
static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
||||
struct ath11k_pdev_cap *cap,
|
||||
struct ieee80211_sband_iftype_data *data,
|
||||
@ -5392,6 +5552,10 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
||||
|
||||
he_cap_elem->mac_cap_info[1] &=
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
|
||||
he_cap_elem->phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
he_cap_elem->phy_cap_info[0] &=
|
||||
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[5] &=
|
||||
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
|
||||
@ -5417,18 +5581,7 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
||||
break;
|
||||
}
|
||||
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80 =
|
||||
cpu_to_le16(band_cap->he_mcs & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80 =
|
||||
cpu_to_le16(band_cap->he_mcs & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_160 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_160 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
|
||||
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
|
||||
ath11k_mac_set_hemcsmap(ar, cap, he_cap, band);
|
||||
|
||||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
@ -6026,69 +6179,6 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
|
||||
}
|
||||
}
|
||||
|
||||
static u32
|
||||
ath11k_mac_prepare_he_mode(struct ath11k_pdev *pdev, u32 viftype)
|
||||
{
|
||||
struct ath11k_pdev_cap *pdev_cap = &pdev->cap;
|
||||
struct ath11k_band_cap *cap_band = NULL;
|
||||
u32 *hecap_phy_ptr = NULL;
|
||||
u32 hemode = 0;
|
||||
|
||||
if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP)
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
|
||||
else
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
|
||||
|
||||
hecap_phy_ptr = &cap_band->he_cap_phy_info[0];
|
||||
|
||||
hemode = FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_SU_TX_BFER, HECAP_PHY_SUBFMR_GET(hecap_phy_ptr)) |
|
||||
FIELD_PREP(HE_MODE_UL_MUMIMO, HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr));
|
||||
|
||||
/* TODO WDS and other modes */
|
||||
if (viftype == NL80211_IFTYPE_AP) {
|
||||
hemode |= FIELD_PREP(HE_MODE_MU_TX_BFER,
|
||||
HECAP_PHY_MUBFMR_GET(hecap_phy_ptr)) |
|
||||
FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) |
|
||||
FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE);
|
||||
} else {
|
||||
hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE);
|
||||
}
|
||||
|
||||
return hemode;
|
||||
}
|
||||
|
||||
static int ath11k_set_he_mu_sounding_mode(struct ath11k *ar,
|
||||
struct ath11k_vif *arvif)
|
||||
{
|
||||
u32 param_id, param_value;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
int ret = 0;
|
||||
|
||||
param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
|
||||
param_value = ath11k_mac_prepare_he_mode(ar->pdev, arvif->vif->type);
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, param_value);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n",
|
||||
arvif->vdev_id, ret, param_value);
|
||||
return ret;
|
||||
}
|
||||
param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
|
||||
param_value =
|
||||
FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) |
|
||||
FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE,
|
||||
HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE);
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, param_value);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -6757,7 +6847,6 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct wmi_vdev_start_req_arg arg = {};
|
||||
const struct cfg80211_chan_def *chandef = &ctx->def;
|
||||
int he_support = arvif->vif->bss_conf.he_support;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
@ -6798,15 +6887,6 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
arg.regdomain = ar->ab->dfs_region;
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
if (he_support) {
|
||||
ret = ath11k_set_he_mu_sounding_mode(ar, arvif);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set he mode vdev %i\n",
|
||||
arg.vdev_id);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
|
||||
@ -9094,6 +9174,11 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
goto err_free_if_combs;
|
||||
}
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
|
||||
ar->hw->queues = ATH11K_HW_MAX_QUEUES;
|
||||
ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN;
|
||||
ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1;
|
||||
|
@ -382,22 +382,23 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr);
|
||||
if (peer) {
|
||||
if (peer->vdev_id == param->vdev_id) {
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Assume sta is transitioning to another band.
|
||||
* Remove here the peer from rhash.
|
||||
*/
|
||||
mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
ath11k_peer_rhash_delete(ar->ab, peer);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
}
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
|
||||
ret = ath11k_wmi_send_peer_create_cmd(ar, param);
|
||||
if (ret) {
|
||||
|
@ -613,13 +613,19 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
{
|
||||
struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL;
|
||||
struct cur_reg_rule *reg_rule;
|
||||
u8 i = 0, j = 0;
|
||||
u8 i = 0, j = 0, k = 0;
|
||||
u8 num_rules;
|
||||
u16 max_bw;
|
||||
u32 flags;
|
||||
char alpha2[3];
|
||||
|
||||
num_rules = reg_info->num_5g_reg_rules + reg_info->num_2g_reg_rules;
|
||||
num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules;
|
||||
|
||||
/* FIXME: Currently taking reg rules for 6 GHz only from Indoor AP mode list.
|
||||
* This can be updated after complete 6 GHz regulatory support is added.
|
||||
*/
|
||||
if (reg_info->is_ext_reg_event)
|
||||
num_rules += reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP];
|
||||
|
||||
if (!num_rules)
|
||||
goto ret;
|
||||
@ -640,24 +646,24 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
tmp_regd->dfs_region = ath11k_map_fw_dfs_region(reg_info->dfs_region);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\r\nCountry %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n",
|
||||
"Country %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n",
|
||||
alpha2, ath11k_reg_get_regdom_str(tmp_regd->dfs_region),
|
||||
reg_info->dfs_region, num_rules);
|
||||
/* Update reg_rules[] below. Firmware is expected to
|
||||
* send these rules in order(2G rules first and then 5G)
|
||||
* send these rules in order(2 GHz rules first and then 5 GHz)
|
||||
*/
|
||||
for (; i < num_rules; i++) {
|
||||
if (reg_info->num_2g_reg_rules &&
|
||||
(i < reg_info->num_2g_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_2g_ptr + i;
|
||||
if (reg_info->num_2ghz_reg_rules &&
|
||||
(i < reg_info->num_2ghz_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_2ghz_ptr + i;
|
||||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_2g);
|
||||
reg_info->max_bw_2ghz);
|
||||
flags = 0;
|
||||
} else if (reg_info->num_5g_reg_rules &&
|
||||
(j < reg_info->num_5g_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_5g_ptr + j++;
|
||||
} else if (reg_info->num_5ghz_reg_rules &&
|
||||
(j < reg_info->num_5ghz_reg_rules)) {
|
||||
reg_rule = reg_info->reg_rules_5ghz_ptr + j++;
|
||||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_5g);
|
||||
reg_info->max_bw_5ghz);
|
||||
|
||||
/* FW doesn't pass NL80211_RRF_AUTO_BW flag for
|
||||
* BW Auto correction, we can enable this by default
|
||||
@ -666,6 +672,14 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
* per other BW rule flags we pass from here
|
||||
*/
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
} else if (reg_info->is_ext_reg_event &&
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] &&
|
||||
(k < reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP])) {
|
||||
reg_rule = reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP] +
|
||||
k++;
|
||||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP]);
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -693,12 +707,21 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
continue;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
|
||||
i + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
|
||||
tmp_regd->reg_rules[i].dfs_cac_ms,
|
||||
flags);
|
||||
if (reg_info->is_ext_reg_event) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n",
|
||||
i + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
|
||||
tmp_regd->reg_rules[i].dfs_cac_ms, flags,
|
||||
reg_rule->psd_flag, reg_rule->psd_eirp);
|
||||
} else {
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
|
||||
i + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
|
||||
tmp_regd->reg_rules[i].dfs_cac_ms,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
tmp_regd->n_reg_rules = i;
|
||||
|
@ -105,6 +105,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
||||
= { .min_len = sizeof(struct wmi_vdev_stopped_event) },
|
||||
[WMI_TAG_REG_CHAN_LIST_CC_EVENT]
|
||||
= { .min_len = sizeof(struct wmi_reg_chan_list_cc_event) },
|
||||
[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]
|
||||
= { .min_len = sizeof(struct wmi_reg_chan_list_cc_ext_event) },
|
||||
[WMI_TAG_MGMT_RX_HDR]
|
||||
= { .min_len = sizeof(struct wmi_mgmt_rx_hdr) },
|
||||
[WMI_TAG_MGMT_TX_COMPL_EVENT]
|
||||
@ -2068,6 +2070,12 @@ void ath11k_wmi_start_scan_init(struct ath11k *ar,
|
||||
WMI_SCAN_EVENT_FOREIGN_CHAN |
|
||||
WMI_SCAN_EVENT_DEQUEUED;
|
||||
arg->scan_flags |= WMI_SCAN_CHAN_STAT_EVENT;
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
arg->scan_ctrl_flags_ext |=
|
||||
WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE;
|
||||
|
||||
arg->num_bssid = 1;
|
||||
|
||||
/* fill bssid_list[0] with 0xff, otherwise bssid and RA will be
|
||||
@ -2149,6 +2157,8 @@ ath11k_wmi_copy_scan_event_cntrl_flags(struct wmi_start_scan_cmd *cmd,
|
||||
/* for adaptive scan mode using 3 bits (21 - 23 bits) */
|
||||
WMI_SCAN_SET_DWELL_MODE(cmd->scan_ctrl_flags,
|
||||
param->adaptive_dwell_time_mode);
|
||||
|
||||
cmd->scan_ctrl_flags_ext = param->scan_ctrl_flags_ext;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
@ -3966,6 +3976,10 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
|
||||
wmi_cfg->sched_params = tg_cfg->sched_params;
|
||||
wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count;
|
||||
wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count;
|
||||
wmi_cfg->host_service_flags &=
|
||||
~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
|
||||
wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported <<
|
||||
WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
|
||||
}
|
||||
|
||||
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
|
||||
@ -4184,6 +4198,10 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
|
||||
ab->hw_params.hw_ops->wmi_init_config(ab, &config);
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
|
||||
ab->wmi_ab.svc_map))
|
||||
config.is_reg_cc_ext_event_supported = 1;
|
||||
|
||||
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
|
||||
|
||||
init_param.res_cfg = &wmi_sc->wlan_resource_config;
|
||||
@ -4907,6 +4925,26 @@ static int ath11k_pull_vdev_start_resp_tlv(struct ath11k_base *ab, struct sk_buf
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_print_reg_rule(struct ath11k_base *ab, const char *band,
|
||||
u32 num_reg_rules,
|
||||
struct cur_reg_rule *reg_rule_ptr)
|
||||
{
|
||||
struct cur_reg_rule *reg_rule = reg_rule_ptr;
|
||||
u32 count;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "number of reg rules in %s band: %d\n",
|
||||
band, num_reg_rules);
|
||||
|
||||
for (count = 0; count < num_reg_rules; count++) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"reg rule %d: (%d - %d @ %d) (%d, %d) (FLAGS %d)\n",
|
||||
count + 1, reg_rule->start_freq, reg_rule->end_freq,
|
||||
reg_rule->max_bw, reg_rule->ant_gain,
|
||||
reg_rule->reg_power, reg_rule->flags);
|
||||
reg_rule++;
|
||||
}
|
||||
}
|
||||
|
||||
static struct cur_reg_rule
|
||||
*create_reg_rules_from_wmi(u32 num_reg_rules,
|
||||
struct wmi_regulatory_rule_struct *wmi_reg_rule)
|
||||
@ -4951,7 +4989,7 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
const void **tb;
|
||||
const struct wmi_reg_chan_list_cc_event *chan_list_event_hdr;
|
||||
struct wmi_regulatory_rule_struct *wmi_reg_rule;
|
||||
u32 num_2g_reg_rules, num_5g_reg_rules;
|
||||
u32 num_2ghz_reg_rules, num_5ghz_reg_rules;
|
||||
int ret;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory channel list\n");
|
||||
@ -4970,10 +5008,10 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
reg_info->num_2g_reg_rules = chan_list_event_hdr->num_2g_reg_rules;
|
||||
reg_info->num_5g_reg_rules = chan_list_event_hdr->num_5g_reg_rules;
|
||||
reg_info->num_2ghz_reg_rules = chan_list_event_hdr->num_2ghz_reg_rules;
|
||||
reg_info->num_5ghz_reg_rules = chan_list_event_hdr->num_5ghz_reg_rules;
|
||||
|
||||
if (!(reg_info->num_2g_reg_rules + reg_info->num_5g_reg_rules)) {
|
||||
if (!(reg_info->num_2ghz_reg_rules + reg_info->num_5ghz_reg_rules)) {
|
||||
ath11k_warn(ab, "No regulatory rules available in the event info\n");
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
@ -4987,61 +5025,68 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
reg_info->phy_id = chan_list_event_hdr->phy_id;
|
||||
reg_info->ctry_code = chan_list_event_hdr->country_id;
|
||||
reg_info->reg_dmn_pair = chan_list_event_hdr->domain_code;
|
||||
if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_PASS)
|
||||
reg_info->status_code = REG_SET_CC_STATUS_PASS;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_CURRENT_ALPHA2_NOT_FOUND)
|
||||
reg_info->status_code = REG_CURRENT_ALPHA2_NOT_FOUND;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_INIT_ALPHA2_NOT_FOUND)
|
||||
reg_info->status_code = REG_INIT_ALPHA2_NOT_FOUND;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_CHANGE_NOT_ALLOWED)
|
||||
reg_info->status_code = REG_SET_CC_CHANGE_NOT_ALLOWED;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_NO_MEMORY)
|
||||
reg_info->status_code = REG_SET_CC_STATUS_NO_MEMORY;
|
||||
else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_FAIL)
|
||||
reg_info->status_code = REG_SET_CC_STATUS_FAIL;
|
||||
|
||||
reg_info->min_bw_2g = chan_list_event_hdr->min_bw_2g;
|
||||
reg_info->max_bw_2g = chan_list_event_hdr->max_bw_2g;
|
||||
reg_info->min_bw_5g = chan_list_event_hdr->min_bw_5g;
|
||||
reg_info->max_bw_5g = chan_list_event_hdr->max_bw_5g;
|
||||
|
||||
num_2g_reg_rules = reg_info->num_2g_reg_rules;
|
||||
num_5g_reg_rules = reg_info->num_5g_reg_rules;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"%s:cc %s dsf %d BW: min_2g %d max_2g %d min_5g %d max_5g %d",
|
||||
__func__, reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2g, reg_info->max_bw_2g,
|
||||
reg_info->min_bw_5g, reg_info->max_bw_5g);
|
||||
"status_code %s",
|
||||
ath11k_cc_status_to_str(reg_info->status_code));
|
||||
|
||||
reg_info->status_code =
|
||||
ath11k_wmi_cc_setting_code_to_reg(chan_list_event_hdr->status_code);
|
||||
|
||||
reg_info->is_ext_reg_event = false;
|
||||
|
||||
reg_info->min_bw_2ghz = chan_list_event_hdr->min_bw_2ghz;
|
||||
reg_info->max_bw_2ghz = chan_list_event_hdr->max_bw_2ghz;
|
||||
reg_info->min_bw_5ghz = chan_list_event_hdr->min_bw_5ghz;
|
||||
reg_info->max_bw_5ghz = chan_list_event_hdr->max_bw_5ghz;
|
||||
|
||||
num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules;
|
||||
num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"%s: num_2g_reg_rules %d num_5g_reg_rules %d", __func__,
|
||||
num_2g_reg_rules, num_5g_reg_rules);
|
||||
"cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d",
|
||||
reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2ghz, reg_info->max_bw_2ghz,
|
||||
reg_info->min_bw_5ghz, reg_info->max_bw_5ghz);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"num_2ghz_reg_rules %d num_5ghz_reg_rules %d",
|
||||
num_2ghz_reg_rules, num_5ghz_reg_rules);
|
||||
|
||||
wmi_reg_rule =
|
||||
(struct wmi_regulatory_rule_struct *)((u8 *)chan_list_event_hdr
|
||||
+ sizeof(*chan_list_event_hdr)
|
||||
+ sizeof(struct wmi_tlv));
|
||||
|
||||
if (num_2g_reg_rules) {
|
||||
reg_info->reg_rules_2g_ptr = create_reg_rules_from_wmi(num_2g_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_2g_ptr) {
|
||||
if (num_2ghz_reg_rules) {
|
||||
reg_info->reg_rules_2ghz_ptr =
|
||||
create_reg_rules_from_wmi(num_2ghz_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_2ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 2g rules\n");
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "2 GHz",
|
||||
num_2ghz_reg_rules,
|
||||
reg_info->reg_rules_2ghz_ptr);
|
||||
}
|
||||
|
||||
if (num_5g_reg_rules) {
|
||||
wmi_reg_rule += num_2g_reg_rules;
|
||||
reg_info->reg_rules_5g_ptr = create_reg_rules_from_wmi(num_5g_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_5g_ptr) {
|
||||
if (num_5ghz_reg_rules) {
|
||||
wmi_reg_rule += num_2ghz_reg_rules;
|
||||
reg_info->reg_rules_5ghz_ptr =
|
||||
create_reg_rules_from_wmi(num_5ghz_reg_rules,
|
||||
wmi_reg_rule);
|
||||
if (!reg_info->reg_rules_5ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 5g rules\n");
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "5 GHz",
|
||||
num_5ghz_reg_rules,
|
||||
reg_info->reg_rules_5ghz_ptr);
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory channel list\n");
|
||||
@ -5050,6 +5095,429 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cur_reg_rule
|
||||
*create_ext_reg_rules_from_wmi(u32 num_reg_rules,
|
||||
struct wmi_regulatory_ext_rule *wmi_reg_rule)
|
||||
{
|
||||
struct cur_reg_rule *reg_rule_ptr;
|
||||
u32 count;
|
||||
|
||||
reg_rule_ptr = kcalloc(num_reg_rules, sizeof(*reg_rule_ptr), GFP_ATOMIC);
|
||||
|
||||
if (!reg_rule_ptr)
|
||||
return NULL;
|
||||
|
||||
for (count = 0; count < num_reg_rules; count++) {
|
||||
reg_rule_ptr[count].start_freq =
|
||||
u32_get_bits(wmi_reg_rule[count].freq_info,
|
||||
REG_RULE_START_FREQ);
|
||||
reg_rule_ptr[count].end_freq =
|
||||
u32_get_bits(wmi_reg_rule[count].freq_info,
|
||||
REG_RULE_END_FREQ);
|
||||
reg_rule_ptr[count].max_bw =
|
||||
u32_get_bits(wmi_reg_rule[count].bw_pwr_info,
|
||||
REG_RULE_MAX_BW);
|
||||
reg_rule_ptr[count].reg_power =
|
||||
u32_get_bits(wmi_reg_rule[count].bw_pwr_info,
|
||||
REG_RULE_REG_PWR);
|
||||
reg_rule_ptr[count].ant_gain =
|
||||
u32_get_bits(wmi_reg_rule[count].bw_pwr_info,
|
||||
REG_RULE_ANT_GAIN);
|
||||
reg_rule_ptr[count].flags =
|
||||
u32_get_bits(wmi_reg_rule[count].flag_info,
|
||||
REG_RULE_FLAGS);
|
||||
reg_rule_ptr[count].psd_flag =
|
||||
u32_get_bits(wmi_reg_rule[count].psd_power_info,
|
||||
REG_RULE_PSD_INFO);
|
||||
reg_rule_ptr[count].psd_eirp =
|
||||
u32_get_bits(wmi_reg_rule[count].psd_power_info,
|
||||
REG_RULE_PSD_EIRP);
|
||||
}
|
||||
|
||||
return reg_rule_ptr;
|
||||
}
|
||||
|
||||
static u8
|
||||
ath11k_invalid_5ghz_reg_ext_rules_from_wmi(u32 num_reg_rules,
|
||||
const struct wmi_regulatory_ext_rule *rule)
|
||||
{
|
||||
u8 num_invalid_5ghz_rules = 0;
|
||||
u32 count, start_freq;
|
||||
|
||||
for (count = 0; count < num_reg_rules; count++) {
|
||||
start_freq = u32_get_bits(rule[count].freq_info,
|
||||
REG_RULE_START_FREQ);
|
||||
|
||||
if (start_freq >= ATH11K_MIN_6G_FREQ)
|
||||
num_invalid_5ghz_rules++;
|
||||
}
|
||||
|
||||
return num_invalid_5ghz_rules;
|
||||
}
|
||||
|
||||
static int ath11k_pull_reg_chan_list_ext_update_ev(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
struct cur_regulatory_info *reg_info)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_reg_chan_list_cc_ext_event *ev;
|
||||
struct wmi_regulatory_ext_rule *ext_wmi_reg_rule;
|
||||
u32 num_2ghz_reg_rules, num_5ghz_reg_rules;
|
||||
u32 num_6ghz_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 num_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 total_reg_rules = 0;
|
||||
int ret, i, j, num_invalid_5ghz_ext_rules = 0;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory ext channel list\n");
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT];
|
||||
if (!ev) {
|
||||
ath11k_warn(ab, "failed to fetch reg chan list ext update ev\n");
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
reg_info->num_2ghz_reg_rules = ev->num_2ghz_reg_rules;
|
||||
reg_info->num_5ghz_reg_rules = ev->num_5ghz_reg_rules;
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->num_6ghz_reg_rules_ap_lpi;
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->num_6ghz_reg_rules_ap_sp;
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->num_6ghz_reg_rules_ap_vlp;
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->num_6ghz_reg_rules_client_lpi[i];
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->num_6ghz_reg_rules_client_sp[i];
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->num_6ghz_reg_rules_client_vlp[i];
|
||||
}
|
||||
|
||||
num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules;
|
||||
num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules;
|
||||
|
||||
total_reg_rules += num_2ghz_reg_rules;
|
||||
total_reg_rules += num_5ghz_reg_rules;
|
||||
|
||||
if ((num_2ghz_reg_rules > MAX_REG_RULES) ||
|
||||
(num_5ghz_reg_rules > MAX_REG_RULES)) {
|
||||
ath11k_warn(ab, "Num reg rules for 2.4 GHz/5 GHz exceeds max limit (num_2ghz_reg_rules: %d num_5ghz_reg_rules: %d max_rules: %d)\n",
|
||||
num_2ghz_reg_rules, num_5ghz_reg_rules, MAX_REG_RULES);
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
|
||||
num_6ghz_reg_rules_ap[i] = reg_info->num_6ghz_rules_ap[i];
|
||||
|
||||
if (num_6ghz_reg_rules_ap[i] > MAX_6GHZ_REG_RULES) {
|
||||
ath11k_warn(ab, "Num 6 GHz reg rules for AP mode(%d) exceeds max limit (num_6ghz_reg_rules_ap: %d, max_rules: %d)\n",
|
||||
i, num_6ghz_reg_rules_ap[i], MAX_6GHZ_REG_RULES);
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
total_reg_rules += num_6ghz_reg_rules_ap[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
num_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i];
|
||||
total_reg_rules += num_6ghz_client[WMI_REG_INDOOR_AP][i];
|
||||
|
||||
num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i];
|
||||
total_reg_rules += num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i];
|
||||
|
||||
num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i];
|
||||
total_reg_rules += num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i];
|
||||
|
||||
if ((num_6ghz_client[WMI_REG_INDOOR_AP][i] > MAX_6GHZ_REG_RULES) ||
|
||||
(num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] >
|
||||
MAX_6GHZ_REG_RULES) ||
|
||||
(num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] >
|
||||
MAX_6GHZ_REG_RULES)) {
|
||||
ath11k_warn(ab,
|
||||
"Num 6 GHz client reg rules exceeds max limit, for client(type: %d)\n",
|
||||
i);
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!total_reg_rules) {
|
||||
ath11k_warn(ab, "No reg rules available\n");
|
||||
kfree(tb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN);
|
||||
|
||||
reg_info->dfs_region = ev->dfs_region;
|
||||
reg_info->phybitmap = ev->phybitmap;
|
||||
reg_info->num_phy = ev->num_phy;
|
||||
reg_info->phy_id = ev->phy_id;
|
||||
reg_info->ctry_code = ev->country_id;
|
||||
reg_info->reg_dmn_pair = ev->domain_code;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"status_code %s",
|
||||
ath11k_cc_status_to_str(reg_info->status_code));
|
||||
|
||||
reg_info->status_code =
|
||||
ath11k_wmi_cc_setting_code_to_reg(ev->status_code);
|
||||
|
||||
reg_info->is_ext_reg_event = true;
|
||||
|
||||
reg_info->min_bw_2ghz = ev->min_bw_2ghz;
|
||||
reg_info->max_bw_2ghz = ev->max_bw_2ghz;
|
||||
reg_info->min_bw_5ghz = ev->min_bw_5ghz;
|
||||
reg_info->max_bw_5ghz = ev->max_bw_5ghz;
|
||||
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->min_bw_6ghz_ap_lpi;
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->max_bw_6ghz_ap_lpi;
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->min_bw_6ghz_ap_sp;
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->max_bw_6ghz_ap_sp;
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->min_bw_6ghz_ap_vlp;
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->max_bw_6ghz_ap_vlp;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz AP BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n",
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP],
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP],
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP],
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP],
|
||||
reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP],
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP]);
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->min_bw_6ghz_client_lpi[i];
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->max_bw_6ghz_client_lpi[i];
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->min_bw_6ghz_client_sp[i];
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->max_bw_6ghz_client_sp[i];
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->min_bw_6ghz_client_vlp[i];
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->max_bw_6ghz_client_vlp[i];
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz %s BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n",
|
||||
ath11k_6ghz_client_type_to_str(i),
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i],
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i],
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i],
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i],
|
||||
reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i],
|
||||
reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i]);
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d",
|
||||
reg_info->alpha2, reg_info->dfs_region,
|
||||
reg_info->min_bw_2ghz, reg_info->max_bw_2ghz,
|
||||
reg_info->min_bw_5ghz, reg_info->max_bw_5ghz);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"num_2ghz_reg_rules %d num_5ghz_reg_rules %d",
|
||||
num_2ghz_reg_rules, num_5ghz_reg_rules);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"num_6ghz_reg_rules_ap_lpi: %d num_6ghz_reg_rules_ap_sp: %d num_6ghz_reg_rules_ap_vlp: %d",
|
||||
num_6ghz_reg_rules_ap[WMI_REG_INDOOR_AP],
|
||||
num_6ghz_reg_rules_ap[WMI_REG_STANDARD_POWER_AP],
|
||||
num_6ghz_reg_rules_ap[WMI_REG_VERY_LOW_POWER_AP]);
|
||||
|
||||
j = WMI_REG_DEFAULT_CLIENT;
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz Regular client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d",
|
||||
num_6ghz_client[WMI_REG_INDOOR_AP][j],
|
||||
num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j],
|
||||
num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]);
|
||||
|
||||
j = WMI_REG_SUBORDINATE_CLIENT;
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz Subordinate client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d",
|
||||
num_6ghz_client[WMI_REG_INDOOR_AP][j],
|
||||
num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j],
|
||||
num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]);
|
||||
|
||||
ext_wmi_reg_rule =
|
||||
(struct wmi_regulatory_ext_rule *)((u8 *)ev + sizeof(*ev) +
|
||||
sizeof(struct wmi_tlv));
|
||||
if (num_2ghz_reg_rules) {
|
||||
reg_info->reg_rules_2ghz_ptr =
|
||||
create_ext_reg_rules_from_wmi(num_2ghz_reg_rules,
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_2ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "2 GHz",
|
||||
num_2ghz_reg_rules,
|
||||
reg_info->reg_rules_2ghz_ptr);
|
||||
}
|
||||
|
||||
ext_wmi_reg_rule += num_2ghz_reg_rules;
|
||||
|
||||
/* Firmware might include 6 GHz reg rule in 5 GHz rule list
|
||||
* for few countries along with separate 6 GHz rule.
|
||||
* Having same 6 GHz reg rule in 5 GHz and 6 GHz rules list
|
||||
* causes intersect check to be true, and same rules will be
|
||||
* shown multiple times in iw cmd.
|
||||
* Hence, avoid parsing 6 GHz rule from 5 GHz reg rule list
|
||||
*/
|
||||
num_invalid_5ghz_ext_rules =
|
||||
ath11k_invalid_5ghz_reg_ext_rules_from_wmi(num_5ghz_reg_rules,
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (num_invalid_5ghz_ext_rules) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"CC: %s 5 GHz reg rules number %d from fw, %d number of invalid 5 GHz rules",
|
||||
reg_info->alpha2, reg_info->num_5ghz_reg_rules,
|
||||
num_invalid_5ghz_ext_rules);
|
||||
|
||||
num_5ghz_reg_rules = num_5ghz_reg_rules - num_invalid_5ghz_ext_rules;
|
||||
reg_info->num_5ghz_reg_rules = num_5ghz_reg_rules;
|
||||
}
|
||||
|
||||
if (num_5ghz_reg_rules) {
|
||||
reg_info->reg_rules_5ghz_ptr =
|
||||
create_ext_reg_rules_from_wmi(num_5ghz_reg_rules,
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_5ghz_ptr) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, "5 GHz",
|
||||
num_5ghz_reg_rules,
|
||||
reg_info->reg_rules_5ghz_ptr);
|
||||
}
|
||||
|
||||
/* We have adjusted the number of 5 GHz reg rules above. But still those
|
||||
* many rules needs to be adjusted in ext_wmi_reg_rule.
|
||||
*
|
||||
* NOTE: num_invalid_5ghz_ext_rules will be 0 for rest other cases.
|
||||
*/
|
||||
ext_wmi_reg_rule += (num_5ghz_reg_rules + num_invalid_5ghz_ext_rules);
|
||||
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
|
||||
reg_info->reg_rules_6ghz_ap_ptr[i] =
|
||||
create_ext_reg_rules_from_wmi(num_6ghz_reg_rules_ap[i],
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_6ghz_ap_ptr[i]) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 6 GHz AP rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab, ath11k_6ghz_ap_type_to_str(i),
|
||||
num_6ghz_reg_rules_ap[i],
|
||||
reg_info->reg_rules_6ghz_ap_ptr[i]);
|
||||
|
||||
ext_wmi_reg_rule += num_6ghz_reg_rules_ap[i];
|
||||
}
|
||||
|
||||
for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz AP type %s", ath11k_6ghz_ap_type_to_str(j));
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->reg_rules_6ghz_client_ptr[j][i] =
|
||||
create_ext_reg_rules_from_wmi(num_6ghz_client[j][i],
|
||||
ext_wmi_reg_rule);
|
||||
|
||||
if (!reg_info->reg_rules_6ghz_client_ptr[j][i]) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "Unable to Allocate memory for 6 GHz client rules\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath11k_print_reg_rule(ab,
|
||||
ath11k_6ghz_client_type_to_str(i),
|
||||
num_6ghz_client[j][i],
|
||||
reg_info->reg_rules_6ghz_client_ptr[j][i]);
|
||||
|
||||
ext_wmi_reg_rule += num_6ghz_client[j][i];
|
||||
}
|
||||
}
|
||||
|
||||
reg_info->client_type = ev->client_type;
|
||||
reg_info->rnr_tpe_usable = ev->rnr_tpe_usable;
|
||||
reg_info->unspecified_ap_usable =
|
||||
ev->unspecified_ap_usable;
|
||||
reg_info->domain_code_6ghz_ap[WMI_REG_INDOOR_AP] =
|
||||
ev->domain_code_6ghz_ap_lpi;
|
||||
reg_info->domain_code_6ghz_ap[WMI_REG_STANDARD_POWER_AP] =
|
||||
ev->domain_code_6ghz_ap_sp;
|
||||
reg_info->domain_code_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] =
|
||||
ev->domain_code_6ghz_ap_vlp;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz reg info client type %s rnr_tpe_usable %d unspecified_ap_usable %d AP sub domain: lpi %s, sp %s, vlp %s\n",
|
||||
ath11k_6ghz_client_type_to_str(reg_info->client_type),
|
||||
reg_info->rnr_tpe_usable,
|
||||
reg_info->unspecified_ap_usable,
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_lpi),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_sp),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_vlp));
|
||||
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) {
|
||||
reg_info->domain_code_6ghz_client[WMI_REG_INDOOR_AP][i] =
|
||||
ev->domain_code_6ghz_client_lpi[i];
|
||||
reg_info->domain_code_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] =
|
||||
ev->domain_code_6ghz_client_sp[i];
|
||||
reg_info->domain_code_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] =
|
||||
ev->domain_code_6ghz_client_vlp[i];
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz client type %s client sub domain: lpi %s, sp %s, vlp %s\n",
|
||||
ath11k_6ghz_client_type_to_str(i),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_lpi[i]),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_sp[i]),
|
||||
ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_vlp[i])
|
||||
);
|
||||
}
|
||||
|
||||
reg_info->domain_code_6ghz_super_id = ev->domain_code_6ghz_super_id;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"6 GHz client_type %s 6 GHz super domain %s",
|
||||
ath11k_6ghz_client_type_to_str(reg_info->client_type),
|
||||
ath11k_super_reg_6ghz_to_str(reg_info->domain_code_6ghz_super_id));
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory ext channel list\n");
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pull_peer_del_resp_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
struct wmi_peer_delete_resp_event *peer_del_resp)
|
||||
{
|
||||
@ -5221,8 +5689,8 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
u32 status)
|
||||
static int wmi_process_mgmt_tx_comp(struct ath11k *ar,
|
||||
struct wmi_mgmt_tx_compl_event *tx_compl_param)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
@ -5230,24 +5698,29 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
int num_mgmt;
|
||||
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
msdu = idr_find(&ar->txmgmt_idr, desc_id);
|
||||
msdu = idr_find(&ar->txmgmt_idr, tx_compl_param->desc_id);
|
||||
|
||||
if (!msdu) {
|
||||
ath11k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n",
|
||||
desc_id);
|
||||
tx_compl_param->desc_id);
|
||||
spin_unlock_bh(&ar->txmgmt_idr_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
idr_remove(&ar->txmgmt_idr, desc_id);
|
||||
idr_remove(&ar->txmgmt_idr, tx_compl_param->desc_id);
|
||||
spin_unlock_bh(&ar->txmgmt_idr_lock);
|
||||
|
||||
skb_cb = ATH11K_SKB_CB(msdu);
|
||||
dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status)
|
||||
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) &&
|
||||
!tx_compl_param->status) {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
info->status.ack_signal = tx_compl_param->ack_rssi;
|
||||
}
|
||||
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
|
||||
@ -5259,7 +5732,7 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"wmi mgmt tx comp pending %d desc id %d\n",
|
||||
num_mgmt, desc_id);
|
||||
num_mgmt, tx_compl_param->desc_id);
|
||||
|
||||
if (!num_mgmt)
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
@ -5292,6 +5765,7 @@ static int ath11k_pull_mgmt_tx_compl_param_tlv(struct ath11k_base *ab,
|
||||
param->pdev_id = ev->pdev_id;
|
||||
param->desc_id = ev->desc_id;
|
||||
param->status = ev->status;
|
||||
param->ack_rssi = ev->ack_rssi;
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
@ -6491,12 +6965,14 @@ static bool ath11k_reg_is_world_alpha(char *alpha)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
enum wmi_reg_chan_list_cmd_type id)
|
||||
{
|
||||
struct cur_regulatory_info *reg_info = NULL;
|
||||
struct ieee80211_regdomain *regd = NULL;
|
||||
bool intersect = false;
|
||||
int ret = 0, pdev_idx;
|
||||
int ret = 0, pdev_idx, i, j;
|
||||
struct ath11k *ar;
|
||||
|
||||
reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
|
||||
@ -6505,7 +6981,11 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info);
|
||||
if (id == WMI_REG_CHAN_LIST_CC_ID)
|
||||
ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info);
|
||||
else
|
||||
ret = ath11k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to extract regulatory info from received event\n");
|
||||
goto fallback;
|
||||
@ -6605,8 +7085,16 @@ fallback:
|
||||
WARN_ON(1);
|
||||
mem_free:
|
||||
if (reg_info) {
|
||||
kfree(reg_info->reg_rules_2g_ptr);
|
||||
kfree(reg_info->reg_rules_5g_ptr);
|
||||
kfree(reg_info->reg_rules_2ghz_ptr);
|
||||
kfree(reg_info->reg_rules_5ghz_ptr);
|
||||
if (reg_info->is_ext_reg_event) {
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++)
|
||||
kfree(reg_info->reg_rules_6ghz_ap_ptr[i]);
|
||||
|
||||
for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++)
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++)
|
||||
kfree(reg_info->reg_rules_6ghz_client_ptr[j][i]);
|
||||
}
|
||||
kfree(reg_info);
|
||||
}
|
||||
return ret;
|
||||
@ -7062,13 +7550,12 @@ static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *s
|
||||
goto exit;
|
||||
}
|
||||
|
||||
wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id,
|
||||
tx_compl_param.status);
|
||||
wmi_process_mgmt_tx_comp(ar, &tx_compl_param);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MGMT,
|
||||
"mgmt tx compl ev pdev_id %d, desc_id %d, status %d",
|
||||
"mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d",
|
||||
tx_compl_param.pdev_id, tx_compl_param.desc_id,
|
||||
tx_compl_param.status);
|
||||
tx_compl_param.status, tx_compl_param.ack_rssi);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
@ -8039,7 +8526,10 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
ath11k_service_ready_ext2_event(ab, skb);
|
||||
break;
|
||||
case WMI_REG_CHAN_LIST_CC_EVENTID:
|
||||
ath11k_reg_chan_list_event(ab, skb);
|
||||
ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_ID);
|
||||
break;
|
||||
case WMI_REG_CHAN_LIST_CC_EXT_EVENTID:
|
||||
ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_EXT_ID);
|
||||
break;
|
||||
case WMI_READY_EVENTID:
|
||||
ath11k_ready_event(ab, skb);
|
||||
|
@ -797,6 +797,7 @@ enum wmi_tlv_event_id {
|
||||
WMI_RMC_NEW_LEADER_EVENTID = WMI_TLV_CMD(WMI_GRP_RMC),
|
||||
WMI_REG_CHAN_LIST_CC_EVENTID = WMI_TLV_CMD(WMI_GRP_REGULATORY),
|
||||
WMI_11D_NEW_COUNTRY_EVENTID,
|
||||
WMI_REG_CHAN_LIST_CC_EXT_EVENTID,
|
||||
WMI_NDI_CAP_RSP_EVENTID = WMI_TLV_CMD(WMI_GRP_PROTOTYPE),
|
||||
WMI_NDP_INITIATOR_RSP_EVENTID,
|
||||
WMI_NDP_RESPONDER_RSP_EVENTID,
|
||||
@ -1865,6 +1866,8 @@ enum wmi_tlv_tag {
|
||||
WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
|
||||
WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD,
|
||||
WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
|
||||
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
|
||||
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
|
||||
WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8,
|
||||
WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD,
|
||||
WMI_TAG_MAX
|
||||
@ -2093,9 +2096,11 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_EXT2_MSG = 220,
|
||||
WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
|
||||
WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
|
||||
WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263,
|
||||
|
||||
/* The second 128 bits */
|
||||
WMI_MAX_EXT_SERVICE = 256,
|
||||
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
|
||||
WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326,
|
||||
|
||||
/* The third 128 bits */
|
||||
@ -2310,6 +2315,9 @@ struct wmi_init_cmd {
|
||||
} __packed;
|
||||
|
||||
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
|
||||
#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
|
||||
|
||||
#define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4
|
||||
|
||||
struct wmi_resource_config {
|
||||
u32 tlv_header;
|
||||
@ -2370,6 +2378,15 @@ struct wmi_resource_config {
|
||||
u32 sched_params;
|
||||
u32 twt_ap_pdev_count;
|
||||
u32 twt_ap_sta_count;
|
||||
u32 max_nlo_ssids;
|
||||
u32 num_pkt_filters;
|
||||
u32 num_max_sta_vdevs;
|
||||
u32 max_bssid_indicator;
|
||||
u32 ul_resp_config;
|
||||
u32 msdu_flow_override_config0;
|
||||
u32 msdu_flow_override_config1;
|
||||
u32 flags2;
|
||||
u32 host_service_flags;
|
||||
} __packed;
|
||||
|
||||
struct wmi_service_ready_event {
|
||||
@ -2852,36 +2869,40 @@ struct rx_reorder_queue_remove_params {
|
||||
#define REG_RULE_MAX_BW 0x0000ffff
|
||||
#define REG_RULE_REG_PWR 0x00ff0000
|
||||
#define REG_RULE_ANT_GAIN 0xff000000
|
||||
#define REG_RULE_PSD_INFO BIT(0)
|
||||
#define REG_RULE_PSD_EIRP 0xff0000
|
||||
|
||||
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
|
||||
#define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1)
|
||||
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
|
||||
#define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
|
||||
|
||||
#define HECAP_PHYDWORD_0 0
|
||||
#define HECAP_PHYDWORD_1 1
|
||||
#define HECAP_PHYDWORD_2 2
|
||||
#define HE_PHYCAP_BYTE_0 0
|
||||
#define HE_PHYCAP_BYTE_1 1
|
||||
#define HE_PHYCAP_BYTE_2 2
|
||||
#define HE_PHYCAP_BYTE_3 3
|
||||
#define HE_PHYCAP_BYTE_4 4
|
||||
|
||||
#define HECAP_PHY_SU_BFER BIT(31)
|
||||
#define HECAP_PHY_SU_BFER BIT(7)
|
||||
#define HECAP_PHY_SU_BFEE BIT(0)
|
||||
#define HECAP_PHY_MU_BFER BIT(1)
|
||||
#define HECAP_PHY_UL_MUMIMO BIT(22)
|
||||
#define HECAP_PHY_UL_MUOFDMA BIT(23)
|
||||
#define HECAP_PHY_UL_MUMIMO BIT(6)
|
||||
#define HECAP_PHY_UL_MUOFDMA BIT(7)
|
||||
|
||||
#define HECAP_PHY_SUBFMR_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HECAP_PHYDWORD_0])
|
||||
FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HE_PHYCAP_BYTE_3])
|
||||
|
||||
#define HECAP_PHY_SUBFME_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HECAP_PHYDWORD_1])
|
||||
FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HE_PHYCAP_BYTE_4])
|
||||
|
||||
#define HECAP_PHY_MUBFMR_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HECAP_PHYDWORD_1])
|
||||
FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HE_PHYCAP_BYTE_4])
|
||||
|
||||
#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HECAP_PHYDWORD_0])
|
||||
FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HE_PHYCAP_BYTE_2])
|
||||
|
||||
#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \
|
||||
FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HECAP_PHYDWORD_0])
|
||||
FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HE_PHYCAP_BYTE_2])
|
||||
|
||||
#define HE_MODE_SU_TX_BFEE BIT(0)
|
||||
#define HE_MODE_SU_TX_BFER BIT(1)
|
||||
@ -2894,8 +2915,11 @@ struct rx_reorder_queue_remove_params {
|
||||
#define HE_DL_MUOFDMA_ENABLE 1
|
||||
#define HE_UL_MUOFDMA_ENABLE 1
|
||||
#define HE_DL_MUMIMO_ENABLE 1
|
||||
#define HE_UL_MUMIMO_ENABLE 1
|
||||
#define HE_MU_BFEE_ENABLE 1
|
||||
#define HE_SU_BFEE_ENABLE 1
|
||||
#define HE_MU_BFER_ENABLE 1
|
||||
#define HE_SU_BFER_ENABLE 1
|
||||
|
||||
#define HE_VHT_SOUNDING_MODE_ENABLE 1
|
||||
#define HE_SU_MU_SOUNDING_MODE_ENABLE 1
|
||||
@ -3223,6 +3247,7 @@ struct wmi_start_scan_cmd {
|
||||
|
||||
#define WMI_SCAN_DWELL_MODE_MASK 0x00E00000
|
||||
#define WMI_SCAN_DWELL_MODE_SHIFT 21
|
||||
#define WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE 0x00000800
|
||||
|
||||
enum {
|
||||
WMI_SCAN_DWELL_MODE_DEFAULT = 0,
|
||||
@ -3270,6 +3295,7 @@ struct scan_req_params {
|
||||
};
|
||||
u32 scan_events;
|
||||
};
|
||||
u32 scan_ctrl_flags_ext;
|
||||
u32 dwell_time_active;
|
||||
u32 dwell_time_active_2g;
|
||||
u32 dwell_time_passive;
|
||||
@ -4040,6 +4066,7 @@ struct wmi_he_rate_set {
|
||||
|
||||
#define MAX_REG_RULES 10
|
||||
#define REG_ALPHA2_LEN 2
|
||||
#define MAX_6GHZ_REG_RULES 5
|
||||
|
||||
enum wmi_start_event_param {
|
||||
WMI_VDEV_START_RESP_EVENT = 0,
|
||||
@ -4070,16 +4097,6 @@ enum wmi_vdev_start_resp_status_code {
|
||||
WMI_VDEV_START_RESPONSE_INVALID_REGDOMAIN = 4,
|
||||
};
|
||||
|
||||
;
|
||||
enum cc_setting_code {
|
||||
REG_SET_CC_STATUS_PASS = 0,
|
||||
REG_CURRENT_ALPHA2_NOT_FOUND = 1,
|
||||
REG_INIT_ALPHA2_NOT_FOUND = 2,
|
||||
REG_SET_CC_CHANGE_NOT_ALLOWED = 3,
|
||||
REG_SET_CC_STATUS_NO_MEMORY = 4,
|
||||
REG_SET_CC_STATUS_FAIL = 5,
|
||||
};
|
||||
|
||||
/* Regaulatory Rule Flags Passed by FW */
|
||||
#define REGULATORY_CHAN_DISABLED BIT(0)
|
||||
#define REGULATORY_CHAN_NO_IR BIT(1)
|
||||
@ -4093,15 +4110,216 @@ enum cc_setting_code {
|
||||
#define REGULATORY_CHAN_NO_20MHZ BIT(11)
|
||||
#define REGULATORY_CHAN_NO_10MHZ BIT(12)
|
||||
|
||||
enum {
|
||||
enum wmi_reg_chan_list_cmd_type {
|
||||
WMI_REG_CHAN_LIST_CC_ID = 0,
|
||||
WMI_REG_CHAN_LIST_CC_EXT_ID = 1,
|
||||
};
|
||||
|
||||
enum wmi_reg_cc_setting_code {
|
||||
WMI_REG_SET_CC_STATUS_PASS = 0,
|
||||
WMI_REG_CURRENT_ALPHA2_NOT_FOUND = 1,
|
||||
WMI_REG_INIT_ALPHA2_NOT_FOUND = 2,
|
||||
WMI_REG_SET_CC_CHANGE_NOT_ALLOWED = 3,
|
||||
WMI_REG_SET_CC_STATUS_NO_MEMORY = 4,
|
||||
WMI_REG_SET_CC_STATUS_FAIL = 5,
|
||||
|
||||
/* add new setting code above, update in
|
||||
* @enum cc_setting_code as well.
|
||||
* Also handle it in ath11k_wmi_cc_setting_code_to_reg()
|
||||
*/
|
||||
};
|
||||
|
||||
enum cc_setting_code {
|
||||
REG_SET_CC_STATUS_PASS = 0,
|
||||
REG_CURRENT_ALPHA2_NOT_FOUND = 1,
|
||||
REG_INIT_ALPHA2_NOT_FOUND = 2,
|
||||
REG_SET_CC_CHANGE_NOT_ALLOWED = 3,
|
||||
REG_SET_CC_STATUS_NO_MEMORY = 4,
|
||||
REG_SET_CC_STATUS_FAIL = 5,
|
||||
|
||||
/* add new setting code above, update in
|
||||
* @enum wmi_reg_cc_setting_code as well.
|
||||
* Also handle it in ath11k_cc_status_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline enum cc_setting_code
|
||||
ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code)
|
||||
{
|
||||
switch (status_code) {
|
||||
case WMI_REG_SET_CC_STATUS_PASS:
|
||||
return REG_SET_CC_STATUS_PASS;
|
||||
case WMI_REG_CURRENT_ALPHA2_NOT_FOUND:
|
||||
return REG_CURRENT_ALPHA2_NOT_FOUND;
|
||||
case WMI_REG_INIT_ALPHA2_NOT_FOUND:
|
||||
return REG_INIT_ALPHA2_NOT_FOUND;
|
||||
case WMI_REG_SET_CC_CHANGE_NOT_ALLOWED:
|
||||
return REG_SET_CC_CHANGE_NOT_ALLOWED;
|
||||
case WMI_REG_SET_CC_STATUS_NO_MEMORY:
|
||||
return REG_SET_CC_STATUS_NO_MEMORY;
|
||||
case WMI_REG_SET_CC_STATUS_FAIL:
|
||||
return REG_SET_CC_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return REG_SET_CC_STATUS_FAIL;
|
||||
}
|
||||
|
||||
static inline const char *ath11k_cc_status_to_str(enum cc_setting_code code)
|
||||
{
|
||||
switch (code) {
|
||||
case REG_SET_CC_STATUS_PASS:
|
||||
return "REG_SET_CC_STATUS_PASS";
|
||||
case REG_CURRENT_ALPHA2_NOT_FOUND:
|
||||
return "REG_CURRENT_ALPHA2_NOT_FOUND";
|
||||
case REG_INIT_ALPHA2_NOT_FOUND:
|
||||
return "REG_INIT_ALPHA2_NOT_FOUND";
|
||||
case REG_SET_CC_CHANGE_NOT_ALLOWED:
|
||||
return "REG_SET_CC_CHANGE_NOT_ALLOWED";
|
||||
case REG_SET_CC_STATUS_NO_MEMORY:
|
||||
return "REG_SET_CC_STATUS_NO_MEMORY";
|
||||
case REG_SET_CC_STATUS_FAIL:
|
||||
return "REG_SET_CC_STATUS_FAIL";
|
||||
}
|
||||
|
||||
return "Unknown CC status";
|
||||
}
|
||||
|
||||
enum wmi_reg_6ghz_ap_type {
|
||||
WMI_REG_INDOOR_AP = 0,
|
||||
WMI_REG_STANDARD_POWER_AP = 1,
|
||||
WMI_REG_VERY_LOW_POWER_AP = 2,
|
||||
|
||||
/* add AP type above, handle in ath11k_6ghz_ap_type_to_str()
|
||||
*/
|
||||
WMI_REG_CURRENT_MAX_AP_TYPE,
|
||||
WMI_REG_MAX_AP_TYPE = 7,
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_6ghz_ap_type_to_str(enum wmi_reg_6ghz_ap_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case WMI_REG_INDOOR_AP:
|
||||
return "INDOOR AP";
|
||||
case WMI_REG_STANDARD_POWER_AP:
|
||||
return "STANDARD POWER AP";
|
||||
case WMI_REG_VERY_LOW_POWER_AP:
|
||||
return "VERY LOW POWER AP";
|
||||
case WMI_REG_CURRENT_MAX_AP_TYPE:
|
||||
return "CURRENT_MAX_AP_TYPE";
|
||||
case WMI_REG_MAX_AP_TYPE:
|
||||
return "MAX_AP_TYPE";
|
||||
}
|
||||
|
||||
return "unknown 6 GHz AP type";
|
||||
}
|
||||
|
||||
enum wmi_reg_6ghz_client_type {
|
||||
WMI_REG_DEFAULT_CLIENT = 0,
|
||||
WMI_REG_SUBORDINATE_CLIENT = 1,
|
||||
WMI_REG_MAX_CLIENT_TYPE = 2,
|
||||
|
||||
/* add client type above, handle it in
|
||||
* ath11k_6ghz_client_type_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_6ghz_client_type_to_str(enum wmi_reg_6ghz_client_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case WMI_REG_DEFAULT_CLIENT:
|
||||
return "DEFAULT CLIENT";
|
||||
case WMI_REG_SUBORDINATE_CLIENT:
|
||||
return "SUBORDINATE CLIENT";
|
||||
case WMI_REG_MAX_CLIENT_TYPE:
|
||||
return "MAX_CLIENT_TYPE";
|
||||
}
|
||||
|
||||
return "unknown 6 GHz client type";
|
||||
}
|
||||
|
||||
enum reg_subdomains_6ghz {
|
||||
EMPTY_6GHZ = 0x0,
|
||||
FCC1_CLIENT_LPI_REGULAR_6GHZ = 0x01,
|
||||
FCC1_CLIENT_SP_6GHZ = 0x02,
|
||||
FCC1_AP_LPI_6GHZ = 0x03,
|
||||
FCC1_CLIENT_LPI_SUBORDINATE = FCC1_AP_LPI_6GHZ,
|
||||
FCC1_AP_SP_6GHZ = 0x04,
|
||||
ETSI1_LPI_6GHZ = 0x10,
|
||||
ETSI1_VLP_6GHZ = 0x11,
|
||||
ETSI2_LPI_6GHZ = 0x12,
|
||||
ETSI2_VLP_6GHZ = 0x13,
|
||||
APL1_LPI_6GHZ = 0x20,
|
||||
APL1_VLP_6GHZ = 0x21,
|
||||
|
||||
/* add sub-domain above, handle it in
|
||||
* ath11k_sub_reg_6ghz_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_sub_reg_6ghz_to_str(enum reg_subdomains_6ghz sub_id)
|
||||
{
|
||||
switch (sub_id) {
|
||||
case EMPTY_6GHZ:
|
||||
return "N/A";
|
||||
case FCC1_CLIENT_LPI_REGULAR_6GHZ:
|
||||
return "FCC1_CLIENT_LPI_REGULAR_6GHZ";
|
||||
case FCC1_CLIENT_SP_6GHZ:
|
||||
return "FCC1_CLIENT_SP_6GHZ";
|
||||
case FCC1_AP_LPI_6GHZ:
|
||||
return "FCC1_AP_LPI_6GHZ/FCC1_CLIENT_LPI_SUBORDINATE";
|
||||
case FCC1_AP_SP_6GHZ:
|
||||
return "FCC1_AP_SP_6GHZ";
|
||||
case ETSI1_LPI_6GHZ:
|
||||
return "ETSI1_LPI_6GHZ";
|
||||
case ETSI1_VLP_6GHZ:
|
||||
return "ETSI1_VLP_6GHZ";
|
||||
case ETSI2_LPI_6GHZ:
|
||||
return "ETSI2_LPI_6GHZ";
|
||||
case ETSI2_VLP_6GHZ:
|
||||
return "ETSI2_VLP_6GHZ";
|
||||
case APL1_LPI_6GHZ:
|
||||
return "APL1_LPI_6GHZ";
|
||||
case APL1_VLP_6GHZ:
|
||||
return "APL1_VLP_6GHZ";
|
||||
}
|
||||
|
||||
return "unknown sub reg id";
|
||||
}
|
||||
|
||||
enum reg_super_domain_6ghz {
|
||||
FCC1_6GHZ = 0x01,
|
||||
ETSI1_6GHZ = 0x02,
|
||||
ETSI2_6GHZ = 0x03,
|
||||
APL1_6GHZ = 0x04,
|
||||
FCC1_6GHZ_CL = 0x05,
|
||||
|
||||
/* add super domain above, handle it in
|
||||
* ath11k_super_reg_6ghz_to_str()
|
||||
*/
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
ath11k_super_reg_6ghz_to_str(enum reg_super_domain_6ghz domain_id)
|
||||
{
|
||||
switch (domain_id) {
|
||||
case FCC1_6GHZ:
|
||||
return "FCC1_6GHZ";
|
||||
case ETSI1_6GHZ:
|
||||
return "ETSI1_6GHZ";
|
||||
case ETSI2_6GHZ:
|
||||
return "ETSI2_6GHZ";
|
||||
case APL1_6GHZ:
|
||||
return "APL1_6GHZ";
|
||||
case FCC1_6GHZ_CL:
|
||||
return "FCC1_6GHZ_CL";
|
||||
}
|
||||
|
||||
return "unknown domain id";
|
||||
}
|
||||
|
||||
struct cur_reg_rule {
|
||||
u16 start_freq;
|
||||
u16 end_freq;
|
||||
@ -4109,6 +4327,8 @@ struct cur_reg_rule {
|
||||
u8 reg_power;
|
||||
u8 ant_gain;
|
||||
u16 flags;
|
||||
bool psd_flag;
|
||||
s8 psd_eirp;
|
||||
};
|
||||
|
||||
struct cur_regulatory_info {
|
||||
@ -4120,14 +4340,30 @@ struct cur_regulatory_info {
|
||||
u8 alpha2[REG_ALPHA2_LEN + 1];
|
||||
u32 dfs_region;
|
||||
u32 phybitmap;
|
||||
u32 min_bw_2g;
|
||||
u32 max_bw_2g;
|
||||
u32 min_bw_5g;
|
||||
u32 max_bw_5g;
|
||||
u32 num_2g_reg_rules;
|
||||
u32 num_5g_reg_rules;
|
||||
struct cur_reg_rule *reg_rules_2g_ptr;
|
||||
struct cur_reg_rule *reg_rules_5g_ptr;
|
||||
u32 min_bw_2ghz;
|
||||
u32 max_bw_2ghz;
|
||||
u32 min_bw_5ghz;
|
||||
u32 max_bw_5ghz;
|
||||
u32 num_2ghz_reg_rules;
|
||||
u32 num_5ghz_reg_rules;
|
||||
struct cur_reg_rule *reg_rules_2ghz_ptr;
|
||||
struct cur_reg_rule *reg_rules_5ghz_ptr;
|
||||
bool is_ext_reg_event;
|
||||
enum wmi_reg_6ghz_client_type client_type;
|
||||
bool rnr_tpe_usable;
|
||||
bool unspecified_ap_usable;
|
||||
u8 domain_code_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u8 domain_code_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 domain_code_6ghz_super_id;
|
||||
u32 min_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 max_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 min_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 max_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
u32 num_6ghz_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
u32 num_6ghz_rules_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
struct cur_reg_rule *reg_rules_6ghz_ap_ptr[WMI_REG_CURRENT_MAX_AP_TYPE];
|
||||
struct cur_reg_rule *reg_rules_6ghz_client_ptr
|
||||
[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
|
||||
};
|
||||
|
||||
struct wmi_reg_chan_list_cc_event {
|
||||
@ -4139,12 +4375,12 @@ struct wmi_reg_chan_list_cc_event {
|
||||
u32 domain_code;
|
||||
u32 dfs_region;
|
||||
u32 phybitmap;
|
||||
u32 min_bw_2g;
|
||||
u32 max_bw_2g;
|
||||
u32 min_bw_5g;
|
||||
u32 max_bw_5g;
|
||||
u32 num_2g_reg_rules;
|
||||
u32 num_5g_reg_rules;
|
||||
u32 min_bw_2ghz;
|
||||
u32 max_bw_2ghz;
|
||||
u32 min_bw_5ghz;
|
||||
u32 max_bw_5ghz;
|
||||
u32 num_2ghz_reg_rules;
|
||||
u32 num_5ghz_reg_rules;
|
||||
} __packed;
|
||||
|
||||
struct wmi_regulatory_rule_struct {
|
||||
@ -4154,6 +4390,61 @@ struct wmi_regulatory_rule_struct {
|
||||
u32 flag_info;
|
||||
};
|
||||
|
||||
#define WMI_REG_CLIENT_MAX 4
|
||||
|
||||
struct wmi_reg_chan_list_cc_ext_event {
|
||||
u32 status_code;
|
||||
u32 phy_id;
|
||||
u32 alpha2;
|
||||
u32 num_phy;
|
||||
u32 country_id;
|
||||
u32 domain_code;
|
||||
u32 dfs_region;
|
||||
u32 phybitmap;
|
||||
u32 min_bw_2ghz;
|
||||
u32 max_bw_2ghz;
|
||||
u32 min_bw_5ghz;
|
||||
u32 max_bw_5ghz;
|
||||
u32 num_2ghz_reg_rules;
|
||||
u32 num_5ghz_reg_rules;
|
||||
u32 client_type;
|
||||
u32 rnr_tpe_usable;
|
||||
u32 unspecified_ap_usable;
|
||||
u32 domain_code_6ghz_ap_lpi;
|
||||
u32 domain_code_6ghz_ap_sp;
|
||||
u32 domain_code_6ghz_ap_vlp;
|
||||
u32 domain_code_6ghz_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 domain_code_6ghz_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 domain_code_6ghz_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
u32 domain_code_6ghz_super_id;
|
||||
u32 min_bw_6ghz_ap_sp;
|
||||
u32 max_bw_6ghz_ap_sp;
|
||||
u32 min_bw_6ghz_ap_lpi;
|
||||
u32 max_bw_6ghz_ap_lpi;
|
||||
u32 min_bw_6ghz_ap_vlp;
|
||||
u32 max_bw_6ghz_ap_vlp;
|
||||
u32 min_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 max_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 min_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 max_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 min_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
u32 max_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
u32 num_6ghz_reg_rules_ap_sp;
|
||||
u32 num_6ghz_reg_rules_ap_lpi;
|
||||
u32 num_6ghz_reg_rules_ap_vlp;
|
||||
u32 num_6ghz_reg_rules_client_sp[WMI_REG_CLIENT_MAX];
|
||||
u32 num_6ghz_reg_rules_client_lpi[WMI_REG_CLIENT_MAX];
|
||||
u32 num_6ghz_reg_rules_client_vlp[WMI_REG_CLIENT_MAX];
|
||||
} __packed;
|
||||
|
||||
struct wmi_regulatory_ext_rule {
|
||||
u32 tlv_header;
|
||||
u32 freq_info;
|
||||
u32 bw_pwr_info;
|
||||
u32 flag_info;
|
||||
u32 psd_power_info;
|
||||
} __packed;
|
||||
|
||||
struct wmi_vdev_delete_resp_event {
|
||||
u32 vdev_id;
|
||||
} __packed;
|
||||
@ -4542,6 +4833,8 @@ struct wmi_mgmt_tx_compl_event {
|
||||
u32 desc_id;
|
||||
u32 status;
|
||||
u32 pdev_id;
|
||||
u32 ppdu_id;
|
||||
u32 ack_rssi;
|
||||
} __packed;
|
||||
|
||||
struct wmi_scan_event {
|
||||
@ -5347,6 +5640,7 @@ struct target_resource_config {
|
||||
u32 sched_params;
|
||||
u32 twt_ap_pdev_count;
|
||||
u32 twt_ap_sta_count;
|
||||
u8 is_reg_cc_ext_event_supported;
|
||||
};
|
||||
|
||||
enum wmi_debug_log_param {
|
||||
|
@ -946,7 +946,7 @@ int ath12k_ce_alloc_pipes(struct ath12k_base *ab)
|
||||
|
||||
ret = ath12k_ce_alloc_pipe(ab, i);
|
||||
if (ret) {
|
||||
/* Free any parial successful allocation */
|
||||
/* Free any partial successful allocation */
|
||||
ath12k_ce_free_pipes(ab);
|
||||
return ret;
|
||||
}
|
||||
|
@ -691,7 +691,7 @@ struct ath12k_base {
|
||||
|
||||
/* Below regd's are protected by ab->data_lock */
|
||||
/* This is the regd set for every radio
|
||||
* by the firmware during initializatin
|
||||
* by the firmware during initialization
|
||||
*/
|
||||
struct ieee80211_regdomain *default_regd[MAX_RADIOS];
|
||||
/* This regd is set during dynamic country setting
|
||||
|
@ -1429,7 +1429,7 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab)
|
||||
}
|
||||
|
||||
if (dp->spt_info[i].paddr & ATH12K_SPT_4K_ALIGN_CHECK) {
|
||||
ath12k_warn(ab, "SPT allocated memoty is not 4K aligned");
|
||||
ath12k_warn(ab, "SPT allocated memory is not 4K aligned");
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
@ -1461,15 +1461,12 @@ static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab)
|
||||
dp->reoq_lut.vaddr = dma_alloc_coherent(ab->dev,
|
||||
DP_REOQ_LUT_SIZE,
|
||||
&dp->reoq_lut.paddr,
|
||||
GFP_KERNEL);
|
||||
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!dp->reoq_lut.vaddr) {
|
||||
ath12k_warn(ab, "failed to allocate memory for reoq table");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(dp->reoq_lut.vaddr, 0, DP_REOQ_LUT_SIZE);
|
||||
|
||||
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab),
|
||||
dp->reoq_lut.paddr);
|
||||
return 0;
|
||||
|
@ -371,7 +371,7 @@ struct ath12k_dp {
|
||||
|
||||
#define HTT_TX_WBM_COMP_STATUS_OFFSET 8
|
||||
|
||||
/* HTT tx completion is overlayed in wbm_release_ring */
|
||||
/* HTT tx completion is overlaid in wbm_release_ring */
|
||||
#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13)
|
||||
#define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0)
|
||||
#define HTT_TX_WBM_COMP_INFO1_EXCEPTION_FRAME BIT(4)
|
||||
@ -545,7 +545,7 @@ enum htt_srng_ring_id {
|
||||
* 3'b010: 4 usec
|
||||
* 3'b011: 8 usec (default)
|
||||
* 3'b100: 16 usec
|
||||
* Others: Reserverd
|
||||
* Others: Reserved
|
||||
* b'19 - response_required:
|
||||
* Host needs HTT_T2H_MSG_TYPE_SRING_SETUP_DONE as response
|
||||
* b'20:31 - reserved: reserved for future use
|
||||
@ -1126,7 +1126,7 @@ struct htt_tx_ring_selection_cfg_cmd {
|
||||
__le32 tlv_filter_mask_in1;
|
||||
__le32 tlv_filter_mask_in2;
|
||||
__le32 tlv_filter_mask_in3;
|
||||
__le32 reserverd[3];
|
||||
__le32 reserved[3];
|
||||
} __packed;
|
||||
|
||||
#define HTT_TX_RING_TLV_FILTER_MGMT_DMA_LEN GENMASK(3, 0)
|
||||
|
@ -529,12 +529,12 @@ static void ath12k_dp_mon_parse_he_sig_su(u8 *tlv_data,
|
||||
case 3:
|
||||
if (he_dcm && he_stbc) {
|
||||
he_gi = HE_GI_0_8;
|
||||
he_ltf = HE_LTF_4_X;
|
||||
he_ltf = HE_LTF_4_X;
|
||||
} else {
|
||||
he_gi = HE_GI_3_2;
|
||||
he_ltf = HE_LTF_4_X;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ppdu_info->gi = he_gi;
|
||||
value = he_gi << HE_GI_SHIFT;
|
||||
@ -813,7 +813,7 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!msdu)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
return HAL_RX_MON_STATUS_PPDU_NOT_DONE;
|
||||
}
|
||||
@ -1124,7 +1124,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
||||
|
||||
/* PN for multicast packets are not validate in HW,
|
||||
* so skip 802.3 rx path
|
||||
* Also, fast_rx expectes the STA to be authorized, hence
|
||||
* Also, fast_rx expects the STA to be authorized, hence
|
||||
* eapol packets are sent in slow path.
|
||||
*/
|
||||
if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol_tkip &&
|
||||
@ -1268,7 +1268,8 @@ int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
|
||||
struct sk_buff *skb;
|
||||
struct hal_srng *srng;
|
||||
dma_addr_t paddr;
|
||||
u32 cookie, buf_id;
|
||||
u32 cookie;
|
||||
int buf_id;
|
||||
|
||||
srng = &ab->hal.srng_list[buf_ring->refill_buf_ring.ring_id];
|
||||
spin_lock_bh(&srng->lock);
|
||||
@ -1917,7 +1918,7 @@ ath12k_dp_mon_tx_parse_status_tlv(struct ath12k_base *ab,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!msdu)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
return DP_MON_TX_STATUS_PPDU_NOT_DONE;
|
||||
}
|
||||
@ -2110,7 +2111,7 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int mac_id, int *budget,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!skb)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
goto move_next;
|
||||
}
|
||||
@ -2511,7 +2512,7 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
|
||||
spin_unlock_bh(&buf_ring->idr_lock);
|
||||
|
||||
if (unlikely(!skb)) {
|
||||
ath12k_warn(ab, "montior destination with invalid buf_id %d\n",
|
||||
ath12k_warn(ab, "monitor destination with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
goto move_next;
|
||||
}
|
||||
|
@ -2443,7 +2443,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
|
||||
|
||||
/* PN for multicast packets are not validate in HW,
|
||||
* so skip 802.3 rx path
|
||||
* Also, fast_rx expectes the STA to be authorized, hence
|
||||
* Also, fast_rx expects the STA to be authorized, hence
|
||||
* eapol packets are sent in slow path.
|
||||
*/
|
||||
if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol &&
|
||||
@ -2611,7 +2611,7 @@ try_again:
|
||||
if (!desc_info) {
|
||||
desc_info = ath12k_dp_get_rx_desc(ab, cookie);
|
||||
if (!desc_info) {
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrival");
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrieval");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -3297,7 +3297,7 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
|
||||
if (!desc_info) {
|
||||
desc_info = ath12k_dp_get_rx_desc(ab, cookie);
|
||||
if (!desc_info) {
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrival");
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrieval");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -3494,11 +3494,14 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
|
||||
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
|
||||
peer_id = ath12k_dp_rx_h_peer_id(ab, desc);
|
||||
|
||||
spin_lock(&ab->base_lock);
|
||||
if (!ath12k_peer_find_by_id(ab, peer_id)) {
|
||||
spin_unlock(&ab->base_lock);
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n",
|
||||
peer_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_unlock(&ab->base_lock);
|
||||
|
||||
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
|
||||
/* First buffer will be freed by the caller, so deduct it's length */
|
||||
@ -3718,7 +3721,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
||||
if (!desc_info) {
|
||||
desc_info = ath12k_dp_get_rx_desc(ab, err_info.cookie);
|
||||
if (!desc_info) {
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrival");
|
||||
ath12k_warn(ab, "Invalid cookie in manual desc retrieval");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ tcl_ring_sel:
|
||||
skb_ext_desc->len, DMA_TO_DEVICE);
|
||||
ret = dma_mapping_error(ab->dev, ti.paddr);
|
||||
if (ret) {
|
||||
kfree(skb_ext_desc);
|
||||
kfree_skb(skb_ext_desc);
|
||||
goto fail_unmap_dma;
|
||||
}
|
||||
|
||||
|
@ -609,7 +609,7 @@ static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
|
||||
HAL_WBM0_RELEASE_RING_BASE_LSB(ab);
|
||||
s->reg_size[1] = HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP;
|
||||
|
||||
/* Some LMAC rings are not accesed from the host:
|
||||
/* Some LMAC rings are not accessed from the host:
|
||||
* RXDMA_BUG, RXDMA_DST, RXDMA_MONITOR_BUF, RXDMA_MONITOR_STATUS,
|
||||
* RXDMA_MONITOR_DST, RXDMA_MONITOR_DESC, RXDMA_DIR_BUF_SRC,
|
||||
* RXDMA_RX_MONITOR_BUF, TX_MONITOR_BUF, TX_MONITOR_DST, SW2RXDMA
|
||||
|
@ -270,7 +270,7 @@ struct ath12k_base;
|
||||
#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN BIT(5)
|
||||
#define HAL_WBM_SW_COOKIE_CONV_CFG_GLOBAL_EN BIT(8)
|
||||
|
||||
/* TCL ring feild mask and offset */
|
||||
/* TCL ring field mask and offset */
|
||||
#define HAL_TCL1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
|
||||
#define HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
|
||||
#define HAL_TCL1_RING_ID_ENTRY_SIZE GENMASK(7, 0)
|
||||
@ -296,7 +296,7 @@ struct ath12k_base;
|
||||
#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP6 GENMASK(20, 18)
|
||||
#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP7 GENMASK(23, 21)
|
||||
|
||||
/* REO ring feild mask and offset */
|
||||
/* REO ring field mask and offset */
|
||||
#define HAL_REO1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
|
||||
#define HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
|
||||
#define HAL_REO1_RING_ID_RING_ID GENMASK(15, 8)
|
||||
@ -738,7 +738,7 @@ struct hal_srng {
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Interrupt mitigation - Batch threshold in terms of numer of frames */
|
||||
/* Interrupt mitigation - Batch threshold in terms of number of frames */
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_TX 256
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_RX 128
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_OTHER 1
|
||||
@ -813,7 +813,7 @@ enum hal_rx_buf_return_buf_manager {
|
||||
#define HAL_REO_CMD_FLG_UNBLK_RESOURCE BIT(7)
|
||||
#define HAL_REO_CMD_FLG_UNBLK_CACHE BIT(8)
|
||||
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* feilds */
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* fields */
|
||||
#define HAL_REO_CMD_UPD0_RX_QUEUE_NUM BIT(8)
|
||||
#define HAL_REO_CMD_UPD0_VLD BIT(9)
|
||||
#define HAL_REO_CMD_UPD0_ALDC BIT(10)
|
||||
@ -838,7 +838,7 @@ enum hal_rx_buf_return_buf_manager {
|
||||
#define HAL_REO_CMD_UPD0_PN_VALID BIT(29)
|
||||
#define HAL_REO_CMD_UPD0_PN BIT(30)
|
||||
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* feilds */
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* fields */
|
||||
#define HAL_REO_CMD_UPD1_VLD BIT(16)
|
||||
#define HAL_REO_CMD_UPD1_ALDC GENMASK(18, 17)
|
||||
#define HAL_REO_CMD_UPD1_DIS_DUP_DETECTION BIT(19)
|
||||
@ -854,7 +854,7 @@ enum hal_rx_buf_return_buf_manager {
|
||||
#define HAL_REO_CMD_UPD1_PN_HANDLE_ENABLE BIT(30)
|
||||
#define HAL_REO_CMD_UPD1_IGNORE_AMPDU_FLG BIT(31)
|
||||
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* feilds */
|
||||
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* fields */
|
||||
#define HAL_REO_CMD_UPD2_SVLD BIT(10)
|
||||
#define HAL_REO_CMD_UPD2_SSN GENMASK(22, 11)
|
||||
#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(23)
|
||||
|
@ -706,7 +706,7 @@ struct rx_msdu_desc {
|
||||
*
|
||||
* msdu_continuation
|
||||
* When set, this MSDU buffer was not able to hold the entire MSDU.
|
||||
* The next buffer will therefor contain additional information
|
||||
* The next buffer will therefore contain additional information
|
||||
* related to this MSDU.
|
||||
*
|
||||
* msdu_length
|
||||
@ -1294,7 +1294,7 @@ struct hal_tcl_data_cmd {
|
||||
* link descriptor.
|
||||
*
|
||||
* tcl_cmd_type
|
||||
* used to select the type of TCL Command decriptor
|
||||
* used to select the type of TCL Command descriptor
|
||||
*
|
||||
* desc_type
|
||||
* Indicates the type of address provided in the buf_addr_info.
|
||||
@ -1408,7 +1408,7 @@ struct hal_tcl_data_cmd {
|
||||
* index_loop_override
|
||||
* When set, address search and packet routing is forced to use
|
||||
* 'search_index' instead of following the register configuration
|
||||
* seleced by Bank_id.
|
||||
* selected by Bank_id.
|
||||
*
|
||||
* ring_id
|
||||
* The buffer pointer ring ID.
|
||||
@ -1990,7 +1990,7 @@ struct hal_wbm_release_ring {
|
||||
* Producer: SW/TQM/RXDMA/REO/SWITCH
|
||||
* Consumer: WBM/SW/FW
|
||||
*
|
||||
* HTT tx status is overlayed on wbm_release ring on 4-byte words 2, 3, 4 and 5
|
||||
* HTT tx status is overlaid on wbm_release ring on 4-byte words 2, 3, 4 and 5
|
||||
* for software based completions.
|
||||
*
|
||||
* buf_addr_info
|
||||
@ -2552,7 +2552,7 @@ struct hal_reo_status_hdr {
|
||||
* commands.
|
||||
*
|
||||
* execution_time (in us)
|
||||
* The amount of time REO took to excecute the command. Note that
|
||||
* The amount of time REO took to execute the command. Note that
|
||||
* this time does not include the duration of the command waiting
|
||||
* in the command ring, before the execution started.
|
||||
*
|
||||
|
@ -119,6 +119,30 @@ static const char *irq_name[ATH12K_IRQ_NUM_MAX] = {
|
||||
"tcl2host-status-ring",
|
||||
};
|
||||
|
||||
static int ath12k_pci_bus_wake_up(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
|
||||
}
|
||||
|
||||
static void ath12k_pci_bus_release(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
|
||||
}
|
||||
|
||||
static const struct ath12k_pci_ops ath12k_pci_ops_qcn9274 = {
|
||||
.wakeup = NULL,
|
||||
.release = NULL,
|
||||
};
|
||||
|
||||
static const struct ath12k_pci_ops ath12k_pci_ops_wcn7850 = {
|
||||
.wakeup = ath12k_pci_bus_wake_up,
|
||||
.release = ath12k_pci_bus_release,
|
||||
};
|
||||
|
||||
static void ath12k_pci_select_window(struct ath12k_pci *ab_pci, u32 offset)
|
||||
{
|
||||
struct ath12k_base *ab = ab_pci->ab;
|
||||
@ -989,13 +1013,14 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
u32 val, window_start;
|
||||
int ret = 0;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup MHI to access.
|
||||
*/
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup)
|
||||
ret = ab_pci->pci_ops->wakeup(ab);
|
||||
|
||||
if (offset < WINDOW_START) {
|
||||
val = ioread32(ab->mem + offset);
|
||||
@ -1023,9 +1048,9 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset)
|
||||
}
|
||||
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
|
||||
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->release &&
|
||||
!ret)
|
||||
ab_pci->pci_ops->release(ab);
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -1033,13 +1058,14 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
u32 window_start;
|
||||
int ret = 0;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup MHI to access.
|
||||
*/
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->wakeup)
|
||||
ret = ab_pci->pci_ops->wakeup(ab);
|
||||
|
||||
if (offset < WINDOW_START) {
|
||||
iowrite32(value, ab->mem + offset);
|
||||
@ -1067,8 +1093,9 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
|
||||
}
|
||||
|
||||
if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
|
||||
offset >= ACCESS_ALWAYS_OFF)
|
||||
mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
|
||||
offset >= ACCESS_ALWAYS_OFF && ab_pci->pci_ops->release &&
|
||||
!ret)
|
||||
ab_pci->pci_ops->release(ab);
|
||||
}
|
||||
|
||||
int ath12k_pci_power_up(struct ath12k_base *ab)
|
||||
@ -1182,6 +1209,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
||||
case QCN9274_DEVICE_ID:
|
||||
ab_pci->msi_config = &ath12k_msi_config[0];
|
||||
ab->static_window_map = true;
|
||||
ab_pci->pci_ops = &ath12k_pci_ops_qcn9274;
|
||||
ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
|
||||
&soc_hw_version_minor);
|
||||
switch (soc_hw_version_major) {
|
||||
@ -1202,6 +1230,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
||||
ab_pci->msi_config = &ath12k_msi_config[0];
|
||||
ab->static_window_map = false;
|
||||
ab->hw_rev = ATH12K_HW_WCN7850_HW20;
|
||||
ab_pci->pci_ops = &ath12k_pci_ops_wcn7850;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -86,6 +86,11 @@ enum ath12k_pci_flags {
|
||||
ATH12K_PCI_ASPM_RESTORE,
|
||||
};
|
||||
|
||||
struct ath12k_pci_ops {
|
||||
int (*wakeup)(struct ath12k_base *ab);
|
||||
void (*release)(struct ath12k_base *ab);
|
||||
};
|
||||
|
||||
struct ath12k_pci {
|
||||
struct pci_dev *pdev;
|
||||
struct ath12k_base *ab;
|
||||
@ -103,6 +108,7 @@ struct ath12k_pci {
|
||||
/* enum ath12k_pci_flags */
|
||||
unsigned long flags;
|
||||
u16 link_ctl;
|
||||
const struct ath12k_pci_ops *pci_ops;
|
||||
};
|
||||
|
||||
static inline struct ath12k_pci *ath12k_pci_priv(struct ath12k_base *ab)
|
||||
|
@ -1072,7 +1072,7 @@ struct rx_msdu_end_qcn9274 {
|
||||
*
|
||||
* l4_offset
|
||||
* Depending upon mode bit, this field either indicates the
|
||||
* L4 offset nin bytes from the start of RX_HEADER (only valid
|
||||
* L4 offset in bytes from the start of RX_HEADER (only valid
|
||||
* if either ipv4_proto or ipv6_proto is set to 1) or indicates
|
||||
* the offset in bytes to the start of TCP or UDP header from
|
||||
* the start of the IP header after decapsulation (Only valid if
|
||||
|
@ -494,7 +494,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
|
||||
|
||||
/* tx/rx chainmask reported from fw depends on the actual hw chains used,
|
||||
* For example, for 4x4 capable macphys, first 4 chains can be used for first
|
||||
* mac and the remaing 4 chains can be used for the second mac or vice-versa.
|
||||
* mac and the remaining 4 chains can be used for the second mac or vice-versa.
|
||||
* In this case, tx/rx chainmask 0xf will be advertised for first mac and 0xf0
|
||||
* will be advertised for second mac or vice-versa. Compute the shift value
|
||||
* for tx/rx chainmask which will be used to advertise supported ht/vht rates to
|
||||
@ -1743,7 +1743,7 @@ int ath12k_wmi_vdev_install_key(struct ath12k *ar,
|
||||
int ret, len, key_len_aligned;
|
||||
|
||||
/* WMI_TAG_ARRAY_BYTE needs to be aligned with 4, the actual key
|
||||
* length is specifed in cmd->key_len.
|
||||
* length is specified in cmd->key_len.
|
||||
*/
|
||||
key_len_aligned = roundup(arg->key_len, 4);
|
||||
|
||||
@ -5995,7 +5995,7 @@ static void ath12k_service_available_event(struct ath12k_base *ab, struct sk_buf
|
||||
}
|
||||
|
||||
/* TODO: Use wmi_service_segment_offset information to get the service
|
||||
* especially when more services are advertised in multiple sevice
|
||||
* especially when more services are advertised in multiple service
|
||||
* available events.
|
||||
*/
|
||||
for (i = 0, j = WMI_MAX_SERVICE;
|
||||
|
@ -4002,7 +4002,7 @@ struct ath12k_wmi_pdev_radar_event {
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_temperature_event {
|
||||
/* temperature value in Celcius degree */
|
||||
/* temperature value in Celsius degree */
|
||||
a_sle32 temp;
|
||||
__le32 pdev_id;
|
||||
} __packed;
|
||||
@ -4192,7 +4192,7 @@ enum wmi_sta_ps_param_tx_wake_threshold {
|
||||
*/
|
||||
enum wmi_sta_ps_param_pspoll_count {
|
||||
WMI_STA_PS_PSPOLL_COUNT_NO_MAX = 0,
|
||||
/* Values greater than 0 indicate the maximum numer of PS-Poll frames
|
||||
/* Values greater than 0 indicate the maximum number of PS-Poll frames
|
||||
* FW will send before waking up.
|
||||
*/
|
||||
};
|
||||
|
@ -113,15 +113,13 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no IRQ resource found\n");
|
||||
ret = -ENXIO;
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq);
|
||||
ret = irq;
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
irq = res->start;
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
|
||||
if (hw == NULL) {
|
||||
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
|
||||
|
@ -529,7 +529,7 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
|
||||
ee->ee_n_piers[mode]++;
|
||||
|
||||
freq2 = (val >> 8) & 0xff;
|
||||
if (!freq2)
|
||||
if (!freq2 || i >= max)
|
||||
break;
|
||||
|
||||
pc[i++].freq = ath5k_eeprom_bin2freq(ee,
|
||||
|
@ -246,7 +246,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
size = sizeof(cid) + sizeof(addr) + sizeof(param);
|
||||
size = sizeof(cid) + sizeof(addr) + sizeof(*param);
|
||||
if (size > ar->bmi.max_cmd_size) {
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
|
@ -960,8 +960,8 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
|
||||
* Thus the possibility of ar->htc_target being NULL
|
||||
* via ath6kl_recv_complete -> ath6kl_usb_io_comp_work.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!target)) {
|
||||
ath6kl_err("Target not yet initialized\n");
|
||||
if (!target) {
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC, "Target not yet initialized\n");
|
||||
status = -EINVAL;
|
||||
goto free_skb;
|
||||
}
|
||||
|
@ -534,6 +534,24 @@ static struct ath9k_htc_hif hif_usb = {
|
||||
.send = hif_usb_send,
|
||||
};
|
||||
|
||||
/* Need to free remain_skb allocated in ath9k_hif_usb_rx_stream
|
||||
* in case ath9k_hif_usb_rx_stream wasn't called next time to
|
||||
* process the buffer and subsequently free it.
|
||||
*/
|
||||
static void ath9k_hif_usb_free_rx_remain_skb(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hif_dev->rx_lock, flags);
|
||||
if (hif_dev->remain_skb) {
|
||||
dev_kfree_skb_any(hif_dev->remain_skb);
|
||||
hif_dev->remain_skb = NULL;
|
||||
hif_dev->rx_remain_len = 0;
|
||||
RX_STAT_INC(hif_dev, skb_dropped);
|
||||
}
|
||||
spin_unlock_irqrestore(&hif_dev->rx_lock, flags);
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -868,6 +886,7 @@ err:
|
||||
static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
usb_kill_anchored_urbs(&hif_dev->rx_submitted);
|
||||
ath9k_hif_usb_free_rx_remain_skb(hif_dev);
|
||||
}
|
||||
|
||||
static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
|
||||
|
@ -503,7 +503,7 @@ int ath_key_config(struct ath_common *common,
|
||||
|
||||
hk.kv_len = key->keylen;
|
||||
if (key->keylen)
|
||||
memcpy(hk.kv_val, key->key, key->keylen);
|
||||
memcpy(&hk.kv_values, key->key, key->keylen);
|
||||
|
||||
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
switch (vif->type) {
|
||||
|
@ -475,8 +475,8 @@ out:
|
||||
|
||||
#define PREPARE_HAL_BUF(send_buf, msg_body) \
|
||||
do { \
|
||||
memset(send_buf, 0, msg_body.header.len); \
|
||||
memcpy(send_buf, &msg_body, sizeof(msg_body)); \
|
||||
memcpy_and_pad(send_buf, msg_body.header.len, \
|
||||
&msg_body, sizeof(msg_body), 0); \
|
||||
} while (0) \
|
||||
|
||||
#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
|
||||
|
@ -6280,6 +6280,11 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
|
||||
(struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;
|
||||
req_len = le32_to_cpu(assoc_info->req_len);
|
||||
resp_len = le32_to_cpu(assoc_info->resp_len);
|
||||
if (req_len > WL_EXTRA_BUF_MAX || resp_len > WL_EXTRA_BUF_MAX) {
|
||||
bphy_err(drvr, "invalid lengths in assoc info: req %u resp %u\n",
|
||||
req_len, resp_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (req_len) {
|
||||
err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
|
||||
cfg->extra_buf,
|
||||
@ -7881,6 +7886,7 @@ static bool brmcf_use_iso3166_ccode_fallback(struct brcmf_pub *drvr)
|
||||
switch (drvr->bus_if->chip) {
|
||||
case BRCM_CC_43430_CHIP_ID:
|
||||
case BRCM_CC_4345_CHIP_ID:
|
||||
case BRCM_CC_4356_CHIP_ID:
|
||||
case BRCM_CC_43602_CHIP_ID:
|
||||
return true;
|
||||
default:
|
||||
|
@ -1234,9 +1234,9 @@ static struct ipw_fw_error *ipw_alloc_error_log(struct ipw_priv *priv)
|
||||
u32 base = ipw_read32(priv, IPW_ERROR_LOG);
|
||||
u32 elem_len = ipw_read_reg32(priv, base);
|
||||
|
||||
error = kmalloc(sizeof(*error) +
|
||||
sizeof(*error->elem) * elem_len +
|
||||
sizeof(*error->log) * log_len, GFP_ATOMIC);
|
||||
error = kmalloc(size_add(struct_size(error, elem, elem_len),
|
||||
array_size(sizeof(*error->log), log_len)),
|
||||
GFP_ATOMIC);
|
||||
if (!error) {
|
||||
IPW_ERROR("Memory allocation for firmware error log "
|
||||
"failed.\n");
|
||||
@ -1247,7 +1247,6 @@ static struct ipw_fw_error *ipw_alloc_error_log(struct ipw_priv *priv)
|
||||
error->config = priv->config;
|
||||
error->elem_len = elem_len;
|
||||
error->log_len = log_len;
|
||||
error->elem = (struct ipw_error_elem *)error->payload;
|
||||
error->log = (struct ipw_event *)(error->elem + elem_len);
|
||||
|
||||
ipw_capture_event_log(priv, log_len, error->log);
|
||||
|
@ -1106,9 +1106,8 @@ struct ipw_fw_error { /* XXX */
|
||||
u32 config;
|
||||
u32 elem_len;
|
||||
u32 log_len;
|
||||
struct ipw_error_elem *elem;
|
||||
struct ipw_event *log;
|
||||
u8 payload[];
|
||||
struct ipw_error_elem elem[];
|
||||
} __packed;
|
||||
|
||||
#ifdef CONFIG_IPW2200_PROMISCUOUS
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "fw/api/txq.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MAX 74
|
||||
#define IWL_22000_UCODE_API_MAX 75
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 39
|
||||
@ -57,6 +57,8 @@
|
||||
#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-"
|
||||
#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-"
|
||||
#define IWL_BZ_A_FM4_A_FW_PRE "iwlwifi-bz-a0-fm4-a0-"
|
||||
#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0-"
|
||||
#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0-"
|
||||
#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm-a0-"
|
||||
#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0-"
|
||||
#define IWL_BZ_Z_GF_A_FW_PRE "iwlwifi-bz-z0-gf-a0-"
|
||||
@ -64,8 +66,11 @@
|
||||
#define IWL_BNJ_A_FM4_A_FW_PRE "iwlwifi-BzBnj-a0-fm4-a0-"
|
||||
#define IWL_BNJ_B_FM4_B_FW_PRE "iwlwifi-BzBnj-b0-fm4-b0-"
|
||||
#define IWL_BNJ_A_GF_A_FW_PRE "iwlwifi-BzBnj-a0-gf-a0-"
|
||||
#define IWL_BNJ_B_GF_A_FW_PRE "iwlwifi-BzBnj-b0-gf-a0-"
|
||||
#define IWL_BNJ_A_GF4_A_FW_PRE "iwlwifi-BzBnj-a0-gf4-a0-"
|
||||
#define IWL_BNJ_B_GF4_A_FW_PRE "iwlwifi-BzBnj-b0-gf4-a0-"
|
||||
#define IWL_BNJ_A_HR_B_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
|
||||
#define IWL_BNJ_B_HR_B_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-"
|
||||
#define IWL_BNJ_B_FM_B_FW_PRE "iwlwifi-BzBnj-b0-fm-b0-"
|
||||
|
||||
|
||||
@ -125,6 +130,10 @@
|
||||
IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_FM4_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_FM_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_A_FM4_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
|
||||
IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \
|
||||
@ -137,10 +146,16 @@
|
||||
IWL_BNJ_B_FM4_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_A_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_A_GF_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_B_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_B_GF_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_B_GF4_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_A_HR_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_B_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_B_HR_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_B_FM_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_B_FM_B_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
@ -281,7 +296,7 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = {
|
||||
.trans.gen2 = true, \
|
||||
.nvm_type = IWL_NVM_EXT, \
|
||||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0x400000, \
|
||||
.min_umac_error_event_table = 0xD0000, \
|
||||
.d3_debug_data_base_addr = 0x401000, \
|
||||
.d3_debug_data_length = 60 * 1024, \
|
||||
.mon_smem_regs = { \
|
||||
@ -961,6 +976,22 @@ const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0 = {
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bz_a0_fm_b0 = {
|
||||
.fw_name_pre = IWL_BZ_A_FM_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0 = {
|
||||
.fw_name_pre = IWL_BZ_A_FM4_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
|
||||
.fw_name_pre = IWL_GL_A_FM_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
@ -1017,6 +1048,14 @@ const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0 = {
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_B_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_GF4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
@ -1025,6 +1064,14 @@ const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0 = {
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_B_GF4_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_HR_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
@ -1033,6 +1080,14 @@ const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = {
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0 = {
|
||||
.fw_name_pre = IWL_BNJ_B_HR_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0 = {
|
||||
.fw_name_pre = IWL_BNJ_B_FM_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
@ -1067,13 +1122,18 @@ MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_B_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
@ -265,6 +265,24 @@ enum iwl_legacy_cmds {
|
||||
*/
|
||||
HOT_SPOT_CMD = 0x53,
|
||||
|
||||
/**
|
||||
* @WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION: Time Sync
|
||||
* measurement notification for TM/FTM. Sent on receipt of
|
||||
* respective WNM action frame for TM protocol or public action
|
||||
* frame for FTM protocol from peer device along with additional
|
||||
* meta data specified in &struct iwl_time_msmt_notify
|
||||
*/
|
||||
WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION = 0x67,
|
||||
|
||||
/**
|
||||
* @WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION: Time Sync
|
||||
* measurement confirmation notification for TM/FTM. Sent on
|
||||
* receipt of Ack from peer for previously Tx'ed TM/FTM
|
||||
* action frame along with additional meta data specified in
|
||||
* &struct iwl_time_msmt_cfm_notify
|
||||
*/
|
||||
WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION = 0x68,
|
||||
|
||||
/**
|
||||
* @SCAN_OFFLOAD_COMPLETE:
|
||||
* notification, &struct iwl_periodic_scan_complete
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -26,6 +26,17 @@ enum iwl_data_path_subcmd_ids {
|
||||
*/
|
||||
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
|
||||
|
||||
/**
|
||||
* @WNM_PLATFORM_PTM_REQUEST_CMD: &struct iwl_time_sync_cfg_cmd
|
||||
*/
|
||||
WNM_PLATFORM_PTM_REQUEST_CMD = 0x3,
|
||||
|
||||
/**
|
||||
* @WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD:
|
||||
* &struct iwl_time_sync_cfg_cmd
|
||||
*/
|
||||
WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD = 0x4,
|
||||
|
||||
/**
|
||||
* @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd
|
||||
*/
|
||||
@ -146,6 +157,177 @@ enum iwl_channel_estimation_flags {
|
||||
IWL_CHANNEL_ESTIMATION_COUNTER = BIT(2),
|
||||
};
|
||||
|
||||
enum iwl_time_sync_protocol_type {
|
||||
IWL_TIME_SYNC_PROTOCOL_TM = BIT(0),
|
||||
IWL_TIME_SYNC_PROTOCOL_FTM = BIT(1),
|
||||
}; /* WNM_TIMING_ENABLED_PROTOCOL_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_time_sync_cfg_cmd - TM/FTM time sync measurement configuration
|
||||
*
|
||||
* @protocols: The type of frames to raise notifications for. A bitmap
|
||||
* of @iwl_time_sync_protocol_type
|
||||
* @peer_addr: peer address with which TM/FTM measurements are required
|
||||
* @reserved: for alignment
|
||||
*/
|
||||
struct iwl_time_sync_cfg_cmd {
|
||||
__le32 protocols;
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
u8 reserved[2];
|
||||
} __packed; /* WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_synced_time_operation - PTM request options
|
||||
*
|
||||
* @IWL_SYNCED_TIME_OPERATION_READ_ARTB: read only the ARTB time
|
||||
* @IWL_SYNCED_TIME_OPERATION_READ_GP2: read only the GP2 time
|
||||
* @IWL_SYNCED_TIME_OPERATION_READ_BOTH: latch the ARTB and GP2 clocks and
|
||||
* provide timestamps from both clocks for the same time point
|
||||
*/
|
||||
enum iwl_synced_time_operation {
|
||||
IWL_SYNCED_TIME_OPERATION_READ_ARTB = 1,
|
||||
IWL_SYNCED_TIME_OPERATION_READ_GP2,
|
||||
IWL_SYNCED_TIME_OPERATION_READ_BOTH,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_synced_time_cmd - request synced GP2/ARTB timestamps
|
||||
*
|
||||
* @operation: one of &enum iwl_synced_time_operation
|
||||
*/
|
||||
struct iwl_synced_time_cmd {
|
||||
__le32 operation;
|
||||
} __packed; /* WNM_80211V_TIMING_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_synced_time_rsp - response to iwl_synced_time_cmd
|
||||
*
|
||||
* @operation: one of &enum iwl_synced_time_operation
|
||||
* @platform_timestamp_hi: high DWORD of the ARTB clock timestamp in nanoseconds
|
||||
* @platform_timestamp_lo: low DWORD of the ARTB clock timestamp in nanoseconds
|
||||
* @gp2_timestamp_hi: high DWORD of the GP2 clock timestamp in 10's of
|
||||
* nanoseconds
|
||||
* @gp2_timestamp_lo: low DWORD of the GP2 clock timestamp in 10's of
|
||||
* nanoseconds
|
||||
*/
|
||||
struct iwl_synced_time_rsp {
|
||||
__le32 operation;
|
||||
__le32 platform_timestamp_hi;
|
||||
__le32 platform_timestamp_lo;
|
||||
__le32 gp2_timestamp_hi;
|
||||
__le32 gp2_timestamp_lo;
|
||||
} __packed; /* WNM_80211V_TIMING_RSP_API_S_VER_1 */
|
||||
|
||||
/* PTP_CTX_MAX_DATA_SIZE_IN_API_D_VER_1 */
|
||||
#define PTP_CTX_MAX_DATA_SIZE 128
|
||||
|
||||
/**
|
||||
* struct iwl_time_msmt_ptp_ctx - Vendor specific information element
|
||||
* to allow a space for flexibility for the userspace App
|
||||
*
|
||||
* @element_id: element id of vendor specific ie
|
||||
* @length: length of vendor specific ie
|
||||
* @reserved: for alignment
|
||||
* @data: vendor specific data blob
|
||||
*/
|
||||
struct iwl_time_msmt_ptp_ctx {
|
||||
/* Differentiate between FTM and TM specific Vendor IEs */
|
||||
union {
|
||||
struct {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
__le16 reserved;
|
||||
u8 data[PTP_CTX_MAX_DATA_SIZE];
|
||||
} ftm; /* FTM specific vendor IE */
|
||||
struct {
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 data[PTP_CTX_MAX_DATA_SIZE];
|
||||
} tm; /* TM specific vendor IE */
|
||||
};
|
||||
} __packed /* PTP_CTX_VER_1 */;
|
||||
|
||||
/**
|
||||
* struct iwl_time_msmt_notify - Time Sync measurement notification
|
||||
* for TM/FTM, along with additional meta data.
|
||||
*
|
||||
* @peer_addr: peer address
|
||||
* @reserved: for alignment
|
||||
* @dialog_token: measurement flow dialog token number
|
||||
* @followup_dialog_token: Measurement flow previous dialog token number
|
||||
* @t1_hi: high dword of t1-time of the Tx'ed action frame departure on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t1_lo: low dword of t1-time of the Tx'ed action frame departure on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t1_max_err: maximum t1-time error in units of 10 nano seconds
|
||||
* @t4_hi: high dword of t4-time of the Rx'ed action frame's Ack arrival on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t4_lo: low dword of t4-time of the Rx'ed action frame's Ack arrival on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t4_max_err: maximum t4-time error in units of 10 nano seconds
|
||||
* @t2_hi: high dword of t2-time of the Rx'ed action frame arrival on
|
||||
* receiver side in units of 10 nano seconds
|
||||
* @t2_lo: low dword of t2-time of the Rx'ed action frame arrival on
|
||||
* receiver side in units of 10 nano seconds
|
||||
* @t2_max_err: maximum t2-time error in units of 10 nano seconds
|
||||
* @t3_hi: high dword of t3-time of the Tx'ed action frame's Ack departure on
|
||||
* receiver side in units of 10 nano seconds
|
||||
* @t3_lo: low dword of t3-time of the Tx'ed action frame's Ack departure on
|
||||
* receiver side in units of 10 nano seconds
|
||||
* @t3_max_err: maximum t3-time error in units of 10 nano seconds
|
||||
* @ptp: vendor specific information element
|
||||
*/
|
||||
struct iwl_time_msmt_notify {
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
u8 reserved[2];
|
||||
__le32 dialog_token;
|
||||
__le32 followup_dialog_token;
|
||||
__le32 t1_hi;
|
||||
__le32 t1_lo;
|
||||
__le32 t1_max_err;
|
||||
__le32 t4_hi;
|
||||
__le32 t4_lo;
|
||||
__le32 t4_max_err;
|
||||
__le32 t2_hi;
|
||||
__le32 t2_lo;
|
||||
__le32 t2_max_err;
|
||||
__le32 t3_hi;
|
||||
__le32 t3_lo;
|
||||
__le32 t3_max_err;
|
||||
struct iwl_time_msmt_ptp_ctx ptp;
|
||||
} __packed; /* WNM_80211V_TIMING_MEASUREMENT_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_time_msmt_cfm_notify - Time Sync measurement confirmation
|
||||
* notification for TM/FTM. Sent on receipt of 802.11 Ack from peer for the
|
||||
* Tx'ed TM/FTM measurement action frame.
|
||||
*
|
||||
* @peer_addr: peer address
|
||||
* @reserved: for alignment
|
||||
* @dialog_token: measurement flow dialog token number
|
||||
* @t1_hi: high dword of t1-time of the Tx'ed action frame departure on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t1_lo: low dword of t1-time of the Tx'ed action frame departure on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t1_max_err: maximum t1-time error in units of 10 nano seconds
|
||||
* @t4_hi: high dword of t4-time of the Rx'ed action frame's Ack arrival on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t4_lo: low dword of t4-time of the Rx'ed action frame's Ack arrival on
|
||||
* sender side in units of 10 nano seconds
|
||||
* @t4_max_err: maximum t4-time error in units of 10 nano seconds
|
||||
*/
|
||||
struct iwl_time_msmt_cfm_notify {
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
u8 reserved[2];
|
||||
__le32 dialog_token;
|
||||
__le32 t1_hi;
|
||||
__le32 t1_lo;
|
||||
__le32 t1_max_err;
|
||||
__le32 t4_hi;
|
||||
__le32 t4_lo;
|
||||
__le32 t4_max_err;
|
||||
} __packed; /* WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_channel_estimation_cfg - channel estimation reporting config
|
||||
*/
|
||||
|
@ -42,6 +42,12 @@ enum iwl_debug_cmds {
|
||||
* &struct iwl_buf_alloc_cmd
|
||||
*/
|
||||
BUFFER_ALLOCATION = 0x8,
|
||||
/**
|
||||
* @GET_TAS_STATUS:
|
||||
* sends command to fw to get TAS status
|
||||
* the response is &struct iwl_mvm_tas_status_resp
|
||||
*/
|
||||
GET_TAS_STATUS = 0xA,
|
||||
/**
|
||||
* @FW_DUMP_COMPLETE_CMD:
|
||||
* sends command to fw once dump collection completed
|
||||
@ -421,4 +427,94 @@ struct iwl_dbg_dump_complete_cmd {
|
||||
__le32 tp_data;
|
||||
} __packed; /* FW_DUMP_COMPLETE_CMD_API_S_VER_1 */
|
||||
|
||||
#define TAS_LMAC_BAND_HB 0
|
||||
#define TAS_LMAC_BAND_LB 1
|
||||
#define TAS_LMAC_BAND_UHB 2
|
||||
#define TAS_LMAC_BAND_INVALID 3
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tas_status_per_mac - tas status per lmac
|
||||
* @static_status: tas statically enabled or disabled per lmac - TRUE/FALSE
|
||||
* @static_dis_reason: TAS static disable reason, uses
|
||||
* &enum iwl_mvm_tas_statically_disabled_reason
|
||||
* @dynamic_status: Current TAS status. uses
|
||||
* &enum iwl_mvm_tas_dyna_status
|
||||
* @near_disconnection: is TAS currently near disconnection per lmac? - TRUE/FALSE
|
||||
* @max_reg_pwr_limit: Regulatory power limits in dBm
|
||||
* @sar_limit: SAR limits per lmac in dBm
|
||||
* @band: Band per lmac
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_mvm_tas_status_per_mac {
|
||||
u8 static_status;
|
||||
u8 static_dis_reason;
|
||||
u8 dynamic_status;
|
||||
u8 near_disconnection;
|
||||
__le16 max_reg_pwr_limit;
|
||||
__le16 sar_limit;
|
||||
u8 band;
|
||||
u8 reserved[3];
|
||||
} __packed; /*DEBUG_GET_TAS_STATUS_PER_MAC_S_VER_1*/
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_tas_status_resp - Response to GET_TAS_STATUS
|
||||
* @tas_fw_version: TAS FW version
|
||||
* @is_uhb_for_usa_enable: is UHB enabled in USA? - TRUE/FALSE
|
||||
* @curr_mcc: current mcc
|
||||
* @block_list: country block list
|
||||
* @tas_status_mac: TAS status per lmac, uses
|
||||
* &struct iwl_mvm_tas_status_per_mac
|
||||
* @in_dual_radio: is TAS in dual radio? - TRUE/FALSE
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_mvm_tas_status_resp {
|
||||
u8 tas_fw_version;
|
||||
u8 is_uhb_for_usa_enable;
|
||||
__le16 curr_mcc;
|
||||
__le16 block_list[16];
|
||||
struct iwl_mvm_tas_status_per_mac tas_status_mac[2];
|
||||
u8 in_dual_radio;
|
||||
u8 reserved[3];
|
||||
} __packed; /*DEBUG_GET_TAS_STATUS_RSP_API_S_VER_3*/
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_tas_dyna_status - TAS current running status
|
||||
* @TAS_DYNA_INACTIVE: TAS status is inactive
|
||||
* @TAS_DYNA_INACTIVE_MVM_MODE: TAS is disabled due because FW is in MVM mode
|
||||
* or is in softap mode.
|
||||
* @TAS_DYNA_INACTIVE_TRIGGER_MODE: TAS is disabled because FW is in
|
||||
* multi user trigger mode
|
||||
* @TAS_DYNA_INACTIVE_BLOCK_LISTED: TAS is disabled because current mcc
|
||||
* is blocklisted mcc
|
||||
* @TAS_DYNA_INACTIVE_UHB_NON_US: TAS is disabled because current band is UHB
|
||||
* and current mcc is USA
|
||||
* @TAS_DYNA_ACTIVE: TAS is currently active
|
||||
* @TAS_DYNA_STATUS_MAX: TAS status max value
|
||||
*/
|
||||
enum iwl_mvm_tas_dyna_status {
|
||||
TAS_DYNA_INACTIVE,
|
||||
TAS_DYNA_INACTIVE_MVM_MODE,
|
||||
TAS_DYNA_INACTIVE_TRIGGER_MODE,
|
||||
TAS_DYNA_INACTIVE_BLOCK_LISTED,
|
||||
TAS_DYNA_INACTIVE_UHB_NON_US,
|
||||
TAS_DYNA_ACTIVE,
|
||||
|
||||
TAS_DYNA_STATUS_MAX,
|
||||
}; /*_TAS_DYNA_STATUS_E*/
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_tas_statically_disabled_reason - TAS statically disabled reason
|
||||
* @TAS_DISABLED_DUE_TO_BIOS: TAS is disabled because TAS is disabled in BIOS
|
||||
* @TAS_DISABLED_DUE_TO_SAR_6DBM: TAS is disabled because SAR limit is less than 6 Dbm
|
||||
* @TAS_DISABLED_REASON_INVALID: TAS disable reason is invalid
|
||||
* @TAS_DISABLED_REASON_MAX: TAS disable reason max value
|
||||
*/
|
||||
enum iwl_mvm_tas_statically_disabled_reason {
|
||||
TAS_DISABLED_DUE_TO_BIOS,
|
||||
TAS_DISABLED_DUE_TO_SAR_6DBM,
|
||||
TAS_DISABLED_REASON_INVALID,
|
||||
|
||||
TAS_DISABLED_REASON_MAX,
|
||||
}; /*_TAS_STATICALLY_DISABLED_REASON_E*/
|
||||
|
||||
#endif /* __iwl_fw_api_debug_h__ */
|
||||
|
@ -1,12 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2019, 2021-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_mac_cfg_h__
|
||||
#define __iwl_fw_api_mac_cfg_h__
|
||||
|
||||
#include "mac.h"
|
||||
|
||||
/**
|
||||
* enum iwl_mac_conf_subcmd_ids - mac configuration command IDs
|
||||
*/
|
||||
@ -31,7 +33,30 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
* @CANCEL_CHANNEL_SWITCH_CMD: &struct iwl_cancel_channel_switch_cmd
|
||||
*/
|
||||
CANCEL_CHANNEL_SWITCH_CMD = 0x6,
|
||||
|
||||
/**
|
||||
* @MAC_CONFIG_CMD: &struct iwl_mac_config_cmd
|
||||
*/
|
||||
MAC_CONFIG_CMD = 0x8,
|
||||
/**
|
||||
* @LINK_CONFIG_CMD: &struct iwl_link_config_cmd
|
||||
*/
|
||||
LINK_CONFIG_CMD = 0x9,
|
||||
/**
|
||||
* @STA_CONFIG_CMD: &struct iwl_mvm_sta_cfg_cmd
|
||||
*/
|
||||
STA_CONFIG_CMD = 0xA,
|
||||
/**
|
||||
* @AUX_STA_CMD: &struct iwl_mvm_aux_sta_cmd
|
||||
*/
|
||||
AUX_STA_CMD = 0xB,
|
||||
/**
|
||||
* @STA_REMOVE_CMD: &struct iwl_mvm_remove_sta_cmd
|
||||
*/
|
||||
STA_REMOVE_CMD = 0xC,
|
||||
/**
|
||||
* @STA_DISABLE_TX_CMD: &struct iwl_mvm_sta_disable_tx_cmd
|
||||
*/
|
||||
STA_DISABLE_TX_CMD = 0xD,
|
||||
/**
|
||||
* @SESSION_PROTECTION_NOTIF: &struct iwl_mvm_session_prot_notif
|
||||
*/
|
||||
@ -182,4 +207,401 @@ struct iwl_mac_low_latency_cmd {
|
||||
__le16 reserved;
|
||||
} __packed; /* MAC_LOW_LATENCY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_client_data - configuration data for client MAC context
|
||||
*
|
||||
* @is_assoc: 1 for associated state, 0 otherwise
|
||||
* @assoc_id: unique ID assigned by the AP during association
|
||||
* @data_policy: see &enum iwl_mac_data_policy
|
||||
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
|
||||
* 0 indicates that there is no CT window.
|
||||
*/
|
||||
struct iwl_mac_client_data {
|
||||
__le32 is_assoc;
|
||||
__le32 assoc_id;
|
||||
__le32 data_policy;
|
||||
__le32 ctwin;
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_go_ibss_data - configuration data for GO and IBSS MAC context
|
||||
*
|
||||
* @beacon_template: beacon template ID
|
||||
*/
|
||||
struct iwl_mac_go_ibss_data {
|
||||
__le32 beacon_template;
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_GO_IBSS_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_p2p_dev_data - configuration data for P2P device MAC context
|
||||
*
|
||||
* @is_disc_extended: if set to true, P2P Device discoverability is enabled on
|
||||
* other channels as well. This should be to true only in case that the
|
||||
* device is discoverable and there is an active GO. Note that setting this
|
||||
* field when not needed, will increase the number of interrupts and have
|
||||
* effect on the platform power, as this setting opens the Rx filters on
|
||||
* all macs.
|
||||
*/
|
||||
struct iwl_mac_p2p_dev_data {
|
||||
__le32 is_disc_extended;
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_P2P_DEV_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_mac_config_filter_flags - MAC context configuration filter flags
|
||||
*
|
||||
* @MAC_CFG_FILTER_PROMISC: accept all data frames
|
||||
* @MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT: pass all management and
|
||||
* control frames to the host
|
||||
* @MAC_CFG_FILTER_ACCEPT_GRP: accept multicast frames
|
||||
* @MAC_CFG_FILTER_ACCEPT_BEACON: accept beacon frames
|
||||
* @MAC_CFG_FILTER_ACCEPT_BCAST_PROBE_RESP: accept broadcast probe response
|
||||
* @MAC_CFG_FILTER_ACCEPT_PROBE_REQ: accept probe requests
|
||||
*/
|
||||
enum iwl_mac_config_filter_flags {
|
||||
MAC_CFG_FILTER_PROMISC = BIT(0),
|
||||
MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT = BIT(1),
|
||||
MAC_CFG_FILTER_ACCEPT_GRP = BIT(2),
|
||||
MAC_CFG_FILTER_ACCEPT_BEACON = BIT(3),
|
||||
MAC_CFG_FILTER_ACCEPT_BCAST_PROBE_RESP = BIT(4),
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ = BIT(5),
|
||||
}; /* MAC_FILTER_FLAGS_MASK_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_config_cmd - command structure to configure MAC contexts in
|
||||
* MLD API
|
||||
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
|
||||
*
|
||||
* @id_and_color: ID and color of the MAC
|
||||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @mac_type: one of &enum iwl_mac_types
|
||||
* @local_mld_addr: mld address
|
||||
* @reserved_for_local_mld_addr: reserved
|
||||
* @filter_flags: combination of &enum iwl_mac_config_filter_flags
|
||||
* @he_support: does this MAC support HE
|
||||
* @eht_support: does this MAC support EHT. Requires he_support
|
||||
* @nic_not_ack_enabled: mark that the NIC doesn't support receiving
|
||||
* ACK-enabled AGG, (i.e. both BACK and non-BACK frames in single AGG).
|
||||
* If the NIC is not ACK_ENABLED it may use the EOF-bit in first non-0
|
||||
* len delim to determine if AGG or single.
|
||||
* @client: client mac data
|
||||
* @go_ibss: mac data for go or ibss
|
||||
* @p2p_dev: mac data for p2p device
|
||||
*/
|
||||
struct iwl_mac_config_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* MAC_CONTEXT_TYPE_API_E */
|
||||
__le32 mac_type;
|
||||
u8 local_mld_addr[6];
|
||||
__le16 reserved_for_local_mld_addr;
|
||||
__le32 filter_flags;
|
||||
__le32 he_support;
|
||||
__le32 eht_support;
|
||||
__le32 nic_not_ack_enabled;
|
||||
/* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_1 */
|
||||
union {
|
||||
struct iwl_mac_client_data client;
|
||||
struct iwl_mac_go_ibss_data go_ibss;
|
||||
struct iwl_mac_p2p_dev_data p2p_dev;
|
||||
};
|
||||
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
|
||||
* modified in &iwl_link_ctx_cfg_cmd
|
||||
*
|
||||
* @LINK_CONTEXT_MODIFY_ACTIVE: covers iwl_link_ctx_cfg_cmd::active
|
||||
* @LINK_CONTEXT_MODIFY_RATES_INFO: covers iwl_link_ctx_cfg_cmd::cck_rates,
|
||||
* iwl_link_ctx_cfg_cmd::ofdm_rates,
|
||||
* iwl_link_ctx_cfg_cmd::cck_short_preamble,
|
||||
* iwl_link_ctx_cfg_cmd::short_slot
|
||||
* @LINK_CONTEXT_MODIFY_PROTECT_FLAGS: covers
|
||||
* iwl_link_ctx_cfg_cmd::protection_flags
|
||||
* @LINK_CONTEXT_MODIFY_QOS_PARAMS: covers iwl_link_ctx_cfg_cmd::qos_flags,
|
||||
* iwl_link_ctx_cfg_cmd::ac,
|
||||
* @LINK_CONTEXT_MODIFY_BEACON_TIMING: covers iwl_link_ctx_cfg_cmd::bi,
|
||||
* iwl_link_ctx_cfg_cmd::dtim_interval,
|
||||
* iwl_link_ctx_cfg_cmd::dtim_time,
|
||||
* iwl_link_ctx_cfg_cmd::dtim_tsf,
|
||||
* iwl_link_ctx_cfg_cmd::assoc_beacon_arrive_time.
|
||||
* This flag can be set only once after assoc.
|
||||
* @LINK_CONTEXT_MODIFY_HE_PARAMS: covers
|
||||
* iwl_link_ctx_cfg_cmd::htc_trig_based_pkt_ext
|
||||
* iwl_link_ctx_cfg_cmd::rand_alloc_ecwmin,
|
||||
* iwl_link_ctx_cfg_cmd::rand_alloc_ecwmax,
|
||||
* iwl_link_ctx_cfg_cmd::trig_based_txf,
|
||||
* iwl_link_ctx_cfg_cmd::bss_color,
|
||||
* iwl_link_ctx_cfg_cmd::ndp_fdbk_buff_th_exp,
|
||||
* iwl_link_ctx_cfg_cmd::ref_bssid_addr
|
||||
* iwl_link_ctx_cfg_cmd::bssid_index,
|
||||
* iwl_link_ctx_cfg_cmd::frame_time_rts_th.
|
||||
* This flag can be set any time.
|
||||
* @LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE: covers
|
||||
* iwl_link_ctx_cfg_cmd::bss_color_disable
|
||||
* @LINK_CONTEXT_MODIFY_EHT_PARAMS: covers iwl_link_ctx_cfg_cmd::puncture_mask.
|
||||
* This flag can be set only if the MAC that this link relates to has
|
||||
* eht_support set to true.
|
||||
* @LINK_CONTEXT_MODIFY_ALL: set all above flags
|
||||
*/
|
||||
enum iwl_link_ctx_modify_flags {
|
||||
LINK_CONTEXT_MODIFY_ACTIVE = BIT(0),
|
||||
LINK_CONTEXT_MODIFY_RATES_INFO = BIT(1),
|
||||
LINK_CONTEXT_MODIFY_PROTECT_FLAGS = BIT(2),
|
||||
LINK_CONTEXT_MODIFY_QOS_PARAMS = BIT(3),
|
||||
LINK_CONTEXT_MODIFY_BEACON_TIMING = BIT(4),
|
||||
LINK_CONTEXT_MODIFY_HE_PARAMS = BIT(5),
|
||||
LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE = BIT(6),
|
||||
LINK_CONTEXT_MODIFY_EHT_PARAMS = BIT(7),
|
||||
LINK_CONTEXT_MODIFY_ALL = 0xff,
|
||||
}; /* LINK_CONTEXT_MODIFY_MASK_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_link_ctx_protection_flags - link protection flags
|
||||
* @LINK_PROT_FLG_TGG_PROTECT: 11g protection when transmitting OFDM frames,
|
||||
* this will require CCK RTS/CTS2self.
|
||||
* RTS/CTS will protect full burst time.
|
||||
* @LINK_PROT_FLG_HT_PROT: enable HT protection
|
||||
* @LINK_PROT_FLG_FAT_PROT: protect 40 MHz transmissions
|
||||
* @LINK_PROT_FLG_SELF_CTS_EN: allow CTS2self
|
||||
*/
|
||||
enum iwl_link_ctx_protection_flags {
|
||||
LINK_PROT_FLG_TGG_PROTECT = BIT(0),
|
||||
LINK_PROT_FLG_HT_PROT = BIT(1),
|
||||
LINK_PROT_FLG_FAT_PROT = BIT(2),
|
||||
LINK_PROT_FLG_SELF_CTS_EN = BIT(3),
|
||||
}; /* LINK_PROTECT_FLAGS_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_link_ctx_flags - link context flags
|
||||
*
|
||||
* @LINK_FLG_BSS_COLOR_DIS: BSS color disable, don't use the BSS
|
||||
* color for RX filter but use MAC header
|
||||
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
|
||||
* @LINK_FLG_MU_EDCA_CW: indicates that there is an element of MU EDCA
|
||||
* parameter set, i.e. the backoff counters for trig-based ACs
|
||||
* @LINK_FLG_RU_2MHZ_BLOCK: indicates that 26-tone RU OFDMA transmission are
|
||||
* not allowed (as there are OBSS that might classify such transmissions as
|
||||
* radar pulses).
|
||||
* @LINK_FLG_NDP_FEEDBACK_ENABLED: mark support for NDP feedback and change
|
||||
* of threshold
|
||||
*/
|
||||
enum iwl_link_ctx_flags {
|
||||
LINK_FLG_BSS_COLOR_DIS = BIT(0),
|
||||
LINK_FLG_MU_EDCA_CW = BIT(1),
|
||||
LINK_FLG_RU_2MHZ_BLOCK = BIT(2),
|
||||
LINK_FLG_NDP_FEEDBACK_ENABLED = BIT(3),
|
||||
}; /* LINK_CONTEXT_FLAG_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_link_config_cmd - command structure to configure the LINK context
|
||||
* in MLD API
|
||||
* ( LINK_CONFIG_CMD =0x9 )
|
||||
*
|
||||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @link_id: the id of the link that this cmd configures
|
||||
* @mac_id: interface ID. Relevant only if action is FW_CTXT_ACTION_ADD
|
||||
* @phy_id: PHY index. Can be changed only if the link was inactive
|
||||
* (and stays inactive). If the link is active (or becomes active),
|
||||
* this field is ignored.
|
||||
* @local_link_addr: the links MAC address. Can be changed only if the link was
|
||||
* inactive (and stays inactive). If the link is active
|
||||
* (or becomes active), this field is ignored.
|
||||
* @reserved_for_local_link_addr: reserved
|
||||
* @modify_mask: from &enum iwl_link_ctx_modify_flags, selects what to change.
|
||||
* Relevant only if action is FW_CTXT_ACTION_MODIFY
|
||||
* @active: indicates whether the link is active or not
|
||||
* @listen_lmac: indicates whether the link should be allocated on the Listen
|
||||
* Lmac or on the Main Lmac. Cannot be changed on an active Link.
|
||||
* Relevant only for eSR.
|
||||
* @cck_rates: basic rates available for CCK
|
||||
* @ofdm_rates: basic rates available for OFDM
|
||||
* @cck_short_preamble: 1 for enabling short preamble, 0 otherwise
|
||||
* @short_slot: 1 for enabling short slots, 0 otherwise
|
||||
* @protection_flags: combination of &enum iwl_link_ctx_protection_flags
|
||||
* @qos_flags: from &enum iwl_mac_qos_flags
|
||||
* @ac: one iwl_mac_qos configuration for each AC
|
||||
* @htc_trig_based_pkt_ext: default PE in 4us units
|
||||
* @rand_alloc_ecwmin: random CWmin = 2**ECWmin-1
|
||||
* @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1
|
||||
* @ndp_fdbk_buff_th_exp: set exponent for the NDP feedback buffered threshold
|
||||
* @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues
|
||||
* @bi: beacon interval in TU, applicable only when associated
|
||||
* @dtim_interval: DTIM interval in TU.
|
||||
* Relevant only for GO, otherwise this is offloaded.
|
||||
* @puncture_mask: puncture mask for EHT
|
||||
* @frame_time_rts_th: HE duration RTS threshold, in units of 32us
|
||||
* @flags: a combination from &enum iwl_link_ctx_flags
|
||||
* @flags_mask: what of %flags have changed. Also &enum iwl_link_ctx_flags
|
||||
* Below fields are for multi-bssid:
|
||||
* @ref_bssid_addr: reference BSSID used by the AP
|
||||
* @reserved_for_ref_bssid_addr: reserved
|
||||
* @bssid_index: index of the associated VAP
|
||||
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
|
||||
* @reserved: alignment
|
||||
* @ibss_bssid_addr: bssid for ibss
|
||||
* @reserved_for_ibss_bssid_addr: reserved
|
||||
* @reserved1: reserved for future use
|
||||
*/
|
||||
struct iwl_link_config_cmd {
|
||||
__le32 action;
|
||||
__le32 link_id;
|
||||
__le32 mac_id;
|
||||
__le32 phy_id;
|
||||
u8 local_link_addr[6];
|
||||
__le16 reserved_for_local_link_addr;
|
||||
__le32 modify_mask;
|
||||
__le32 active;
|
||||
__le32 listen_lmac;
|
||||
__le32 cck_rates;
|
||||
__le32 ofdm_rates;
|
||||
__le32 cck_short_preamble;
|
||||
__le32 short_slot;
|
||||
__le32 protection_flags;
|
||||
/* MAC_QOS_PARAM_API_S_VER_1 */
|
||||
__le32 qos_flags;
|
||||
struct iwl_ac_qos ac[AC_NUM + 1];
|
||||
u8 htc_trig_based_pkt_ext;
|
||||
u8 rand_alloc_ecwmin;
|
||||
u8 rand_alloc_ecwmax;
|
||||
u8 ndp_fdbk_buff_th_exp;
|
||||
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
|
||||
__le32 bi;
|
||||
__le32 dtim_interval;
|
||||
__le16 puncture_mask;
|
||||
__le16 frame_time_rts_th;
|
||||
__le32 flags;
|
||||
__le32 flags_mask;
|
||||
/* The below fields are for multi-bssid */
|
||||
u8 ref_bssid_addr[6];
|
||||
__le16 reserved_for_ref_bssid_addr;
|
||||
u8 bssid_index;
|
||||
u8 bss_color;
|
||||
u8 reserved[2];
|
||||
u8 ibss_bssid_addr[6];
|
||||
__le16 reserved_for_ibss_bssid_addr;
|
||||
__le32 reserved1[8];
|
||||
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1 */
|
||||
|
||||
/* Currently FW supports link ids in the range 0-3 and can have
|
||||
* at most two active links for each vif.
|
||||
*/
|
||||
#define IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM 2
|
||||
#define IWL_MVM_FW_MAX_LINK_ID 3
|
||||
|
||||
/**
|
||||
* enum iwl_fw_sta_type - FW station types
|
||||
* @STATION_TYPE_PEER: represents a peer - AP in BSS, a TDLS sta, a client in
|
||||
* P2P.
|
||||
* @STATION_TYPE_BCAST_MGMT: The station used to send beacons and
|
||||
* probe responses. Also used for traffic injection in sniffer mode
|
||||
* @STATION_TYPE_MCAST: the station used for BCAST / MCAST in GO. Will be
|
||||
* suspended / resumed at the right timing depending on the clients'
|
||||
* power save state and the DTIM timing
|
||||
* @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type
|
||||
* for the aux sta, so this type is only for driver - internal use.
|
||||
*/
|
||||
enum iwl_fw_sta_type {
|
||||
STATION_TYPE_PEER,
|
||||
STATION_TYPE_BCAST_MGMT,
|
||||
STATION_TYPE_MCAST,
|
||||
STATION_TYPE_AUX,
|
||||
}; /* STATION_TYPE_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
|
||||
* station table
|
||||
* ( STA_CONFIG_CMD = 0xA )
|
||||
*
|
||||
* @sta_id: index of station in uCode's station table
|
||||
* @link_id: the id of the link that is used to communicate with this sta
|
||||
* @peer_mld_address: the peers mld address
|
||||
* @reserved_for_peer_mld_address: reserved
|
||||
* @peer_link_address: the address of the link that is used to communicate
|
||||
* with this sta
|
||||
* @reserved_for_peer_link_address: reserved
|
||||
* @station_type: type of this station. See &enum iwl_fw_sta_type
|
||||
* @assoc_id: for GO only
|
||||
* @beamform_flags: beam forming controls
|
||||
* @mfp: indicates whether the STA uses management frame protection or not.
|
||||
* @mimo: indicates whether the sta uses mimo or not
|
||||
* @mimo_protection: indicates whether the sta uses mimo protection or not
|
||||
* @ack_enabled: indicates that the AP supports receiving ACK-
|
||||
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
|
||||
* @trig_rnd_alloc: indicates that trigger based random allocation
|
||||
* is enabled according to UORA element existence
|
||||
* @tx_ampdu_spacing: minimum A-MPDU spacing:
|
||||
* 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density
|
||||
* @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K,
|
||||
* 3 - 64K, 4 - 128K, 5 - 256K, 6 - 512K, 7 - 1024K.
|
||||
* @sp_length: the size of the SP in actual number of frames
|
||||
* @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
|
||||
* enabled ACs.
|
||||
* @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
|
||||
* capa
|
||||
* @htc_flags: which features are supported in HTC
|
||||
*/
|
||||
struct iwl_mvm_sta_cfg_cmd {
|
||||
__le32 sta_id;
|
||||
__le32 link_id;
|
||||
u8 peer_mld_address[ETH_ALEN];
|
||||
__le16 reserved_for_peer_mld_address;
|
||||
u8 peer_link_address[ETH_ALEN];
|
||||
__le16 reserved_for_peer_link_address;
|
||||
__le32 station_type;
|
||||
__le32 assoc_id;
|
||||
__le32 beamform_flags;
|
||||
__le32 mfp;
|
||||
__le32 mimo;
|
||||
__le32 mimo_protection;
|
||||
__le32 ack_enabled;
|
||||
__le32 trig_rnd_alloc;
|
||||
__le32 tx_ampdu_spacing;
|
||||
__le32 tx_ampdu_max_size;
|
||||
__le32 sp_length;
|
||||
__le32 uapsd_acs;
|
||||
struct iwl_he_pkt_ext_v2 pkt_ext;
|
||||
__le32 htc_flags;
|
||||
} __packed; /* STA_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_aux_sta_cmd - command for AUX STA configuration
|
||||
* ( AUX_STA_CMD = 0xB )
|
||||
*
|
||||
* @sta_id: index of aux sta to configure
|
||||
* @lmac_id: ?
|
||||
* @mac_addr: mac addr of the auxilary sta
|
||||
* @reserved_for_mac_addr: reserved
|
||||
*/
|
||||
struct iwl_mvm_aux_sta_cmd {
|
||||
__le32 sta_id;
|
||||
__le32 lmac_id;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
__le16 reserved_for_mac_addr;
|
||||
|
||||
} __packed; /* AUX_STA_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_remove_sta_cmd - a cmd structure to remove a sta added by
|
||||
* STA_CONFIG_CMD or AUX_STA_CONFIG_CMD
|
||||
* ( STA_REMOVE_CMD = 0xC )
|
||||
*
|
||||
* @sta_id: index of station to remove
|
||||
*/
|
||||
struct iwl_mvm_remove_sta_cmd {
|
||||
__le32 sta_id;
|
||||
} __packed; /* REMOVE_STA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_sta_disable_tx_cmd - disable / re-enable tx to a sta
|
||||
* ( STA_DISABLE_TX_CMD = 0xD )
|
||||
*
|
||||
* @sta_id: index of the station to disable tx to
|
||||
* @disable: indicates if to disable or re-enable tx
|
||||
*/
|
||||
struct iwl_mvm_sta_disable_tx_cmd {
|
||||
__le32 sta_id;
|
||||
__le32 disable;
|
||||
} __packed; /* STA_DISABLE_TX_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_mac_cfg_h__ */
|
||||
|
@ -800,7 +800,7 @@ enum iwl_mac_beacon_flags {
|
||||
* is &enum iwl_mac_beacon_flags.
|
||||
* @short_ssid: Short SSID
|
||||
* @reserved: reserved
|
||||
* @template_id: currently equal to the mac context id of the coresponding mac.
|
||||
* @link_id: the firmware id of the link that will use this beacon
|
||||
* @tim_idx: the offset of the tim IE in the beacon
|
||||
* @tim_size: the length of the tim IE
|
||||
* @ecsa_offset: offset to the ECSA IE if present
|
||||
@ -812,15 +812,17 @@ struct iwl_mac_beacon_cmd {
|
||||
__le16 flags;
|
||||
__le32 short_ssid;
|
||||
__le32 reserved;
|
||||
__le32 template_id;
|
||||
__le32 link_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
__le32 ecsa_offset;
|
||||
__le32 csa_offset;
|
||||
struct ieee80211_hdr frame[];
|
||||
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10,
|
||||
BEACON_TEMPLATE_CMD_API_S_VER_11,
|
||||
BEACON_TEMPLATE_CMD_API_S_VER_12 */
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_11,
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_12,
|
||||
* BEACON_TEMPLATE_CMD_API_S_VER_13
|
||||
*/
|
||||
|
||||
struct iwl_beacon_notif {
|
||||
struct iwl_mvm_tx_resp beacon_notify_hdr;
|
||||
|
@ -2320,6 +2320,34 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
|
||||
return entry->size;
|
||||
}
|
||||
|
||||
static u32 iwl_dump_ini_file_name_info(struct iwl_fw_runtime *fwrt,
|
||||
struct list_head *list)
|
||||
{
|
||||
struct iwl_fw_ini_dump_entry *entry;
|
||||
struct iwl_dump_file_name_info *tlv;
|
||||
u32 len = strnlen(fwrt->trans->dbg.dump_file_name_ext,
|
||||
IWL_FW_INI_MAX_NAME);
|
||||
|
||||
if (!fwrt->trans->dbg.dump_file_name_ext_valid)
|
||||
return 0;
|
||||
|
||||
entry = vzalloc(sizeof(*entry) + sizeof(*tlv) + len);
|
||||
if (!entry)
|
||||
return 0;
|
||||
|
||||
entry->size = sizeof(*tlv) + len;
|
||||
|
||||
tlv = (void *)entry->data;
|
||||
tlv->type = cpu_to_le32(IWL_INI_DUMP_NAME_TYPE);
|
||||
tlv->len = cpu_to_le32(len);
|
||||
memcpy(tlv->data, fwrt->trans->dbg.dump_file_name_ext, len);
|
||||
|
||||
/* add the dump file name extension tlv to the list */
|
||||
list_add_tail(&entry->list, list);
|
||||
|
||||
return entry->size;
|
||||
}
|
||||
|
||||
static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
|
||||
[IWL_FW_INI_REGION_INVALID] = {},
|
||||
[IWL_FW_INI_REGION_INTERNAL_BUFFER] = {
|
||||
@ -2495,8 +2523,10 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
size += iwl_dump_ini_mem(fwrt, list, ®_data,
|
||||
&iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]);
|
||||
|
||||
if (size)
|
||||
if (size) {
|
||||
size += iwl_dump_ini_file_name_info(fwrt, list);
|
||||
size += iwl_dump_ini_info(fwrt, trigger, list);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -14,6 +14,13 @@
|
||||
#include "iwl-csr.h"
|
||||
#include "pnvm.h"
|
||||
|
||||
#define FW_ASSERT_LMAC_FATAL 0x70
|
||||
#define FW_ASSERT_LMAC2_FATAL 0x72
|
||||
#define FW_ASSERT_UMAC_FATAL 0x71
|
||||
#define UMAC_RT_NMI_LMAC2_FATAL 0x72
|
||||
#define RT_NMI_INTERRUPT_OTHER_LMAC_FATAL 0x73
|
||||
#define FW_ASSERT_NMI_UNKNOWN 0x84
|
||||
|
||||
/*
|
||||
* Note: This structure is read from the device with IO accesses,
|
||||
* and the reading already does the endian conversion. As it is
|
||||
@ -96,6 +103,17 @@ struct iwl_umac_error_event_table {
|
||||
#define ERROR_START_OFFSET (1 * sizeof(u32))
|
||||
#define ERROR_ELEM_SIZE (7 * sizeof(u32))
|
||||
|
||||
static bool iwl_fwrt_if_errorid_other_cpu(u32 err_id)
|
||||
{
|
||||
err_id &= 0xFF;
|
||||
|
||||
if ((err_id >= FW_ASSERT_LMAC_FATAL &&
|
||||
err_id <= RT_NMI_INTERRUPT_OTHER_LMAC_FATAL) ||
|
||||
err_id == FW_ASSERT_NMI_UNKNOWN)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct iwl_trans *trans = fwrt->trans;
|
||||
@ -113,6 +131,13 @@ static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt)
|
||||
if (table.valid)
|
||||
fwrt->dump.umac_err_id = table.error_id;
|
||||
|
||||
if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.umac_err_id) &&
|
||||
!fwrt->trans->dbg.dump_file_name_ext_valid) {
|
||||
fwrt->trans->dbg.dump_file_name_ext_valid = true;
|
||||
snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
|
||||
"0x%x", fwrt->dump.umac_err_id);
|
||||
}
|
||||
|
||||
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
|
||||
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
|
||||
IWL_ERR(trans, "Transport status: 0x%08lX, valid: %d\n",
|
||||
@ -189,6 +214,13 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
|
||||
if (table.valid)
|
||||
fwrt->dump.lmac_err_id[lmac_num] = table.error_id;
|
||||
|
||||
if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.lmac_err_id[lmac_num]) &&
|
||||
!fwrt->trans->dbg.dump_file_name_ext_valid) {
|
||||
fwrt->trans->dbg.dump_file_name_ext_valid = true;
|
||||
snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
|
||||
"0x%x", fwrt->dump.lmac_err_id[lmac_num]);
|
||||
}
|
||||
|
||||
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
|
||||
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
|
||||
IWL_ERR(trans, "Transport status: 0x%08lX, valid: %d\n",
|
||||
@ -274,6 +306,16 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx)
|
||||
|
||||
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
|
||||
|
||||
if (table.valid)
|
||||
fwrt->dump.tcm_err_id[idx] = table.error_id;
|
||||
|
||||
if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.tcm_err_id[idx]) &&
|
||||
!fwrt->trans->dbg.dump_file_name_ext_valid) {
|
||||
fwrt->trans->dbg.dump_file_name_ext_valid = true;
|
||||
snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
|
||||
"0x%x", fwrt->dump.tcm_err_id[idx]);
|
||||
}
|
||||
|
||||
IWL_ERR(fwrt, "TCM%d status:\n", idx + 1);
|
||||
IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
|
||||
IWL_ERR(fwrt, "0x%08X | tcm branchlink2\n", table.blink2);
|
||||
@ -337,6 +379,16 @@ static void iwl_fwrt_dump_rcm_error_log(struct iwl_fw_runtime *fwrt, int idx)
|
||||
|
||||
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
|
||||
|
||||
if (table.valid)
|
||||
fwrt->dump.rcm_err_id[idx] = table.error_id;
|
||||
|
||||
if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.rcm_err_id[idx]) &&
|
||||
!fwrt->trans->dbg.dump_file_name_ext_valid) {
|
||||
fwrt->trans->dbg.dump_file_name_ext_valid = true;
|
||||
snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
|
||||
"0x%x", fwrt->dump.rcm_err_id[idx]);
|
||||
}
|
||||
|
||||
IWL_ERR(fwrt, "RCM%d status:\n", idx + 1);
|
||||
IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
|
||||
IWL_ERR(fwrt, "0x%08X | rcm branchlink2\n", table.blink2);
|
||||
@ -444,8 +496,10 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
|
||||
iwl_fwrt_dump_umac_error_log(fwrt);
|
||||
iwl_fwrt_dump_tcm_error_log(fwrt, 0);
|
||||
iwl_fwrt_dump_rcm_error_log(fwrt, 0);
|
||||
iwl_fwrt_dump_tcm_error_log(fwrt, 1);
|
||||
iwl_fwrt_dump_rcm_error_log(fwrt, 1);
|
||||
if (fwrt->trans->dbg.tcm_error_event_table[1])
|
||||
iwl_fwrt_dump_tcm_error_log(fwrt, 1);
|
||||
if (fwrt->trans->dbg.rcm_error_event_table[1])
|
||||
iwl_fwrt_dump_rcm_error_log(fwrt, 1);
|
||||
iwl_fwrt_dump_iml_error_log(fwrt);
|
||||
iwl_fwrt_dump_fseq_regs(fwrt);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -75,6 +75,18 @@ struct iwl_fw_error_dump_data {
|
||||
__u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_dump_file_name_info - data for dump file name addition
|
||||
* @type: region type with reserved bits
|
||||
* @len: the length of file name string to be added to dump file
|
||||
* @data: the string need to be added to dump file
|
||||
*/
|
||||
struct iwl_dump_file_name_info {
|
||||
__le32 type;
|
||||
__le32 len;
|
||||
__u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_file - the layout of the header of the file
|
||||
* @barker: must be %IWL_FW_ERROR_DUMP_BARKER
|
||||
@ -231,6 +243,9 @@ struct iwl_fw_error_dump_mem {
|
||||
/* Use bit 31 as dump info type to avoid colliding with region types */
|
||||
#define IWL_INI_DUMP_INFO_TYPE BIT(31)
|
||||
|
||||
/* Use bit 31 and bit 24 as dump name type to avoid colliding with region types */
|
||||
#define IWL_INI_DUMP_NAME_TYPE (BIT(31) | BIT(24))
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_data - data for one type
|
||||
* @type: &enum iwl_fw_ini_region_type
|
||||
|
@ -455,6 +455,9 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT = (__force iwl_ucode_tlv_capa_t)100,
|
||||
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT = (__force iwl_ucode_tlv_capa_t)104,
|
||||
IWL_UCODE_TLV_CAPA_DUMP_COMPLETE_SUPPORT = (__force iwl_ucode_tlv_capa_t)105,
|
||||
IWL_UCODE_TLV_CAPA_SYNCED_TIME = (__force iwl_ucode_tlv_capa_t)106,
|
||||
IWL_UCODE_TLV_CAPA_TIME_SYNC_BOTH_FTM_TM = (__force iwl_ucode_tlv_capa_t)108,
|
||||
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT = (__force iwl_ucode_tlv_capa_t)109,
|
||||
|
||||
#ifdef __CHECKER__
|
||||
/* sparse says it cannot increment the previous enum member */
|
||||
|
@ -182,10 +182,10 @@ struct iwl_dump_exclude {
|
||||
* @enhance_sensitivity_table: device can do enhanced sensitivity.
|
||||
* @init_evtlog_ptr: event log offset for init ucode.
|
||||
* @init_evtlog_size: event log size for init ucode.
|
||||
* @init_errlog_ptr: error log offfset for init ucode.
|
||||
* @init_errlog_ptr: error log offset for init ucode.
|
||||
* @inst_evtlog_ptr: event log offset for runtime ucode.
|
||||
* @inst_evtlog_size: event log size for runtime ucode.
|
||||
* @inst_errlog_ptr: error log offfset for runtime ucode.
|
||||
* @inst_errlog_ptr: error log offset for runtime ucode.
|
||||
* @type: firmware type (&enum iwl_fw_type)
|
||||
* @human_readable: human readable version
|
||||
* we get the ALIVE from the uCode
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright(c) 2020-2021 Intel Corporation
|
||||
* Copyright(c) 2020-2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "iwl-drv.h"
|
||||
@ -318,7 +318,6 @@ parse:
|
||||
kfree(data);
|
||||
|
||||
skip_parse:
|
||||
data = NULL;
|
||||
/* now try to get the reduce power table, if not loaded yet */
|
||||
if (!trans->reduce_power_loaded) {
|
||||
data = iwl_uefi_get_reduced_power(trans, &len);
|
||||
@ -329,19 +328,16 @@ skip_parse:
|
||||
* trying again over and over.
|
||||
*/
|
||||
trans->reduce_power_loaded = true;
|
||||
|
||||
goto skip_reduce_power;
|
||||
} else {
|
||||
ret = iwl_trans_set_reduce_power(trans, data, len);
|
||||
if (ret)
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Failed to set reduce power table %d\n",
|
||||
ret);
|
||||
kfree(data);
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_trans_set_reduce_power(trans, data, len);
|
||||
if (ret)
|
||||
IWL_DEBUG_FW(trans,
|
||||
"Failed to set reduce power table %d\n",
|
||||
ret);
|
||||
kfree(data);
|
||||
|
||||
skip_reduce_power:
|
||||
iwl_init_notification_wait(notif_wait, &pnvm_wait,
|
||||
ntf_cmds, ARRAY_SIZE(ntf_cmds),
|
||||
iwl_pnvm_complete_fn, trans);
|
||||
|
@ -24,6 +24,8 @@ struct iwl_fw_runtime_ops {
|
||||
};
|
||||
|
||||
#define MAX_NUM_LMAC 2
|
||||
#define MAX_NUM_TCM 2
|
||||
#define MAX_NUM_RCM 2
|
||||
struct iwl_fwrt_shared_mem_cfg {
|
||||
int num_lmacs;
|
||||
int num_txfifo_entries;
|
||||
@ -129,6 +131,8 @@ struct iwl_fw_runtime {
|
||||
unsigned long non_collect_ts_start[IWL_FW_INI_TIME_POINT_NUM];
|
||||
u32 *d3_debug_data;
|
||||
u32 lmac_err_id[MAX_NUM_LMAC];
|
||||
u32 tcm_err_id[MAX_NUM_TCM];
|
||||
u32 rcm_err_id[MAX_NUM_RCM];
|
||||
u32 umac_err_id;
|
||||
|
||||
struct iwl_txf_iter_data txf_iter_data;
|
||||
|
@ -650,14 +650,19 @@ extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_fm_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_gl_b0_fm_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_z0_gf_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
@ -12,6 +12,9 @@
|
||||
#include "iwl-trans.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#ifdef CONFIG_CC_IS_GCC
|
||||
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
|
||||
#endif
|
||||
#include "iwl-devtrace.h"
|
||||
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
|
||||
|
@ -81,7 +81,7 @@ static const u16 iwl_nvm_channels[] = {
|
||||
/* 2.4 GHz */
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
/* 5 GHz */
|
||||
36, 40, 44 , 48, 52, 56, 60, 64,
|
||||
36, 40, 44, 48, 52, 56, 60, 64,
|
||||
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
|
||||
149, 153, 157, 161, 165
|
||||
};
|
||||
|
@ -775,6 +775,8 @@ struct iwl_imr_data {
|
||||
* @periodic_trig_list: periodic triggers list
|
||||
* @domains_bitmap: bitmap of active domains other than &IWL_FW_INI_DOMAIN_ALWAYS_ON
|
||||
* @ucode_preset: preset based on ucode
|
||||
* @dump_file_name_ext: dump file name extension
|
||||
* @dump_file_name_ext_valid: dump file name extension if valid or not
|
||||
*/
|
||||
struct iwl_trans_debug {
|
||||
u8 n_dest_reg;
|
||||
@ -813,6 +815,8 @@ struct iwl_trans_debug {
|
||||
bool restart_required;
|
||||
u32 last_tp_resetfw;
|
||||
struct iwl_imr_data imr_data;
|
||||
u8 dump_file_name_ext[IWL_FW_INI_MAX_NAME];
|
||||
bool dump_file_name_ext_valid;
|
||||
};
|
||||
|
||||
struct iwl_dma_ptr {
|
||||
|
@ -7,7 +7,9 @@ iwlmvm-y += power.o coex.o
|
||||
iwlmvm-y += tt.o offloading.o tdls.o
|
||||
iwlmvm-y += ftm-responder.o ftm-initiator.o
|
||||
iwlmvm-y += rfi.o
|
||||
iwlmvm-y += mld-key.o
|
||||
iwlmvm-y += mld-key.o mld-mac.o link.o mld-sta.o mld-mac80211.o
|
||||
iwlmvm-y += ptp.o
|
||||
iwlmvm-y += time-sync.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
|
||||
iwlmvm-$(CONFIG_PM) += d3.o
|
||||
|
@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2020 Intel Corporation
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*/
|
||||
#include <net/mac80211.h>
|
||||
#include "fw-api.h"
|
||||
@ -75,7 +76,7 @@ static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
|
||||
if (vif == data->ignore_vif)
|
||||
return;
|
||||
|
||||
if (mvmvif->phy_ctxt != data->phyctxt)
|
||||
if (mvmvif->deflink.phy_ctxt != data->phyctxt)
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
|
||||
@ -132,7 +133,7 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
|
||||
if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
@ -142,7 +143,8 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
if (iwl_mvm_sf_update(mvm, vif, false))
|
||||
return -EINVAL;
|
||||
|
||||
return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
|
||||
return iwl_mvm_binding_update(mvm, vif, mvmvif->deflink.phy_ctxt,
|
||||
true);
|
||||
}
|
||||
|
||||
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
@ -150,10 +152,11 @@ int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
|
||||
if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
|
||||
return -EINVAL;
|
||||
|
||||
ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
|
||||
ret = iwl_mvm_binding_update(mvm, vif, mvmvif->deflink.phy_ctxt,
|
||||
false);
|
||||
|
||||
if (!ret)
|
||||
if (iwl_mvm_sf_update(mvm, vif, true))
|
||||
|
@ -194,7 +194,7 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
|
||||
if (mvmsta->bt_reduced_txpower == enable)
|
||||
return 0;
|
||||
|
||||
value = mvmsta->sta_id;
|
||||
value = mvmsta->deflink.sta_id;
|
||||
|
||||
if (enable)
|
||||
value |= BT_REDUCED_TX_POWER_BIT;
|
||||
@ -257,33 +257,35 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
|
||||
swap(data->primary, data->secondary);
|
||||
}
|
||||
|
||||
/* must be called under rcu_read_lock */
|
||||
static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_bt_iterator_data *data,
|
||||
unsigned int link_id)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_bt_iterator_data *data = _data;
|
||||
struct iwl_mvm *mvm = data->mvm;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
/* default smps_mode is AUTOMATIC - only used for client modes */
|
||||
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 bt_activity_grading, min_ag_for_static_smps;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct iwl_mvm_vif_link_info *link_info;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
int ave_rssi;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (!mvmvif->ap_ibss_active)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
link_info = mvmvif->link[link_id];
|
||||
if (!link_info)
|
||||
return;
|
||||
}
|
||||
|
||||
chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf);
|
||||
link_conf = rcu_dereference(vif->link_conf[link_id]);
|
||||
/* This can happen due to races: if we receive the notification
|
||||
* and have the mutex held, while mac80211 is stuck on our mutex
|
||||
* in the middle of removing the link.
|
||||
*/
|
||||
if (!link_conf)
|
||||
return;
|
||||
|
||||
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
|
||||
|
||||
/* If channel context is invalid or not on 2.4GHz .. */
|
||||
if ((!chanctx_conf ||
|
||||
@ -291,9 +293,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
/* ... relax constraints and disable rssi events */
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
|
||||
smps_mode);
|
||||
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
|
||||
smps_mode, link_id);
|
||||
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
|
||||
false);
|
||||
/* FIXME: should this be per link? */
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
|
||||
}
|
||||
return;
|
||||
@ -314,17 +317,18 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
if (!vif->cfg.assoc)
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
if (mvmvif->phy_ctxt &&
|
||||
(mvm->last_bt_notif.rrc_status & BIT(mvmvif->phy_ctxt->id)))
|
||||
if (link_info->phy_ctxt &&
|
||||
(mvm->last_bt_notif.rrc_status & BIT(link_info->phy_ctxt->id)))
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
IWL_DEBUG_COEX(data->mvm,
|
||||
"mac %d: bt_activity_grading %d smps_req %d\n",
|
||||
mvmvif->id, bt_activity_grading, smps_mode);
|
||||
"mac %d link %d: bt_activity_grading %d smps_req %d\n",
|
||||
mvmvif->id, link_info->fw_link_id,
|
||||
bt_activity_grading, smps_mode);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
|
||||
smps_mode);
|
||||
smps_mode, link_id);
|
||||
|
||||
/* low latency is always primary */
|
||||
if (iwl_mvm_vif_low_latency(mvmvif)) {
|
||||
@ -353,6 +357,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
data->secondary = chanctx_conf;
|
||||
}
|
||||
|
||||
/* FIXME: TCM load per interface? or need something per link? */
|
||||
if (data->primary == chanctx_conf)
|
||||
data->primary_load = mvm->tcm.result.load[mvmvif->id];
|
||||
else if (data->secondary == chanctx_conf)
|
||||
@ -370,6 +375,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
/* if secondary is not NULL, it might be a GO */
|
||||
data->secondary = chanctx_conf;
|
||||
|
||||
/* FIXME: TCM load per interface? or need something per link? */
|
||||
if (data->primary == chanctx_conf)
|
||||
data->primary_load = mvm->tcm.result.load[mvmvif->id];
|
||||
else if (data->secondary == chanctx_conf)
|
||||
@ -384,7 +390,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
|
||||
mvm->cfg->bt_shared_single_ant || !vif->cfg.assoc ||
|
||||
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
|
||||
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
|
||||
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id, false);
|
||||
/* FIXME: should this be per link? */
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
|
||||
return;
|
||||
}
|
||||
@ -396,10 +403,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
if (!ave_rssi)
|
||||
ave_rssi = -100;
|
||||
if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
|
||||
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
|
||||
if (iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
|
||||
true))
|
||||
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
|
||||
} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
|
||||
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
|
||||
if (iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
|
||||
false))
|
||||
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
|
||||
}
|
||||
|
||||
@ -407,6 +416,32 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
|
||||
}
|
||||
|
||||
/* must be called under rcu_read_lock */
|
||||
static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_bt_iterator_data *data = _data;
|
||||
struct iwl_mvm *mvm = data->mvm;
|
||||
unsigned int link_id;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (!mvmvif->ap_ibss_active)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
|
||||
iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
|
||||
}
|
||||
|
||||
static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_bt_iterator_data data = {
|
||||
@ -521,7 +556,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
* Rssi update while not associated - can happen since the statistics
|
||||
* are handled asynchronously
|
||||
*/
|
||||
if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA)
|
||||
if (mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA)
|
||||
return;
|
||||
|
||||
/* No BT - reports should be disabled */
|
||||
@ -537,10 +572,13 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
*/
|
||||
if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
|
||||
iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
|
||||
ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
|
||||
ret = iwl_mvm_bt_coex_reduced_txp(mvm,
|
||||
mvmvif->deflink.ap_sta_id,
|
||||
false);
|
||||
else
|
||||
ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
|
||||
ret = iwl_mvm_bt_coex_reduced_txp(mvm,
|
||||
mvmvif->deflink.ap_sta_id,
|
||||
true);
|
||||
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
|
||||
@ -554,7 +592,7 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
|
||||
enum iwl_bt_coex_lut_type lut_type;
|
||||
|
||||
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
|
||||
@ -578,7 +616,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->deflink.phy_ctxt;
|
||||
enum iwl_bt_coex_lut_type lut_type;
|
||||
|
||||
if (mvm->last_bt_notif.ttc_status & BIT(phy_ctxt->id))
|
||||
|
@ -470,7 +470,7 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
|
||||
for (i = 0; i < ARRAY_SIZE(data.rsc->mcast_key_id_map); i++)
|
||||
data.rsc->mcast_key_id_map[i] =
|
||||
IWL_MCAST_KEY_MAP_INVALID;
|
||||
data.rsc->sta_id = cpu_to_le32(mvmvif->ap_sta_id);
|
||||
data.rsc->sta_id = cpu_to_le32(mvmvif->deflink.ap_sta_id);
|
||||
|
||||
ieee80211_iter_keys(mvm->hw, vif,
|
||||
iwl_mvm_wowlan_get_rsc_v5_data,
|
||||
@ -493,7 +493,8 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
|
||||
|
||||
if (ver == 4) {
|
||||
size = sizeof(*data.rsc_tsc);
|
||||
data.rsc_tsc->sta_id = cpu_to_le32(mvmvif->ap_sta_id);
|
||||
data.rsc_tsc->sta_id =
|
||||
cpu_to_le32(mvmvif->deflink.ap_sta_id);
|
||||
} else {
|
||||
/* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */
|
||||
size = sizeof(data.rsc_tsc->params);
|
||||
@ -691,7 +692,7 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
|
||||
|
||||
pattern_cmd->n_patterns = wowlan->n_patterns;
|
||||
if (ver >= 3)
|
||||
pattern_cmd->sta_id = mvmvif->ap_sta_id;
|
||||
pattern_cmd->sta_id = mvmvif->deflink.ap_sta_id;
|
||||
|
||||
for (i = 0; i < wowlan->n_patterns; i++) {
|
||||
int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
|
||||
@ -732,7 +733,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return -EINVAL;
|
||||
|
||||
/* add back the PHY */
|
||||
if (WARN_ON(!mvmvif->phy_ctxt))
|
||||
if (WARN_ON(!mvmvif->deflink.phy_ctxt))
|
||||
return -EINVAL;
|
||||
|
||||
rcu_read_lock();
|
||||
@ -746,7 +747,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
chains_dynamic = ctx->rx_chains_dynamic;
|
||||
rcu_read_unlock();
|
||||
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt, &chandef,
|
||||
ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->deflink.phy_ctxt, &chandef,
|
||||
chains_static, chains_dynamic);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -763,12 +764,12 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
||||
/* add back binding - XXX refactor? */
|
||||
binding_cmd.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
|
||||
mvmvif->phy_ctxt->color));
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,
|
||||
mvmvif->deflink.phy_ctxt->color));
|
||||
binding_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||
binding_cmd.phy =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
|
||||
mvmvif->phy_ctxt->color));
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,
|
||||
mvmvif->deflink.phy_ctxt->color));
|
||||
binding_cmd.macs[0] = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color));
|
||||
for (i = 1; i < MAX_MACS_IN_BINDING; i++)
|
||||
@ -791,7 +792,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
ret = iwl_mvm_sta_send_to_fw(mvm, ap_sta, false, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta);
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id],
|
||||
ap_sta);
|
||||
|
||||
ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
if (ret)
|
||||
@ -800,8 +802,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
/* and some quota */
|
||||
quota = iwl_mvm_quota_cmd_get_quota(mvm, "a_cmd, 0);
|
||||
quota->id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
|
||||
mvmvif->phy_ctxt->color));
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,
|
||||
mvmvif->deflink.phy_ctxt->color));
|
||||
quota->quota = cpu_to_le32(IWL_MVM_MAX_QUOTA);
|
||||
quota->max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA);
|
||||
|
||||
@ -1027,7 +1029,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
|
||||
if (ver == 2) {
|
||||
size = sizeof(tkip_data.tkip);
|
||||
tkip_data.tkip.sta_id =
|
||||
cpu_to_le32(mvmvif->ap_sta_id);
|
||||
cpu_to_le32(mvmvif->deflink.ap_sta_id);
|
||||
} else if (ver == 1 || ver == IWL_FW_CMD_VER_UNKNOWN) {
|
||||
size = sizeof(struct iwl_wowlan_tkip_params_cmd_ver_1);
|
||||
} else {
|
||||
@ -1076,7 +1078,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
|
||||
kek_kck_cmd.kek_len = cpu_to_le16(mvmvif->rekey_data.kek_len);
|
||||
kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;
|
||||
kek_kck_cmd.akm = cpu_to_le32(mvmvif->rekey_data.akm);
|
||||
kek_kck_cmd.sta_id = cpu_to_le32(mvmvif->ap_sta_id);
|
||||
kek_kck_cmd.sta_id = cpu_to_le32(mvmvif->deflink.ap_sta_id);
|
||||
|
||||
if (cmd_ver == 4) {
|
||||
cmd_size = sizeof(struct iwl_wowlan_kek_kck_material_cmd_v4);
|
||||
@ -1269,7 +1271,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA) {
|
||||
if (mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA) {
|
||||
/* if we're not associated, this must be netdetect */
|
||||
if (!wowlan->nd_config) {
|
||||
ret = 1;
|
||||
@ -1285,10 +1287,10 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
|
||||
} else {
|
||||
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
|
||||
|
||||
wowlan_config_cmd.sta_id = mvmvif->ap_sta_id;
|
||||
wowlan_config_cmd.sta_id = mvmvif->deflink.ap_sta_id;
|
||||
|
||||
ap_sta = rcu_dereference_protected(
|
||||
mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
|
||||
mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (IS_ERR_OR_NULL(ap_sta)) {
|
||||
ret = -EINVAL;
|
||||
@ -2575,7 +2577,8 @@ iwl_mvm_choose_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
/* if FW uses status notification, status shouldn't be NULL here */
|
||||
if (!d3_data->status) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u8 sta_id = mvm->net_detect ? IWL_MVM_INVALID_STA : mvmvif->ap_sta_id;
|
||||
u8 sta_id = mvm->net_detect ? IWL_MVM_INVALID_STA :
|
||||
mvmvif->deflink.ap_sta_id;
|
||||
|
||||
d3_data->status = iwl_mvm_send_wowlan_get_status(mvm, sta_id);
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
ap_sta_id = mvmvif->ap_sta_id;
|
||||
ap_sta_id = mvmvif->deflink.ap_sta_id;
|
||||
|
||||
switch (ieee80211_vif_type_p2p(vif)) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
@ -211,14 +211,14 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "Load: %d\n",
|
||||
mvm->tcm.result.load[mvmvif->id]);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
|
||||
for (i = 0; i < ARRAY_SIZE(mvmvif->deflink.queue_params); i++)
|
||||
pos += scnprintf(buf+pos, bufsz-pos,
|
||||
"\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
|
||||
i, mvmvif->queue_params[i].txop,
|
||||
mvmvif->queue_params[i].cw_min,
|
||||
mvmvif->queue_params[i].cw_max,
|
||||
mvmvif->queue_params[i].aifs,
|
||||
mvmvif->queue_params[i].uapsd);
|
||||
i, mvmvif->deflink.queue_params[i].txop,
|
||||
mvmvif->deflink.queue_params[i].cw_min,
|
||||
mvmvif->deflink.queue_params[i].cw_max,
|
||||
mvmvif->deflink.queue_params[i].aifs,
|
||||
mvmvif->deflink.queue_params[i].uapsd);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
ap_sta_id != IWL_MVM_INVALID_STA) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -8,6 +8,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include "mvm.h"
|
||||
#include "sta.h"
|
||||
@ -15,6 +16,7 @@
|
||||
#include "debugfs.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "fw/error-dump.h"
|
||||
#include "fw/api/phy-ctxt.h"
|
||||
|
||||
static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
@ -214,9 +216,9 @@ static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
|
||||
int pos;
|
||||
|
||||
if (!mvm->temperature_test)
|
||||
pos = scnprintf(buf , sizeof(buf), "disabled\n");
|
||||
pos = scnprintf(buf, sizeof(buf), "disabled\n");
|
||||
else
|
||||
pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature);
|
||||
pos = scnprintf(buf, sizeof(buf), "%d\n", mvm->temperature);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
@ -261,7 +263,7 @@ static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
|
||||
mvm->temperature = temperature;
|
||||
}
|
||||
IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
|
||||
mvm->temperature_test ? "En" : "Dis" ,
|
||||
mvm->temperature_test ? "En" : "Dis",
|
||||
mvm->temperature);
|
||||
/* handle the temperature change */
|
||||
iwl_mvm_tt_handler(mvm);
|
||||
@ -291,7 +293,7 @@ static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
pos = scnprintf(buf , sizeof(buf), "%d\n", temp);
|
||||
pos = scnprintf(buf, sizeof(buf), "%d\n", temp);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
@ -374,7 +376,7 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
|
||||
struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
|
||||
struct iwl_mvm *mvm = lq_sta->pers.drv;
|
||||
static const size_t bufsz = 2048;
|
||||
char *buff;
|
||||
@ -714,6 +716,190 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct iwl_mvm_tas_status_resp tas_rsp;
|
||||
struct iwl_mvm_tas_status_resp *rsp = &tas_rsp;
|
||||
static const size_t bufsz = 1024;
|
||||
char *buff, *pos, *endpos;
|
||||
const char * const tas_dis_reason[TAS_DISABLED_REASON_MAX] = {
|
||||
[TAS_DISABLED_DUE_TO_BIOS] =
|
||||
"Due To BIOS",
|
||||
[TAS_DISABLED_DUE_TO_SAR_6DBM] =
|
||||
"Due To SAR Limit Less Than 6 dBm",
|
||||
[TAS_DISABLED_REASON_INVALID] =
|
||||
"N/A",
|
||||
};
|
||||
const char * const tas_current_status[TAS_DYNA_STATUS_MAX] = {
|
||||
[TAS_DYNA_INACTIVE] = "INACTIVE",
|
||||
[TAS_DYNA_INACTIVE_MVM_MODE] =
|
||||
"inactive due to mvm mode",
|
||||
[TAS_DYNA_INACTIVE_TRIGGER_MODE] =
|
||||
"inactive due to trigger mode",
|
||||
[TAS_DYNA_INACTIVE_BLOCK_LISTED] =
|
||||
"inactive due to block listed",
|
||||
[TAS_DYNA_INACTIVE_UHB_NON_US] =
|
||||
"inactive due to uhb non US",
|
||||
[TAS_DYNA_ACTIVE] = "ACTIVE",
|
||||
};
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(DEBUG_GROUP, GET_TAS_STATUS),
|
||||
.flags = CMD_WANT_SKB,
|
||||
.len = { 0, },
|
||||
.data = { NULL, },
|
||||
};
|
||||
int ret, i, tmp;
|
||||
bool tas_enabled = false;
|
||||
unsigned long dyn_status;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_send_cmd(mvm, &hcmd);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
buff = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
pos = buff;
|
||||
endpos = pos + bufsz;
|
||||
|
||||
rsp = (void *)hcmd.resp_pkt->data;
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "TAS Conclusion:\n");
|
||||
for (i = 0; i < rsp->in_dual_radio + 1; i++) {
|
||||
if (rsp->tas_status_mac[i].band != TAS_LMAC_BAND_INVALID &&
|
||||
rsp->tas_status_mac[i].dynamic_status & BIT(TAS_DYNA_ACTIVE)) {
|
||||
pos += scnprintf(pos, endpos - pos, "\tON for ");
|
||||
switch (rsp->tas_status_mac[i].band) {
|
||||
case TAS_LMAC_BAND_HB:
|
||||
pos += scnprintf(pos, endpos - pos, "HB\n");
|
||||
break;
|
||||
case TAS_LMAC_BAND_LB:
|
||||
pos += scnprintf(pos, endpos - pos, "LB\n");
|
||||
break;
|
||||
case TAS_LMAC_BAND_UHB:
|
||||
pos += scnprintf(pos, endpos - pos, "UHB\n");
|
||||
break;
|
||||
case TAS_LMAC_BAND_INVALID:
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"INVALID BAND\n");
|
||||
break;
|
||||
default:
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Unsupported band (%d)\n",
|
||||
rsp->tas_status_mac[i].band);
|
||||
goto out;
|
||||
}
|
||||
tas_enabled = true;
|
||||
}
|
||||
}
|
||||
if (!tas_enabled)
|
||||
pos += scnprintf(pos, endpos - pos, "\tOFF\n");
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "TAS Report\n");
|
||||
pos += scnprintf(pos, endpos - pos, "TAS FW version: %d\n",
|
||||
rsp->tas_fw_version);
|
||||
pos += scnprintf(pos, endpos - pos, "Is UHB enabled for USA?: %s\n",
|
||||
rsp->is_uhb_for_usa_enable ? "True" : "False");
|
||||
pos += scnprintf(pos, endpos - pos, "Current MCC: 0x%x\n",
|
||||
le16_to_cpu(rsp->curr_mcc));
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "Block list entries:");
|
||||
for (i = 0; i < APCI_WTAS_BLACK_LIST_MAX; i++)
|
||||
pos += scnprintf(pos, endpos - pos, " 0x%x",
|
||||
le16_to_cpu(rsp->block_list[i]));
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "\nOEM name: %s\n",
|
||||
dmi_get_system_info(DMI_SYS_VENDOR));
|
||||
pos += scnprintf(pos, endpos - pos, "\tVendor In Approved List: %s\n",
|
||||
iwl_mvm_is_vendor_in_approved_list() ? "YES" : "NO");
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"\tDo TAS Support Dual Radio?: %s\n",
|
||||
rsp->in_dual_radio ? "TRUE" : "FALSE");
|
||||
|
||||
for (i = 0; i < rsp->in_dual_radio + 1; i++) {
|
||||
if (rsp->tas_status_mac[i].static_status == 0) {
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Static status: disabled\n");
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Static disabled reason: %s (0)\n",
|
||||
tas_dis_reason[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "TAS status for ");
|
||||
switch (rsp->tas_status_mac[i].band) {
|
||||
case TAS_LMAC_BAND_HB:
|
||||
pos += scnprintf(pos, endpos - pos, "High band\n");
|
||||
break;
|
||||
case TAS_LMAC_BAND_LB:
|
||||
pos += scnprintf(pos, endpos - pos, "Low band\n");
|
||||
break;
|
||||
case TAS_LMAC_BAND_UHB:
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Ultra high band\n");
|
||||
break;
|
||||
case TAS_LMAC_BAND_INVALID:
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"INVALID band\n");
|
||||
break;
|
||||
default:
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Unsupported band (%d)\n",
|
||||
rsp->tas_status_mac[i].band);
|
||||
goto out;
|
||||
}
|
||||
pos += scnprintf(pos, endpos - pos, "Static status: %sabled\n",
|
||||
rsp->tas_status_mac[i].static_status ?
|
||||
"En" : "Dis");
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"\tStatic Disabled Reason: ");
|
||||
if (rsp->tas_status_mac[i].static_dis_reason < TAS_DISABLED_REASON_MAX)
|
||||
pos += scnprintf(pos, endpos - pos, "%s (%d)\n",
|
||||
tas_dis_reason[rsp->tas_status_mac[i].static_dis_reason],
|
||||
rsp->tas_status_mac[i].static_dis_reason);
|
||||
else
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"unsupported value (%d)\n",
|
||||
rsp->tas_status_mac[i].static_dis_reason);
|
||||
|
||||
pos += scnprintf(pos, endpos - pos, "Dynamic status:\n");
|
||||
dyn_status = (rsp->tas_status_mac[i].dynamic_status);
|
||||
for_each_set_bit(tmp, &dyn_status, sizeof(dyn_status)) {
|
||||
if (tmp >= 0 && tmp < TAS_DYNA_STATUS_MAX)
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"\t%s (%d)\n",
|
||||
tas_current_status[tmp], tmp);
|
||||
}
|
||||
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Is near disconnection?: %s\n",
|
||||
rsp->tas_status_mac[i].near_disconnection ?
|
||||
"True" : "False");
|
||||
tmp = le16_to_cpu(rsp->tas_status_mac[i].max_reg_pwr_limit);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"Max. regulatory pwr limit (dBm): %d.%03d\n",
|
||||
tmp / 8, 125 * (tmp % 8));
|
||||
tmp = le16_to_cpu(rsp->tas_status_mac[i].sar_limit);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"SAR limit (dBm): %d.%03d\n",
|
||||
tmp / 8, 125 * (tmp % 8));
|
||||
}
|
||||
|
||||
out:
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
|
||||
kfree(buff);
|
||||
iwl_free_resp(&hcmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_phy_integration_ver_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -1202,6 +1388,7 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
|
||||
struct sk_buff *beacon;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct iwl_mac_beacon_cmd beacon_cmd = {};
|
||||
unsigned int link_id;
|
||||
u8 rate;
|
||||
int i;
|
||||
|
||||
@ -1250,17 +1437,24 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
|
||||
info = IEEE80211_SKB_CB(beacon);
|
||||
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
|
||||
|
||||
beacon_cmd.flags =
|
||||
cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));
|
||||
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
|
||||
beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
|
||||
for_each_mvm_vif_valid_link(mvmvif, link_id) {
|
||||
beacon_cmd.flags =
|
||||
cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw,
|
||||
rate));
|
||||
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
|
||||
beacon_cmd.link_id =
|
||||
cpu_to_le32(mvmvif->link[link_id]->fw_link_id);
|
||||
else
|
||||
beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);
|
||||
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
|
||||
&beacon_cmd.tim_size,
|
||||
beacon->data, beacon->len);
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
|
||||
&beacon_cmd.tim_size,
|
||||
beacon->data, beacon->len);
|
||||
|
||||
iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
|
||||
sizeof(beacon_cmd));
|
||||
iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
|
||||
sizeof(beacon_cmd));
|
||||
}
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
dev_kfree_skb(beacon);
|
||||
@ -1685,6 +1879,7 @@ MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(tas_get_status);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
|
||||
@ -1894,6 +2089,7 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
|
||||
|
||||
if (mvm->fw->phy_integration_ver)
|
||||
MVM_DEBUGFS_ADD_FILE(phy_integration_ver, mvm->debugfs_dir, 0400);
|
||||
MVM_DEBUGFS_ADD_FILE(tas_get_status, mvm->debugfs_dir, 0400);
|
||||
#ifdef CONFIG_ACPI
|
||||
MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400);
|
||||
#endif
|
||||
|
@ -73,7 +73,7 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]);
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
|
||||
if (!IS_ERR_OR_NULL(sta) && sta->mfp)
|
||||
expected_tk_len = 0;
|
||||
rcu_read_unlock();
|
||||
@ -510,13 +510,13 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]);
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
|
||||
if (sta->mfp && (peer->ftm.trigger_based || peer->ftm.non_trigger_based))
|
||||
FTM_PUT_FLAG(PMF);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
target->sta_id = mvmvif->ap_sta_id;
|
||||
target->sta_id = mvmvif->deflink.ap_sta_id;
|
||||
} else {
|
||||
target->sta_id = IWL_MVM_INVALID_STA;
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
|
||||
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
|
||||
IWL_TOF_RESPONDER_CMD_VALID_BSSID |
|
||||
IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
|
||||
.sta_id = mvmvif->bcast_sta.sta_id,
|
||||
.sta_id = mvmvif->deflink.bcast_sta.sta_id,
|
||||
};
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 6);
|
||||
int err;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "iwl-phy-db.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-nvm-parse.h"
|
||||
#include "time-sync.h"
|
||||
|
||||
#define MVM_UCODE_ALIVE_TIMEOUT (HZ)
|
||||
#define MVM_UCODE_CALIB_TIMEOUT (2 * HZ)
|
||||
@ -122,8 +123,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
u32 version = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
UCODE_ALIVE_NTFY, 0);
|
||||
u32 i;
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
enum iwl_device_family device_family = trans->trans_cfg->device_family;
|
||||
|
||||
|
||||
if (version == 6) {
|
||||
@ -233,8 +232,7 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
|
||||
if (umac_error_table) {
|
||||
if (umac_error_table >=
|
||||
mvm->trans->cfg->min_umac_error_event_table ||
|
||||
device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
mvm->trans->cfg->min_umac_error_event_table) {
|
||||
iwl_fw_umac_set_alive_err_table(mvm->trans,
|
||||
umac_error_table);
|
||||
} else {
|
||||
@ -1040,7 +1038,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
|
||||
|
||||
ret = iwl_read_ppag_table(&mvm->fwrt, &cmd, &cmd_size);
|
||||
/* Not supporting PPAG table is a valid scenario */
|
||||
if(ret < 0)
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
|
||||
@ -1094,6 +1092,11 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
bool iwl_mvm_is_vendor_in_approved_list(void)
|
||||
{
|
||||
return dmi_check_system(dmi_tas_approved_list);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_add_to_tas_block_list(__le32 *list, __le32 *le_size, unsigned int mcc)
|
||||
{
|
||||
int i;
|
||||
@ -1373,6 +1376,11 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
|
||||
bool iwl_mvm_is_vendor_in_approved_list(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
|
||||
{
|
||||
return DSM_VALUE_RFI_DISABLE;
|
||||
@ -1562,8 +1570,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
}
|
||||
|
||||
/* init the fw <-> mac80211 STA mapping */
|
||||
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++)
|
||||
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
|
||||
}
|
||||
|
||||
memset(&mvm->fw_link_ids_map, 0, sizeof(mvm->fw_link_ids_map));
|
||||
|
||||
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
|
||||
|
||||
@ -1669,8 +1681,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
|
||||
iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr,
|
||||
IWL_TIME_SYNC_PROTOCOL_TM |
|
||||
IWL_TIME_SYNC_PROTOCOL_FTM);
|
||||
}
|
||||
|
||||
if (!mvm->ptp_data.ptp_clock)
|
||||
iwl_mvm_ptp_init(mvm);
|
||||
|
||||
if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid))
|
||||
IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n");
|
||||
@ -1740,8 +1759,10 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
|
||||
goto error;
|
||||
|
||||
/* init the fw <-> mac80211 STA mapping */
|
||||
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++)
|
||||
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
|
||||
}
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
|
||||
/*
|
||||
|
294
drivers/net/wireless/intel/iwlwifi/mvm/link.c
Normal file
294
drivers/net/wireless/intel/iwlwifi/mvm/link.c
Normal file
@ -0,0 +1,294 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2022 - 2023 Intel Corporation
|
||||
*/
|
||||
#include "mvm.h"
|
||||
#include "time-event.h"
|
||||
|
||||
static u32 iwl_mvm_get_free_fw_link_id(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvm_vif)
|
||||
{
|
||||
u32 link_id;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
link_id = ffz(mvm->fw_link_ids_map);
|
||||
|
||||
/* this case can happen if there're deactivated but not removed links */
|
||||
if (link_id > IWL_MVM_FW_MAX_LINK_ID)
|
||||
return IWL_MVM_FW_LINK_ID_INVALID;
|
||||
|
||||
mvm->fw_link_ids_map |= BIT(link_id);
|
||||
return link_id;
|
||||
}
|
||||
|
||||
static void iwl_mvm_release_fw_link_id(struct iwl_mvm *mvm, u32 link_id)
|
||||
{
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (!WARN_ON(link_id > IWL_MVM_FW_MAX_LINK_ID))
|
||||
mvm->fw_link_ids_map &= ~BIT(link_id);
|
||||
}
|
||||
|
||||
static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
|
||||
struct iwl_link_config_cmd *cmd,
|
||||
enum iwl_ctxt_action action)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cmd->action = cpu_to_le32(action);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD), 0,
|
||||
sizeof(*cmd), cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send LINK_CONFIG_CMD (action:%d): %d\n",
|
||||
action, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(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;
|
||||
|
||||
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)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Update SF - Disable if needed. if this fails, SF might still be on
|
||||
* while many macs are bound, which is forbidden - so fail the binding.
|
||||
*/
|
||||
if (iwl_mvm_sf_update(mvm, vif, false))
|
||||
return -EINVAL;
|
||||
|
||||
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
|
||||
cmd.mac_id = cpu_to_le32(mvmvif->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);
|
||||
|
||||
memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
|
||||
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
|
||||
|
||||
return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD);
|
||||
}
|
||||
|
||||
int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
u32 changes, bool active)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
unsigned int link_id = link_conf->link_id;
|
||||
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
|
||||
struct iwl_mvm_phy_ctxt *phyctxt;
|
||||
struct iwl_link_config_cmd cmd = {};
|
||||
u32 ht_flag, flags = 0, flags_mask = 0;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!link_info ||
|
||||
link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
|
||||
return -EINVAL;
|
||||
|
||||
if (changes & LINK_CONTEXT_MODIFY_ACTIVE) {
|
||||
/* When activating a link, phy context should be valid;
|
||||
* when deactivating a link, it also should be valid since
|
||||
* the link was active before. So, do nothing in this case.
|
||||
* Since a link is added first with FW_CTXT_INVALID, then we
|
||||
* can get here in case it's removed before it was activated.
|
||||
*/
|
||||
if (!link_info->phy_ctxt)
|
||||
return 0;
|
||||
|
||||
/* check there aren't too many active links */
|
||||
if (!link_info->active && active) {
|
||||
int i, count = 0;
|
||||
|
||||
/* link with phy_ctxt is active in FW */
|
||||
for_each_mvm_vif_valid_link(mvmvif, i)
|
||||
if (mvmvif->link[i]->phy_ctxt)
|
||||
count++;
|
||||
|
||||
/* FIXME: IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM should be
|
||||
* defined per HW
|
||||
*/
|
||||
if (count >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Catch early if driver tries to activate or deactivate a link
|
||||
* twice.
|
||||
*/
|
||||
WARN_ON_ONCE(active == link_info->active);
|
||||
|
||||
/* When deactivating a link session protection should
|
||||
* be stopped
|
||||
*/
|
||||
if (!active && vif->type == NL80211_IFTYPE_STATION)
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
}
|
||||
|
||||
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
|
||||
|
||||
/* The phy_id, link address and listen_lmac can be modified only until
|
||||
* the link becomes active, otherwise they will be ignored.
|
||||
*/
|
||||
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);
|
||||
cmd.mac_id = cpu_to_le32(mvmvif->id);
|
||||
|
||||
memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN);
|
||||
|
||||
cmd.active = cpu_to_le32(active);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
|
||||
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
|
||||
|
||||
/* TODO: set a value to cmd.listen_lmac when system requiremens
|
||||
* will define it
|
||||
*/
|
||||
|
||||
iwl_mvm_set_fw_basic_rates(mvm, vif, link_conf,
|
||||
&cmd.cck_rates, &cmd.ofdm_rates);
|
||||
|
||||
cmd.cck_short_preamble = cpu_to_le32(link_conf->use_short_preamble);
|
||||
cmd.short_slot = cpu_to_le32(link_conf->use_short_slot);
|
||||
|
||||
/* The fw does not distinguish between ht and fat */
|
||||
ht_flag = LINK_PROT_FLG_HT_PROT | LINK_PROT_FLG_FAT_PROT;
|
||||
iwl_mvm_set_fw_protection_flags(mvm, vif, link_conf,
|
||||
&cmd.protection_flags,
|
||||
ht_flag, LINK_PROT_FLG_TGG_PROTECT);
|
||||
|
||||
iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, &cmd.ac[0],
|
||||
&cmd.qos_flags);
|
||||
|
||||
|
||||
cmd.bi = cpu_to_le32(link_conf->beacon_int);
|
||||
cmd.dtim_interval = cpu_to_le32(link_conf->beacon_int *
|
||||
link_conf->dtim_period);
|
||||
|
||||
if (!link_conf->he_support || iwlwifi_mod_params.disable_11ax ||
|
||||
(vif->type == NL80211_IFTYPE_STATION && !vif->cfg.assoc)) {
|
||||
changes &= ~LINK_CONTEXT_MODIFY_HE_PARAMS;
|
||||
goto send_cmd;
|
||||
}
|
||||
|
||||
cmd.htc_trig_based_pkt_ext = link_conf->htc_trig_based_pkt_ext;
|
||||
|
||||
if (link_conf->uora_exists) {
|
||||
cmd.rand_alloc_ecwmin =
|
||||
link_conf->uora_ocw_range & 0x7;
|
||||
cmd.rand_alloc_ecwmax =
|
||||
(link_conf->uora_ocw_range >> 3) & 0x7;
|
||||
}
|
||||
|
||||
/* TODO how to set ndp_fdbk_buff_th_exp? */
|
||||
|
||||
if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif,
|
||||
&cmd.trig_based_txf[0])) {
|
||||
flags |= LINK_FLG_MU_EDCA_CW;
|
||||
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;
|
||||
|
||||
cmd.bss_color = link_conf->he_bss_color.color;
|
||||
|
||||
if (!link_conf->he_bss_color.enabled) {
|
||||
flags |= LINK_FLG_BSS_COLOR_DIS;
|
||||
flags_mask |= LINK_FLG_BSS_COLOR_DIS;
|
||||
}
|
||||
|
||||
cmd.frame_time_rts_th = cpu_to_le16(link_conf->frame_time_rts_th);
|
||||
|
||||
/* Block 26-tone RU OFDMA transmissions */
|
||||
if (link_info->he_ru_2mhz_block) {
|
||||
flags |= LINK_FLG_RU_2MHZ_BLOCK;
|
||||
flags_mask |= LINK_FLG_RU_2MHZ_BLOCK;
|
||||
}
|
||||
|
||||
if (link_conf->nontransmitted) {
|
||||
ether_addr_copy(cmd.ref_bssid_addr,
|
||||
link_conf->transmitter_bssid);
|
||||
cmd.bssid_index = link_conf->bssid_index;
|
||||
}
|
||||
|
||||
send_cmd:
|
||||
cmd.modify_mask = cpu_to_le32(changes);
|
||||
cmd.flags = cpu_to_le32(flags);
|
||||
cmd.flags_mask = cpu_to_le32(flags_mask);
|
||||
|
||||
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY);
|
||||
if (!ret && (changes & LINK_CONTEXT_MODIFY_ACTIVE))
|
||||
link_info->active = active;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(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 = {};
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(!link_info ||
|
||||
link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
|
||||
return -EINVAL;
|
||||
|
||||
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
|
||||
iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
|
||||
link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
|
||||
|
||||
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);
|
||||
|
||||
if (!ret)
|
||||
if (iwl_mvm_sf_update(mvm, vif, true))
|
||||
IWL_ERR(mvm, "Failed to update SF state\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* link should be deactivated before removal, so in most cases we need to
|
||||
* perform these two operations together
|
||||
*/
|
||||
int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iwl_mvm_link_changed(mvm, vif, link_conf,
|
||||
LINK_CONTEXT_MODIFY_ACTIVE, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mvm_remove_link(mvm, vif, link_conf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
@ -293,15 +293,15 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
* For TVQM this will be overwritten later with the FW assigned
|
||||
* queue value (when queue is enabled).
|
||||
*/
|
||||
mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
|
||||
mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
|
||||
}
|
||||
|
||||
mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
|
||||
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
|
||||
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->smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
|
||||
mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -396,15 +396,46 @@ static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
|
||||
*ofdm_rates = ofdm;
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_ctx_cmd *cmd)
|
||||
void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
__le32 *cck_rates, __le32 *ofdm_rates)
|
||||
{
|
||||
struct ieee80211_chanctx_conf *chanctx;
|
||||
u8 cck_ack_rates = 0, ofdm_ack_rates = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx = rcu_dereference(link_conf->chanctx_conf);
|
||||
iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
|
||||
: NL80211_BAND_2GHZ,
|
||||
&cck_ack_rates, &ofdm_ack_rates);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
*cck_rates = cpu_to_le32((u32)cck_ack_rates);
|
||||
*ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
|
||||
}
|
||||
|
||||
void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
__le32 *protection_flags, u32 ht_flag,
|
||||
u32 tgg_flag)
|
||||
{
|
||||
/* for both sta and ap, ht_operation_mode hold the protection_mode */
|
||||
u8 protection_mode = vif->bss_conf.ht_operation_mode &
|
||||
u8 protection_mode = link_conf->ht_operation_mode &
|
||||
IEEE80211_HT_OP_MODE_PROTECTION;
|
||||
/* The fw does not distinguish between ht and fat */
|
||||
u32 ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT;
|
||||
bool ht_enabled = !!(link_conf->ht_operation_mode &
|
||||
IEEE80211_HT_OP_MODE_PROTECTION);
|
||||
|
||||
if (link_conf->use_cts_prot)
|
||||
*protection_flags |= cpu_to_le32(tgg_flag);
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
|
||||
link_conf->use_cts_prot,
|
||||
link_conf->ht_operation_mode);
|
||||
|
||||
if (!ht_enabled)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "protection mode set to %d\n", protection_mode);
|
||||
/*
|
||||
@ -416,12 +447,12 @@ static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm,
|
||||
break;
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
|
||||
cmd->protection_flags |= cpu_to_le32(ht_flag);
|
||||
*protection_flags |= cpu_to_le32(ht_flag);
|
||||
break;
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
|
||||
/* Protect when channel wider than 20MHz */
|
||||
if (vif->bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
|
||||
cmd->protection_flags |= cpu_to_le32(ht_flag);
|
||||
if (link_conf->chandef.width > NL80211_CHAN_WIDTH_20)
|
||||
*protection_flags |= cpu_to_le32(ht_flag);
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(mvm, "Illegal protection mode %d\n",
|
||||
@ -430,6 +461,63 @@ static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm,
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct iwl_ac_qos *ac, __le32 *qos_flags)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
|
||||
u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
|
||||
|
||||
ac[ucode_ac].cw_min =
|
||||
cpu_to_le16(mvmvif->deflink.queue_params[i].cw_min);
|
||||
ac[ucode_ac].cw_max =
|
||||
cpu_to_le16(mvmvif->deflink.queue_params[i].cw_max);
|
||||
ac[ucode_ac].edca_txop =
|
||||
cpu_to_le16(mvmvif->deflink.queue_params[i].txop * 32);
|
||||
ac[ucode_ac].aifsn = mvmvif->deflink.queue_params[i].aifs;
|
||||
ac[ucode_ac].fifos_mask = BIT(txf);
|
||||
}
|
||||
|
||||
if (link_conf->qos)
|
||||
*qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
|
||||
|
||||
if (link_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
|
||||
*qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
|
||||
}
|
||||
|
||||
int iwl_mvm_get_mac_type(struct ieee80211_vif *vif)
|
||||
{
|
||||
u32 mac_type = FW_MAC_TYPE_BSS_STA;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (vif->p2p)
|
||||
mac_type = FW_MAC_TYPE_P2P_STA;
|
||||
else
|
||||
mac_type = FW_MAC_TYPE_BSS_STA;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
mac_type = FW_MAC_TYPE_GO;
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
mac_type = FW_MAC_TYPE_LISTENER;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
mac_type = FW_MAC_TYPE_P2P_DEVICE;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
mac_type = FW_MAC_TYPE_IBSS;
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
return mac_type;
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_ctx_cmd *cmd,
|
||||
@ -437,39 +525,13 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_chanctx_conf *chanctx;
|
||||
bool ht_enabled = !!(vif->bss_conf.ht_operation_mode &
|
||||
IEEE80211_HT_OP_MODE_PROTECTION);
|
||||
u8 cck_ack_rates, ofdm_ack_rates;
|
||||
const u8 *bssid = bssid_override ?: vif->bss_conf.bssid;
|
||||
int i;
|
||||
u32 ht_flag;
|
||||
|
||||
cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color));
|
||||
cmd->action = cpu_to_le32(action);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (vif->p2p)
|
||||
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_STA);
|
||||
else
|
||||
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_BSS_STA);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_GO);
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_LISTENER);
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_DEVICE);
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_IBSS);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
cmd->mac_type = cpu_to_le32(iwl_mvm_get_mac_type(vif));
|
||||
|
||||
cmd->tsf_id = cpu_to_le32(mvmvif->tsf_id);
|
||||
|
||||
@ -480,15 +542,8 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
||||
else
|
||||
eth_broadcast_addr(cmd->bssid_addr);
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx = rcu_dereference(vif->bss_conf.chanctx_conf);
|
||||
iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
|
||||
: NL80211_BAND_2GHZ,
|
||||
&cck_ack_rates, &ofdm_ack_rates);
|
||||
rcu_read_unlock();
|
||||
|
||||
cmd->cck_rates = cpu_to_le32((u32)cck_ack_rates);
|
||||
cmd->ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
|
||||
iwl_mvm_set_fw_basic_rates(mvm, vif, &vif->bss_conf, &cmd->cck_rates,
|
||||
&cmd->ofdm_rates);
|
||||
|
||||
cmd->cck_short_preamble =
|
||||
cpu_to_le32(vif->bss_conf.use_short_preamble ?
|
||||
@ -499,33 +554,14 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
||||
|
||||
cmd->filter_flags = 0;
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
|
||||
u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
|
||||
iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, &cmd->ac[0],
|
||||
&cmd->qos_flags);
|
||||
|
||||
cmd->ac[ucode_ac].cw_min =
|
||||
cpu_to_le16(mvmvif->queue_params[i].cw_min);
|
||||
cmd->ac[ucode_ac].cw_max =
|
||||
cpu_to_le16(mvmvif->queue_params[i].cw_max);
|
||||
cmd->ac[ucode_ac].edca_txop =
|
||||
cpu_to_le16(mvmvif->queue_params[i].txop * 32);
|
||||
cmd->ac[ucode_ac].aifsn = mvmvif->queue_params[i].aifs;
|
||||
cmd->ac[ucode_ac].fifos_mask = BIT(txf);
|
||||
}
|
||||
|
||||
if (vif->bss_conf.qos)
|
||||
cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
|
||||
|
||||
if (vif->bss_conf.use_cts_prot)
|
||||
cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
|
||||
vif->bss_conf.use_cts_prot,
|
||||
vif->bss_conf.ht_operation_mode);
|
||||
if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
|
||||
cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
|
||||
if (ht_enabled)
|
||||
iwl_mvm_mac_ctxt_set_ht_flags(mvm, vif, cmd);
|
||||
/* The fw does not distinguish between ht and fat */
|
||||
ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT;
|
||||
iwl_mvm_set_fw_protection_flags(mvm, vif, &vif->bss_conf,
|
||||
&cmd->protection_flags,
|
||||
ht_flag, MAC_PROT_FLG_TGG_PROTECT);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
|
||||
@ -534,11 +570,76 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
|
||||
int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
|
||||
sizeof(*cmd), cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n",
|
||||
IWL_ERR(mvm, "Failed to send MAC_CONTEXT_CMD (action:%d): %d\n",
|
||||
le32_to_cpu(cmd->action), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
__le64 *dtim_tsf, __le32 *dtim_time,
|
||||
__le32 *assoc_beacon_arrive_time)
|
||||
{
|
||||
u32 dtim_offs;
|
||||
|
||||
/*
|
||||
* The DTIM count counts down, so when it is N that means N
|
||||
* more beacon intervals happen until the DTIM TBTT. Therefore
|
||||
* add this to the current time. If that ends up being in the
|
||||
* future, the firmware will handle it.
|
||||
*
|
||||
* Also note that the system_timestamp (which we get here as
|
||||
* "sync_device_ts") and TSF timestamp aren't at exactly the
|
||||
* same offset in the frame -- the TSF is at the first symbol
|
||||
* of the TSF, the system timestamp is at signal acquisition
|
||||
* time. This means there's an offset between them of at most
|
||||
* a few hundred microseconds (24 * 8 bits + PLCP time gives
|
||||
* 384us in the longest case), this is currently not relevant
|
||||
* as the firmware wakes up around 2ms before the TBTT.
|
||||
*/
|
||||
dtim_offs = link_conf->sync_dtim_count *
|
||||
link_conf->beacon_int;
|
||||
/* convert TU to usecs */
|
||||
dtim_offs *= 1024;
|
||||
|
||||
*dtim_tsf =
|
||||
cpu_to_le64(link_conf->sync_tsf + dtim_offs);
|
||||
*dtim_time =
|
||||
cpu_to_le32(link_conf->sync_device_ts + dtim_offs);
|
||||
*assoc_beacon_arrive_time =
|
||||
cpu_to_le32(link_conf->sync_device_ts);
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
|
||||
le64_to_cpu(*dtim_tsf),
|
||||
le32_to_cpu(*dtim_time),
|
||||
dtim_offs);
|
||||
}
|
||||
|
||||
__le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_p2p_noa_attr *noa =
|
||||
&vif->bss_conf.p2p_noa_attr;
|
||||
|
||||
return cpu_to_le32(noa->oppps_ctwindow &
|
||||
IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
|
||||
}
|
||||
|
||||
__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
__le32 twt_policy = cpu_to_le32(0);
|
||||
|
||||
if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT)
|
||||
twt_policy |= cpu_to_le32(TWT_SUPPORTED);
|
||||
if (vif->bss_conf.twt_protected)
|
||||
twt_policy |= cpu_to_le32(PROTECTED_TWT_SUPPORTED);
|
||||
if (vif->bss_conf.twt_broadcast)
|
||||
twt_policy |= cpu_to_le32(BROADCAST_TWT_SUPPORTED);
|
||||
|
||||
return twt_policy;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action, bool force_assoc_off,
|
||||
@ -559,11 +660,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
|
||||
|
||||
if (vif->p2p) {
|
||||
struct ieee80211_p2p_noa_attr *noa =
|
||||
&vif->bss_conf.p2p_noa_attr;
|
||||
cmd.p2p_sta.ctwin =
|
||||
iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(mvm, vif);
|
||||
|
||||
cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
|
||||
IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
|
||||
ctxt_sta = &cmd.p2p_sta.sta;
|
||||
} else {
|
||||
ctxt_sta = &cmd.sta;
|
||||
@ -573,39 +672,11 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
||||
if (vif->cfg.assoc && vif->bss_conf.dtim_period &&
|
||||
!force_assoc_off) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 dtim_offs;
|
||||
|
||||
/*
|
||||
* The DTIM count counts down, so when it is N that means N
|
||||
* more beacon intervals happen until the DTIM TBTT. Therefore
|
||||
* add this to the current time. If that ends up being in the
|
||||
* future, the firmware will handle it.
|
||||
*
|
||||
* Also note that the system_timestamp (which we get here as
|
||||
* "sync_device_ts") and TSF timestamp aren't at exactly the
|
||||
* same offset in the frame -- the TSF is at the first symbol
|
||||
* of the TSF, the system timestamp is at signal acquisition
|
||||
* time. This means there's an offset between them of at most
|
||||
* a few hundred microseconds (24 * 8 bits + PLCP time gives
|
||||
* 384us in the longest case), this is currently not relevant
|
||||
* as the firmware wakes up around 2ms before the TBTT.
|
||||
*/
|
||||
dtim_offs = vif->bss_conf.sync_dtim_count *
|
||||
vif->bss_conf.beacon_int;
|
||||
/* convert TU to usecs */
|
||||
dtim_offs *= 1024;
|
||||
|
||||
ctxt_sta->dtim_tsf =
|
||||
cpu_to_le64(vif->bss_conf.sync_tsf + dtim_offs);
|
||||
ctxt_sta->dtim_time =
|
||||
cpu_to_le32(vif->bss_conf.sync_device_ts + dtim_offs);
|
||||
ctxt_sta->assoc_beacon_arrive_time =
|
||||
cpu_to_le32(vif->bss_conf.sync_device_ts);
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
|
||||
le64_to_cpu(ctxt_sta->dtim_tsf),
|
||||
le32_to_cpu(ctxt_sta->dtim_time),
|
||||
dtim_offs);
|
||||
iwl_mvm_set_fw_dtim_tbtt(mvm, vif, &vif->bss_conf,
|
||||
&ctxt_sta->dtim_tsf,
|
||||
&ctxt_sta->dtim_time,
|
||||
&ctxt_sta->assoc_beacon_arrive_time);
|
||||
|
||||
ctxt_sta->is_assoc = cpu_to_le32(1);
|
||||
|
||||
@ -635,14 +706,8 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
||||
|
||||
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
|
||||
if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT)
|
||||
ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED);
|
||||
if (vif->bss_conf.twt_protected)
|
||||
ctxt_sta->data_policy |=
|
||||
cpu_to_le32(PROTECTED_TWT_SUPPORTED);
|
||||
if (vif->bss_conf.twt_broadcast)
|
||||
ctxt_sta->data_policy |=
|
||||
cpu_to_le32(BROADCAST_TWT_SUPPORTED);
|
||||
ctxt_sta->data_policy |=
|
||||
iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif);
|
||||
}
|
||||
|
||||
|
||||
@ -724,20 +789,11 @@ static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
|
||||
data->go_active = true;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
__le32 iwl_mac_ctxt_p2p_dev_has_extended_disc(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mac_ctx_cmd cmd = {};
|
||||
struct iwl_mvm_go_iterator_data data = {};
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
|
||||
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
|
||||
|
||||
/* Override the filter flags to accept only probe requests */
|
||||
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
/*
|
||||
* This flag should be set to true when the P2P Device is
|
||||
* discoverable and there is at least another active P2P GO. Settings
|
||||
@ -750,7 +806,25 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
iwl_mvm_go_iterator, &data);
|
||||
|
||||
cmd.p2p_dev.is_disc_extended = cpu_to_le32(data.go_active ? 1 : 0);
|
||||
return cpu_to_le32(data.go_active ? 1 : 0);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mac_ctx_cmd cmd = {};
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
|
||||
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
|
||||
|
||||
cmd.p2p_dev.is_disc_extended =
|
||||
iwl_mac_ctxt_p2p_dev_has_extended_disc(mvm, vif);
|
||||
|
||||
/* Override the filter flags to accept only probe requests */
|
||||
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
@ -878,7 +952,7 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
|
||||
|
||||
/* Set up TX command fields */
|
||||
tx->len = cpu_to_le16((u16)beacon->len);
|
||||
tx->sta_id = mvmvif->bcast_sta.sta_id;
|
||||
tx->sta_id = mvmvif->deflink.bcast_sta.sta_id;
|
||||
tx->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
|
||||
tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
|
||||
tx_flags |=
|
||||
@ -973,7 +1047,8 @@ static int iwl_mvm_mac_ctxt_send_beacon_v7(struct iwl_mvm *mvm,
|
||||
|
||||
static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *beacon)
|
||||
struct sk_buff *beacon,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
|
||||
@ -986,7 +1061,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
||||
|
||||
/* Enable FILS on PSC channels only */
|
||||
rcu_read_lock();
|
||||
ctx = rcu_dereference(vif->bss_conf.chanctx_conf);
|
||||
ctx = rcu_dereference(link_conf->chanctx_conf);
|
||||
channel = ieee80211_frequency_to_channel(ctx->def.chan->center_freq);
|
||||
WARN_ON(channel == 0);
|
||||
if (cfg80211_channel_is_psc(ctx->def.chan) &&
|
||||
@ -1003,7 +1078,11 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
||||
|
||||
beacon_cmd.flags = cpu_to_le16(flags);
|
||||
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
|
||||
beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
|
||||
beacon_cmd.link_id =
|
||||
cpu_to_le32(mvmvif->link[link_conf->link_id]->fw_link_id);
|
||||
else
|
||||
beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
|
||||
@ -1025,7 +1104,8 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
|
||||
|
||||
int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *beacon)
|
||||
struct sk_buff *beacon,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
if (WARN_ON(!beacon))
|
||||
return -EINVAL;
|
||||
@ -1039,14 +1119,16 @@ int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
|
||||
if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
|
||||
return iwl_mvm_mac_ctxt_send_beacon_v9(mvm, vif, beacon);
|
||||
return iwl_mvm_mac_ctxt_send_beacon_v9(mvm, vif, beacon,
|
||||
link_conf);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_beacon_v7(mvm, vif, beacon);
|
||||
}
|
||||
|
||||
/* The beacon template for the AP/GO/IBSS has changed and needs update */
|
||||
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct sk_buff *beacon;
|
||||
int ret;
|
||||
@ -1054,7 +1136,8 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_AP &&
|
||||
vif->type != NL80211_IFTYPE_ADHOC);
|
||||
|
||||
beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0);
|
||||
beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL,
|
||||
link_conf->link_id);
|
||||
if (!beacon)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1065,7 +1148,7 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
|
||||
ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon, link_conf);
|
||||
dev_kfree_skb(beacon);
|
||||
return ret;
|
||||
}
|
||||
@ -1094,6 +1177,30 @@ static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
|
||||
data->beacon_int = vif->bss_conf.beacon_int;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the filter flags for mac context of type AP or P2P GO.
|
||||
*/
|
||||
void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif,
|
||||
__le32 *filter_flags,
|
||||
int accept_probe_req_flag,
|
||||
int accept_beacon_flag)
|
||||
{
|
||||
/*
|
||||
* in AP mode, pass probe requests and beacons from other APs
|
||||
* (needed for ht protection); when there're no any associated
|
||||
* station don't ask FW to pass beacons to prevent unnecessary
|
||||
* wake-ups.
|
||||
*/
|
||||
*filter_flags |= cpu_to_le32(accept_probe_req_flag);
|
||||
if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
|
||||
*filter_flags |= cpu_to_le32(accept_beacon_flag);
|
||||
IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
|
||||
} else {
|
||||
IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the specific data for mac context of type AP of P2P GO
|
||||
*/
|
||||
@ -1113,19 +1220,10 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
|
||||
/* in AP mode, the MCAST FIFO takes the EDCA params from VO */
|
||||
cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
|
||||
|
||||
/*
|
||||
* in AP mode, pass probe requests and beacons from other APs
|
||||
* (needed for ht protection); when there're no any associated
|
||||
* station don't ask FW to pass beacons to prevent unnecessary
|
||||
* wake-ups.
|
||||
*/
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
|
||||
} else {
|
||||
IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
|
||||
}
|
||||
iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(mvm, mvmvif,
|
||||
&cmd->filter_flags,
|
||||
MAC_FILTER_IN_PROBE_REQUEST,
|
||||
MAC_FILTER_IN_BEACON);
|
||||
|
||||
ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
|
||||
ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
|
||||
@ -1133,7 +1231,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
|
||||
|
||||
if (!fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_STA_TYPE))
|
||||
ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue);
|
||||
ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->deflink.cab_queue);
|
||||
|
||||
/*
|
||||
* Only set the beacon time when the MAC is being added, when we
|
||||
@ -1287,12 +1385,9 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
mvmvif->color));
|
||||
cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret);
|
||||
ret = iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mvmvif->uploaded = false;
|
||||
|
||||
@ -1320,7 +1415,8 @@ static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) {
|
||||
int c = ieee80211_beacon_update_cntdwn(csa_vif);
|
||||
|
||||
iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
|
||||
iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif,
|
||||
&csa_vif->bss_conf);
|
||||
if (csa_vif->p2p &&
|
||||
!iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
|
||||
tx_success) {
|
||||
@ -1428,6 +1524,7 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif;
|
||||
u32 id = le32_to_cpu(mb->mac_id);
|
||||
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
|
||||
u32 mac_type;
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
|
||||
@ -1443,6 +1540,14 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
if (!vif)
|
||||
goto out;
|
||||
|
||||
mac_type = iwl_mvm_get_mac_type(vif);
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type);
|
||||
|
||||
mvm->trans->dbg.dump_file_name_ext_valid = true;
|
||||
snprintf(mvm->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
|
||||
"MacId_%d_MacType_%d", id, mac_type);
|
||||
|
||||
rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons);
|
||||
rx_missed_bcon_since_rx =
|
||||
le32_to_cpu(mb->consec_missed_beacons_since_last_rx);
|
||||
@ -1576,9 +1681,9 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
|
||||
sizeof(struct ieee80211_p2p_noa_desc) + 2)
|
||||
new_data->noa_len -= sizeof(struct ieee80211_p2p_noa_desc);
|
||||
|
||||
old_data = rcu_dereference_protected(mvmvif->probe_resp_data,
|
||||
lockdep_is_held(&mvmvif->mvm->mutex));
|
||||
rcu_assign_pointer(mvmvif->probe_resp_data, new_data);
|
||||
old_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
|
||||
lockdep_is_held(&mvmvif->mvm->mutex));
|
||||
rcu_assign_pointer(mvmvif->deflink.probe_resp_data, new_data);
|
||||
|
||||
if (old_data)
|
||||
kfree_rcu(old_data, rcu_head);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,17 +17,17 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP &&
|
||||
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
return BIT(mvmvif->mcast_sta.sta_id);
|
||||
return BIT(mvmvif->deflink.mcast_sta.sta_id);
|
||||
|
||||
if (sta) {
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
return BIT(mvmsta->sta_id);
|
||||
return BIT(mvmsta->deflink.sta_id);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id != IWL_MVM_INVALID_STA)
|
||||
return BIT(mvmvif->ap_sta_id);
|
||||
mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA)
|
||||
return BIT(mvmvif->deflink.ap_sta_id);
|
||||
|
||||
/* invalid */
|
||||
return 0;
|
||||
@ -70,8 +70,8 @@ static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
|
||||
|
||||
rcu_read_lock();
|
||||
if (!sta && vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
|
||||
u8 sta_id = mvmvif->ap_sta_id;
|
||||
mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
|
||||
u8 sta_id = mvmvif->deflink.ap_sta_id;
|
||||
|
||||
sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
@ -195,6 +195,7 @@ static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw,
|
||||
void *data)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
unsigned int link_id = (uintptr_t)data;
|
||||
|
||||
if (key->hw_key_idx == STA_KEY_IDX_INVALID)
|
||||
return;
|
||||
@ -202,19 +203,23 @@ static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw,
|
||||
if (sta)
|
||||
return;
|
||||
|
||||
if (key->link_id >= 0 && key->link_id != link_id)
|
||||
return;
|
||||
|
||||
_iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC);
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
}
|
||||
|
||||
void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_vif_link_info *link,
|
||||
unsigned int link_id)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
|
||||
u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
|
||||
|
||||
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION ||
|
||||
mvmvif->ap_sta_id == IWL_MVM_INVALID_STA))
|
||||
if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION ||
|
||||
link->ap_sta_id == IWL_MVM_INVALID_STA))
|
||||
return;
|
||||
|
||||
if (!sec_key_ver)
|
||||
@ -222,5 +227,5 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
|
||||
|
||||
ieee80211_iter_keys_rcu(mvm->hw, vif,
|
||||
iwl_mvm_sec_key_remove_ap_iter,
|
||||
NULL);
|
||||
(void *)(uintptr_t)link_id);
|
||||
}
|
||||
|
306
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
Normal file
306
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
Normal file
@ -0,0 +1,306 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*/
|
||||
#include "mvm.h"
|
||||
|
||||
static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_config_cmd *cmd,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int link_id;
|
||||
|
||||
cmd->id_and_color = cpu_to_le32(mvmvif->id);
|
||||
cmd->action = cpu_to_le32(action);
|
||||
|
||||
cmd->mac_type = cpu_to_le32(iwl_mvm_get_mac_type(vif));
|
||||
|
||||
memcpy(cmd->local_mld_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
cmd->he_support = 0;
|
||||
cmd->eht_support = 0;
|
||||
|
||||
/* should be set by specific context type handler */
|
||||
cmd->filter_flags = 0;
|
||||
|
||||
cmd->nic_not_ack_enabled =
|
||||
cpu_to_le32(!iwl_mvm_is_nic_ack_enabled(mvm, vif));
|
||||
|
||||
if (iwlwifi_mod_params.disable_11ax)
|
||||
return;
|
||||
|
||||
/* If we have MLO enabled, then the firmware needs to enable
|
||||
* address translation for the station(s) we add. That depends
|
||||
* on having EHT enabled in firmware, which in turn depends on
|
||||
* mac80211 in the code below.
|
||||
* However, mac80211 doesn't enable HE/EHT until it has parsed
|
||||
* the association response successfully, so just skip all that
|
||||
* and enable both when we have MLO.
|
||||
*/
|
||||
if (vif->valid_links) {
|
||||
cmd->he_support = cpu_to_le32(1);
|
||||
cmd->eht_support = cpu_to_le32(1);
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) {
|
||||
link_conf = rcu_dereference(vif->link_conf[link_id]);
|
||||
if (!link_conf)
|
||||
continue;
|
||||
|
||||
if (link_conf->he_support)
|
||||
cmd->he_support = cpu_to_le32(1);
|
||||
|
||||
/* it's not reasonable to have EHT without HE and FW API doesn't
|
||||
* support it. Ignore EHT in this case.
|
||||
*/
|
||||
if (!link_conf->he_support && link_conf->eht_support)
|
||||
continue;
|
||||
|
||||
if (link_conf->eht_support) {
|
||||
cmd->eht_support = cpu_to_le32(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
int ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(MAC_CONF_GROUP, MAC_CONFIG_CMD),
|
||||
0, sizeof(*cmd), cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send MAC_CONFIG_CMD (action:%d): %d\n",
|
||||
le32_to_cpu(cmd->action), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action, bool force_assoc_off)
|
||||
{
|
||||
struct iwl_mac_config_cmd cmd = {};
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_STATION);
|
||||
|
||||
/* Fill the common data for all mac context types */
|
||||
iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
/*
|
||||
* We always want to hear MCAST frames, if we're not authorized yet,
|
||||
* we'll drop them.
|
||||
*/
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
|
||||
if (vif->p2p)
|
||||
cmd.client.ctwin =
|
||||
iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(mvm, vif);
|
||||
|
||||
if (vif->cfg.assoc && !force_assoc_off) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
cmd.client.is_assoc = cpu_to_le32(1);
|
||||
|
||||
if (!mvmvif->authorized &&
|
||||
fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
|
||||
cmd.client.data_policy |=
|
||||
cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
|
||||
|
||||
} else {
|
||||
cmd.client.is_assoc = cpu_to_le32(0);
|
||||
|
||||
/* Allow beacons to pass through as long as we are not
|
||||
* associated, or we do not have dtim period information.
|
||||
*/
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON);
|
||||
}
|
||||
|
||||
cmd.client.assoc_id = cpu_to_le32(vif->cfg.aid);
|
||||
|
||||
if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
|
||||
|
||||
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax)
|
||||
cmd.client.data_policy |=
|
||||
iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif);
|
||||
|
||||
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mac_config_cmd cmd = {};
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
|
||||
|
||||
iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_PROMISC |
|
||||
MAC_FILTER_IN_CONTROL_AND_MGMT |
|
||||
MAC_CFG_FILTER_ACCEPT_BEACON |
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
|
||||
MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
|
||||
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mac_config_cmd cmd = {};
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
|
||||
|
||||
iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON |
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
|
||||
MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
|
||||
/* TODO: Assumes that the beacon id == mac context id */
|
||||
cmd.go_ibss.beacon_template = cpu_to_le32(mvmvif->id);
|
||||
|
||||
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mac_config_cmd cmd = {};
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
|
||||
|
||||
iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
cmd.p2p_dev.is_disc_extended =
|
||||
iwl_mac_ctxt_p2p_dev_has_extended_disc(mvm, vif);
|
||||
|
||||
/* Override the filter flags to accept only probe requests */
|
||||
cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
|
||||
|
||||
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_mac_ctxt_cmd_ap_go(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mac_config_cmd cmd = {};
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_AP);
|
||||
|
||||
/* Fill the common data for all mac context types */
|
||||
iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(mvm, mvmvif,
|
||||
&cmd.filter_flags,
|
||||
MAC_CFG_FILTER_ACCEPT_PROBE_REQ,
|
||||
MAC_CFG_FILTER_ACCEPT_BEACON);
|
||||
|
||||
/* TODO: Assume that the beacon id == mac context id */
|
||||
cmd.go_ibss.beacon_template = cpu_to_le32(mvmvif->id);
|
||||
|
||||
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mld_mac_ctx_send(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 action, bool force_assoc_off)
|
||||
{
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
return iwl_mvm_mld_mac_ctxt_cmd_sta(mvm, vif, action,
|
||||
force_assoc_off);
|
||||
case NL80211_IFTYPE_AP:
|
||||
return iwl_mvm_mld_mac_ctxt_cmd_ap_go(mvm, vif, action);
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
return iwl_mvm_mld_mac_ctxt_cmd_listener(mvm, vif, action);
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
return iwl_mvm_mld_mac_ctxt_cmd_p2p_device(mvm, vif, action);
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return iwl_mvm_mld_mac_ctxt_cmd_ibss(mvm, vif, action);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
|
||||
vif->addr, ieee80211_vif_type_p2p(vif)))
|
||||
return -EIO;
|
||||
|
||||
ret = iwl_mvm_mld_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,
|
||||
true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* will only do anything at resume from D3 time */
|
||||
iwl_mvm_set_last_nonqos_seq(mvm, vif);
|
||||
|
||||
mvmvif->uploaded = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
bool force_assoc_off)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
|
||||
vif->addr, ieee80211_vif_type_p2p(vif)))
|
||||
return -EIO;
|
||||
|
||||
return iwl_mvm_mld_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,
|
||||
force_assoc_off);
|
||||
}
|
||||
|
||||
int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mac_config_cmd cmd = {
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
|
||||
.id_and_color = cpu_to_le32(mvmvif->id),
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
|
||||
vif->addr, ieee80211_vif_type_p2p(vif)))
|
||||
return -EIO;
|
||||
|
||||
ret = iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mvmvif->uploaded = false;
|
||||
|
||||
return 0;
|
||||
}
|
1074
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
Normal file
1074
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
Normal file
File diff suppressed because it is too large
Load Diff
1058
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
Normal file
1058
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,8 @@
|
||||
#include <linux/thermal.h>
|
||||
#endif
|
||||
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
|
||||
#include <linux/ktime.h>
|
||||
|
||||
#include "iwl-op-mode.h"
|
||||
@ -71,7 +73,11 @@
|
||||
/* offchannel queue towards mac80211 */
|
||||
#define IWL_MVM_OFFCHANNEL_QUEUE 0
|
||||
|
||||
/* invalid value for FW link id */
|
||||
#define IWL_MVM_FW_LINK_ID_INVALID 0xff
|
||||
|
||||
extern const struct ieee80211_ops iwl_mvm_hw_ops;
|
||||
extern const struct ieee80211_ops iwl_mvm_mld_hw_ops;
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_mod_params - module parameters for iwlmvm
|
||||
@ -277,12 +283,61 @@ struct iwl_probe_resp_data {
|
||||
int noa_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_vif_link_info - per link data in Virtual Interface
|
||||
* @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA
|
||||
* @fw_link_id: the id of the link according to the FW API
|
||||
* @bssid: BSSID for this (client) interface
|
||||
* @bcast_sta: station used for broadcast packets. Used by the following
|
||||
* vifs: P2P_DEVICE, GO and AP.
|
||||
* @beacon_stats: beacon statistics, containing the # of received beacons,
|
||||
* # of received beacons accumulated over FW restart, and the current
|
||||
* average signal of beacons retrieved from the firmware
|
||||
* @smps_requests: the SMPS requests of different parts of the driver,
|
||||
* combined on update to yield the overall request to mac80211.
|
||||
* @probe_resp_data: data from FW notification to store NOA and CSA related
|
||||
* data to be inserted into probe response.
|
||||
* @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked
|
||||
* @queue_params: QoS params for this MAC
|
||||
* @mgmt_queue: queue number for unbufferable management frames
|
||||
*/
|
||||
struct iwl_mvm_vif_link_info {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 ap_sta_id;
|
||||
u8 fw_link_id;
|
||||
|
||||
struct iwl_mvm_int_sta bcast_sta;
|
||||
struct iwl_mvm_int_sta mcast_sta;
|
||||
|
||||
struct {
|
||||
u32 num_beacons, accu_num_beacons;
|
||||
u8 avg_signal;
|
||||
} beacon_stats;
|
||||
|
||||
enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
|
||||
struct iwl_probe_resp_data __rcu *probe_resp_data;
|
||||
|
||||
bool he_ru_2mhz_block;
|
||||
bool active;
|
||||
|
||||
u16 cab_queue;
|
||||
/* Assigned while mac80211 has the link in a channel context,
|
||||
* or, for P2P Device, while it exists.
|
||||
*/
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||
/* QoS data from mac80211, need to store this here
|
||||
* as mac80211 has a separate callback but we need
|
||||
* to have the data for the MAC context
|
||||
*/
|
||||
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
|
||||
|
||||
u16 mgmt_queue;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context
|
||||
* @id: between 0 and 3
|
||||
* @color: to solve races upon MAC addition and removal
|
||||
* @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA
|
||||
* @bssid: BSSID for this (client) interface
|
||||
* @associated: indicates that we're currently associated, used only for
|
||||
* managing the firmware state in iwl_mvm_bss_info_changed_station()
|
||||
* @ap_assoc_sta_count: count of stations associated to us - valid only
|
||||
@ -290,7 +345,7 @@ struct iwl_probe_resp_data {
|
||||
* @uploaded: indicates the MAC context has been added to the device
|
||||
* @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
|
||||
* should get quota etc.
|
||||
* @pm_enabled - Indicate if MAC power management is allowed
|
||||
* @pm_enabled - indicate if MAC power management is allowed
|
||||
* @monitor_active: indicates that monitor context is configured, and that the
|
||||
* interface should get quota etc.
|
||||
* @low_latency: bit flags for low latency
|
||||
@ -299,68 +354,31 @@ struct iwl_probe_resp_data {
|
||||
* as a result from low_latency bit flags and takes force into account.
|
||||
* @authorized: indicates the AP station was set to authorized
|
||||
* @ps_disabled: indicates that this interface requires PS to be disabled
|
||||
* @queue_params: QoS params for this MAC
|
||||
* @bcast_sta: station used for broadcast packets. Used by the following
|
||||
* vifs: P2P_DEVICE, GO and AP.
|
||||
* @beacon_skb: the skb used to hold the AP/GO beacon template
|
||||
* @smps_requests: the SMPS requests of different parts of the driver,
|
||||
* combined on update to yield the overall request to mac80211.
|
||||
* @beacon_stats: beacon statistics, containing the # of received beacons,
|
||||
* # of received beacons accumulated over FW restart, and the current
|
||||
* average signal of beacons retrieved from the firmware
|
||||
* @csa_countdown: indicates that CSA countdown may be started
|
||||
* @csa_failed: CSA failed to schedule time event, report an error later
|
||||
* @csa_bcn_pending: indicates that we are waiting for a beacon on a new channel
|
||||
* @features: hw features active for this vif
|
||||
* @probe_resp_data: data from FW notification to store NOA and CSA related
|
||||
* data to be inserted into probe response.
|
||||
*/
|
||||
struct iwl_mvm_vif {
|
||||
struct iwl_mvm *mvm;
|
||||
u16 id;
|
||||
u16 color;
|
||||
u8 ap_sta_id;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
bool associated;
|
||||
u8 ap_assoc_sta_count;
|
||||
|
||||
u16 cab_queue;
|
||||
|
||||
bool uploaded;
|
||||
bool ap_ibss_active;
|
||||
bool pm_enabled;
|
||||
bool monitor_active;
|
||||
|
||||
u8 low_latency: 6;
|
||||
u8 low_latency_actual: 1;
|
||||
|
||||
u8 authorized:1;
|
||||
bool ps_disabled;
|
||||
struct iwl_mvm_vif_bf_data bf_data;
|
||||
|
||||
struct {
|
||||
u32 num_beacons, accu_num_beacons;
|
||||
u8 avg_signal;
|
||||
} beacon_stats;
|
||||
|
||||
u32 ap_beacon_time;
|
||||
|
||||
enum iwl_tsf_id tsf_id;
|
||||
|
||||
/*
|
||||
* QoS data from mac80211, need to store this here
|
||||
* as mac80211 has a separate callback but we need
|
||||
* to have the data for the MAC context
|
||||
*/
|
||||
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
|
||||
struct iwl_mvm_time_event_data time_event_data;
|
||||
struct iwl_mvm_time_event_data hs_time_event_data;
|
||||
|
||||
struct iwl_mvm_int_sta bcast_sta;
|
||||
struct iwl_mvm_int_sta mcast_sta;
|
||||
|
||||
/*
|
||||
* Assigned while mac80211 has the interface in a channel context,
|
||||
* or, for P2P Device, while it exists.
|
||||
*/
|
||||
struct iwl_mvm_phy_ctxt *phy_ctxt;
|
||||
struct iwl_mvm_vif_bf_data bf_data;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* WoWLAN GTK rekey data */
|
||||
@ -396,40 +414,43 @@ struct iwl_mvm_vif {
|
||||
int dbgfs_quota_min;
|
||||
#endif
|
||||
|
||||
enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
|
||||
|
||||
/* FW identified misbehaving AP */
|
||||
u8 uapsd_misbehaving_bssid[ETH_ALEN];
|
||||
|
||||
struct delayed_work uapsd_nonagg_detected_wk;
|
||||
|
||||
/* Indicates that CSA countdown may be started */
|
||||
bool csa_countdown;
|
||||
bool csa_failed;
|
||||
bool csa_bcn_pending;
|
||||
u16 csa_target_freq;
|
||||
u16 csa_count;
|
||||
u16 csa_misbehave;
|
||||
struct delayed_work csa_work;
|
||||
|
||||
/* Indicates that we are waiting for a beacon on a new channel */
|
||||
bool csa_bcn_pending;
|
||||
enum iwl_tsf_id tsf_id;
|
||||
|
||||
struct iwl_mvm_time_event_data time_event_data;
|
||||
struct iwl_mvm_time_event_data hs_time_event_data;
|
||||
|
||||
/* TCP Checksum Offload */
|
||||
netdev_features_t features;
|
||||
|
||||
struct iwl_probe_resp_data __rcu *probe_resp_data;
|
||||
|
||||
/* we can only have 2 GTK + 2 IGTK active at a time */
|
||||
struct ieee80211_key_conf *ap_early_keys[4];
|
||||
|
||||
/* 26-tone RU OFDMA transmissions should be blocked */
|
||||
bool he_ru_2mhz_block;
|
||||
|
||||
struct {
|
||||
struct ieee80211_key_conf __rcu *keys[2];
|
||||
} bcn_prot;
|
||||
|
||||
struct iwl_mvm_vif_link_info deflink;
|
||||
struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
};
|
||||
|
||||
#define for_each_mvm_vif_valid_link(mvm_vif, link_id) \
|
||||
for (link_id = 0; \
|
||||
link_id < ARRAY_SIZE((mvm_vif)->link); \
|
||||
link_id++) \
|
||||
if ((mvm_vif)->link[link_id])
|
||||
|
||||
static inline struct iwl_mvm_vif *
|
||||
iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -772,6 +793,37 @@ struct iwl_mvm_dqa_txq_info {
|
||||
enum iwl_mvm_queue_status status;
|
||||
};
|
||||
|
||||
struct ptp_data {
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_clock_info;
|
||||
|
||||
struct delayed_work dwork;
|
||||
|
||||
/* The last GP2 reading from the hw */
|
||||
u32 last_gp2;
|
||||
|
||||
/* number of wraparounds since scale_update_adj_time_ns */
|
||||
u32 wrap_counter;
|
||||
|
||||
/* GP2 time when the scale was last updated */
|
||||
u32 scale_update_gp2;
|
||||
|
||||
/* Adjusted time when the scale was last updated in nanoseconds */
|
||||
u64 scale_update_adj_time_ns;
|
||||
|
||||
/* clock frequency offset, scaled to 65536000000 */
|
||||
u64 scaled_freq;
|
||||
|
||||
/* Delta between hardware clock and ptp clock in nanoseconds */
|
||||
s64 delta;
|
||||
};
|
||||
|
||||
struct iwl_time_sync_data {
|
||||
struct sk_buff_head frame_list;
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
bool active;
|
||||
};
|
||||
|
||||
struct iwl_mvm {
|
||||
/* for logger access */
|
||||
struct device *dev;
|
||||
@ -857,6 +909,8 @@ struct iwl_mvm {
|
||||
/* data related to data path */
|
||||
struct iwl_rx_phy_info last_phy_info;
|
||||
struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_MVM_STATION_COUNT_MAX];
|
||||
unsigned long fw_link_ids_map;
|
||||
u8 rx_ba_sessions;
|
||||
|
||||
/* configured by mac80211 */
|
||||
@ -1083,6 +1137,8 @@ struct iwl_mvm {
|
||||
|
||||
struct list_head resp_pasn_list;
|
||||
|
||||
struct ptp_data ptp_data;
|
||||
|
||||
struct {
|
||||
u8 range_resp;
|
||||
} cmd_ver;
|
||||
@ -1114,8 +1170,11 @@ struct iwl_mvm {
|
||||
unsigned long last_reset_or_resume_time_jiffies;
|
||||
|
||||
bool sta_remove_requires_queue_remove;
|
||||
bool mld_api_is_used;
|
||||
|
||||
bool pldr_sync;
|
||||
|
||||
struct iwl_time_sync_data time_sync;
|
||||
};
|
||||
|
||||
/* Extract MVM priv from op_mode and _hw */
|
||||
@ -1315,7 +1374,7 @@ static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT) &&
|
||||
!IWL_MVM_HW_CSUM_DISABLE;
|
||||
!IWL_MVM_HW_CSUM_DISABLE;
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm)
|
||||
@ -1340,6 +1399,28 @@ static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
|
||||
IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_has_mld_api(const struct iwl_fw *fw)
|
||||
{
|
||||
return (iwl_fw_lookup_cmd_ver(fw, LINK_CONFIG_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN) !=
|
||||
IWL_FW_CMD_VER_UNKNOWN) &&
|
||||
(iwl_fw_lookup_cmd_ver(fw, MAC_CONFIG_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN) !=
|
||||
IWL_FW_CMD_VER_UNKNOWN) &&
|
||||
(iwl_fw_lookup_cmd_ver(fw, STA_CONFIG_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN) !=
|
||||
IWL_FW_CMD_VER_UNKNOWN) &&
|
||||
(iwl_fw_lookup_cmd_ver(fw, AUX_STA_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN) !=
|
||||
IWL_FW_CMD_VER_UNKNOWN) &&
|
||||
(iwl_fw_lookup_cmd_ver(fw, STA_REMOVE_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN) !=
|
||||
IWL_FW_CMD_VER_UNKNOWN) &&
|
||||
(iwl_fw_lookup_cmd_ver(fw, STA_DISABLE_TX_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN) !=
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* TODO - replace with TLV once defined */
|
||||
@ -1481,6 +1562,7 @@ void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
|
||||
struct ieee80211_tx_rate *r);
|
||||
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx);
|
||||
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);
|
||||
bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
||||
static inline void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||
{
|
||||
@ -1528,6 +1610,17 @@ 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_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids);
|
||||
|
||||
/* Utils to extract sta related data */
|
||||
__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta,
|
||||
struct ieee80211_link_sta *link_sta);
|
||||
u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta);
|
||||
u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
u32 *_agg_size);
|
||||
int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct iwl_he_pkt_ext_v2 *pkt_ext);
|
||||
|
||||
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
|
||||
|
||||
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
|
||||
@ -1627,6 +1720,7 @@ void iwl_mvm_rx_shared_mem_cfg_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
|
||||
/* MVM PHY */
|
||||
struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm);
|
||||
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);
|
||||
@ -1642,16 +1736,55 @@ u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef);
|
||||
u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
|
||||
|
||||
/* MAC (virtual interface) programming */
|
||||
|
||||
void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
__le32 *cck_rates, __le32 *ofdm_rates);
|
||||
void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
__le32 *protection_flags, u32 ht_flag,
|
||||
u32 tgg_flag);
|
||||
void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct iwl_ac_qos *ac, __le32 *qos_flags);
|
||||
bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif,
|
||||
struct iwl_he_backoff_conf *trig_based_txf);
|
||||
void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
__le64 *dtim_tsf, __le32 *dtim_time,
|
||||
__le32 *assoc_beacon_arrive_time);
|
||||
__le32 iwl_mac_ctxt_p2p_dev_has_extended_disc(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif,
|
||||
__le32 *filter_flags,
|
||||
int accept_probe_req_flag,
|
||||
int accept_beacon_flag);
|
||||
int iwl_mvm_get_mac_type(struct ieee80211_vif *vif);
|
||||
__le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool force_assoc_off);
|
||||
int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool force_assoc_off, const u8 *bssid_override);
|
||||
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *beacon);
|
||||
struct sk_buff *beacon,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
|
||||
struct sk_buff *beacon,
|
||||
void *data, int len);
|
||||
@ -1688,6 +1821,93 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
|
||||
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
||||
/* Links */
|
||||
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
u32 changes, bool active);
|
||||
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
|
||||
/* AP and IBSS */
|
||||
bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int *ret);
|
||||
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,
|
||||
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_assoc(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u64 changes);
|
||||
|
||||
/* ROC */
|
||||
/**
|
||||
* struct iwl_mvm_roc_ops - callbacks for the remain_on_channel()
|
||||
*
|
||||
* Since the only difference between both MLD and
|
||||
* non-MLD versions of remain_on_channel() is these function calls,
|
||||
* each version will send its specific function calls to
|
||||
* %iwl_mvm_roc_common().
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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 iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *channel, int duration,
|
||||
enum ieee80211_roc_type type,
|
||||
struct iwl_mvm_roc_ops *ops);
|
||||
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);
|
||||
|
||||
/* Quota management */
|
||||
static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm)
|
||||
{
|
||||
@ -1867,10 +2087,17 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
/* SMPS */
|
||||
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
enum iwl_mvm_smps_type_request req_type,
|
||||
enum ieee80211_smps_mode smps_request);
|
||||
enum ieee80211_smps_mode smps_request,
|
||||
unsigned int link_id);
|
||||
void
|
||||
iwl_mvm_update_smps_on_active_links(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
enum iwl_mvm_smps_type_request req_type,
|
||||
enum ieee80211_smps_mode smps_request);
|
||||
bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt);
|
||||
void iwl_mvm_apply_fw_smps_request(struct ieee80211_vif *vif);
|
||||
void iwl_mvm_update_link_smps(struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
|
||||
/* Low latency */
|
||||
int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
@ -2080,6 +2307,9 @@ void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
|
||||
const struct ieee80211_sta *sta,
|
||||
u16 tid);
|
||||
|
||||
void iwl_mvm_ptp_init(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_ptp_remove(struct iwl_mvm *mvm);
|
||||
u64 iwl_mvm_ptp_get_adj_time(struct iwl_mvm *mvm, u64 base_time);
|
||||
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b);
|
||||
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm);
|
||||
@ -2101,7 +2331,9 @@ int iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *keyconf);
|
||||
void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_vif_link_info *link,
|
||||
unsigned int link_id);
|
||||
|
||||
int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_rfi_lut_entry *rfi_table);
|
||||
@ -2124,6 +2356,45 @@ static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band)
|
||||
}
|
||||
}
|
||||
|
||||
/* Channel Switch */
|
||||
void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk);
|
||||
int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
/* Channel Context */
|
||||
/**
|
||||
* struct iwl_mvm_switch_vif_chanctx_ops - callbacks for switch_vif_chanctx()
|
||||
*
|
||||
* Since the only difference between both MLD and
|
||||
* non-MLD versions of switch_vif_chanctx() is these function calls,
|
||||
* each version will send its specific function calls to
|
||||
* %iwl_mvm_switch_vif_chanctx_common().
|
||||
*
|
||||
* @__assign_vif_chanctx: pointer to the function that assigns a chanctx to
|
||||
* a given vif
|
||||
* @__unassign_vif_chanctx: pointer to the function that unassigns a chanctx to
|
||||
* a given vif
|
||||
*/
|
||||
struct iwl_mvm_switch_vif_chanctx_ops {
|
||||
int (*__assign_vif_chanctx)(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
bool switching_chanctx);
|
||||
void (*__unassign_vif_chanctx)(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
bool switching_chanctx);
|
||||
};
|
||||
|
||||
int
|
||||
iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs,
|
||||
enum ieee80211_chanctx_switch_mode mode,
|
||||
struct iwl_mvm_switch_vif_chanctx_ops *ops);
|
||||
|
||||
/* Channel info utils */
|
||||
static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm)
|
||||
{
|
||||
@ -2244,5 +2515,128 @@ static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm)
|
||||
void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
bool forbidden);
|
||||
bool iwl_mvm_is_vendor_in_approved_list(void);
|
||||
|
||||
/* Callbacks for ieee80211_ops */
|
||||
void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_control *control, struct sk_buff *skb);
|
||||
void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq);
|
||||
|
||||
int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params);
|
||||
int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
|
||||
int iwl_mvm_mac_start(struct ieee80211_hw *hw);
|
||||
void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
|
||||
enum ieee80211_reconfig_type reconfig_type);
|
||||
void iwl_mvm_mac_stop(struct ieee80211_hw *hw);
|
||||
static inline int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
|
||||
struct netdev_hw_addr_list *mc_list);
|
||||
|
||||
void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags, u64 multicast);
|
||||
int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *hw_req);
|
||||
void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta);
|
||||
void
|
||||
iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, u16 tids,
|
||||
int num_frames,
|
||||
enum ieee80211_frame_release_type reason,
|
||||
bool more_data);
|
||||
void
|
||||
iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, u16 tids,
|
||||
int num_frames,
|
||||
enum ieee80211_frame_release_type reason,
|
||||
bool more_data);
|
||||
int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
|
||||
void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u32 changed);
|
||||
void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_prep_tx_info *info);
|
||||
void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_prep_tx_info *info);
|
||||
void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u32 queues, bool drop);
|
||||
int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_sched_scan_request *req,
|
||||
struct ieee80211_scan_ies *ies);
|
||||
int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 iv32, u16 *phase1key);
|
||||
int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
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,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw);
|
||||
void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw);
|
||||
void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const struct ieee80211_event *event);
|
||||
void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw);
|
||||
int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
void *data, int len);
|
||||
int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
struct survey_info *survey);
|
||||
void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo);
|
||||
int
|
||||
iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_ftm_responder_stats *stats);
|
||||
int iwl_mvm_start_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *request);
|
||||
void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct cfg80211_pmsr_request *request);
|
||||
|
||||
bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1,
|
||||
struct iwl_mvm_vif *vif2);
|
||||
bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif);
|
||||
int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
s16 tx_power);
|
||||
int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_set_hw_timestamp *hwts);
|
||||
int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "fw-api.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/uefi.h"
|
||||
#include "time-sync.h"
|
||||
|
||||
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
@ -208,24 +209,37 @@ static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
|
||||
ieee80211_disconnect(vif, true);
|
||||
}
|
||||
|
||||
void iwl_mvm_apply_fw_smps_request(struct ieee80211_vif *vif)
|
||||
void iwl_mvm_update_link_smps(struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
enum ieee80211_smps_mode mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
if (!link_conf)
|
||||
return;
|
||||
|
||||
if (mvm->fw_static_smps_request &&
|
||||
vif->bss_conf.chandef.width == NL80211_CHAN_WIDTH_160 &&
|
||||
vif->bss_conf.he_support)
|
||||
link_conf->chandef.width == NL80211_CHAN_WIDTH_160 &&
|
||||
link_conf->he_support)
|
||||
mode = IEEE80211_SMPS_STATIC;
|
||||
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_FW, mode);
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_FW, mode,
|
||||
link_conf->link_id);
|
||||
}
|
||||
|
||||
static void iwl_mvm_intf_dual_chain_req(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
iwl_mvm_apply_fw_smps_request(vif);
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int link_id;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id)
|
||||
iwl_mvm_update_link_smps(vif, link_conf);
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx_thermal_dual_chain_req(struct iwl_mvm *mvm,
|
||||
@ -404,6 +418,15 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
||||
RX_HANDLER_GRP(SYSTEM_GROUP, RFI_DEACTIVATE_NOTIF,
|
||||
iwl_rfi_deactivate_notif_handler, RX_HANDLER_ASYNC_UNLOCKED,
|
||||
struct iwl_rfi_deactivate_notif),
|
||||
|
||||
RX_HANDLER_GRP(LEGACY_GROUP,
|
||||
WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION,
|
||||
iwl_mvm_time_sync_msmt_event, RX_HANDLER_SYNC,
|
||||
struct iwl_time_msmt_notify),
|
||||
RX_HANDLER_GRP(LEGACY_GROUP,
|
||||
WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION,
|
||||
iwl_mvm_time_sync_msmt_confirm_event, RX_HANDLER_SYNC,
|
||||
struct iwl_time_msmt_cfm_notify),
|
||||
};
|
||||
#undef RX_HANDLER
|
||||
#undef RX_HANDLER_GRP
|
||||
@ -449,6 +472,8 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
|
||||
HCMD_NAME(SCAN_OFFLOAD_PROFILES_QUERY_CMD),
|
||||
HCMD_NAME(BT_COEX_UPDATE_REDUCED_TXP),
|
||||
HCMD_NAME(BT_COEX_CI),
|
||||
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION),
|
||||
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION),
|
||||
HCMD_NAME(PHY_CONFIGURATION_CMD),
|
||||
HCMD_NAME(CALIB_RES_NOTIF_PHY_DB),
|
||||
HCMD_NAME(PHY_DB_CMD),
|
||||
@ -521,6 +546,12 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
||||
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
|
||||
HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),
|
||||
HCMD_NAME(SESSION_PROTECTION_CMD),
|
||||
HCMD_NAME(MAC_CONFIG_CMD),
|
||||
HCMD_NAME(LINK_CONFIG_CMD),
|
||||
HCMD_NAME(STA_CONFIG_CMD),
|
||||
HCMD_NAME(AUX_STA_CMD),
|
||||
HCMD_NAME(STA_REMOVE_CMD),
|
||||
HCMD_NAME(STA_DISABLE_TX_CMD),
|
||||
HCMD_NAME(SESSION_PROTECTION_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),
|
||||
};
|
||||
@ -1098,6 +1129,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
********************************/
|
||||
hw = ieee80211_alloc_hw(sizeof(struct iwl_op_mode) +
|
||||
sizeof(struct iwl_mvm),
|
||||
iwl_mvm_has_mld_api(fw) ? &iwl_mvm_mld_hw_ops :
|
||||
&iwl_mvm_hw_ops);
|
||||
if (!hw)
|
||||
return NULL;
|
||||
@ -1278,6 +1310,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
mvm->sta_remove_requires_queue_remove =
|
||||
trans_cfg.queue_alloc_cmd_ver > 0;
|
||||
|
||||
mvm->mld_api_is_used = iwl_mvm_has_mld_api(mvm->fw);
|
||||
|
||||
/* Configure transport layer */
|
||||
iwl_trans_configure(mvm->trans, &trans_cfg);
|
||||
|
||||
@ -1333,6 +1367,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
else
|
||||
memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
|
||||
|
||||
iwl_mvm_init_time_sync(&mvm->time_sync);
|
||||
|
||||
mvm->debugfs_dir = dbgfs_dir;
|
||||
|
||||
mvm->mei_registered = !iwl_mei_register(mvm, &mei_ops);
|
||||
@ -1430,6 +1466,8 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
||||
kfree(mvm->error_recovery_buf);
|
||||
mvm->error_recovery_buf = NULL;
|
||||
|
||||
iwl_mvm_ptp_remove(mvm);
|
||||
|
||||
iwl_trans_op_mode_leave(mvm->trans);
|
||||
|
||||
iwl_phy_db_free(mvm->phy_db);
|
||||
|
@ -382,12 +382,12 @@ static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
|
||||
unsigned long *data = _data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (!mvmvif->phy_ctxt)
|
||||
if (!mvmvif->deflink.phy_ctxt)
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION ||
|
||||
vif->type == NL80211_IFTYPE_AP)
|
||||
__set_bit(mvmvif->phy_ctxt->id, data);
|
||||
__set_bit(mvmvif->deflink.phy_ctxt->id, data);
|
||||
}
|
||||
|
||||
int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm)
|
||||
|
@ -150,7 +150,7 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
|
||||
#endif
|
||||
|
||||
for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
|
||||
if (!mvmvif->queue_params[ac].uapsd)
|
||||
if (!mvmvif->deflink.queue_params[ac].uapsd)
|
||||
continue;
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
|
||||
@ -160,7 +160,7 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
|
||||
cmd->uapsd_ac_flags |= BIT(ac);
|
||||
|
||||
/* QNDP TID - the highest TID with no admission control */
|
||||
if (!tid_found && !mvmvif->queue_params[ac].acm) {
|
||||
if (!tid_found && !mvmvif->deflink.queue_params[ac].acm) {
|
||||
tid_found = true;
|
||||
switch (ac) {
|
||||
case IEEE80211_AC_VO:
|
||||
@ -279,18 +279,25 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
||||
static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_channel *chan;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
bool radar_detect = false;
|
||||
unsigned int link_id;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf);
|
||||
WARN_ON(!chanctx_conf);
|
||||
if (chanctx_conf) {
|
||||
chan = chanctx_conf->def.chan;
|
||||
radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
|
||||
/* this happens on link switching, just ignore inactive ones */
|
||||
if (!chanctx_conf)
|
||||
continue;
|
||||
|
||||
radar_detect = !!(chanctx_conf->def.chan->flags &
|
||||
IEEE80211_CHAN_RADAR);
|
||||
if (radar_detect)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return radar_detect;
|
||||
}
|
||||
|
||||
@ -509,8 +516,9 @@ static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
|
||||
/* The ap_sta_id is not expected to change during current association
|
||||
* so no explicit protection is needed
|
||||
*/
|
||||
if (mvmvif->ap_sta_id == *ap_sta_id)
|
||||
memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
|
||||
if (mvmvif->deflink.ap_sta_id == *ap_sta_id)
|
||||
memcpy(mvmvif->uapsd_misbehaving_bssid,
|
||||
vif->bss_conf.bssid,
|
||||
ETH_ALEN);
|
||||
}
|
||||
|
||||
@ -552,7 +560,7 @@ static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
bool *disable_ps = _data;
|
||||
|
||||
if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX)
|
||||
if (iwl_mvm_vif_is_active(mvmvif))
|
||||
*disable_ps |= mvmvif->ps_disabled;
|
||||
}
|
||||
|
||||
@ -561,11 +569,13 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_power_vifs *power_iterator = _data;
|
||||
bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
|
||||
bool active;
|
||||
|
||||
if (!mvmvif->uploaded)
|
||||
return;
|
||||
|
||||
active = iwl_mvm_vif_is_active(mvmvif);
|
||||
|
||||
switch (ieee80211_vif_type_p2p(vif)) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
break;
|
||||
@ -649,11 +659,12 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
if (vifs->bss_active && vifs->p2p_active)
|
||||
client_same_channel = (bss_mvmvif->phy_ctxt->id ==
|
||||
p2p_mvmvif->phy_ctxt->id);
|
||||
client_same_channel =
|
||||
iwl_mvm_have_links_same_channel(bss_mvmvif, p2p_mvmvif);
|
||||
|
||||
if (vifs->bss_active && vifs->ap_active)
|
||||
ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
|
||||
ap_mvmvif->phy_ctxt->id);
|
||||
ap_same_channel =
|
||||
iwl_mvm_have_links_same_channel(bss_mvmvif, ap_mvmvif);
|
||||
|
||||
/* clients are not stand alone: enable PM if DCM */
|
||||
if (!(client_same_channel || ap_same_channel)) {
|
||||
|
326
drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
Normal file
326
drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
Normal file
@ -0,0 +1,326 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2021 - 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "mvm.h"
|
||||
#include "iwl-debug.h"
|
||||
#include <linux/timekeeping.h>
|
||||
#include <linux/math64.h>
|
||||
|
||||
#define IWL_PTP_GP2_WRAP 0x100000000ULL
|
||||
#define IWL_PTP_WRAP_TIME (3600 * HZ)
|
||||
|
||||
/* The scaled_ppm parameter is ppm (parts per million) with a 16-bit fractional
|
||||
* part, which means that a value of 1 in one of those fields actually means
|
||||
* 2^-16 ppm, and 2^16=65536 is 1 ppm.
|
||||
*/
|
||||
#define SCALE_FACTOR 65536000000ULL
|
||||
#define IWL_PTP_WRAP_THRESHOLD_USEC (5000)
|
||||
|
||||
#define IWL_PTP_GET_CROSS_TS_NUM 5
|
||||
|
||||
static void iwl_mvm_ptp_update_new_read(struct iwl_mvm *mvm, u32 gp2)
|
||||
{
|
||||
/* If the difference is above the threshold, assume it's a wraparound.
|
||||
* Otherwise assume it's an old read and ignore it.
|
||||
*/
|
||||
if (gp2 < mvm->ptp_data.last_gp2 &&
|
||||
mvm->ptp_data.last_gp2 - gp2 < IWL_PTP_WRAP_THRESHOLD_USEC) {
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"PTP: ignore old read (gp2=%u, last_gp2=%u)\n",
|
||||
gp2, mvm->ptp_data.last_gp2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gp2 < mvm->ptp_data.last_gp2) {
|
||||
mvm->ptp_data.wrap_counter++;
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"PTP: wraparound detected (new counter=%u)\n",
|
||||
mvm->ptp_data.wrap_counter);
|
||||
}
|
||||
|
||||
mvm->ptp_data.last_gp2 = gp2;
|
||||
schedule_delayed_work(&mvm->ptp_data.dwork, IWL_PTP_WRAP_TIME);
|
||||
}
|
||||
|
||||
u64 iwl_mvm_ptp_get_adj_time(struct iwl_mvm *mvm, u64 base_time_ns)
|
||||
{
|
||||
struct ptp_data *data = &mvm->ptp_data;
|
||||
u64 last_gp2_ns = mvm->ptp_data.scale_update_gp2 * NSEC_PER_USEC;
|
||||
u64 res;
|
||||
u64 diff;
|
||||
|
||||
iwl_mvm_ptp_update_new_read(mvm,
|
||||
div64_u64(base_time_ns, NSEC_PER_USEC));
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "base_time_ns=%llu, wrap_counter=%u\n",
|
||||
(unsigned long long)base_time_ns, data->wrap_counter);
|
||||
|
||||
base_time_ns = base_time_ns +
|
||||
(data->wrap_counter * IWL_PTP_GP2_WRAP * NSEC_PER_USEC);
|
||||
|
||||
/* It is possible that a GP2 timestamp was received from fw before the
|
||||
* last scale update. Since we don't know how to scale - ignore it.
|
||||
*/
|
||||
if (base_time_ns < last_gp2_ns) {
|
||||
IWL_DEBUG_INFO(mvm, "Time before scale update - ignore\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff = base_time_ns - last_gp2_ns;
|
||||
IWL_DEBUG_INFO(mvm, "diff ns=%llu\n", (unsigned long long)diff);
|
||||
|
||||
diff = mul_u64_u64_div_u64(diff, data->scaled_freq,
|
||||
SCALE_FACTOR);
|
||||
IWL_DEBUG_INFO(mvm, "scaled diff ns=%llu\n", (unsigned long long)diff);
|
||||
|
||||
res = data->scale_update_adj_time_ns + data->delta + diff;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "base=%llu delta=%lld adj=%llu\n",
|
||||
(unsigned long long)base_time_ns, (long long)data->delta,
|
||||
(unsigned long long)res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mvm_get_crosstimestamp_fw(struct iwl_mvm *mvm, u32 *gp2, u64 *sys_time)
|
||||
{
|
||||
struct iwl_synced_time_cmd synced_time_cmd = {
|
||||
.operation = cpu_to_le32(IWL_SYNCED_TIME_OPERATION_READ_BOTH)
|
||||
};
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WIDE_ID(DATA_PATH_GROUP, WNM_PLATFORM_PTM_REQUEST_CMD),
|
||||
.flags = CMD_WANT_SKB,
|
||||
.data[0] = &synced_time_cmd,
|
||||
.len[0] = sizeof(synced_time_cmd),
|
||||
};
|
||||
struct iwl_synced_time_rsp *resp;
|
||||
struct iwl_rx_packet *pkt;
|
||||
int ret;
|
||||
u64 gp2_10ns;
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pkt = cmd.resp_pkt;
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) != sizeof(*resp)) {
|
||||
IWL_ERR(mvm, "PTP: Invalid command response\n");
|
||||
iwl_free_resp(&cmd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
resp = (void *)pkt->data;
|
||||
|
||||
gp2_10ns = (u64)le32_to_cpu(resp->gp2_timestamp_hi) << 32 |
|
||||
le32_to_cpu(resp->gp2_timestamp_lo);
|
||||
*gp2 = div_u64(gp2_10ns, 100);
|
||||
|
||||
*sys_time = (u64)le32_to_cpu(resp->platform_timestamp_hi) << 32 |
|
||||
le32_to_cpu(resp->platform_timestamp_lo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_phc_get_crosstimestamp_loop(struct iwl_mvm *mvm,
|
||||
ktime_t *sys_time, u32 *gp2)
|
||||
{
|
||||
u64 diff = 0, new_diff;
|
||||
u64 tmp_sys_time;
|
||||
u32 tmp_gp2;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IWL_PTP_GET_CROSS_TS_NUM; i++) {
|
||||
iwl_mvm_get_sync_time(mvm, CLOCK_REALTIME, &tmp_gp2, NULL,
|
||||
&tmp_sys_time);
|
||||
new_diff = tmp_sys_time - ((u64)tmp_gp2 * NSEC_PER_USEC);
|
||||
if (!diff || new_diff < diff) {
|
||||
*sys_time = tmp_sys_time;
|
||||
*gp2 = tmp_gp2;
|
||||
diff = new_diff;
|
||||
IWL_DEBUG_INFO(mvm, "PTP: new times: gp2=%u sys=%lld\n",
|
||||
*gp2, *sys_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mvm_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
|
||||
struct system_device_crosststamp *xtstamp)
|
||||
{
|
||||
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
|
||||
ptp_data.ptp_clock_info);
|
||||
int ret = 0;
|
||||
/* Raw value read from GP2 register in usec */
|
||||
u32 gp2;
|
||||
/* GP2 value in ns*/
|
||||
s64 gp2_ns;
|
||||
/* System (wall) time */
|
||||
ktime_t sys_time;
|
||||
|
||||
memset(xtstamp, 0, sizeof(struct system_device_crosststamp));
|
||||
|
||||
if (!mvm->ptp_data.ptp_clock) {
|
||||
IWL_ERR(mvm, "No PHC clock registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SYNCED_TIME)) {
|
||||
ret = iwl_mvm_get_crosstimestamp_fw(mvm, &gp2, &sys_time);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
} else {
|
||||
iwl_mvm_phc_get_crosstimestamp_loop(mvm, &sys_time, &gp2);
|
||||
}
|
||||
|
||||
gp2_ns = iwl_mvm_ptp_get_adj_time(mvm, (u64)gp2 * NSEC_PER_USEC);
|
||||
|
||||
IWL_INFO(mvm, "Got Sync Time: GP2:%u, last_GP2: %u, GP2_ns: %lld, sys_time: %lld\n",
|
||||
gp2, mvm->ptp_data.last_gp2, gp2_ns, (s64)sys_time);
|
||||
|
||||
/* System monotonic raw time is not used */
|
||||
xtstamp->device = (ktime_t)gp2_ns;
|
||||
xtstamp->sys_realtime = sys_time;
|
||||
|
||||
out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_ptp_work(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm,
|
||||
ptp_data.dwork.work);
|
||||
u32 gp2;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
gp2 = iwl_mvm_get_systime(mvm);
|
||||
iwl_mvm_ptp_update_new_read(mvm, gp2);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static int iwl_mvm_ptp_gettime(struct ptp_clock_info *ptp,
|
||||
struct timespec64 *ts)
|
||||
{
|
||||
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
|
||||
ptp_data.ptp_clock_info);
|
||||
u64 gp2;
|
||||
u64 ns;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
gp2 = iwl_mvm_get_systime(mvm);
|
||||
ns = iwl_mvm_ptp_get_adj_time(mvm, gp2 * NSEC_PER_USEC);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
*ts = ns_to_timespec64(ns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
|
||||
ptp_data.ptp_clock_info);
|
||||
struct ptp_data *data = container_of(ptp, struct ptp_data,
|
||||
ptp_clock_info);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
data->delta += delta;
|
||||
IWL_DEBUG_INFO(mvm, "delta=%lld, new delta=%lld\n", (long long)delta,
|
||||
(long long)data->delta);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
||||
{
|
||||
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
|
||||
ptp_data.ptp_clock_info);
|
||||
struct ptp_data *data = &mvm->ptp_data;
|
||||
u32 gp2;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
/* Must call _iwl_mvm_ptp_get_adj_time() before updating
|
||||
* data->scale_update_gp2 or data->scaled_freq since
|
||||
* scale_update_adj_time_ns should reflect the previous scaled_freq.
|
||||
*/
|
||||
gp2 = iwl_mvm_get_systime(mvm);
|
||||
data->scale_update_adj_time_ns =
|
||||
iwl_mvm_ptp_get_adj_time(mvm, gp2 * NSEC_PER_USEC);
|
||||
data->scale_update_gp2 = gp2;
|
||||
data->wrap_counter = 0;
|
||||
data->delta = 0;
|
||||
|
||||
data->scaled_freq = SCALE_FACTOR + scaled_ppm;
|
||||
IWL_DEBUG_INFO(mvm, "adjfine: scaled_ppm=%ld new=%llu\n",
|
||||
scaled_ppm, (unsigned long long)data->scaled_freq);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* iwl_mvm_ptp_init - initialize PTP for devices which support it.
|
||||
* @mvm: internal mvm structure, see &struct iwl_mvm.
|
||||
*
|
||||
* Performs the required steps for enabling PTP support.
|
||||
*/
|
||||
void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* Warn if the interface already has a ptp_clock defined */
|
||||
if (WARN_ON(mvm->ptp_data.ptp_clock))
|
||||
return;
|
||||
|
||||
mvm->ptp_data.ptp_clock_info.owner = THIS_MODULE;
|
||||
mvm->ptp_data.ptp_clock_info.max_adj = 0x7fffffff;
|
||||
mvm->ptp_data.ptp_clock_info.getcrosststamp =
|
||||
iwl_mvm_phc_get_crosstimestamp;
|
||||
mvm->ptp_data.ptp_clock_info.adjfine = iwl_mvm_ptp_adjfine;
|
||||
mvm->ptp_data.ptp_clock_info.adjtime = iwl_mvm_ptp_adjtime;
|
||||
mvm->ptp_data.ptp_clock_info.gettime64 = iwl_mvm_ptp_gettime;
|
||||
mvm->ptp_data.scaled_freq = SCALE_FACTOR;
|
||||
|
||||
/* Give a short 'friendly name' to identify the PHC clock */
|
||||
snprintf(mvm->ptp_data.ptp_clock_info.name,
|
||||
sizeof(mvm->ptp_data.ptp_clock_info.name),
|
||||
"%s", "iwlwifi-PTP");
|
||||
|
||||
INIT_DELAYED_WORK(&mvm->ptp_data.dwork, iwl_mvm_ptp_work);
|
||||
|
||||
mvm->ptp_data.ptp_clock =
|
||||
ptp_clock_register(&mvm->ptp_data.ptp_clock_info, mvm->dev);
|
||||
|
||||
if (IS_ERR(mvm->ptp_data.ptp_clock)) {
|
||||
IWL_ERR(mvm, "Failed to register PHC clock (%ld)\n",
|
||||
PTR_ERR(mvm->ptp_data.ptp_clock));
|
||||
mvm->ptp_data.ptp_clock = NULL;
|
||||
} else if (mvm->ptp_data.ptp_clock) {
|
||||
IWL_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
|
||||
mvm->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mvm->ptp_data.ptp_clock));
|
||||
}
|
||||
}
|
||||
|
||||
/* iwl_mvm_ptp_remove - disable PTP device.
|
||||
* @mvm: internal mvm structure, see &struct iwl_mvm.
|
||||
*
|
||||
* Disable PTP support.
|
||||
*/
|
||||
void iwl_mvm_ptp_remove(struct iwl_mvm *mvm)
|
||||
{
|
||||
if (mvm->ptp_data.ptp_clock) {
|
||||
IWL_INFO(mvm, "Unregistering PHC clock: %s, with index: %d\n",
|
||||
mvm->ptp_data.ptp_clock_info.name,
|
||||
ptp_clock_index(mvm->ptp_data.ptp_clock));
|
||||
|
||||
ptp_clock_unregister(mvm->ptp_data.ptp_clock);
|
||||
mvm->ptp_data.ptp_clock = NULL;
|
||||
memset(&mvm->ptp_data.ptp_clock_info, 0,
|
||||
sizeof(mvm->ptp_data.ptp_clock_info));
|
||||
mvm->ptp_data.last_gp2 = 0;
|
||||
cancel_delayed_work_sync(&mvm->ptp_data.dwork);
|
||||
}
|
||||
}
|
@ -33,11 +33,11 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
|
||||
if (vif == data->disabled_vif)
|
||||
return;
|
||||
|
||||
if (!mvmvif->phy_ctxt)
|
||||
if (!mvmvif->deflink.phy_ctxt)
|
||||
return;
|
||||
|
||||
/* currently, PHY ID == binding ID */
|
||||
id = mvmvif->phy_ctxt->id;
|
||||
id = mvmvif->deflink.phy_ctxt->id;
|
||||
|
||||
/* need at least one binding per PHY */
|
||||
BUILD_BUG_ON(NUM_PHY_CTX > MAX_BINDINGS);
|
||||
@ -67,9 +67,10 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
|
||||
}
|
||||
|
||||
if (data->colors[id] < 0)
|
||||
data->colors[id] = mvmvif->phy_ctxt->color;
|
||||
data->colors[id] = mvmvif->deflink.phy_ctxt->color;
|
||||
else
|
||||
WARN_ON_ONCE(data->colors[id] != mvmvif->phy_ctxt->color);
|
||||
WARN_ON_ONCE(data->colors[id] !=
|
||||
mvmvif->deflink.phy_ctxt->color);
|
||||
|
||||
data->n_interfaces[id]++;
|
||||
|
||||
@ -99,7 +100,7 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
|
||||
if (!mvmvif->ap_ibss_active)
|
||||
return;
|
||||
|
||||
phy_id = mvmvif->phy_ctxt->id;
|
||||
phy_id = mvmvif->deflink.phy_ctxt->id;
|
||||
beacon_int = mvm->noa_vif->bss_conf.beacon_int;
|
||||
|
||||
for (i = 0; i < MAX_BINDINGS; i++) {
|
||||
|
@ -9,9 +9,9 @@
|
||||
#include "iwl-op-mode.h"
|
||||
#include "mvm.h"
|
||||
|
||||
static u8 rs_fw_bw_from_sta_bw(const struct ieee80211_sta *sta)
|
||||
static u8 rs_fw_bw_from_sta_bw(const struct ieee80211_link_sta *link_sta)
|
||||
{
|
||||
switch (sta->deflink.bandwidth) {
|
||||
switch (link_sta->bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_320:
|
||||
return IWL_TLC_MNG_CH_WIDTH_320MHZ;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
@ -38,11 +38,11 @@ static u8 rs_fw_set_active_chains(u8 chains)
|
||||
return fw_chains;
|
||||
}
|
||||
|
||||
static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta)
|
||||
static u8 rs_fw_sgi_cw_support(struct ieee80211_link_sta *link_sta)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
|
||||
struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
|
||||
u8 supp = 0;
|
||||
|
||||
if (he_cap->has_he)
|
||||
@ -61,12 +61,12 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta)
|
||||
}
|
||||
|
||||
static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_supported_band *sband)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
|
||||
struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
|
||||
bool vht_ena = vht_cap->vht_supported;
|
||||
u16 flags = 0;
|
||||
|
||||
@ -132,20 +132,20 @@ int rs_fw_vht_highest_rx_mcs_index(const struct ieee80211_sta_vht_cap *vht_cap,
|
||||
}
|
||||
|
||||
static void
|
||||
rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
rs_fw_vht_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
|
||||
const struct ieee80211_sta_vht_cap *vht_cap,
|
||||
struct iwl_tlc_config_cmd_v4 *cmd)
|
||||
{
|
||||
u16 supp;
|
||||
int i, highest_mcs;
|
||||
u8 max_nss = sta->deflink.rx_nss;
|
||||
u8 max_nss = link_sta->rx_nss;
|
||||
struct ieee80211_vht_cap ieee_vht_cap = {
|
||||
.vht_cap_info = cpu_to_le32(vht_cap->cap),
|
||||
.supp_mcs = vht_cap->vht_mcs,
|
||||
};
|
||||
|
||||
/* the station support only a single receive chain */
|
||||
if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC)
|
||||
if (link_sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
max_nss = 1;
|
||||
|
||||
for (i = 0; i < max_nss && i < IWL_TLC_NSS_MAX; i++) {
|
||||
@ -156,7 +156,7 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
continue;
|
||||
|
||||
supp = BIT(highest_mcs + 1) - 1;
|
||||
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
|
||||
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
|
||||
supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9);
|
||||
|
||||
cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le16(supp);
|
||||
@ -165,7 +165,7 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
* configuration is supported - only for MCS 0 since we already
|
||||
* decoded the MCS bits anyway ourselves.
|
||||
*/
|
||||
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160 &&
|
||||
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160 &&
|
||||
ieee80211_get_vht_max_nss(&ieee_vht_cap,
|
||||
IEEE80211_VHT_CHANWIDTH_160MHZ,
|
||||
0, true, nss) >= nss)
|
||||
@ -192,11 +192,11 @@ static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs)
|
||||
}
|
||||
|
||||
static void
|
||||
rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
rs_fw_he_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct iwl_tlc_config_cmd_v4 *cmd)
|
||||
{
|
||||
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
|
||||
const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
|
||||
u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
|
||||
u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
|
||||
u16 tx_mcs_80 =
|
||||
@ -204,10 +204,10 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
u16 tx_mcs_160 =
|
||||
le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
|
||||
int i;
|
||||
u8 nss = sta->deflink.rx_nss;
|
||||
u8 nss = link_sta->rx_nss;
|
||||
|
||||
/* the station support only a single receive chain */
|
||||
if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC)
|
||||
if (link_sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
nss = 1;
|
||||
|
||||
for (i = 0; i < nss && i < IWL_TLC_NSS_MAX; i++) {
|
||||
@ -282,13 +282,14 @@ rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw,
|
||||
}
|
||||
}
|
||||
|
||||
static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct iwl_tlc_config_cmd_v4 *cmd)
|
||||
static void
|
||||
rs_fw_eht_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct iwl_tlc_config_cmd_v4 *cmd)
|
||||
{
|
||||
/* peer RX mcs capa */
|
||||
const struct ieee80211_eht_mcs_nss_supp *eht_rx_mcs =
|
||||
&sta->deflink.eht_cap.eht_mcs_nss_supp;
|
||||
&link_sta->eht_cap.eht_mcs_nss_supp;
|
||||
/* our TX mcs capa */
|
||||
const struct ieee80211_eht_mcs_nss_supp *eht_tx_mcs =
|
||||
&sband->iftype_data->eht_cap.eht_mcs_nss_supp;
|
||||
@ -298,7 +299,7 @@ static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_tx_20;
|
||||
|
||||
/* peer is 20Mhz only */
|
||||
if (!(sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
|
||||
mcs_rx_20 = eht_rx_mcs->only_20mhz;
|
||||
} else {
|
||||
@ -354,25 +355,25 @@ static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
}
|
||||
|
||||
/* the station support only a single receive chain */
|
||||
if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC ||
|
||||
sta->deflink.rx_nss < 2)
|
||||
if (link_sta->smps_mode == IEEE80211_SMPS_STATIC ||
|
||||
link_sta->rx_nss < 2)
|
||||
memset(cmd->ht_rates[IWL_TLC_NSS_2], 0,
|
||||
sizeof(cmd->ht_rates[IWL_TLC_NSS_2]));
|
||||
}
|
||||
|
||||
static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
|
||||
static void rs_fw_set_supp_rates(struct ieee80211_link_sta *link_sta,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct iwl_tlc_config_cmd_v4 *cmd)
|
||||
{
|
||||
int i;
|
||||
u16 supp = 0;
|
||||
unsigned long tmp; /* must be unsigned long for for_each_set_bit */
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
|
||||
const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
|
||||
|
||||
/* non HT rates */
|
||||
tmp = sta->deflink.supp_rates[sband->band];
|
||||
tmp = link_sta->supp_rates[sband->band];
|
||||
for_each_set_bit(i, &tmp, BITS_PER_LONG)
|
||||
supp |= BIT(sband->bitrates[i].hw_value);
|
||||
|
||||
@ -380,22 +381,22 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
|
||||
cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
|
||||
|
||||
/* HT/VHT rates */
|
||||
if (sta->deflink.eht_cap.has_eht) {
|
||||
if (link_sta->eht_cap.has_eht) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_EHT;
|
||||
rs_fw_eht_set_enabled_rates(sta, sband, cmd);
|
||||
rs_fw_eht_set_enabled_rates(link_sta, sband, cmd);
|
||||
} else if (he_cap->has_he) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_HE;
|
||||
rs_fw_he_set_enabled_rates(sta, sband, cmd);
|
||||
rs_fw_he_set_enabled_rates(link_sta, sband, cmd);
|
||||
} else if (vht_cap->vht_supported) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_VHT;
|
||||
rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
|
||||
rs_fw_vht_set_enabled_rates(link_sta, vht_cap, cmd);
|
||||
} else if (ht_cap->ht_supported) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_HT;
|
||||
cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] =
|
||||
cpu_to_le16(ht_cap->mcs.rx_mask[0]);
|
||||
|
||||
/* the station support only a single receive chain */
|
||||
if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC)
|
||||
if (link_sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] =
|
||||
0;
|
||||
else
|
||||
@ -410,15 +411,18 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_tlc_update_notif *notif;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct iwl_mvm_link_sta *mvm_link_sta;
|
||||
struct iwl_lq_sta_rs_fw *lq_sta;
|
||||
u32 flags;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
notif = (void *)pkt->data;
|
||||
link_sta = rcu_dereference(mvm->fw_id_to_link_sta[notif->sta_id]);
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[notif->sta_id]);
|
||||
if (IS_ERR_OR_NULL(sta)) {
|
||||
if (IS_ERR_OR_NULL(sta) || !link_sta) {
|
||||
/* can happen in remove station flow where mvm removed internally
|
||||
* the station before removing from FW
|
||||
*/
|
||||
@ -438,7 +442,14 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
||||
|
||||
flags = le32_to_cpu(notif->flags);
|
||||
|
||||
lq_sta = &mvmsta->lq_sta.rs_fw;
|
||||
mvm_link_sta = rcu_dereference(mvmsta->link[link_sta->link_id]);
|
||||
if (!mvm_link_sta) {
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"Invalid mvmsta RCU pointer for link (%d) of sta id (%d) in TLC notification\n",
|
||||
link_sta->link_id, notif->sta_id);
|
||||
goto out;
|
||||
}
|
||||
lq_sta = &mvm_link_sta->lq_sta.rs_fw;
|
||||
|
||||
if (flags & IWL_TLC_NOTIF_FLAG_RATE) {
|
||||
char pretty_rate[100];
|
||||
@ -465,9 +476,9 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
||||
u16 size = le32_to_cpu(notif->amsdu_size);
|
||||
int i;
|
||||
|
||||
if (sta->deflink.agg.max_amsdu_len < size) {
|
||||
if (link_sta->agg.max_amsdu_len < size) {
|
||||
/*
|
||||
* In debug sta->deflink.agg.max_amsdu_len < size
|
||||
* In debug link_sta->agg.max_amsdu_len < size
|
||||
* so also check with orig_amsdu_len which holds the
|
||||
* original data before debugfs changed the value
|
||||
*/
|
||||
@ -477,18 +488,18 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
||||
|
||||
mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
|
||||
mvmsta->max_amsdu_len = size;
|
||||
sta->deflink.agg.max_rc_amsdu_len = mvmsta->max_amsdu_len;
|
||||
link_sta->agg.max_rc_amsdu_len = mvmsta->max_amsdu_len;
|
||||
|
||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||
if (mvmsta->amsdu_enabled & BIT(i))
|
||||
sta->deflink.agg.max_tid_amsdu_len[i] =
|
||||
link_sta->agg.max_tid_amsdu_len[i] =
|
||||
iwl_mvm_max_amsdu_size(mvm, sta, i);
|
||||
else
|
||||
/*
|
||||
* Not so elegant, but this will effectively
|
||||
* prevent AMSDU on this TID
|
||||
*/
|
||||
sta->deflink.agg.max_tid_amsdu_len[i] = 1;
|
||||
link_sta->agg.max_tid_amsdu_len[i] = 1;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
@ -500,14 +511,18 @@ out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta)
|
||||
u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
|
||||
|
||||
if (mvmsta->vif->bss_conf.chandef.chan->band == NL80211_BAND_6GHZ) {
|
||||
switch (le16_get_bits(sta->deflink.he_6ghz_capa.capa,
|
||||
if (WARN_ON_ONCE(!link_conf->chandef.chan))
|
||||
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
|
||||
|
||||
if (link_conf->chandef.chan->band == NL80211_BAND_6GHZ) {
|
||||
switch (le16_get_bits(link_sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) {
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
|
||||
return IEEE80211_MAX_MPDU_LEN_VHT_11454;
|
||||
@ -543,33 +558,50 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta)
|
||||
}
|
||||
|
||||
void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
enum nl80211_band band, bool update)
|
||||
{
|
||||
struct ieee80211_hw *hw = mvm->hw;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
|
||||
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD);
|
||||
struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
|
||||
u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta);
|
||||
u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta, link_conf, link_sta);
|
||||
struct iwl_mvm_link_sta *mvm_link_sta;
|
||||
struct iwl_lq_sta_rs_fw *lq_sta;
|
||||
struct iwl_tlc_config_cmd_v4 cfg_cmd = {
|
||||
.sta_id = mvmsta->sta_id,
|
||||
.max_ch_width = update ?
|
||||
rs_fw_bw_from_sta_bw(sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ,
|
||||
.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)),
|
||||
rs_fw_bw_from_sta_bw(link_sta) :
|
||||
IWL_TLC_MNG_CH_WIDTH_20MHZ,
|
||||
.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, link_sta,
|
||||
sband)),
|
||||
.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
|
||||
.sgi_ch_width_supp = rs_fw_sgi_cw_support(sta),
|
||||
.sgi_ch_width_supp = rs_fw_sgi_cw_support(link_sta),
|
||||
.max_mpdu_len = iwl_mvm_is_csum_supported(mvm) ?
|
||||
cpu_to_le16(max_amsdu_len) : 0,
|
||||
};
|
||||
int ret;
|
||||
unsigned int link_id = link_conf->link_id;
|
||||
int cmd_ver;
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
mvm_link_sta = rcu_dereference(mvmsta->link[link_id]);
|
||||
if (WARN_ON_ONCE(!mvm_link_sta)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
cfg_cmd.sta_id = mvm_link_sta->sta_id;
|
||||
|
||||
lq_sta = &mvm_link_sta->lq_sta.rs_fw;
|
||||
memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
iwl_mvm_reset_frame_stats(mvm);
|
||||
#endif
|
||||
rs_fw_set_supp_rates(sta, sband, &cfg_cmd);
|
||||
rs_fw_set_supp_rates(link_sta, sband, &cfg_cmd);
|
||||
|
||||
/*
|
||||
* since TLC offload works with one mode we can assume
|
||||
@ -641,18 +673,30 @@ int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
|
||||
void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
|
||||
{
|
||||
struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
|
||||
unsigned int link_id;
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "create station rate scale window\n");
|
||||
|
||||
lq_sta->pers.drv = mvm;
|
||||
lq_sta->pers.sta_id = mvmsta->sta_id;
|
||||
lq_sta->pers.chains = 0;
|
||||
memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal));
|
||||
lq_sta->pers.last_rssi = S8_MIN;
|
||||
lq_sta->last_rate_n_flags = 0;
|
||||
for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
|
||||
struct iwl_lq_sta_rs_fw *lq_sta;
|
||||
struct iwl_mvm_link_sta *link =
|
||||
rcu_dereference_protected(mvmsta->link[link_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
lq_sta = &link->lq_sta.rs_fw;
|
||||
|
||||
lq_sta->pers.drv = mvm;
|
||||
lq_sta->pers.sta_id = link->sta_id;
|
||||
lq_sta->pers.chains = 0;
|
||||
memset(lq_sta->pers.chain_signal, 0,
|
||||
sizeof(lq_sta->pers.chain_signal));
|
||||
lq_sta->pers.last_rssi = S8_MIN;
|
||||
lq_sta->last_rate_n_flags = 0;
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
lq_sta->pers.dbg_fixed_rate = 0;
|
||||
lq_sta->pers.dbg_fixed_rate = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -512,10 +512,10 @@ static char *rs_pretty_rate(const struct rs_rate *rate)
|
||||
(rate->index <= IWL_RATE_MCS_9_INDEX))
|
||||
rate_str = ht_vht_rates[rate->index];
|
||||
else
|
||||
rate_str = "BAD_RATE";
|
||||
rate_str = NULL;
|
||||
|
||||
sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type),
|
||||
iwl_rs_pretty_ant(rate->ant), rate_str);
|
||||
iwl_rs_pretty_ant(rate->ant), rate_str ?: "BAD_RATE");
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -754,7 +754,7 @@ static int rs_collect_tlc_data(struct iwl_mvm *mvm,
|
||||
return -EINVAL;
|
||||
|
||||
if (tbl->column != RS_COLUMN_INVALID) {
|
||||
struct lq_sta_pers *pers = &mvmsta->lq_sta.rs_drv.pers;
|
||||
struct lq_sta_pers *pers = &mvmsta->deflink.lq_sta.rs_drv.pers;
|
||||
|
||||
pers->tx_stats[tbl->column][scale_index].total += attempts;
|
||||
pers->tx_stats[tbl->column][scale_index].success += successes;
|
||||
@ -1487,9 +1487,11 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
enum rs_action scale_action)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct ieee80211_bss_conf *bss_conf = &mvmsta->vif->bss_conf;
|
||||
int i;
|
||||
|
||||
sta->deflink.agg.max_amsdu_len = rs_fw_get_max_amsdu_len(sta);
|
||||
sta->deflink.agg.max_amsdu_len =
|
||||
rs_fw_get_max_amsdu_len(sta, bss_conf, &sta->deflink);
|
||||
|
||||
/*
|
||||
* In case TLC offload is not active amsdu_enabled is either 0xFFFF
|
||||
@ -1502,7 +1504,7 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
else
|
||||
mvmsta->amsdu_enabled = 0xFFFF;
|
||||
|
||||
if (mvmsta->vif->bss_conf.he_support &&
|
||||
if (bss_conf->he_support &&
|
||||
!iwlwifi_mod_params.disable_11ax)
|
||||
mvmsta->max_amsdu_len = sta->deflink.agg.max_amsdu_len;
|
||||
else
|
||||
@ -2599,7 +2601,7 @@ void rs_update_last_rssi(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvmsta,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;
|
||||
int i;
|
||||
|
||||
lq_sta->pers.chains = rx_status->chains;
|
||||
@ -2682,7 +2684,6 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
|
||||
/* if vif isn't initialized mvm doesn't know about
|
||||
* this station, so don't do anything with the it
|
||||
*/
|
||||
sta = NULL;
|
||||
mvm_sta = NULL;
|
||||
}
|
||||
|
||||
@ -2712,7 +2713,7 @@ static void *rs_drv_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_rate;
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "create station rate scale window\n");
|
||||
|
||||
@ -2918,18 +2919,18 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;
|
||||
struct ieee80211_supported_band *sband;
|
||||
unsigned long supp; /* must be unsigned long for for_each_set_bit */
|
||||
|
||||
lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock);
|
||||
lockdep_assert_held(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);
|
||||
|
||||
/* clear all non-persistent lq data */
|
||||
memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
|
||||
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
lq_sta->lq.sta_id = mvmsta->sta_id;
|
||||
lq_sta->lq.sta_id = mvmsta->deflink.sta_id;
|
||||
mvmsta->amsdu_enabled = 0;
|
||||
mvmsta->max_amsdu_len = sta->cur->max_amsdu_len;
|
||||
|
||||
@ -2941,7 +2942,7 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"LQ: *** rate scale station global init for station %d ***\n",
|
||||
mvmsta->sta_id);
|
||||
mvmsta->deflink.sta_id);
|
||||
/* TODO: what is a good starting rate for STA? About middle? Maybe not
|
||||
* the lowest or the highest rate.. Could consider using RSSI from
|
||||
* previous packets? Need to have IEEE 802.1X auth succeed immediately
|
||||
@ -3003,17 +3004,20 @@ static void rs_drv_rate_update(void *mvm_r,
|
||||
void *priv_sta, u32 changed)
|
||||
{
|
||||
struct iwl_op_mode *op_mode = mvm_r;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
u8 tid;
|
||||
|
||||
if (!iwl_mvm_sta_from_mac80211(sta)->vif)
|
||||
if (!mvmsta->vif)
|
||||
return;
|
||||
|
||||
/* Stop any ongoing aggregations as rs starts off assuming no agg */
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
|
||||
ieee80211_stop_tx_ba_session(sta, tid);
|
||||
|
||||
iwl_mvm_rs_rate_init(mvm, sta, sband->band, true);
|
||||
iwl_mvm_rs_rate_init(mvm, sta,
|
||||
&mvmsta->vif->bss_conf, &sta->deflink,
|
||||
sband->band, true);
|
||||
}
|
||||
|
||||
static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
|
||||
@ -3033,7 +3037,7 @@ static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
|
||||
u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
|
||||
u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->deflink.lq_sta.rs_drv;
|
||||
|
||||
if (!lq_sta->pers.drv) {
|
||||
IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
|
||||
@ -3257,11 +3261,11 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
/* If it's locked we are in middle of init flow
|
||||
* just wait for next tx status to update the lq_sta data
|
||||
*/
|
||||
if (!spin_trylock(&mvmsta->lq_sta.rs_drv.pers.lock))
|
||||
if (!spin_trylock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock))
|
||||
return;
|
||||
|
||||
__iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp);
|
||||
spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
|
||||
spin_unlock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
@ -3437,7 +3441,7 @@ static void rs_bfer_active_iter(void *_data,
|
||||
{
|
||||
struct rs_bfer_active_iter_data *data = _data;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_lq_cmd *lq_cmd = &mvmsta->lq_sta.rs_drv.lq;
|
||||
struct iwl_lq_cmd *lq_cmd = &mvmsta->deflink.lq_sta.rs_drv.lq;
|
||||
u32 ss_params = le32_to_cpu(lq_cmd->ss_params);
|
||||
|
||||
if (sta == data->exclude_sta)
|
||||
@ -3468,7 +3472,8 @@ static int rs_bfer_priority(struct iwl_mvm_sta *sta)
|
||||
prio = 1;
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(true, "viftype %d sta_id %d", viftype, sta->sta_id);
|
||||
WARN_ONCE(true, "viftype %d sta_id %d", viftype,
|
||||
sta->deflink.sta_id);
|
||||
prio = -1;
|
||||
}
|
||||
|
||||
@ -3545,12 +3550,12 @@ static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "Found existing sta %d with BFER activated\n",
|
||||
bfer_mvmsta->sta_id);
|
||||
bfer_mvmsta->deflink.sta_id);
|
||||
|
||||
/* Disallow BFER on another STA if active and we're a higher priority */
|
||||
if (rs_bfer_priority_cmp(mvmsta, bfer_mvmsta) > 0) {
|
||||
struct iwl_lq_cmd *bfersta_lq_cmd =
|
||||
&bfer_mvmsta->lq_sta.rs_drv.lq;
|
||||
&bfer_mvmsta->deflink.lq_sta.rs_drv.lq;
|
||||
u32 bfersta_ss_params = le32_to_cpu(bfersta_lq_cmd->ss_params);
|
||||
|
||||
bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED;
|
||||
@ -3560,7 +3565,7 @@ static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
|
||||
ss_params |= LQ_SS_BFER_ALLOWED;
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"Lower priority BFER sta found (%d). Switch BFER\n",
|
||||
bfer_mvmsta->sta_id);
|
||||
bfer_mvmsta->deflink.sta_id);
|
||||
}
|
||||
out:
|
||||
lq_cmd->ss_params = cpu_to_le32(ss_params);
|
||||
@ -3602,7 +3607,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
|
||||
num_of_ant(initial_rate->ant) == 1)
|
||||
lq_cmd->single_stream_ant_msk = initial_rate->ant;
|
||||
|
||||
lq_cmd->agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
|
||||
lq_cmd->agg_frame_cnt_limit = lq_sta->pers.max_agg_bufsize;
|
||||
|
||||
/*
|
||||
* In case of low latency, tell the firmware to leave a frame in the
|
||||
@ -3745,7 +3750,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
|
||||
|
||||
struct iwl_lq_sta *lq_sta = file->private_data;
|
||||
struct iwl_mvm_sta *mvmsta =
|
||||
container_of(lq_sta, struct iwl_mvm_sta, lq_sta.rs_drv);
|
||||
container_of(lq_sta, struct iwl_mvm_sta, deflink.lq_sta.rs_drv);
|
||||
struct iwl_mvm *mvm;
|
||||
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
struct rs_rate *rate = &tbl->rate;
|
||||
@ -4046,7 +4051,8 @@ static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta,
|
||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
|
||||
mvmsta = container_of(lq_sta, struct iwl_mvm_sta, lq_sta.rs_drv);
|
||||
mvmsta = container_of(lq_sta, struct iwl_mvm_sta,
|
||||
deflink.lq_sta.rs_drv);
|
||||
|
||||
if (!mvmsta->vif)
|
||||
return;
|
||||
@ -4096,16 +4102,18 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
|
||||
};
|
||||
|
||||
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
enum nl80211_band band, bool update)
|
||||
{
|
||||
if (iwl_mvm_has_tlc_offload(mvm)) {
|
||||
rs_fw_rate_init(mvm, sta, band, update);
|
||||
rs_fw_rate_init(mvm, sta, link_conf, link_sta, band, update);
|
||||
} else {
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
spin_lock(&mvmsta->lq_sta.rs_drv.pers.lock);
|
||||
spin_lock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);
|
||||
rs_drv_rate_init(mvm, sta, band);
|
||||
spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
|
||||
spin_unlock(&mvmsta->deflink.lq_sta.rs_drv.pers.lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4122,7 +4130,7 @@ void iwl_mvm_rate_control_unregister(void)
|
||||
static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
bool enable)
|
||||
{
|
||||
struct iwl_lq_cmd *lq = &mvmsta->lq_sta.rs_drv.lq;
|
||||
struct iwl_lq_cmd *lq = &mvmsta->deflink.lq_sta.rs_drv.lq;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* Copyright (C) 2003 - 2014, 2018 - 2022 Intel Corporation
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __rs_h__
|
||||
@ -204,6 +203,7 @@ struct rs_rate {
|
||||
/**
|
||||
* struct iwl_lq_sta_rs_fw - rate and related statistics for RS in FW
|
||||
* @last_rate_n_flags: last rate reported by FW
|
||||
* @max_agg_bufsize: the maximal size of the AGG buffer for this station
|
||||
* @sta_id: the id of the station
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
* @dbg_fixed_rate: for debug, use fixed rate if not 0
|
||||
@ -353,6 +353,7 @@ struct iwl_lq_sta {
|
||||
|
||||
/* last tx rate_n_flags */
|
||||
u32 last_rate_n_flags;
|
||||
|
||||
/* packets destined for this STA are aggregated */
|
||||
u8 is_agg;
|
||||
|
||||
@ -371,6 +372,7 @@ struct iwl_lq_sta {
|
||||
u8 chains;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
s8 last_rssi;
|
||||
u16 max_agg_bufsize;
|
||||
struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];
|
||||
struct iwl_mvm *drv;
|
||||
spinlock_t lock; /* for races in reinit/update table */
|
||||
@ -393,7 +395,9 @@ struct iwl_lq_sta {
|
||||
|
||||
/* Initialize station's rate scaling information after adding station */
|
||||
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
enum nl80211_band band, bool init);
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
enum nl80211_band band, bool update);
|
||||
|
||||
/* Notify RS about Tx status */
|
||||
void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
@ -430,11 +434,15 @@ void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm);
|
||||
|
||||
void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta);
|
||||
void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
enum nl80211_band band, bool update);
|
||||
int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
bool enable);
|
||||
void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
|
||||
u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta);
|
||||
u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta);
|
||||
#endif /* __rs__ */
|
||||
|
@ -237,11 +237,11 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
|
||||
|
||||
if (mdata->opened_rx_ba_sessions ||
|
||||
mdata->uapsd_nonagg_detect.detected ||
|
||||
(!mvmvif->queue_params[IEEE80211_AC_VO].uapsd &&
|
||||
!mvmvif->queue_params[IEEE80211_AC_VI].uapsd &&
|
||||
!mvmvif->queue_params[IEEE80211_AC_BE].uapsd &&
|
||||
!mvmvif->queue_params[IEEE80211_AC_BK].uapsd) ||
|
||||
mvmsta->sta_id != mvmvif->ap_sta_id)
|
||||
(!mvmvif->deflink.queue_params[IEEE80211_AC_VO].uapsd &&
|
||||
!mvmvif->deflink.queue_params[IEEE80211_AC_VI].uapsd &&
|
||||
!mvmvif->deflink.queue_params[IEEE80211_AC_BE].uapsd &&
|
||||
!mvmvif->deflink.queue_params[IEEE80211_AC_BK].uapsd) ||
|
||||
mvmsta->deflink.sta_id != mvmvif->deflink.ap_sta_id)
|
||||
return;
|
||||
|
||||
if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
|
||||
@ -628,9 +628,9 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
* data copied into the "data" struct, but rather the data from
|
||||
* the notification directly.
|
||||
*/
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
mvmvif->deflink.beacon_stats.num_beacons =
|
||||
le32_to_cpu(data->beacon_counter[vif_id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
mvmvif->deflink.beacon_stats.avg_signal =
|
||||
-data->beacon_average_energy[vif_id];
|
||||
|
||||
if (mvmvif->id != id)
|
||||
@ -643,8 +643,8 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
mvmvif->deflink.beacon_stats.accu_num_beacons +=
|
||||
mvmvif->deflink.beacon_stats.num_beacons;
|
||||
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
}
|
||||
@ -666,17 +666,17 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
||||
|
||||
mac_stats = &data->per_mac_stats[vif_id];
|
||||
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
mvmvif->deflink.beacon_stats.num_beacons =
|
||||
le32_to_cpu(mac_stats->beacon_counter);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
mvmvif->deflink.beacon_stats.avg_signal =
|
||||
-le32_to_cpu(mac_stats->beacon_average_energy);
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
mvmvif->deflink.beacon_stats.accu_num_beacons +=
|
||||
mvmvif->deflink.beacon_stats.num_beacons;
|
||||
|
||||
sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
@ -712,14 +712,14 @@ static void iwl_mvm_stats_energy_iter(void *_data,
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
u8 *energy = _data;
|
||||
u32 sta_id = mvmsta->sta_id;
|
||||
u32 sta_id = mvmsta->deflink.sta_id;
|
||||
|
||||
if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT_MAX, "sta_id %d >= %d",
|
||||
sta_id, IWL_MVM_STATION_COUNT_MAX))
|
||||
return;
|
||||
|
||||
if (energy[sta_id])
|
||||
mvmsta->avg_energy = energy[sta_id];
|
||||
mvmsta->deflink.avg_energy = energy[sta_id];
|
||||
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "iwl-trans.h"
|
||||
#include "mvm.h"
|
||||
#include "fw-api.h"
|
||||
#include "time-sync.h"
|
||||
|
||||
static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
int queue, struct ieee80211_sta *sta)
|
||||
@ -252,12 +253,22 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
|
||||
static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
||||
struct napi_struct *napi,
|
||||
struct sk_buff *skb, int queue,
|
||||
struct ieee80211_sta *sta)
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_link_sta *link_sta)
|
||||
{
|
||||
if (iwl_mvm_check_pn(mvm, skb, queue, sta))
|
||||
if (unlikely(iwl_mvm_check_pn(mvm, skb, queue, sta))) {
|
||||
kfree_skb(skb);
|
||||
else
|
||||
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta && sta->valid_links && link_sta) {
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
rx_status->link_valid = 1;
|
||||
rx_status->link_id = link_sta->link_id;
|
||||
}
|
||||
|
||||
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
|
||||
}
|
||||
|
||||
static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
|
||||
@ -630,7 +641,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
||||
while ((skb = __skb_dequeue(skb_list))) {
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
|
||||
reorder_buf->queue,
|
||||
sta);
|
||||
sta, NULL /* FIXME */);
|
||||
reorder_buf->num_stored--;
|
||||
}
|
||||
}
|
||||
@ -978,9 +989,10 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (WARN(tid != baid_data->tid || mvm_sta->sta_id != baid_data->sta_id,
|
||||
if (WARN(tid != baid_data->tid ||
|
||||
mvm_sta->deflink.sta_id != baid_data->sta_id,
|
||||
"baid 0x%x is mapped to sta:%d tid:%d, but was received for sta:%d tid:%d\n",
|
||||
baid, baid_data->sta_id, baid_data->tid, mvm_sta->sta_id,
|
||||
baid, baid_data->sta_id, baid_data->tid, mvm_sta->deflink.sta_id,
|
||||
tid))
|
||||
return false;
|
||||
|
||||
@ -2296,6 +2308,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
u32 len;
|
||||
u32 pkt_len = iwl_rx_packet_payload_len(pkt);
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct ieee80211_link_sta *link_sta = NULL;
|
||||
struct sk_buff *skb;
|
||||
u8 crypt_len = 0;
|
||||
size_t desc_size;
|
||||
@ -2452,6 +2465,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
|
||||
if (IS_ERR(sta))
|
||||
sta = NULL;
|
||||
link_sta = rcu_dereference(mvm->fw_id_to_link_sta[id]);
|
||||
}
|
||||
} else if (!is_multicast_ether_addr(hdr->addr2)) {
|
||||
/*
|
||||
@ -2585,9 +2599,11 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc))
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue,
|
||||
sta);
|
||||
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) &&
|
||||
likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)))
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta,
|
||||
link_sta);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -193,8 +193,9 @@ static void iwl_mvm_scan_iterator(void *_data, u8 *mac,
|
||||
struct iwl_mvm_scan_iter_data *data = _data;
|
||||
struct iwl_mvm_vif *curr_mvmvif;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
|
||||
mvmvif->phy_ctxt->id < NUM_PHY_CTX)
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE &&
|
||||
mvmvif->deflink.phy_ctxt &&
|
||||
mvmvif->deflink.phy_ctxt->id < NUM_PHY_CTX)
|
||||
data->global_cnt += 1;
|
||||
|
||||
if (!data->current_vif || vif == data->current_vif)
|
||||
@ -203,8 +204,8 @@ static void iwl_mvm_scan_iterator(void *_data, u8 *mac,
|
||||
curr_mvmvif = iwl_mvm_vif_from_mac80211(data->current_vif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
|
||||
mvmvif->phy_ctxt && curr_mvmvif->phy_ctxt &&
|
||||
mvmvif->phy_ctxt->id != curr_mvmvif->phy_ctxt->id)
|
||||
mvmvif->deflink.phy_ctxt && curr_mvmvif->deflink.phy_ctxt &&
|
||||
mvmvif->deflink.phy_ctxt->id != curr_mvmvif->deflink.phy_ctxt->id)
|
||||
data->is_dcm_with_p2p_go = true;
|
||||
}
|
||||
|
||||
@ -2676,11 +2677,23 @@ static void iwl_mvm_scan_respect_p2p_go_iter(void *_data, u8 *mac,
|
||||
if (vif == data->current_vif)
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
|
||||
mvmvif->phy_ctxt->id < NUM_PHY_CTX &&
|
||||
(data->band == NUM_NL80211_BANDS ||
|
||||
mvmvif->phy_ctxt->channel->band == data->band))
|
||||
data->p2p_go = true;
|
||||
if (vif->type == NL80211_IFTYPE_AP && vif->p2p) {
|
||||
u32 link_id;
|
||||
|
||||
for (link_id = 0;
|
||||
link_id < ARRAY_SIZE(mvmvif->link);
|
||||
link_id++) {
|
||||
struct iwl_mvm_vif_link_info *link =
|
||||
mvmvif->link[link_id];
|
||||
|
||||
if (link && link->phy_ctxt->id < NUM_PHY_CTX &&
|
||||
(data->band == NUM_NL80211_BANDS ||
|
||||
link->phy_ctxt->channel->band == data->band)) {
|
||||
data->p2p_go = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool _iwl_mvm_get_respect_p2p_go(struct iwl_mvm *mvm,
|
||||
@ -2980,7 +2993,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
|
||||
.scan_start_tsf = mvm->scan_start,
|
||||
};
|
||||
|
||||
memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
|
||||
memcpy(info.tsf_bssid, mvm->scan_vif->deflink.bssid, ETH_ALEN);
|
||||
ieee80211_scan_completed(mvm->hw, &info);
|
||||
mvm->scan_vif = NULL;
|
||||
cancel_delayed_work(&mvm->scan_timeout_dwork);
|
||||
|
@ -23,14 +23,14 @@ static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac,
|
||||
struct iwl_mvm_active_iface_iterator_data *data = _data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (vif == data->ignore_vif || !mvmvif->phy_ctxt ||
|
||||
if (vif == data->ignore_vif || !mvmvif->deflink.phy_ctxt ||
|
||||
vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
return;
|
||||
|
||||
data->num_active_macs++;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
data->sta_vif_ap_sta_id = mvmvif->ap_sta_id;
|
||||
data->sta_vif_ap_sta_id = mvmvif->deflink.ap_sta_id;
|
||||
if (vif->cfg.assoc)
|
||||
data->sta_vif_state = SF_FULL_ON;
|
||||
else
|
||||
@ -98,6 +98,10 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int i, j, watermark;
|
||||
u8 max_rx_nss = 0;
|
||||
bool is_legacy = true;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
unsigned int link_id;
|
||||
|
||||
sf_cmd->watermark[SF_LONG_DELAY_ON] = cpu_to_le32(SF_W_MARK_SCAN);
|
||||
|
||||
@ -106,10 +110,25 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
|
||||
* capabilities of the AP station, and choose the watermark accordingly.
|
||||
*/
|
||||
if (sta) {
|
||||
if (sta->deflink.ht_cap.ht_supported ||
|
||||
sta->deflink.vht_cap.vht_supported ||
|
||||
sta->deflink.he_cap.has_he) {
|
||||
switch (sta->deflink.rx_nss) {
|
||||
/* find the maximal NSS number among all links (if relevant) */
|
||||
rcu_read_lock();
|
||||
for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
|
||||
link_sta = rcu_dereference(sta->link[link_id]);
|
||||
if (!link_sta)
|
||||
continue;
|
||||
|
||||
if (link_sta->ht_cap.ht_supported ||
|
||||
link_sta->vht_cap.vht_supported ||
|
||||
link_sta->eht_cap.has_eht ||
|
||||
link_sta->he_cap.has_he) {
|
||||
is_legacy = false;
|
||||
max_rx_nss = max(max_rx_nss, link_sta->rx_nss);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!is_legacy) {
|
||||
switch (max_rx_nss) {
|
||||
case 1:
|
||||
watermark = SF_W_MARK_SISO;
|
||||
break;
|
||||
@ -151,7 +170,6 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
|
||||
memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
|
||||
sizeof(sf_full_timeout_def));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
|
||||
@ -264,7 +282,7 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
|
||||
} else if (changed_vif->cfg.assoc &&
|
||||
changed_vif->bss_conf.dtim_period) {
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
|
||||
sta_id = mvmvif->ap_sta_id;
|
||||
sta_id = mvmvif->deflink.ap_sta_id;
|
||||
new_state = SF_FULL_ON;
|
||||
} else {
|
||||
new_state = SF_INIT_OFF;
|
||||
@ -275,5 +293,9 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
|
||||
/* If there are multiple active macs - change to SF_UNINIT */
|
||||
new_state = SF_UNINIT;
|
||||
}
|
||||
|
||||
/* For MLO it's ok to use deflink->sta_id as it's needed only to get
|
||||
* a pointer to mac80211 sta
|
||||
*/
|
||||
return iwl_mvm_sf_config(mvm, sta_id, new_state);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2016 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -330,14 +330,31 @@ struct iwl_mvm_rxq_dup_data {
|
||||
u8 last_sub_frame[IWL_MAX_TID_COUNT + 1];
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_link_sta - link specific parameters of a station
|
||||
* @rcu_head: used for freeing the data
|
||||
* @sta_id: the index of the station in the fw
|
||||
* @lq_sta: holds rate scaling data, either for the case when RS is done in
|
||||
* the driver - %rs_drv or in the FW - %rs_fw.
|
||||
* @avg_energy: energy as reported by FW statistics notification
|
||||
*/
|
||||
struct iwl_mvm_link_sta {
|
||||
struct rcu_head rcu_head;
|
||||
u32 sta_id;
|
||||
union {
|
||||
struct iwl_lq_sta_rs_fw rs_fw;
|
||||
struct iwl_lq_sta rs_drv;
|
||||
} lq_sta;
|
||||
|
||||
u8 avg_energy;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_sta - representation of a station in the driver
|
||||
* @sta_id: the index of the station in the fw (will be replaced by id_n_color)
|
||||
* @tfd_queue_msk: the tfd queues used by the station
|
||||
* @mac_id_n_color: the MAC context this station is linked to
|
||||
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
|
||||
* tid.
|
||||
* @max_agg_bufsize: the maximal size of the AGG buffer for this station
|
||||
* @sta_type: station type
|
||||
* @sta_state: station state according to enum %ieee80211_sta_state
|
||||
* @bt_reduced_txpower: is reduced tx power enabled for this station
|
||||
@ -347,8 +364,6 @@ struct iwl_mvm_rxq_dup_data {
|
||||
* and from Tx response flow, it needs a spinlock.
|
||||
* @tid_data: per tid data + mgmt. Look at %iwl_mvm_tid_data.
|
||||
* @tid_to_baid: a simple map of TID to baid
|
||||
* @lq_sta: holds rate scaling data, either for the case when RS is done in
|
||||
* the driver - %rs_drv or in the FW - %rs_fw.
|
||||
* @reserved_queue: the queue reserved for this STA for DQA purposes
|
||||
* Every STA has is given one reserved queue to allow it to operate. If no
|
||||
* such queue can be guaranteed, the STA addition will fail.
|
||||
@ -374,6 +389,12 @@ struct iwl_mvm_rxq_dup_data {
|
||||
* used during connection establishment (e.g. for the 4 way handshake
|
||||
* exchange).
|
||||
* @pairwise_cipher: used to feed iwlmei upon authorization
|
||||
* @deflink: the default link station, for non-MLO STA, all link specific data
|
||||
* is accessed via deflink (or link[0]). For MLO, it will hold data of the
|
||||
* first added link STA.
|
||||
* @link: per link sta entries. For non-MLO only link[0] holds data. For MLO,
|
||||
* link[0] points to deflink and link[link_id] is allocated when new link
|
||||
* sta is added.
|
||||
*
|
||||
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
|
||||
* in the structure for use by driver. This structure is placed in that
|
||||
@ -381,22 +402,16 @@ struct iwl_mvm_rxq_dup_data {
|
||||
*
|
||||
*/
|
||||
struct iwl_mvm_sta {
|
||||
u32 sta_id;
|
||||
u32 tfd_queue_msk;
|
||||
u32 mac_id_n_color;
|
||||
u16 tid_disable_agg;
|
||||
u16 max_agg_bufsize;
|
||||
enum iwl_sta_type sta_type;
|
||||
u8 sta_type;
|
||||
enum ieee80211_sta_state sta_state;
|
||||
bool bt_reduced_txpower;
|
||||
bool next_status_eosp;
|
||||
spinlock_t lock;
|
||||
struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT + 1];
|
||||
u8 tid_to_baid[IWL_MAX_TID_COUNT];
|
||||
union {
|
||||
struct iwl_lq_sta_rs_fw rs_fw;
|
||||
struct iwl_lq_sta rs_drv;
|
||||
} lq_sta;
|
||||
struct ieee80211_vif *vif;
|
||||
struct iwl_mvm_key_pn __rcu *ptk_pn[4];
|
||||
struct iwl_mvm_rxq_dup_data *dup_data;
|
||||
@ -414,9 +429,11 @@ struct iwl_mvm_sta {
|
||||
bool sleeping;
|
||||
u8 agg_tids;
|
||||
u8 sleep_tx_count;
|
||||
u8 avg_energy;
|
||||
u8 tx_ant;
|
||||
u32 pairwise_cipher;
|
||||
|
||||
struct iwl_mvm_link_sta deflink;
|
||||
struct iwl_mvm_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
};
|
||||
|
||||
u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data);
|
||||
@ -436,7 +453,7 @@ iwl_mvm_sta_from_mac80211(struct ieee80211_sta *sta)
|
||||
*/
|
||||
struct iwl_mvm_int_sta {
|
||||
u32 sta_id;
|
||||
enum iwl_sta_type type;
|
||||
u8 type;
|
||||
u32 tfd_queue_msk;
|
||||
};
|
||||
|
||||
@ -452,6 +469,9 @@ struct iwl_mvm_int_sta {
|
||||
*/
|
||||
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
bool update, unsigned int flags);
|
||||
int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype);
|
||||
int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, int sta_id, u8 sta_type);
|
||||
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
@ -463,8 +483,13 @@ static inline int iwl_mvm_update_sta(struct iwl_mvm *mvm,
|
||||
return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
|
||||
}
|
||||
|
||||
void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvm_sta);
|
||||
bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_link_sta *link_sta, int *ret);
|
||||
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
@ -510,6 +535,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id);
|
||||
int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm);
|
||||
|
||||
int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_add_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
@ -519,7 +546,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_int_sta *sta,
|
||||
u32 qmask, enum nl80211_iftype iftype,
|
||||
enum iwl_sta_type type);
|
||||
u8 type);
|
||||
void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta);
|
||||
int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
@ -543,6 +570,7 @@ void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
|
||||
void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif,
|
||||
bool disable);
|
||||
|
||||
void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk);
|
||||
int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
@ -551,4 +579,78 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 mac_id);
|
||||
/* Queues */
|
||||
int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
u8 sta_id, u8 tid, unsigned int timeout);
|
||||
|
||||
/* Sta state */
|
||||
/**
|
||||
* struct iwl_mvm_sta_state_ops - callbacks for the sta_state() ops
|
||||
*
|
||||
* Since the only difference between both MLD and
|
||||
* non-MLD versions of sta_state() is these function calls,
|
||||
* each version will send its specific function calls to
|
||||
* %iwl_mvm_mac_sta_state_common().
|
||||
*
|
||||
* @add_sta: pointer to the function that adds a new sta
|
||||
* @update_sta: pointer to the function that updates a sta
|
||||
* @rm_sta: pointer to the functions that removes a sta
|
||||
* @mac_ctxt_changed: pointer to the function that handles a change in mac ctxt
|
||||
*/
|
||||
struct iwl_mvm_sta_state_ops {
|
||||
int (*add_sta)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int (*update_sta)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int (*rm_sta)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int (*mac_ctxt_changed)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool force_assoc_off);
|
||||
};
|
||||
|
||||
int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
enum ieee80211_sta_state old_state,
|
||||
enum ieee80211_sta_state new_state,
|
||||
struct iwl_mvm_sta_state_ops *callbacks);
|
||||
|
||||
/* New MLD STA related APIs */
|
||||
/* STA */
|
||||
int iwl_mvm_mld_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_mld_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_mld_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_mld_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id);
|
||||
int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_mld_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int iwl_mvm_mld_rm_aux_sta(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id);
|
||||
int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
u16 old_links, u16 new_links);
|
||||
|
||||
/* Queues */
|
||||
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif,
|
||||
bool disable);
|
||||
void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvm_sta,
|
||||
bool disable);
|
||||
void iwl_mvm_mld_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
bool disable);
|
||||
#endif /* __sta_h__ */
|
||||
|
@ -369,7 +369,7 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
|
||||
goto out;
|
||||
}
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
cmd.peer_sta_id = cpu_to_le32(mvmsta->sta_id);
|
||||
cmd.peer_sta_id = cpu_to_le32(mvmsta->deflink.sta_id);
|
||||
|
||||
if (!chandef) {
|
||||
if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
|
||||
@ -414,7 +414,7 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
iwl_mvm_set_tx_cmd(mvm, skb, &tail->frame.tx_cmd, info,
|
||||
mvmsta->sta_id);
|
||||
mvmsta->deflink.sta_id);
|
||||
|
||||
iwl_mvm_set_tx_cmd_rate(mvm, &tail->frame.tx_cmd, info, sta,
|
||||
hdr->frame_control);
|
||||
@ -431,7 +431,7 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
|
||||
|
||||
/* channel switch has started, update state */
|
||||
if (type != TDLS_MOVE_CH) {
|
||||
mvm->tdls_cs.cur_sta_id = mvmsta->sta_id;
|
||||
mvm->tdls_cs.cur_sta_id = mvmsta->deflink.sta_id;
|
||||
iwl_mvm_tdls_update_cs_state(mvm,
|
||||
type == TDLS_SEND_CHAN_SW_REQ ?
|
||||
IWL_MVM_TDLS_SW_REQ_SENT :
|
||||
@ -541,7 +541,7 @@ iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
mvm->tdls_cs.peer.sta_id = mvmsta->sta_id;
|
||||
mvm->tdls_cs.peer.sta_id = mvmsta->deflink.sta_id;
|
||||
mvm->tdls_cs.peer.chandef = *chandef;
|
||||
mvm->tdls_cs.peer.initiator = sta->tdls_initiator;
|
||||
mvm->tdls_cs.peer.op_class = oper_class;
|
||||
|
@ -79,7 +79,8 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
|
||||
|
||||
if (!WARN_ON(!mvm->p2p_device_vif)) {
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(mvm->p2p_device_vif);
|
||||
iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true);
|
||||
iwl_mvm_flush_sta(mvm, &mvmvif->deflink.bcast_sta,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +95,11 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
|
||||
/* do the same in case of hot spot 2.0 */
|
||||
iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true);
|
||||
|
||||
if (mvm->mld_api_is_used) {
|
||||
iwl_mvm_mld_rm_aux_sta(mvm);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* In newer version of this command an aux station is added only
|
||||
* in cases of dedicated tx queue and need to be removed in end
|
||||
* of use */
|
||||
@ -101,6 +107,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
|
||||
iwl_mvm_rm_aux_sta(mvm);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
@ -170,7 +177,8 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
|
||||
rcu_read_lock();
|
||||
mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
|
||||
mvmsta = iwl_mvm_sta_from_staid_rcu(mvm,
|
||||
mvmvif->deflink.ap_sta_id);
|
||||
if (!WARN_ON(!mvmsta))
|
||||
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
|
||||
rcu_read_unlock();
|
||||
|
173
drivers/net/wireless/intel/iwlwifi/mvm/time-sync.c
Normal file
173
drivers/net/wireless/intel/iwlwifi/mvm/time-sync.c
Normal file
@ -0,0 +1,173 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "mvm.h"
|
||||
#include "time-sync.h"
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
void iwl_mvm_init_time_sync(struct iwl_time_sync_data *data)
|
||||
{
|
||||
skb_queue_head_init(&data->frame_list);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_is_skb_match(struct sk_buff *skb, u8 *addr, u8 dialog_token)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||
u8 skb_dialog_token;
|
||||
|
||||
if (ieee80211_is_timing_measurement(skb))
|
||||
skb_dialog_token = mgmt->u.action.u.wnm_timing_msr.dialog_token;
|
||||
else
|
||||
skb_dialog_token = mgmt->u.action.u.ftm.dialog_token;
|
||||
|
||||
if ((ether_addr_equal(mgmt->sa, addr) ||
|
||||
ether_addr_equal(mgmt->da, addr)) &&
|
||||
skb_dialog_token == dialog_token)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct sk_buff *iwl_mvm_time_sync_find_skb(struct iwl_mvm *mvm, u8 *addr,
|
||||
u8 dialog_token)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* The queue is expected to have only one SKB. If there are other SKBs
|
||||
* in the queue, they did not get a time sync notification and are
|
||||
* probably obsolete by now, so drop them.
|
||||
*/
|
||||
while ((skb = skb_dequeue(&mvm->time_sync.frame_list))) {
|
||||
if (iwl_mvm_is_skb_match(skb, addr, dialog_token))
|
||||
break;
|
||||
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static u64 iwl_mvm_get_64_bit(__le32 high, __le32 low)
|
||||
{
|
||||
return ((u64)le32_to_cpu(high) << 32) | le32_to_cpu(low);
|
||||
}
|
||||
|
||||
void iwl_mvm_time_sync_msmt_event(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_time_msmt_notify *notif = (void *)pkt->data;
|
||||
struct ieee80211_rx_status *rx_status;
|
||||
struct skb_shared_hwtstamps *shwt;
|
||||
u64 ts_10ns;
|
||||
struct sk_buff *skb =
|
||||
iwl_mvm_time_sync_find_skb(mvm, notif->peer_addr,
|
||||
le32_to_cpu(notif->dialog_token));
|
||||
u64 adj_time;
|
||||
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(mvm, "Time sync event but no pending skb\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ts_10ns = iwl_mvm_get_64_bit(notif->t2_hi, notif->t2_lo);
|
||||
adj_time = iwl_mvm_ptp_get_adj_time(mvm, ts_10ns * 10);
|
||||
shwt = skb_hwtstamps(skb);
|
||||
shwt->hwtstamp = ktime_set(0, adj_time);
|
||||
|
||||
ts_10ns = iwl_mvm_get_64_bit(notif->t3_hi, notif->t3_lo);
|
||||
adj_time = iwl_mvm_ptp_get_adj_time(mvm, ts_10ns * 10);
|
||||
rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
rx_status->ack_tx_hwtstamp = ktime_set(0, adj_time);
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"Time sync: RX event - report frame t2=%llu t3=%llu\n",
|
||||
ktime_to_ns(shwt->hwtstamp),
|
||||
ktime_to_ns(rx_status->ack_tx_hwtstamp));
|
||||
ieee80211_rx_napi(mvm->hw, NULL, skb, NULL);
|
||||
}
|
||||
|
||||
void iwl_mvm_time_sync_msmt_confirm_event(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_time_msmt_cfm_notify *notif = (void *)pkt->data;
|
||||
struct ieee80211_tx_status status = {};
|
||||
struct skb_shared_hwtstamps *shwt;
|
||||
u64 ts_10ns, adj_time;
|
||||
|
||||
status.skb =
|
||||
iwl_mvm_time_sync_find_skb(mvm, notif->peer_addr,
|
||||
le32_to_cpu(notif->dialog_token));
|
||||
|
||||
if (!status.skb) {
|
||||
IWL_DEBUG_INFO(mvm, "Time sync confirm but no pending skb\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ts_10ns = iwl_mvm_get_64_bit(notif->t1_hi, notif->t1_lo);
|
||||
adj_time = iwl_mvm_ptp_get_adj_time(mvm, ts_10ns * 10);
|
||||
shwt = skb_hwtstamps(status.skb);
|
||||
shwt->hwtstamp = ktime_set(0, adj_time);
|
||||
|
||||
ts_10ns = iwl_mvm_get_64_bit(notif->t4_hi, notif->t4_lo);
|
||||
adj_time = iwl_mvm_ptp_get_adj_time(mvm, ts_10ns * 10);
|
||||
status.info = IEEE80211_SKB_CB(status.skb);
|
||||
status.ack_hwtstamp = ktime_set(0, adj_time);
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"Time sync: TX event - report frame t1=%llu t4=%llu\n",
|
||||
ktime_to_ns(shwt->hwtstamp),
|
||||
ktime_to_ns(status.ack_hwtstamp));
|
||||
ieee80211_tx_status_ext(mvm->hw, &status);
|
||||
}
|
||||
|
||||
int iwl_mvm_time_sync_config(struct iwl_mvm *mvm, const u8 *addr, u32 protocols)
|
||||
{
|
||||
struct iwl_time_sync_cfg_cmd cmd = {};
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_TIME_SYNC_BOTH_FTM_TM))
|
||||
return -EINVAL;
|
||||
|
||||
/* The fw only supports one peer. We do allow reconfiguration of the
|
||||
* same peer for cases of fw reset etc.
|
||||
*/
|
||||
if (mvm->time_sync.active &&
|
||||
!ether_addr_equal(addr, mvm->time_sync.peer_addr)) {
|
||||
IWL_DEBUG_INFO(mvm, "Time sync: reject config for peer: %pM\n",
|
||||
addr);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
if (protocols & ~(IWL_TIME_SYNC_PROTOCOL_TM |
|
||||
IWL_TIME_SYNC_PROTOCOL_FTM))
|
||||
return -EINVAL;
|
||||
|
||||
cmd.protocols = cpu_to_le32(protocols);
|
||||
|
||||
ether_addr_copy(cmd.peer_addr, addr);
|
||||
|
||||
err = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(DATA_PATH_GROUP,
|
||||
WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD),
|
||||
0, sizeof(cmd), &cmd);
|
||||
if (err) {
|
||||
IWL_ERR(mvm, "Failed to send time sync cfg cmd: %d\n", err);
|
||||
} else {
|
||||
mvm->time_sync.active = protocols != 0;
|
||||
ether_addr_copy(mvm->time_sync.peer_addr, addr);
|
||||
IWL_DEBUG_INFO(mvm, "Time sync: set peer addr=%pM\n", addr);
|
||||
}
|
||||
|
||||
if (!mvm->time_sync.active)
|
||||
skb_queue_purge(&mvm->time_sync.frame_list);
|
||||
|
||||
return err;
|
||||
}
|
30
drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h
Normal file
30
drivers/net/wireless/intel/iwlwifi/mvm/time-sync.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*/
|
||||
#ifndef __TIME_SYNC_H__
|
||||
#define __TIME_SYNC_H__
|
||||
|
||||
#include "mvm.h"
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
void iwl_mvm_init_time_sync(struct iwl_time_sync_data *data);
|
||||
void iwl_mvm_time_sync_msmt_event(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_time_sync_msmt_confirm_event(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
int iwl_mvm_time_sync_config(struct iwl_mvm *mvm, const u8 *addr,
|
||||
u32 protocols);
|
||||
|
||||
static inline
|
||||
bool iwl_mvm_time_sync_frame(struct iwl_mvm *mvm, struct sk_buff *skb, u8 *addr)
|
||||
{
|
||||
if (ether_addr_equal(mvm->time_sync.peer_addr, addr) &&
|
||||
(ieee80211_is_timing_measurement(skb) || ieee80211_is_ftm(skb))) {
|
||||
skb_queue_tail(&mvm->time_sync.frame_list, skb);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2019-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2019-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2016 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -334,7 +334,7 @@ static void iwl_mvm_tt_smps_iterator(void *_data, u8 *mac,
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode);
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode, 0);
|
||||
}
|
||||
|
||||
static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "mvm.h"
|
||||
#include "sta.h"
|
||||
#include "time-sync.h"
|
||||
|
||||
static void
|
||||
iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
|
||||
@ -603,11 +604,10 @@ static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif_link_info *link,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif =
|
||||
iwl_mvm_vif_from_mac80211(info->control.vif);
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
||||
switch (info->control.vif->type) {
|
||||
@ -626,15 +626,15 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
|
||||
if (ieee80211_is_mgmt(fc) &&
|
||||
(!ieee80211_is_bufferable_mmpdu(fc) ||
|
||||
ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
|
||||
return mvm->probe_queue;
|
||||
return link->mgmt_queue;
|
||||
|
||||
if (!ieee80211_has_order(fc) && !ieee80211_is_probe_req(fc) &&
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
return mvmvif->cab_queue;
|
||||
return link->cab_queue;
|
||||
|
||||
WARN_ONCE(info->control.vif->type != NL80211_IFTYPE_ADHOC,
|
||||
"fc=0x%02x", le16_to_cpu(fc));
|
||||
return mvm->probe_queue;
|
||||
return link->mgmt_queue;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
return mvm->p2p_dev_queue;
|
||||
@ -667,7 +667,7 @@ static void iwl_mvm_probe_resp_set_noa(struct iwl_mvm *mvm,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
resp_data = rcu_dereference(mvmvif->probe_resp_data);
|
||||
resp_data = rcu_dereference(mvmvif->deflink.probe_resp_data);
|
||||
if (!resp_data)
|
||||
goto out;
|
||||
|
||||
@ -738,12 +738,26 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE ||
|
||||
info.control.vif->type == NL80211_IFTYPE_AP ||
|
||||
info.control.vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
sta_id = mvmvif->bcast_sta.sta_id;
|
||||
else
|
||||
sta_id = mvmvif->mcast_sta.sta_id;
|
||||
u32 link_id = u32_get_bits(info.control.flags,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
struct iwl_mvm_vif_link_info *link;
|
||||
|
||||
queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr);
|
||||
if (link_id == IEEE80211_LINK_UNSPECIFIED) {
|
||||
if (info.control.vif->active_links)
|
||||
link_id = ffs(info.control.vif->active_links) - 1;
|
||||
else
|
||||
link_id = 0;
|
||||
}
|
||||
|
||||
link = mvmvif->link[link_id];
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
sta_id = link->bcast_sta.sta_id;
|
||||
else
|
||||
sta_id = link->mcast_sta.sta_id;
|
||||
|
||||
queue = iwl_mvm_get_ctrl_vif_queue(mvm, link, &info,
|
||||
hdr);
|
||||
} else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
|
||||
queue = mvm->snif_queue;
|
||||
sta_id = mvm->snif_sta.sta_id;
|
||||
@ -1083,7 +1097,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
if (WARN_ON_ONCE(!mvmsta))
|
||||
return -1;
|
||||
|
||||
if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA))
|
||||
if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
|
||||
return -1;
|
||||
|
||||
if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->deflink.he_cap.has_he)
|
||||
@ -1093,7 +1107,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
iwl_mvm_probe_resp_set_noa(mvm, skb);
|
||||
|
||||
dev_cmd = iwl_mvm_set_tx_params(mvm, skb, info, hdrlen,
|
||||
sta, mvmsta->sta_id);
|
||||
sta, mvmsta->deflink.sta_id);
|
||||
if (!dev_cmd)
|
||||
goto drop;
|
||||
|
||||
@ -1169,7 +1183,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x len %d\n",
|
||||
mvmsta->sta_id, tid, txq_id,
|
||||
mvmsta->deflink.sta_id, tid, txq_id,
|
||||
IEEE80211_SEQ_TO_SN(seq_number), skb->len);
|
||||
|
||||
/* From now on, we cannot access info->control */
|
||||
@ -1204,7 +1218,8 @@ drop_unlock_sta:
|
||||
iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
|
||||
spin_unlock(&mvmsta->lock);
|
||||
drop:
|
||||
IWL_DEBUG_TX(mvm, "TX to [%d|%d] dropped\n", mvmsta->sta_id, tid);
|
||||
IWL_DEBUG_TX(mvm, "TX to [%d|%d] dropped\n", mvmsta->deflink.sta_id,
|
||||
tid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1221,7 +1236,7 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
if (WARN_ON_ONCE(!mvmsta))
|
||||
return -1;
|
||||
|
||||
if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA))
|
||||
if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
|
||||
return -1;
|
||||
|
||||
memcpy(&info, skb->cb, sizeof(info));
|
||||
@ -1643,7 +1658,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
info->status.status_driver_data[0] =
|
||||
RS_DRV_DATA_PACK(lq_color, tx_resp->reduced_tpc);
|
||||
|
||||
ieee80211_tx_status(mvm->hw, skb);
|
||||
if (likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr1)))
|
||||
ieee80211_tx_status(mvm->hw, skb);
|
||||
}
|
||||
|
||||
/* This is an aggregation queue or might become one, so we use
|
||||
@ -1973,9 +1989,11 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
|
||||
* possible (i.e. first MPDU in the aggregation wasn't acked)
|
||||
* Still it's important to update RS about sent vs. acked.
|
||||
*/
|
||||
if (!is_flush && skb_queue_empty(&reclaimed_skbs)) {
|
||||
if (!is_flush && skb_queue_empty(&reclaimed_skbs) &&
|
||||
!iwl_mvm_has_tlc_offload(mvm)) {
|
||||
struct ieee80211_chanctx_conf *chanctx_conf = NULL;
|
||||
|
||||
/* no TLC offload, so non-MLD mode */
|
||||
if (mvmsta->vif)
|
||||
chanctx_conf =
|
||||
rcu_dereference(mvmsta->vif->bss_conf.chanctx_conf);
|
||||
@ -1986,11 +2004,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
|
||||
tx_info->band = chanctx_conf->def.chan->band;
|
||||
iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, tx_info);
|
||||
|
||||
if (!iwl_mvm_has_tlc_offload(mvm)) {
|
||||
IWL_DEBUG_TX_REPLY(mvm,
|
||||
"No reclaim. Update rs directly\n");
|
||||
iwl_mvm_rs_tx_status(mvm, sta, tid, tx_info, false);
|
||||
}
|
||||
IWL_DEBUG_TX_REPLY(mvm, "No reclaim. Update rs directly\n");
|
||||
iwl_mvm_rs_tx_status(mvm, sta, tid, tx_info, false);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -2228,17 +2243,22 @@ free_rsp:
|
||||
|
||||
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal)
|
||||
{
|
||||
struct iwl_mvm_int_sta *int_sta = sta;
|
||||
struct iwl_mvm_sta *mvm_sta = sta;
|
||||
u32 sta_id, tfd_queue_msk;
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct iwl_mvm_int_sta, sta_id) !=
|
||||
offsetof(struct iwl_mvm_sta, sta_id));
|
||||
if (internal) {
|
||||
struct iwl_mvm_int_sta *int_sta = sta;
|
||||
|
||||
sta_id = int_sta->sta_id;
|
||||
tfd_queue_msk = int_sta->tfd_queue_msk;
|
||||
} else {
|
||||
struct iwl_mvm_sta *mvm_sta = sta;
|
||||
|
||||
sta_id = mvm_sta->deflink.sta_id;
|
||||
tfd_queue_msk = mvm_sta->tfd_queue_msk;
|
||||
}
|
||||
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id, 0xffff);
|
||||
return iwl_mvm_flush_sta_tids(mvm, sta_id, 0xffff);
|
||||
|
||||
if (internal)
|
||||
return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk);
|
||||
|
||||
return iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk);
|
||||
return iwl_mvm_flush_tx_path(mvm, tfd_queue_msk);
|
||||
}
|
||||
|
@ -272,13 +272,15 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
|
||||
* @vif: Pointer to the ieee80211_vif structure
|
||||
* @req_type: The part of the driver who call for a change.
|
||||
* @smps_request: The request to change the SMPS mode.
|
||||
* @link_id: for MLO link_id, otherwise 0 (deflink)
|
||||
*
|
||||
* Get a requst to change the SMPS mode,
|
||||
* and change it according to all other requests in the driver.
|
||||
*/
|
||||
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
enum iwl_mvm_smps_type_request req_type,
|
||||
enum ieee80211_smps_mode smps_request)
|
||||
enum ieee80211_smps_mode smps_request,
|
||||
unsigned int link_id)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
@ -294,17 +296,38 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
mvmvif->smps_requests[req_type] = smps_request;
|
||||
|
||||
if (WARN_ON_ONCE(!mvmvif->link[link_id]))
|
||||
return;
|
||||
|
||||
mvmvif->link[link_id]->smps_requests[req_type] = smps_request;
|
||||
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
|
||||
if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC) {
|
||||
if (mvmvif->link[link_id]->smps_requests[i] ==
|
||||
IEEE80211_SMPS_STATIC) {
|
||||
smps_mode = IEEE80211_SMPS_STATIC;
|
||||
break;
|
||||
}
|
||||
if (mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC)
|
||||
if (mvmvif->link[link_id]->smps_requests[i] ==
|
||||
IEEE80211_SMPS_DYNAMIC)
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
}
|
||||
|
||||
ieee80211_request_smps(vif, 0, smps_mode);
|
||||
ieee80211_request_smps(vif, link_id, smps_mode);
|
||||
}
|
||||
|
||||
void iwl_mvm_update_smps_on_active_links(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
enum iwl_mvm_smps_type_request req_type,
|
||||
enum ieee80211_smps_mode smps_request)
|
||||
{
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
unsigned int link_id;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_vif_active_link(vif, link_conf, link_id)
|
||||
iwl_mvm_update_smps(mvm, vif, req_type, smps_request,
|
||||
link_id);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static bool iwl_wait_stats_complete(struct iwl_notif_wait_data *notif_wait,
|
||||
@ -392,12 +415,12 @@ static void iwl_mvm_diversity_iter(void *_data, u8 *mac,
|
||||
struct iwl_mvm_diversity_iter_data *data = _data;
|
||||
int i;
|
||||
|
||||
if (mvmvif->phy_ctxt != data->ctxt)
|
||||
if (mvmvif->deflink.phy_ctxt != data->ctxt)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
|
||||
if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC ||
|
||||
mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
|
||||
if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC ||
|
||||
mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
|
||||
data->result = false;
|
||||
break;
|
||||
}
|
||||
@ -495,10 +518,10 @@ static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
|
||||
if (iwl_mvm_vif_low_latency(mvmvif)) {
|
||||
result->result = true;
|
||||
|
||||
if (!mvmvif->phy_ctxt)
|
||||
if (!mvmvif->deflink.phy_ctxt)
|
||||
return;
|
||||
|
||||
band = mvmvif->phy_ctxt->channel->band;
|
||||
band = mvmvif->deflink.phy_ctxt->channel->band;
|
||||
result->result_per_band[band] = true;
|
||||
}
|
||||
}
|
||||
@ -819,10 +842,10 @@ static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm,
|
||||
if (!vif->cfg.assoc)
|
||||
return;
|
||||
|
||||
if (!mvmvif->queue_params[IEEE80211_AC_VO].uapsd &&
|
||||
!mvmvif->queue_params[IEEE80211_AC_VI].uapsd &&
|
||||
!mvmvif->queue_params[IEEE80211_AC_BE].uapsd &&
|
||||
!mvmvif->queue_params[IEEE80211_AC_BK].uapsd)
|
||||
if (!mvmvif->deflink.queue_params[IEEE80211_AC_VO].uapsd &&
|
||||
!mvmvif->deflink.queue_params[IEEE80211_AC_VI].uapsd &&
|
||||
!mvmvif->deflink.queue_params[IEEE80211_AC_BE].uapsd &&
|
||||
!mvmvif->deflink.queue_params[IEEE80211_AC_BK].uapsd)
|
||||
return;
|
||||
|
||||
if (mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected)
|
||||
@ -831,7 +854,8 @@ static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm,
|
||||
mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected = true;
|
||||
IWL_INFO(mvm,
|
||||
"detected AP should do aggregation but isn't, likely due to U-APSD\n");
|
||||
schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk, 15 * HZ);
|
||||
schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk,
|
||||
15 * HZ);
|
||||
}
|
||||
|
||||
static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
|
||||
@ -883,10 +907,10 @@ static void iwl_mvm_tcm_iterator(void *_data, u8 *mac,
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 *band = _data;
|
||||
|
||||
if (!mvmvif->phy_ctxt)
|
||||
if (!mvmvif->deflink.phy_ctxt)
|
||||
return;
|
||||
|
||||
band[mvmvif->id] = mvmvif->phy_ctxt->channel->band;
|
||||
band[mvmvif->id] = mvmvif->deflink.phy_ctxt->channel->band;
|
||||
}
|
||||
|
||||
static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
|
||||
@ -1137,3 +1161,36 @@ void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, int clock_type,
|
||||
iwl_mvm_power_update_device(mvm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find if at least two links from different vifs use same channel
|
||||
* FIXME: consider having a refcount array in struct iwl_mvm_vif for
|
||||
* used phy_ctxt ids.
|
||||
*/
|
||||
bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1,
|
||||
struct iwl_mvm_vif *vif2)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for_each_mvm_vif_valid_link(vif1, i) {
|
||||
for_each_mvm_vif_valid_link(vif2, j) {
|
||||
if (vif1->link[i]->phy_ctxt == vif2->link[j]->phy_ctxt)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* FIXME: can it fail when phy_ctxt is assigned? */
|
||||
for_each_mvm_vif_valid_link(mvmvif, i) {
|
||||
if (mvmvif->link[i]->phy_ctxt &&
|
||||
mvmvif->link[i]->phy_ctxt->id < NUM_PHY_CTX)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1159,6 +1159,16 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_NO_JACKET,
|
||||
iwl_cfg_bz_a0_fm4_a0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bz_a0_fm_b0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bz_a0_fm4_b0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
|
||||
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
|
||||
@ -1204,15 +1214,30 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bnj_a0_gf_a0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bnj_b0_gf_a0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bnj_a0_gf4_a0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bnj_b0_gf4_a0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
|
||||
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bnj_a0_hr_b0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
|
||||
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
|
||||
iwl_cfg_bnj_b0_hr_b0, iwl_bz_name),
|
||||
|
||||
/* SoF with JF2 */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
|
55
drivers/net/wireless/legacy/Kconfig
Normal file
55
drivers/net/wireless/legacy/Kconfig
Normal file
@ -0,0 +1,55 @@
|
||||
config PCMCIA_RAYCS
|
||||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||
depends on PCMCIA
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
help
|
||||
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
|
||||
(PC-card) wireless Ethernet networking card to your computer.
|
||||
Please read the file
|
||||
<file:Documentation/networking/device_drivers/wifi/ray_cs.rst> for
|
||||
details.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ray_cs. If unsure, say N.
|
||||
|
||||
config PCMCIA_WL3501
|
||||
tristate "Planet WL3501 PCMCIA cards"
|
||||
depends on CFG80211 && PCMCIA
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
help
|
||||
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
||||
It has basic support for Linux wireless extensions and initial
|
||||
micro support for ethtool.
|
||||
|
||||
config USB_NET_RNDIS_WLAN
|
||||
tristate "Wireless RNDIS USB support"
|
||||
depends on USB
|
||||
depends on CFG80211
|
||||
select USB_NET_DRIVERS
|
||||
select USB_USBNET
|
||||
select USB_NET_CDCETHER
|
||||
select USB_NET_RNDIS_HOST
|
||||
help
|
||||
This is a driver for wireless RNDIS devices.
|
||||
These are USB based adapters found in devices such as:
|
||||
|
||||
Buffalo WLI-U2-KG125S
|
||||
U.S. Robotics USR5421
|
||||
Belkin F5D7051
|
||||
Linksys WUSB54GSv2
|
||||
Linksys WUSB54GSC
|
||||
Asus WL169gE
|
||||
Eminent EM4045
|
||||
BT Voyager 1055
|
||||
Linksys WUSB54GSv1
|
||||
U.S. Robotics USR5420
|
||||
BUFFALO WLI-USB-G54
|
||||
|
||||
All of these devices are based on Broadcom 4320 chip which is the
|
||||
only wireless RNDIS chip known to date.
|
||||
|
||||
If you choose to build a module, it'll be called rndis_wlan.
|
||||
|
6
drivers/net/wireless/legacy/Makefile
Normal file
6
drivers/net/wireless/legacy/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# 16-bit wireless PCMCIA client drivers
|
||||
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
|
||||
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
|
||||
|
||||
obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user