wireless-drivers-next patches for v5.13

Second set of patches for v5.13. A lot of iwlwifi and mt76 patches
 this time, and also smaller features and fixes all over.
 
 mt76
 
 * mt7915/mt7615 decapsulation offload support
 
 * threaded NAPI support
 
 * new device IDs
 
 * mt7921 device reset support
 
 * rx timestamp support
 
 iwlwifi
 
 * passive scan support for 6GHz
 
 * new hardware support
 
 wilc1000
 
 * CRC support for SPI bus
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJge+xHAAoJEG4XJFUm622b3+MH/RLorFA9iU+jdbq9nA1a9f/K
 roiB9+lJogZKdy0rphF3d+/ItOPe1CZ791HP0GRRA3SsE+jO3LAxzEWvh27k7NoB
 G3gdGSXtMkUY70Fab89QG8pyn07/R/403gr6H6sxMYg3Y/2gUHUbCqPN2N4DXw0/
 2MVtxvrV4WERxirChJV3uzord8BGce1H69S6+jVLQiuoJM1PZZVr6vw+OSw7qntL
 Zc2fMjBlBulU2R3EFiOkm08PwM8mJRB8JJiQ8vnB2nMeKpFOnCgm3Hozly7q/zCB
 xCWlZcKBPYhtCRLoipvWnTt0SopZXyqslJbBBqlFVUkjPdrLqBBcVv3j5K7OZd4=
 =DVDR
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-2021-04-18' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for v5.13

Second set of patches for v5.13. A lot of iwlwifi and mt76 patches
this time, and also smaller features and fixes all over.

mt76

* mt7915/mt7615 decapsulation offload support

* threaded NAPI support

* new device IDs

* mt7921 device reset support

* rx timestamp support

iwlwifi

* passive scan support for 6GHz

* new hardware support

wilc1000

* CRC support for SPI bus
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-04-19 14:35:05 -07:00
commit 56aa7b21a5
170 changed files with 4581 additions and 2469 deletions

View file

@ -1,24 +0,0 @@
Common IEEE 802.11 properties
This provides documentation of common properties that are valid for all wireless
devices.
Optional properties:
- ieee80211-freq-limit : list of supported frequency ranges in KHz. This can be
used for devices that in a given config support less channels than
normally. It may happen chipset supports a wide wireless band but it is
limited to some part of it due to used antennas or power amplifier.
An example case for this can be tri-band wireless router with two
identical chipsets used for two different 5 GHz subbands. Using them
incorrectly could not work or decrease performance noticeably.
Example:
pcie@0,0 {
reg = <0x0000 0 0 0 0>;
wifi@0,0 {
reg = <0x0000 0 0 0 0>;
ieee80211-freq-limit = <2402000 2482000>,
<5170000 5250000>;
};
};

View file

@ -0,0 +1,45 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/wireless/ieee80211.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Common IEEE 802.11 Binding
maintainers:
- Lorenzo Bianconi <lorenzo@kernel.org>
description: |
This provides documentation of common properties that are valid for
all wireless devices
properties:
ieee80211-freq-limit:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
items:
minItems: 2
maxItems: 2
description:
List of supported frequency ranges in KHz. This can be used for devices
that in a given config support less channels than normally. It may happen
chipset supports a wide wireless band but it is limited to some part of
it due to used antennas or power amplifier. An example case for this
can be tri-band wireless router with two identical chipsets used for two
different 5 GHz subbands. Using them incorrectly could not work or
decrease performance noticeably
additionalProperties: true
examples:
- |
pcie0 {
#address-cells = <3>;
#size-cells = <2>;
wifi@0,0 {
reg = <0x0000 0 0 0 0>;
ieee80211-freq-limit = <2402000 2482000>,
<5170000 5250000>;
};
};

View file

@ -1,78 +0,0 @@
* MediaTek mt76xx devices
This node provides properties for configuring the MediaTek mt76xx wireless
device. The node is expected to be specified as a child node of the PCI
controller to which the wireless chip is connected.
Alternatively, it can specify the wireless part of the MT7628/MT7688 or
MT7622 SoC. For SoC, use the following compatible strings:
compatible:
- "mediatek,mt7628-wmac" for MT7628/MT7688
- "mediatek,mt7622-wmac" for MT7622
properties:
- reg: Address and length of the register set for the device.
- interrupts: Main device interrupt
MT7622 specific properties:
- power-domains: phandle to the power domain that the WMAC is part of
- mediatek,infracfg: phandle to the infrastructure bus fabric syscon node
Optional properties:
- ieee80211-freq-limit: See ieee80211.txt
- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
- big-endian: if the radio eeprom partition is written in big-endian, specify
this property
- mediatek,eeprom-merge-otp: Merge EEPROM data with OTP data. Can be used on
boards where the flash calibration data is generic and specific calibration
data should be pulled from the OTP ROM
The MAC address can as well be set with corresponding optional properties
defined in net/ethernet.txt.
Optional nodes:
- led: Properties for a connected LED
Optional properties:
- led-sources: See Documentation/devicetree/bindings/leds/common.txt
&pcie {
pcie0 {
wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;
ieee80211-freq-limit = <5000000 6000000>;
mediatek,mtd-eeprom = <&factory 0x8000>;
big-endian;
led {
led-sources = <2>;
};
};
};
};
MT7628 example:
wmac: wmac@10300000 {
compatible = "mediatek,mt7628-wmac";
reg = <0x10300000 0x100000>;
interrupt-parent = <&cpuintc>;
interrupts = <6>;
mediatek,mtd-eeprom = <&factory 0x0000>;
};
MT7622 example:
wmac: wmac@18000000 {
compatible = "mediatek,mt7622-wmac";
reg = <0 0x18000000 0 0x100000>;
interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_LOW>;
mediatek,infracfg = <&infracfg>;
power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>;
};

View file

@ -0,0 +1,121 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/wireless/mediatek,mt76.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek mt76 wireless devices Generic Binding
maintainers:
- Felix Fietkau <nbd@nbd.name>
- Lorenzo Bianconi <lorenzo@kernel.org>
- Ryder Lee <ryder.lee@mediatek.com>
description: |
This node provides properties for configuring the MediaTek mt76xx
wireless device. The node is expected to be specified as a child
node of the PCI controller to which the wireless chip is connected.
Alternatively, it can specify the wireless part of the MT7628/MT7688
or MT7622 SoC.
allOf:
- $ref: ieee80211.yaml#
properties:
compatible:
enum:
- mediatek,mt76
- mediatek,mt7628-wmac
- mediatek,mt7622-wmac
reg:
maxItems: 1
interrupts:
maxItems: 1
power-domains:
maxItems: 1
mediatek,infracfg:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to the infrastructure bus fabric syscon node.
This property is MT7622 specific
ieee80211-freq-limit: true
mediatek,mtd-eeprom:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
Phandle to a MTD partition + offset containing EEPROM data
big-endian:
$ref: /schemas/types.yaml#/definitions/flag
description:
Specify if the radio eeprom partition is written in big-endian
mediatek,eeprom-merge-otp:
type: boolean
description:
Merge EEPROM data with OTP data. Can be used on boards where the flash
calibration data is generic and specific calibration data should be
pulled from the OTP ROM
led:
type: object
$ref: /schemas/leds/common.yaml#
additionalProperties: false
properties:
led-sources:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
pcie0 {
#address-cells = <3>;
#size-cells = <2>;
wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;
ieee80211-freq-limit = <5000000 6000000>;
mediatek,mtd-eeprom = <&factory 0x8000>;
big-endian;
led {
led-sources = <2>;
};
};
};
- |
wifi@10300000 {
compatible = "mediatek,mt7628-wmac";
reg = <0x10300000 0x100000>;
interrupt-parent = <&cpuintc>;
interrupts = <6>;
mediatek,mtd-eeprom = <&factory 0x0>;
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
wifi@18000000 {
compatible = "mediatek,mt7622-wmac";
reg = <0x10300000 0x100000>;
interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_LOW>;
mediatek,infracfg = <&infracfg>;
power-domains = <&scpsys 3>;
};

View file

@ -52,13 +52,6 @@ static inline u32 mips_read32(struct bcma_drv_mips *mcore,
return bcma_read32(mcore->core, offset);
}
static inline void mips_write32(struct bcma_drv_mips *mcore,
u16 offset,
u32 value)
{
bcma_write32(mcore->core, offset, value);
}
static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
{
u32 flag;

View file

@ -631,14 +631,9 @@ static inline u16 carl9170_get_seq(struct sk_buff *skb)
return get_seq_h(carl9170_get_hdr(skb));
}
static inline u16 get_tid_h(struct ieee80211_hdr *hdr)
{
return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
}
static inline u16 carl9170_get_tid(struct sk_buff *skb)
{
return get_tid_h(carl9170_get_hdr(skb));
return ieee80211_get_tid(carl9170_get_hdr(skb));
}
static inline struct ieee80211_vif *

View file

@ -394,7 +394,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
if (unlikely(!sta))
goto out_rcu;
tid = get_tid_h(hdr);
tid = ieee80211_get_tid(hdr);
sta_info = (void *) sta->drv_priv;
tid_info = rcu_dereference(sta_info->agg[tid]);

View file

@ -1456,7 +1456,7 @@ static void wil_link_stats_store_basic(struct wil6210_vif *vif,
u8 cid = basic->cid;
struct wil_sta_info *sta;
if (cid < 0 || cid >= wil->max_assoc_sta) {
if (cid >= wil->max_assoc_sta) {
wil_err(wil, "invalid cid %d\n", cid);
return;
}

View file

@ -112,7 +112,6 @@ do { \
extern int brcmf_msg_level;
struct brcmf_bus;
struct brcmf_pub;
#ifdef DEBUG
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);

View file

@ -28,7 +28,7 @@ struct brcmf_usbdev {
int ntxq, nrxq, rxsize;
u32 bus_mtu;
int devid;
int chiprev; /* chip revsion number */
int chiprev; /* chip revision number */
};
/* IO Request Block (IRB) */

View file

@ -3817,6 +3817,68 @@ static inline void set_auth_type(struct airo_info *local, int auth_type)
local->last_auth = auth_type;
}
static int noinline_for_stack airo_readconfig(struct airo_info *ai, u8 *mac, int lock)
{
int i, status;
/* large variables, so don't inline this function,
* maybe change to kmalloc
*/
tdsRssiRid rssi_rid;
CapabilityRid cap_rid;
kfree(ai->SSID);
ai->SSID = NULL;
// general configuration (read/modify/write)
status = readConfigRid(ai, lock);
if (status != SUCCESS) return ERROR;
status = readCapabilityRid(ai, &cap_rid, lock);
if (status != SUCCESS) return ERROR;
status = PC4500_readrid(ai, RID_RSSI, &rssi_rid, sizeof(rssi_rid), lock);
if (status == SUCCESS) {
if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
}
else {
kfree(ai->rssi);
ai->rssi = NULL;
if (cap_rid.softCap & cpu_to_le16(8))
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else
airo_print_warn(ai->dev->name, "unknown received signal "
"level scale");
}
ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
set_auth_type(ai, AUTH_OPEN);
ai->config.modulation = MOD_CCK;
if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) &&
(cap_rid.extSoftCap & cpu_to_le16(1)) &&
micsetup(ai) == SUCCESS) {
ai->config.opmode |= MODE_MIC;
set_bit(FLAG_MIC_CAPABLE, &ai->flags);
}
/* Save off the MAC */
for (i = 0; i < ETH_ALEN; i++) {
mac[i] = ai->config.macAddr[i];
}
/* Check to see if there are any insmod configured
rates to add */
if (rates[0]) {
memset(ai->config.rates, 0, sizeof(ai->config.rates));
for (i = 0; i < 8 && rates[i]; i++) {
ai->config.rates[i] = rates[i];
}
}
set_bit (FLAG_COMMIT, &ai->flags);
return SUCCESS;
}
static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
{
Cmd cmd;
@ -3863,58 +3925,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if (lock)
up(&ai->sem);
if (ai->config.len == 0) {
int i;
tdsRssiRid rssi_rid;
CapabilityRid cap_rid;
kfree(ai->SSID);
ai->SSID = NULL;
// general configuration (read/modify/write)
status = readConfigRid(ai, lock);
if (status != SUCCESS) return ERROR;
status = readCapabilityRid(ai, &cap_rid, lock);
if (status != SUCCESS) return ERROR;
status = PC4500_readrid(ai, RID_RSSI,&rssi_rid, sizeof(rssi_rid), lock);
if (status == SUCCESS) {
if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
}
else {
kfree(ai->rssi);
ai->rssi = NULL;
if (cap_rid.softCap & cpu_to_le16(8))
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else
airo_print_warn(ai->dev->name, "unknown received signal "
"level scale");
}
ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
set_auth_type(ai, AUTH_OPEN);
ai->config.modulation = MOD_CCK;
if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) &&
(cap_rid.extSoftCap & cpu_to_le16(1)) &&
micsetup(ai) == SUCCESS) {
ai->config.opmode |= MODE_MIC;
set_bit(FLAG_MIC_CAPABLE, &ai->flags);
}
/* Save off the MAC */
for (i = 0; i < ETH_ALEN; i++) {
mac[i] = ai->config.macAddr[i];
}
/* Check to see if there are any insmod configured
rates to add */
if (rates[0]) {
memset(ai->config.rates, 0, sizeof(ai->config.rates));
for (i = 0; i < 8 && rates[i]; i++) {
ai->config.rates[i] = rates[i];
}
}
set_bit (FLAG_COMMIT, &ai->flags);
status = airo_readconfig(ai, mac, lock);
if (status != SUCCESS)
return ERROR;
}
/* Setup the SSIDs if present */

View file

