diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-21 18:24:12 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-21 18:24:12 -0800 |
commit | 5b7c4cabbb65f5c469464da6c5f614cbd7f730f2 (patch) | |
tree | cc5c2d0a898769fd59549594fedb3ee6f84e59a0 /drivers/net/wireless/mediatek/mt76/mt7996 | |
parent | 36289a03bcd3aabdf66de75cb6d1b4ee15726438 (diff) | |
parent | d1fabc68f8e0541d41657096dc713cb01775652d (diff) |
Merge tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski:
"Core:
- Add dedicated kmem_cache for typical/small skb->head, avoid having
to access struct page at kfree time, and improve memory use.
- Introduce sysctl to set default RPS configuration for new netdevs.
- Define Netlink protocol specification format which can be used to
describe messages used by each family and auto-generate parsers.
Add tools for generating kernel data structures and uAPI headers.
- Expose all net/core sysctls inside netns.
- Remove 4s sleep in netpoll if carrier is instantly detected on
boot.
- Add configurable limit of MDB entries per port, and port-vlan.
- Continue populating drop reasons throughout the stack.
- Retire a handful of legacy Qdiscs and classifiers.
Protocols:
- Support IPv4 big TCP (TSO frames larger than 64kB).
- Add IP_LOCAL_PORT_RANGE socket option, to control local port range
on socket by socket basis.
- Track and report in procfs number of MPTCP sockets used.
- Support mixing IPv4 and IPv6 flows in the in-kernel MPTCP path
manager.
- IPv6: don't check net.ipv6.route.max_size and rely on garbage
collection to free memory (similarly to IPv4).
- Support Penultimate Segment Pop (PSP) flavor in SRv6 (RFC8986).
- ICMP: add per-rate limit counters.
- Add support for user scanning requests in ieee802154.
- Remove static WEP support.
- Support minimal Wi-Fi 7 Extremely High Throughput (EHT) rate
reporting.
- WiFi 7 EHT channel puncturing support (client & AP).
BPF:
- Add a rbtree data structure following the "next-gen data structure"
precedent set by recently added linked list, that is, by using
kfunc + kptr instead of adding a new BPF map type.
- Expose XDP hints via kfuncs with initial support for RX hash and
timestamp metadata.
- Add BPF_F_NO_TUNNEL_KEY extension to bpf_skb_set_tunnel_key to
better support decap on GRE tunnel devices not operating in collect
metadata.
- Improve x86 JIT's codegen for PROBE_MEM runtime error checks.
- Remove the need for trace_printk_lock for bpf_trace_printk and
bpf_trace_vprintk helpers.
- Extend libbpf's bpf_tracing.h support for tracing arguments of
kprobes/uprobes and syscall as a special case.
- Significantly reduce the search time for module symbols by
livepatch and BPF.
- Enable cpumasks to be used as kptrs, which is useful for tracing
programs tracking which tasks end up running on which CPUs in
different time intervals.
- Add support for BPF trampoline on s390x and riscv64.
- Add capability to export the XDP features supported by the NIC.
- Add __bpf_kfunc tag for marking kernel functions as kfuncs.
- Add cgroup.memory=nobpf kernel parameter option to disable BPF
memory accounting for container environments.
Netfilter:
- Remove the CLUSTERIP target. It has been marked as obsolete for
years, and we still have WARN splats wrt races of the out-of-band
/proc interface installed by this target.
- Add 'destroy' commands to nf_tables. They are identical to the
existing 'delete' commands, but do not return an error if the
referenced object (set, chain, rule...) did not exist.
Driver API:
- Improve cpumask_local_spread() locality to help NICs set the right
IRQ affinity on AMD platforms.
- Separate C22 and C45 MDIO bus transactions more clearly.
- Introduce new DCB table to control DSCP rewrite on egress.
- Support configuration of Physical Layer Collision Avoidance (PLCA)
Reconciliation Sublayer (RS) (802.3cg-2019). Modern version of
shared medium Ethernet.
- Support for MAC Merge layer (IEEE 802.3-2018 clause 99). Allowing
preemption of low priority frames by high priority frames.
- Add support for controlling MACSec offload using netlink SET.
- Rework devlink instance refcounts to allow registration and
de-registration under the instance lock. Split the code into
multiple files, drop some of the unnecessarily granular locks and
factor out common parts of netlink operation handling.
- Add TX frame aggregation parameters (for USB drivers).
- Add a new attr TCA_EXT_WARN_MSG to report TC (offload) warning
messages with notifications for debug.
- Allow offloading of UDP NEW connections via act_ct.
- Add support for per action HW stats in TC.
- Support hardware miss to TC action (continue processing in SW from
a specific point in the action chain).
- Warn if old Wireless Extension user space interface is used with
modern cfg80211/mac80211 drivers. Do not support Wireless
Extensions for Wi-Fi 7 devices at all. Everyone should switch to
using nl80211 interface instead.
- Improve the CAN bit timing configuration. Use extack to return
error messages directly to user space, update the SJW handling,
including the definition of a new default value that will benefit
CAN-FD controllers, by increasing their oscillator tolerance.
New hardware / drivers:
- Ethernet:
- nVidia BlueField-3 support (control traffic driver)
- Ethernet support for imx93 SoCs
- Motorcomm yt8531 gigabit Ethernet PHY
- onsemi NCN26000 10BASE-T1S PHY (with support for PLCA)
- Microchip LAN8841 PHY (incl. cable diagnostics and PTP)
- Amlogic gxl MDIO mux
- WiFi:
- RealTek RTL8188EU (rtl8xxxu)
- Qualcomm Wi-Fi 7 devices (ath12k)
- CAN:
- Renesas R-Car V4H
Drivers:
- Bluetooth:
- Set Per Platform Antenna Gain (PPAG) for Intel controllers.
- Ethernet NICs:
- Intel (1G, igc):
- support TSN / Qbv / packet scheduling features of i226 model
- Intel (100G, ice):
- use GNSS subsystem instead of TTY
- multi-buffer XDP support
- extend support for GPIO pins to E823 devices
- nVidia/Mellanox:
- update the shared buffer configuration on PFC commands
- implement PTP adjphase function for HW offset control
- TC support for Geneve and GRE with VF tunnel offload
- more efficient crypto key management method
- multi-port eswitch support
- Netronome/Corigine:
- add DCB IEEE support
- support IPsec offloading for NFP3800
- Freescale/NXP (enetc):
- support XDP_REDIRECT for XDP non-linear buffers
- improve reconfig, avoid link flap and waiting for idle
- support MAC Merge layer
- Other NICs:
- sfc/ef100: add basic devlink support for ef100
- ionic: rx_push mode operation (writing descriptors via MMIO)
- bnxt: use the auxiliary bus abstraction for RDMA
- r8169: disable ASPM and reset bus in case of tx timeout
- cpsw: support QSGMII mode for J721e CPSW9G
- cpts: support pulse-per-second output
- ngbe: add an mdio bus driver
- usbnet: optimize usbnet_bh() by avoiding unnecessary queuing
- r8152: handle devices with FW with NCM support
- amd-xgbe: support 10Mbps, 2.5GbE speeds and rx-adaptation
- virtio-net: support multi buffer XDP
- virtio/vsock: replace virtio_vsock_pkt with sk_buff
- tsnep: XDP support
- Ethernet high-speed switches:
- nVidia/Mellanox (mlxsw):
- add support for latency TLV (in FW control messages)
- Microchip (sparx5):
- separate explicit and implicit traffic forwarding rules, make
the implicit rules always active
- add support for egress DSCP rewrite
- IS0 VCAP support (Ingress Classification)
- IS2 VCAP filters (protos, L3 addrs, L4 ports, flags, ToS
etc.)
- ES2 VCAP support (Egress Access Control)
- support for Per-Stream Filtering and Policing (802.1Q,
8.6.5.1)
- Ethernet embedded switches:
- Marvell (mv88e6xxx):
- add MAB (port auth) offload support
- enable PTP receive for mv88e6390
- NXP (ocelot):
- support MAC Merge layer
- support for the the vsc7512 internal copper phys
- Microchip:
- lan9303: convert to PHYLINK
- lan966x: support TC flower filter statistics
- lan937x: PTP support for KSZ9563/KSZ8563 and LAN937x
- lan937x: support Credit Based Shaper configuration
- ksz9477: support Energy Efficient Ethernet
- other:
- qca8k: convert to regmap read/write API, use bulk operations
- rswitch: Improve TX timestamp accuracy
- Intel WiFi (iwlwifi):
- EHT (Wi-Fi 7) rate reporting
- STEP equalizer support: transfer some STEP (connection to radio
on platforms with integrated wifi) related parameters from the
BIOS to the firmware.
- Qualcomm 802.11ax WiFi (ath11k):
- IPQ5018 support
- Fine Timing Measurement (FTM) responder role support
- channel 177 support
- MediaTek WiFi (mt76):
- per-PHY LED support
- mt7996: EHT (Wi-Fi 7) support
- Wireless Ethernet Dispatch (WED) reset support
- switch to using page pool allocator
- RealTek WiFi (rtw89):
- support new version of Bluetooth co-existance
- Mobile:
- rmnet: support TX aggregation"
* tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1872 commits)
page_pool: add a comment explaining the fragment counter usage
net: ethtool: fix __ethtool_dev_mm_supported() implementation
ethtool: pse-pd: Fix double word in comments
xsk: add linux/vmalloc.h to xsk.c
sefltests: netdevsim: wait for devlink instance after netns removal
selftest: fib_tests: Always cleanup before exit
net/mlx5e: Align IPsec ASO result memory to be as required by hardware
net/mlx5e: TC, Set CT miss to the specific ct action instance
net/mlx5e: Rename CHAIN_TO_REG to MAPPED_OBJ_TO_REG
net/mlx5: Refactor tc miss handling to a single function
net/mlx5: Kconfig: Make tc offload depend on tc skb extension
net/sched: flower: Support hardware miss to tc action
net/sched: flower: Move filter handle initialization earlier
net/sched: cls_api: Support hardware miss to tc action
net/sched: Rename user cookie and act cookie
sfc: fix builds without CONFIG_RTC_LIB
sfc: clean up some inconsistent indentings
net/mlx4_en: Introduce flexible array to silence overflow warning
net: lan966x: Fix possible deadlock inside PTP
net/ulp: Remove redundant ->clone() test in inet_clone_ulp().
...
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7996')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/init.c | 416 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 149 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mac.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/main.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 249 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 16 |
11 files changed, 618 insertions, 360 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c index 2e4a8909b9e8..9c5e9ac1c335 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c @@ -457,7 +457,7 @@ mt7996_hw_queue_read(struct seq_file *s, u32 size, if (val & BIT(map[i].index)) continue; - ctrl = BIT(31) | (map[i].pid << 10) | (map[i].qid << 24); + ctrl = BIT(31) | (map[i].pid << 10) | ((u32)map[i].qid << 24); mt76_wr(dev, MT_FL_Q0_CTRL, ctrl); head = mt76_get_field(dev, MT_FL_Q2_CTRL, @@ -653,8 +653,9 @@ static int mt7996_rf_regval_set(void *data, u64 val) { struct mt7996_dev *dev = data; + u32 val32 = val; - return mt7996_mcu_rf_regval(dev, dev->mt76.debugfs_reg, (u32 *)&val, true); + return mt7996_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &val32, true); } DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7996_rf_regval_get, @@ -790,10 +791,10 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file, else buf[count] = '\0'; - /* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9 - * bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3 - * nss - vht: 1~4, he: 1~4, others: ignore - * mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2 + /* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9 EHT: 15 + * bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3, BW320: 4 + * nss - vht: 1~4, he: 1~4, eht: 1~4, others: ignore + * mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2, eht: 0~13 * gi - (ht/vht) lgi: 0, sgi: 1; (he) 0.8us: 0, 1.6us: 1, 3.2us: 2 * preamble - short: 1, long: 0 * ldpc - off: 0, on: 1 diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c index b9f62bedbc48..2e48c5a40f81 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c @@ -65,22 +65,50 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev) } else { u8 free_block_num; u32 block_num, i; + u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE; - /* TODO: check free block event */ - mt7996_mcu_get_eeprom_free_block(dev, &free_block_num); - /* efuse info not enough */ + ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num); + if (ret < 0) + return ret; + + /* efuse info isn't enough */ if (free_block_num >= 59) return -EINVAL; /* read eeprom data from efuse */ - block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, MT7996_EEPROM_BLOCK_SIZE); - for (i = 0; i < block_num; i++) - mt7996_mcu_get_eeprom(dev, i * MT7996_EEPROM_BLOCK_SIZE); + block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size); + for (i = 0; i < block_num; i++) { + ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size); + if (ret < 0) + return ret; + } } return mt7996_check_eeprom(dev); } +static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev) +{ +#define MODE_HE_ONLY BIT(0) +#define WTBL_SIZE_GROUP GENMASK(31, 28) + u32 cap = 0; + int ret; + + ret = mt7996_mcu_get_chip_config(dev, &cap); + if (ret) + return ret; + + if (cap) { + dev->has_eht = !(cap & MODE_HE_ONLY); + dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP); + } + + if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4) + dev->wtbl_size_group = 2; /* set default */ + + return 0; +} + static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy) { u8 *eeprom = phy->dev->mt76.eeprom.data; @@ -127,6 +155,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy) u8 path, nss, band_idx = phy->mt76->band_idx; u8 *eeprom = dev->mt76.eeprom.data; struct mt76_phy *mphy = phy->mt76; + int ret; switch (band_idx) { case MT_BAND1: @@ -161,6 +190,10 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy) dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] + hweight16(mphy->chainmask); + ret = mt7996_eeprom_parse_efuse_hw_cap(dev); + if (ret) + return ret; + return mt7996_eeprom_parse_band_config(phy); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 46b290526092..946da93eed32 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -37,8 +37,7 @@ static const struct ieee80211_iface_combination if_comb[] = { BIT(NL80211_CHAN_WIDTH_20) | BIT(NL80211_CHAN_WIDTH_40) | BIT(NL80211_CHAN_WIDTH_80) | - BIT(NL80211_CHAN_WIDTH_160) | - BIT(NL80211_CHAN_WIDTH_80P80), + BIT(NL80211_CHAN_WIDTH_160), } }; @@ -46,11 +45,11 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev, u8 delay_on, u8 delay_off) { struct mt7996_dev *dev; - struct mt76_dev *mt76; + struct mt76_phy *mphy; u32 val; - mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); - dev = container_of(mt76, struct mt7996_dev, mt76); + mphy = container_of(led_cdev, struct mt76_phy, leds.cdev); + dev = container_of(mphy->dev, struct mt7996_dev, mt76); /* select TX blink mode, 2: only data frames */ mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2); @@ -65,7 +64,7 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev, /* control LED */ val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK; - if (dev->mt76.led_al) + if (mphy->leds.al) val |= MT_LED_CTRL_POLARITY; mt76_wr(dev, MT_LED_CTRL(0), val); @@ -153,10 +152,12 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt76_dev *mdev = &phy->dev->mt76; struct wiphy *wiphy = hw->wiphy; + u16 max_subframes = phy->dev->has_eht ? IEEE80211_MAX_AMPDU_BUF_EHT : + IEEE80211_MAX_AMPDU_BUF_HE; hw->queues = 4; - hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; - hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + hw->max_rx_aggregation_subframes = max_subframes; + hw->max_tx_aggregation_subframes = max_subframes; hw->netdev_features = NETIF_F_RXCSUM; hw->radiotap_timestamp.units_pos = @@ -214,7 +215,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) mt76_set_stream_caps(phy->mt76, true); mt7996_set_stream_vht_txbf_caps(phy); - mt7996_set_stream_he_caps(phy); + mt7996_set_stream_he_eht_caps(phy); wiphy->available_antennas_rx = phy->mt76->antenna_mask; wiphy->available_antennas_tx = phy->mt76->antenna_mask; @@ -256,12 +257,12 @@ static void mt7996_mac_init(struct mt7996_dev *dev) mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT); - for (i = 0; i < MT7996_WTBL_SIZE; i++) + for (i = 0; i < mt7996_wtbl_size(dev); i++) mt7996_mac_wtbl_update(dev, i, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); if (IS_ENABLED(CONFIG_MT76_LEDS)) { - i = dev->mt76.led_pin ? MT_LED_GPIO_MUX3 : MT_LED_GPIO_MUX2; + i = dev->mphy.leds.pin ? MT_LED_GPIO_MUX3 : MT_LED_GPIO_MUX2; mt76_rmw_field(dev, i, MT_LED_GPIO_SEL_MASK, 4); } @@ -465,7 +466,7 @@ void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy) *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | - (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT); + FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, sts - 1); *cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | @@ -572,11 +573,15 @@ mt7996_gen_ppe_thresh(u8 *he_ppet, int nss) (0xff >> (8 - (ppet_bits - 1) % 8)); } -static int +static void mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, - struct ieee80211_sband_iftype_data *data) + struct ieee80211_sband_iftype_data *data, + enum nl80211_iftype iftype) { - int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask); + struct ieee80211_sta_he_cap *he_cap = &data->he_cap; + struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem; + struct ieee80211_he_mcs_nss_supp *he_mcs = &he_cap->he_mcs_nss_supp; + int i, nss = hweight8(phy->mt76->antenna_mask); u16 mcs_map = 0; for (i = 0; i < 8; i++) { @@ -586,179 +591,254 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band, mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2)); } - for (i = 0; i < NUM_NL80211_IFTYPES; i++) { - struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap; - struct ieee80211_he_cap_elem *he_cap_elem = - &he_cap->he_cap_elem; - struct ieee80211_he_mcs_nss_supp *he_mcs = - &he_cap->he_mcs_nss_supp; - - switch (i) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_AP: -#ifdef CONFIG_MAC80211_MESH - case NL80211_IFTYPE_MESH_POINT: -#endif - break; - default: - continue; - } + he_cap->has_he = true; - data[idx].types_mask = BIT(i); - he_cap->has_he = true; + he_cap_elem->mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE; + he_cap_elem->mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL | + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3; + he_cap_elem->mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU; - he_cap_elem->mac_cap_info[0] = - IEEE80211_HE_MAC_CAP0_HTC_HE; - he_cap_elem->mac_cap_info[3] = - IEEE80211_HE_MAC_CAP3_OMI_CONTROL | - IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3; - he_cap_elem->mac_cap_info[4] = - IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU; + if (band == NL80211_BAND_2GHZ) + he_cap_elem->phy_cap_info[0] = + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; + else + he_cap_elem->phy_cap_info[0] = + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; + + he_cap_elem->phy_cap_info[1] = IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; + he_cap_elem->phy_cap_info[2] = IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | + IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; + + switch (iftype) { + case NL80211_IFTYPE_AP: + he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_RES; + he_cap_elem->mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_BSR; + he_cap_elem->mac_cap_info[4] |= IEEE80211_HE_MAC_CAP4_BQR; + he_cap_elem->mac_cap_info[5] |= + IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX; + he_cap_elem->phy_cap_info[3] |= + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; + he_cap_elem->phy_cap_info[6] |= + IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; + he_cap_elem->phy_cap_info[9] |= + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; + break; + case NL80211_IFTYPE_STATION: + he_cap_elem->mac_cap_info[1] |= + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US; if (band == NL80211_BAND_2GHZ) - he_cap_elem->phy_cap_info[0] = - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; + he_cap_elem->phy_cap_info[0] |= + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G; else - he_cap_elem->phy_cap_info[0] = - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; - - he_cap_elem->phy_cap_info[1] = - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; - he_cap_elem->phy_cap_info[2] = - IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | - IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; + he_cap_elem->phy_cap_info[0] |= + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G; + + he_cap_elem->phy_cap_info[1] |= + IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | + IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; + he_cap_elem->phy_cap_info[3] |= + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; + he_cap_elem->phy_cap_info[6] |= + IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB | + IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; + he_cap_elem->phy_cap_info[7] |= + IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | + IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; + he_cap_elem->phy_cap_info[8] |= + IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | + IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | + IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU | + IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484; + he_cap_elem->phy_cap_info[9] |= + IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM | + IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK | + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | + IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; + break; + default: + break; + } - switch (i) { - case NL80211_IFTYPE_AP: - he_cap_elem->mac_cap_info[0] |= - IEEE80211_HE_MAC_CAP0_TWT_RES; - he_cap_elem->mac_cap_info[2] |= - IEEE80211_HE_MAC_CAP2_BSR; - he_cap_elem->mac_cap_info[4] |= - IEEE80211_HE_MAC_CAP4_BQR; - he_cap_elem->mac_cap_info[5] |= - IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX; - he_cap_elem->phy_cap_info[3] |= - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; - he_cap_elem->phy_cap_info[6] |= - IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | - IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; - he_cap_elem->phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | - IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; - break; - case NL80211_IFTYPE_STATION: - he_cap_elem->mac_cap_info[1] |= - IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US; - - if (band == NL80211_BAND_2GHZ) - he_cap_elem->phy_cap_info[0] |= - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G; - else - he_cap_elem->phy_cap_info[0] |= - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G; - - he_cap_elem->phy_cap_info[1] |= - IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | - IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; - he_cap_elem->phy_cap_info[3] |= - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; - he_cap_elem->phy_cap_info[6] |= - IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB | - IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | - IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; - he_cap_elem->phy_cap_info[7] |= - IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | - IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; - he_cap_elem->phy_cap_info[8] |= - IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | - IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | - IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU | - IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484; - he_cap_elem->phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM | - IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK | - IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | - IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | - IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | - IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; - break; - } + he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map); + he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map); + he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map); + he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map); + + mt7996_set_stream_he_txbf_caps(phy, he_cap, iftype); + + memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); + if (he_cap_elem->phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { + mt7996_gen_ppe_thresh(he_cap->ppe_thres, nss); + } else { + he_cap_elem->phy_cap_info[9] |= + u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, + IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK); + } - he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map); - he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map); - he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map); - he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map); - he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map); - he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map); - - mt7996_set_stream_he_txbf_caps(phy, he_cap, i); - - memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); - if (he_cap_elem->phy_cap_info[6] & - IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt7996_gen_ppe_thresh(he_cap->ppe_thres, nss); - } else { - he_cap_elem->phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US; - } + if (band == NL80211_BAND_6GHZ) { + u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | + IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; - if (band == NL80211_BAND_6GHZ) { - u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | - IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; + cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2, + IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | + u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | + u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); - cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2, - IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | - u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, - IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | - u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, - IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); + data->he_6ghz_capa.capa = cpu_to_le16(cap); + } +} - data[idx].he_6ghz_capa.capa = cpu_to_le16(cap); - } +static void +mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, + struct ieee80211_sband_iftype_data *data, + enum nl80211_iftype iftype) +{ + struct ieee80211_sta_eht_cap *eht_cap = &data->eht_cap; + struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp *eht_nss = &eht_cap->eht_mcs_nss_supp; + enum nl80211_chan_width width = phy->mt76->chandef.width; + int nss = hweight8(phy->mt76->antenna_mask); + int sts = hweight16(phy->mt76->chainmask); + u8 val; - idx++; - } + if (!phy->dev->has_eht) + return; - return idx; + eht_cap->has_eht = true; + + eht_cap_elem->mac_cap_info[0] = + IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | + IEEE80211_EHT_MAC_CAP0_OM_CONTROL; + + eht_cap_elem->phy_cap_info[0] = + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ | + IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; + + eht_cap_elem->phy_cap_info[0] |= + u8_encode_bits(u8_get_bits(sts - 1, BIT(0)), + IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK); + + eht_cap_elem->phy_cap_info[1] = + u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)), + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) | + u8_encode_bits(sts - 1, + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) | + u8_encode_bits(sts - 1, + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK); + + eht_cap_elem->phy_cap_info[2] = + u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) | + u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK) | + u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK); + + eht_cap_elem->phy_cap_info[3] = + IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | + IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | + IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | + IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK; + + eht_cap_elem->phy_cap_info[4] = + u8_encode_bits(min_t(int, sts - 1, 2), + IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK); + + eht_cap_elem->phy_cap_info[5] = + IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | + u8_encode_bits(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US, + IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK) | + u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)), + IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK); + + val = width == NL80211_CHAN_WIDTH_320 ? 0xf : + width == NL80211_CHAN_WIDTH_160 ? 0x7 : + width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1; + eht_cap_elem->phy_cap_info[6] = + u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)), + IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK) | + u8_encode_bits(val, IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK); + + eht_cap_elem->phy_cap_info[7] = + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; + + val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) | + u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_TX); +#define SET_EHT_MAX_NSS(_bw, _val) do { \ + eht_nss->bw._##_bw.rx_tx_mcs9_max_nss = _val; \ + eht_nss->bw._##_bw.rx_tx_mcs11_max_nss = _val; \ + eht_nss->bw._##_bw.rx_tx_mcs13_max_nss = _val; \ + } while (0) + + SET_EHT_MAX_NSS(80, val); + SET_EHT_MAX_NSS(160, val); + SET_EHT_MAX_NSS(320, val); +#undef SET_EHT_MAX_NSS } -void mt7996_set_stream_he_caps(struct mt7996_phy *phy) +static void +__mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy, + struct ieee80211_supported_band *sband, + enum nl80211_band band) { - struct ieee80211_sband_iftype_data *data; - struct ieee80211_supported_band *band; - int n; + struct ieee80211_sband_iftype_data *data = phy->iftype[band]; + int i, n = 0; + + for (i = 0; i < NUM_NL80211_IFTYPES; i++) { + switch (i) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_AP: +#ifdef CONFIG_MAC80211_MESH + case NL80211_IFTYPE_MESH_POINT: +#endif + break; + default: + continue; + } - if (phy->mt76->cap.has_2ghz) { - data = phy->iftype[NL80211_BAND_2GHZ]; - n = mt7996_init_he_caps(phy, NL80211_BAND_2GHZ, data); + data[n].types_mask = BIT(i); + mt7996_init_he_caps(phy, band, &data[n], i); + mt7996_init_eht_caps(phy, band, &data[n], i); - band = &phy->mt76->sband_2g.sband; - band->iftype_data = data; - band->n_iftype_data = n; + n++; } - if (phy->mt76->cap.has_5ghz) { - data = phy->iftype[NL80211_BAND_5GHZ]; - n = mt7996_init_he_caps(phy, NL80211_BAND_5GHZ, data); + sband->iftype_data = data; + sband->n_iftype_data = n; +} - band = &phy->mt76->sband_5g.sband; - band->iftype_data = data; - band->n_iftype_data = n; - } +void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy) +{ + if (phy->mt76->cap.has_2ghz) + __mt7996_set_stream_he_eht_caps(phy, &phy->mt76->sband_2g.sband, + NL80211_BAND_2GHZ); - if (phy->mt76->cap.has_6ghz) { - data = phy->iftype[NL80211_BAND_6GHZ]; - n = mt7996_init_he_caps(phy, NL80211_BAND_6GHZ, data); + if (phy->mt76->cap.has_5ghz) + __mt7996_set_stream_he_eht_caps(phy, &phy->mt76->sband_5g.sband, + NL80211_BAND_5GHZ); - band = &phy->mt76->sband_6g.sband; - band->iftype_data = data; - band->n_iftype_data = n; - } + if (phy->mt76->cap.has_6ghz) + __mt7996_set_stream_he_eht_caps(phy, &phy->mt76->sband_6g.sband, + NL80211_BAND_6GHZ); } int mt7996_register_device(struct mt7996_dev *dev) @@ -787,8 +867,8 @@ int mt7996_register_device(struct mt7996_dev *dev) /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mt76.led_cdev.brightness_set = mt7996_led_set_brightness; - dev->mt76.led_cdev.blink_set = mt7996_led_set_blink; + dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness; + dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink; } ret = mt76_register_device(&dev->mt76, true, mt76_rates, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 0b3e28748e76..c9a9f0e31771 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -189,6 +189,9 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) rate = &msta->wcid.rate; switch (rate->bw) { + case RATE_INFO_BW_320: + bw = IEEE80211_STA_RX_BW_320; + break; case RATE_INFO_BW_160: bw = IEEE80211_STA_RX_BW_160; break; @@ -205,7 +208,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 6); val = mt76_rr(dev, addr); - if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { + if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) { + addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 5); + val = mt76_rr(dev, addr); + rate->eht_gi = FIELD_GET(GENMASK(25, 24), val); + } else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { u8 offs = 24 + 2 * bw; rate->he_gi = (val & (0x3 << offs)) >> offs; @@ -469,7 +476,7 @@ static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) ether_addr_copy(hdr.addr4, eth_hdr->h_source); break; default: - break; + return -EINVAL; } skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2); @@ -560,6 +567,15 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, status->he_dcm = dcm; break; + case MT_PHY_TYPE_EHT_SU: + case MT_PHY_TYPE_EHT_TRIG: + case MT_PHY_TYPE_EHT_MU: + /* TODO: currently report rx rate with HE rate */ + status->nss = nss; + status->encoding = RX_ENC_HE; + bw = min_t(int, bw, IEEE80211_STA_RX_BW_160); + i = min_t(int, i & 0xf, 11); + break; default: return -EINVAL; } @@ -584,6 +600,9 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, case IEEE80211_STA_RX_BW_160: status->bw = RATE_INFO_BW_160; break; + case IEEE80211_STA_RX_BW_320: + status->bw = RATE_INFO_BW_320; + break; default: return -EINVAL; } @@ -959,51 +978,6 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, } } -static u16 -mt7996_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif, - bool beacon, bool mcast) -{ - u8 mode = 0, band = mphy->chandef.chan->band; - int rateidx = 0, mcast_rate; - - if (beacon) { - struct cfg80211_bitrate_mask *mask; - - mask = &vif->bss_conf.beacon_tx_rate; - if (hweight16(mask->control[band].he_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].he_mcs[0]) - 1; - mode = MT_PHY_TYPE_HE_SU; - goto out; - } else if (hweight16(mask->control[band].vht_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].vht_mcs[0]) - 1; - mode = MT_PHY_TYPE_VHT; - goto out; - } else if (hweight8(mask->control[band].ht_mcs[0]) == 1) { - rateidx = ffs(mask->control[band].ht_mcs[0]) - 1; - mode = MT_PHY_TYPE_HT; - goto out; - } else if (hweight32(mask->control[band].legacy) == 1) { - rateidx = ffs(mask->control[band].legacy) - 1; - goto legacy; - } - } - - mcast_rate = vif->bss_conf.mcast_rate[band]; - if (mcast && mcast_rate > 0) - rateidx = mcast_rate - 1; - else - rateidx = ffs(vif->bss_conf.basic_rates) - 1; - -legacy: - rateidx = mt76_calculate_default_rate(mphy, rateidx); - mode = rateidx >> 8; - rateidx &= GENMASK(7, 0); - -out: - return FIELD_PREP(MT_TX_RATE_IDX, rateidx) | - FIELD_PREP(MT_TX_RATE_MODE, mode); -} - void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, int pid, struct ieee80211_key_conf *key, u32 changed) @@ -1091,7 +1065,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, /* Fixed rata is available just for 802.11 txd */ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; bool multicast = is_multicast_ether_addr(hdr->addr1); - u16 rate = mt7996_mac_tx_rate_val(mphy, vif, beacon, multicast); + u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, + multicast); /* fix to bw 20 */ val = MT_TXD6_FIXED_BW | @@ -1113,8 +1088,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; struct ieee80211_vif *vif = info->control.vif; + struct mt76_connac_txp_common *txp; struct mt76_txwi_cache *t; - struct mt7996_txp *txp; int id, i, pid, nbuf = tx_info->nbuf - 1; bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; u8 *txwi = (u8 *)txwi_ptr; @@ -1148,35 +1123,35 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, 0); - txp = (struct mt7996_txp *)(txwi + MT_TXD_SIZE); + txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { - txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); - txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); + txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); + txp->fw.len[i] = cpu_to_le16(tx_info->buf[i + 1].len); } - txp->nbuf = nbuf; + txp->fw.nbuf = nbuf; - txp->flags = cpu_to_le16(MT_CT_INFO_FROM_HOST); + txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST); if (!is_8023 || pid >= MT_PACKET_ID_FIRST) - txp->flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD); + txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD); if (!key) - txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); + txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control)) - txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); + txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); if (vif) { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - txp->bss_idx = mvif->mt76.idx; + txp->fw.bss_idx = mvif->mt76.idx; } - txp->token = cpu_to_le16(id); + txp->fw.token = cpu_to_le16(id); if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) - txp->rept_wds_wcid = cpu_to_le16(wcid->idx); + txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx); else - txp->rept_wds_wcid = cpu_to_le16(0xfff); + txp->fw.rept_wds_wcid = cpu_to_le16(0xfff); tx_info->skb = DMA_DUMMY_DATA; /* pass partial skb header to fw */ @@ -1213,18 +1188,6 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) } static void -mt7996_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t) -{ - struct mt7996_txp *txp; - int i; - - txp = mt7996_txwi_to_txp(dev, t); - 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); -} - -static void mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, struct ieee80211_sta *sta, struct list_head *free_list) { @@ -1233,7 +1196,7 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, __le32 *txwi; u16 wcid_idx; - mt7996_txp_skb_unmap(mdev, t); + mt76_connac_txp_skb_unmap(mdev, t); if (!t->skb) goto out; @@ -1434,6 +1397,15 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid, rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); rate.flags = RATE_INFO_FLAGS_HE_MCS; break; + case MT_PHY_TYPE_EHT_SU: + case MT_PHY_TYPE_EHT_TRIG: + case MT_PHY_TYPE_EHT_MU: + if (rate.mcs > 13) + goto out; + + rate.eht_gi = wcid->rate.eht_gi; + rate.flags = RATE_INFO_FLAGS_EHT_MCS; + break; default: goto out; } @@ -1441,6 +1413,10 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid, stats->tx_mode[mode]++; switch (FIELD_GET(MT_TXS0_BW, txs)) { + case IEEE80211_STA_RX_BW_320: + rate.bw = RATE_INFO_BW_320; + stats->tx_bw[4]++; + break; case IEEE80211_STA_RX_BW_160: rate.bw = RATE_INFO_BW_160; stats->tx_bw[3]++; @@ -1486,7 +1462,7 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) if (pid < MT_PACKET_ID_FIRST) return; - if (wcidx >= MT7996_WTBL_SIZE) + if (wcidx >= mt7996_wtbl_size(dev)) return; rcu_read_lock(); @@ -1589,27 +1565,6 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } } -void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) -{ - if (!e->txwi) { - dev_kfree_skb_any(e->skb); - return; - } - - /* error path */ - if (e->skb == DMA_DUMMY_DATA) { - struct mt76_txwi_cache *t; - struct mt7996_txp *txp; - - txp = mt7996_txwi_to_txp(mdev, e->txwi); - t = mt76_token_put(mdev, le16_to_cpu(txp->token)); - e->skb = t ? t->skb : NULL; - } - - if (e->skb) - mt76_tx_complete_skb(mdev, e->wcid, e->skb); -} - void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy) { struct mt7996_dev *dev = phy->dev; @@ -1690,7 +1645,7 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy) else val = MT7996_CFEND_RATE_11B; - mt76_rmw_field(dev, MT_AGG_ACR0(band_idx), MT_AGG_ACR_CFEND_RATE, val); + mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val); mt76_clear(dev, MT_ARB_SCR(band_idx), MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h index 9f68852012b9..27184cbac619 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h @@ -268,17 +268,6 @@ enum tx_mgnt_type { /* VHT/HE only use bits 0-3 */ #define MT_TX_RATE_IDX GENMASK(5, 0) -struct mt7996_txp { - __le16 flags; - __le16 token; - u8 bss_idx; - __le16 rept_wds_wcid; - u8 nbuf; -#define MT_TXP_MAX_BUF_NUM 6 - __le32 buf[MT_TXP_MAX_BUF_NUM]; - __le16 len[MT_TXP_MAX_BUF_NUM]; -} __packed __aligned(4); - #define MT_TXFREE0_PKT_TYPE GENMASK(31, 27) #define MT_TXFREE0_MSDU_CNT GENMASK(25, 16) #define MT_TXFREE0_RX_BYTE GENMASK(15, 0) @@ -382,17 +371,4 @@ struct mt7996_dfs_radar_spec { struct mt7996_dfs_pattern radar_pattern[16]; }; -static inline struct mt7996_txp * -mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) -{ - u8 *txwi; - - if (!t) - return NULL; - - txwi = mt76_get_txwi_ptr(dev, t); - - return (struct mt7996_txp *)(txwi + MT_TXD_SIZE); -} - #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 4421cd54311b..3e4da0350d96 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -170,7 +170,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, phy->monitor_vif = vif; mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); - if (mvif->mt76.idx >= (MT7996_MAX_INTERFACES << dev->dbdc_support)) { + if (mvif->mt76.idx >= mt7996_max_interface_num(dev)) { ret = -ENOSPC; goto out; } @@ -880,14 +880,17 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) phy->mt76->antenna_mask = tx_ant; /* restore to the origin chainmask which might have auxiliary path */ - if (hweight8(tx_ant) == max_nss) + if (hweight8(tx_ant) == max_nss && band_idx < MT_BAND2) + phy->mt76->chainmask = ((dev->chainmask >> shift) & + (BIT(dev->chainshift[band_idx + 1] - shift) - 1)) << shift; + else if (hweight8(tx_ant) == max_nss) phy->mt76->chainmask = (dev->chainmask >> shift) << shift; else phy->mt76->chainmask = tx_ant << shift; mt76_set_stream_caps(phy->mt76, true); mt7996_set_stream_vht_txbf_caps(phy); - mt7996_set_stream_he_caps(phy); + mt7996_set_stream_he_eht_caps(phy); mutex_unlock(&dev->mt76.mutex); @@ -1081,10 +1084,14 @@ static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_mode_he_ext_su", "v_tx_mode_he_tb", "v_tx_mode_he_mu", + "v_tx_mode_eht_su", + "v_tx_mode_eht_trig", + "v_tx_mode_eht_mu", "v_tx_bw_20", "v_tx_bw_40", "v_tx_bw_80", "v_tx_bw_160", + "v_tx_bw_320", "v_tx_mcs_0", "v_tx_mcs_1", "v_tx_mcs_2", @@ -1097,6 +1104,8 @@ static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_mcs_9", "v_tx_mcs_10", "v_tx_mcs_11", + "v_tx_mcs_12", + "v_tx_mcs_13", }; #define MT7996_SSTATS_LEN ARRAY_SIZE(mt7996_gstrings_stats) @@ -1130,7 +1139,7 @@ static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) if (msta->vif->mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->stats); + mt76_ethtool_worker(wi, &msta->stats, true); } static diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 04e1d10bbd21..dbe30832fd88 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -70,6 +70,7 @@ struct mt7996_fw_region { #define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p) #define HE_MAC(m, c) u8_get_bits(c, IEEE80211_HE_MAC_##m) +#define EHT_PHY(p, c) u8_get_bits(c, IEEE80211_EHT_PHY_##p) static bool sr_scene_detect = true; module_param(sr_scene_detect, bool, 0644); @@ -335,6 +336,9 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) r = (struct mt7996_mcu_rdd_report *)skb->data; + if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys)) + return; + mphy = dev->mt76.phys[r->band_idx]; if (!mphy) return; @@ -412,6 +416,9 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb) struct header *hdr = (struct header *)data; struct tlv *tlv = (struct tlv *)(data + 4); + if (hdr->band >= ARRAY_SIZE(dev->mt76.phys)) + return; + if (hdr->band && dev->mt76.phys[hdr->band]) mphy = dev->mt76.phys[hdr->band]; @@ -765,9 +772,8 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, bss->dtim_period = vif->bss_conf.dtim_period; bss->phymode = mt76_connac_get_phy_mode(phy, vif, chandef->chan->band, NULL); - - if (chandef->chan->band == NL80211_BAND_6GHZ) - bss->phymode_ext |= PHY_MODE_AX_6G; + bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, vif, + chandef->chan->band); return 0; } @@ -903,8 +909,8 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) he = (struct sta_rec_he_v2 *)tlv; for (i = 0; i < 11; i++) { if (i < 6) - he->he_mac_cap[i] = cpu_to_le16(elem->mac_cap_info[i]); - he->he_phy_cap[i] = cpu_to_le16(elem->phy_cap_info[i]); + he->he_mac_cap[i] = elem->mac_cap_info[i]; + he->he_phy_cap[i] = elem->phy_cap_info[i]; } mcs_map = sta->deflink.he_cap.he_mcs_nss_supp; @@ -946,6 +952,35 @@ mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) } static void +mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + struct ieee80211_eht_mcs_nss_supp *mcs_map; + struct ieee80211_eht_cap_elem_fixed *elem; + struct sta_rec_eht *eht; + struct tlv *tlv; + + if (!sta->deflink.eht_cap.has_eht) + return; + + mcs_map = &sta->deflink.eht_cap.eht_mcs_nss_supp; + elem = &sta->deflink.eht_cap.eht_cap_elem; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT, sizeof(*eht)); + + eht = (struct sta_rec_eht *)tlv; + eht->tid_bitmap = 0xff; + eht->mac_cap = cpu_to_le16(*(u16 *)elem->mac_cap_info); + eht->phy_cap = cpu_to_le64(*(u64 *)elem->phy_cap_info); + eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]); + + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) + memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20)); + memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80)); + memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160)); + memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320)); +} + +static void mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) { struct sta_rec_ht *ht; @@ -1019,15 +1054,27 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; - int tx_ant = hweight8(phy->mt76->antenna_mask) - 1; + int sts = hweight16(phy->mt76->chainmask); if (vif->type != NL80211_IFTYPE_STATION && vif->type != NL80211_IFTYPE_AP) return false; - if (!bfee && tx_ant < 2) + if (!bfee && sts < 2) return false; + if (sta->deflink.eht_cap.has_eht) { + struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap; + struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; + + if (bfee) + return mvif->cap.eht_su_ebfee && + EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); + else + return mvif->cap.eht_su_ebfer && + EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]); + } + if (sta->deflink.he_cap.has_he) { struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; @@ -1185,12 +1232,68 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, } static void +mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + struct mt7996_phy *phy, struct sta_rec_bf *bf) +{ + struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap; + struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp; + const struct ieee80211_sta_eht_cap *vc = + mt76_connac_get_eht_phy_cap(phy->mt76, vif); + const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem; + u8 nss_mcs = u8_get_bits(eht_nss->bw._80.rx_tx_mcs9_max_nss, + IEEE80211_EHT_MCS_NSS_RX) - 1; + u8 snd_dim, sts; + + bf->tx_mode = MT_PHY_TYPE_EHT_MU; + + mt7996_mcu_sta_sounding_rate(bf); + + bf->trigger_su = EHT_PHY(CAP3_TRIG_SU_BF_FDBK, pe->phy_cap_info[3]); + bf->trigger_mu = EHT_PHY(CAP3_TRIG_MU_BF_PART_BW_FDBK, pe->phy_cap_info[3]); + snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_80MHZ_MASK, ve->phy_cap_info[2]); + sts = EHT_PHY(CAP0_BEAMFORMEE_SS_80MHZ_MASK, pe->phy_cap_info[0]) + + (EHT_PHY(CAP1_BEAMFORMEE_SS_80MHZ_MASK, pe->phy_cap_info[1]) << 1); + bf->nrow = min_t(u8, snd_dim, sts); + bf->ncol = min_t(u8, nss_mcs, bf->nrow); + bf->ibf_ncol = bf->ncol; + + if (sta->deflink.bandwidth < IEEE80211_STA_RX_BW_160) + return; + + switch (sta->deflink.bandwidth) { + case IEEE80211_STA_RX_BW_160: + snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_160MHZ_MASK, ve->phy_cap_info[2]); + sts = EHT_PHY(CAP1_BEAMFORMEE_SS_160MHZ_MASK, pe->phy_cap_info[1]); + nss_mcs = u8_get_bits(eht_nss->bw._160.rx_tx_mcs9_max_nss, + IEEE80211_EHT_MCS_NSS_RX) - 1; + + bf->nrow_gt_bw80 = min_t(u8, snd_dim, sts); + bf->ncol_gt_bw80 = nss_mcs; + break; + case IEEE80211_STA_RX_BW_320: + snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_320MHZ_MASK, ve->phy_cap_info[2]) + + (EHT_PHY(CAP3_SOUNDING_DIM_320MHZ_MASK, + ve->phy_cap_info[3]) << 1); + sts = EHT_PHY(CAP1_BEAMFORMEE_SS_320MHZ_MASK, pe->phy_cap_info[1]); + nss_mcs = u8_get_bits(eht_nss->bw._320.rx_tx_mcs9_max_nss, + IEEE80211_EHT_MCS_NSS_RX) - 1; + + bf->nrow_gt_bw80 = min_t(u8, snd_dim, sts) << 4; + bf->ncol_gt_bw80 = nss_mcs << 4; + break; + default: + break; + } +} + +static void mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_phy *phy = mvif->phy; - int tx_ant = hweight8(phy->mt76->antenna_mask) - 1; + int tx_ant = hweight8(phy->mt76->chainmask) - 1; struct sta_rec_bf *bf; struct tlv *tlv; const u8 matrix[4][4] = { @@ -1211,11 +1314,13 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); bf = (struct sta_rec_bf *)tlv; - /* he: eBF only, in accordance with spec + /* he/eht: eBF only, in accordance with spec * vht: support eBF and iBF * ht: iBF only, since mac80211 lacks of eBF support */ - if (sta->deflink.he_cap.has_he && ebf) + if (sta->deflink.eht_cap.has_eht && ebf) + mt7996_mcu_sta_bfer_eht(sta, vif, phy, bf); + else if (sta->deflink.he_cap.has_he && ebf) mt7996_mcu_sta_bfer_he(sta, vif, phy, bf); else if (sta->deflink.vht_cap.vht_supported) mt7996_mcu_sta_bfer_vht(sta, phy, bf, ebf); @@ -1430,8 +1535,9 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev, ra->auto_rate = true; ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, sta); ra->channel = chandef->chan->hw_value; - ra->bw = sta->deflink.bandwidth; - ra->phy.bw = sta->deflink.bandwidth; + ra->bw = (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) ? + CMD_CBW_320MHZ : sta->deflink.bandwidth; + ra->phy.bw = ra->bw; ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode); if (supp_rate) { @@ -1613,6 +1719,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif, mt7996_mcu_sta_he_tlv(skb, sta); /* starec he 6g*/ mt7996_mcu_sta_he_6g_tlv(skb, sta); + /* starec eht */ + mt7996_mcu_sta_eht_tlv(skb, sta); /* TODO: starec muru */ /* starec bfee */ mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta); @@ -1809,6 +1917,7 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif, { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_vif_cap *vc = &mvif->cap; + const struct ieee80211_eht_cap_elem_fixed *eht; const struct ieee80211_he_cap_elem *he; const struct ieee80211_vht_cap *vht; const struct ieee80211_ht_cap *ht; @@ -1879,6 +1988,23 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif, HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) && HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]); } + + ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY, + mgmt->u.beacon.variable, len); + if (ie && ie[1] >= sizeof(*eht) + 1) { + const struct ieee80211_sta_eht_cap *pc = + mt76_connac_get_eht_phy_cap(phy->mt76, vif); + const struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; + + eht = (void *)(ie + 3); + + vc->eht_su_ebfer = + EHT_PHY(CAP0_SU_BEAMFORMER, eht->phy_cap_info[0]) && + EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]); + vc->eht_su_ebfee = + EHT_PHY(CAP0_SU_BEAMFORMEE, eht->phy_cap_info[0]) && + EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); + } } int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, @@ -2241,6 +2367,26 @@ mt7996_firmware_state(struct mt7996_dev *dev, bool wa) return 0; } +static int +mt7996_mcu_restart(struct mt76_dev *dev) +{ + struct { + u8 __rsv1[4]; + + __le16 tag; + __le16 len; + u8 power_mode; + u8 __rsv2[3]; + } __packed req = { + .tag = cpu_to_le16(UNI_POWER_OFF), + .len = cpu_to_le16(sizeof(req) - 4), + .power_mode = 1, + }; + + return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(POWER_CTRL), &req, + sizeof(req), false); +} + static int mt7996_load_firmware(struct mt7996_dev *dev) { int ret; @@ -2248,7 +2394,7 @@ static int mt7996_load_firmware(struct mt7996_dev *dev) /* make sure fw is download state */ if (mt7996_firmware_state(dev, false)) { /* restart firmware once */ - __mt76_mcu_restart(&dev->mt76); + mt7996_mcu_restart(&dev->mt76); ret = mt7996_firmware_state(dev, false); if (ret) { dev_err(dev->mt76.dev, @@ -2377,33 +2523,12 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev) MCU_WM_UNI_CMD(VOW), true); } -static int -mt7996_mcu_restart(struct mt76_dev *dev) -{ - struct { - u8 __rsv1[4]; - - __le16 tag; - __le16 len; - u8 power_mode; - u8 __rsv2[3]; - } __packed req = { - .tag = cpu_to_le16(UNI_POWER_OFF), - .len = cpu_to_le16(sizeof(req) - 4), - .power_mode = 1, - }; - - return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(POWER_CREL), &req, - sizeof(req), false); -} - int mt7996_mcu_init(struct mt7996_dev *dev) { static const struct mt76_mcu_ops mt7996_mcu_ops = { .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */ .mcu_skb_send_msg = mt7996_mcu_send_message, .mcu_parse_response = mt7996_mcu_parse_response, - .mcu_restart = mt7996_mcu_restart, }; int ret; @@ -2451,16 +2576,17 @@ int mt7996_mcu_init(struct mt7996_dev *dev) void mt7996_mcu_exit(struct mt7996_dev *dev) { - __mt76_mcu_restart(&dev->mt76); + mt7996_mcu_restart(&dev->mt76); if (mt7996_firmware_state(dev, false)) { dev_err(dev->mt76.dev, "Failed to exit mcu\n"); - return; + goto out; } mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN); if (dev->hif2) mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1), MT_TOP_LPCR_HOST_FW_OWN); +out: skb_queue_purge(&dev->mt76.mcu.res_q); } @@ -2921,8 +3047,9 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset) bool valid; int ret; - ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), &req, - sizeof(req), true, &skb); + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), + &req, sizeof(req), true, &skb); if (ret) return ret; @@ -2970,6 +3097,52 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num) return 0; } +int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap) +{ +#define NIC_CAP 3 +#define UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION 0x21 + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + } __packed req = { + .tag = cpu_to_le16(NIC_CAP), + .len = cpu_to_le16(sizeof(req) - 4), + }; + struct sk_buff *skb; + u8 *buf; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_WM_UNI_CMD_QUERY(CHIP_CONFIG), &req, + sizeof(req), true, &skb); + if (ret) + return ret; + + /* fixed field */ + skb_pull(skb, 4); + + buf = skb->data; + while (buf - skb->data < skb->len) { + struct tlv *tlv = (struct tlv *)buf; + + switch (le16_to_cpu(tlv->tag)) { + case UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION: + *cap = le32_to_cpu(*(__le32 *)(buf + sizeof(*tlv))); + break; + default: + break; + }; + + buf += le16_to_cpu(tlv->len); + } + + dev_kfree_skb(skb); + + return 0; +} + int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index 6084b2337598..dd0c5ac52703 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -347,6 +347,21 @@ struct sta_rec_ba_uni { u8 __rsv[3]; } __packed; +struct sta_rec_eht { + __le16 tag; + __le16 len; + u8 tid_bitmap; + u8 _rsv; + __le16 mac_cap; + __le64 phy_cap; + __le64 phy_cap_ext; + u8 mcs_map_bw20[4]; + u8 mcs_map_bw80[3]; + u8 mcs_map_bw160[3]; + u8 mcs_map_bw320[3]; + u8 _rsv2[3]; +} __packed; + struct sec_key_uni { __le16 wlan_idx; u8 mgmt_prot; @@ -554,6 +569,7 @@ enum { sizeof(struct sta_rec_sec) + \ sizeof(struct sta_rec_ra_fixed) + \ sizeof(struct sta_rec_he_6g_capa) + \ + sizeof(struct sta_rec_eht) + \ sizeof(struct sta_rec_hdrt) + \ sizeof(struct sta_rec_hdr_trans) + \ sizeof(struct tlv)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 521769eb6b0e..902370a2a639 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -21,6 +21,7 @@ static const struct __base mt7996_reg_base[] = { [WF_ETBF_BASE] = { { 0x820ea000, 0x820fa000, 0x830ea000 } }, [WF_LPON_BASE] = { { 0x820eb000, 0x820fb000, 0x830eb000 } }, [WF_MIB_BASE] = { { 0x820ed000, 0x820fd000, 0x830ed000 } }, + [WF_RATE_BASE] = { { 0x820ee000, 0x820fe000, 0x830ee000 } }, }; static const struct __map mt7996_reg_map[] = { @@ -149,7 +150,7 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr) if (dev_is_pci(dev->mt76.dev) && ((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) || - (addr >= MT_CBTOP2_PHY_START && addr <= MT_CBTOP2_PHY_END))) + addr >= MT_CBTOP2_PHY_START)) return mt7996_reg_map_l1(dev, addr); /* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */ @@ -317,7 +318,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, { static const struct mt76_driver_ops drv_ops = { /* txwi_size = txd size + txp size */ - .txwi_size = MT_TXD_SIZE + sizeof(struct mt7996_txp), + .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp), .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ, .survey_flags = SURVEY_INFO_TIME_TX | @@ -325,7 +326,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev, SURVEY_INFO_TIME_BSS_RX, .token_size = MT7996_TOKEN_SIZE, .tx_prepare_skb = mt7996_tx_prepare_skb, - .tx_complete_skb = mt7996_tx_complete_skb, + .tx_complete_skb = mt76_connac_tx_complete_skb, .rx_skb = mt7996_queue_rx_skb, .rx_check = mt7996_rx_check, .rx_poll_complete = mt7996_rx_poll_complete, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 725344791b4c..018dfd2b36b0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -11,12 +11,11 @@ #include "../mt76_connac.h" #include "regs.h" -#define MT7996_MAX_INTERFACES 19 +#define MT7996_MAX_INTERFACES 19 /* per-band */ #define MT7996_MAX_WMM_SETS 4 -#define MT7996_WTBL_SIZE 544 -#define MT7996_WTBL_RESERVED (MT7996_WTBL_SIZE - 1) +#define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1) #define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \ - MT7996_MAX_INTERFACES) + mt7996_max_interface_num(dev)) #define MT7996_WATCHDOG_TIME (HZ / 10) #define MT7996_RESET_TIMEOUT (30 * HZ) @@ -124,6 +123,8 @@ struct mt7996_vif_cap { bool he_su_ebfer:1; bool he_su_ebfee:1; bool he_mu_ebfer:1; + bool eht_su_ebfer:1; + bool eht_su_ebfee:1; }; struct mt7996_vif { @@ -264,6 +265,7 @@ struct mt7996_dev { bool dbdc_support:1; bool tbtc_support:1; bool flash_mode:1; + bool has_eht:1; bool ibf; u8 fw_debug_wm; @@ -281,6 +283,8 @@ struct mt7996_dev { u32 reg_l1_backup; u32 reg_l2_backup; + + u8 wtbl_size_group; }; enum { @@ -419,6 +423,7 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, int mt7996_mcu_set_eeprom(struct mt7996_dev *dev); int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset); int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num); +int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap); int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band); int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action); int mt7996_mcu_set_fcc5_lpn(struct mt7996_dev *dev, int val); @@ -443,6 +448,16 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level); void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb); void mt7996_mcu_exit(struct mt7996_dev *dev); +static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev) +{ + return MT7996_MAX_INTERFACES * (1 + dev->dbdc_support + dev->tbtc_support); +} + +static inline u16 mt7996_wtbl_size(struct mt7996_dev *dev) +{ + return (dev->wtbl_size_group << 8) + 64; +} + void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg, u32 clear, u32 set); @@ -493,7 +508,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); -void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); void mt7996_tx_token_put(struct mt7996_dev *dev); void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); @@ -502,7 +516,7 @@ void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); void mt7996_stats_work(struct work_struct *work); int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force); int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy); -void mt7996_set_stream_he_caps(struct mt7996_phy *phy); +void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy); void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy); void mt7996_update_channel(struct mt76_phy *mphy); int mt7996_init_debugfs(struct mt7996_phy *phy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 794f61b93a46..7a28cae34e34 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -33,6 +33,7 @@ enum base_rev { WF_ETBF_BASE, WF_LPON_BASE, WF_MIB_BASE, + WF_RATE_BASE, __MT_REG_BASE_MAX, }; @@ -235,13 +236,6 @@ enum base_rev { FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) -/* AGG: band 0(0x820e2000), band 1(0x820f2000), band 2(0x830e2000) */ -#define MT_WF_AGG_BASE(_band) __BASE(WF_AGG_BASE, (_band)) -#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) - -#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x054) -#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) - /* ARB: band 0(0x820e3000), band 1(0x820f3000), band 2(0x830e3000) */ #define MT_WF_ARB_BASE(_band) __BASE(WF_ARB_BASE, (_band)) #define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) @@ -300,6 +294,13 @@ enum base_rev { #define MT_WF_RMAC_RSVD0(_band) MT_WF_RMAC(_band, 0x03e0) #define MT_WF_RMAC_RSVD0_EIFS_CLR BIT(21) +/* RATE: band 0(0x820ee000), band 1(0x820fe000), band 2(0x830ee000) */ +#define MT_WF_RATE_BASE(_band) __BASE(WF_RATE_BASE, (_band)) +#define MT_WF_RATE(_band, ofs) (MT_WF_RATE_BASE(_band) + (ofs)) + +#define MT_RATE_HRCR0(_band) MT_WF_RATE(_band, 0x050) +#define MT_RATE_HRCR0_CFEND_RATE GENMASK(14, 0) + /* WFDMA0 */ #define MT_WFDMA0_BASE 0xd4000 #define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs)) @@ -463,7 +464,6 @@ enum base_rev { #define MT_CBTOP1_PHY_START 0x70000000 #define MT_CBTOP1_PHY_END 0x77ffffff #define MT_CBTOP2_PHY_START 0xf0000000 -#define MT_CBTOP2_PHY_END 0xffffffff #define MT_INFRA_MCU_START 0x7c000000 #define MT_INFRA_MCU_END 0x7c3fffff |