@ -633,8 +633,10 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee,
}
if (ext->alg != IW_ENCODE_ALG_NONE) {
memcpy(sec.keys[idx], ext->key, ext->key_len);
sec.key_sizes[idx] = ext->key_len;
int key_len = clamp_val(ext->key_len, 0, SCM_KEY_LEN);
memcpy(sec.keys[idx], ext->key, key_len);
sec.key_sizes[idx] = key_len;
sec.flags |= (1 << idx);
if (ext->alg == IW_ENCODE_ALG_WEP) {
sec.encode_alg[idx] = SEC_ALG_WEP;

View file

@ -9,7 +9,7 @@
#include "iwl-prph.h"
/* Highest firmware API version supported */
#define IWL_22000_UCODE_API_MAX 62
#define IWL_22000_UCODE_API_MAX 63
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
@ -48,6 +48,10 @@
#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0-"
#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0-"
#define IWL_SNJ_A_MR_A_FW_PRE "iwlwifi-SoSnj-a0-mr-a0-"
#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0-"
#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0-"
#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-"
#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-"
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
@ -91,6 +95,14 @@
IWL_MA_A_MR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_SNJ_A_MR_A_MODULE_FIRMWARE(api) \
IWL_SNJ_A_MR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
IWL_BZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
IWL_BZ_A_GF_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \
IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \
IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode"
static const struct iwl_base_params iwl_22000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
@ -357,13 +369,27 @@ const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
.umac_prph_offset = 0x300000
};
const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.mq_rx_supported = true,
.use_tfh = true,
.rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
.xtal_latency = 12000,
.low_latency_xtal = true,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6 AX211 160MHz";
const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6 AX411 160MHz";
const char iwl_ma_name[] = "Intel(R) Wi-Fi 6";
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz";
const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
const char iwl_ax200_killer_1650w_name[] =
"Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)";
@ -373,6 +399,10 @@ const char iwl_ax201_killer_1650s_name[] =
"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)";
const char iwl_ax201_killer_1650i_name[] =
"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)";
const char iwl_ax210_killer_1675w_name[] =
"Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
const char iwl_ax210_killer_1675x_name[] =
"Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
@ -578,7 +608,7 @@ const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg = {
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = {
const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
.name = "Intel(R) Wireless-AC 9560 160MHz",
.fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
IWL_DEVICE_AX210,
@ -719,6 +749,34 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = {
.fw_name_pre = IWL_BZ_A_HR_B_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = {
.fw_name_pre = IWL_BZ_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = {
.fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = {
.fw_name_pre = IWL_BZ_A_MR_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
@ -740,3 +798,7 @@ MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SNJ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
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));

View file

@ -168,7 +168,7 @@ const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz";
const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz";
const char iwl9260_killer_1550_name[] =
"Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW)";
"Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz";
const char iwl9560_killer_1550i_name[] =
"Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)";
const char iwl9560_killer_1550s_name[] =

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2019-2020 Intel Corporation
* Copyright (C) 2019-2021 Intel Corporation
*/
#include <linux/uuid.h>
#include "iwl-drv.h"
@ -181,14 +181,13 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
/*
* We need at least two packages, one for the revision and one
* for the data itself. Also check that the revision is valid
* (i.e. it is an integer smaller than 2, as we currently support only
* 2 revisions).
* (i.e. it is an integer (each caller has to check by itself
* if the returned revision is supported)).
*/
if (data->type != ACPI_TYPE_PACKAGE ||
data->package.count < 2 ||
data->package.elements[0].type != ACPI_TYPE_INTEGER ||
data->package.elements[0].integer.value > 1) {
IWL_DEBUG_DEV_RADIO(dev, "Unsupported packages structure\n");
data->package.elements[0].type != ACPI_TYPE_INTEGER) {
IWL_DEBUG_DEV_RADIO(dev, "Invalid packages structure\n");
return ERR_PTR(-EINVAL);
}
@ -696,3 +695,70 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
return 0;
}
IWL_EXPORT_SYMBOL(iwl_sar_geo_init);
static u32 iwl_acpi_eval_dsm_func(struct device *dev, enum iwl_dsm_funcs_rev_0 eval_func)
{
union acpi_object *obj;
u32 ret;
obj = iwl_acpi_get_dsm_object(dev, 0,
eval_func, NULL,
&iwl_guid);
if (IS_ERR(obj)) {
IWL_DEBUG_DEV_RADIO(dev,
"ACPI: DSM func '%d': Got Error in obj = %ld\n",
eval_func,
PTR_ERR(obj));
return 0;
}
if (obj->type != ACPI_TYPE_INTEGER) {
IWL_DEBUG_DEV_RADIO(dev,
"ACPI: DSM func '%d' did not return a valid object, type=%d\n",
eval_func,
obj->type);
ret = 0;
goto out;
}
ret = obj->integer.value;
IWL_DEBUG_DEV_RADIO(dev,
"ACPI: DSM method evaluated: func='%d', ret=%d\n",
eval_func,
ret);
out:
ACPI_FREE(obj);
return ret;
}
__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
{
u32 ret;
__le32 config_bitmap = 0;
/*
** Evaluate func 'DSM_FUNC_ENABLE_INDONESIA_5G2'
*/
ret = iwl_acpi_eval_dsm_func(fwrt->dev, DSM_FUNC_ENABLE_INDONESIA_5G2);
if (ret == DSM_VALUE_INDONESIA_ENABLE)
config_bitmap |=
cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
/*
** Evaluate func 'DSM_FUNC_DISABLE_SRD'
*/
ret = iwl_acpi_eval_dsm_func(fwrt->dev, DSM_FUNC_DISABLE_SRD);
if (ret == DSM_VALUE_SRD_PASSIVE)
config_bitmap |=
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
else if (ret == DSM_VALUE_SRD_DISABLE)
config_bitmap |=
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
return config_bitmap;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_lari_config_bitmap);

View file

@ -53,8 +53,8 @@
#define ACPI_WGDS_TABLE_SIZE 3
#define ACPI_PPAG_WIFI_DATA_SIZE ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS) + 2)
#define ACPI_PPAG_WIFI_DATA_SIZE_V1 ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS_V1) + 2)
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS_V2) + 2)
@ -77,6 +77,7 @@ enum iwl_dsm_funcs_rev_0 {
DSM_FUNC_QUERY = 0,
DSM_FUNC_DISABLE_SRD = 1,
DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
DSM_FUNC_11AX_ENABLEMENT = 6,
};
enum iwl_dsm_values_srd {
@ -160,6 +161,8 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array,
int *block_list_size);
__le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
#else /* CONFIG_ACPI */
static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
@ -235,5 +238,11 @@ static inline int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
{
return -ENOENT;
}
static inline __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
{
return 0;
}
#endif /* CONFIG_ACPI */
#endif /* __iwl_fw_acpi__ */

View file

@ -147,6 +147,10 @@ enum iwl_tof_mcsi_enable {
* @IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL: retry on algorithm failure
* is valid
* @IWL_TOF_RESPONDER_CMD_VALID_STA_ID: station ID is valid
* @IWL_TOF_RESPONDER_CMD_VALID_NDP_SUPPORT: enable/disable NDP ranging support
* is valid
* @IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS: NDP parameters are valid
* @IWL_TOF_RESPONDER_CMD_VALID_LMR_FEEDBACK: LMR feedback support is valid
*/
enum iwl_tof_responder_cmd_valid_field {
IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO = BIT(0),
@ -162,6 +166,9 @@ enum iwl_tof_responder_cmd_valid_field {
IWL_TOF_RESPONDER_CMD_VALID_FAST_ALGO_SUPPORT = BIT(10),
IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL = BIT(11),
IWL_TOF_RESPONDER_CMD_VALID_STA_ID = BIT(12),
IWL_TOF_RESPONDER_CMD_VALID_NDP_SUPPORT = BIT(22),
IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS = BIT(23),
IWL_TOF_RESPONDER_CMD_VALID_LMR_FEEDBACK = BIT(24),
};
/**
@ -176,6 +183,9 @@ enum iwl_tof_responder_cmd_valid_field {
* @IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT: fast algorithm support
* @IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL: retry on algorithm fail
* @IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT: TX antenna mask
* @IWL_TOF_RESPONDER_FLAGS_NDP_SUPPORT: support NDP ranging
* @IWL_TOF_RESPONDER_FLAGS_LMR_FEEDBACK: request for LMR feedback if the
* initiator supports it
*/
enum iwl_tof_responder_cfg_flags {
IWL_TOF_RESPONDER_FLAGS_NON_ASAP_SUPPORT = BIT(0),
@ -188,6 +198,8 @@ enum iwl_tof_responder_cfg_flags {
IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT = BIT(9),
IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL = BIT(10),
IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_ABC_MSK,
IWL_TOF_RESPONDER_FLAGS_NDP_SUPPORT = BIT(24),
IWL_TOF_RESPONDER_FLAGS_LMR_FEEDBACK = BIT(25),
};
/**
@ -226,7 +238,7 @@ struct iwl_tof_responder_config_cmd_v6 {
} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */
/**
* struct iwl_tof_responder_config_cmd - ToF AP mode (for debug)
* struct iwl_tof_responder_config_cmd_v7 - ToF AP mode (for debug)
* @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
* @responder_cfg_flags: &iwl_tof_responder_cfg_flags
* @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
@ -245,7 +257,7 @@ struct iwl_tof_responder_config_cmd_v6 {
* @bssid: Current AP BSSID
* @reserved2: reserved
*/
struct iwl_tof_responder_config_cmd {
struct iwl_tof_responder_config_cmd_v7 {
__le32 cmd_valid_fields;
__le32 responder_cfg_flags;
u8 format_bw;
@ -259,7 +271,56 @@ struct iwl_tof_responder_config_cmd {
__le16 specific_calib;
u8 bssid[ETH_ALEN];
__le16 reserved2;
} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */
} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_7 */
#define IWL_RESPONDER_STS_POS 3
#define IWL_RESPONDER_TOTAL_LTF_POS 6
/**
* struct iwl_tof_responder_config_cmd_v8 - ToF AP mode (for debug)
* @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
* @responder_cfg_flags: &iwl_tof_responder_cfg_flags
* @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
* bits 4 - 7: &enum iwl_location_bw.
* @rate: current AP rate
* @channel_num: current AP Channel
* @ctrl_ch_position: coding of the control channel position relative to
* the center frequency, see iwl_mvm_get_ctrl_pos()
* @sta_id: index of the AP STA when in AP mode
* @reserved1: reserved
* @toa_offset: Artificial addition [pSec] for the ToA - to be used for debug
* purposes, simulating station movement by adding various values
* to this field
* @common_calib: XVT: common calibration value
* @specific_calib: XVT: specific calibration value
* @bssid: Current AP BSSID
* @r2i_ndp_params: parameters for R2I NDP.
* bits 0 - 2: max number of LTF repetitions
* bits 3 - 5: max number of spatial streams (supported values are < 2)
* bits 6 - 7: max number of total LTFs
* (&enum ieee80211_range_params_max_total_ltf)
* @i2r_ndp_params: parameters for I2R NDP.
* bits 0 - 2: max number of LTF repetitions
* bits 3 - 5: max number of spatial streams
* bits 6 - 7: max number of total LTFs
* (&enum ieee80211_range_params_max_total_ltf)
*/
struct iwl_tof_responder_config_cmd_v8 {
__le32 cmd_valid_fields;
__le32 responder_cfg_flags;
u8 format_bw;
u8 rate;
u8 channel_num;
u8 ctrl_ch_position;
u8 sta_id;
u8 reserved1;
__le16 toa_offset;
__le16 common_calib;
__le16 specific_calib;
u8 bssid[ETH_ALEN];
u8 r2i_ndp_params;
u8 i2r_ndp_params;
} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_8 */
#define IWL_LCI_CIVIC_IE_MAX_SIZE 400
@ -422,10 +483,12 @@ struct iwl_tof_range_req_ap_entry_v2 {
* driver.
* @IWL_INITIATOR_AP_FLAGS_NON_TB: Use non trigger based flow
* @IWL_INITIATOR_AP_FLAGS_TB: Use trigger based flow
* @IWL_INITIATOR_AP_FLAGS_SECURED: request secured measurement
* @IWL_INITIATOR_AP_FLAGS_SECURED: request secure LTF measurement
* @IWL_INITIATOR_AP_FLAGS_LMR_FEEDBACK: Send LMR feedback
* @IWL_INITIATOR_AP_FLAGS_USE_CALIB: Use calibration values from the request
* instead of fw internal values.
* @IWL_INITIATOR_AP_FLAGS_PMF: request to protect the negotiation and LMR
* frames with protected management frames.
*/
enum iwl_initiator_ap_flags {
IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1),
@ -440,6 +503,7 @@ enum iwl_initiator_ap_flags {
IWL_INITIATOR_AP_FLAGS_SECURED = BIT(11),
IWL_INITIATOR_AP_FLAGS_LMR_FEEDBACK = BIT(12),
IWL_INITIATOR_AP_FLAGS_USE_CALIB = BIT(13),
IWL_INITIATOR_AP_FLAGS_PMF = BIT(14),
};
/**
@ -657,6 +721,79 @@ struct iwl_tof_range_req_ap_entry_v7 {
u8 tx_pn[IEEE80211_CCMP_PN_LEN];
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_7 */
#define IWL_LOCATION_MAX_STS_POS 3
/**
* struct iwl_tof_range_req_ap_entry_v8 - AP configuration parameters
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
* @channel_num: AP Channel number
* @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
* bits 4 - 7: &enum iwl_location_bw.
* @ctrl_ch_position: Coding of the control channel position relative to the
* center frequency, see iwl_mvm_get_ctrl_pos().
* @ftmr_max_retries: Max number of retries to send the FTMR in case of no
* reply from the AP.
* @bssid: AP's BSSID
* @burst_period: Recommended value to be sent to the AP. Measurement
* periodicity In units of 100ms. ignored if num_of_bursts_exp = 0
* @samples_per_burst: the number of FTMs pairs in single Burst (1-31);
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
* the number of measurement iterations (min 2^0 = 1, max 2^14)
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
* otherwise should be set to &IWL_MVM_INVALID_STA.
* @cipher: pairwise cipher suite for secured measurement.
* &enum iwl_location_cipher.
* @hltk: HLTK to be used for secured 11az measurement
* @tk: TK to be used for secured 11az measurement
* @calib: An array of calibration values per FTM rx bandwidth.
* If &IWL_INITIATOR_AP_FLAGS_USE_CALIB is set, the fw will use the
* calibration value that corresponds to the rx bandwidth of the FTM
* frame.
* @beacon_interval: beacon interval of the AP in TUs. Only required if
* &IWL_INITIATOR_AP_FLAGS_TB is set.
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
* is set to &IWL_MVM_INVALID_STA.
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
* is set to &IWL_MVM_INVALID_STA.
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
* bits 0 - 2: max LTF repetitions
* bits 3 - 5: max number of spatial streams
* bits 6 - 7: reserved
* @i2r_ndp_params: parameters for I2R NDP ranging negotiation.
* bits 0 - 2: max LTF repetitions
* bits 3 - 5: max number of spatial streams (supported values are < 2)
* bits 6 - 7: reserved
* @r2i_max_total_ltf: R2I Max Total LTFs for NDP ranging negotiation.
* One of &enum ieee80211_range_params_max_total_ltf.
* @i2r_max_total_ltf: I2R Max Total LTFs for NDP ranging negotiation.
* One of &enum ieee80211_range_params_max_total_ltf.
*/
struct iwl_tof_range_req_ap_entry_v8 {
__le32 initiator_ap_flags;
u8 channel_num;
u8 format_bw;
u8 ctrl_ch_position;
u8 ftmr_max_retries;
u8 bssid[ETH_ALEN];
__le16 burst_period;
u8 samples_per_burst;
u8 num_of_bursts;
u8 sta_id;
u8 cipher;
u8 hltk[HLTK_11AZ_LEN];
u8 tk[TK_11AZ_LEN];
__le16 calib[IWL_TOF_BW_NUM];
__le16 beacon_interval;
u8 rx_pn[IEEE80211_CCMP_PN_LEN];
u8 tx_pn[IEEE80211_CCMP_PN_LEN];
u8 r2i_ndp_params;
u8 i2r_ndp_params;
u8 r2i_max_total_ltf;
u8 i2r_max_total_ltf;
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_8 */
/**
* enum iwl_tof_response_mode
* @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as
@ -878,6 +1015,34 @@ struct iwl_tof_range_req_cmd_v11 {
struct iwl_tof_range_req_ap_entry_v7 ap[IWL_MVM_TOF_MAX_APS];
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_11 */
/**
* struct iwl_tof_range_req_cmd_v12 - start measurement cmd
* @initiator_flags: see flags @ iwl_tof_initiator_flags
* @request_id: A Token incremented per request. The same Token will be
* sent back in the range response
* @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
* @range_req_bssid: ranging request BSSID
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
* Bits set to 1 shall be randomized by the UMAC
* @macaddr_template: MAC address template to use for non-randomized bits
* @req_timeout_ms: Requested timeout of the response in units of milliseconds.
* This is the session time for completing the measurement.
* @tsf_mac_id: report the measurement start time for each ap in terms of the
* TSF of this mac id. 0xff to disable TSF reporting.
* @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2.
*/
struct iwl_tof_range_req_cmd_v12 {
__le32 initiator_flags;
u8 request_id;
u8 num_of_ap;
u8 range_req_bssid[ETH_ALEN];
u8 macaddr_mask[ETH_ALEN];
u8 macaddr_template[ETH_ALEN];
__le32 req_timeout_ms;
__le32 tsf_mac_id;
struct iwl_tof_range_req_ap_entry_v8 ap[IWL_MVM_TOF_MAX_APS];
} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_12 */
/*
* enum iwl_tof_range_request_status - status of the sent request
* @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the

View file

@ -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-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -414,6 +414,9 @@ enum iwl_lari_config_masks {
LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK = BIT(3),
};
#define IWL_11AX_UKRAINE_MASK 3
#define IWL_11AX_UKRAINE_SHIFT 8
/**
* struct iwl_lari_config_change_cmd_v1 - change LARI configuration
* @config_bitmap: bit map of the config commands. each bit will trigger a
@ -434,6 +437,21 @@ struct iwl_lari_config_change_cmd_v2 {
__le32 oem_uhb_allow_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_2 */
/**
* struct iwl_lari_config_change_cmd_v3 - change LARI configuration
* @config_bitmap: bit map of the config commands. each bit will trigger a
* different predefined FW config operation
* @oem_uhb_allow_bitmap: bitmap of UHB enabled MCC sets
* @oem_11ax_allow_bitmap: bitmap of 11ax allowed MCCs.
* For each supported country, a pair of regulatory override bit and 11ax mode exist
* in the bit field.
*/
struct iwl_lari_config_change_cmd_v3 {
__le32 config_bitmap;
__le32 oem_uhb_allow_bitmap;
__le32 oem_11ax_allow_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_3 */
/**
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
* @status: PNVM image loading status

View file

@ -274,7 +274,7 @@ enum iwl_dev_tx_power_cmd_mode {
#define IWL_NUM_CHAIN_TABLES 1
#define IWL_NUM_CHAIN_TABLES_V2 2
#define IWL_NUM_CHAIN_LIMITS 2
#define IWL_NUM_SUB_BANDS 5
#define IWL_NUM_SUB_BANDS_V1 5
#define IWL_NUM_SUB_BANDS_V2 11
/**
@ -300,7 +300,7 @@ struct iwl_dev_tx_power_common {
* @per_chain: per chain restrictions
*/
struct iwl_dev_tx_power_cmd_v3 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
} __packed; /* TX_REDUCED_POWER_API_S_VER_3 */
#define IWL_DEV_MAX_TX_POWER 0x7FFF
@ -313,7 +313,7 @@ struct iwl_dev_tx_power_cmd_v3 {
* @reserved: reserved (padding)
*/
struct iwl_dev_tx_power_cmd_v4 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
u8 enable_ack_reduction;
u8 reserved[3];
} __packed; /* TX_REDUCED_POWER_API_S_VER_4 */
@ -332,7 +332,7 @@ struct iwl_dev_tx_power_cmd_v4 {
* BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
*/
struct iwl_dev_tx_power_cmd_v5 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
__le16 per_chain[IWL_NUM_CHAIN_TABLES][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
u8 enable_ack_reduction;
u8 per_chain_restriction_changed;
u8 reserved[2];
@ -454,21 +454,23 @@ struct iwl_geo_tx_power_profiles_resp {
/**
* union iwl_ppag_table_cmd - union for all versions of PPAG command
* @v1: version 1, table revision = 0
* @v2: version 2, table revision = 1
* @v1: version 1
* @v2: version 2
*
* @enabled: 1 if PPAG is enabled, 0 otherwise
* @flags: bit 0 - indicates enablement of PPAG for ETSI
* bit 1 - indicates enablement of PPAG for CHINA BIOS
* bit 1 can be used only in v3 (identical to v2)
* @gain: table of antenna gain values per chain and sub-band
* @reserved: reserved
*/
union iwl_ppag_table_cmd {
struct {
__le32 enabled;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
s8 reserved[2];
} v1;
struct {
__le32 enabled;
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
} v2;

View file

@ -779,36 +779,6 @@ struct iwl_rxq_sync_notification {
u8 payload[];
} __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */
/**
* enum iwl_mvm_rxq_notif_type - Internal message identifier
*
* @IWL_MVM_RXQ_EMPTY: empty sync notification
* @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
* @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
*/
enum iwl_mvm_rxq_notif_type {
IWL_MVM_RXQ_EMPTY,
IWL_MVM_RXQ_NOTIF_DEL_BA,
IWL_MVM_RXQ_NSSN_SYNC,
};
/**
* struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent
* in &iwl_rxq_sync_cmd. Should be DWORD aligned.
* FW is agnostic to the payload, so there are no endianity requirements.
*
* @type: value from &iwl_mvm_rxq_notif_type
* @sync: ctrl path is waiting for all notifications to be received
* @cookie: internal cookie to identify old notifications
* @data: payload
*/
struct iwl_mvm_internal_rxq_notif {
u16 type;
u16 sync;
u32 cookie;
u8 data[];
} __packed;
/**
* enum iwl_mvm_pm_event - type of station PM event
* @IWL_MVM_PM_EVENT_AWAKE: station woke up

View file

@ -634,6 +634,12 @@ enum iwl_umac_scan_general_flags2 {
* @IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN: at the end of 2.4GHz and
* 5.2Ghz bands scan, trigger scan on 6GHz band to discover
* the reported collocated APs
* @IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN: at the end of 2.4GHz and 5GHz
* bands scan, if not APs were discovered, allow scan to conitnue and scan
* 6GHz PSC channels in order to discover country information.
* @IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN_FILTER_IN: in case
* &IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN is enabled and scan is
* activated over 6GHz PSC channels, filter in beacons and probe responses.
*/
enum iwl_umac_scan_general_flags_v2 {
IWL_UMAC_SCAN_GEN_FLAGS_V2_PERIODIC = BIT(0),
@ -649,6 +655,8 @@ enum iwl_umac_scan_general_flags_v2 {
IWL_UMAC_SCAN_GEN_FLAGS_V2_MULTI_SSID = BIT(10),
IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE = BIT(11),
IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN = BIT(12),
IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN = BIT(13),
IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN_FILTER_IN = BIT(14),
};
/**

View file

@ -2559,7 +2559,9 @@ int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
fwrt->dump.wks[idx].dump_data = *dump_data;
IWL_WARN(fwrt, "WRT: Collecting data: ini trigger %d fired.\n", tp_id);
IWL_WARN(fwrt,
"WRT: Collecting data: ini trigger %d fired (delay=%dms).\n",
tp_id, (u32)(delay / USEC_PER_MSEC));
schedule_delayed_work(&fwrt->dump.wks[idx].wk, usecs_to_jiffies(delay));

View file

@ -362,6 +362,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_PROTECTED_TWT: Supports protection of TWT action frames
* @IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE: Supports the firmware handshake in
* reset flow
* @IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN: Support for passive scan on 6GHz PSC
* channels even when these are not enabled.
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
@ -408,6 +410,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD = (__force iwl_ucode_tlv_capa_t)54,
IWL_UCODE_TLV_CAPA_PROTECTED_TWT = (__force iwl_ucode_tlv_capa_t)56,
IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE = (__force iwl_ucode_tlv_capa_t)57,
IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)58,
/* set 2 */
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@ -116,6 +116,9 @@ struct fw_img {
#define PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS 0
#define PAGING_TLV_SECURE_MASK 1
/* FW MSB Mask for regions/cache_control */
#define FW_ADDR_CACHE_CONTROL 0xC0000000UL
/**
* struct iwl_fw_paging
* @fw_paging_phys: page phy pointer

View file

@ -10,6 +10,8 @@
#include "fw/api/soc.h"
#include "fw/api/commands.h"
#include "fw/api/rx.h"
#include "fw/api/datapath.h"
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
const struct iwl_fw *fw,
@ -95,3 +97,60 @@ int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt)
return ret;
}
IWL_EXPORT_SYMBOL(iwl_set_soc_latency);
int iwl_configure_rxq(struct iwl_fw_runtime *fwrt)
{
int i, num_queues, size, ret;
struct iwl_rfh_queue_config *cmd;
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD),
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
/*
* The default queue is configured via context info, so if we
* have a single queue, there's nothing to do here.
*/
if (fwrt->trans->num_rx_queues == 1)
return 0;
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22000)
return 0;
/* skip the default queue */
num_queues = fwrt->trans->num_rx_queues - 1;
size = struct_size(cmd, data, num_queues);
cmd = kzalloc(size, GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->num_queues = num_queues;
for (i = 0; i < num_queues; i++) {
struct iwl_trans_rxq_dma_data data;
cmd->data[i].q_num = i + 1;
iwl_trans_get_rxq_dma_data(fwrt->trans, i + 1, &data);
cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb);
cmd->data[i].urbd_stts_wrptr =
cpu_to_le64(data.urbd_stts_wrptr);
cmd->data[i].ur_bd_cb = cpu_to_le64(data.ur_bd_cb);
cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid);
}
hcmd.data[0] = cmd;
hcmd.len[0] = size;
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
kfree(cmd);
if (ret)
IWL_ERR(fwrt, "Failed to configure RX queues: %d\n", ret);
return ret;
}
IWL_EXPORT_SYMBOL(iwl_configure_rxq);

View file

@ -190,5 +190,6 @@ void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt);
void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt);
int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt);
int iwl_configure_rxq(struct iwl_fw_runtime *fwrt);
#endif /* __iwl_fw_runtime_h__ */

View file

@ -416,6 +416,7 @@ struct iwl_cfg {
#define IWL_CFG_MAC_TYPE_SNJ 0x42
#define IWL_CFG_MAC_TYPE_SOF 0x43
#define IWL_CFG_MAC_TYPE_MA 0x44
#define IWL_CFG_MAC_TYPE_BZ 0x46
#define IWL_CFG_RF_TYPE_TH 0x105
#define IWL_CFG_RF_TYPE_TH1 0x108
@ -477,6 +478,7 @@ extern const struct iwl_cfg_trans_params iwl_snj_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg;
extern const char iwl9162_name[];
extern const char iwl9260_name[];
extern const char iwl9260_1_name[];
@ -501,8 +503,10 @@ extern const char iwl_ax200_killer_1650w_name[];
extern const char iwl_ax200_killer_1650x_name[];
extern const char iwl_ax201_killer_1650s_name[];
extern const char iwl_ax201_killer_1650i_name[];
extern const char iwl_ma_name[];
extern const char iwl_ax210_killer_1675w_name[];
extern const char iwl_ax210_killer_1675x_name[];
extern const char iwl_ax211_name[];
extern const char iwl_ax221_name[];
extern const char iwl_ax411_name[];
#if IS_ENABLED(CONFIG_IWLDVM)
extern const struct iwl_cfg iwl5300_agn_cfg;
@ -594,7 +598,7 @@ extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg killer1650x_2ax_cfg;
extern const struct iwl_cfg killer1650w_2ax_cfg;
extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0;
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long;
@ -612,6 +616,10 @@ extern const struct iwl_cfg iwl_cfg_ma_a0_mr_a0;
extern const struct iwl_cfg iwl_cfg_snj_a0_mr_a0;
extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0;
extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0;
extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0;
extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0;
extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
#endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */

View file

@ -578,6 +578,9 @@ enum msix_fh_int_causes {
MSIX_FH_INT_CAUSES_FH_ERR = BIT(21),
};
/* The low 16 bits are for rx data queue indication */
#define MSIX_FH_INT_CAUSES_DATA_QUEUE 0xffff
/*
* Causes for the HW register interrupts
*/

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2018-2020 Intel Corporation
* Copyright (C) 2018-2021 Intel Corporation
*/
#include <linux/firmware.h>
#include "iwl-drv.h"
@ -426,7 +426,8 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
const struct firmware *fw;
int res;
if (!iwlwifi_mod_params.enable_ini)
if (!iwlwifi_mod_params.enable_ini ||
trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_9000)
return;
res = firmware_request_nowarn(&fw, "iwl-debug-yoyo.bin", dev);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -550,8 +550,6 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
return 0;
}
#define FW_ADDR_CACHE_CONTROL 0xC0000000
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces,

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
@ -176,6 +176,8 @@ iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, bool state)
static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,
struct sk_buff *skb)
{
if (WARN_ON_ONCE(!op_mode))
return;
op_mode->ops->free_skb(op_mode, skb);
}

View file

@ -2,7 +2,7 @@
/*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2019-2020 Intel Corporation
* Copyright (C) 2019-2021 Intel Corporation
*/
#include <linux/kernel.h>
#include <linux/bsearch.h>
@ -21,7 +21,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
const struct iwl_cfg_trans_params *cfg_trans)
{
struct iwl_trans *trans;
int txcmd_size, txcmd_align;
#ifdef CONFIG_LOCKDEP
static struct lock_class_key __key;
#endif
@ -31,23 +30,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
return NULL;
trans->trans_cfg = cfg_trans;
if (!cfg_trans->gen2) {
txcmd_size = sizeof(struct iwl_tx_cmd);
txcmd_align = sizeof(void *);
} else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) {
txcmd_size = sizeof(struct iwl_tx_cmd_gen2);
txcmd_align = 64;
} else {
txcmd_size = sizeof(struct iwl_tx_cmd_gen3);
txcmd_align = 128;
}
txcmd_size += sizeof(struct iwl_cmd_header);
txcmd_size += 36; /* biggest possible 802.11 header */
/* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align))
return ERR_PTR(-EINVAL);
#ifdef CONFIG_LOCKDEP
lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
@ -58,22 +40,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
trans->ops = ops;
trans->num_rx_queues = 1;
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl);
else
trans->txqs.bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl);
/*
* For gen2 devices, we use a single allocation for each byte-count
* table, but they're pretty small (1k) so use a DMA pool that we
* allocate here.
*/
if (trans->trans_cfg->gen2) {
trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", dev,
trans->txqs.bc_tbl_size,
256, 0);
if (!trans->txqs.bc_pool)
return NULL;
}
WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
if (trans->trans_cfg->use_tfh) {
trans->txqs.tfd.addr_size = 64;
@ -86,6 +53,52 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
}
trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans);
return trans;
}
int iwl_trans_init(struct iwl_trans *trans)
{
int txcmd_size, txcmd_align;
if (!trans->trans_cfg->gen2) {
txcmd_size = sizeof(struct iwl_tx_cmd);
txcmd_align = sizeof(void *);
} else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
txcmd_size = sizeof(struct iwl_tx_cmd_gen2);
txcmd_align = 64;
} else {
txcmd_size = sizeof(struct iwl_tx_cmd_gen3);
txcmd_align = 128;
}
txcmd_size += sizeof(struct iwl_cmd_header);
txcmd_size += 36; /* biggest possible 802.11 header */
/* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align))
return -EINVAL;
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl);
else
trans->txqs.bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl);
/*
* For gen2 devices, we use a single allocation for each byte-count
* table, but they're pretty small (1k) so use a DMA pool that we
* allocate here.
*/
if (trans->trans_cfg->gen2) {
trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", trans->dev,
trans->txqs.bc_tbl_size,
256, 0);
if (!trans->txqs.bc_pool)
return -ENOMEM;
}
/* Some things must not change even if the config does */
WARN_ON(trans->txqs.tfd.addr_size !=
(trans->trans_cfg->use_tfh ? 64 : 36));
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
"iwl_cmd_pool:%s", dev_name(trans->dev));
trans->dev_cmd_pool =
@ -93,36 +106,36 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
txcmd_size, txcmd_align,
SLAB_HWCACHE_ALIGN, NULL);
if (!trans->dev_cmd_pool)
return NULL;
WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
return -ENOMEM;
trans->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page);
if (!trans->txqs.tso_hdr_page) {
kmem_cache_destroy(trans->dev_cmd_pool);
return NULL;
return -ENOMEM;
}
/* Initialize the wait queue for commands */
init_waitqueue_head(&trans->wait_command_queue);
return trans;
return 0;
}
void iwl_trans_free(struct iwl_trans *trans)
{
int i;
for_each_possible_cpu(i) {
struct iwl_tso_hdr_page *p =
per_cpu_ptr(trans->txqs.tso_hdr_page, i);
if (trans->txqs.tso_hdr_page) {
for_each_possible_cpu(i) {
struct iwl_tso_hdr_page *p =
per_cpu_ptr(trans->txqs.tso_hdr_page, i);
if (p->page)
__free_page(p->page);
if (p && p->page)
__free_page(p->page);
}
free_percpu(trans->txqs.tso_hdr_page);
}
free_percpu(trans->txqs.tso_hdr_page);
kmem_cache_destroy(trans->dev_cmd_pool);
}

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -1267,7 +1267,8 @@ static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans,
if (WARN_ON_ONCE(!trans->ops->wait_tx_queues_empty))
return -ENOTSUPP;
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
/* No need to wait if the firmware is not alive */
if (trans->state != IWL_TRANS_FW_ALIVE) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
}
@ -1438,6 +1439,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
struct device *dev,
const struct iwl_trans_ops *ops,
const struct iwl_cfg_trans_params *cfg_trans);
int iwl_trans_init(struct iwl_trans *trans);
void iwl_trans_free(struct iwl_trans *trans);
/*****************************************************

View file

@ -93,6 +93,15 @@
#define IWL_MVM_ENABLE_EBS 1
#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE
#define IWL_MVM_FTM_INITIATOR_DYNACK true
#define IWL_MVM_FTM_R2I_MAX_REP 7
#define IWL_MVM_FTM_I2R_MAX_REP 7
#define IWL_MVM_FTM_R2I_MAX_STS 1
#define IWL_MVM_FTM_I2R_MAX_STS 1
#define IWL_MVM_FTM_R2I_MAX_TOTAL_LTF 3
#define IWL_MVM_FTM_I2R_MAX_TOTAL_LTF 3
#define IWL_MVM_FTM_INITIATOR_SECURE_LTF false
#define IWL_MVM_FTM_RESP_NDP_SUPPORT true
#define IWL_MVM_FTM_RESP_LMR_FEEDBACK_SUPPORT true
#define IWL_MVM_D3_DEBUG false
#define IWL_MVM_USE_TWT true
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10
@ -108,5 +117,7 @@
#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016
#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2
#define IWL_MVM_DISABLE_AP_FILS false
#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */
#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */
#endif /* __MVM_CONSTANTS_H */

View file

@ -2028,6 +2028,8 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
mutex_lock(&mvm->mutex);
mvm->last_reset_or_resume_time_jiffies = jiffies;
/* get the BSS vif pointer again */
vif = iwl_mvm_get_bss_vif(mvm);
if (IS_ERR_OR_NULL(vif))

View file

@ -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-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -1210,10 +1210,10 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
return -EINVAL;
rcu_read_lock();
mutex_lock(&mvm->mutex);
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true);
vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
if (!vif)
continue;
@ -1253,18 +1253,16 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
&beacon_cmd.tim_size,
beacon->data, beacon->len);
mutex_lock(&mvm->mutex);
iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
sizeof(beacon_cmd));
mutex_unlock(&mvm->mutex);
dev_kfree_skb(beacon);
rcu_read_unlock();
return 0;
out_err:
rcu_read_unlock();
mutex_unlock(&mvm->mutex);
return -EINVAL;
}

View file

@ -490,6 +490,15 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (vif->bss_conf.assoc &&
!memcmp(peer->addr, vif->bss_conf.bssid, ETH_ALEN)) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_sta *sta;
rcu_read_lock();
sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]);
if (sta->mfp)
FTM_PUT_FLAG(PMF);
rcu_read_unlock();
target->sta_id = mvmvif->ap_sta_id;
} else {
@ -684,6 +693,19 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
}
static int
iwl_mvm_ftm_put_target_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request_peer *peer,
struct iwl_tof_range_req_ap_entry_v7 *target)
{
int err = iwl_mvm_ftm_put_target(mvm, vif, peer, (void *)target);
if (err)
return err;
iwl_mvm_ftm_set_secured_ranging(mvm, vif, target);
return err;
}
static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *req)
@ -704,11 +726,67 @@ static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm,
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
struct iwl_tof_range_req_ap_entry_v7 *target = &cmd.ap[i];
err = iwl_mvm_ftm_put_target(mvm, vif, peer, (void *)target);
err = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, target);
if (err)
return err;
}
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
}
static void
iwl_mvm_ftm_set_ndp_params(struct iwl_mvm *mvm,
struct iwl_tof_range_req_ap_entry_v8 *target)
{
/* Only 2 STS are supported on Tx */
u32 i2r_max_sts = IWL_MVM_FTM_I2R_MAX_STS > 1 ? 1 :
IWL_MVM_FTM_I2R_MAX_STS;
target->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP |
(IWL_MVM_FTM_R2I_MAX_STS << IWL_LOCATION_MAX_STS_POS);
target->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP |
(i2r_max_sts << IWL_LOCATION_MAX_STS_POS);
target->r2i_max_total_ltf = IWL_MVM_FTM_R2I_MAX_TOTAL_LTF;
target->i2r_max_total_ltf = IWL_MVM_FTM_I2R_MAX_TOTAL_LTF;
}
static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *req)
{
struct iwl_tof_range_req_cmd_v12 cmd;
struct iwl_host_cmd hcmd = {
.id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0),
.dataflags[0] = IWL_HCMD_DFL_DUP,
.data[0] = &cmd,
.len[0] = sizeof(cmd),
};
u8 i;
int err;
iwl_mvm_ftm_cmd_common(mvm, vif, (void *)&cmd, req);
for (i = 0; i < cmd.num_of_ap; i++) {
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
struct iwl_tof_range_req_ap_entry_v8 *target = &cmd.ap[i];
u32 flags;
err = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, (void *)target);
if (err)
return err;
iwl_mvm_ftm_set_secured_ranging(mvm, vif, target);
iwl_mvm_ftm_set_ndp_params(mvm, target);
/*
* If secure LTF is turned off, replace the flag with PMF only
*/
flags = le32_to_cpu(target->initiator_ap_flags);
if ((flags & IWL_INITIATOR_AP_FLAGS_SECURED) &&
!IWL_MVM_FTM_INITIATOR_SECURE_LTF) {
flags &= ~IWL_INITIATOR_AP_FLAGS_SECURED;
flags |= IWL_INITIATOR_AP_FLAGS_PMF;
target->initiator_ap_flags = cpu_to_le32(flags);
}
}
return iwl_mvm_ftm_send_cmd(mvm, &hcmd);
@ -732,6 +810,9 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_FW_CMD_VER_UNKNOWN);
switch (cmd_ver) {
case 12:
err = iwl_mvm_ftm_start_v12(mvm, vif, req);
break;
case 11:
err = iwl_mvm_ftm_start_v11(mvm, vif, req);
break;

View file

@ -75,6 +75,24 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
return 0;
}
static void
iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm,
struct iwl_tof_responder_config_cmd_v8 *cmd)
{
/* Up to 2 R2I STS are allowed on the responder */
u32 r2i_max_sts = IWL_MVM_FTM_R2I_MAX_STS < 2 ?
IWL_MVM_FTM_R2I_MAX_STS : 1;
cmd->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP |
(r2i_max_sts << IWL_RESPONDER_STS_POS) |
(IWL_MVM_FTM_R2I_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS);
cmd->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP |
(IWL_MVM_FTM_I2R_MAX_STS << IWL_RESPONDER_STS_POS) |
(IWL_MVM_FTM_I2R_MAX_TOTAL_LTF << IWL_RESPONDER_TOTAL_LTF_POS);
cmd->cmd_valid_fields |=
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_NDP_PARAMS);
}
static int
iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@ -82,11 +100,11 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
/*
* The command structure is the same for versions 6 and 7, (only the
* The command structure is the same for versions 6, 7 and 8 (only the
* field interpretation is different), so the same struct can be use
* for all cases.
*/
struct iwl_tof_responder_config_cmd cmd = {
struct iwl_tof_responder_config_cmd_v8 cmd = {
.channel_num = chandef->chan->hw_value,
.cmd_valid_fields =
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
@ -100,7 +118,10 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
if (cmd_ver == 7)
if (cmd_ver == 8)
iwl_mvm_ftm_responder_set_ndp(mvm, &cmd);
if (cmd_ver >= 7)
err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw,
&cmd.ctrl_ch_position);
else

View file

@ -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-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -29,6 +29,9 @@
#define UCODE_VALID_OK cpu_to_le32(0x1)
#define IWL_PPAG_MASK 3
#define IWL_PPAG_ETSI_MASK BIT(0)
struct iwl_mvm_alive_data {
bool valid;
u32 scd_base_addr;
@ -70,56 +73,6 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
}
static int iwl_configure_rxq(struct iwl_mvm *mvm)
{
int i, num_queues, size, ret;
struct iwl_rfh_queue_config *cmd;
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD),
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
/*
* The default queue is configured via context info, so if we
* have a single queue, there's nothing to do here.
*/
if (mvm->trans->num_rx_queues == 1)
return 0;
/* skip the default queue */
num_queues = mvm->trans->num_rx_queues - 1;
size = struct_size(cmd, data, num_queues);
cmd = kzalloc(size, GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->num_queues = num_queues;
for (i = 0; i < num_queues; i++) {
struct iwl_trans_rxq_dma_data data;
cmd->data[i].q_num = i + 1;
iwl_trans_get_rxq_dma_data(mvm->trans, i + 1, &data);
cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb);
cmd->data[i].urbd_stts_wrptr =
cpu_to_le64(data.urbd_stts_wrptr);
cmd->data[i].ur_bd_cb = cpu_to_le64(data.ur_bd_cb);
cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid);
}
hcmd.data[0] = cmd;
hcmd.len[0] = size;
ret = iwl_mvm_send_cmd(mvm, &hcmd);
kfree(cmd);
return ret;
}
static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm)
{
struct iwl_dqa_enable_cmd dqa_cmd = {
@ -233,7 +186,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
mvm->trans->dbg.lmac_error_event_table[1] =
le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr);
umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr) &
~FW_ADDR_CACHE_CONTROL;
if (umac_error_table) {
if (umac_error_table >=
@ -773,16 +727,16 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
} else if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_REDUCE_TX_POWER)) {
len = sizeof(cmd.v5);
n_subbands = IWL_NUM_SUB_BANDS;
n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = cmd.v5.per_chain[0][0];
} else if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_TX_POWER_ACK)) {
len = sizeof(cmd.v4);
n_subbands = IWL_NUM_SUB_BANDS;
n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = cmd.v4.per_chain[0][0];
} else {
len = sizeof(cmd.v3);
n_subbands = IWL_NUM_SUB_BANDS;
n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = cmd.v3.per_chain[0][0];
}
@ -909,46 +863,50 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg, *data, *enabled;
union acpi_object *wifi_pkg, *data, *flags;
int i, j, ret, tbl_rev, num_sub_bands;
int idx = 2;
s8 *gain;
/*
* The 'enabled' field is the same in v1 and v2 so we can just
* The 'flags' field is the same in v1 and in v2 so we can just
* use v1 to access it.
*/
mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0);
data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
/* try to read ppag table revision 1 */
/* try to read ppag table rev 2 or 1 (both have the same data size) */
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
if (!IS_ERR(wifi_pkg)) {
if (tbl_rev != 1) {
if (tbl_rev == 1 || tbl_rev == 2) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = mvm->fwrt.ppag_table.v2.gain[0];
mvm->fwrt.ppag_ver = tbl_rev;
IWL_DEBUG_RADIO(mvm,
"Reading PPAG table v2 (tbl_rev=%d)\n",
tbl_rev);
goto read_table;
} else {
ret = -EINVAL;
goto out_free;
}
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = mvm->fwrt.ppag_table.v2.gain[0];
mvm->fwrt.ppag_ver = 2;
IWL_DEBUG_RADIO(mvm, "Reading PPAG table v2 (tbl_rev=1)\n");
goto read_table;
}
/* try to read ppag table revision 0 */
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev);
ACPI_PPAG_WIFI_DATA_SIZE_V1, &tbl_rev);
if (!IS_ERR(wifi_pkg)) {
if (tbl_rev != 0) {
ret = -EINVAL;
goto out_free;
}
num_sub_bands = IWL_NUM_SUB_BANDS;
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = mvm->fwrt.ppag_table.v1.gain[0];
mvm->fwrt.ppag_ver = 1;
mvm->fwrt.ppag_ver = 0;
IWL_DEBUG_RADIO(mvm, "Reading PPAG table v1 (tbl_rev=0)\n");
goto read_table;
}
@ -956,15 +914,17 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
goto out_free;
read_table:
enabled = &wifi_pkg->package.elements[1];
if (enabled->type != ACPI_TYPE_INTEGER ||
(enabled->integer.value != 0 && enabled->integer.value != 1)) {
flags = &wifi_pkg->package.elements[1];
if (flags->type != ACPI_TYPE_INTEGER) {
ret = -EINVAL;
goto out_free;
}
mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(enabled->integer.value);
if (!mvm->fwrt.ppag_table.v1.enabled) {
mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(flags->integer.value &
IWL_PPAG_MASK);
if (!mvm->fwrt.ppag_table.v1.flags) {
ret = 0;
goto out_free;
}
@ -992,12 +952,13 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
(j != 0 &&
(gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_HB ||
gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_HB))) {
mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0);
ret = -EINVAL;
goto out_free;
}
}
}
ret = 0;
out_free:
kfree(data);
@ -1015,7 +976,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
"PPAG capability not supported by FW, command not sent.\n");
return 0;
}
if (!mvm->fwrt.ppag_table.v1.enabled) {
if (!mvm->fwrt.ppag_table.v1.flags) {
IWL_DEBUG_RADIO(mvm, "PPAG not enabled, command not sent.\n");
return 0;
}
@ -1024,20 +985,28 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
PER_PLATFORM_ANT_GAIN_CMD,
IWL_FW_CMD_VER_UNKNOWN);
if (cmd_ver == 1) {
num_sub_bands = IWL_NUM_SUB_BANDS;
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = mvm->fwrt.ppag_table.v1.gain[0];
cmd_size = sizeof(mvm->fwrt.ppag_table.v1);
if (mvm->fwrt.ppag_ver == 2) {
if (mvm->fwrt.ppag_ver == 1 || mvm->fwrt.ppag_ver == 2) {
IWL_DEBUG_RADIO(mvm,
"PPAG table is v2 but FW supports v1, sending truncated table\n");
"PPAG table rev is %d but FW supports v1, sending truncated table\n",
mvm->fwrt.ppag_ver);
mvm->fwrt.ppag_table.v1.flags &=
cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
} else if (cmd_ver == 2) {
} else if (cmd_ver == 2 || cmd_ver == 3) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = mvm->fwrt.ppag_table.v2.gain[0];
cmd_size = sizeof(mvm->fwrt.ppag_table.v2);
if (mvm->fwrt.ppag_ver == 1) {
if (mvm->fwrt.ppag_ver == 0) {
IWL_DEBUG_RADIO(mvm,
"PPAG table is v1 but FW supports v2, sending padded table\n");
} else if (cmd_ver == 2 && mvm->fwrt.ppag_ver == 2) {
IWL_DEBUG_RADIO(mvm,
"PPAG table is v3 but FW supports v2, sending partial bitmap.\n");
mvm->fwrt.ppag_table.v1.flags &=
cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
} else {
IWL_DEBUG_RADIO(mvm, "Unsupported PPAG command version\n");
@ -1102,7 +1071,7 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
IWL_DEBUG_RADIO(mvm,
"System vendor '%s' is not in the approved list, disabling PPAG.\n",
dmi_get_system_info(DMI_SYS_VENDOR));
mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
mvm->fwrt.ppag_table.v1.flags = cpu_to_le32(0);
return 0;
}
@ -1144,33 +1113,6 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
}
static u8 iwl_mvm_eval_dsm_indonesia_5g2(struct iwl_mvm *mvm)
{
u8 value;
int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0,
DSM_FUNC_ENABLE_INDONESIA_5G2,
&iwl_guid, &value);
if (ret < 0)
IWL_DEBUG_RADIO(mvm,
"Failed to evaluate DSM function ENABLE_INDONESIA_5G2, ret=%d\n",
ret);
else if (value >= DSM_VALUE_INDONESIA_MAX)
IWL_DEBUG_RADIO(mvm,
"DSM function ENABLE_INDONESIA_5G2 return invalid value, value=%d\n",
value);
else if (value == DSM_VALUE_INDONESIA_ENABLE) {
IWL_DEBUG_RADIO(mvm,
"Evaluated DSM function ENABLE_INDONESIA_5G2: Enabling 5g2\n");
return DSM_VALUE_INDONESIA_ENABLE;
}
/* default behaviour is disabled */
return DSM_VALUE_INDONESIA_DISABLE;
}
static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
{
u8 value;
@ -1195,64 +1137,27 @@ static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
return DSM_VALUE_RFI_DISABLE;
}
static u8 iwl_mvm_eval_dsm_disable_srd(struct iwl_mvm *mvm)
{
u8 value;
int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0,
DSM_FUNC_DISABLE_SRD,
&iwl_guid, &value);
if (ret < 0)
IWL_DEBUG_RADIO(mvm,
"Failed to evaluate DSM function DISABLE_SRD, ret=%d\n",
ret);
else if (value >= DSM_VALUE_SRD_MAX)
IWL_DEBUG_RADIO(mvm,
"DSM function DISABLE_SRD return invalid value, value=%d\n",
value);
else if (value == DSM_VALUE_SRD_PASSIVE) {
IWL_DEBUG_RADIO(mvm,
"Evaluated DSM function DISABLE_SRD: setting SRD to passive\n");
return DSM_VALUE_SRD_PASSIVE;
} else if (value == DSM_VALUE_SRD_DISABLE) {
IWL_DEBUG_RADIO(mvm,
"Evaluated DSM function DISABLE_SRD: disabling SRD\n");
return DSM_VALUE_SRD_DISABLE;
}
/* default behaviour is active */
return DSM_VALUE_SRD_ACTIVE;
}
static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
{
u8 ret;
int cmd_ret;
struct iwl_lari_config_change_cmd_v2 cmd = {};
struct iwl_lari_config_change_cmd_v3 cmd = {};
if (iwl_mvm_eval_dsm_indonesia_5g2(mvm) == DSM_VALUE_INDONESIA_ENABLE)
cmd.config_bitmap |=
cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
ret = iwl_mvm_eval_dsm_disable_srd(mvm);
if (ret == DSM_VALUE_SRD_PASSIVE)
cmd.config_bitmap |=
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
else if (ret == DSM_VALUE_SRD_DISABLE)
cmd.config_bitmap |=
cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt);
/* apply more config masks here */
if (cmd.config_bitmap) {
size_t cmd_size = iwl_fw_lookup_cmd_ver(mvm->fw,
REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE, 1) == 2 ?
sizeof(struct iwl_lari_config_change_cmd_v2) :
sizeof(struct iwl_lari_config_change_cmd_v1);
size_t cmd_size;
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE, 1);
if (cmd_ver == 3)
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3);
else if (cmd_ver == 2)
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2);
else
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
IWL_DEBUG_RADIO(mvm,
"sending LARI_CONFIG_CHANGE, config_bitmap=0x%x\n",
le32_to_cpu(cmd.config_bitmap));
@ -1485,14 +1390,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
}
/* Init RSS configuration */
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
ret = iwl_configure_rxq(mvm);
if (ret) {
IWL_ERR(mvm, "Failed to configure RX queues: %d\n",
ret);
goto error;
}
}
ret = iwl_configure_rxq(&mvm->fwrt);
if (ret)
goto error;
if (iwl_mvm_has_new_rx_api(mvm)) {
ret = iwl_send_rss_cfg_cmd(mvm);

View file

@ -1099,6 +1099,8 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC,
NULL);
mvm->last_reset_or_resume_time_jiffies = jiffies;
if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/* Something went wrong - we need to finish some cleanup
* that normally iwl_mvm_mac_restart_complete() below
@ -4610,6 +4612,16 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
break;
case NL80211_IFTYPE_STATION:
/*
* We haven't configured the firmware to be associated yet since
* we don't know the dtim period. In this case, the firmware can't
* track the beacons.
*/
if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period) {
ret = -EBUSY;
goto out_unlock;
}
if (chsw->delay > IWL_MAX_CSA_BLOCK_TX)
schedule_delayed_work(&mvmvif->csa_work, 0);
@ -5134,28 +5146,50 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
}
void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
struct iwl_mvm_internal_rxq_notif *notif,
u32 size)
enum iwl_mvm_rxq_notif_type type,
bool sync,
const void *data, u32 size)
{
u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
struct {
struct iwl_rxq_sync_cmd cmd;
struct iwl_mvm_internal_rxq_notif notif;
} __packed cmd = {
.cmd.rxq_mask = cpu_to_le32(BIT(mvm->trans->num_rx_queues) - 1),
.cmd.count =
cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) +
size),
.notif.type = type,
.notif.sync = sync,
};
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD),
.data[0] = &cmd,
.len[0] = sizeof(cmd),
.data[1] = data,
.len[1] = size,
.flags = sync ? 0 : CMD_ASYNC,
};
int ret;
/* size must be a multiple of DWORD */
if (WARN_ON(cmd.cmd.count & cpu_to_le32(3)))
return;
if (!iwl_mvm_has_new_rx_api(mvm))
return;
if (notif->sync) {
notif->cookie = mvm->queue_sync_cookie;
if (sync) {
cmd.notif.cookie = mvm->queue_sync_cookie;
mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1;
}
ret = iwl_mvm_notify_rx_queue(mvm, qmask, notif, size, !notif->sync);
ret = iwl_mvm_send_cmd(mvm, &hcmd);
if (ret) {
IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
goto out;
}
if (notif->sync) {
if (sync) {
lockdep_assert_held(&mvm->mutex);
ret = wait_event_timeout(mvm->rx_sync_waitq,
READ_ONCE(mvm->queue_sync_state) == 0 ||
@ -5167,21 +5201,18 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
}
out:
mvm->queue_sync_state = 0;
if (notif->sync)
if (sync) {
mvm->queue_sync_state = 0;
mvm->queue_sync_cookie++;
}
}
static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_internal_rxq_notif data = {
.type = IWL_MVM_RXQ_EMPTY,
.sync = 1,
};
mutex_lock(&mvm->mutex);
iwl_mvm_sync_rx_queues_internal(mvm, &data, sizeof(data));
iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_EMPTY, true, NULL, 0);
mutex_unlock(&mvm->mutex);
}

View file

@ -591,7 +591,6 @@ struct iwl_mvm_tcm {
enum iwl_mvm_traffic_load global_load;
bool low_latency[NUM_MAC_INDEX_DRIVER];
bool change[NUM_MAC_INDEX_DRIVER];
bool global_change;
} result;
};
@ -1096,6 +1095,9 @@ struct iwl_mvm {
/* sniffer data to include in radiotap */
__le16 cur_aid;
u8 cur_bssid[ETH_ALEN];
unsigned long last_6ghz_passive_scan_jiffies;
unsigned long last_reset_or_resume_time_jiffies;
};
/* Extract MVM priv from op_mode and _hw */
@ -1570,9 +1572,6 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
const struct iwl_mvm_internal_rxq_notif *notif,
u32 notif_size, bool async);
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
@ -2001,8 +2000,9 @@ void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_tdls_ch_switch_work(struct work_struct *work);
void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
struct iwl_mvm_internal_rxq_notif *notif,
u32 size);
enum iwl_mvm_rxq_notif_type type,
bool sync,
const void *data, u32 size);
void iwl_mvm_reorder_timer_expired(struct timer_list *t);
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid);

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2020 Intel Corporation
* Copyright (C) 2018-2021 Intel Corporation
*/
#include "rs.h"
#include "fw-api.h"
@ -72,19 +72,15 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
bool vht_ena = vht_cap->vht_supported;
u16 flags = 0;
/* get STBC flags */
if (mvm->cfg->ht_params->stbc &&
(num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) {
if (he_cap->has_he) {
if (he_cap->he_cap_elem.phy_cap_info[2] &
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
if (he_cap->he_cap_elem.phy_cap_info[7] &
IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK;
} else if ((ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) ||
(vht_ena &&
(vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)))
if (he_cap->has_he && he_cap->he_cap_elem.phy_cap_info[2] &
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
else if (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
else if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
}

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*
* Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation. All rights reserved.
* Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
@ -1926,9 +1926,7 @@ static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (is_ht(rate))
return index == IWL_RATE_MCS_7_INDEX;
if (is_vht(rate))
return index == IWL_RATE_MCS_7_INDEX ||
index == IWL_RATE_MCS_8_INDEX ||
index == IWL_RATE_MCS_9_INDEX;
return index == IWL_RATE_MCS_9_INDEX;
WARN_ON_ONCE(1);
return false;

View file

@ -527,37 +527,6 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
return false;
}
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
const struct iwl_mvm_internal_rxq_notif *notif,
u32 notif_size, bool async)
{
u8 buf[sizeof(struct iwl_rxq_sync_cmd) +
sizeof(struct iwl_mvm_rss_sync_notif)];
struct iwl_rxq_sync_cmd *cmd = (void *)buf;
u32 data_size = sizeof(*cmd) + notif_size;
int ret;
/*
* size must be a multiple of DWORD
* Ensure we don't overflow buf
*/
if (WARN_ON(notif_size & 3 ||
notif_size > sizeof(struct iwl_mvm_rss_sync_notif)))
return -EINVAL;
cmd->rxq_mask = cpu_to_le32(rxq_mask);
cmd->count = cpu_to_le32(notif_size);
cmd->flags = 0;
memcpy(cmd->payload, notif, notif_size);
ret = iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(DATA_PATH_GROUP,
TRIGGER_RX_QUEUES_NOTIF_CMD),
async ? CMD_ASYNC : 0, data_size, cmd);
return ret;
}
/*
* Returns true if sn2 - buffer_size < sn1 < sn2.
* To be used only in order to compare reorder buffer head with NSSN.
@ -573,15 +542,13 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
{
if (IWL_MVM_USE_NSSN_SYNC) {
struct iwl_mvm_rss_sync_notif notif = {
.metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
.metadata.sync = 0,
.nssn_sync.baid = baid,
.nssn_sync.nssn = nssn,
struct iwl_mvm_nssn_sync_data notif = {
.baid = baid,
.nssn = nssn,
};
iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif,
sizeof(notif));
iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NSSN_SYNC, false,
&notif, sizeof(notif));
}
}
@ -830,8 +797,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
"invalid notification size %d (%d)",
len, (int)(sizeof(*notif) + sizeof(*internal_notif))))
return;
/* remove only the firmware header, we want all of our payload below */
len -= sizeof(*notif);
len -= sizeof(*notif) + sizeof(*internal_notif);
if (internal_notif->sync &&
mvm->queue_sync_cookie != internal_notif->cookie) {
@ -841,21 +807,19 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
switch (internal_notif->type) {
case IWL_MVM_RXQ_EMPTY:
WARN_ONCE(len != sizeof(*internal_notif),
"invalid empty notification size %d (%d)",
len, (int)sizeof(*internal_notif));
WARN_ONCE(len, "invalid empty notification size %d", len);
break;
case IWL_MVM_RXQ_NOTIF_DEL_BA:
if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
if (WARN_ONCE(len != sizeof(struct iwl_mvm_delba_data),
"invalid delba notification size %d (%d)",
len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
len, (int)sizeof(struct iwl_mvm_delba_data)))
break;
iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
break;
case IWL_MVM_RXQ_NSSN_SYNC:
if (WARN_ONCE(len != sizeof(struct iwl_mvm_rss_sync_notif),
if (WARN_ONCE(len != sizeof(struct iwl_mvm_nssn_sync_data),
"invalid nssn sync notification size %d (%d)",
len, (int)sizeof(struct iwl_mvm_rss_sync_notif)))
len, (int)sizeof(struct iwl_mvm_nssn_sync_data)))
break;
iwl_mvm_nssn_sync(mvm, napi, queue,
(void *)internal_notif->data);

View file

@ -43,6 +43,9 @@
/* adaptive dwell number of APs override for social channels */
#define IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS 2
/* minimal number of 2GHz and 5GHz channels in the regular scan request */
#define IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS 4
struct iwl_mvm_scan_timing_params {
u32 suspend_time;
u32 max_out_time;
@ -94,6 +97,7 @@ struct iwl_mvm_scan_params {
struct cfg80211_scan_6ghz_params *scan_6ghz_params;
u32 n_6ghz_params;
bool scan_6ghz;
bool enable_6ghz_passive;
};
static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm)
@ -1873,6 +1877,98 @@ static u8 iwl_mvm_scan_umac_chan_flags_v2(struct iwl_mvm *mvm,
return flags;
}
static void iwl_mvm_scan_6ghz_passive_scan(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif)
{
struct ieee80211_supported_band *sband =
&mvm->nvm_data->bands[NL80211_BAND_6GHZ];
u32 n_disabled, i;
params->enable_6ghz_passive = false;
if (params->scan_6ghz)
return;
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN)) {
IWL_DEBUG_SCAN(mvm,
"6GHz passive scan: Not supported by FW\n");
return;
}
/* 6GHz passive scan allowed only on station interface */
if (vif->type != NL80211_IFTYPE_STATION) {
IWL_DEBUG_SCAN(mvm,
"6GHz passive scan: not station interface\n");
return;
}
/*
* 6GHz passive scan is allowed while associated in a defined time
* interval following HW reset or resume flow
*/
if (vif->bss_conf.assoc &&
(time_before(mvm->last_reset_or_resume_time_jiffies +
(IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT * HZ),
jiffies))) {
IWL_DEBUG_SCAN(mvm, "6GHz passive scan: associated\n");
return;
}
/* No need for 6GHz passive scan if not enough time elapsed */
if (time_after(mvm->last_6ghz_passive_scan_jiffies +
(IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT * HZ), jiffies)) {
IWL_DEBUG_SCAN(mvm,
"6GHz passive scan: timeout did not expire\n");
return;
}
/* not enough channels in the regular scan request */
if (params->n_channels < IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS) {
IWL_DEBUG_SCAN(mvm,
"6GHz passive scan: not enough channels\n");
return;
}
for (i = 0; i < params->n_ssids; i++) {
if (!params->ssids[i].ssid_len)
break;
}
/* not a wildcard scan, so cannot enable passive 6GHz scan */
if (i == params->n_ssids) {
IWL_DEBUG_SCAN(mvm,
"6GHz passive scan: no wildcard SSID\n");
return;
}
if (!sband || !sband->n_channels) {
IWL_DEBUG_SCAN(mvm,
"6GHz passive scan: no 6GHz channels\n");
return;
}
for (i = 0, n_disabled = 0; i < sband->n_channels; i++) {
if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED))
n_disabled++;
}
/*
* Not all the 6GHz channels are disabled, so no need for 6GHz passive
* scan
*/
if (n_disabled != sband->n_channels) {
IWL_DEBUG_SCAN(mvm,
"6GHz passive scan: 6GHz channels enabled\n");
return;
}
/* all conditions to enable 6ghz passive scan are satisfied */
IWL_DEBUG_SCAN(mvm, "6GHz passive scan: can be enabled\n");
params->enable_6ghz_passive = true;
}
static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif,
@ -1911,6 +2007,9 @@ static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
params->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ)
flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN;
if (params->enable_6ghz_passive)
flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN;
return flags;
}
@ -2183,6 +2282,30 @@ iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm,
params->n_channels,
channel_cfg_flags,
vif->type);
if (params->enable_6ghz_passive) {
struct ieee80211_supported_band *sband =
&mvm->nvm_data->bands[NL80211_BAND_6GHZ];
u32 i;
for (i = 0; i < sband->n_channels; i++) {
struct ieee80211_channel *channel =
&sband->channels[i];
struct iwl_scan_channel_cfg_umac *cfg =
&cp->channel_config[cp->count];
if (!cfg80211_channel_is_psc(channel))
continue;
cfg->flags = 0;
cfg->v2.channel_num = channel->hw_value;
cfg->v2.band = PHY_BAND_6;
cfg->v2.iter_count = 1;
cfg->v2.iter_interval = 0;
cp->count++;
}
}
}
static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@ -2500,6 +2623,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_build_scan_probe(mvm, vif, ies, &params);
iwl_mvm_scan_6ghz_passive_scan(mvm, &params, vif);
uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params,
IWL_MVM_SCAN_REGULAR);
@ -2524,6 +2649,9 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
if (params.enable_6ghz_passive)
mvm->last_6ghz_passive_scan_jiffies = jiffies;
schedule_delayed_work(&mvm->scan_timeout_dwork,
msecs_to_jiffies(SCAN_TIMEOUT));

View file

@ -2441,12 +2441,12 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
{
struct iwl_mvm_rss_sync_notif notif = {
.metadata.type = IWL_MVM_RXQ_NOTIF_DEL_BA,
.metadata.sync = 1,
.delba.baid = baid,
struct iwl_mvm_delba_data notif = {
.baid = baid,
};
iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif, sizeof(notif));
iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_NOTIF_DEL_BA, true,
&notif, sizeof(notif));
};
static void iwl_mvm_free_reorder(struct iwl_mvm *mvm,

View file

@ -281,6 +281,36 @@ struct iwl_mvm_key_pn {
} ____cacheline_aligned_in_smp q[];
};
/**
* enum iwl_mvm_rxq_notif_type - Internal message identifier
*
* @IWL_MVM_RXQ_EMPTY: empty sync notification
* @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
* @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
*/
enum iwl_mvm_rxq_notif_type {
IWL_MVM_RXQ_EMPTY,
IWL_MVM_RXQ_NOTIF_DEL_BA,
IWL_MVM_RXQ_NSSN_SYNC,
};
/**
* struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent
* in &iwl_rxq_sync_cmd. Should be DWORD aligned.
* FW is agnostic to the payload, so there are no endianity requirements.
*
* @type: value from &iwl_mvm_rxq_notif_type
* @sync: ctrl path is waiting for all notifications to be received
* @cookie: internal cookie to identify old notifications
* @data: payload
*/
struct iwl_mvm_internal_rxq_notif {
u16 type;
u16 sync;
u32 cookie;
u8 data[];
} __packed;
struct iwl_mvm_delba_data {
u32 baid;
} __packed;
@ -290,14 +320,6 @@ struct iwl_mvm_nssn_sync_data {
u32 nssn;
} __packed;
struct iwl_mvm_rss_sync_notif {
struct iwl_mvm_internal_rxq_notif metadata;
union {
struct iwl_mvm_delba_data delba;
struct iwl_mvm_nssn_sync_data nssn_sync;
};
} __packed;
/**
* struct iwl_mvm_rxq_dup_data - per station per rx queue data
* @last_seq: last sequence per tid for duplicate packet detection

View file

@ -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-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
@ -151,6 +151,16 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
if (errmsg)
IWL_ERR(mvm, "%s\n", errmsg);
if (mvmvif->csa_bcn_pending) {
struct iwl_mvm_sta *mvmsta;
rcu_read_lock();
mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
if (!WARN_ON(!mvmsta))
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
rcu_read_unlock();
}
iwl_mvm_connection_loss(mvm, vif, errmsg);
return true;
}
@ -284,6 +294,17 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
iwl_mvm_roc_finished(mvm);
break;
case NL80211_IFTYPE_STATION:
/*
* If we are switching channel, don't disconnect
* if the time event is already done. Beacons can
* be delayed a bit after the switch.
*/
if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) {
IWL_DEBUG_TE(mvm,
"No beacon heard and the CS time event is over, don't disconnect\n");
break;
}
/*
* By now, we should have finished association
* and know the dtim period.
@ -713,8 +734,8 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id));
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0,
sizeof(time_cmd), &time_cmd);
if (WARN_ON(ret))
return;
if (ret)
IWL_ERR(mvm, "Couldn't remove the time event\n");
}
/*

View file

@ -1030,15 +1030,9 @@ iwl_mvm_tcm_load(struct iwl_mvm *mvm, u32 airtime, unsigned long elapsed)
return IWL_MVM_TRAFFIC_LOW;
}
struct iwl_mvm_tcm_iter_data {
struct iwl_mvm *mvm;
bool any_sent;
};
static void iwl_mvm_tcm_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
{
struct iwl_mvm_tcm_iter_data *data = _data;
struct iwl_mvm *mvm = data->mvm;
struct iwl_mvm *mvm = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool low_latency, prev = mvmvif->low_latency & LOW_LATENCY_TRAFFIC;
@ -1060,22 +1054,15 @@ static void iwl_mvm_tcm_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
} else {
iwl_mvm_update_quotas(mvm, false, NULL);
}
data->any_sent = true;
}
static void iwl_mvm_tcm_results(struct iwl_mvm *mvm)
{
struct iwl_mvm_tcm_iter_data data = {
.mvm = mvm,
.any_sent = false,
};
mutex_lock(&mvm->mutex);
ieee80211_iterate_active_interfaces(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_tcm_iter, &data);
iwl_mvm_tcm_iter, mvm);
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
iwl_mvm_config_scan(mvm);
@ -1257,7 +1244,6 @@ static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
}
load = iwl_mvm_tcm_load(mvm, total_airtime, elapsed);
mvm->tcm.result.global_change = load != mvm->tcm.result.global_load;
mvm->tcm.result.global_load = load;
for (i = 0; i < NUM_NL80211_BANDS; i++) {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2014, 2018-2020 Intel Corporation
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -17,10 +17,20 @@
#include "iwl-prph.h"
#include "internal.h"
#define TRANS_CFG_MARKER BIT(0)
#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \
struct _struct)
extern int _invalid_type;
#define _TRANS_CFG_MARKER(cfg) \
(__builtin_choose_expr(_IS_A(cfg, iwl_cfg_trans_params), \
TRANS_CFG_MARKER, \
__builtin_choose_expr(_IS_A(cfg, iwl_cfg), 0, _invalid_type)))
#define _ASSIGN_CFG(cfg) (_TRANS_CFG_MARKER(cfg) + (kernel_ulong_t)&(cfg))
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
.driver_data = (kernel_ulong_t)&(cfg)
.driver_data = _ASSIGN_CFG(cfg)
/* Hardware specific file defines the PCI IDs table for that hardware module */
static const struct pci_device_id iwl_hw_card_ids[] = {
@ -490,6 +500,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_trans_cfg)},
{IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)},
/* Bz devices */
{IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)},
#endif /* CONFIG_IWLMVM */
{0}
@ -607,6 +619,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x2725, 0x4020, iwlax210_2ax_cfg_ty_gf_a0, NULL),
IWL_DEV_INFO(0x2725, 0x6020, iwlax210_2ax_cfg_ty_gf_a0, NULL),
IWL_DEV_INFO(0x2725, 0x6024, iwlax210_2ax_cfg_ty_gf_a0, NULL),
IWL_DEV_INFO(0x2725, 0x1673, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675w_name),
IWL_DEV_INFO(0x2725, 0x1674, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675x_name),
IWL_DEV_INFO(0x7A70, 0x0090, iwlax211_2ax_cfg_so_gf_a0_long, NULL),
IWL_DEV_INFO(0x7A70, 0x0098, iwlax211_2ax_cfg_so_gf_a0_long, NULL),
IWL_DEV_INFO(0x7A70, 0x00B0, iwlax411_2ax_cfg_so_gf4_a0_long, NULL),
@ -1014,12 +1028,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_ma_a0_mr_a0, iwl_ma_name),
iwl_cfg_ma_a0_mr_a0, iwl_ax221_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_snj_a0_mr_a0, iwl_ma_name),
iwl_cfg_snj_a0_mr_a0, iwl_ax221_name),
/* So with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
@ -1067,6 +1081,35 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
/* Bz */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_bz_a0_hr_b0, iwl_ax201_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_bz_a0_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB,
iwl_cfg_bz_a0_gf4_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_bz_a0_mr_a0, iwl_ax211_name),
/* So with GF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name)
#endif /* CONFIG_IWLMVM */
};
@ -1075,19 +1118,22 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct iwl_cfg_trans_params *trans =
(struct iwl_cfg_trans_params *)(ent->driver_data);
const struct iwl_cfg_trans_params *trans;
const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
struct iwl_trans *iwl_trans;
struct iwl_trans_pcie *trans_pcie;
int i, ret;
const struct iwl_cfg *cfg;
trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
/*
* This is needed for backwards compatibility with the old
* tables, so we don't need to change all the config structs
* at the same time. The cfg is used to compare with the old
* full cfg structs.
*/
const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
cfg = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
/* make sure trans is the first element in iwl_cfg */
BUILD_BUG_ON(offsetof(struct iwl_cfg, trans));
@ -1165,7 +1211,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_a0;
iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_b0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
iwl_trans->cfg = &iwlax211_2ax_cfg_so_gf_a0;
@ -1202,11 +1248,19 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif
/*
* If we didn't set the cfg yet, assume the trans is actually
* a full cfg from the old tables.
* If we didn't set the cfg yet, the PCI ID table entry should have
* been a full config - if yes, use it, otherwise fail.
*/
if (!iwl_trans->cfg)
if (!iwl_trans->cfg) {
if (ent->driver_data & TRANS_CFG_MARKER) {
pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
pdev->device, pdev->subsystem_device,
iwl_trans->hw_rev, iwl_trans->hw_rf_id);
ret = -EINVAL;
goto out_free_trans;
}
iwl_trans->cfg = cfg;
}
/* if we don't have a name yet, copy name from the old cfg */
if (!iwl_trans->name)
@ -1222,6 +1276,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
}
ret = iwl_trans_init(iwl_trans);
if (ret)
goto out_free_trans;
pci_set_drvdata(pdev, iwl_trans);
iwl_trans->drv = iwl_drv_start(iwl_trans);

View file

@ -447,6 +447,11 @@ struct iwl_trans
const struct iwl_cfg_trans_params *cfg_trans);
void iwl_trans_pcie_free(struct iwl_trans *trans);
bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);
#define _iwl_trans_pcie_grab_nic_access(trans) \
__cond_lock(nic_access_nobh, \
likely(__iwl_trans_pcie_grab_nic_access(trans)))
/*****************************************************
* RX
******************************************************/

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2003-2014, 2018-2020 Intel Corporation
* Copyright (C) 2003-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -1023,6 +1023,9 @@ static int iwl_pcie_napi_poll(struct napi_struct *napi, int budget)
ret = iwl_pcie_rx_handle(trans, rxq->id, budget);
IWL_DEBUG_ISR(trans, "[%d] handled %d, budget %d\n",
rxq->id, ret, budget);
if (ret < budget) {
spin_lock(&trans_pcie->irq_lock);
if (test_bit(STATUS_INT_ENABLED, &trans->status))
@ -1046,33 +1049,19 @@ static int iwl_pcie_napi_poll_msix(struct napi_struct *napi, int budget)
trans = trans_pcie->trans;
ret = iwl_pcie_rx_handle(trans, rxq->id, budget);
IWL_DEBUG_ISR(trans, "[%d] handled %d, budget %d\n", rxq->id, ret,
budget);
if (ret < budget) {
int irq_line = rxq->id;
/* FIRST_RSS is shared with line 0 */
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS &&
rxq->id == 1)
irq_line = 0;
spin_lock(&trans_pcie->irq_lock);
iwl_pcie_clear_irq(trans, rxq->id);
spin_unlock(&trans_pcie->irq_lock);
napi_complete_done(&rxq->napi, ret);
}
return ret;
}
static int iwl_pcie_napi_poll_msix_shared(struct napi_struct *napi, int budget)
{
struct iwl_rxq *rxq = container_of(napi, struct iwl_rxq, napi);
struct iwl_trans_pcie *trans_pcie;
struct iwl_trans *trans;
int ret;
trans_pcie = container_of(napi->dev, struct iwl_trans_pcie, napi_dev);
trans = trans_pcie->trans;
ret = iwl_pcie_rx_handle(trans, rxq->id, budget);
if (ret < budget) {
spin_lock(&trans_pcie->irq_lock);
iwl_pcie_clear_irq(trans, 0);
iwl_pcie_clear_irq(trans, irq_line);
spin_unlock(&trans_pcie->irq_lock);
napi_complete_done(&rxq->napi, ret);
@ -1134,18 +1123,9 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
if (!rxq->napi.poll) {
int (*poll)(struct napi_struct *, int) = iwl_pcie_napi_poll;
if (trans_pcie->msix_enabled) {
if (trans_pcie->msix_enabled)
poll = iwl_pcie_napi_poll_msix;
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX &&
i == 0)
poll = iwl_pcie_napi_poll_msix_shared;
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS &&
i == 1)
poll = iwl_pcie_napi_poll_msix_shared;
}
netif_napi_add(&trans_pcie->napi_dev, &rxq->napi,
poll, NAPI_POLL_WEIGHT);
napi_enable(&rxq->napi);
@ -1659,10 +1639,13 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
if (WARN_ON(entry->entry >= trans->num_rx_queues))
return IRQ_NONE;
if (WARN_ONCE(!rxq, "Got MSI-X interrupt before we have Rx queues"))
if (WARN_ONCE(!rxq,
"[%d] Got MSI-X interrupt before we have Rx queues",
entry->entry))
return IRQ_NONE;
lock_map_acquire(&trans->sync_cmd_lockdep_map);
IWL_DEBUG_ISR(trans, "[%d] Got interrupt\n", entry->entry);
local_bh_disable();
if (napi_schedule_prep(&rxq->napi))
@ -2194,9 +2177,16 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry);
struct iwl_trans *trans = trans_pcie->trans;
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
u32 inta_fh_msk = ~MSIX_FH_INT_CAUSES_DATA_QUEUE;
u32 inta_fh, inta_hw;
bool polling = false;
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX)
inta_fh_msk |= MSIX_FH_INT_CAUSES_Q0;
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS)
inta_fh_msk |= MSIX_FH_INT_CAUSES_Q1;
lock_map_acquire(&trans->sync_cmd_lockdep_map);
spin_lock_bh(&trans_pcie->irq_lock);
@ -2205,7 +2195,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
/*
* Clear causes registers to avoid being handling the same cause.
*/
iwl_write32(trans, CSR_MSIX_FH_INT_CAUSES_AD, inta_fh);
iwl_write32(trans, CSR_MSIX_FH_INT_CAUSES_AD, inta_fh & inta_fh_msk);
iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, inta_hw);
spin_unlock_bh(&trans_pcie->irq_lock);
@ -2219,8 +2209,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
if (iwl_have_debug_level(IWL_DL_ISR)) {
IWL_DEBUG_ISR(trans,
"ISR inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
inta_fh, trans_pcie->fh_mask,
"ISR[%d] inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
entry->entry, inta_fh, trans_pcie->fh_mask,
iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD));
if (inta_fh & ~trans_pcie->fh_mask)
IWL_DEBUG_ISR(trans,
@ -2275,8 +2265,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
/* After checking FH register check HW register */
if (iwl_have_debug_level(IWL_DL_ISR)) {
IWL_DEBUG_ISR(trans,
"ISR inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
inta_hw, trans_pcie->hw_mask,
"ISR[%d] inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
entry->entry, inta_hw, trans_pcie->hw_mask,
iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD));
if (inta_hw & ~trans_pcie->hw_mask)
IWL_DEBUG_ISR(trans,

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2020 Intel Corporation
* Copyright (C) 2018-2021 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-prph.h"
@ -108,8 +108,8 @@ static void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
ret = wait_event_timeout(trans_pcie->fw_reset_waitq,
trans_pcie->fw_reset_done, FW_RESET_TIMEOUT);
if (!ret)
IWL_ERR(trans,
"firmware didn't ACK the reset - continue anyway\n");
IWL_INFO(trans,
"firmware didn't ACK the reset - continue anyway\n");
}
void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
@ -143,7 +143,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
IWL_DEBUG_INFO(trans,
"DEVICE_ENABLED bit was set and is now cleared\n");
iwl_txq_gen2_tx_stop(trans);
iwl_txq_gen2_tx_free(trans);
iwl_pcie_rx_stop(trans);
}

View file

@ -1604,6 +1604,11 @@ iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
} else {
trans_pcie->trans->num_rx_queues = num_irqs - 1;
}
IWL_DEBUG_INFO(trans,
"MSI-X enabled with rx queues %d, vec mask 0x%x\n",
trans_pcie->trans->num_rx_queues, trans_pcie->shared_vec_mask);
WARN_ON(trans_pcie->trans->num_rx_queues > IWL_MAX_RX_HW_QUEUES);
trans_pcie->alloc_vecs = num_irqs;
@ -1973,12 +1978,16 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk)
module_put(THIS_MODULE);
}
static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
/*
* This version doesn't disable BHs but rather assumes they're
* already disabled.
*/
bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
{
int ret;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
spin_lock_bh(&trans_pcie->reg_lock);
spin_lock(&trans_pcie->reg_lock);
if (trans_pcie->cmd_hold_nic_awake)
goto out;
@ -2063,7 +2072,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
}
err:
spin_unlock_bh(&trans_pcie->reg_lock);
spin_unlock(&trans_pcie->reg_lock);
return false;
}
@ -2076,6 +2085,20 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
return true;
}
static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
{
bool ret;
local_bh_disable();
ret = __iwl_trans_pcie_grab_nic_access(trans);
if (ret) {
/* keep BHs disabled until iwl_trans_pcie_release_nic_access */
return ret;
}
local_bh_enable();
return false;
}
static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2003-2014, 2018-2020 Intel Corporation
* Copyright (C) 2003-2014, 2018-2021 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -181,16 +181,20 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
lockdep_assert_held(&trans_pcie->reg_lock);
if (!trans->trans_cfg->base_params->apmg_wake_up_wa)
return;
if (WARN_ON(!trans_pcie->cmd_hold_nic_awake))
spin_lock(&trans_pcie->reg_lock);
if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) {
spin_unlock(&trans_pcie->reg_lock);
return;
}
trans_pcie->cmd_hold_nic_awake = false;
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock(&trans_pcie->reg_lock);
}
/*
@ -198,7 +202,6 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
*/
static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = trans->txqs.txq[txq_id];
if (!txq) {
@ -222,12 +225,9 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
iwl_txq_free_tfd(trans, txq);
txq->read_ptr = iwl_txq_inc_wrap(trans, txq->read_ptr);
if (txq->read_ptr == txq->write_ptr) {
spin_lock(&trans_pcie->reg_lock);
if (txq_id == trans->txqs.cmd.q_id)
iwl_pcie_clear_cmd_in_flight(trans);
spin_unlock(&trans_pcie->reg_lock);
}
if (txq->read_ptr == txq->write_ptr &&
txq_id == trans->txqs.cmd.q_id)
iwl_pcie_clear_cmd_in_flight(trans);
}
while (!skb_queue_empty(&txq->overflow_q)) {
@ -629,38 +629,30 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
const struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
lockdep_assert_held(&trans_pcie->reg_lock);
/* Make sure the NIC is still alive in the bus */
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
return -ENODEV;
if (!trans->trans_cfg->base_params->apmg_wake_up_wa)
return 0;
/*
* wake up the NIC to make sure that the firmware will see the host
* command - we will let the NIC sleep once all the host commands
* returned. This needs to be done only on NICs that have
* apmg_wake_up_wa set.
* apmg_wake_up_wa set (see above.)
*/
if (trans->trans_cfg->base_params->apmg_wake_up_wa &&
!trans_pcie->cmd_hold_nic_awake) {
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (!_iwl_trans_pcie_grab_nic_access(trans))
return -EIO;
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
15000);
if (ret < 0) {
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
return -EIO;
}
trans_pcie->cmd_hold_nic_awake = true;
}
/*
* In iwl_trans_grab_nic_access(), we've acquired the reg_lock.
* There, we also returned immediately if cmd_hold_nic_awake is
* already true, so it's OK to unconditionally set it to true.
*/
trans_pcie->cmd_hold_nic_awake = true;
spin_unlock(&trans_pcie->reg_lock);
return 0;
}
@ -674,7 +666,6 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
*/
static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = trans->txqs.txq[txq_id];
int nfreed = 0;
u16 r;
@ -705,12 +696,8 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
}
}
if (txq->read_ptr == txq->write_ptr) {
/* BHs are also disabled due to txq->lock */
spin_lock(&trans_pcie->reg_lock);
if (txq->read_ptr == txq->write_ptr)
iwl_pcie_clear_cmd_in_flight(trans);
spin_unlock(&trans_pcie->reg_lock);
}
iwl_txq_progress(txq);
}
@ -914,7 +901,6 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id,
int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
@ -1161,19 +1147,16 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
if (txq->read_ptr == txq->write_ptr && txq->wd_timeout)
mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout);
spin_lock(&trans_pcie->reg_lock);
ret = iwl_pcie_set_cmd_in_flight(trans, cmd);
if (ret < 0) {
idx = ret;
goto unlock_reg;
goto out;
}
/* Increment and update queue's write index */
txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr);
iwl_pcie_txq_inc_wr_ptr(trans, txq);
unlock_reg:
spin_unlock(&trans_pcie->reg_lock);
out:
spin_unlock_irqrestore(&txq->lock, flags);
free_dup_buf:
@ -1367,7 +1350,6 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
/* this is the data left for this subframe */
unsigned int data_left =
min_t(unsigned int, mss, total_len);
struct sk_buff *csum_skb = NULL;
unsigned int hdr_tb_len;
dma_addr_t hdr_tb_phys;
u8 *subf_hdrs_start = hdr_page->pos;
@ -1398,10 +1380,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
hdr_tb_len = hdr_page->pos - start_hdr;
hdr_tb_phys = dma_map_single(trans->dev, start_hdr,
hdr_tb_len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(trans->dev, hdr_tb_phys))) {
dev_kfree_skb(csum_skb);
if (unlikely(dma_mapping_error(trans->dev, hdr_tb_phys)))
return -EINVAL;
}
iwl_pcie_txq_build_tfd(trans, txq, hdr_tb_phys,
hdr_tb_len, false);
trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr,
@ -1420,10 +1400,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
tb_phys = dma_map_single(trans->dev, tso.data,
size, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
dev_kfree_skb(csum_skb);
if (unlikely(dma_mapping_error(trans->dev, tb_phys)))
return -EINVAL;
}
iwl_pcie_txq_build_tfd(trans, txq, tb_phys,
size, false);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2020 Intel Corporation
* Copyright (C) 2020-2021 Intel Corporation
*/
#include <net/tso.h>
#include <linux/tcp.h>
@ -13,30 +13,6 @@
#include "iwl-scd.h"
#include <linux/dmapool.h>
/*
* iwl_txq_gen2_tx_stop - Stop all Tx DMA channels
*/
void iwl_txq_gen2_tx_stop(struct iwl_trans *trans)
{
int txq_id;
/*
* This function can be called before the op_mode disabled the
* queues. This happens when we have an rfkill interrupt.
* Since we stop Tx altogether - mark the queues as stopped.
*/
memset(trans->txqs.queue_stopped, 0,
sizeof(trans->txqs.queue_stopped));
memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
/* Unmap DMA from host system and free skb's */
for (txq_id = 0; txq_id < ARRAY_SIZE(trans->txqs.txq); txq_id++) {
if (!trans->txqs.txq[txq_id])
continue;
iwl_txq_gen2_unmap(trans, txq_id);
}
}
/*
* iwl_txq_update_byte_tbl - Set up entry in Tx byte-count array
*/
@ -399,7 +375,6 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
while (total_len) {
/* this is the data left for this subframe */
unsigned int data_left = min_t(unsigned int, mss, total_len);
struct sk_buff *csum_skb = NULL;
unsigned int tb_len;
dma_addr_t tb_phys;
u8 *subf_hdrs_start = hdr_page->pos;
@ -430,10 +405,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
tb_len = hdr_page->pos - start_hdr;
tb_phys = dma_map_single(trans->dev, start_hdr,
tb_len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
dev_kfree_skb(csum_skb);
if (unlikely(dma_mapping_error(trans->dev, tb_phys)))
goto out_err;
}
/*
* No need for _with_wa, this is from the TSO page and
* we leave some space at the end of it so can't hit
@ -458,10 +431,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
ret = iwl_txq_gen2_set_tb_with_wa(trans, skb, tfd,
tb_phys, tso.data,
tb_len, NULL);
if (ret) {
dev_kfree_skb(csum_skb);
if (ret)
goto out_err;
}
data_left -= tb_len;
tso_build_data(skb, &tso, tb_len);
@ -1189,6 +1160,12 @@ static int iwl_txq_alloc_response(struct iwl_trans *trans, struct iwl_txq *txq,
goto error_free_resp;
}
if (WARN_ONCE(trans->txqs.txq[qid],
"queue %d already allocated\n", qid)) {
ret = -EIO;
goto error_free_resp;
}
txq->id = qid;
trans->txqs.txq[qid] = txq;
wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2020 Intel Corporation
* Copyright (C) 2020-2021 Intel Corporation
*/
#ifndef __iwl_trans_queue_tx_h__
#define __iwl_trans_queue_tx_h__
@ -123,7 +123,6 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
void iwl_txq_dyn_free(struct iwl_trans *trans, int queue);
void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq);
void iwl_txq_gen2_tx_stop(struct iwl_trans *trans);
void iwl_txq_gen2_tx_free(struct iwl_trans *trans);
int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
bool cmd_queue);

View file

@ -23,7 +23,6 @@ struct lbs_private;
typedef void (*lbs_fw_cb)(struct lbs_private *priv, int ret,
const struct firmware *helper, const struct firmware *mainfw);
struct lbs_private;
struct sk_buff;
struct net_device;
struct cmd_ds_command;

View file

@ -60,13 +60,13 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
#else
#define lbs_init_mesh(priv)
#define lbs_deinit_mesh(priv)
#define lbs_start_mesh(priv)
#define lbs_add_mesh(priv)
#define lbs_remove_mesh(priv)
#define lbs_init_mesh(priv) do { } while (0)
#define lbs_deinit_mesh(priv) do { } while (0)
#define lbs_start_mesh(priv) do { } while (0)
#define lbs_add_mesh(priv) do { } while (0)
#define lbs_remove_mesh(priv) do { } while (0)
#define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
#define lbs_mesh_set_txpd(priv, dev, txpd)
#define lbs_mesh_set_txpd(priv, dev, txpd) do { } while (0)
#define lbs_mesh_set_channel(priv, channel) (0)
#define lbs_mesh_activated(priv) (false)

View file

@ -2300,8 +2300,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
is_scanning_required = 1;
} else {
mwifiex_dbg(priv->adapter, MSG,
"info: trying to associate to '%.*s' bssid %pM\n",
req_ssid.ssid_len, (char *)req_ssid.ssid,
"info: trying to associate to bssid %pM\n",
bss->bssid);
memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
break;
@ -2378,8 +2377,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
}
mwifiex_dbg(adapter, INFO,
"info: Trying to associate to %.*s and bssid %pM\n",
(int)sme->ssid_len, (char *)sme->ssid, sme->bssid);
"info: Trying to associate to bssid %pM\n", sme->bssid);
if (!mwifiex_stop_bg_scan(priv))
cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);
@ -2512,9 +2510,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
goto done;
}
mwifiex_dbg(priv->adapter, MSG,
"info: trying to join to %.*s and bssid %pM\n",
params->ssid_len, (char *)params->ssid, params->bssid);
mwifiex_dbg(priv->adapter, MSG, "info: trying to join to bssid %pM\n",
params->bssid);
mwifiex_set_ibss_params(priv, params);

View file

@ -1211,7 +1211,6 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
struct mwifiex_bssdescriptor *bss_entry)
{
int ret = 0;
u8 element_id;
struct ieee_types_fh_param_set *fh_param_set;
struct ieee_types_ds_param_set *ds_param_set;
@ -1464,7 +1463,7 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
bytes_left -= total_ie_len;
} /* while (bytes_left > 2) */
return ret;
return 0;
}
/*

View file

@ -1473,6 +1473,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
if (txq->skb == NULL) {
dma_free_coherent(&priv->pdev->dev, size, txq->txd,
txq->txd_dma);
txq->txd = NULL;
return -ENOMEM;
}

View file

@ -76,9 +76,9 @@ mt76_rx_aggr_check_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames)
nframes--;
status = (struct mt76_rx_status *)skb->cb;
if (!time_after(jiffies,
status->reorder_time +
mt76_aggr_tid_to_timeo(tid->num)))
if (!time_after32(jiffies,
status->reorder_time +
mt76_aggr_tid_to_timeo(tid->num)))
continue;
mt76_rx_aggr_release_frames(tid, frames, status->seqno);
@ -122,6 +122,7 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
struct ieee80211_bar *bar = mt76_skb_get_hdr(skb);
struct mt76_wcid *wcid = status->wcid;
struct mt76_rx_tid *tid;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
u16 seqno;
if (!ieee80211_is_ctl(bar->frame_control))
@ -130,9 +131,9 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
if (!ieee80211_is_back_req(bar->frame_control))
return;
status->tid = le16_to_cpu(bar->control) >> 12;
status->qos_ctl = tidno = le16_to_cpu(bar->control) >> 12;
seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num));
tid = rcu_dereference(wcid->aggr[status->tid]);
tid = rcu_dereference(wcid->aggr[tidno]);
if (!tid)
return;
@ -147,12 +148,12 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct mt76_wcid *wcid = status->wcid;
struct ieee80211_sta *sta;
struct mt76_rx_tid *tid;
bool sn_less;
u16 seqno, head, size, idx;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
u8 ackp;
__skb_queue_tail(frames, skb);
@ -161,18 +162,18 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
if (!sta)
return;
if (!status->aggr) {
if (!status->aggr && !(status->flag & RX_FLAG_8023)) {
mt76_rx_aggr_check_ctl(skb, frames);
return;
}
/* not part of a BA session */
ackp = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
return;
tid = rcu_dereference(wcid->aggr[status->tid]);
tid = rcu_dereference(wcid->aggr[tidno]);
if (!tid)
return;

View file

@ -79,13 +79,38 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
local_bh_enable();
}
static void
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
{
writel(q->desc_dma, &q->regs->desc_base);
writel(q->ndesc, &q->regs->ring_size);
q->head = readl(&q->regs->dma_idx);
q->tail = q->head;
}
static void
mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
{
int i;
if (!q)
return;
/* clear descriptors */
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
writel(0, &q->regs->cpu_idx);
writel(0, &q->regs->dma_idx);
mt76_dma_sync_idx(dev, q);
}
static int
mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
int idx, int n_desc, int bufsize,
u32 ring_base)
{
int size;
int i;
spin_lock_init(&q->lock);
spin_lock_init(&q->cleanup_lock);
@ -105,14 +130,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
if (!q->entry)
return -ENOMEM;
/* clear descriptors */
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
writel(q->desc_dma, &q->regs->desc_base);
writel(0, &q->regs->cpu_idx);
writel(0, &q->regs->dma_idx);
writel(q->ndesc, &q->regs->ring_size);
mt76_dma_queue_reset(dev, q);
return 0;
}
@ -201,15 +219,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
memset(e, 0, sizeof(*e));
}
static void
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
{
writel(q->desc_dma, &q->regs->desc_base);
writel(q->ndesc, &q->regs->ring_size);
q->head = readl(&q->regs->dma_idx);
q->tail = q->head;
}
static void
mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
{
@ -309,7 +318,7 @@ static int
mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, u32 tx_info)
{
struct mt76_queue_buf buf;
struct mt76_queue_buf buf = {};
dma_addr_t addr;
if (q->queued + 1 >= q->ndesc - 1)
@ -602,7 +611,6 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget)
dev = container_of(napi->dev, struct mt76_dev, napi_dev);
qid = napi - dev->napi;
local_bh_disable();
rcu_read_lock();
do {
@ -612,7 +620,6 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget)
} while (cur && done < budget);
rcu_read_unlock();
local_bh_enable();
if (done < budget && napi_complete(napi))
dev->drv->rx_poll_complete(dev, qid);
@ -626,6 +633,10 @@ mt76_dma_init(struct mt76_dev *dev)
int i;
init_dummy_netdev(&dev->napi_dev);
init_dummy_netdev(&dev->tx_napi_dev);
snprintf(dev->napi_dev.name, sizeof(dev->napi_dev.name), "%s",
wiphy_name(dev->hw->wiphy));
dev->napi_dev.threaded = 1;
mt76_for_each_q_rx(dev, i) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll,
@ -640,9 +651,11 @@ mt76_dma_init(struct mt76_dev *dev)
static const struct mt76_queue_ops mt76_dma_ops = {
.init = mt76_dma_init,
.alloc = mt76_dma_alloc_queue,
.reset_q = mt76_dma_queue_reset,
.tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw,
.tx_queue_skb = mt76_dma_tx_queue_skb,
.tx_cleanup = mt76_dma_tx_cleanup,
.rx_cleanup = mt76_dma_rx_cleanup,
.rx_reset = mt76_dma_rx_reset,
.kick = mt76_dma_kick_queue,
};

View file

@ -508,6 +508,39 @@ void mt76_free_device(struct mt76_dev *dev)
}
EXPORT_SYMBOL_GPL(mt76_free_device);
static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
{
struct sk_buff *skb = phy->rx_amsdu[q].head;
struct mt76_dev *dev = phy->dev;
phy->rx_amsdu[q].head = NULL;
phy->rx_amsdu[q].tail = NULL;
__skb_queue_tail(&dev->rx_skb[q], skb);
}
static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q,
struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
if (phy->rx_amsdu[q].head &&
(!status->amsdu || status->first_amsdu ||
status->seqno != phy->rx_amsdu[q].seqno))
mt76_rx_release_amsdu(phy, q);
if (!phy->rx_amsdu[q].head) {
phy->rx_amsdu[q].tail = &skb_shinfo(skb)->frag_list;
phy->rx_amsdu[q].seqno = status->seqno;
phy->rx_amsdu[q].head = skb;
} else {
*phy->rx_amsdu[q].tail = skb;
phy->rx_amsdu[q].tail = &skb->next;
}
if (!status->amsdu || status->last_amsdu)
mt76_rx_release_amsdu(phy, q);
}
void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
@ -525,7 +558,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
phy->test.rx_stats.fcs_error[q]++;
}
#endif
__skb_queue_tail(&dev->rx_skb[q], skb);
mt76_rx_release_burst(phy, q, skb);
}
EXPORT_SYMBOL_GPL(mt76_rx);
@ -720,6 +754,8 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
status->signal = mstat.signal;
status->chains = mstat.chains;
status->ampdu_reference = mstat.ampdu_ref;
status->device_timestamp = mstat.timestamp;
status->mactime = mstat.timestamp;
BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb));
BUILD_BUG_ON(sizeof(status->chain_signal) !=
@ -737,6 +773,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_wcid *wcid = status->wcid;
struct ieee80211_hdr *hdr;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
int ret;
if (!(status->flag & RX_FLAG_DECRYPTED))
@ -757,12 +794,12 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
}
BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0]));
ret = memcmp(status->iv, wcid->rx_key_pn[status->tid],
ret = memcmp(status->iv, wcid->rx_key_pn[tidno],
sizeof(status->iv));
if (ret <= 0)
return -EINVAL; /* replay */
memcpy(wcid->rx_key_pn[status->tid], status->iv, sizeof(status->iv));
memcpy(wcid->rx_key_pn[tidno], status->iv, sizeof(status->iv));
if (status->flag & RX_FLAG_IV_STRIPPED)
status->flag |= RX_FLAG_PN_VALIDATED;
@ -785,6 +822,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status,
};
struct ieee80211_sta *sta;
u32 airtime;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len);
spin_lock(&dev->cc_lock);
@ -795,7 +833,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status,
return;
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
ieee80211_sta_register_airtime(sta, status->tid, 0, airtime);
ieee80211_sta_register_airtime(sta, tidno, 0, airtime);
}
static void
@ -823,7 +861,6 @@ mt76_airtime_flush_ampdu(struct mt76_dev *dev)
static void
mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_wcid *wcid = status->wcid;
@ -831,6 +868,11 @@ mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)
return;
if (!wcid || !wcid->sta) {
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
if (status->flag & RX_FLAG_8023)
return;
if (!ether_addr_equal(hdr->addr1, dev->phy.macaddr))
return;
@ -864,10 +906,12 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
struct ieee80211_sta *sta;
struct ieee80211_hw *hw;
struct mt76_wcid *wcid = status->wcid;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
bool ps;
hw = mt76_phy_hw(dev, status->ext_phy);
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) {
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid &&
!(status->flag & RX_FLAG_8023)) {
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
if (sta)
wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv;
@ -885,6 +929,9 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
wcid->inactive_count = 0;
if (status->flag & RX_FLAG_8023)
return;
if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags))
return;
@ -902,7 +949,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
if (ps && (ieee80211_is_data_qos(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control)))
ieee80211_sta_uapsd_trigger(sta, status->tid);
ieee80211_sta_uapsd_trigger(sta, tidno);
if (!!test_bit(MT_WCID_FLAG_PS, &wcid->flags) == ps)
return;
@ -926,13 +973,26 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
spin_lock(&dev->rx_lock);
while ((skb = __skb_dequeue(frames)) != NULL) {
struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
if (mt76_check_ccmp_pn(skb)) {
dev_kfree_skb(skb);
continue;
}
skb_shinfo(skb)->frag_list = NULL;
mt76_rx_convert(dev, skb, &hw, &sta);
ieee80211_rx_list(hw, sta, skb, &list);
/* subsequent amsdu frames */
while (nskb) {
skb = nskb;
nskb = nskb->next;
skb->next = NULL;
mt76_rx_convert(dev, skb, &hw, &sta);
ieee80211_rx_list(hw, sta, skb, &list);
}
}
spin_unlock(&dev->rx_lock);

View file

@ -99,6 +99,10 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
dev_kfree_skb(skb);
} while (ret == -EAGAIN);
/* notify driver code to reset the mcu */
if (ret == -ETIMEDOUT && dev->mcu_ops->mcu_reset)
dev->mcu_ops->mcu_reset(dev);
out:
mutex_unlock(&dev->mcu.mutex);

View file

@ -166,6 +166,7 @@ struct mt76_mcu_ops {
int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base,
struct mt76_reg_pair *rp, int len);
int (*mcu_restart)(struct mt76_dev *dev);
void (*mcu_reset)(struct mt76_dev *dev);
};
struct mt76_queue_ops {
@ -190,13 +191,18 @@ struct mt76_queue_ops {
void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q,
bool flush);
void (*rx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q);
void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q);
};
enum mt76_wcid_flags {
MT_WCID_FLAG_CHECK_PS,
MT_WCID_FLAG_PS,
MT_WCID_FLAG_4ADDR,
MT_WCID_FLAG_HDR_TRANS,
};
#define MT76_N_WCIDS 288
@ -222,6 +228,7 @@ struct mt76_wcid {
u16 idx;
u8 hw_key_idx;
u8 hw_key_idx2;
u8 sta:1;
u8 ext_phy:1;
@ -491,15 +498,16 @@ struct mt76_rx_status {
u16 wcid_idx;
};
unsigned long reorder_time;
u32 reorder_time;
u32 ampdu_ref;
u32 timestamp;
u8 iv[6];
u8 ext_phy:1;
u8 aggr:1;
u8 tid;
u8 qos_ctl;
u16 seqno;
u16 freq;
@ -507,6 +515,7 @@ struct mt76_rx_status {
u8 enc_flags;
u8 encoding:2, bw:3, he_ru:3;
u8 he_gi:2, he_dcm:1;
u8 amsdu:1, first_amsdu:1, last_amsdu:1;
u8 rate_idx;
u8 nss;
u8 band;
@ -600,6 +609,12 @@ struct mt76_phy {
struct delayed_work mac_work;
u8 mac_work_count;
struct {
struct sk_buff *head;
struct sk_buff **tail;
u16 seqno;
} rx_amsdu[__MT_RXQ_MAX];
};
struct mt76_dev {
@ -628,6 +643,7 @@ struct mt76_dev {
struct mt76_mcu mcu;
struct net_device napi_dev;
struct net_device tx_napi_dev;
spinlock_t rx_lock;
struct napi_struct napi[__MT_RXQ_MAX];
struct sk_buff_head rx_skb[__MT_RXQ_MAX];
@ -783,8 +799,10 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
#define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__)
#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_rx_cleanup(dev, ...) (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_reset(dev, ...) (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__)
#define mt76_for_each_q_rx(dev, i) \
for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \

View file

@ -223,7 +223,7 @@ int mt7603_dma_init(struct mt7603_dev *dev)
if (ret)
return ret;
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt7603_poll_tx, NAPI_POLL_WEIGHT);
napi_enable(&dev->mt76.tx_napi);

View file

@ -548,6 +548,9 @@ int mt7603_register_device(struct mt7603_dev *dev)
hw->max_report_rates = 7;
hw->max_rate_tries = 11;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
hw->sta_data_size = sizeof(struct mt7603_sta);
hw->vif_data_size = sizeof(struct mt7603_vif);

View file

@ -532,20 +532,6 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
}
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
MT_RXD2_NORMAL_NON_AMPDU))) {
status->flag |= RX_FLAG_AMPDU_DETAILS;
/* all subframes of an A-MPDU have the same timestamp */
if (dev->rx_ampdu_ts != rxd[12]) {
if (!++dev->ampdu_ref)
dev->ampdu_ref++;
}
dev->rx_ampdu_ts = rxd[12];
status->ampdu_ref = dev->ampdu_ref;
}
remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET;
if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
@ -579,6 +565,23 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
return -EINVAL;
}
if (rxd0 & MT_RXD0_NORMAL_GROUP_2) {
status->timestamp = le32_to_cpu(rxd[0]);
status->flag |= RX_FLAG_MACTIME_START;
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
MT_RXD2_NORMAL_NON_AMPDU))) {
status->flag |= RX_FLAG_AMPDU_DETAILS;
/* all subframes of an A-MPDU have the same timestamp */
if (dev->rx_ampdu_ts != status->timestamp) {
if (!++dev->ampdu_ref)
dev->ampdu_ref++;
}
dev->rx_ampdu_ts = status->timestamp;
status->ampdu_ref = dev->ampdu_ref;
}
rxd += 2;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
@ -651,7 +654,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(hdr->frame_control);
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
return 0;

View file

@ -120,7 +120,7 @@ struct mt7603_dev {
unsigned long last_cca_adj;
u32 ampdu_ref;
__le32 rx_ampdu_ts;
u32 rx_ampdu_ts;
u8 rssi_offset[3];
u8 slottime;

View file

@ -7,7 +7,7 @@
#include "mt7603.h"
static const struct pci_device_id mt76pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7603) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7603) },
{ },
};

View file

@ -517,18 +517,23 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
&fops_pm_idle_timeout);
debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,
mt7615_radio_read);
debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);
/* test pattern knobs */
debugfs_create_u8("pattern_len", 0600, dir,
&dev->radar_pattern.n_pulses);
debugfs_create_u32("pulse_period", 0600, dir,
&dev->radar_pattern.period);
debugfs_create_u16("pulse_width", 0600, dir,
&dev->radar_pattern.width);
debugfs_create_u16("pulse_power", 0600, dir,
&dev->radar_pattern.power);
debugfs_create_file("radar_trigger", 0200, dir, dev,
&fops_radar_pattern);
if (is_mt7615(&dev->mt76)) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
&dev->hw_pattern);
/* test pattern knobs */
debugfs_create_u8("pattern_len", 0600, dir,
&dev->radar_pattern.n_pulses);
debugfs_create_u32("pulse_period", 0600, dir,
&dev->radar_pattern.period);
debugfs_create_u16("pulse_width", 0600, dir,
&dev->radar_pattern.width);
debugfs_create_u16("pulse_power", 0600, dir,
&dev->radar_pattern.power);
debugfs_create_file("radar_trigger", 0200, dir, dev,
&fops_radar_pattern);
}
debugfs_create_file("reset_test", 0200, dir, dev,
&fops_reset_test);
debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir,

View file

@ -176,6 +176,21 @@ static void mt7663_dma_sched_init(struct mt7615_dev *dev)
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987);
}
void mt7615_dma_start(struct mt7615_dev *dev)
{
/* start dma engine */
mt76_set(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_DMA_EN |
MT_WPDMA_GLO_CFG_RX_DMA_EN |
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
if (is_mt7622(&dev->mt76))
mt7622_dma_sched_init(dev);
if (is_mt7663(&dev->mt76))
mt7663_dma_sched_init(dev);
}
int mt7615_dma_init(struct mt7615_dev *dev)
{
int rx_ring_size = MT7615_RX_RING_SIZE;
@ -245,7 +260,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
if (ret < 0)
return ret;
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt7615_poll_tx, NAPI_POLL_WEIGHT);
napi_enable(&dev->mt76.tx_napi);
@ -253,20 +268,11 @@ int mt7615_dma_init(struct mt7615_dev *dev)
MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000);
/* start dma engine */
mt76_set(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_DMA_EN |
MT_WPDMA_GLO_CFG_RX_DMA_EN);
/* enable interrupts for TX/RX rings */
mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | mt7615_tx_mcu_int_mask(dev) |
MT_INT_MCU_CMD);
if (is_mt7622(&dev->mt76))
mt7622_dma_sched_init(dev);
if (is_mt7663(&dev->mt76))
mt7663_dma_sched_init(dev);
mt7615_dma_start(dev);
return 0;
}

View file

@ -86,6 +86,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev)
switch (val) {
case 0x7615:
case 0x7622:
case 0x7663:
return 0;
default:
return -EINVAL;

View file

@ -116,10 +116,10 @@ mt7615_mac_init(struct mt7615_dev *dev)
mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN);
/* disable hdr translation and hw AMSDU */
mt76_wr(dev, MT_DMA_DCR0,
FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) |
MT_DMA_DCR0_RX_VEC_DROP);
MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN |
MT_DMA_DCR0_RX_HDR_TRANS_EN);
/* disable TDLS filtering */
mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN);
mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN);
@ -129,6 +129,7 @@ mt7615_mac_init(struct mt7615_dev *dev)
} else {
mt7615_init_mac_chain(dev, 1);
}
mt7615_mcu_set_rx_hdr_trans_blacklist(dev);
}
static void
@ -330,6 +331,10 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
hw->max_rates = 3;
hw->max_report_rates = 7;
hw->max_rate_tries = 11;
hw->netdev_features = NETIF_F_RXCSUM;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
phy->slottime = 9;
@ -360,11 +365,17 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
if (is_mt7615(&phy->dev->mt76))
hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;
else
hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;
phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
phy->mt76->sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
}
static void
@ -496,16 +507,11 @@ void mt7615_init_device(struct mt7615_dev *dev)
init_waitqueue_head(&dev->reset_wait);
init_waitqueue_head(&dev->phy.roc_wait);
INIT_WORK(&dev->reset_work, mt7615_mac_reset_work);
INIT_WORK(&dev->phy.roc_work, mt7615_roc_work);
timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0);
mt7615_init_wiphy(hw);
dev->pm.idle_timeout = MT7615_PM_TIMEOUT;
dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
mt7615_cap_dbdc_disable(dev);
dev->phy.dfs_state = -1;

View file

@ -234,11 +234,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
u32 rxd0 = le32_to_cpu(rxd[0]);
u32 rxd1 = le32_to_cpu(rxd[1]);
u32 rxd2 = le32_to_cpu(rxd[2]);
__le32 rxd12 = rxd[12];
bool unicast, remove_pad, insert_ccmp_hdr = false;
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false;
int phy_idx;
int i, idx;
u8 chfreq;
u8 chfreq, amsdu_info, qos_ctl = 0;
u16 seq_ctrl = 0;
__le16 fc = 0;
memset(status, 0, sizeof(*status));
@ -254,8 +256,12 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
else
phy_idx = -1;
if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
return -EINVAL;
unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M;
idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2);
hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS;
status->wcid = mt7615_rx_get_wcid(dev, idx, unicast);
if (status->wcid) {
@ -268,6 +274,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
spin_unlock_bh(&dev->sta_poll_lock);
}
if ((rxd0 & csum_mask) == csum_mask)
skb->ip_summed = CHECKSUM_UNNECESSARY;
if (rxd2 & MT_RXD2_NORMAL_FCS_ERR)
status->flag |= RX_FLAG_FAILED_FCS_CRC;
@ -288,6 +297,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
rxd += 4;
if (rxd0 & MT_RXD0_NORMAL_GROUP_4) {
u32 v0 = le32_to_cpu(rxd[0]);
u32 v2 = le32_to_cpu(rxd[2]);
fc = cpu_to_le16(FIELD_GET(MT_RXD4_FRAME_CONTROL, v0));
qos_ctl = FIELD_GET(MT_RXD6_QOS_CTL, v2);
seq_ctrl = FIELD_GET(MT_RXD6_SEQ_CTRL, v2);
rxd += 4;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
@ -312,6 +328,23 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
}
if (rxd0 & MT_RXD0_NORMAL_GROUP_2) {
status->timestamp = le32_to_cpu(rxd[0]);
status->flag |= RX_FLAG_MACTIME_START;
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
MT_RXD2_NORMAL_NON_AMPDU))) {
status->flag |= RX_FLAG_AMPDU_DETAILS;
/* all subframes of an A-MPDU have the same timestamp */
if (phy->rx_ampdu_ts != status->timestamp) {
if (!++phy->ampdu_ref)
phy->ampdu_ref++;
}
phy->rx_ampdu_ts = status->timestamp;
status->ampdu_ref = phy->ampdu_ref;
}
rxd += 2;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
@ -355,20 +388,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
if (!sband->channels)
return -EINVAL;
if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
MT_RXD2_NORMAL_NON_AMPDU))) {
status->flag |= RX_FLAG_AMPDU_DETAILS;
/* all subframes of an A-MPDU have the same timestamp */
if (phy->rx_ampdu_ts != rxd12) {
if (!++phy->ampdu_ref)
phy->ampdu_ref++;
}
phy->rx_ampdu_ts = rxd12;
status->ampdu_ref = phy->ampdu_ref;
}
if (rxd0 & MT_RXD0_NORMAL_GROUP_3) {
u32 rxdg0 = le32_to_cpu(rxd[0]);
u32 rxdg1 = le32_to_cpu(rxd[1]);
@ -446,20 +465,42 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad);
if (insert_ccmp_hdr) {
amsdu_info = FIELD_GET(MT_RXD1_NORMAL_PAYLOAD_FORMAT, rxd1);
status->amsdu = !!amsdu_info;
if (status->amsdu) {
status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME;
status->last_amsdu = amsdu_info == MT_RXD1_LAST_AMSDU_FRAME;
if (!hdr_trans) {
memmove(skb->data + 2, skb->data,
ieee80211_get_hdrlen_from_skb(skb));
skb_pull(skb, 2);
}
}
if (insert_ccmp_hdr && !hdr_trans) {
u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
mt76_insert_ccmp_hdr(skb, key_id);
}
hdr = (struct ieee80211_hdr *)skb->data;
if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
if (!hdr_trans) {
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
if (ieee80211_is_data_qos(fc)) {
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
qos_ctl = *ieee80211_get_qos_ctl(hdr);
}
} else {
status->flag |= RX_FLAG_8023;
}
if (!status->wcid || !ieee80211_is_data_qos(fc))
return 0;
status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(hdr->frame_control);
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
!ieee80211_is_qos_nullfunc(fc);
status->qos_ctl = qos_ctl;
status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
return 0;
}
@ -690,7 +731,7 @@ mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp)
{
int i;
for (i = 1; i < txp->nbuf; i++)
for (i = 0; i < txp->nbuf; i++)
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
}
@ -966,6 +1007,7 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
struct mt7615_dev *dev = phy->dev;
struct mt7615_rate_desc rd;
u32 w5, w27, addr;
u16 idx = sta->vif->mt76.omac_idx;
if (!mt76_is_mmio(&dev->mt76)) {
mt7615_mac_queue_rate_update(phy, sta, probe_rate, rates);
@ -1017,7 +1059,10 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
mt76_wr(dev, addr + 27 * 4, w27);
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
sta->rate_set_tsf = mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0);
sta->rate_set_tsf |= rd.rateset;
@ -1033,7 +1078,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
static int
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key,
enum mt7615_cipher_type cipher,
enum mt7615_cipher_type cipher, u16 cipher_mask,
enum set_key_cmd cmd)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
@ -1050,22 +1095,22 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
memcpy(data + 16, key->key + 24, 8);
memcpy(data + 24, key->key + 16, 8);
} else {
if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher)
memmove(data + 16, data, 16);
if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher)
if (cipher_mask == BIT(cipher))
memcpy(data, key->key, key->keylen);
else if (cipher == MT_CIPHER_BIP_CMAC_128)
else if (cipher != MT_CIPHER_BIP_CMAC_128)
memcpy(data, key->key, 16);
if (cipher == MT_CIPHER_BIP_CMAC_128)
memcpy(data + 16, key->key, 16);
}
} else {
if (wcid->cipher & ~BIT(cipher)) {
if (cipher != MT_CIPHER_BIP_CMAC_128)
memmove(data, data + 16, 16);
if (cipher == MT_CIPHER_BIP_CMAC_128)
memset(data + 16, 0, 16);
} else {
else if (cipher_mask)
memset(data, 0, 16);
if (!cipher_mask)
memset(data, 0, sizeof(data));
}
}
mt76_wr_copy(dev, addr, data, sizeof(data));
return 0;
@ -1073,7 +1118,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static int
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
enum mt7615_cipher_type cipher,
enum mt7615_cipher_type cipher, u16 cipher_mask,
int keyidx, enum set_key_cmd cmd)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
@ -1083,20 +1128,23 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
w0 = mt76_rr(dev, addr);
w1 = mt76_rr(dev, addr + 4);
if (cmd == SET_KEY) {
w0 |= MT_WTBL_W0_RX_KEY_VALID |
FIELD_PREP(MT_WTBL_W0_RX_IK_VALID,
cipher == MT_CIPHER_BIP_CMAC_128);
if (cipher != MT_CIPHER_BIP_CMAC_128 ||
!wcid->cipher)
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
} else {
if (!(wcid->cipher & ~BIT(cipher)))
w0 &= ~(MT_WTBL_W0_RX_KEY_VALID |
MT_WTBL_W0_KEY_IDX);
if (cipher == MT_CIPHER_BIP_CMAC_128)
w0 &= ~MT_WTBL_W0_RX_IK_VALID;
if (cipher_mask)
w0 |= MT_WTBL_W0_RX_KEY_VALID;
else
w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX);
if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128))
w0 |= MT_WTBL_W0_RX_IK_VALID;
else
w0 &= ~MT_WTBL_W0_RX_IK_VALID;
if (cmd == SET_KEY &&
(cipher != MT_CIPHER_BIP_CMAC_128 ||
cipher_mask == BIT(cipher))) {
w0 &= ~MT_WTBL_W0_KEY_IDX;
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
}
mt76_wr(dev, MT_WTBL_RICR0, w0);
mt76_wr(dev, MT_WTBL_RICR1, w1);
@ -1109,24 +1157,25 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static void
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
enum mt7615_cipher_type cipher,
enum mt7615_cipher_type cipher, u16 cipher_mask,
enum set_key_cmd cmd)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
if (cmd == SET_KEY) {
if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher)
mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher));
} else {
if (cipher != MT_CIPHER_BIP_CMAC_128 &&
wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128))
mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
FIELD_PREP(MT_WTBL_W2_KEY_TYPE,
MT_CIPHER_BIP_CMAC_128));
else if (!(wcid->cipher & ~BIT(cipher)))
mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
if (!cipher_mask) {
mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
return;
}
if (cmd != SET_KEY)
return;
if (cipher == MT_CIPHER_BIP_CMAC_128 &&
cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
return;
mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher));
}
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
@ -1135,25 +1184,30 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
enum set_key_cmd cmd)
{
enum mt7615_cipher_type cipher;
u16 cipher_mask = wcid->cipher;
int err;
cipher = mt7615_mac_get_cipher(key->cipher);
if (cipher == MT_CIPHER_NONE)
return -EOPNOTSUPP;
mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd);
err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd);
if (err < 0)
return err;
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd);
if (err < 0)
return err;
if (cmd == SET_KEY)
wcid->cipher |= BIT(cipher);
cipher_mask |= BIT(cipher);
else
wcid->cipher &= ~BIT(cipher);
cipher_mask &= ~BIT(cipher);
mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
cmd);
if (err < 0)
return err;
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
key->keyidx, cmd);
if (err < 0)
return err;
wcid->cipher = cipher_mask;
return 0;
}
@ -1821,10 +1875,8 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy)
int i, aggr;
u32 val, val2;
memset(mib, 0, sizeof(*mib));
mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
MT_MIB_SDR3_FCS_ERR_MASK);
mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
MT_MIB_SDR3_FCS_ERR_MASK);
val = mt76_get_field(dev, MT_MIB_SDR14(ext_phy),
MT_MIB_AMPDU_MPDU_COUNT);
@ -1837,24 +1889,16 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy)
aggr = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
for (i = 0; i < 4; i++) {
val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i));
val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val);
if (val2 > mib->ack_fail_cnt)
mib->ack_fail_cnt = val2;
val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
if (val2 > mib->ba_miss_cnt)
mib->ba_miss_cnt = val2;
mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
mib->ack_fail_cnt += FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK,
val);
val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i));
val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val);
if (val2 > mib->rts_retries_cnt) {
mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
mib->rts_retries_cnt = val2;
}
mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
mib->rts_retries_cnt += FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK,
val);
val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i));
dev->mt76.aggr_stats[aggr++] += val & 0xffff;
dev->mt76.aggr_stats[aggr++] += val >> 16;
}
@ -1924,74 +1968,6 @@ void mt7615_mac_work(struct work_struct *work)
MT7615_WATCHDOG_TIME);
}
static bool
mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state)
{
bool ret;
ret = wait_event_timeout(dev->reset_wait,
(READ_ONCE(dev->reset_state) & state),
MT7615_RESET_TIMEOUT);
WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
return ret;
}
static void
mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct ieee80211_hw *hw = priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
mt7615_mcu_add_beacon(dev, hw, vif,
vif->bss_conf.enable_beacon);
break;
default:
break;
}
}
static void
mt7615_update_beacons(struct mt7615_dev *dev)
{
ieee80211_iterate_active_interfaces(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_update_vif_beacon, dev->mt76.hw);
if (!dev->mt76.phy2)
return;
ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_update_vif_beacon, dev->mt76.phy2->hw);
}
void mt7615_dma_reset(struct mt7615_dev *dev)
{
int i;
mt76_clear(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
usleep_range(1000, 2000);
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i);
}
mt76_set(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
}
EXPORT_SYMBOL_GPL(mt7615_dma_reset);
void mt7615_tx_token_put(struct mt7615_dev *dev)
{
struct mt76_txwi_cache *txwi;
@ -2009,94 +1985,6 @@ void mt7615_tx_token_put(struct mt7615_dev *dev)
}
EXPORT_SYMBOL_GPL(mt7615_tx_token_put);
void mt7615_mac_reset_work(struct work_struct *work)
{
struct mt7615_phy *phy2;
struct mt76_phy *ext_phy;
struct mt7615_dev *dev;
dev = container_of(work, struct mt7615_dev, reset_work);
ext_phy = dev->mt76.phy2;
phy2 = ext_phy ? ext_phy->priv : NULL;
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA))
return;
ieee80211_stop_queues(mt76_hw(dev));
if (ext_phy)
ieee80211_stop_queues(ext_phy->hw);
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
cancel_delayed_work_sync(&dev->mphy.mac_work);
del_timer_sync(&dev->phy.roc_timer);
cancel_work_sync(&dev->phy.roc_work);
if (phy2) {
cancel_delayed_work_sync(&phy2->mt76->mac_work);
del_timer_sync(&phy2->roc_timer);
cancel_work_sync(&phy2->roc_work);
}
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);
if (ext_phy)
mt76_txq_schedule_all(ext_phy);
mt76_worker_disable(&dev->mt76.tx_worker);
napi_disable(&dev->mt76.napi[0]);
napi_disable(&dev->mt76.napi[1]);
napi_disable(&dev->mt76.tx_napi);
mt7615_mutex_acquire(dev);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED);
mt7615_tx_token_put(dev);
idr_init(&dev->token);
if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
mt7615_dma_reset(dev);
mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_INIT);
mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
}
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
napi_enable(&dev->mt76.napi[0]);
napi_schedule(&dev->mt76.napi[0]);
napi_enable(&dev->mt76.napi[1]);
napi_schedule(&dev->mt76.napi[1]);
ieee80211_wake_queues(mt76_hw(dev));
if (ext_phy)
ieee80211_wake_queues(ext_phy->hw);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
mt7615_update_beacons(dev);
mt7615_mutex_release(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT7615_WATCHDOG_TIME);
if (phy2)
ieee80211_queue_delayed_work(ext_phy->hw,
&phy2->mt76->mac_work,
MT7615_WATCHDOG_TIME);
}
static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy)
{
struct mt7615_dev *dev = phy->dev;
@ -2304,8 +2192,10 @@ void mt7615_coredump_work(struct work_struct *work)
break;
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ)
break;
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
dev_kfree_skb(skb);
continue;
}
memcpy(data, skb->data, skb->len);
data += skb->len;

View file

@ -33,6 +33,9 @@ enum rx_pkt_type {
#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26)
#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24)
#define MT_RXD1_FIRST_AMSDU_FRAME GENMASK(1, 0)
#define MT_RXD1_MID_AMSDU_FRAME BIT(1)
#define MT_RXD1_LAST_AMSDU_FRAME BIT(0)
#define MT_RXD1_NORMAL_HDR_TRANS BIT(23)
#define MT_RXD1_NORMAL_HDR_OFFSET BIT(22)
#define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16)
@ -78,6 +81,11 @@ enum rx_pkt_type {
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8)
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXD4_FRAME_CONTROL GENMASK(15, 0)
#define MT_RXD6_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD6_QOS_CTL GENMASK(31, 16)
#define MT_RXV1_ACID_DET_H BIT(31)
#define MT_RXV1_ACID_DET_L BIT(30)
#define MT_RXV1_VHTA2_B8_B3 GENMASK(29, 24)

View file

@ -29,6 +29,7 @@ static int mt7615_start(struct ieee80211_hw *hw)
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
bool running;
int ret;
if (!mt7615_wait_for_mcu_init(dev))
return -EIO;
@ -38,21 +39,38 @@ static int mt7615_start(struct ieee80211_hw *hw)
running = mt7615_dev_running(dev);
if (!running) {
mt7615_mcu_set_pm(dev, 0, 0);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
ret = mt7615_mcu_set_pm(dev, 0, 0);
if (ret)
goto out;
ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
if (ret)
goto out;
mt7615_mac_enable_nf(dev, 0);
}
if (phy != &dev->phy) {
mt7615_mcu_set_pm(dev, 1, 0);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false);
ret = mt7615_mcu_set_pm(dev, 1, 0);
if (ret)
goto out;
ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false);
if (ret)
goto out;
mt7615_mac_enable_nf(dev, 1);
}
if (mt7615_firmware_offload(dev))
mt76_connac_mcu_set_channel_domain(phy->mt76);
if (mt7615_firmware_offload(dev)) {
ret = mt76_connac_mcu_set_channel_domain(phy->mt76);
if (ret)
goto out;
}
mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
if (ret)
goto out;
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
@ -62,9 +80,10 @@ static int mt7615_start(struct ieee80211_hw *hw)
if (!running)
mt7615_mac_reset_counters(dev);
out:
mt7615_mutex_release(dev);
return 0;
return ret;
}
static void mt7615_stop(struct ieee80211_hw *hw)
@ -197,7 +216,9 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
mt7615_mcu_set_dbdc(dev);
ret = mt7615_mcu_set_dbdc(dev);
if (ret)
goto out;
idx = MT7615_WTBL_RESERVED - mvif->mt76.idx;
@ -217,8 +238,6 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
ret = mt7615_mcu_add_dev_info(phy, vif, true);
if (ret)
goto out;
mt7615_mac_set_beacon_filter(phy, vif, true);
out:
mt7615_mutex_release(dev);
@ -234,17 +253,17 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
struct mt7615_phy *phy = mt7615_hw_phy(hw);
int idx = msta->wcid.idx;
/* TODO: disable beacon for the bss */
mt7615_mutex_acquire(dev);
mt7615_mcu_add_bss_info(phy, vif, NULL, false);
mt7615_mcu_sta_add(phy, vif, NULL, false);
mt76_testmode_reset(phy->mt76, true);
if (vif == phy->monitor_vif)
phy->monitor_vif = NULL;
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
mt7615_mac_set_beacon_filter(phy, vif, false);
mt7615_mcu_add_dev_info(phy, vif, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
@ -296,8 +315,13 @@ int mt7615_set_channel(struct mt7615_phy *phy)
mt76_set_channel(phy->mt76);
if (is_mt7615(&dev->mt76) && dev->flash_eeprom) {
mt7615_mcu_apply_rx_dcoc(phy);
mt7615_mcu_apply_tx_dpd(phy);
ret = mt7615_mcu_apply_rx_dcoc(phy);
if (ret)
goto out;
ret = mt7615_mcu_apply_tx_dpd(phy);
if (ret)
goto out;
}
ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH);
@ -306,8 +330,13 @@ int mt7615_set_channel(struct mt7615_phy *phy)
mt7615_mac_set_timing(phy);
ret = mt7615_dfs_init_radar_detector(phy);
if (ret)
goto out;
mt7615_mac_cca_stats_reset(phy);
mt7615_mcu_set_sku_en(phy, true);
ret = mt7615_mcu_set_sku_en(phy, true);
if (ret)
goto out;
mt7615_mac_reset_counters(dev);
phy->noise = 0;
@ -337,7 +366,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv :
&mvif->sta;
struct mt76_wcid *wcid = &msta->wcid;
int idx = key->keyidx, err;
int idx = key->keyidx, err = 0;
u8 *wcid_keyidx = &wcid->hw_key_idx;
/* The hardware does not support per-STA RX GTK, fallback
* to software mode for these.
@ -352,6 +382,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
/* fall back to sw encryption for unsupported ciphers */
switch (key->cipher) {
case WLAN_CIPHER_SUITE_AES_CMAC:
wcid_keyidx = &wcid->hw_key_idx2;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
break;
case WLAN_CIPHER_SUITE_TKIP:
@ -369,12 +400,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mt7615_mutex_acquire(dev);
if (cmd == SET_KEY) {
key->hw_key_idx = wcid->idx;
wcid->hw_key_idx = idx;
} else if (idx == wcid->hw_key_idx) {
wcid->hw_key_idx = -1;
}
if (cmd == SET_KEY)
*wcid_keyidx = idx;
else if (idx == *wcid_keyidx)
*wcid_keyidx = -1;
else
goto out;
mt76_wcid_key_setup(&dev->mt76, wcid,
cmd == SET_KEY ? key : NULL);
@ -383,6 +415,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
else
err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
out:
mt7615_mutex_release(dev);
return err;
@ -526,11 +559,11 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
}
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
mt7615_mcu_add_bss_info(phy, vif, NULL, info->enable_beacon);
mt7615_mcu_sta_add(phy, vif, NULL, info->enable_beacon);
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
mt7615_mcu_add_bss_info(phy, vif, NULL, true);
mt7615_mcu_sta_add(phy, vif, NULL, true);
if (vif->p2p && info->enable_beacon)
if (vif->p2p)
mt7615_mcu_set_p2p_oppps(hw, vif);
}
@ -544,6 +577,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ARP_FILTER)
mt7615_mcu_update_arp_filter(hw, vif, info);
if (changed & BSS_CHANGED_ASSOC)
mt7615_mac_set_beacon_filter(phy, vif, info->assoc);
mt7615_mutex_release(dev);
}
@ -583,15 +619,21 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (err)
return err;
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
mt7615_mcu_add_bss_info(phy, vif, sta, true);
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
err = mt7615_mcu_add_bss_info(phy, vif, sta, true);
if (err)
return err;
}
mt7615_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
mt7615_mcu_sta_add(&dev->phy, vif, sta, true);
err = mt7615_mcu_sta_add(&dev->phy, vif, sta, true);
if (err)
return err;
mt76_connac_power_save_sched(phy->mt76, &dev->pm);
return 0;
return err;
}
EXPORT_SYMBOL_GPL(mt7615_mac_sta_add);
@ -711,13 +753,13 @@ static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
int band = phy != &dev->phy;
int err, band = phy != &dev->phy;
mt7615_mutex_acquire(dev);
mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band);
err = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band);
mt7615_mutex_release(dev);
return 0;
return err;
}
static int
@ -745,16 +787,16 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_RX_START:
mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
params->buf_size);
mt7615_mcu_add_rx_ba(dev, params, true);
ret = mt7615_mcu_add_rx_ba(dev, params, true);
break;
case IEEE80211_AMPDU_RX_STOP:
mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
mt7615_mcu_add_rx_ba(dev, params, false);
ret = mt7615_mcu_add_rx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
mtxq->aggr = true;
mtxq->send_bar = false;
mt7615_mcu_add_tx_ba(dev, params, true);
ret = mt7615_mcu_add_tx_ba(dev, params, true);
ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid);
ieee80211_send_bar(vif, sta->addr, tid,
IEEE80211_SN_TO_SEQ(ssn));
@ -762,7 +804,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
mt7615_mcu_add_tx_ba(dev, params, false);
ret = mt7615_mcu_add_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid);
@ -771,7 +813,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
mt7615_mcu_add_tx_ba(dev, params, false);
ret = mt7615_mcu_add_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
}
@ -803,26 +845,38 @@ mt7615_get_stats(struct ieee80211_hw *hw,
struct mt7615_phy *phy = mt7615_hw_phy(hw);
struct mib_stats *mib = &phy->mib;
mt7615_mutex_acquire(phy->dev);
stats->dot11RTSSuccessCount = mib->rts_cnt;
stats->dot11RTSFailureCount = mib->rts_retries_cnt;
stats->dot11FCSErrorCount = mib->fcs_err_cnt;
stats->dot11ACKFailureCount = mib->ack_fail_cnt;
memset(mib, 0, sizeof(*mib));
mt7615_mutex_release(phy->dev);
return 0;
}
static u64
mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
union {
u64 t64;
u32 t32[2];
} tsf;
u16 idx = mvif->mt76.omac_idx;
u32 reg;
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
mt7615_mutex_acquire(dev);
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */
mt76_set(dev, reg, MT_LPON_TCR_MODE); /* TSF read */
tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0);
tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1);
@ -835,18 +889,24 @@ static void
mt7615_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u64 timestamp)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
union {
u64 t64;
u32 t32[2];
} tsf = { .t64 = timestamp, };
u16 idx = mvif->mt76.omac_idx;
u32 reg;
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
mt7615_mutex_acquire(dev);
mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]);
mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]);
/* TSF software overwrite */
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_WRITE);
mt76_set(dev, reg, MT_LPON_TCR_WRITE);
mt7615_mutex_release(dev);
}
@ -1069,6 +1129,7 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt7615_phy *phy = mt7615_hw_phy(hw);
int err;
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
return 0;
@ -1077,10 +1138,26 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
cancel_work_sync(&phy->roc_work);
mt7615_mutex_acquire(phy->dev);
mt7615_mcu_set_roc(phy, vif, NULL, 0);
err = mt7615_mcu_set_roc(phy, vif, NULL, 0);
mt7615_mutex_release(phy->dev);
return 0;
return err;
}
static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
bool enabled)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
if (enabled)
set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
else
clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
mt7615_mcu_sta_update_hdr_trans(dev, vif, sta);
}
#ifdef CONFIG_PM
@ -1183,6 +1260,7 @@ const struct ieee80211_ops mt7615_ops = {
.sta_remove = mt7615_sta_remove,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
.set_key = mt7615_set_key,
.sta_set_decap_offload = mt7615_sta_set_decap_offload,
.ampdu_action = mt7615_ampdu_action,
.set_rts_threshold = mt7615_set_rts_threshold,
.wake_tx_queue = mt7615_wake_tx_queue,

View file

@ -274,7 +274,7 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val)
sizeof(req), false);
}
static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
{
if (!is_mt7622(&dev->mt76))
return;
@ -283,6 +283,7 @@ static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
MT_INFRACFG_MISC_AP2CONN_WAKE,
!en * MT_INFRACFG_MISC_AP2CONN_WAKE);
}
EXPORT_SYMBOL_GPL(mt7622_trigger_hif_int);
static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)
{
@ -372,6 +373,23 @@ mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
ieee80211_csa_finish(vif);
}
static void
mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb)
{
struct mt7615_phy *ext_phy = mt7615_ext_phy(dev);
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7615_mcu_csa_notify *c;
c = (struct mt7615_mcu_csa_notify *)skb->data;
if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))
mphy = dev->mt76.phy2;
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_mcu_csa_finish, mphy->hw);
}
static void
mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
{
@ -380,7 +398,7 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
r = (struct mt7615_mcu_rdd_report *)skb->data;
if (r->idx && dev->mt76.phy2)
if (r->band_idx && dev->mt76.phy2)
mphy = dev->mt76.phy2;
ieee80211_radar_detected(mphy->hw);
@ -406,7 +424,8 @@ mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb)
break;
}
wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data);
wiphy_info(mt76_hw(dev)->wiphy, "%s: %*s", type,
(int)(skb->len - sizeof(*rxd)), data);
}
static void
@ -419,9 +438,7 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)
mt7615_mcu_rx_radar_detected(dev, skb);
break;
case MCU_EXT_EVENT_CSA_NOTIFY:
ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_mcu_csa_finish, dev);
mt7615_mcu_rx_csa_notify(dev, skb);
break;
case MCU_EXT_EVENT_FW_LOG_2_HOST:
mt7615_mcu_rx_log_message(dev, skb);
@ -685,6 +702,9 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
};
struct sk_buff *skb;
if (!enable)
goto out;
skb = ieee80211_beacon_get_template(hw, vif, &offs);
if (!skb)
return -EINVAL;
@ -714,6 +734,7 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
}
dev_kfree_skb(skb);
out:
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req,
sizeof(req), true);
}
@ -973,7 +994,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable);
if (enable && sta)
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif);
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0);
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
WTBL_RESET_AND_SET, NULL,
@ -987,6 +1008,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
if (sta)
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,
NULL, wtbl_hdr);
mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, &msta->wcid, NULL,
wtbl_hdr);
}
cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE;
@ -1040,6 +1063,9 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev,
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
WTBL_SET, sta_wtbl, &skb);
if (IS_ERR(wtbl_hdr))
return PTR_ERR(wtbl_hdr);
mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx,
sta_wtbl, wtbl_hdr);
@ -1068,10 +1094,15 @@ __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable, int cmd)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt76_wcid *wcid;
struct mt76_sta_cmd_info info = {
.sta = sta,
.vif = vif,
.enable = enable,
.cmd = cmd,
};
wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
return mt76_connac_mcu_add_sta_cmd(phy, vif, sta, wcid, enable, cmd);
info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
return mt76_connac_mcu_add_sta_cmd(phy, &info);
}
static int
@ -1094,6 +1125,25 @@ static const struct mt7615_mcu_ops sta_update_ops = {
.set_fw_ctrl = mt7615_mcu_fw_pmctrl,
};
int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
struct wtbl_req_hdr *wtbl_hdr;
struct sk_buff *skb = NULL;
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
WTBL_SET, NULL, &skb);
if (IS_ERR(wtbl_hdr))
return PTR_ERR(wtbl_hdr);
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, &msta->wcid, NULL, wtbl_hdr);
return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE,
true);
}
static int
mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
{
@ -1120,8 +1170,8 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
__le16 tim_ie_pos;
__le16 csa_ie_pos;
__le16 bcc_ie_pos;
/* 0: enable beacon offload
* 1: disable beacon offload
/* 0: disable beacon offload
* 1: enable beacon offload
* 2: update probe respond offload
*/
u8 enable;
@ -1144,6 +1194,9 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
};
struct sk_buff *skb;
if (!enable)
goto out;
skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs);
if (!skb)
return -EINVAL;
@ -1168,6 +1221,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
}
dev_kfree_skb(skb);
out:
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE,
&req, sizeof(req), true);
}
@ -1427,8 +1481,7 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name)
sizeof(dev->mt76.hw->wiphy->fw_version),
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
if (!is_mt7615(&dev->mt76) &&
!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) {
if (!is_mt7615(&dev->mt76)) {
dev->fw_ver = MT7615_FIRMWARE_V2;
dev->mcu_ops = &sta_update_ops;
} else {
@ -2155,7 +2208,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
.center_chan2 = ieee80211_frequency_to_channel(freq2),
};
if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
@ -2497,6 +2550,26 @@ int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy)
return ret;
}
int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev)
{
struct {
u8 operation;
u8 count;
u8 _rsv[2];
u8 index;
u8 enable;
__le16 etype;
} req = {
.operation = 1,
.count = 1,
.enable = 1,
.etype = cpu_to_le16(ETH_P_PAE),
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS,
&req, sizeof(req), false);
}
int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,
bool enable)
{

View file

@ -176,10 +176,18 @@ struct mt7615_mcu_rxd {
u8 s2d_index;
};
struct mt7615_mcu_csa_notify {
struct mt7615_mcu_rxd rxd;
u8 omac_idx;
u8 csa_count;
u8 rsv[2];
} __packed;
struct mt7615_mcu_rdd_report {
struct mt7615_mcu_rxd rxd;
u8 idx;
u8 band_idx;
u8 long_detected;
u8 constant_prf_detected;
u8 staggered_prf_detected;
@ -362,30 +370,6 @@ enum {
BSS_INFO_MAX_NUM
};
#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_generic) + \
sizeof(struct wtbl_rx) + \
sizeof(struct wtbl_ht) + \
sizeof(struct wtbl_vht) + \
sizeof(struct wtbl_tx_ps) + \
sizeof(struct wtbl_hdr_trans) +\
sizeof(struct wtbl_ba) + \
sizeof(struct wtbl_bf) + \
sizeof(struct wtbl_smps) + \
sizeof(struct wtbl_pn) + \
sizeof(struct wtbl_spe))
#define MT7615_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct sta_rec_basic) + \
sizeof(struct sta_rec_ht) + \
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct tlv) + \
MT7615_WTBL_UPDATE_MAX_SIZE)
#define MT7615_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_ba))
enum {
CH_SWITCH_NORMAL = 0,
CH_SWITCH_SCAN = 3,

View file

@ -1,3 +1,6 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>

View file

@ -133,11 +133,11 @@ struct mt7615_vif {
};
struct mib_stats {
u16 ack_fail_cnt;
u16 fcs_err_cnt;
u16 rts_cnt;
u16 rts_retries_cnt;
u16 ba_miss_cnt;
u32 ack_fail_cnt;
u32 fcs_err_cnt;
u32 rts_cnt;
u32 rts_retries_cnt;
u32 ba_miss_cnt;
unsigned long aggr_per;
};
@ -168,7 +168,7 @@ struct mt7615_phy {
u8 rdd_state;
int dfs_state;
__le32 rx_ampdu_ts;
u32 rx_ampdu_ts;
u32 ampdu_ref;
struct mib_stats mib;
@ -376,6 +376,7 @@ int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev,
enum nl80211_band band);
int mt7615_wait_pdma_busy(struct mt7615_dev *dev);
int mt7615_dma_init(struct mt7615_dev *dev);
void mt7615_dma_start(struct mt7615_dev *dev);
void mt7615_dma_cleanup(struct mt7615_dev *dev);
int mt7615_mcu_init(struct mt7615_dev *dev);
bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev);
@ -408,11 +409,6 @@ static inline bool is_mt7615(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611;
}
static inline bool is_mt7663(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7663;
}
static inline bool is_mt7611(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7611;
@ -524,6 +520,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
void mt7615_mac_work(struct work_struct *work);
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *txwi);
int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev);
int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val);
int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,
const struct mt7615_dfs_pulse *pulse);
@ -557,6 +557,8 @@ u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset);
void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
void mt7615_coredump_work(struct work_struct *work);
void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en);
/* usb */
int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,

View file

@ -13,9 +13,9 @@
#include "mcu.h"
static const struct pci_device_id mt7615_pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7615) },
{ PCI_DEVICE(0x14c3, 0x7663) },
{ PCI_DEVICE(0x14c3, 0x7611) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7615) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7663) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7611) },
{ },
};

View file

@ -126,6 +126,7 @@ int mt7615_register_device(struct mt7615_dev *dev)
int ret;
mt7615_init_device(dev);
INIT_WORK(&dev->reset_work, mt7615_mac_reset_work);
/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {

View file

@ -181,3 +181,171 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
void mt7615_dma_reset(struct mt7615_dev *dev)
{
int i;
mt76_clear(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
usleep_range(1000, 2000);
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
for (i = 0; i < __MT_MCUQ_MAX; i++)
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_reset(dev, i);
mt7615_dma_start(dev);
}
EXPORT_SYMBOL_GPL(mt7615_dma_reset);
static void
mt7615_hif_int_event_trigger(struct mt7615_dev *dev, u8 event)
{
mt76_wr(dev, MT_MCU_INT_EVENT, event);
mt7622_trigger_hif_int(dev, true);
mt7622_trigger_hif_int(dev, false);
}
static bool
mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state)
{
bool ret;
ret = wait_event_timeout(dev->reset_wait,
(READ_ONCE(dev->reset_state) & state),
MT7615_RESET_TIMEOUT);
WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
return ret;
}
static void
mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct ieee80211_hw *hw = priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
mt7615_mcu_add_beacon(dev, hw, vif,
vif->bss_conf.enable_beacon);
break;
default:
break;
}
}
static void
mt7615_update_beacons(struct mt7615_dev *dev)
{
ieee80211_iterate_active_interfaces(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_update_vif_beacon, dev->mt76.hw);
if (!dev->mt76.phy2)
return;
ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_update_vif_beacon, dev->mt76.phy2->hw);
}
void mt7615_mac_reset_work(struct work_struct *work)
{
struct mt7615_phy *phy2;
struct mt76_phy *ext_phy;
struct mt7615_dev *dev;
dev = container_of(work, struct mt7615_dev, reset_work);
ext_phy = dev->mt76.phy2;
phy2 = ext_phy ? ext_phy->priv : NULL;
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA))
return;
ieee80211_stop_queues(mt76_hw(dev));
if (ext_phy)
ieee80211_stop_queues(ext_phy->hw);
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
cancel_delayed_work_sync(&dev->mphy.mac_work);
del_timer_sync(&dev->phy.roc_timer);
cancel_work_sync(&dev->phy.roc_work);
if (phy2) {
set_bit(MT76_RESET, &phy2->mt76->state);
cancel_delayed_work_sync(&phy2->mt76->mac_work);
del_timer_sync(&phy2->roc_timer);
cancel_work_sync(&phy2->roc_work);
}
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);
if (ext_phy)
mt76_txq_schedule_all(ext_phy);
mt76_worker_disable(&dev->mt76.tx_worker);
napi_disable(&dev->mt76.napi[0]);
napi_disable(&dev->mt76.napi[1]);
napi_disable(&dev->mt76.tx_napi);
mt7615_mutex_acquire(dev);
mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_STOPPED);
mt7615_tx_token_put(dev);
idr_init(&dev->token);
if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
mt7615_dma_reset(dev);
mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0);
mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_INIT);
mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
}
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
if (phy2)
clear_bit(MT76_RESET, &phy2->mt76->state);
mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
napi_enable(&dev->mt76.napi[0]);
napi_schedule(&dev->mt76.napi[0]);
napi_enable(&dev->mt76.napi[1]);
napi_schedule(&dev->mt76.napi[1]);
ieee80211_wake_queues(mt76_hw(dev));
if (ext_phy)
ieee80211_wake_queues(ext_phy->hw);
mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_RESET_DONE);
mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
mt7615_update_beacons(dev);
mt7615_mutex_release(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT7615_WATCHDOG_TIME);
if (phy2)
ieee80211_queue_delayed_work(ext_phy->hw,
&phy2->mt76->mac_work,
MT7615_WATCHDOG_TIME);
}

View file

@ -368,7 +368,9 @@ enum mt7615_reg_base {
#define MT_DMA_DCR0 MT_WF_DMA(0x000)
#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2)
#define MT_DMA_DCR0_DAMSDU_EN BIT(16)
#define MT_DMA_DCR0_RX_VEC_DROP BIT(17)
#define MT_DMA_DCR0_RX_HDR_TRANS_EN BIT(19)
#define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40)
#define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2)
@ -447,9 +449,10 @@ enum mt7615_reg_base {
#define MT_LPON(_n) ((dev)->reg_map[MT_LPON_BASE] + (_n))
#define MT_LPON_T0CR MT_LPON(0x010)
#define MT_LPON_T0CR_MODE GENMASK(1, 0)
#define MT_LPON_T0CR_WRITE BIT(0)
#define MT_LPON_TCR0(_n) MT_LPON(0x010 + ((_n) * 4))
#define MT_LPON_TCR2(_n) MT_LPON(0x0f8 + ((_n) - 2) * 4)
#define MT_LPON_TCR_MODE GENMASK(1, 0)
#define MT_LPON_TCR_WRITE BIT(0)
#define MT_LPON_UTTR0 MT_LPON(0x018)
#define MT_LPON_UTTR1 MT_LPON(0x01c)

View file

@ -218,12 +218,15 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
int qid, err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0;
bool mcu = q == dev->q_mcu[MT_MCUQ_WM];
struct mt76_sdio *sdio = &dev->sdio;
u8 pad;
qid = mcu ? ARRAY_SIZE(sdio->xmit_buf) - 1 : q->qid;
while (q->first != q->head) {
struct mt76_queue_entry *e = &q->entry[q->first];
struct sk_buff *iter;
smp_rmb();
if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) {
__skb_put_zero(e->skb, 4);
err = __mt7663s_xmit_queue(dev, e->skb->data,
@ -234,7 +237,8 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
goto next;
}
if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ)
pad = roundup(e->skb->len, 4) - e->skb->len;
if (len + e->skb->len + pad + 4 > MT76S_XMIT_BUF_SZ)
break;
if (mt7663s_tx_pick_quota(sdio, mcu, e->buf_sz, &pse_sz,
@ -252,6 +256,11 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
len += iter->len;
nframes++;
}
if (unlikely(pad)) {
memset(sdio->xmit_buf[qid] + len, 0, pad);
len += pad;
}
next:
q->first = (q->first + 1) % q->ndesc;
e->done = true;

View file

@ -67,6 +67,7 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
struct mt7615_rate_desc *rate = &wrd->rate;
struct mt7615_sta *sta = wrd->sta;
u32 w5, w27, addr, val;
u16 idx = sta->vif->mt76.omac_idx;
lockdep_assert_held(&dev->mt76.mutex);
@ -118,7 +119,10 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
sta->rate_probe = sta->rateset[rate->rateset].probe_rate.idx != -1;
mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */
idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
val = mt76_rr(dev, MT_LPON_UTTR0);
sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset;

View file

@ -73,6 +73,11 @@ static inline bool is_mt7921(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7961;
}
static inline bool is_mt7663(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7663;
}
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
void mt76_connac_power_save_sched(struct mt76_phy *phy,
struct mt76_connac_pm *pm);

View file

@ -287,7 +287,7 @@ mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid,
&hdr.wlan_idx_hi);
if (!nskb) {
nskb = mt76_mcu_msg_alloc(dev, NULL,
MT76_CONNAC_WTBL_UPDATE_BA_SIZE);
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE);
if (!nskb)
return ERR_PTR(-ENOMEM);
@ -392,6 +392,21 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif,
uapsd->max_sp = sta->max_sp;
}
void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
struct mt76_wcid *wcid,
void *sta_wtbl, void *wtbl_tlv)
{
struct wtbl_hdr_trans *htr;
struct tlv *tlv;
tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS,
sizeof(*htr),
wtbl_tlv, sta_wtbl);
htr = (struct wtbl_hdr_trans *)tlv;
htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);
void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,
struct sk_buff *skb,
struct ieee80211_vif *vif,
@ -655,7 +670,8 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
struct ieee80211_vif *vif,
u8 rcpi)
{
struct cfg80211_chan_def *chandef = &mphy->chandef;
enum nl80211_band band = chandef->chan->band;
@ -704,6 +720,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
phy = (struct sta_rec_phy *)tlv;
phy->phy_type = mt76_connac_get_phy_mode_v2(mphy, vif, band, sta);
phy->basic_rate = cpu_to_le16((u16)vif->bss_conf.basic_rates);
phy->rcpi = rcpi;
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info));
ra_info = (struct sta_rec_ra_info *)tlv;
@ -808,40 +825,42 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv);
int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct mt76_wcid *wcid,
bool enable, int cmd)
struct mt76_sta_cmd_info *info)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv;
struct mt76_dev *dev = phy->dev;
struct wtbl_req_hdr *wtbl_hdr;
struct tlv *sta_wtbl;
struct sk_buff *skb;
skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);
skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid);
if (IS_ERR(skb))
return PTR_ERR(skb);
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable);
if (enable && sta)
mt76_connac_mcu_sta_tlv(phy, skb, sta, vif);
mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta, info->enable);
if (info->enable && info->sta)
mt76_connac_mcu_sta_tlv(phy, skb, info->sta, info->vif,
info->rcpi);
sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
sizeof(struct tlv));
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid,
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, info->wcid,
WTBL_RESET_AND_SET,
sta_wtbl, &skb);
if (enable) {
mt76_connac_mcu_wtbl_generic_tlv(dev, skb, vif, sta, sta_wtbl,
if (IS_ERR(wtbl_hdr))
return PTR_ERR(wtbl_hdr);
if (info->enable) {
mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif,
info->sta, sta_wtbl,
wtbl_hdr);
if (sta)
mt76_connac_mcu_wtbl_ht_tlv(dev, skb, sta, sta_wtbl,
wtbl_hdr);
if (info->sta)
mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
sta_wtbl, wtbl_hdr);
}
return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_sta_cmd);
@ -946,6 +965,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP:
basic_req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP);
break;
@ -1195,6 +1215,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
.center_chan = ieee80211_frequency_to_channel(freq1),
.center_chan2 = ieee80211_frequency_to_channel(freq2),
.tx_streams = hweight8(phy->antenna_mask),
.ht_op_info = 4, /* set HT 40M allowed */
.rx_streams = phy->chainmask,
.short_st = true,
},
@ -1287,6 +1308,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
case NL80211_CHAN_WIDTH_20:
default:
rlm_req.rlm.bw = CMD_CBW_20MHZ;
rlm_req.rlm.ht_op_info = 0;
break;
}
@ -1306,7 +1328,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct cfg80211_scan_request *sreq = &scan_req->req;
int n_ssids = 0, err, i, duration = MT76_CONNAC_SCAN_CHANNEL_TIME;
int n_ssids = 0, err, i, duration;
int ext_channels_num = max_t(int, sreq->n_channels - 32, 0);
struct ieee80211_channel **scan_list = sreq->channels;
struct mt76_dev *mdev = phy->dev;
@ -1343,6 +1365,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
req->ssid_type_ext = n_ssids ? BIT(0) : 0;
req->ssids_num = n_ssids;
duration = is_mt7921(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;
/* increase channel time for passive scan */
if (!sreq->n_ssids)
duration *= 2;
@ -1368,11 +1391,14 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
req->ies_len = cpu_to_le16(sreq->ie_len);
}
if (is_mt7921(phy->dev))
req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
memcpy(req->bssid, sreq->bssid, ETH_ALEN);
if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
get_random_mask_addr(req->random_mac, sreq->mac_addr,
sreq->mac_addr_mask);
req->scan_func = 1;
req->scan_func |= SCAN_FUNC_RANDOM_MAC;
}
err = mt76_mcu_skb_send_msg(mdev, skb, MCU_CMD_START_HW_SCAN, false);
@ -1433,10 +1459,13 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
req->version = 1;
req->seq_num = mvif->scan_seq_num | ext_phy << 7;
if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
get_random_mask_addr(req->random_mac, sreq->mac_addr,
if (is_mt7663(phy->dev) &&
(sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) {
get_random_mask_addr(req->mt7663.random_mac, sreq->mac_addr,
sreq->mac_addr_mask);
req->scan_func = 1;
} else if (is_mt7921(phy->dev)) {
req->mt7921.bss_idx = mvif->idx;
}
req->ssids_num = sreq->n_ssids;

View file

@ -210,7 +210,7 @@ struct wtbl_hdr_trans {
__le16 len;
u8 to_ds;
u8 from_ds;
u8 disable_rx_trans;
u8 no_rx_trans;
u8 rsv;
} __packed;
@ -304,9 +304,6 @@ struct wtbl_raw {
sizeof(struct tlv) + \
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
#define MT76_CONNAC_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_ba))
enum {
STA_REC_BASIC,
STA_REC_RA,
@ -365,6 +362,9 @@ enum {
#define NETWORK_IBSS BIT(18)
#define NETWORK_WDS BIT(21)
#define SCAN_FUNC_RANDOM_MAC BIT(0)
#define SCAN_FUNC_SPLIT_SCAN BIT(5)
#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA)
#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P)
@ -759,11 +759,19 @@ struct mt76_connac_sched_scan_req {
u8 channel_type;
u8 channels_num;
u8 intervals_num;
u8 scan_func; /* BIT(0) eable random mac address */
u8 scan_func; /* MT7663: BIT(0) eable random mac address */
struct mt76_connac_mcu_scan_channel channels[64];
__le16 intervals[MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL];
u8 random_mac[ETH_ALEN]; /* valid when BIT(0) in scan_func is set */
u8 pad2[58];
union {
struct {
u8 random_mac[ETH_ALEN];
u8 pad2[58];
} mt7663;
struct {
u8 bss_idx;
u8 pad2[63];
} mt7921;
};
} __packed;
struct mt76_connac_sched_scan_done {
@ -876,6 +884,17 @@ struct mt76_connac_suspend_tlv {
u8 pad[5];
} __packed;
struct mt76_sta_cmd_info {
struct ieee80211_sta *sta;
struct mt76_wcid *wcid;
struct ieee80211_vif *vif;
bool enable;
int cmd;
u8 rcpi;
};
#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
@ -917,9 +936,13 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *sta_wtbl,
void *wtbl_tlv);
void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
struct mt76_wcid *wcid,
void *sta_wtbl, void *wtbl_tlv);
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
struct ieee80211_sta *sta,
struct ieee80211_vif *vif);
struct ieee80211_vif *vif,
u8 rcpi);
void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta, void *sta_wtbl,
void *wtbl_tlv);
@ -942,10 +965,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
struct mt76_wcid *wcid,
bool enable);
int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct mt76_wcid *wcid,
bool enable, int cmd);
struct mt76_sta_cmd_info *info);
void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band);

View file

@ -221,9 +221,9 @@ mt76x0e_remove(struct pci_dev *pdev)
}
static const struct pci_device_id mt76x0e_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7610) },
{ PCI_DEVICE(0x14c3, 0x7630) },
{ PCI_DEVICE(0x14c3, 0x7650) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7610) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7630) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7650) },
{ },
};

View file

@ -32,7 +32,8 @@ static struct usb_device_id mt76x0_device_table[] = {
{ USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH */
{ USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
{ USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac Stick */
{ USB_DEVICE(0x2357, 0x0123) }, /* TP-LINK T2UHP */
{ USB_DEVICE(0x2357, 0x0123) }, /* TP-LINK T2UHP_US_v1 */
{ USB_DEVICE(0x2357, 0x010b) }, /* TP-LINK T2UHP_UN_v1 */
/* TP-LINK Archer T1U */
{ USB_DEVICE(0x2357, 0x0105), .driver_info = 1, },
/* MT7630U */

View file

@ -770,6 +770,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
void *rxi)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_hdr *hdr;
struct mt76x02_rxwi *rxwi = rxi;
struct mt76x02_sta *sta;
u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
@ -864,7 +865,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->freq = dev->mphy.chandef.chan->center_freq;
status->band = dev->mphy.chandef.chan->band;
status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
hdr = (struct ieee80211_hdr *)skb->data;
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
return mt76x02_mac_process_rate(dev, status, rate);

View file

@ -230,7 +230,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
if (ret)
return ret;
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
mt76x02_poll_tx, NAPI_POLL_WEIGHT);
napi_enable(&dev->mt76.tx_napi);

View file

@ -447,6 +447,10 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
return -EOPNOTSUPP;
/* MT76x0 GTK offloading does not work with more than one VIF */
if (is_mt76x0(dev) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
return -EOPNOTSUPP;
msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
wcid = msta ? &msta->wcid : &mvif->group_wcid;

View file

@ -10,9 +10,9 @@
#include "mt76x2.h"
static const struct pci_device_id mt76x2e_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7662) },
{ PCI_DEVICE(0x14c3, 0x7612) },
{ PCI_DEVICE(0x14c3, 0x7602) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7662) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7612) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7602) },
{ },
};

View file

@ -3,6 +3,6 @@
obj-$(CONFIG_MT7915E) += mt7915e.o
mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
debugfs.o
debugfs.o mmio.o
mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o

View file

@ -124,7 +124,7 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i));
for (i = 0; i < ARRAY_SIZE(bound); i++)
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1;
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
seq_printf(file, "\nPhy %d\n", ext_phy);

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