diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt index 7e675dafc256..3a76d8faaaed 100644 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt @@ -4,17 +4,27 @@ 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 SoC. -For SoC, use the compatible string "mediatek,mt7628-wmac" and the following -properties: +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 The MAC address can as well be set with corresponding optional properties defined in net/ethernet.txt. @@ -31,6 +41,7 @@ Optional nodes: reg = <0x0000 0 0 0 0>; ieee80211-freq-limit = <5000000 6000000>; mediatek,mtd-eeprom = <&factory 0x8000>; + big-endian; led { led-sources = <2>; @@ -50,3 +61,15 @@ wmac: wmac@10300000 { mediatek,mtd-eeprom = <&factory 0x0000>; }; + +MT7622 example: + +wmac: wmac@18000000 { + compatible = "mediatek,mt7622-wmac"; + reg = <0 0x18000000 0 0x100000>; + interrupts = ; + + mediatek,infracfg = <&infracfg>; + + power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>; +}; diff --git a/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt b/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt index f38950560982..88fd28d15eac 100644 --- a/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt +++ b/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt @@ -9,11 +9,12 @@ Required properties: - spi-max-frequency : Maximum SPI clocking speed of device in Hz - interrupts : Should contain interrupt line - vio-supply : phandle to regulator providing VIO -- ti,power-gpio : GPIO connected to chip's PMEN pin Optional properties: - ti,wl1251-has-eeprom : boolean, the wl1251 has an eeprom connected, which provides configuration data (calibration, MAC, ...) +- ti,power-gpio : GPIO connected to chip's PMEN pin if operated in + SPI mode - Please consult Documentation/devicetree/bindings/spi/spi-bus.txt for optional SPI connection related properties, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 282d0bc14e8e..a3a257089696 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -723,6 +723,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) return 0x200000; case BRCM_CC_4359_CHIP_ID: return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000; + case BRCM_CC_4364_CHIP_ID: case CY_CC_4373_CHIP_ID: return 0x160000; default: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 5105f62767fb..39381cbde89e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -52,6 +52,7 @@ BRCMF_FW_DEF(4356, "brcmfmac4356-pcie"); BRCMF_FW_DEF(43570, "brcmfmac43570-pcie"); BRCMF_FW_DEF(4358, "brcmfmac4358-pcie"); BRCMF_FW_DEF(4359, "brcmfmac4359-pcie"); +BRCMF_FW_DEF(4364, "brcmfmac4364-pcie"); BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie"); BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie"); BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); @@ -70,6 +71,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570), BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358), BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), + BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0xFFFFFFFF, 4364), BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B), BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C), BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B), @@ -2105,6 +2107,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID), diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index f9047db6a11d..3a08252f1a53 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1938,6 +1938,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new, BRCMF_SDIO_FT_NORMAL)) { rd->len = 0; + brcmf_sdio_rxfail(bus, true, true); + sdio_release_host(bus->sdiodev->func1); brcmu_pkt_buf_free_skb(pkt); continue; } diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h index d1037b6ef2d6..c6c4be05159d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h @@ -44,6 +44,7 @@ #define BRCM_CC_4358_CHIP_ID 0x4358 #define BRCM_CC_4359_CHIP_ID 0x4359 #define BRCM_CC_43602_CHIP_ID 43602 +#define BRCM_CC_4364_CHIP_ID 0x4364 #define BRCM_CC_4365_CHIP_ID 0x4365 #define BRCM_CC_4366_CHIP_ID 0x4366 #define BRCM_CC_43664_CHIP_ID 43664 @@ -74,6 +75,7 @@ #define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb #define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc #define BRCM_PCIE_43602_RAW_DEVICE_ID 43602 +#define BRCM_PCIE_4364_DEVICE_ID 0x4464 #define BRCM_PCIE_4365_DEVICE_ID 0x43ca #define BRCM_PCIE_4365_2G_DEVICE_ID 0x43cb #define BRCM_PCIE_4365_5G_DEVICE_ID 0x43cc diff --git a/drivers/net/wireless/marvell/mwifiex/11ac.c b/drivers/net/wireless/marvell/mwifiex/11ac.c index 59d23fb2365f..756f019ef28a 100644 --- a/drivers/net/wireless/marvell/mwifiex/11ac.c +++ b/drivers/net/wireless/marvell/mwifiex/11ac.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11ac + * NXP Wireless LAN device driver: 802.11ac * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11ac.h b/drivers/net/wireless/marvell/mwifiex/11ac.h index 1ca92c7a8a4a..29e83468cf3f 100644 --- a/drivers/net/wireless/marvell/mwifiex/11ac.h +++ b/drivers/net/wireless/marvell/mwifiex/11ac.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11ac + * NXP Wireless LAN device driver: 802.11ac * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c index 238accfe4f41..d2ee6469e67b 100644 --- a/drivers/net/wireless/marvell/mwifiex/11h.c +++ b/drivers/net/wireless/marvell/mwifiex/11h.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11h + * NXP Wireless LAN device driver: 802.11h * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c index e435f801bc91..6696bce56178 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.c +++ b/drivers/net/wireless/marvell/mwifiex/11n.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n + * NXP Wireless LAN device driver: 802.11n * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n.h b/drivers/net/wireless/marvell/mwifiex/11n.h index 33268ce2cd82..83a88eecbda6 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.h +++ b/drivers/net/wireless/marvell/mwifiex/11n.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n + * NXP Wireless LAN device driver: 802.11n * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c index 088612438530..46f41dbcf30d 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n Aggregation + * NXP Wireless LAN device driver: 802.11n Aggregation * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.h b/drivers/net/wireless/marvell/mwifiex/11n_aggr.h index 8279b159da7c..382c1265c441 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.h +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n Aggregation + * NXP Wireless LAN device driver: 802.11n Aggregation * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 05a3c61ac603..0bdafe9f66db 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering + * NXP Wireless LAN device driver: 802.11n RX Re-ordering * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h index 22d991f514c8..465f244b3636 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering + * NXP Wireless LAN device driver: 802.11n RX Re-ordering * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index d89684168500..0a6da6fe2f89 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: CFG80211 + * NXP Wireless LAN device driver: CFG80211 * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.h b/drivers/net/wireless/marvell/mwifiex/cfg80211.h index 908367857d58..530a63f13f14 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.h +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: CFG80211 + * NXP Wireless LAN device driver: CFG80211 * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c index f1522fb1c1e8..fb91ecfc5546 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfp.c +++ b/drivers/net/wireless/marvell/mwifiex/cfp.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: Channel, Frequence and Power + * NXP Wireless LAN device driver: Channel, Frequence and Power * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index e8788c35a453..7e4b8cd52605 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: commands and events + * NXP Wireless LAN device driver: commands and events * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index 8ab114cf3467..dded92db1f37 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: debugfs + * NXP Wireless LAN device driver: debugfs * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index 46696ea0b23e..6bd23c9b1eed 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: generic data structures and APIs + * NXP Wireless LAN device driver: generic data structures and APIs * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/ethtool.c b/drivers/net/wireless/marvell/mwifiex/ethtool.c index 58400c69ab26..9bdad3f59039 100644 --- a/drivers/net/wireless/marvell/mwifiex/ethtool.c +++ b/drivers/net/wireless/marvell/mwifiex/ethtool.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: ethtool + * NXP Wireless LAN device driver: ethtool * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 1fb76d2f5d3f..4dfdf928f705 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: Firmware specific macros & structures + * NXP Wireless LAN device driver: Firmware specific macros & structures * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c index 580387f9f12a..811abe963af2 100644 --- a/drivers/net/wireless/marvell/mwifiex/ie.c +++ b/drivers/net/wireless/marvell/mwifiex/ie.c @@ -1,11 +1,11 @@ /* - * Marvell Wireless LAN device driver: management IE handling- setting and + * NXP Wireless LAN device driver: management IE handling- setting and * deleting IE. * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 1aa93e7e9835..82d69bc3aaaf 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: HW/FW Initialization + * NXP Wireless LAN device driver: HW/FW Initialization * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 0dd592ea6e83..3db449efa167 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: ioctl data structures & APIs + * NXP Wireless LAN device driver: ioctl data structures & APIs * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c index d87aeff70cef..5934f7147547 100644 --- a/drivers/net/wireless/marvell/mwifiex/join.c +++ b/drivers/net/wireless/marvell/mwifiex/join.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: association and ad-hoc start/join + * NXP Wireless LAN device driver: association and ad-hoc start/join * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 7d94695e7961..529099137644 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: major functions + * NXP Wireless LAN device driver: major functions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index fa5634af40f7..afaffc325452 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: major data structures and prototypes + * NXP Wireless LAN device driver: major data structures and prototypes * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index fc1706d0647d..87b4ccca4b9a 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: PCIE specific handling + * NXP Wireless LAN device driver: PCIE specific handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index f7ce9b6db6b4..fc59b522f670 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -3,10 +3,10 @@ * @brief This file contains definitions for PCI-E interface. * driver. * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index a7968a84aaf8..ff932627a46c 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: scan ioctl and command handling + * NXP Wireless LAN device driver: scan ioctl and command handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index fec38b6e86ff..6a2dcb01caf4 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: SDIO specific handling + * NXP Wireless LAN device driver: SDIO specific handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h index f672bdf52cc1..71cd8629b28e 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.h +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: SDIO specific definitions + * NXP Wireless LAN device driver: SDIO specific definitions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 4ed10cf82f9a..0bd93f26bd7f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station command handling + * NXP Wireless LAN device driver: station command handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 20c206da0631..f21660149f58 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station command response handling + * NXP Wireless LAN device driver: station command response handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 5fdffb114913..bc79ca4cb803 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station event handling + * NXP Wireless LAN device driver: station event handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index fbfa0b15d0c8..653f9e094256 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: functions for station ioctl + * NXP Wireless LAN device driver: functions for station ioctl * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c index 52a2ce2e78b0..0d2adf887900 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station RX data handling + * NXP Wireless LAN device driver: station RX data handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c index 37c24b95e642..241305377e20 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station TX data handling + * NXP Wireless LAN device driver: station TX data handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index f8f282ce39bd..97bb87c3676b 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -1,9 +1,10 @@ -/* Marvell Wireless LAN device driver: TDLS handling +/* + * NXP Wireless LAN device driver: TDLS handling * - * Copyright (C) 2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available on the worldwide web at diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c index e3c1446dd847..a8479b879382 100644 --- a/drivers/net/wireless/marvell/mwifiex/txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/txrx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: generic TX/RX data handling + * NXP Wireless LAN device driver: generic TX/RX data handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c index 0939a8c8f3ab..b48a85d791f6 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: AP specific command handling + * NXP Wireless LAN device driver: AP specific command handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c index 86bfa1b9ef9d..9121447e2701 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_event.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: AP event handling + * NXP Wireless LAN device driver: AP event handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index 354b09c5e8dc..77c8595f84f8 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: AP TX and RX data handling + * NXP Wireless LAN device driver: AP TX and RX data handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index c2365eeb7016..6f3cfde4654c 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: USB specific handling + * NXP Wireless LAN device driver: USB specific handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h index 37abd228a84f..d822ec15b7e6 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.h +++ b/drivers/net/wireless/marvell/mwifiex/usb.h @@ -1,10 +1,10 @@ /* * This file contains definitions for mwifiex USB interface driver. * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index 3b0d31827681..de89a1e710b1 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: utility functions + * NXP Wireless LAN device driver: utility functions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/util.h b/drivers/net/wireless/marvell/mwifiex/util.h index 7cafcecd7b85..44aa80eb7827 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.h +++ b/drivers/net/wireless/marvell/mwifiex/util.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: utility functions + * NXP Wireless LAN device driver: utility functions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index 132f9e8ed68c..a06fff199ea3 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: WMM + * NXP Wireless LAN device driver: WMM * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.h b/drivers/net/wireless/marvell/mwifiex/wmm.h index 38f09762bd2f..04d7da95e307 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.h +++ b/drivers/net/wireless/marvell/mwifiex/wmm.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: WMM + * NXP Wireless LAN device driver: WMM * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 99bbc74acda8..d7a1ddc9e407 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ - tx.o agg-rx.o mcu.o airtime.o + tx.o agg-rx.o mcu.o mt76-$(CONFIG_PCI) += pci.o diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index 59c187898132..f77f03530259 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -4,7 +4,13 @@ */ #include "mt76.h" -#define REORDER_TIMEOUT (HZ / 10) +static unsigned long mt76_aggr_tid_to_timeo(u8 tidno) +{ + /* Currently voice traffic (AC_VO) always runs without aggregation, + * no special handling is needed. AC_BE/AC_BK use tids 0-3. Just check + * for non AC_BK/AC_BE and set smaller timeout for it. */ + return HZ / (tidno >= 4 ? 25 : 10); +} static void mt76_aggr_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames, int idx) @@ -71,7 +77,8 @@ 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 + REORDER_TIMEOUT)) + status->reorder_time + + mt76_aggr_tid_to_timeo(tid->num))) continue; mt76_rx_aggr_release_frames(tid, frames, status->seqno); @@ -101,7 +108,7 @@ mt76_rx_aggr_reorder_work(struct work_struct *work) if (nframes) ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work, - REORDER_TIMEOUT); + mt76_aggr_tid_to_timeo(tid->num)); mt76_rx_complete(dev, &frames, NULL); rcu_read_unlock(); @@ -225,7 +232,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) mt76_rx_aggr_release_head(tid, frames); ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work, - REORDER_TIMEOUT); + mt76_aggr_tid_to_timeo(tid->num)); out: spin_unlock_bh(&tid->lock); @@ -245,6 +252,7 @@ int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno, tid->dev = dev; tid->head = ssn; tid->size = size; + tid->num = tidno; INIT_DELAYED_WORK(&tid->reorder_work, mt76_rx_aggr_reorder_work); spin_lock_init(&tid->lock); @@ -268,6 +276,7 @@ static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid) if (!skb) continue; + tid->reorder_buf[i] = NULL; tid->nframes--; dev_kfree_skb(skb); } diff --git a/drivers/net/wireless/mediatek/mt76/airtime.c b/drivers/net/wireless/mediatek/mt76/airtime.c deleted file mode 100644 index a4a785467748..000000000000 --- a/drivers/net/wireless/mediatek/mt76/airtime.c +++ /dev/null @@ -1,326 +0,0 @@ -// SPDX-License-Identifier: ISC -/* - * Copyright (C) 2019 Felix Fietkau - */ - -#include "mt76.h" - -#define AVG_PKT_SIZE 1024 - -/* Number of bits for an average sized packet */ -#define MCS_NBITS (AVG_PKT_SIZE << 3) - -/* Number of symbols for a packet with (bps) bits per symbol */ -#define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps)) - -/* Transmission time (1024 usec) for a packet containing (syms) * symbols */ -#define MCS_SYMBOL_TIME(sgi, syms) \ - (sgi ? \ - ((syms) * 18 * 1024 + 4 * 1024) / 5 : /* syms * 3.6 us */ \ - ((syms) * 1024) << 2 /* syms * 4 us */ \ - ) - -/* Transmit duration for the raw data part of an average sized packet */ -#define MCS_DURATION(streams, sgi, bps) \ - MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps))) - -#define BW_20 0 -#define BW_40 1 -#define BW_80 2 - -/* - * Define group sort order: HT40 -> SGI -> #streams - */ -#define MT_MAX_STREAMS 4 -#define MT_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */ -#define MT_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */ - -#define MT_HT_GROUPS_NB (MT_MAX_STREAMS * \ - MT_HT_STREAM_GROUPS) -#define MT_VHT_GROUPS_NB (MT_MAX_STREAMS * \ - MT_VHT_STREAM_GROUPS) -#define MT_GROUPS_NB (MT_HT_GROUPS_NB + \ - MT_VHT_GROUPS_NB) - -#define MT_HT_GROUP_0 0 -#define MT_VHT_GROUP_0 (MT_HT_GROUP_0 + MT_HT_GROUPS_NB) - -#define MCS_GROUP_RATES 10 - -#define HT_GROUP_IDX(_streams, _sgi, _ht40) \ - MT_HT_GROUP_0 + \ - MT_MAX_STREAMS * 2 * _ht40 + \ - MT_MAX_STREAMS * _sgi + \ - _streams - 1 - -#define _MAX(a, b) (((a)>(b))?(a):(b)) - -#define GROUP_SHIFT(duration) \ - _MAX(0, 16 - __builtin_clz(duration)) - -/* MCS rate information for an MCS group */ -#define __MCS_GROUP(_streams, _sgi, _ht40, _s) \ - [HT_GROUP_IDX(_streams, _sgi, _ht40)] = { \ - .shift = _s, \ - .duration = { \ - MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \ - } \ -} - -#define MCS_GROUP_SHIFT(_streams, _sgi, _ht40) \ - GROUP_SHIFT(MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26)) - -#define MCS_GROUP(_streams, _sgi, _ht40) \ - __MCS_GROUP(_streams, _sgi, _ht40, \ - MCS_GROUP_SHIFT(_streams, _sgi, _ht40)) - -#define VHT_GROUP_IDX(_streams, _sgi, _bw) \ - (MT_VHT_GROUP_0 + \ - MT_MAX_STREAMS * 2 * (_bw) + \ - MT_MAX_STREAMS * (_sgi) + \ - (_streams) - 1) - -#define BW2VBPS(_bw, r3, r2, r1) \ - (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1) - -#define __VHT_GROUP(_streams, _sgi, _bw, _s) \ - [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \ - .shift = _s, \ - .duration = { \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 117, 54, 26)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 234, 108, 52)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 351, 162, 78)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 468, 216, 104)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 702, 324, 156)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 936, 432, 208)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1053, 486, 234)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1170, 540, 260)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1404, 648, 312)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1560, 720, 346)) >> _s \ - } \ -} - -#define VHT_GROUP_SHIFT(_streams, _sgi, _bw) \ - GROUP_SHIFT(MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 117, 54, 26))) - -#define VHT_GROUP(_streams, _sgi, _bw) \ - __VHT_GROUP(_streams, _sgi, _bw, \ - VHT_GROUP_SHIFT(_streams, _sgi, _bw)) - -struct mcs_group { - u8 shift; - u16 duration[MCS_GROUP_RATES]; -}; - -static const struct mcs_group airtime_mcs_groups[] = { - MCS_GROUP(1, 0, BW_20), - MCS_GROUP(2, 0, BW_20), - MCS_GROUP(3, 0, BW_20), - MCS_GROUP(4, 0, BW_20), - - MCS_GROUP(1, 1, BW_20), - MCS_GROUP(2, 1, BW_20), - MCS_GROUP(3, 1, BW_20), - MCS_GROUP(4, 1, BW_20), - - MCS_GROUP(1, 0, BW_40), - MCS_GROUP(2, 0, BW_40), - MCS_GROUP(3, 0, BW_40), - MCS_GROUP(4, 0, BW_40), - - MCS_GROUP(1, 1, BW_40), - MCS_GROUP(2, 1, BW_40), - MCS_GROUP(3, 1, BW_40), - MCS_GROUP(4, 1, BW_40), - - VHT_GROUP(1, 0, BW_20), - VHT_GROUP(2, 0, BW_20), - VHT_GROUP(3, 0, BW_20), - VHT_GROUP(4, 0, BW_20), - - VHT_GROUP(1, 1, BW_20), - VHT_GROUP(2, 1, BW_20), - VHT_GROUP(3, 1, BW_20), - VHT_GROUP(4, 1, BW_20), - - VHT_GROUP(1, 0, BW_40), - VHT_GROUP(2, 0, BW_40), - VHT_GROUP(3, 0, BW_40), - VHT_GROUP(4, 0, BW_40), - - VHT_GROUP(1, 1, BW_40), - VHT_GROUP(2, 1, BW_40), - VHT_GROUP(3, 1, BW_40), - VHT_GROUP(4, 1, BW_40), - - VHT_GROUP(1, 0, BW_80), - VHT_GROUP(2, 0, BW_80), - VHT_GROUP(3, 0, BW_80), - VHT_GROUP(4, 0, BW_80), - - VHT_GROUP(1, 1, BW_80), - VHT_GROUP(2, 1, BW_80), - VHT_GROUP(3, 1, BW_80), - VHT_GROUP(4, 1, BW_80), -}; - -static u32 -mt76_calc_legacy_rate_duration(const struct ieee80211_rate *rate, bool short_pre, - int len) -{ - u32 duration; - - switch (rate->hw_value >> 8) { - case MT_PHY_TYPE_CCK: - duration = 144 + 48; /* preamble + PLCP */ - if (short_pre) - duration >>= 1; - - duration += 10; /* SIFS */ - break; - case MT_PHY_TYPE_OFDM: - duration = 20 + 16; /* premable + SIFS */ - break; - default: - WARN_ON_ONCE(1); - return 0; - } - - len <<= 3; - duration += (len * 10) / rate->bitrate; - - return duration; -} - -u32 mt76_calc_rx_airtime(struct mt76_dev *dev, struct mt76_rx_status *status, - int len) -{ - struct ieee80211_supported_band *sband; - const struct ieee80211_rate *rate; - bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI; - bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE; - int bw, streams; - u32 duration; - int group, idx; - - switch (status->bw) { - case RATE_INFO_BW_20: - bw = BW_20; - break; - case RATE_INFO_BW_40: - bw = BW_40; - break; - case RATE_INFO_BW_80: - bw = BW_80; - break; - default: - WARN_ON_ONCE(1); - return 0; - } - - switch (status->encoding) { - case RX_ENC_LEGACY: - if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ)) - return 0; - - sband = dev->hw->wiphy->bands[status->band]; - if (!sband || status->rate_idx >= sband->n_bitrates) - return 0; - - rate = &sband->bitrates[status->rate_idx]; - - return mt76_calc_legacy_rate_duration(rate, sp, len); - case RX_ENC_VHT: - streams = status->nss; - idx = status->rate_idx; - group = VHT_GROUP_IDX(streams, sgi, bw); - break; - case RX_ENC_HT: - streams = ((status->rate_idx >> 3) & 3) + 1; - idx = status->rate_idx & 7; - group = HT_GROUP_IDX(streams, sgi, bw); - break; - default: - WARN_ON_ONCE(1); - return 0; - } - - if (WARN_ON_ONCE(streams > 4)) - return 0; - - duration = airtime_mcs_groups[group].duration[idx]; - duration <<= airtime_mcs_groups[group].shift; - duration *= len; - duration /= AVG_PKT_SIZE; - duration /= 1024; - - duration += 36 + (streams << 2); - - return duration; -} - -u32 mt76_calc_tx_airtime(struct mt76_dev *dev, struct ieee80211_tx_info *info, - int len) -{ - struct mt76_rx_status stat = { - .band = info->band, - }; - u32 duration = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { - struct ieee80211_tx_rate *rate = &info->status.rates[i]; - u32 cur_duration; - - if (rate->idx < 0 || !rate->count) - break; - - if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) - stat.bw = RATE_INFO_BW_80; - else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - stat.bw = RATE_INFO_BW_40; - else - stat.bw = RATE_INFO_BW_20; - - stat.enc_flags = 0; - if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - stat.enc_flags |= RX_ENC_FLAG_SHORTPRE; - if (rate->flags & IEEE80211_TX_RC_SHORT_GI) - stat.enc_flags |= RX_ENC_FLAG_SHORT_GI; - - stat.rate_idx = rate->idx; - if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { - stat.encoding = RX_ENC_VHT; - stat.rate_idx = ieee80211_rate_get_vht_mcs(rate); - stat.nss = ieee80211_rate_get_vht_nss(rate); - } else if (rate->flags & IEEE80211_TX_RC_MCS) { - stat.encoding = RX_ENC_HT; - } else { - stat.encoding = RX_ENC_LEGACY; - } - - cur_duration = mt76_calc_rx_airtime(dev, &stat, len); - duration += cur_duration * rate->count; - } - - return duration; -} -EXPORT_SYMBOL_GPL(mt76_calc_tx_airtime); diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 6173c80189ba..e5dd7080e88e 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -132,6 +132,11 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) 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) +{ writel(q->head, &q->regs->cpu_idx); } @@ -141,7 +146,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) struct mt76_sw_queue *sq = &dev->q_tx[qid]; struct mt76_queue *q = sq->q; struct mt76_queue_entry entry; - unsigned int n_swq_queued[4] = {}; + unsigned int n_swq_queued[8] = {}; unsigned int n_queued = 0; bool wake = false; int i, last; @@ -178,15 +183,25 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) spin_lock_bh(&q->lock); q->queued -= n_queued; - for (i = 0; i < ARRAY_SIZE(n_swq_queued); i++) { + for (i = 0; i < 4; i++) { if (!n_swq_queued[i]) continue; dev->q_tx[i].swq_queued -= n_swq_queued[i]; } - if (flush) + /* ext PHY */ + for (i = 0; i < 4; i++) { + if (!n_swq_queued[i]) + continue; + + dev->q_tx[__MT_TXQ_MAX + i].swq_queued -= n_swq_queued[4 + i]; + } + + if (flush) { mt76_dma_sync_idx(dev, q); + mt76_dma_kick_queue(dev, q); + } wake = wake && q->stopped && qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; @@ -238,7 +253,9 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, if (!q->queued) return NULL; - if (!flush && !(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) + if (flush) + q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE); + else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) return NULL; q->tail = (q->tail + 1) % q->ndesc; @@ -247,12 +264,6 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, return mt76_dma_get_buf(dev, q, idx, len, info, more); } -static void -mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) -{ - writel(q->head, &q->regs->cpu_idx); -} - static int mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, u32 tx_info) @@ -261,10 +272,13 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, struct mt76_queue_buf buf; dma_addr_t addr; + if (q->queued + 1 >= q->ndesc - 1) + goto error; + addr = dma_map_single(dev->dev, skb->data, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev->dev, addr))) - return -ENOMEM; + goto error; buf.addr = addr; buf.len = skb->len; @@ -275,6 +289,10 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, spin_unlock_bh(&q->lock); return 0; + +error: + dev_kfree_skb(skb); + return -ENOMEM; } static int @@ -286,6 +304,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, struct mt76_tx_info tx_info = { .skb = skb, }; + struct ieee80211_hw *hw; int len, n = 0, ret = -ENOMEM; struct mt76_queue_entry e; struct mt76_txwi_cache *t; @@ -295,7 +314,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, t = mt76_get_txwi(dev); if (!t) { - ieee80211_free_txskb(dev->hw, skb); + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); return -ENOMEM; } txwi = mt76_get_txwi_ptr(dev, t); @@ -427,7 +447,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) int i; for (i = 0; i < q->ndesc; i++) - q->desc[i].ctrl &= ~cpu_to_le32(MT_DMA_CTL_DMA_DONE); + q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); mt76_dma_rx_cleanup(dev, q); mt76_dma_sync_idx(dev, q); @@ -528,6 +548,7 @@ 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 { @@ -537,6 +558,7 @@ 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); @@ -555,7 +577,6 @@ mt76_dma_init(struct mt76_dev *dev) netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, 64); mt76_dma_rx_fill(dev, &dev->q_rx[i]); - skb_queue_head_init(&dev->rx_skb[i]); napi_enable(&dev->napi[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 804224e81103..c236e303ccfd 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -64,6 +64,16 @@ mt76_get_of_eeprom(struct mt76_dev *dev, int len) goto out_put_node; } + if (of_property_read_bool(dev->dev->of_node, "big-endian")) { + u8 *data = (u8 *)dev->eeprom.data; + int i; + + /* convert eeprom data in Little Endian */ + for (i = 0; i < round_down(len, 2); i += 2) + put_unaligned_le16(get_unaligned_be16(&data[i]), + &data[i]); + } + out_put_node: of_node_put(np); return ret; @@ -77,13 +87,11 @@ mt76_eeprom_override(struct mt76_dev *dev) { #ifdef CONFIG_OF struct device_node *np = dev->dev->of_node; - const u8 *mac; + const u8 *mac = NULL; - if (!np) - return; - - mac = of_get_mac_address(np); - if (!IS_ERR(mac)) + if (np) + mac = of_get_mac_address(np); + if (!IS_ERR_OR_NULL(mac)) ether_addr_copy(dev->macaddr, mac); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 96018fd65779..f44f99184c10 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -121,7 +121,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, bool vht) { struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; - int i, nstream = hweight8(dev->antenna_mask); + int i, nstream = hweight8(dev->phy.antenna_mask); struct ieee80211_sta_vht_cap *vht_cap; u16 mcs_map = 0; @@ -156,9 +156,9 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, void mt76_set_stream_caps(struct mt76_dev *dev, bool vht) { if (dev->cap.has_2ghz) - mt76_init_stream_cap(dev, &dev->sband_2g.sband, false); + mt76_init_stream_cap(dev, &dev->phy.sband_2g.sband, false); if (dev->cap.has_5ghz) - mt76_init_stream_cap(dev, &dev->sband_5g.sband, vht); + mt76_init_stream_cap(dev, &dev->phy.sband_5g.sband, vht); } EXPORT_SYMBOL_GPL(mt76_set_stream_caps); @@ -187,8 +187,6 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, sband->n_channels = n_chan; sband->bitrates = rates; sband->n_bitrates = n_rates; - dev->chandef.chan = &sband->channels[0]; - dev->chan_state = &msband->chan[0]; ht_cap = &sband->ht_cap; ht_cap->ht_supported = true; @@ -223,9 +221,9 @@ static int mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates, int n_rates) { - dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->sband_2g.sband; + dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->phy.sband_2g.sband; - return mt76_init_sband(dev, &dev->sband_2g, + return mt76_init_sband(dev, &dev->phy.sband_2g, mt76_channels_2ghz, ARRAY_SIZE(mt76_channels_2ghz), rates, n_rates, false); @@ -235,18 +233,19 @@ static int mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates, int n_rates, bool vht) { - dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->sband_5g.sband; + dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->phy.sband_5g.sband; - return mt76_init_sband(dev, &dev->sband_5g, + return mt76_init_sband(dev, &dev->phy.sband_5g, mt76_channels_5ghz, ARRAY_SIZE(mt76_channels_5ghz), rates, n_rates, vht); } static void -mt76_check_sband(struct mt76_dev *dev, int band) +mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, + enum nl80211_band band) { - struct ieee80211_supported_band *sband = dev->hw->wiphy->bands[band]; + struct ieee80211_supported_band *sband = &msband->sband; bool found = false; int i; @@ -261,71 +260,41 @@ mt76_check_sband(struct mt76_dev *dev, int band) break; } - if (found) + if (found) { + phy->chandef.chan = &sband->channels[0]; + phy->chan_state = &msband->chan[0]; return; + } sband->n_channels = 0; - dev->hw->wiphy->bands[band] = NULL; + phy->hw->wiphy->bands[band] = NULL; } -struct mt76_dev * -mt76_alloc_device(struct device *pdev, unsigned int size, - const struct ieee80211_ops *ops, - const struct mt76_driver_ops *drv_ops) +static void +mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) { - struct ieee80211_hw *hw; - struct mt76_dev *dev; - - hw = ieee80211_alloc_hw(size, ops); - if (!hw) - return NULL; - - dev = hw->priv; - dev->hw = hw; - dev->dev = pdev; - dev->drv = drv_ops; - - spin_lock_init(&dev->rx_lock); - spin_lock_init(&dev->lock); - spin_lock_init(&dev->cc_lock); - mutex_init(&dev->mutex); - init_waitqueue_head(&dev->tx_wait); - skb_queue_head_init(&dev->status_list); - - tasklet_init(&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long)dev); - - return dev; -} -EXPORT_SYMBOL_GPL(mt76_alloc_device); - -int mt76_register_device(struct mt76_dev *dev, bool vht, - struct ieee80211_rate *rates, int n_rates) -{ - struct ieee80211_hw *hw = dev->hw; struct wiphy *wiphy = hw->wiphy; - int ret; - - dev_set_drvdata(dev->dev, dev); - - INIT_LIST_HEAD(&dev->txwi_cache); SET_IEEE80211_DEV(hw, dev->dev); SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL); - wiphy->available_antennas_tx = dev->antenna_mask; - wiphy->available_antennas_rx = dev->antenna_mask; + wiphy->available_antennas_tx = dev->phy.antenna_mask; + wiphy->available_antennas_rx = dev->phy.antenna_mask; hw->txq_data_size = sizeof(struct mt76_txq); - hw->max_tx_fragments = 16; + + if (!hw->max_tx_fragments) + hw->max_tx_fragments = 16; ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, PS_NULLFUNC_STACK); - ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(hw, AMPDU_AGGREGATION); ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); @@ -337,7 +306,6 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, ieee80211_hw_set(hw, AP_LINK_PS); ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); - ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); wiphy->flags |= WIPHY_FLAG_IBSS_RSN; wiphy->interface_modes = @@ -347,6 +315,135 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, BIT(NL80211_IFTYPE_MESH_POINT) | #endif BIT(NL80211_IFTYPE_ADHOC); +} + +struct mt76_phy * +mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, + const struct ieee80211_ops *ops) +{ + struct ieee80211_hw *hw; + struct mt76_phy *phy; + unsigned int phy_size, chan_size; + unsigned int size_2g, size_5g; + void *priv; + + phy_size = ALIGN(sizeof(*phy), 8); + chan_size = sizeof(dev->phy.sband_2g.chan[0]); + size_2g = ALIGN(ARRAY_SIZE(mt76_channels_2ghz) * chan_size, 8); + size_5g = ALIGN(ARRAY_SIZE(mt76_channels_5ghz) * chan_size, 8); + + size += phy_size + size_2g + size_5g; + hw = ieee80211_alloc_hw(size, ops); + if (!hw) + return NULL; + + phy = hw->priv; + phy->dev = dev; + phy->hw = hw; + + mt76_phy_init(dev, hw); + + priv = hw->priv + phy_size; + + phy->sband_2g = dev->phy.sband_2g; + phy->sband_2g.chan = priv; + priv += size_2g; + + phy->sband_5g = dev->phy.sband_5g; + phy->sband_5g.chan = priv; + priv += size_5g; + + phy->priv = priv; + + hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; + hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; + + mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ); + mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); + + return phy; +} +EXPORT_SYMBOL_GPL(mt76_alloc_phy); + +int +mt76_register_phy(struct mt76_phy *phy) +{ + int ret; + + ret = ieee80211_register_hw(phy->hw); + if (ret) + return ret; + + phy->dev->phy2 = phy; + return 0; +} +EXPORT_SYMBOL_GPL(mt76_register_phy); + +void +mt76_unregister_phy(struct mt76_phy *phy) +{ + struct mt76_dev *dev = phy->dev; + + dev->phy2 = NULL; + mt76_tx_status_check(dev, NULL, true); + ieee80211_unregister_hw(phy->hw); +} +EXPORT_SYMBOL_GPL(mt76_unregister_phy); + +struct mt76_dev * +mt76_alloc_device(struct device *pdev, unsigned int size, + const struct ieee80211_ops *ops, + const struct mt76_driver_ops *drv_ops) +{ + struct ieee80211_hw *hw; + struct mt76_phy *phy; + struct mt76_dev *dev; + int i; + + hw = ieee80211_alloc_hw(size, ops); + if (!hw) + return NULL; + + dev = hw->priv; + dev->hw = hw; + dev->dev = pdev; + dev->drv = drv_ops; + + phy = &dev->phy; + phy->dev = dev; + phy->hw = hw; + + spin_lock_init(&dev->rx_lock); + spin_lock_init(&dev->lock); + spin_lock_init(&dev->cc_lock); + mutex_init(&dev->mutex); + init_waitqueue_head(&dev->tx_wait); + skb_queue_head_init(&dev->status_list); + + skb_queue_head_init(&dev->mcu.res_q); + init_waitqueue_head(&dev->mcu.wait); + mutex_init(&dev->mcu.mutex); + + INIT_LIST_HEAD(&dev->txwi_cache); + + for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) + skb_queue_head_init(&dev->rx_skb[i]); + + tasklet_init(&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long)dev); + + return dev; +} +EXPORT_SYMBOL_GPL(mt76_alloc_device); + +int mt76_register_device(struct mt76_dev *dev, bool vht, + struct ieee80211_rate *rates, int n_rates) +{ + struct ieee80211_hw *hw = dev->hw; + struct mt76_phy *phy = &dev->phy; + int ret; + + dev_set_drvdata(dev->dev, dev); + mt76_phy_init(dev, hw); if (dev->cap.has_2ghz) { ret = mt76_init_sband_2g(dev, rates, n_rates); @@ -360,9 +457,9 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, return ret; } - wiphy_read_of_freq_limits(dev->hw->wiphy); - mt76_check_sband(dev, NL80211_BAND_2GHZ); - mt76_check_sband(dev, NL80211_BAND_5GHZ); + wiphy_read_of_freq_limits(hw->wiphy); + mt76_check_sband(&dev->phy, &phy->sband_2g, NL80211_BAND_2GHZ); + mt76_check_sband(&dev->phy, &phy->sband_5g, NL80211_BAND_5GHZ); if (IS_ENABLED(CONFIG_MT76_LEDS)) { ret = mt76_led_init(dev); @@ -394,7 +491,10 @@ EXPORT_SYMBOL_GPL(mt76_free_device); void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) { - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) { + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy); + + if (!test_bit(MT76_STATE_RUNNING, &phy->state)) { dev_kfree_skb(skb); return; } @@ -403,13 +503,16 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(mt76_rx); -bool mt76_has_tx_pending(struct mt76_dev *dev) +bool mt76_has_tx_pending(struct mt76_phy *phy) { + struct mt76_dev *dev = phy->dev; struct mt76_queue *q; - int i; + int i, offset; - for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { - q = dev->q_tx[i].q; + offset = __MT_TXQ_MAX * (phy != &dev->phy); + + for (i = 0; i < __MT_TXQ_MAX; i++) { + q = dev->q_tx[offset + i].q; if (q && q->queued) return true; } @@ -419,37 +522,45 @@ bool mt76_has_tx_pending(struct mt76_dev *dev) EXPORT_SYMBOL_GPL(mt76_has_tx_pending); static struct mt76_channel_state * -mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c) +mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c) { struct mt76_sband *msband; int idx; if (c->band == NL80211_BAND_2GHZ) - msband = &dev->sband_2g; + msband = &phy->sband_2g; else - msband = &dev->sband_5g; + msband = &phy->sband_5g; idx = c - &msband->sband.channels[0]; return &msband->chan[idx]; } +static void +mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time) +{ + struct mt76_channel_state *state = phy->chan_state; + + state->cc_active += ktime_to_us(ktime_sub(time, + phy->survey_time)); + phy->survey_time = time; +} + void mt76_update_survey(struct mt76_dev *dev) { - struct mt76_channel_state *state = dev->chan_state; ktime_t cur_time; - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) - return; - if (dev->drv->update_survey) dev->drv->update_survey(dev); cur_time = ktime_get_boottime(); - state->cc_active += ktime_to_us(ktime_sub(cur_time, - dev->survey_time)); - dev->survey_time = cur_time; + mt76_update_survey_active_time(&dev->phy, cur_time); + if (dev->phy2) + mt76_update_survey_active_time(dev->phy2, cur_time); if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) { + struct mt76_channel_state *state = dev->phy.chan_state; + spin_lock_bh(&dev->cc_lock); state->cc_bss_rx += dev->cur_cc_bss_rx; dev->cur_cc_bss_rx = 0; @@ -458,31 +569,33 @@ void mt76_update_survey(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_update_survey); -void mt76_set_channel(struct mt76_dev *dev) +void mt76_set_channel(struct mt76_phy *phy) { - struct ieee80211_hw *hw = dev->hw; + struct mt76_dev *dev = phy->dev; + struct ieee80211_hw *hw = phy->hw; struct cfg80211_chan_def *chandef = &hw->conf.chandef; bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; int timeout = HZ / 5; - wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(dev), timeout); + wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); mt76_update_survey(dev); - dev->chandef = *chandef; - dev->chan_state = mt76_channel_state(dev, chandef->chan); + phy->chandef = *chandef; + phy->chan_state = mt76_channel_state(phy, chandef->chan); if (!offchannel) - dev->main_chan = chandef->chan; + phy->main_chan = chandef->chan; - if (chandef->chan != dev->main_chan) - memset(dev->chan_state, 0, sizeof(*dev->chan_state)); + if (chandef->chan != phy->main_chan) + memset(phy->chan_state, 0, sizeof(*phy->chan_state)); } EXPORT_SYMBOL_GPL(mt76_set_channel); int mt76_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; struct mt76_sband *sband; struct ieee80211_channel *chan; struct mt76_channel_state *state; @@ -492,10 +605,10 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, if (idx == 0 && dev->drv->update_survey) mt76_update_survey(dev); - sband = &dev->sband_2g; + sband = &phy->sband_2g; if (idx >= sband->sband.n_channels) { idx -= sband->sband.n_channels; - sband = &dev->sband_5g; + sband = &phy->sband_5g; } if (idx >= sband->sband.n_channels) { @@ -504,13 +617,16 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, } chan = &sband->sband.channels[idx]; - state = mt76_channel_state(dev, chan); + state = mt76_channel_state(phy, chan); memset(survey, 0, sizeof(*survey)); survey->channel = chan; survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; survey->filled |= dev->drv->survey_flags; - if (chan == dev->main_chan) { + if (state->noise) + survey->filled |= SURVEY_INFO_NOISE_DBM; + + if (chan == phy->main_chan) { survey->filled |= SURVEY_INFO_IN_USE; if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) @@ -520,6 +636,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, survey->time_busy = div_u64(state->cc_busy, 1000); survey->time_rx = div_u64(state->cc_rx, 1000); survey->time = div_u64(state->cc_active, 1000); + survey->noise = state->noise; spin_lock_bh(&dev->cc_lock); survey->time_bss_rx = div_u64(state->cc_bss_rx, 1000); @@ -555,8 +672,12 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid, } EXPORT_SYMBOL(mt76_wcid_key_setup); -static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb) +static void +mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, + struct ieee80211_hw **hw, + struct ieee80211_sta **sta) { + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct mt76_rx_status mstat; @@ -581,7 +702,8 @@ static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb) memcpy(status->chain_signal, mstat.chain_signal, sizeof(mstat.chain_signal)); - return wcid_to_sta(mstat.wcid); + *sta = wcid_to_sta(mstat.wcid); + *hw = mt76_phy_hw(dev, mstat.ext_phy); } static int @@ -628,10 +750,18 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status, int len) { struct mt76_wcid *wcid = status->wcid; + struct ieee80211_rx_status info = { + .enc_flags = status->enc_flags, + .rate_idx = status->rate_idx, + .encoding = status->encoding, + .band = status->band, + .nss = status->nss, + .bw = status->bw, + }; struct ieee80211_sta *sta; u32 airtime; - airtime = mt76_calc_rx_airtime(dev, status, len); + airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len); spin_lock(&dev->cc_lock); dev->cur_cc_bss_rx += airtime; spin_unlock(&dev->cc_lock); @@ -707,12 +837,14 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_sta *sta; + struct ieee80211_hw *hw; struct mt76_wcid *wcid = status->wcid; bool ps; int i; + hw = mt76_phy_hw(dev, status->ext_phy); if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) { - sta = ieee80211_find_sta_by_ifaddr(dev->hw, hdr->addr2, NULL); + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); if (sta) wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv; } @@ -770,7 +902,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; if (!skb_queue_empty(&mtxq->retry_q)) - ieee80211_schedule_txq(dev->hw, sta->txq[i]); + ieee80211_schedule_txq(hw, sta->txq[i]); } } @@ -778,6 +910,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, struct napi_struct *napi) { struct ieee80211_sta *sta; + struct ieee80211_hw *hw; struct sk_buff *skb; spin_lock(&dev->rx_lock); @@ -787,8 +920,8 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, continue; } - sta = mt76_rx_convert(skb); - ieee80211_rx_napi(dev->hw, sta, skb, napi); + mt76_rx_convert(dev, skb, &hw, &sta); + ieee80211_rx_napi(hw, sta, skb, napi); } spin_unlock(&dev->rx_lock); } @@ -812,7 +945,7 @@ EXPORT_SYMBOL_GPL(mt76_rx_poll_complete); static int mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, bool ext_phy) { struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int ret; @@ -837,6 +970,9 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, } ewma_signal_init(&wcid->rssi); + if (ext_phy) + mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); + wcid->ext_phy = ext_phy; rcu_assign_pointer(dev->wcid[wcid->idx], wcid); out: @@ -851,9 +987,6 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int i, idx = wcid->idx; - rcu_assign_pointer(dev->wcid[idx], NULL); - synchronize_rcu(); - for (i = 0; i < ARRAY_SIZE(wcid->aggr); i++) mt76_rx_aggr_stop(dev, wcid, i); @@ -863,7 +996,8 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, mt76_tx_status_check(dev, wcid, true); for (i = 0; i < ARRAY_SIZE(sta->txq); i++) mt76_txq_remove(dev, sta->txq[i]); - mt76_wcid_free(dev->wcid_mask, idx); + mt76_wcid_mask_clear(dev->wcid_mask, idx); + mt76_wcid_mask_clear(dev->wcid_phy_mask, idx); } EXPORT_SYMBOL_GPL(__mt76_sta_remove); @@ -881,11 +1015,13 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) - return mt76_sta_add(dev, vif, sta); + return mt76_sta_add(dev, vif, sta, ext_phy); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && @@ -900,30 +1036,27 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76_sta_state); +void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + + mutex_lock(&dev->mutex); + rcu_assign_pointer(dev->wcid[wcid->idx], NULL); + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); + int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { - struct mt76_dev *dev = hw->priv; - int n_chains = hweight8(dev->antenna_mask); + struct mt76_phy *phy = hw->priv; + int n_chains = hweight8(phy->antenna_mask); + int delta = mt76_tx_power_nss_delta(n_chains); - *dbm = DIV_ROUND_UP(dev->txpower_cur, 2); - - /* convert from per-chain power to combined - * output power - */ - switch (n_chains) { - case 4: - *dbm += 6; - break; - case 3: - *dbm += 4; - break; - case 2: - *dbm += 3; - break; - default: - break; - } + *dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2); return 0; } @@ -1005,11 +1138,11 @@ int mt76_get_rate(struct mt76_dev *dev, int i, offset = 0, len = sband->n_bitrates; if (cck) { - if (sband == &dev->sband_5g.sband) + if (sband == &dev->phy.sband_5g.sband) return 0; idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->sband_2g.sband) { + } else if (sband == &dev->phy.sband_2g.sband) { offset = 4; } @@ -1025,27 +1158,28 @@ EXPORT_SYMBOL_GPL(mt76_get_rate); void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; - set_bit(MT76_SCANNING, &dev->state); + set_bit(MT76_SCANNING, &phy->state); } EXPORT_SYMBOL_GPL(mt76_sw_scan); void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; - clear_bit(MT76_SCANNING, &dev->state); + clear_bit(MT76_SCANNING, &phy->state); } EXPORT_SYMBOL_GPL(mt76_sw_scan_complete); int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; mutex_lock(&dev->mutex); - *tx_ant = dev->antenna_mask; - *rx_ant = dev->antenna_mask; + *tx_ant = phy->antenna_mask; + *rx_ant = phy->antenna_mask; mutex_unlock(&dev->mutex); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index 2a976688804d..633ad948c21d 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -24,7 +24,6 @@ mt76_mcu_msg_alloc(const void *data, int head_len, } EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc); -/* mmio */ struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires) { @@ -34,16 +33,17 @@ struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, return NULL; timeout = expires - jiffies; - wait_event_timeout(dev->mmio.mcu.wait, - !skb_queue_empty(&dev->mmio.mcu.res_q), + wait_event_timeout(dev->mcu.wait, + (!skb_queue_empty(&dev->mcu.res_q) || + test_bit(MT76_MCU_RESET, &dev->phy.state)), timeout); - return skb_dequeue(&dev->mmio.mcu.res_q); + return skb_dequeue(&dev->mcu.res_q); } EXPORT_SYMBOL_GPL(mt76_mcu_get_response); void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb) { - skb_queue_tail(&dev->mmio.mcu.res_q, skb); - wake_up(&dev->mmio.mcu.wait); + skb_queue_tail(&dev->mcu.res_q, skb); + wake_up(&dev->mcu.wait); } EXPORT_SYMBOL_GPL(mt76_mcu_rx_event); diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 1c974df1fe25..7ead6620bb8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -94,9 +94,6 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) dev->bus = &mt76_mmio_ops; dev->mmio.regs = regs; - skb_queue_head_init(&dev->mmio.mcu.res_q); - init_waitqueue_head(&dev->mmio.mcu.wait); spin_lock_init(&dev->mmio.irq_lock); - mutex_init(&dev->mmio.mcu.mutex); } EXPORT_SYMBOL_GPL(mt76_mmio_init); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index fb077760347a..2e57e7c6bd29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -22,6 +22,7 @@ #define MT_SKB_HEAD_LEN 128 struct mt76_dev; +struct mt76_phy; struct mt76_wcid; struct mt76_reg_pair { @@ -177,6 +178,9 @@ enum mt76_wcid_flags { #define MT76_N_WCIDS 128 +/* stored in ieee80211_tx_info::hw_queue */ +#define MT_TX_HW_QUEUE_EXT_PHY BIT(3) + DECLARE_EWMA(signal, 10, 8); #define MT_WCID_TX_INFO_RATE GENMASK(15, 0) @@ -196,6 +200,7 @@ struct mt76_wcid { u8 hw_key_idx; u8 sta:1; + u8 ext_phy:1; u8 rx_check_pn; u8 rx_key_pn[IEEE80211_NUM_TIDS][6]; @@ -237,6 +242,8 @@ struct mt76_rx_tid { u8 size; u8 nframes; + u8 num; + u8 started:1, stopped:1, timer_pending:1; struct sk_buff *reorder_buf[]; @@ -267,6 +274,7 @@ enum { MT76_STATE_MCU_RUNNING, MT76_SCANNING, MT76_RESET, + MT76_MCU_RESET, MT76_REMOVED, MT76_READING_STATS, }; @@ -279,6 +287,7 @@ struct mt76_hw_cap { #define MT_DRV_TXWI_NO_FREE BIT(0) #define MT_DRV_TX_ALIGNED4_SKBS BIT(1) #define MT_DRV_SW_RX_AIRTIME BIT(2) +#define MT_DRV_RX_DMA_HDR BIT(3) struct mt76_driver_ops { u32 drv_flags; @@ -321,6 +330,8 @@ struct mt76_channel_state { u64 cc_rx; u64 cc_bss_rx; u64 cc_tx; + + s8 noise; }; struct mt76_sband { @@ -350,12 +361,15 @@ struct mt76_rate_power { enum mt_vendor_req { MT_VEND_DEV_MODE = 0x1, MT_VEND_WRITE = 0x2, + MT_VEND_POWER_ON = 0x4, MT_VEND_MULTI_WRITE = 0x6, MT_VEND_MULTI_READ = 0x7, MT_VEND_READ_EEPROM = 0x9, MT_VEND_WRITE_FCE = 0x42, MT_VEND_WRITE_CFG = 0x46, MT_VEND_READ_CFG = 0x47, + MT_VEND_READ_EXT = 0x63, + MT_VEND_WRITE_EXT = 0x66, }; enum mt76u_in_ep { @@ -374,20 +388,27 @@ enum mt76u_out_ep { __MT_EP_OUT_MAX, }; +struct mt76_mcu { + struct mutex mutex; + u32 msg_seq; + + struct sk_buff_head res_q; + wait_queue_head_t wait; +}; + #define MT_TX_SG_MAX_SIZE 8 -#define MT_RX_SG_MAX_SIZE 1 +#define MT_RX_SG_MAX_SIZE 4 #define MT_NUM_TX_ENTRIES 256 #define MT_NUM_RX_ENTRIES 128 #define MCU_RESP_URB_SIZE 1024 struct mt76_usb { struct mutex usb_ctrl_mtx; - union { - u8 data[32]; - __le32 reg_val; - }; + __le32 reg_val; + u8 *data; + u16 data_len; struct tasklet_struct rx_tasklet; - struct workqueue_struct *stat_wq; + struct workqueue_struct *wq; struct work_struct stat_work; u8 out_ep[__MT_EP_OUT_MAX]; @@ -395,10 +416,7 @@ struct mt76_usb { bool sg_en; struct mt76u_mcu { - struct mutex mutex; u8 *data; - u32 msg_seq; - /* multiple reads */ struct mt76_reg_pair *rp; int rp_len; @@ -408,14 +426,6 @@ struct mt76_usb { }; struct mt76_mmio { - struct mt76e_mcu { - struct mutex mutex; - - wait_queue_head_t wait; - struct sk_buff_head res_q; - - u32 msg_seq; - } mcu; void __iomem *regs; spinlock_t irq_lock; u32 irqmask; @@ -433,6 +443,7 @@ struct mt76_rx_status { u8 iv[6]; + u8 ext_phy:1; u8 aggr:1; u8 tid; u16 seqno; @@ -449,12 +460,33 @@ struct mt76_rx_status { s8 chain_signal[IEEE80211_MAX_CHAINS]; }; -struct mt76_dev { +struct mt76_phy { struct ieee80211_hw *hw; + struct mt76_dev *dev; + void *priv; + + unsigned long state; + struct cfg80211_chan_def chandef; struct ieee80211_channel *main_chan; struct mt76_channel_state *chan_state; + ktime_t survey_time; + + struct mt76_sband sband_2g; + struct mt76_sband sband_5g; + + int txpower_cur; + u8 antenna_mask; +}; + +struct mt76_dev { + struct mt76_phy phy; /* must be first */ + + struct mt76_phy *phy2; + + struct ieee80211_hw *hw; + spinlock_t lock; spinlock_t cc_lock; @@ -471,14 +503,15 @@ struct mt76_dev { const struct mt76_mcu_ops *mcu_ops; struct device *dev; + struct mt76_mcu mcu; + struct net_device napi_dev; spinlock_t rx_lock; struct napi_struct napi[__MT_RXQ_MAX]; struct sk_buff_head rx_skb[__MT_RXQ_MAX]; - u32 ampdu_ref; struct list_head txwi_cache; - struct mt76_sw_queue q_tx[__MT_TXQ_MAX]; + struct mt76_sw_queue q_tx[2 * __MT_TXQ_MAX]; struct mt76_queue q_rx[__MT_RXQ_MAX]; const struct mt76_queue_ops *queue_ops; int tx_dma_idx[4]; @@ -491,32 +524,25 @@ struct mt76_dev { struct sk_buff_head status_list; unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG]; + unsigned long wcid_phy_mask[MT76_N_WCIDS / BITS_PER_LONG]; struct mt76_wcid global_wcid; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; u8 macaddr[ETH_ALEN]; u32 rev; - unsigned long state; u32 aggr_stats[32]; - u8 antenna_mask; - u16 chainmask; - struct tasklet_struct pre_tbtt_tasklet; int beacon_int; u8 beacon_mask; - struct mt76_sband sband_2g; - struct mt76_sband sband_5g; struct debugfs_blob_wrapper eeprom; struct debugfs_blob_wrapper otp; struct mt76_hw_cap cap; struct mt76_rate_power rate_power; - int txpower_conf; - int txpower_cur; enum nl80211_dfs_regions region; @@ -529,8 +555,6 @@ struct mt76_dev { u8 csa_complete; - ktime_t survey_time; - u32 rxfilter; union { @@ -581,7 +605,17 @@ enum mt76_phy_type { #define __mt76_rmw_field(_dev, _reg, _field, _val) \ __mt76_rmw(_dev, _reg, _field, FIELD_PREP(_field, _val)) -#define mt76_hw(dev) (dev)->mt76.hw +#define mt76_hw(dev) (dev)->mphy.hw + +static inline struct ieee80211_hw * +mt76_wcid_hw(struct mt76_dev *dev, u8 wcid) +{ + if (wcid <= MT76_N_WCIDS && + mt76_wcid_mask_test(dev->wcid_phy_mask, wcid)) + return dev->phy2->hw; + + return dev->phy.hw; +} bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, int timeout); @@ -624,6 +658,11 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates); void mt76_unregister_device(struct mt76_dev *dev); void mt76_free_device(struct mt76_dev *dev); +void mt76_unregister_phy(struct mt76_phy *phy); + +struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, + const struct ieee80211_ops *ops); +int mt76_register_phy(struct mt76_phy *phy); struct dentry *mt76_register_debugfs(struct mt76_dev *dev); int mt76_queues_read(struct seq_file *s, void *data); @@ -633,6 +672,20 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str, int mt76_eeprom_init(struct mt76_dev *dev, int len); void mt76_eeprom_override(struct mt76_dev *dev); +static inline struct mt76_phy * +mt76_dev_phy(struct mt76_dev *dev, bool phy_ext) +{ + if (phy_ext && dev->phy2) + return dev->phy2; + return &dev->phy; +} + +static inline struct ieee80211_hw * +mt76_phy_hw(struct mt76_dev *dev, bool phy_ext) +{ + return mt76_dev_phy(dev, phy_ext)->hw; +} + static inline u8 * mt76_get_txwi_ptr(struct mt76_dev *dev, struct mt76_txwi_cache *t) { @@ -701,24 +754,31 @@ static inline bool mt76_is_skb_pktid(u8 pktid) return pktid >= MT_PACKET_ID_FIRST; } +static inline u8 mt76_tx_power_nss_delta(u8 nss) +{ + static const u8 nss_delta[4] = { 0, 6, 9, 12 }; + + return nss_delta[nss - 1]; +} + void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); -void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, +void mt76_tx(struct mt76_phy *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); void mt76_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq); void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq); void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq); void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, bool send_bar); -void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid); -void mt76_txq_schedule_all(struct mt76_dev *dev); +void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid); +void mt76_txq_schedule_all(struct mt76_phy *phy); void mt76_tx_tasklet(unsigned long data); void mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u16 tids, int nframes, enum ieee80211_frame_release_type reason, bool more_data); -bool mt76_has_tx_pending(struct mt76_dev *dev); -void mt76_set_channel(struct mt76_dev *dev); +bool mt76_has_tx_pending(struct mt76_phy *phy); +void mt76_set_channel(struct mt76_phy *phy); void mt76_update_survey(struct mt76_dev *dev); int mt76_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); @@ -752,8 +812,10 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_sta_state new_state); void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); +void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); -int mt76_get_min_avg_rssi(struct mt76_dev *dev); +int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy); int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm); @@ -771,10 +833,22 @@ void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac); void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -u32 mt76_calc_tx_airtime(struct mt76_dev *dev, struct ieee80211_tx_info *info, - int len); /* internal */ +static inline struct ieee80211_hw * +mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hw *hw = dev->phy.hw; + + if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phy2) + hw = dev->phy2->hw; + + info->hw_queue &= ~MT_TX_HW_QUEUE_EXT_PHY; + + return hw; +} + void mt76_tx_free(struct mt76_dev *dev); struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev); void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t); @@ -783,8 +857,6 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, struct napi_struct *napi); void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames); -u32 mt76_calc_rx_airtime(struct mt76_dev *dev, struct mt76_rx_status *status, - int len); /* usb */ static inline bool mt76u_urb_error(struct urb *urb) @@ -804,7 +876,7 @@ static inline u8 q2ep(u8 qid) static inline int mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, - int timeout) + int timeout, int ep) { struct usb_interface *uintf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(uintf); @@ -812,20 +884,23 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, unsigned int pipe; if (actual_len) - pipe = usb_rcvbulkpipe(udev, usb->in_ep[MT_EP_IN_CMD_RESP]); + pipe = usb_rcvbulkpipe(udev, usb->in_ep[ep]); else - pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); + pipe = usb_sndbulkpipe(udev, usb->out_ep[ep]); return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout); } +int mt76u_skb_dma_info(struct sk_buff *skb, u32 info); int mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, void *buf, size_t len); void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); -int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); void mt76u_deinit(struct mt76_dev *dev); +int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, + bool ext); +int mt76u_alloc_mcu_queue(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev); void mt76u_stop_tx(struct mt76_dev *dev); void mt76u_stop_rx(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c index e5af4f3389cc..60a996b63c0c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: ISC #include "mt7603.h" +#include "../trace.h" void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { @@ -17,9 +18,11 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) intr = mt76_rr(dev, MT_INT_SOURCE_CSR); mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + intr &= dev->mt76.mmio.irqmask; if (intr & MT_INT_MAC_IRQ3) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index a6ab73060aad..a08b85281170 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -30,6 +30,16 @@ mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_sw_queue *q, static void mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) { + static const u8 tid_to_ac[8] = { + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO + }; __le32 *txd = (__le32 *)skb->data; struct ieee80211_hdr *hdr; struct ieee80211_sta *sta; @@ -38,7 +48,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) void *priv; int idx; u32 val; - u8 tid; + u8 tid = 0; if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr)) goto free; @@ -56,15 +66,16 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) priv = msta = container_of(wcid, struct mt7603_sta, wcid); val = le32_to_cpu(txd[0]); - skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); - val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT); txd[0] = cpu_to_le32(val); sta = container_of(priv, struct ieee80211_sta, drv_priv); hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE]; - tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + if (ieee80211_is_data_qos(hdr->frame_control)) + tid = *ieee80211_get_qos_ctl(hdr) & + IEEE80211_QOS_CTL_TAG1D_MASK; + skb_set_queue_mapping(skb, tid_to_ac[tid]); ieee80211_sta_set_buffered(sta, tid, true); spin_lock_bh(&dev->ps_lock); @@ -210,7 +221,7 @@ int mt7603_dma_init(struct mt7603_dev *dev) return ret; ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, - MT_MCU_RING_SIZE, MT_RX_BUF_SIZE); + MT7603_MCU_RX_RING_SIZE, MT_RX_BUF_SIZE); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 0696dbf28c5b..9e40e81bcc29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -113,7 +113,7 @@ mt7603_dma_sched_init(struct mt7603_dev *dev) static void mt7603_phy_init(struct mt7603_dev *dev) { - int rx_chains = dev->mt76.antenna_mask; + int rx_chains = dev->mphy.antenna_mask; int tx_chains = hweight8(rx_chains) - 1; mt76_rmw(dev, MT_WF_RMAC_RMCR, @@ -284,7 +284,7 @@ mt7603_init_hardware(struct mt7603_dev *dev) mt76_wr(dev, MT_WPDMA_GLO_CFG, 0x52000850); mt7603_mac_dma_start(dev); dev->rxfilter = mt76_rr(dev, MT_WF_RFCR); - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); for (i = 0; i < MT7603_WTBL_SIZE; i++) { mt76_wr(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY | MT_PSE_RTA_WRITE | @@ -363,9 +363,9 @@ static void mt7603_led_set_config(struct mt76_dev *mt76, u8 delay_on, mt76); u32 val, addr; - val = MT_LED_STATUS_DURATION(0xffff) | - MT_LED_STATUS_OFF(delay_off) | - MT_LED_STATUS_ON(delay_on); + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); mt76_wr(dev, addr, val); @@ -493,12 +493,12 @@ mt7603_init_txpower(struct mt7603_dev *dev, target_power += max_offset; dev->tx_power_limit = target_power; - dev->mt76.txpower_cur = target_power; + dev->mphy.txpower_cur = target_power; target_power = DIV_ROUND_UP(target_power, 2); /* add 3 dBm for 2SS devices (combined output) */ - if (dev->mt76.antenna_mask & BIT(1)) + if (dev->mphy.antenna_mask & BIT(1)) target_power += 3; for (i = 0; i < sband->n_channels; i++) { @@ -535,9 +535,9 @@ int mt7603_register_device(struct mt7603_dev *dev) (unsigned long)dev); /* Check for 7688, which only has 1SS */ - dev->mt76.antenna_mask = 3; + dev->mphy.antenna_mask = 3; if (mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4)) - dev->mt76.antenna_mask = 1; + dev->mphy.antenna_mask = 1; dev->slottime = 9; @@ -557,6 +557,7 @@ int mt7603_register_device(struct mt7603_dev *dev) wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { @@ -564,7 +565,6 @@ int mt7603_register_device(struct mt7603_dev *dev) dev->mt76.led_cdev.blink_set = mt7603_led_set_blink; } - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy->reg_notifier = mt7603_regd_notifier; ret = mt76_register_device(&dev->mt76, true, mt7603_rates, @@ -573,7 +573,7 @@ int mt7603_register_device(struct mt7603_dev *dev) return ret; mt7603_init_debugfs(dev); - mt7603_init_txpower(dev, &dev->mt76.sband_2g.sband); + mt7603_init_txpower(dev, &dev->mphy.sband_2g.sband); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 812d081ad943..8f5ca9283f7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -4,6 +4,7 @@ #include #include "mt7603.h" #include "mac.h" +#include "../trace.h" #define MT_PSE_PAGE_SIZE 128 @@ -53,7 +54,7 @@ void mt7603_mac_set_timing(struct mt7603_dev *dev) int sifs; u32 val; - if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) + if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ) sifs = 16; else sifs = 10; @@ -456,7 +457,7 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev) return; spin_lock_bh(&dev->mt76.cc_lock); - dev->mt76.chan_state->cc_tx += total_airtime; + dev->mphy.chan_state->cc_tx += total_airtime; spin_unlock_bh(&dev->mt76.cc_lock); } @@ -502,7 +503,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) memset(status, 0, sizeof(*status)); i = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); - sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband; + sband = (i & 1) ? &dev->mphy.sband_5g.sband : &dev->mphy.sband_2g.sband; i >>= 1; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); @@ -531,12 +532,12 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) /* all subframes of an A-MPDU have the same timestamp */ if (dev->rx_ampdu_ts != rxd[12]) { - if (!++dev->mt76.ampdu_ref) - dev->mt76.ampdu_ref++; + if (!++dev->ampdu_ref) + dev->ampdu_ref++; } dev->rx_ampdu_ts = rxd[12]; - status->ampdu_ref = dev->mt76.ampdu_ref; + status->ampdu_ref = dev->ampdu_ref; } remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; @@ -609,7 +610,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) status->rate_idx = i; - status->chains = dev->mt76.antenna_mask; + status->chains = dev->mphy.antenna_mask; status->chain_signal[0] = FIELD_GET(MT_RXV4_IB_RSSI0, rxdg3) + dev->rssi_offset[0]; status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) + @@ -668,7 +669,7 @@ mt7603_mac_tx_rate_val(struct mt7603_dev *dev, *bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mt76.chandef.chan->band; + int band = dev->mphy.chandef.chan->band; u16 val; nss = 1; @@ -1156,10 +1157,10 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; + if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ) + sband = &dev->mphy.sband_5g.sband; else - sband = &dev->mt76.sband_2g.sband; + sband = &dev->mphy.sband_2g.sband; final_rate &= GENMASK(5, 0); final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, cck); @@ -1193,6 +1194,8 @@ mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, if (pid < MT_PACKET_ID_FIRST) return false; + trace_mac_txdone(mdev, sta->wcid.idx, pid); + mt76_tx_status_lock(mdev, &list); skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); if (skb) { @@ -1389,10 +1392,10 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) int i; ieee80211_stop_queues(dev->mt76.hw); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); /* lock/unlock all queues to ensure that no tx is pending */ - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); tasklet_disable(&dev->mt76.tx_tasklet); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); @@ -1426,7 +1429,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt7603_pse_client_reset(dev); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) + for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) @@ -1439,7 +1442,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt7603_irq_enable(dev, mask); skip_dma_reset: - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); tasklet_enable(&dev->mt76.tx_tasklet); @@ -1456,7 +1459,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) napi_schedule(&dev->mt76.napi[1]); ieee80211_wake_queues(dev->mt76.hw); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index) @@ -1574,7 +1577,7 @@ void mt7603_update_channel(struct mt76_dev *mdev) struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); struct mt76_channel_state *state; - state = mdev->chan_state; + state = mdev->phy.chan_state; state->cc_busy += mt76_rr(dev, MT_MIB_STAT_CCA); } @@ -1737,7 +1740,7 @@ mt7603_false_cca_check(struct mt7603_dev *dev) mt7603_cca_stats_reset(dev); - min_signal = mt76_get_min_avg_rssi(&dev->mt76); + min_signal = mt76_get_min_avg_rssi(&dev->mt76, false); if (!min_signal) { dev->sensitivity = 0; dev->last_cca_adj = jiffies; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 962e2822d19f..26cb711b465f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -15,8 +15,8 @@ mt7603_start(struct ieee80211_hw *hw) mt7603_mac_reset_counters(dev); mt7603_mac_start(dev); - dev->mt76.survey_time = ktime_get_boottime(); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + dev->mphy.survey_time = ktime_get_boottime(); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt7603_mac_work(&dev->mt76.mac_work.work); return 0; @@ -27,7 +27,7 @@ mt7603_stop(struct ieee80211_hw *hw) { struct mt7603_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); cancel_delayed_work_sync(&dev->mt76.mac_work); mt7603_mac_stop(dev); } @@ -143,16 +143,16 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); mt7603_beacon_set_timer(dev, -1, 0); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt7603_mac_stop(dev); if (def->width == NL80211_CHAN_WIDTH_40) bw = MT_BW_40; - dev->mt76.chandef = *def; + dev->mphy.chandef = *def; mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw); ret = mt7603_mcu_set_channel(dev); if (ret) { @@ -176,9 +176,9 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt7603_mac_set_timing(dev); mt7603_mac_start(dev); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, msecs_to_jiffies(MT7603_WATCHDOG_TIME)); @@ -187,10 +187,10 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_READ_CLR_DIS); mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME); - mt76_rr(dev, MT_MIB_STAT_PSCCA); + mt76_rr(dev, MT_MIB_STAT_CCA); mt7603_cca_stats_reset(dev); - dev->mt76.survey_time = ktime_get_boottime(); + dev->mphy.survey_time = ktime_get_boottime(); mt7603_init_edcca(dev); @@ -642,7 +642,7 @@ mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { struct mt7603_dev *dev = hw->priv; - dev->coverage_class = coverage_class; + dev->coverage_class = max_t(s16, coverage_class, 0); mt7603_mac_set_timing(dev); } @@ -667,7 +667,7 @@ static void mt7603_tx(struct ieee80211_hw *hw, wcid = &mvif->sta.wcid; } - mt76_tx(&dev->mt76, control->sta, wcid, skb); + mt76_tx(&dev->mphy, control->sta, wcid, skb); } const struct ieee80211_ops mt7603_ops = { @@ -680,6 +680,7 @@ const struct ieee80211_ops mt7603_ops = { .configure_filter = mt7603_configure_filter, .bss_info_changed = mt7603_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7603_set_key, .conf_tx = mt7603_conf_tx, .sw_scan_start = mt76_sw_scan, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 02b2bd60d04d..b466b3ab8a2c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -22,9 +22,9 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, struct mt7603_mcu_txd *txd; u8 seq; - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; if (!seq) - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen); memset(txd, 0, hdrlen); @@ -67,7 +67,7 @@ mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&mdev->mmio.mcu.mutex); + mutex_lock(&mdev->mcu.mutex); ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq); if (ret) @@ -97,7 +97,7 @@ mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, } out: - mutex_unlock(&mdev->mmio.mcu.mutex); + mutex_unlock(&mdev->mcu.mutex); return ret; } @@ -277,7 +277,7 @@ int mt7603_mcu_init(struct mt7603_dev *dev) void mt7603_mcu_exit(struct mt7603_dev *dev) { __mt76_mcu_restart(&dev->mt76); - skb_queue_purge(&dev->mt76.mmio.mcu.res_q); + skb_queue_purge(&dev->mt76.mcu.res_q); } int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) @@ -397,7 +397,7 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) u8 temp_comp_power[17]; u8 reserved; } req = { - .center_channel = dev->mt76.chandef.chan->hw_value, + .center_channel = dev->mphy.chandef.chan->hw_value, #define EEP_VAL(n) ((u8 *)dev->mt76.eeprom.data)[n] .tssi = EEP_VAL(MT_EE_NIC_CONF_1 + 1), .temp_comp = EEP_VAL(MT_EE_NIC_CONF_1), @@ -430,9 +430,9 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) int mt7603_mcu_set_channel(struct mt7603_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; struct ieee80211_hw *hw = mt76_hw(dev); - int n_chains = hweight8(dev->mt76.antenna_mask); + int n_chains = hweight8(dev->mphy.antenna_mask); struct { u8 control_chan; u8 center_chan; @@ -452,7 +452,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) s8 tx_power; int i, ret; - if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) { + if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_40) { req.bw = MT_BW_40; if (chandef->center_freq1 > chandef->chan->center_freq) req.center_chan += 2; @@ -461,11 +461,11 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) } tx_power = hw->conf.power_level * 2; - if (dev->mt76.antenna_mask == 3) + if (dev->mphy.antenna_mask == 3) tx_power -= 6; tx_power = min(tx_power, dev->tx_power_limit); - dev->mt76.txpower_cur = tx_power; + dev->mphy.txpower_cur = tx_power; for (i = 0; i < ARRAY_SIZE(req.txpower); i++) req.txpower[i] = tx_power; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index ab54b0612e98..ef374641fe80 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -15,6 +15,7 @@ #define MT7603_RATE_RETRY 2 +#define MT7603_MCU_RX_RING_SIZE 64 #define MT7603_RX_RING_SIZE 128 #define MT7603_FIRMWARE_E1 "mt7603_e1.bin" @@ -98,7 +99,10 @@ enum mt7603_reset_cause { }; struct mt7603_dev { - struct mt76_dev mt76; /* must be first */ + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; const struct mt76_bus_ops *bus_ops; @@ -115,6 +119,7 @@ struct mt7603_dev { u32 false_cca_ofdm, false_cca_cck; unsigned long last_cca_adj; + u32 ampdu_ref; __le32 rx_ampdu_ts; u8 rssi_offset[3]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index 6e23ed3dfdff..6741e6907194 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -585,18 +585,9 @@ enum { #define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8)) #define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8)) -#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) -#define MT_LED_STATUS_OFF(_v) (((_v) << \ - __ffs(MT_LED_STATUS_OFF_MASK)) & \ - MT_LED_STATUS_OFF_MASK) -#define MT_LED_STATUS_ON_MASK GENMASK(23, 16) -#define MT_LED_STATUS_ON(_v) (((_v) << \ - __ffs(MT_LED_STATUS_ON_MASK)) & \ - MT_LED_STATUS_ON_MASK) -#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 0) -#define MT_LED_STATUS_DURATION(_v) (((_v) << \ - __ffs(MT_LED_STATUS_DURATION_MASK)) &\ - MT_LED_STATUS_DURATION_MASK) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 0) #define MT_CLIENT_BASE_PHYS_ADDR 0x800c0000 diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig index 4cabba9aa2ea..6afd4aea67ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig @@ -11,3 +11,14 @@ config MT7615E MU-MIMO up to 4 users/group and 160MHz channels. To compile this driver as a module, choose M here. + +config MT7622_WMAC + bool "MT7622 (SoC) WMAC support" + depends on MT7615E + depends on ARCH_MEDIATEK || COMPILE_TEST + select REGMAP + default y + help + This adds support for the built-in WMAC on MT7622 SoC devices + which has the same feature set as a MT7615, but limited to + 2.4 GHz only. diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile index 5aaac69849d6..5c6a220ed7e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile @@ -2,5 +2,8 @@ obj-$(CONFIG_MT7615E) += mt7615e.o -mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ - debugfs.o +CFLAGS_trace.o := -I$(src) + +mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o mmio.o \ + debugfs.o trace.o +mt7615e-$(CONFIG_MT7622_WMAC) += soc.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index f6b75f832e6a..b4d0795154e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -7,6 +7,9 @@ mt7615_radar_pattern_set(void *data, u64 val) { struct mt7615_dev *dev = data; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + return mt7615_mcu_rdd_send_pattern(dev); } @@ -18,6 +21,9 @@ mt7615_scs_set(void *data, u64 val) { struct mt7615_dev *dev = data; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + mt7615_mac_set_scs(dev, val); return 0; @@ -36,6 +42,84 @@ mt7615_scs_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_scs, mt7615_scs_get, mt7615_scs_set, "%lld\n"); +static int +mt7615_dbdc_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + if (val) + mt7615_register_ext_phy(dev); + else + mt7615_unregister_ext_phy(dev); + + return 0; +} + +static int +mt7615_dbdc_get(void *data, u64 *val) +{ + struct mt7615_dev *dev = data; + + *val = !!mt7615_ext_phy(dev); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get, + mt7615_dbdc_set, "%lld\n"); + +static int +mt7615_fw_debug_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + dev->fw_debug = val; + mt7615_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0); + + return 0; +} + +static int +mt7615_fw_debug_get(void *data, u64 *val) +{ + struct mt7615_dev *dev = data; + + *val = dev->fw_debug; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7615_fw_debug_get, + mt7615_fw_debug_set, "%lld\n"); + +static int +mt7615_reset_test_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + struct sk_buff *skb; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + skb = alloc_skb(1, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + skb_put(skb, 1); + mt76_tx_queue_skb_raw(dev, 0, skb, 0); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_reset_test, NULL, + mt7615_reset_test_set, "%lld\n"); + static int mt7615_ampdu_stat_read(struct seq_file *file, void *data) { @@ -74,15 +158,28 @@ static const struct file_operations fops_ampdu_stat = { .release = single_release, }; +static void +mt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s) +{ + struct mt7615_dev *dev = dev_get_drvdata(s->private); + bool ext_phy = phy != &dev->phy; + + if (!phy) + return; + + seq_printf(s, "Radio %d sensitivity: ofdm=%d cck=%d\n", ext_phy, + phy->ofdm_sensitivity, phy->cck_sensitivity); + seq_printf(s, "Radio %d false CCA: ofdm=%d cck=%d\n", ext_phy, + phy->false_cca_ofdm, phy->false_cca_cck); +} + static int mt7615_radio_read(struct seq_file *s, void *data) { struct mt7615_dev *dev = dev_get_drvdata(s->private); - seq_printf(s, "Sensitivity: ofdm=%d cck=%d\n", - dev->ofdm_sensitivity, dev->cck_sensitivity); - seq_printf(s, "False CCA: ofdm=%d cck=%d\n", - dev->false_cca_ofdm, dev->false_cca_cck); + mt7615_radio_read_phy(&dev->phy, s); + mt7615_radio_read_phy(mt7615_ext_phy(dev), s); return 0; } @@ -92,6 +189,9 @@ static int mt7615_read_temperature(struct seq_file *s, void *data) struct mt7615_dev *dev = dev_get_drvdata(s->private); int temp; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + /* cpu */ temp = mt7615_mcu_get_temperature(dev, 0); seq_printf(s, "Temperature: %d\n", temp); @@ -164,12 +264,18 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) if (!dir) return -ENOMEM; - debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, - mt7615_queues_read); + if (is_mt7615(&dev->mt76)) + debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, + mt7615_queues_read); + else + debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, + mt76_queues_read); debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, mt7615_queues_acq); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("scs", 0600, dir, dev, &fops_scs); + debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); + debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7615_radio_read); debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); @@ -184,6 +290,8 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) &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, mt7615_read_temperature); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 285d4f1d6178..1bc71f5081ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -12,31 +12,7 @@ #include "mac.h" static int -mt7615_init_tx_queues(struct mt7615_dev *dev, int n_desc) -{ - struct mt76_sw_queue *q; - struct mt76_queue *hwq; - int err, i; - - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; - - err = mt76_queue_alloc(dev, hwq, 0, n_desc, 0, MT_TX_RING_BASE); - if (err < 0) - return err; - - for (i = 0; i < MT_TXQ_MCU; i++) { - q = &dev->mt76.q_tx[i]; - INIT_LIST_HEAD(&q->swq); - q->q = hwq; - } - - return 0; -} - -static int -mt7615_init_mcu_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, +mt7615_init_tx_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, int idx, int n_desc) { struct mt76_queue *hwq; @@ -56,6 +32,68 @@ mt7615_init_mcu_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, return 0; } +static int +mt7622_init_tx_queues_multi(struct mt7615_dev *dev) +{ + static const u8 wmm_queue_map[] = { + MT7622_TXQ_AC0, + MT7622_TXQ_AC1, + MT7622_TXQ_AC2, + MT7622_TXQ_AC3, + }; + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[i], + wmm_queue_map[i], + MT7615_TX_RING_SIZE / 2); + if (ret) + return ret; + } + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD], + MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE); + if (ret) + return ret; + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7622_TXQ_MCU, MT7615_TX_MCU_RING_SIZE); + return ret; +} + +static int +mt7615_init_tx_queues(struct mt7615_dev *dev) +{ + struct mt76_sw_queue *q; + int ret, i; + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], + MT7615_TXQ_FWDL, + MT7615_TX_FWDL_RING_SIZE); + if (ret) + return ret; + + if (!is_mt7615(&dev->mt76)) + return mt7622_init_tx_queues_multi(dev); + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[0], 0, + MT7615_TX_RING_SIZE); + if (ret) + return ret; + + for (i = 1; i < MT_TXQ_MCU; i++) { + q = &dev->mt76.q_tx[i]; + INIT_LIST_HEAD(&q->swq); + q->q = dev->mt76.q_tx[0].q; + } + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7615_TXQ_MCU, + MT7615_TX_MCU_RING_SIZE); + return 0; +} + void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb) { @@ -90,25 +128,32 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } } +static void +mt7615_tx_cleanup(struct mt7615_dev *dev) +{ + int i; + + mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); + if (is_mt7615(&dev->mt76)) { + mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); + } else { + for (i = 0; i < IEEE80211_NUM_ACS; i++) + mt76_queue_tx_cleanup(dev, i, false); + } +} + static int mt7615_poll_tx(struct napi_struct *napi, int budget) { - static const u8 queue_map[] = { - MT_TXQ_MCU, - MT_TXQ_BE - }; struct mt7615_dev *dev; - int i; dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); - for (i = 0; i < ARRAY_SIZE(queue_map); i++) - mt76_queue_tx_cleanup(dev, queue_map[i], false); + mt7615_tx_cleanup(dev); if (napi_complete_done(napi, 0)) mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); - for (i = 0; i < ARRAY_SIZE(queue_map); i++) - mt76_queue_tx_cleanup(dev, queue_map[i], false); + mt7615_tx_cleanup(dev); mt7615_mac_sta_poll(dev); @@ -117,8 +162,33 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget) return 0; } +static void mt7622_dma_sched_init(struct mt7615_dev *dev) +{ + u32 reg = mt7615_reg_map(dev, MT_DMASHDL_BASE); + int i; + + mt76_rmw(dev, reg + MT_DMASHDL_PKT_MAX_SIZE, + MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE, + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) | + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 8)); + + for (i = 0; i <= 5; i++) + mt76_wr(dev, reg + MT_DMASHDL_GROUP_QUOTA(i), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x10) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x800)); + + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(0), 0x42104210); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(1), 0x42104210); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(2), 0x5); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(3), 0); + + mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET0, 0x6012345f); + mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET1, 0xedcba987); +} + int mt7615_dma_init(struct mt7615_dev *dev) { + int rx_ring_size = MT7615_RX_RING_SIZE; int ret; mt76_dma_attach(&dev->mt76); @@ -126,9 +196,12 @@ int mt7615_dma_init(struct mt7615_dev *dev) mt76_wr(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE | MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN | - MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY | MT_WPDMA_GLO_CFG_OMIT_TX_INFO); + if (!is_mt7622(&dev->mt76)) + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY); + mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0, 0x1); @@ -141,28 +214,19 @@ int mt7615_dma_init(struct mt7615_dev *dev) mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_MULTI_DMA_EN, 0x3); - mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); - mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); - mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); - mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026); - mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881); - mt76_set(dev, 0x7158, BIT(16)); - mt76_clear(dev, 0x7000, BIT(23)); + if (is_mt7615(&dev->mt76)) { + mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); + mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); + mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); + mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026); + mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881); + mt76_set(dev, 0x7158, BIT(16)); + mt76_clear(dev, 0x7000, BIT(23)); + } + mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); - ret = mt7615_init_tx_queues(dev, MT7615_TX_RING_SIZE); - if (ret) - return ret; - - ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], - MT7615_TXQ_MCU, - MT7615_TX_MCU_RING_SIZE); - if (ret) - return ret; - - ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], - MT7615_TXQ_FWDL, - MT7615_TX_FWDL_RING_SIZE); + ret = mt7615_init_tx_queues(dev); if (ret) return ret; @@ -173,9 +237,11 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret) return ret; + if (!is_mt7615(&dev->mt76)) + rx_ring_size /= 2; + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, - MT7615_RX_RING_SIZE, MT_RX_BUF_SIZE, - MT_RX_RING_BASE); + rx_ring_size, MT_RX_BUF_SIZE, MT_RX_RING_BASE); if (ret) return ret; @@ -199,7 +265,11 @@ int mt7615_dma_init(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_RX_DMA_EN); /* enable interrupts for TX/RX rings */ - mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); + mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); + + if (is_mt7622(&dev->mt76)) + mt7622_dma_sched_init(dev); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 17e277bf39e0..5220c18e711f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -84,6 +84,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) switch (val) { case 0x7615: + case 0x7622: return 0; default: return -EINVAL; @@ -93,7 +94,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) { u8 *eeprom = dev->mt76.eeprom.data; - u8 tx_mask, rx_mask, max_nss; + u8 tx_mask, max_nss; u32 val; val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, @@ -111,22 +112,21 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) break; } + if (is_mt7622(&dev->mt76)) + dev->mt76.cap.has_5ghz = false; + /* read tx-rx mask from eeprom */ val = mt76_rr(dev, MT_TOP_STRAP_STA); max_nss = val & MT_TOP_3NSS ? 3 : 4; - rx_mask = FIELD_GET(MT_EE_NIC_CONF_RX_MASK, - eeprom[MT_EE_NIC_CONF_0]); - if (!rx_mask || rx_mask > max_nss) - rx_mask = max_nss; - tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK, eeprom[MT_EE_NIC_CONF_0]); if (!tx_mask || tx_mask > max_nss) tx_mask = max_nss; - dev->mt76.chainmask = tx_mask << 8 | rx_mask; - dev->mt76.antenna_mask = BIT(tx_mask) - 1; + dev->chainmask = BIT(tx_mask) - 1; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; } int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, @@ -209,6 +209,26 @@ static void mt7615_apply_cal_free_data(struct mt7615_dev *dev) eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]]; } +static void mt7622_apply_cal_free_data(struct mt7615_dev *dev) +{ + static const u16 ical[] = { + 0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b + }; + u8 *eeprom = dev->mt76.eeprom.data; + u8 *otp = dev->mt76.otp.data; + int i; + + if (!otp) + return; + + for (i = 0; i < ARRAY_SIZE(ical); i++) { + if (!otp[ical[i]]) + continue; + + eeprom[ical[i]] = otp[ical[i]]; + } +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; @@ -221,6 +241,8 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) if (ret && dev->mt76.otp.data) memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); + else if (is_mt7622(&dev->mt76)) + mt7622_apply_cal_free_data(dev); else mt7615_apply_cal_free_data(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index c3bc69ac210e..18c7301521b7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -21,7 +21,8 @@ enum mt7615_eeprom_field { MT_EE_TX2_5G_G0_TARGET_POWER = 0x142, MT_EE_TX3_5G_G0_TARGET_POWER = 0x16a, - __MT_EE_MAX = 0x3bf + MT7615_EE_MAX = 0x3bf, + MT7622_EE_MAX = 0x3db, }; #define MT_EE_NIC_CONF_TX_MASK GENMASK(7, 4) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 553bd4d988f7..889eb72ad6bd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -13,9 +13,9 @@ static void mt7615_phy_init(struct mt7615_dev *dev) { - /* disable band 0 rf low power beacon mode */ - mt76_rmw(dev, MT_WF_PHY_WF2_RFCTRL0, MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN, - MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); + /* disable rf low power beacon mode */ + mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(0), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); + mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(1), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); } static void mt7615_mac_init(struct mt7615_dev *dev) @@ -28,17 +28,17 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN | MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN); - val = mt76_rmw(dev, MT_TMAC_TRCR0, + val = mt76_rmw(dev, MT_TMAC_TRCR(0), MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); - mt76_wr(dev, MT_TMAC_TRCR1, val); + mt76_wr(dev, MT_TMAC_TRCR(1), val); val = MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | - FIELD_PREP(MT_AGG_ACR_CFEND_RATE, 0x49) | /* 24M */ - FIELD_PREP(MT_AGG_ACR_BAR_RATE, 0x4b); /* 6M */ - mt76_wr(dev, MT_AGG_ACR0, val); - mt76_wr(dev, MT_AGG_ACR1, val); + FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | + FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT); + mt76_wr(dev, MT_AGG_ACR(0), val); + mt76_wr(dev, MT_AGG_ACR(1), val); mt76_rmw_field(dev, MT_TMAC_CTCR0, MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); @@ -50,36 +50,36 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | MT_TMAC_CTCR0_INS_DDLMT_EN); - mt7615_mcu_set_rts_thresh(dev, 0x92b); + mt7615_mcu_set_rts_thresh(&dev->phy, 0x92b); mt7615_mac_set_scs(dev, true); mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, MT_AGG_SCR_NLNAV_MID_PTEC_DIS); - mt7615_mcu_init_mac(dev); - mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072)); - mt76_wr(dev, MT_AGG_ARUCR, - FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); + val = FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1); + mt76_wr(dev, MT_AGG_ARUCR(0), val); + mt76_wr(dev, MT_AGG_ARUCR(1), val); - mt76_wr(dev, MT_AGG_ARDCR, - FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1)); + val = FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1); + mt76_wr(dev, MT_AGG_ARDCR(0), val); + mt76_wr(dev, MT_AGG_ARDCR(1), val); mt76_wr(dev, MT_AGG_ARCR, (FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | @@ -95,8 +95,8 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_DMA_RCFR0_RX_DROPPED_MCAST; set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) | FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2); - mt76_rmw(dev, MT_DMA_BN0RCFR0, mask, set); - mt76_rmw(dev, MT_DMA_BN1RCFR0, mask, set); + mt76_rmw(dev, MT_DMA_RCFR0(0), mask, set); + mt76_rmw(dev, MT_DMA_RCFR0(1), mask, set); for (i = 0; i < MT7615_WTBL_SIZE; i++) mt7615_mac_wtbl_update(dev, i, @@ -106,12 +106,33 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN); } +bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev) +{ + flush_work(&dev->mcu_work); + + return test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); +} + +static void mt7615_init_work(struct work_struct *work) +{ + struct mt7615_dev *dev = container_of(work, struct mt7615_dev, mcu_work); + + if (mt7615_mcu_init(dev)) + return; + + mt7615_mcu_set_eeprom(dev); + mt7615_mac_init(dev); + mt7615_phy_init(dev); + mt7615_mcu_del_wtbl_all(dev); +} + static int mt7615_init_hardware(struct mt7615_dev *dev) { int ret, idx; mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); + INIT_WORK(&dev->mcu_work, mt7615_init_work); spin_lock_init(&dev->token_lock); idr_init(&dev->token); @@ -123,17 +144,7 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) if (ret) return ret; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); - - ret = mt7615_mcu_init(dev); - if (ret) - return ret; - - mt7615_mcu_set_eeprom(dev); - mt7615_mac_init(dev); - mt7615_phy_init(dev); - mt7615_mcu_ctrl_pm_state(dev, 0); - mt7615_mcu_del_wtbl_all(dev); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); /* Beacon and mgmt frames should occupy wcid 0 */ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1); @@ -199,13 +210,66 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; +static void +mt7615_led_set_config(struct led_classdev *led_cdev, + u8 delay_on, u8 delay_off) +{ + struct mt7615_dev *dev; + struct mt76_dev *mt76; + u32 val, addr; + + mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); + dev = container_of(mt76, struct mt7615_dev, mt76); + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); + + addr = mt7615_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); + mt76_wr(dev, addr, val); + addr = mt7615_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin)); + mt76_wr(dev, addr, val); + + val = MT_LED_CTRL_REPLAY(mt76->led_pin) | + MT_LED_CTRL_KICK(mt76->led_pin); + if (mt76->led_al) + val |= MT_LED_CTRL_POLARITY(mt76->led_pin); + addr = mt7615_reg_map(dev, MT_LED_CTRL); + mt76_wr(dev, addr, val); +} + +static int +mt7615_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + u8 delta_on, delta_off; + + delta_off = max_t(u8, *delay_off / 10, 1); + delta_on = max_t(u8, *delay_on / 10, 1); + + mt7615_led_set_config(led_cdev, delta_on, delta_off); + + return 0; +} + +static void +mt7615_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + if (!brightness) + mt7615_led_set_config(led_cdev, 0, 0xff); + else + mt7615_led_set_config(led_cdev, 0xff, 0); +} + static void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband) { - int i, n_chains = hweight8(dev->mt76.antenna_mask), target_chains; + int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains; u8 *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = sband->band; + int delta = mt76_tx_power_nss_delta(n_chains); target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; for (i = 0; i < sband->n_channels; i++) { @@ -220,21 +284,7 @@ mt7615_init_txpower(struct mt7615_dev *dev, target_power = max(target_power, eep[index]); } - target_power = DIV_ROUND_UP(target_power, 2); - switch (n_chains) { - case 4: - target_power += 6; - break; - case 3: - target_power += 4; - break; - case 2: - target_power += 3; - break; - default: - break; - } - + target_power = DIV_ROUND_UP(target_power + delta, 2); chan->max_power = min_t(int, chan->max_reg_power, target_power); chan->orig_mpwr = target_power; @@ -246,74 +296,181 @@ mt7615_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt7615_dev *dev = hw->priv; - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; - - if (request->dfs_region == dev->mt76.region) - return; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct mt7615_phy *phy = mphy->priv; + struct cfg80211_chan_def *chandef = &mphy->chandef; dev->mt76.region = request->dfs_region; if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) return; - mt7615_dfs_stop_radar_detector(dev); - if (request->dfs_region == NL80211_DFS_UNSET) - mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0, - MT_RX_SEL0, 0); - else - mt7615_dfs_start_radar_detector(dev); + mt7615_dfs_init_radar_detector(phy); } -int mt7615_register_device(struct mt7615_dev *dev) +static void +mt7615_init_wiphy(struct ieee80211_hw *hw) { - struct ieee80211_hw *hw = mt76_hw(dev); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct wiphy *wiphy = hw->wiphy; - int ret; - - INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); - - ret = mt7615_init_hardware(dev); - if (ret) - return ret; hw->queues = 4; hw->max_rates = 3; hw->max_report_rates = 7; hw->max_rate_tries = 11; + phy->slottime = 9; + hw->sta_data_size = sizeof(struct mt7615_sta); hw->vif_data_size = sizeof(struct mt7615_vif); wiphy->iface_combinations = if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->reg_notifier = mt7615_regd_notifier; - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); - dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.vht_cap.cap |= + 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; +} + +static void +mt7615_cap_dbdc_enable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap &= + ~(IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); + if (dev->chainmask == 0xf) + dev->mphy.antenna_mask = dev->chainmask >> 2; + else + dev->mphy.antenna_mask = dev->chainmask >> 1; + dev->phy.chainmask = dev->mphy.antenna_mask; + mt76_set_stream_caps(&dev->mt76, true); +} + +static void +mt7615_cap_dbdc_disable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; - dev->dfs_state = -1; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; + mt76_set_stream_caps(&dev->mt76, true); +} + +int mt7615_register_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy; + int ret; + + if (!is_mt7615(&dev->mt76)) + return -EOPNOTSUPP; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return -EINVAL; + + if (phy) + return 0; + + mt7615_cap_dbdc_enable(dev); + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); + if (!mphy) + return -ENOMEM; + + phy = mphy->priv; + phy->dev = dev; + phy->mt76 = mphy; + phy->chainmask = dev->chainmask & ~dev->phy.chainmask; + mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; + mt7615_init_wiphy(mphy->hw); + + /* + * Make the secondary PHY MAC address local without overlapping with + * the usual MAC address allocation scheme on multiple virtual interfaces + */ + mphy->hw->wiphy->perm_addr[0] |= 2; + mphy->hw->wiphy->perm_addr[0] ^= BIT(7); + + /* second phy can only handle 5 GHz */ + mphy->sband_2g.sband.n_channels = 0; + mphy->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + + /* The second interface does not get any packets unless it has a vif */ + ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); + + ret = mt76_register_phy(mphy); + if (ret) + ieee80211_free_hw(mphy->hw); + + return ret; +} + +void mt7615_unregister_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy = dev->mt76.phy2; + + if (!phy) + return; + + mt7615_cap_dbdc_disable(dev); + mt76_unregister_phy(mphy); + ieee80211_free_hw(mphy->hw); +} + + +int mt7615_register_device(struct mt7615_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + int ret; + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); + INIT_LIST_HEAD(&dev->sta_poll_list); + spin_lock_init(&dev->sta_poll_lock); + init_waitqueue_head(&dev->reset_wait); + INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); + + ret = mt7622_wmac_init(dev); + if (ret) + return ret; + + ret = mt7615_init_hardware(dev); + if (ret) + return ret; + + mt7615_init_wiphy(hw); + 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_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + mt7615_cap_dbdc_disable(dev); + dev->phy.dfs_state = -1; + + /* init led callbacks */ + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + dev->mt76.led_cdev.brightness_set = mt7615_led_set_brightness; + dev->mt76.led_cdev.blink_set = mt7615_led_set_blink; + } ret = mt76_register_device(&dev->mt76, true, mt7615_rates, ARRAY_SIZE(mt7615_rates)); if (ret) return ret; - mt7615_init_txpower(dev, &dev->mt76.sband_2g.sband); - mt7615_init_txpower(dev, &dev->mt76.sband_5g.sband); - - hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; + ieee80211_queue_work(mt76_hw(dev), &dev->mcu_work); + mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); return mt7615_init_debugfs(dev); } @@ -321,10 +478,15 @@ int mt7615_register_device(struct mt7615_dev *dev) void mt7615_unregister_device(struct mt7615_dev *dev) { struct mt76_txwi_cache *txwi; + bool mcu_running; int id; + mcu_running = mt7615_wait_for_mcu_init(dev); + + mt7615_unregister_ext_phy(dev); mt76_unregister_device(&dev->mt76); - mt7615_mcu_exit(dev); + if (mcu_running) + mt7615_mcu_exit(dev); mt7615_dma_cleanup(dev); spin_lock_bh(&dev->token_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index c77adc5d2552..145366dbc39b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -10,13 +10,50 @@ #include #include #include "mt7615.h" +#include "../trace.h" #include "../dma.h" +#include "mt7615_trace.h" #include "mac.h" -static inline s8 to_rssi(u32 field, u32 rxv) -{ - return (FIELD_GET(field, rxv) - 220) / 2; -} +#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) + +static const struct mt7615_dfs_radar_spec etsi_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [5] = { 1, 0, 6, 32, 28, 0, 17, 990, 5010, 1, 1 }, + [6] = { 1, 0, 9, 32, 28, 0, 27, 615, 5010, 1, 1 }, + [7] = { 1, 0, 15, 32, 28, 0, 27, 240, 445, 1, 1 }, + [8] = { 1, 0, 12, 32, 28, 0, 42, 240, 510, 1, 1 }, + [9] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 12, 32, 28 }, + [10] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 15, 32, 24 }, + [11] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 18, 32, 28 }, + [12] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 27, 32, 24 }, + }, +}; + +static const struct mt7615_dfs_radar_spec fcc_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 9, 32, 28, 0, 13, 508, 3076, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 }, + [4] = { 1, 0, 9, 255, 28, 0, 13, 323, 343, 1, 32 }, + }, +}; + +static const struct mt7615_dfs_radar_spec jp_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 8, 32, 28, 0, 13, 508, 3076, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 }, + [4] = { 1, 0, 9, 32, 28, 0, 13, 323, 343, 1, 32 }, + [13] = { 1, 0, 8, 32, 28, 0, 14, 3836, 3856, 1, 1 }, + [14] = { 1, 0, 8, 32, 28, 0, 14, 3990, 4010, 1, 1 }, + }, +}; static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, u8 idx, bool unicast) @@ -49,34 +86,116 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev) mt76_rr(dev, MT_TX_AGG_CNT(i)); memset(dev->mt76.aggr_stats, 0, sizeof(dev->mt76.aggr_stats)); - - /* TODO: add DBDC support */ + dev->mt76.phy.survey_time = ktime_get_boottime(); + if (dev->mt76.phy2) + dev->mt76.phy2->survey_time = ktime_get_boottime(); /* reset airtime counters */ mt76_rr(dev, MT_MIB_SDR9(0)); + mt76_rr(dev, MT_MIB_SDR9(1)); + mt76_rr(dev, MT_MIB_SDR36(0)); + mt76_rr(dev, MT_MIB_SDR36(1)); + mt76_rr(dev, MT_MIB_SDR37(0)); + mt76_rr(dev, MT_MIB_SDR37(1)); + mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_CLR); } +void mt7615_mac_set_timing(struct mt7615_phy *phy) +{ + s16 coverage_class = phy->coverage_class; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 val, reg_offset; + u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24); + int sifs, offset; + + if (phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ) + sifs = 16; + else + sifs = 10; + + if (ext_phy) { + coverage_class = max_t(s16, dev->phy.coverage_class, + coverage_class); + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE); + } else { + struct mt7615_phy *phy_ext = mt7615_ext_phy(dev); + + if (phy_ext) + coverage_class = max_t(s16, phy_ext->coverage_class, + coverage_class); + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE); + } + udelay(1); + + offset = 3 * coverage_class; + reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + mt76_wr(dev, MT_TMAC_CDTR, cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR, ofdm + reg_offset); + + mt76_wr(dev, MT_TMAC_ICR(ext_phy), + FIELD_PREP(MT_IFS_EIFS, 360) | + FIELD_PREP(MT_IFS_RIFS, 2) | + FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, phy->slottime)); + + if (phy->slottime < 20) + val = MT7615_CFEND_RATE_DEFAULT; + else + val = MT7615_CFEND_RATE_11B; + + mt76_rmw_field(dev, MT_AGG_ACR(ext_phy), MT_AGG_ACR_CFEND_RATE, val); + if (ext_phy) + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE); + else + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE); + +} + int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_phy *phy = &dev->phy; + struct mt7615_phy *phy2 = dev->mt76.phy2 ? dev->mt76.phy2->priv : NULL; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; __le32 *rxd = (__le32 *)skb->data; 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; + int phy_idx; int i, idx; - - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) - return -EINVAL; + u8 chfreq; memset(status, 0, sizeof(*status)); + chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); + if (!phy2) + phy_idx = 0; + else if (phy2->chfreq == phy->chfreq) + phy_idx = -1; + else if (phy->chfreq == chfreq) + phy_idx = 0; + else if (phy2->chfreq == chfreq) + phy_idx = 1; + else + phy_idx = -1; + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); @@ -91,14 +210,6 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->sta_poll_lock); } - /* TODO: properly support DBDC */ - status->freq = dev->mt76.chandef.chan->center_freq; - status->band = dev->mt76.chandef.chan->band; - if (status->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; - else - sband = &dev->mt76.sband_2g.sband; - if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; @@ -112,28 +223,11 @@ int mt7615_mac_fill_rx(struct mt7615_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->mt76.ampdu_ref) - dev->mt76.ampdu_ref++; - } - dev->rx_ampdu_ts = rxd[12]; - - status->ampdu_ref = dev->mt76.ampdu_ref; - } - remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) return -EINVAL; - if (!sband->channels) - return -EINVAL; - rxd += 4; if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { rxd += 4; @@ -165,6 +259,59 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) return -EINVAL; } + if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { + u32 rxdg5 = le32_to_cpu(rxd[5]); + + /* + * If both PHYs are on the same channel and we don't have a WCID, + * we need to figure out which PHY this packet was received on. + * On the primary PHY, the noise value for the chains belonging to the + * second PHY will be set to the noise value of the last packet from + * that PHY. + */ + if (phy_idx < 0) { + int first_chain = ffs(phy2->chainmask) - 1; + + phy_idx = ((rxdg5 >> (first_chain * 8)) & 0xff) == 0; + } + } + + if (phy_idx == 1 && phy2) { + mphy = dev->mt76.phy2; + phy = phy2; + status->ext_phy = true; + } + + if (chfreq != phy->chfreq) + return -EINVAL; + + status->freq = mphy->chandef.chan->center_freq; + status->band = mphy->chandef.chan->band; + if (status->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) + return -EINVAL; + + 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]); @@ -218,14 +365,14 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - status->chains = dev->mt76.antenna_mask; + status->chains = mphy->antenna_mask; status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3); status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3); status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3); status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3); status->signal = status->chain_signal[0]; - for (i = 1; i < hweight8(dev->mt76.antenna_mask); i++) { + for (i = 1; i < hweight8(mphy->antenna_mask); i++) { if (!(status->chains & BIT(i))) continue; @@ -274,13 +421,20 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, if (e->skb == DMA_DUMMY_DATA) { struct mt76_txwi_cache *t; struct mt7615_dev *dev; - struct mt7615_txp *txp; + struct mt7615_txp_common *txp; + u16 token; dev = container_of(mdev, struct mt7615_dev, mt76); txp = mt7615_txwi_to_txp(mdev, e->txwi); + if (is_mt7615(&dev->mt76)) + token = le16_to_cpu(txp->fw.token); + else + token = le16_to_cpu(txp->hw.msdu_id[0]) & + ~MT_MSDU_ID_VALID; + spin_lock_bh(&dev->token_lock); - t = idr_remove(&dev->token, le16_to_cpu(txp->token)); + t = idr_remove(&dev->token, token); spin_unlock_bh(&dev->token_lock); e->skb = t ? t->skb : NULL; } @@ -291,6 +445,7 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, static u16 mt7615_mac_tx_rate_val(struct mt7615_dev *dev, + struct mt76_phy *mphy, const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw) { @@ -319,11 +474,11 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev, *bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mt76.chandef.chan->band; + int band = mphy->chandef.chan->band; u16 val; nss = 1; - r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx]; + r = &mphy->hw->wiphy->bands[band]->bitrates[rate->idx]; if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) val = r->hw_value_short; else @@ -355,6 +510,8 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; bool multicast = is_multicast_ether_addr(hdr->addr1); struct ieee80211_vif *vif = info->control.vif; + struct mt76_phy *mphy = &dev->mphy; + bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; int tx_count = 8; u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; __le16 fc = hdr->frame_control; @@ -374,6 +531,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, tx_count = msta->rate_count; } + if (ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; @@ -382,10 +542,16 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, skb_get_queue_mapping(skb); p_fmt = MT_TX_TYPE_CT; } else if (ieee80211_is_beacon(fc)) { - q_idx = MT_LMAC_BCN0; + if (ext_phy) + q_idx = MT_LMAC_BCN1; + else + q_idx = MT_LMAC_BCN0; p_fmt = MT_TX_TYPE_FW; } else { - q_idx = MT_LMAC_ALTX0; + if (ext_phy) + q_idx = MT_LMAC_ALTX1; + else + q_idx = MT_LMAC_ALTX0; p_fmt = MT_TX_TYPE_CT; } @@ -431,7 +597,8 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) { bool stbc = info->flags & IEEE80211_TX_CTL_STBC; u8 bw; - u16 rateval = mt7615_mac_tx_rate_val(dev, rate, stbc, &bw); + u16 rateval = mt7615_mac_tx_rate_val(dev, mphy, rate, stbc, + &bw); txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); @@ -486,18 +653,56 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, return 0; } -void mt7615_txp_skb_unmap(struct mt76_dev *dev, - struct mt76_txwi_cache *t) +static void +mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp) { - struct mt7615_txp *txp; int i; - txp = mt7615_txwi_to_txp(dev, t); for (i = 1; 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 +mt7615_txp_skb_unmap_hw(struct mt76_dev *dev, struct mt7615_hw_txp *txp) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) { + struct mt7615_txp_ptr *ptr = &txp->ptr[i]; + bool last; + u16 len; + + len = le16_to_cpu(ptr->len0); + last = len & MT_TXD_LEN_MSDU_LAST; + len &= ~MT_TXD_LEN_MSDU_LAST; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len, + DMA_TO_DEVICE); + if (last) + break; + + len = le16_to_cpu(ptr->len1); + last = len & MT_TXD_LEN_MSDU_LAST; + len &= ~MT_TXD_LEN_MSDU_LAST; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len, + DMA_TO_DEVICE); + if (last) + break; + } +} + +void mt7615_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *t) +{ + struct mt7615_txp_common *txp; + + txp = mt7615_txwi_to_txp(dev, t); + if (is_mt7615(dev)) + mt7615_txp_skb_unmap_fw(dev, &txp->fw); + else + mt7615_txp_skb_unmap_hw(dev, &txp->hw); +} + static u32 mt7615_mac_wtbl_addr(int wcid) { return MT_WTBL_BASE + wcid * MT_WTBL_ENTRY_SIZE; @@ -588,10 +793,12 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) rcu_read_unlock(); } -void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, +void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates) { + struct mt7615_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; struct ieee80211_tx_rate *ref; int wcid = sta->wcid.idx; u32 addr = mt7615_mac_wtbl_addr(wcid); @@ -649,11 +856,12 @@ void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, } } - val[0] = mt7615_mac_tx_rate_val(dev, &rates[0], stbc, &bw); + val[0] = mt7615_mac_tx_rate_val(dev, mphy, &rates[0], stbc, &bw); bw_prev = bw; if (probe_rate) { - probe_val = mt7615_mac_tx_rate_val(dev, probe_rate, stbc, &bw); + probe_val = mt7615_mac_tx_rate_val(dev, mphy, probe_rate, + stbc, &bw); if (bw) bw_idx = 1; else @@ -662,19 +870,19 @@ void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, probe_val = val[0]; } - val[1] = mt7615_mac_tx_rate_val(dev, &rates[1], stbc, &bw); + val[1] = mt7615_mac_tx_rate_val(dev, mphy, &rates[1], stbc, &bw); if (bw_prev) { bw_idx = 3; bw_prev = bw; } - val[2] = mt7615_mac_tx_rate_val(dev, &rates[2], stbc, &bw); + val[2] = mt7615_mac_tx_rate_val(dev, mphy, &rates[2], stbc, &bw); if (bw_prev) { bw_idx = 5; bw_prev = bw; } - val[3] = mt7615_mac_tx_rate_val(dev, &rates[3], stbc, &bw); + val[3] = mt7615_mac_tx_rate_val(dev, mphy, &rates[3], stbc, &bw); if (bw_prev) bw_idx = 7; @@ -884,39 +1092,51 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, return err; } -int mt7615_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) +static void +mt7615_write_hw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, + void *txp_ptr, u32 id) +{ + struct mt7615_hw_txp *txp = txp_ptr; + struct mt7615_txp_ptr *ptr = &txp->ptr[0]; + int nbuf = tx_info->nbuf - 1; + int i; + + tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); + tx_info->nbuf = 1; + + txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); + + for (i = 0; i < nbuf; i++) { + u32 addr = tx_info->buf[i + 1].addr; + u16 len = tx_info->buf[i + 1].len; + + if (i == nbuf - 1) + len |= MT_TXD_LEN_MSDU_LAST | + MT_TXD_LEN_AMSDU_LAST; + + if (i & 1) { + ptr->buf1 = cpu_to_le32(addr); + ptr->len1 = cpu_to_le16(len); + ptr++; + } else { + ptr->buf0 = cpu_to_le32(addr); + ptr->len0 = cpu_to_le16(len); + } + } +} + +static void +mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, + void *txp_ptr, u32 id) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid); 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; - int i, pid, id, nbuf = tx_info->nbuf - 1; - u8 *txwi = (u8 *)txwi_ptr; - struct mt76_txwi_cache *t; - struct mt7615_txp *txp; + struct mt7615_fw_txp *txp = txp_ptr; + int nbuf = tx_info->nbuf - 1; + int i; - if (!wcid) - wcid = &dev->mt76.global_wcid; - - pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); - - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { - spin_lock_bh(&dev->mt76.lock); - mt7615_mac_set_rates(dev, msta, &info->control.rates[0], - msta->rates); - msta->rate_probe = true; - spin_unlock_bh(&dev->mt76.lock); - } - - mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, - pid, key); - - txp = (struct mt7615_txp *)(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); @@ -924,6 +1144,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, txp->nbuf = nbuf; /* pass partial skb header to fw */ + tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); tx_info->buf[1].len = MT_CT_PARSE_LEN; tx_info->nbuf = MT_CT_DMA_BUF_NUM; @@ -941,6 +1162,42 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, txp->bss_idx = mvif->idx; } + txp->token = cpu_to_le16(id); + txp->rept_wds_wcid = 0xff; +} + +int mt7615_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) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + int pid, id; + u8 *txwi = (u8 *)txwi_ptr; + struct mt76_txwi_cache *t; + void *txp; + + if (!wcid) + wcid = &dev->mt76.global_wcid; + + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { + struct mt7615_phy *phy = &dev->phy; + + if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2) + phy = mdev->phy2->priv; + + spin_lock_bh(&dev->mt76.lock); + mt7615_mac_set_rates(phy, msta, &info->control.rates[0], + msta->rates); + msta->rate_probe = true; + spin_unlock_bh(&dev->mt76.lock); + } + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); t->skb = tx_info->skb; @@ -950,8 +1207,16 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (id < 0) return id; - txp->token = cpu_to_le16(id); - txp->rept_wds_wcid = 0xff; + mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, + pid, key); + + txp = txwi + MT_TXD_SIZE; + memset(txp, 0, sizeof(struct mt7615_txp_common)); + if (is_mt7615(&dev->mt76)) + mt7615_write_fw_txp(dev, tx_info, txp, id); + else + mt7615_write_hw_txp(dev, tx_info, txp, id); + tx_info->skb = DMA_DUMMY_DATA; return 0; @@ -962,6 +1227,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, { struct ieee80211_supported_band *sband; struct mt7615_rate_set *rs; + struct mt76_phy *mphy; int first_idx = 0, last_idx; int i, idx, count; bool fixed_rate, ack_timeout; @@ -1019,7 +1285,12 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, spin_lock_bh(&dev->mt76.lock); if (sta->rate_probe) { - mt7615_mac_set_rates(dev, sta, NULL, sta->rates); + struct mt7615_phy *phy = &dev->phy; + + if (sta->wcid.ext_phy && dev->mt76.phy2) + phy = dev->mt76.phy2->priv; + + mt7615_mac_set_rates(phy, sta, NULL, sta->rates); sta->rate_probe = false; } spin_unlock_bh(&dev->mt76.lock); @@ -1059,10 +1330,14 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; + mphy = &dev->mphy; + if (sta->wcid.ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; else - sband = &dev->mt76.sband_2g.sband; + sband = &mphy->sband_2g.sband; final_rate &= MT_TX_RATE_IDX; final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, cck); @@ -1105,6 +1380,8 @@ static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev, if (pid < MT_PACKET_ID_FIRST) return false; + trace_mac_txdone(mdev, sta->wcid.idx, pid); + mt76_tx_status_lock(mdev, &list); skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); if (skb) { @@ -1128,6 +1405,7 @@ void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) struct ieee80211_sta *sta = NULL; struct mt7615_sta *msta = NULL; struct mt76_wcid *wcid; + struct mt76_phy *mphy = &dev->mt76.phy; __le32 *txs_data = data; u32 txs; u8 wcidx; @@ -1164,111 +1442,154 @@ void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) if (wcidx >= MT7615_WTBL_STA || !sta) goto out; + if (wcid->ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + if (mt7615_fill_txs(dev, msta, &info, txs_data)) - ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); + ieee80211_tx_status_noskb(mphy->hw, sta, &info); out: rcu_read_unlock(); } +static void +mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) +{ + struct mt76_dev *mdev = &dev->mt76; + struct mt76_txwi_cache *txwi; + + trace_mac_tx_free(dev, token); + + spin_lock_bh(&dev->token_lock); + txwi = idr_remove(&dev->token, token); + spin_unlock_bh(&dev->token_lock); + + if (!txwi) + return; + + mt7615_txp_skb_unmap(mdev, txwi); + if (txwi->skb) { + mt76_tx_complete_skb(mdev, txwi->skb); + txwi->skb = NULL; + } + + mt76_put_txwi(mdev, txwi); +} + void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; - struct mt76_dev *mdev = &dev->mt76; - struct mt76_txwi_cache *txwi; u8 i, count; count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); - for (i = 0; i < count; i++) { - spin_lock_bh(&dev->token_lock); - txwi = idr_remove(&dev->token, le16_to_cpu(free->token[i])); - spin_unlock_bh(&dev->token_lock); + if (is_mt7615(&dev->mt76)) { + __le16 *token = &free->token[0]; - if (!txwi) - continue; + for (i = 0; i < count; i++) + mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i])); + } else { + __le32 *token = (__le32 *)&free->token[0]; - mt7615_txp_skb_unmap(mdev, txwi); - if (txwi->skb) { - mt76_tx_complete_skb(mdev, txwi->skb); - txwi->skb = NULL; - } - - mt76_put_txwi(mdev, txwi); + for (i = 0; i < count; i++) + mt7615_mac_tx_free_token(dev, le32_to_cpu(token[i])); } + dev_kfree_skb(skb); } static void -mt7615_mac_set_default_sensitivity(struct mt7615_dev *dev) +mt7615_mac_set_default_sensitivity(struct mt7615_phy *phy) { - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(0x13c)); - mt76_rmw(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_OFDM_MASK, - MT_WF_PHY_B1_PD_OFDM(0x13c)); + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(0x92)); - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(0x92)); + mt76_rmw(dev, MT_WF_PHY_MIN_PRI_PWR(ext_phy), + MT_WF_PHY_PD_OFDM_MASK(ext_phy), + MT_WF_PHY_PD_OFDM(ext_phy, 0x13c)); + mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy), + MT_WF_PHY_PD_CCK_MASK(ext_phy), + MT_WF_PHY_PD_CCK(ext_phy, 0x92)); - dev->ofdm_sensitivity = -98; - dev->cck_sensitivity = -110; - dev->last_cca_adj = jiffies; + phy->ofdm_sensitivity = -98; + phy->cck_sensitivity = -110; + phy->last_cca_adj = jiffies; } void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable) { + struct mt7615_phy *ext_phy; + mutex_lock(&dev->mt76.mutex); if (dev->scs_en == enable) goto out; if (enable) { - /* DBDC not supported */ - mt76_set(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_BLK); + mt76_set(dev, MT_WF_PHY_MIN_PRI_PWR(0), + MT_WF_PHY_PD_BLK(0)); + mt76_set(dev, MT_WF_PHY_MIN_PRI_PWR(1), + MT_WF_PHY_PD_BLK(1)); if (is_mt7622(&dev->mt76)) { mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7 << 8); mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7); } } else { - mt76_clear(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_BLK); - mt76_clear(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_BLK); + mt76_clear(dev, MT_WF_PHY_MIN_PRI_PWR(0), + MT_WF_PHY_PD_BLK(0)); + mt76_clear(dev, MT_WF_PHY_MIN_PRI_PWR(1), + MT_WF_PHY_PD_BLK(1)); } - mt7615_mac_set_default_sensitivity(dev); + mt7615_mac_set_default_sensitivity(&dev->phy); + ext_phy = mt7615_ext_phy(dev); + if (ext_phy) + mt7615_mac_set_default_sensitivity(ext_phy); + dev->scs_en = enable; out: mutex_unlock(&dev->mt76.mutex); } -void mt7615_mac_cca_stats_reset(struct mt7615_dev *dev) +void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy) { - mt76_clear(dev, MT_WF_PHY_R0_B0_PHYMUX_5, GENMASK(22, 20)); - mt76_set(dev, MT_WF_PHY_R0_B0_PHYMUX_5, BIT(22) | BIT(20)); + u32 rxtd; + + if (ext_phy) + rxtd = MT_WF_PHY_RXTD2(10); + else + rxtd = MT_WF_PHY_RXTD(12); + + mt76_set(dev, rxtd, BIT(18) | BIT(29)); + mt76_set(dev, MT_WF_PHY_R0_PHYMUX_5(ext_phy), 0x5 << 12); +} + +void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy) +{ + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 reg = MT_WF_PHY_R0_PHYMUX_5(ext_phy); + + mt76_clear(dev, reg, GENMASK(22, 20)); + mt76_set(dev, reg, BIT(22) | BIT(20)); } static void -mt7615_mac_adjust_sensitivity(struct mt7615_dev *dev, +mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy, u32 rts_err_rate, bool ofdm) { - int false_cca = ofdm ? dev->false_cca_ofdm : dev->false_cca_cck; + struct mt7615_dev *dev = phy->dev; + int false_cca = ofdm ? phy->false_cca_ofdm : phy->false_cca_cck; + bool ext_phy = phy != &dev->phy; u16 def_th = ofdm ? -98 : -110; bool update = false; s8 *sensitivity; int signal; - sensitivity = ofdm ? &dev->ofdm_sensitivity : &dev->cck_sensitivity; - signal = mt76_get_min_avg_rssi(&dev->mt76); + sensitivity = ofdm ? &phy->ofdm_sensitivity : &phy->cck_sensitivity; + signal = mt76_get_min_avg_rssi(&dev->mt76, ext_phy); if (!signal) { - mt7615_mac_set_default_sensitivity(dev); + mt7615_mac_set_default_sensitivity(phy); return; } @@ -1303,99 +1624,156 @@ mt7615_mac_adjust_sensitivity(struct mt7615_dev *dev, u16 val; if (ofdm) { - /* DBDC not supported */ val = *sensitivity * 2 + 512; - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(val)); + mt76_rmw(dev, MT_WF_PHY_MIN_PRI_PWR(ext_phy), + MT_WF_PHY_PD_OFDM_MASK(ext_phy), + MT_WF_PHY_PD_OFDM(ext_phy, val)); } else { val = *sensitivity + 256; - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(val)); - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(val)); + if (!ext_phy) + mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy), + MT_WF_PHY_PD_CCK_MASK(ext_phy), + MT_WF_PHY_PD_CCK(ext_phy, val)); } - dev->last_cca_adj = jiffies; + phy->last_cca_adj = jiffies; } } static void -mt7615_mac_scs_check(struct mt7615_dev *dev) +mt7615_mac_scs_check(struct mt7615_phy *phy) { - u32 val, rts_cnt = 0, rts_retries_cnt = 0, rts_err_rate = 0; + struct mt7615_dev *dev = phy->dev; + struct mib_stats *mib = &phy->mib; + u32 val, rts_err_rate = 0; u32 mdrdy_cck, mdrdy_ofdm, pd_cck, pd_ofdm; - int i; + bool ext_phy = phy != &dev->phy; if (!dev->scs_en) return; - for (i = 0; i < 4; i++) { - u32 data; - - val = mt76_rr(dev, MT_MIB_MB_SDR0(i)); - data = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (data > rts_retries_cnt) { - rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - rts_retries_cnt = data; - } - } - - val = mt76_rr(dev, MT_WF_PHY_R0_B0_PHYCTRL_STS0); + val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS0(ext_phy)); pd_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_CCK, val); pd_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_OFDM, val); - val = mt76_rr(dev, MT_WF_PHY_R0_B0_PHYCTRL_STS5); + val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS5(ext_phy)); mdrdy_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_CCK, val); mdrdy_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_OFDM, val); - dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; - dev->false_cca_cck = pd_cck - mdrdy_cck; - mt7615_mac_cca_stats_reset(dev); + phy->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; + phy->false_cca_cck = pd_cck - mdrdy_cck; + mt7615_mac_cca_stats_reset(phy); - if (rts_cnt + rts_retries_cnt) - rts_err_rate = MT_FRAC(rts_retries_cnt, - rts_cnt + rts_retries_cnt); + if (mib->rts_cnt + mib->rts_retries_cnt) + rts_err_rate = MT_FRAC(mib->rts_retries_cnt, + mib->rts_cnt + mib->rts_retries_cnt); /* cck */ - mt7615_mac_adjust_sensitivity(dev, rts_err_rate, false); + mt7615_mac_adjust_sensitivity(phy, rts_err_rate, false); /* ofdm */ - mt7615_mac_adjust_sensitivity(dev, rts_err_rate, true); + mt7615_mac_adjust_sensitivity(phy, rts_err_rate, true); - if (time_after(jiffies, dev->last_cca_adj + 10 * HZ)) - mt7615_mac_set_default_sensitivity(dev); + if (time_after(jiffies, phy->last_cca_adj + 10 * HZ)) + mt7615_mac_set_default_sensitivity(phy); +} + +static u8 +mt7615_phy_get_nf(struct mt7615_dev *dev, int idx) +{ + static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; + u32 reg = idx ? MT_WF_PHY_RXTD2(17) : MT_WF_PHY_RXTD(20); + u32 val, sum = 0, n = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { + val = mt76_rr(dev, reg); + sum += val * nf_power[i]; + n += val; + } + + if (!n) + return 0; + + return sum / n; +} + +static void +mt7615_phy_update_channel(struct mt76_phy *mphy, int idx) +{ + struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76); + struct mt7615_phy *phy = mphy->priv; + struct mt76_channel_state *state; + u64 busy_time, tx_time, rx_time, obss_time; + u32 obss_reg = idx ? MT_WF_RMAC_MIB_TIME6 : MT_WF_RMAC_MIB_TIME5; + int nf; + + busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), + MT_MIB_SDR9_BUSY_MASK); + tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), + MT_MIB_SDR36_TXTIME_MASK); + rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), + MT_MIB_SDR37_RXTIME_MASK); + obss_time = mt76_get_field(dev, obss_reg, MT_MIB_OBSSTIME_MASK); + + nf = mt7615_phy_get_nf(dev, idx); + if (!phy->noise) + phy->noise = nf << 4; + else if (nf) + phy->noise += nf - (phy->noise >> 4); + + state = mphy->chan_state; + state->cc_busy += busy_time; + state->cc_tx += tx_time; + state->cc_rx += rx_time + obss_time; + state->cc_bss_rx += rx_time; + state->noise = -(phy->noise >> 4); } void mt7615_update_channel(struct mt76_dev *mdev) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - struct mt76_channel_state *state; - u64 busy_time, tx_time, rx_time, obss_time; - /* TODO: add DBDC support */ - busy_time = mt76_get_field(dev, MT_MIB_SDR9(0), - MT_MIB_SDR9_BUSY_MASK); - tx_time = mt76_get_field(dev, MT_MIB_SDR36(0), - MT_MIB_SDR36_TXTIME_MASK); - rx_time = mt76_get_field(dev, MT_MIB_SDR37(0), - MT_MIB_SDR37_RXTIME_MASK); - obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_TIME5, - MT_MIB_OBSSTIME_MASK); - - state = mdev->chan_state; - state->cc_busy += busy_time; - state->cc_tx += tx_time; - state->cc_rx += rx_time + obss_time; - state->cc_bss_rx += rx_time; + mt7615_phy_update_channel(&mdev->phy, 0); + if (mdev->phy2) + mt7615_phy_update_channel(mdev->phy2, 1); /* reset obss airtime */ mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); } +static void +mt7615_mac_update_mib_stats(struct mt7615_phy *phy) +{ + struct mt7615_dev *dev = phy->dev; + struct mib_stats *mib = &phy->mib; + bool ext_phy = phy != &dev->phy; + int i; + + memset(mib, 0, sizeof(*mib)); + + mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); + + for (i = 0; i < 4; i++) { + u32 data, val, val2; + + val = mt76_get_field(dev, MT_MIB_MB_SDR1(ext_phy, i), + MT_MIB_ACK_FAIL_COUNT_MASK); + if (val > mib->ack_fail_cnt) + mib->ack_fail_cnt = val; + + val2 = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); + data = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val2); + if (data > mib->rts_retries_cnt) { + mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val2); + mib->rts_retries_cnt = data; + } + } +} + void mt7615_mac_work(struct work_struct *work) { struct mt7615_dev *dev; + struct mt7615_phy *ext_phy; int i, idx; dev = (struct mt7615_dev *)container_of(work, struct mt76_dev, @@ -1404,7 +1782,15 @@ void mt7615_mac_work(struct work_struct *work) mutex_lock(&dev->mt76.mutex); mt76_update_survey(&dev->mt76); if (++dev->mac_work_count == 5) { - mt7615_mac_scs_check(dev); + ext_phy = mt7615_ext_phy(dev); + + mt7615_mac_update_mib_stats(&dev->phy); + mt7615_mac_scs_check(&dev->phy); + if (ext_phy) { + mt7615_mac_update_mib_stats(ext_phy); + mt7615_mac_scs_check(ext_phy); + } + dev->mac_work_count = 0; } @@ -1421,21 +1807,139 @@ void mt7615_mac_work(struct work_struct *work) MT7615_WATCHDOG_TIME); } -int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev) +static bool +mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; - int err; + bool ret; - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD0, - MT_RX_SEL0, 0); - if (err < 0) - return err; + 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; +} - if (chandef->width == NL80211_CHAN_WIDTH_160 || - chandef->width == NL80211_CHAN_WIDTH_80P80) - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD1, - MT_RX_SEL0, 0); - return err; +static void +mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct ieee80211_hw *hw = priv; + + mt7615_mcu_set_bcn(hw, vif, vif->bss_conf.enable_beacon); +} + +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); +} + +static 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, i, true); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); 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); +} + +void mt7615_mac_reset_work(struct work_struct *work) +{ + struct mt7615_dev *dev; + + dev = container_of(work, struct mt7615_dev, reset_work); + + if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) + return; + + ieee80211_stop_queues(mt76_hw(dev)); + if (dev->mt76.phy2) + ieee80211_stop_queues(dev->mt76.phy2->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->mt76.mac_work); + + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mphy); + if (dev->mt76.phy2) + mt76_txq_schedule_all(dev->mt76.phy2); + + tasklet_disable(&dev->mt76.tx_tasklet); + napi_disable(&dev->mt76.napi[0]); + napi_disable(&dev->mt76.napi[1]); + napi_disable(&dev->mt76.tx_napi); + + mutex_lock(&dev->mt76.mutex); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED); + + 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); + + tasklet_enable(&dev->mt76.tx_tasklet); + 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 (dev->mt76.phy2) + ieee80211_wake_queues(dev->mt76.phy2->hw); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + mutex_unlock(&dev->mt76.mutex); + + mt7615_update_beacons(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7615_WATCHDOG_TIME); +} + +static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy) +{ + struct mt7615_dev *dev = phy->dev; + + if (phy->rdd_state & BIT(0)) + mt7615_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); + if (phy->rdd_state & BIT(1)) + mt7615_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); } static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) @@ -1450,61 +1954,112 @@ static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) MT_RX_SEL0, 1); } -int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev) +static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int err; /* start CAC */ - err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, MT_HW_RDD0, - MT_RX_SEL0, 0); + err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, ext_phy, MT_RX_SEL0, 0); if (err < 0) return err; - /* TODO: DBDC support */ - - err = mt7615_dfs_start_rdd(dev, MT_HW_RDD0); + err = mt7615_dfs_start_rdd(dev, ext_phy); if (err < 0) return err; + phy->rdd_state |= BIT(ext_phy); + if (chandef->width == NL80211_CHAN_WIDTH_160 || chandef->width == NL80211_CHAN_WIDTH_80P80) { - err = mt7615_dfs_start_rdd(dev, MT_HW_RDD1); + err = mt7615_dfs_start_rdd(dev, 1); if (err < 0) return err; + + phy->rdd_state |= BIT(1); } return 0; } -int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev) +static int +mt7615_dfs_init_radar_specs(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + const struct mt7615_dfs_radar_spec *radar_specs; + struct mt7615_dev *dev = phy->dev; + int err, i; + + switch (dev->mt76.region) { + case NL80211_DFS_FCC: + radar_specs = &fcc_radar_specs; + err = mt7615_mcu_set_fcc5_lpn(dev, 8); + if (err < 0) + return err; + break; + case NL80211_DFS_ETSI: + radar_specs = &etsi_radar_specs; + break; + case NL80211_DFS_JP: + radar_specs = &jp_radar_specs; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { + err = mt7615_mcu_set_radar_th(dev, i, + &radar_specs->radar_pattern[i]); + if (err < 0) + return err; + } + + return mt7615_mcu_set_pulse_th(dev, &radar_specs->pulse_th); +} + +int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy) +{ + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int err; - if (dev->mt76.region == NL80211_DFS_UNSET) + if (dev->mt76.region == NL80211_DFS_UNSET) { + phy->dfs_state = -1; + if (phy->rdd_state) + goto stop; + + return 0; + } + + if (test_bit(MT76_SCANNING, &phy->mt76->state)) return 0; - if (test_bit(MT76_SCANNING, &dev->mt76.state)) + if (phy->dfs_state == chandef->chan->dfs_state) return 0; - if (dev->dfs_state == chandef->chan->dfs_state) - return 0; + err = mt7615_dfs_init_radar_specs(phy); + if (err < 0) { + phy->dfs_state = -1; + goto stop; + } - dev->dfs_state = chandef->chan->dfs_state; + phy->dfs_state = chandef->chan->dfs_state; if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) - return mt7615_dfs_start_radar_detector(dev); - else - return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0, - MT_RX_SEL0, 0); - } else { - err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, - MT_HW_RDD0, MT_RX_SEL0, 0); - if (err < 0) - return err; + return mt7615_dfs_start_radar_detector(phy); - return mt7615_dfs_stop_radar_detector(dev); + return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, ext_phy, + MT_RX_SEL0, 0); } + +stop: + err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, ext_phy, MT_RX_SEL0, 0); + if (err < 0) + return err; + + mt7615_dfs_stop_radar_detector(phy); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 38695d4f92e2..6fa7e3dd6a3a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -103,6 +103,11 @@ enum rx_pkt_type { #define MT_RXV4_RCPI1 GENMASK(15, 8) #define MT_RXV4_RCPI0 GENMASK(7, 0) +#define MT_RXV6_NF3 GENMASK(31, 24) +#define MT_RXV6_NF2 GENMASK(23, 16) +#define MT_RXV6_NF1 GENMASK(15, 8) +#define MT_RXV6_NF0 GENMASK(7, 0) + enum tx_header_format { MT_HDR_FORMAT_802_3, MT_HDR_FORMAT_CMD, @@ -126,6 +131,10 @@ enum tx_pkt_queue_idx { MT_LMAC_BMC0, MT_LMAC_BCN0, MT_LMAC_PSMP0, + MT_LMAC_ALTX1, + MT_LMAC_BMC1, + MT_LMAC_BCN1, + MT_LMAC_PSMP1, }; enum tx_port_idx { @@ -229,8 +238,27 @@ enum tx_phy_bandwidth { #define MT_TX_RATE_IDX GENMASK(5, 0) #define MT_TXP_MAX_BUF_NUM 6 +#define MT_HW_TXP_MAX_MSDU_NUM 4 +#define MT_HW_TXP_MAX_BUF_NUM 4 -struct mt7615_txp { +#define MT_MSDU_ID_VALID BIT(15) + +#define MT_TXD_LEN_MSDU_LAST BIT(14) +#define MT_TXD_LEN_AMSDU_LAST BIT(15) + +struct mt7615_txp_ptr { + __le32 buf0; + __le16 len0; + __le16 len1; + __le32 buf1; +} __packed __aligned(4); + +struct mt7615_hw_txp { + __le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM]; + struct mt7615_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2]; +} __packed __aligned(4); + +struct mt7615_fw_txp { __le16 flags; __le16 token; u8 bss_idx; @@ -239,7 +267,14 @@ struct mt7615_txp { u8 nbuf; __le32 buf[MT_TXP_MAX_BUF_NUM]; __le16 len[MT_TXP_MAX_BUF_NUM]; -} __packed; +} __packed __aligned(4); + +struct mt7615_txp_common { + union { + struct mt7615_fw_txp fw; + struct mt7615_hw_txp hw; + }; +}; struct mt7615_tx_free { __le16 rx_byte_cnt; @@ -247,7 +282,7 @@ struct mt7615_tx_free { u8 txd_cnt; u8 rsv[3]; __le16 token[]; -} __packed; +} __packed __aligned(4); #define MT_TX_FREE_MSDU_ID_CNT GENMASK(6, 0) @@ -302,6 +337,38 @@ struct mt7615_tx_free { #define MT_TXS6_F1_RCPI_1 GENMASK(15, 8) #define MT_TXS6_F1_RCPI_0 GENMASK(7, 0) +struct mt7615_dfs_pulse { + u32 max_width; /* us */ + int max_pwr; /* dbm */ + int min_pwr; /* dbm */ + u32 min_stgr_pri; /* us */ + u32 max_stgr_pri; /* us */ + u32 min_cr_pri; /* us */ + u32 max_cr_pri; /* us */ +}; + +struct mt7615_dfs_pattern { + u8 enb; + u8 stgr; + u8 min_crpn; + u8 max_crpn; + u8 min_crpr; + u8 min_pw; + u8 max_pw; + u32 min_pri; + u32 max_pri; + u8 min_crbn; + u8 max_crbn; + u8 min_stgpn; + u8 max_stgpn; + u8 min_stgpr; +}; + +struct mt7615_dfs_radar_spec { + struct mt7615_dfs_pulse pulse_th; + struct mt7615_dfs_pattern radar_pattern[16]; +}; + enum mt7615_cipher_type { MT_CIPHER_NONE, MT_CIPHER_WEP40, @@ -317,7 +384,7 @@ enum mt7615_cipher_type { MT_CIPHER_GCMP_256, }; -static inline struct mt7615_txp * +static inline struct mt7615_txp_common * mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) { u8 *txwi; @@ -327,7 +394,7 @@ mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) txwi = mt76_get_txwi_ptr(dev, t); - return (struct mt7615_txp *)(txwi + MT_TXD_SIZE); + return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE); } #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 070b03403894..01194ed79869 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -11,27 +11,85 @@ #include #include #include "mt7615.h" +#include "mcu.h" + +static bool mt7615_dev_running(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return true; + + phy = mt7615_ext_phy(dev); + + return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); +} static int mt7615_start(struct ieee80211_hw *hw) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool running; + + if (!mt7615_wait_for_mcu_init(dev)) + return -EIO; + + mutex_lock(&dev->mt76.mutex); + + running = mt7615_dev_running(dev); + + if (!running) { + mt7615_mcu_ctrl_pm_state(dev, 0, 0); + mt7615_mcu_set_mac_enable(dev, 0, true); + mt7615_mac_enable_nf(dev, 0); + } + + if (phy != &dev->phy) { + mt7615_mcu_ctrl_pm_state(dev, 1, 0); + mt7615_mcu_set_mac_enable(dev, 1, true); + mt7615_mac_enable_nf(dev, 1); + } + + mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + if (running) + goto out; mt7615_mac_reset_counters(dev); - dev->mt76.survey_time = ktime_get_boottime(); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); +out: + mutex_unlock(&dev->mt76.mutex); + return 0; } static void mt7615_stop(struct ieee80211_hw *hw) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); - cancel_delayed_work_sync(&dev->mt76.mac_work); + mutex_lock(&dev->mt76.mutex); + + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + if (phy != &dev->phy) { + mt7615_mcu_ctrl_pm_state(dev, 1, 1); + mt7615_mcu_set_mac_enable(dev, 1, false); + } + + if (!mt7615_dev_running(dev)) { + cancel_delayed_work_sync(&dev->mt76.mac_work); + + mt7615_mcu_ctrl_pm_state(dev, 0, 1); + mt7615_mcu_set_mac_enable(dev, 0, false); + } + + mutex_unlock(&dev->mt76.mutex); } static int get_omac_idx(enum nl80211_iftype type, u32 mask) @@ -39,6 +97,7 @@ static int get_omac_idx(enum nl80211_iftype type, u32 mask) int i; switch (type) { + case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: @@ -70,8 +129,10 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt76_txq *mtxq; + bool ext_phy = phy != &dev->phy; int idx, ret = 0; mutex_lock(&dev->mt76.mutex); @@ -89,9 +150,12 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, } mvif->omac_idx = idx; - /* TODO: DBDC support. Use band 0 for now */ - mvif->band_idx = 0; - mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; + mvif->band_idx = ext_phy; + if (mt7615_ext_phy(dev)) + mvif->wmm_idx = ext_phy * (MT7615_MAX_WMM_SETS / 2) + + mvif->idx % (MT7615_MAX_WMM_SETS / 2); + else + mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; ret = mt7615_mcu_set_dev_info(dev, vif, 1); if (ret) @@ -99,18 +163,25 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, dev->vif_mask |= BIT(mvif->idx); dev->omac_mask |= BIT(mvif->omac_idx); + phy->omac_mask |= BIT(mvif->omac_idx); + + mt7615_mcu_set_dbdc(dev); + idx = MT7615_WTBL_RESERVED - mvif->idx; INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; + mvif->sta.wcid.ext_phy = mvif->band_idx; mvif->sta.wcid.hw_key_idx = -1; mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); - mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; - mt76_txq_init(&dev->mt76, vif->txq); + if (vif->txq) { + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mtxq->wcid = &mvif->sta.wcid; + mt76_txq_init(&dev->mt76, vif->txq); + } out: mutex_unlock(&dev->mt76.mutex); @@ -123,7 +194,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = &mvif->sta; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); int idx = msta->wcid.idx; /* TODO: disable beacon for the bss */ @@ -131,11 +203,13 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt7615_mcu_set_dev_info(dev, vif, 0); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - mt76_txq_remove(&dev->mt76, vif->txq); + if (vif->txq) + mt76_txq_remove(&dev->mt76, vif->txq); mutex_lock(&dev->mt76.mutex); dev->vif_mask &= ~BIT(mvif->idx); dev->omac_mask &= ~BIT(mvif->omac_idx); + phy->omac_mask &= ~BIT(mvif->omac_idx); mutex_unlock(&dev->mt76.mutex); spin_lock_bh(&dev->sta_poll_lock); @@ -144,34 +218,38 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, spin_unlock_bh(&dev->sta_poll_lock); } -static int mt7615_set_channel(struct mt7615_dev *dev) +static int mt7615_set_channel(struct mt7615_phy *phy) { + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int ret; cancel_delayed_work_sync(&dev->mt76.mac_work); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &phy->mt76->state); - mt7615_dfs_check_channel(dev); + phy->dfs_state = -1; + mt76_set_channel(phy->mt76); - mt76_set_channel(&dev->mt76); - - ret = mt7615_mcu_set_channel(dev); + ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); if (ret) goto out; - ret = mt7615_dfs_init_radar_detector(dev); - mt7615_mac_cca_stats_reset(dev); - dev->mt76.survey_time = ktime_get_boottime(); + mt7615_mac_set_timing(phy); + ret = mt7615_dfs_init_radar_detector(phy); + mt7615_mac_cca_stats_reset(phy); + mt7615_mcu_set_sku_en(phy, true); mt7615_mac_reset_counters(dev); + phy->noise = 0; + phy->chfreq = mt76_rr(dev, MT_CHFREQ(ext_phy)); out: - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &phy->mt76->state); mutex_unlock(&dev->mt76.mutex); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(phy->mt76); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); return ret; @@ -181,7 +259,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; @@ -230,27 +308,27 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int mt7615_config(struct ieee80211_hw *hw, u32 changed) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool band = phy != &dev->phy; int ret = 0; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | + IEEE80211_CONF_CHANGE_POWER)) { ieee80211_stop_queues(hw); - ret = mt7615_set_channel(dev); + ret = mt7615_set_channel(phy); ieee80211_wake_queues(hw); } mutex_lock(&dev->mt76.mutex); - if (changed & IEEE80211_CONF_CHANGE_POWER) - ret = mt7615_mcu_set_tx_power(dev); - if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) - dev->mt76.rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; else - dev->mt76.rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; - mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); } mutex_unlock(&dev->mt76.mutex); @@ -263,7 +341,7 @@ mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); queue += mvif->wmm_idx * MT7615_MAX_WMM_SETS; @@ -275,7 +353,10 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool band = phy != &dev->phy; + u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | MT_WF_RFCR1_DROP_BF_POLL | MT_WF_RFCR1_DROP_BA | @@ -285,21 +366,21 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, #define MT76_FILTER(_flag, _hw) do { \ flags |= *total_flags & FIF_##_flag; \ - dev->mt76.rxfilter &= ~(_hw); \ - dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + phy->rxfilter &= ~(_hw); \ + phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ } while (0) - dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | - MT_WF_RFCR_DROP_OTHER_BEACON | - MT_WF_RFCR_DROP_FRAME_REPORT | - MT_WF_RFCR_DROP_PROBEREQ | - MT_WF_RFCR_DROP_MCAST_FILTERED | - MT_WF_RFCR_DROP_MCAST | - MT_WF_RFCR_DROP_BCAST | - MT_WF_RFCR_DROP_DUPLICATE | - MT_WF_RFCR_DROP_A2_BSSID | - MT_WF_RFCR_DROP_UNWANTED_CTL | - MT_WF_RFCR_DROP_STBC_MULTI); + phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | MT_WF_RFCR_DROP_A3_MAC | @@ -313,12 +394,12 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_NDPA); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); if (*total_flags & FIF_CONTROL) - mt76_clear(dev, MT_WF_RFCR1, ctl_flags); + mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags); else - mt76_set(dev, MT_WF_RFCR1, ctl_flags); + mt76_set(dev, MT_WF_RFCR1(band), ctl_flags); } static void mt7615_bss_info_changed(struct ieee80211_hw *hw, @@ -326,24 +407,32 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u32 changed) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); mutex_lock(&dev->mt76.mutex); if (changed & BSS_CHANGED_ASSOC) mt7615_mcu_set_bss_info(dev, vif, info->assoc); - /* TODO: update beacon content - * BSS_CHANGED_BEACON - */ + if (changed & BSS_CHANGED_ERP_SLOT) { + int slottime = info->use_short_slot ? 9 : 20; + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + if (slottime != phy->slottime) { + phy->slottime = slottime; + mt7615_mac_set_timing(phy); + } + } if (changed & BSS_CHANGED_BEACON_ENABLED) { mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); - mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); - mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon); - mt7615_mcu_set_bcn(dev, vif, info->enable_beacon); + mt7615_mcu_set_bmc(dev, vif, info->enable_beacon); } + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) + mt7615_mcu_set_bcn(hw, vif, info->enable_beacon); + mutex_unlock(&dev->mt76.mutex); } @@ -352,15 +441,15 @@ mt7615_channel_switch_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7615_mcu_set_bcn(dev, vif, true); + mt7615_mcu_set_bcn(hw, vif, true); mutex_unlock(&dev->mt76.mutex); } -int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -375,33 +464,23 @@ int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; + msta->wcid.ext_phy = mvif->band_idx; + mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - mt7615_mcu_add_wtbl(dev, vif, sta); - mt7615_mcu_set_sta_rec(dev, vif, sta, 1); + mt7615_mcu_set_sta(dev, vif, sta, 1); return 0; } -void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - - if (sta->ht_cap.ht_supported) - mt7615_mcu_set_ht_cap(dev, vif, sta); -} - -void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - mt7615_mcu_set_sta_rec(dev, vif, sta, 0); - mt7615_mcu_del_wtbl(dev, sta); - + mt7615_mcu_set_sta(dev, vif, sta, 0); mt7615_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -415,7 +494,8 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); int i; @@ -430,7 +510,7 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, break; } msta->n_rates = i; - mt7615_mac_set_rates(dev, msta, NULL, msta->rates); + mt7615_mac_set_rates(phy, msta, NULL, msta->rates); msta->rate_probe = false; spin_unlock_bh(&dev->mt76.lock); } @@ -439,7 +519,8 @@ static void mt7615_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct mt76_wcid *wcid = &dev->mt76.global_wcid; @@ -458,15 +539,16 @@ static void mt7615_tx(struct ieee80211_hw *hw, wcid = &mvif->sta.wcid; } - mt76_tx(&dev->mt76, control->sta, wcid, skb); + mt76_tx(mphy, control->sta, wcid, skb); } static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); mutex_lock(&dev->mt76.mutex); - mt7615_mcu_set_rts_thresh(dev, val); + mt7615_mcu_set_rts_thresh(phy, val); mutex_unlock(&dev->mt76.mutex); return 0; @@ -477,7 +559,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) { enum ieee80211_ampdu_mlme_action action = params->action; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -527,6 +609,92 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return ret; } +static int +mt7615_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, + IEEE80211_STA_NONE); +} + +static int +mt7615_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, + IEEE80211_STA_NOTEXIST); +} + +static int +mt7615_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + struct mib_stats *mib = &phy->mib; + + stats->dot11RTSSuccessCount = mib->rts_cnt; + stats->dot11RTSFailureCount = mib->rts_retries_cnt; + stats->dot11FCSErrorCount = mib->fcs_err_cnt; + stats->dot11ACKFailureCount = mib->ack_fail_cnt; + + return 0; +} + +static u64 +mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + union { + u64 t64; + u32 t32[2]; + } tsf; + + mutex_lock(&dev->mt76.mutex); + + mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0); + tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1); + + mutex_unlock(&dev->mt76.mutex); + + return tsf.t64; +} + +static void +mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + phy->coverage_class = max_t(s16, coverage_class, 0); + mt7615_mac_set_timing(phy); +} + +static int +mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + int max_nss = hweight8(hw->wiphy->available_antennas_tx); + bool ext_phy = phy != &dev->phy; + + if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) + return -EINVAL; + + if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) + tx_ant = BIT(ffs(tx_ant) - 1) - 1; + + mutex_lock(&dev->mt76.mutex); + + phy->mt76->antenna_mask = tx_ant; + phy->chainmask = ext_phy ? tx_ant << 2 : tx_ant; + + mt76_set_stream_caps(&dev->mt76, true); + + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + const struct ieee80211_ops mt7615_ops = { .tx = mt7615_tx, .start = mt7615_start, @@ -537,7 +705,9 @@ const struct ieee80211_ops mt7615_ops = { .conf_tx = mt7615_conf_tx, .configure_filter = mt7615_configure_filter, .bss_info_changed = mt7615_bss_info_changed, - .sta_state = mt76_sta_state, + .sta_add = mt7615_sta_add, + .sta_remove = mt7615_sta_remove, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7615_set_key, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, @@ -548,6 +718,38 @@ const struct ieee80211_ops mt7615_ops = { .release_buffered_frames = mt76_release_buffered_frames, .get_txpower = mt76_get_txpower, .channel_switch_beacon = mt7615_channel_switch_beacon, + .get_stats = mt7615_get_stats, + .get_tsf = mt7615_get_tsf, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, + .set_antenna = mt7615_set_antenna, + .set_coverage_class = mt7615_set_coverage_class, }; + +static int __init mt7615_init(void) +{ + int ret; + + ret = pci_register_driver(&mt7615_pci_driver); + if (ret) + return ret; + + if (IS_ENABLED(CONFIG_MT7622_WMAC)) { + ret = platform_driver_register(&mt7622_wmac_driver); + if (ret) + pci_unregister_driver(&mt7615_pci_driver); + } + + return ret; +} + +static void __exit mt7615_exit(void) +{ + if (IS_ENABLED(CONFIG_MT7622_WMAC)) + platform_driver_unregister(&mt7622_wmac_driver); + pci_unregister_driver(&mt7615_pci_driver); +} + +module_init(mt7615_init); +module_exit(mt7615_exit); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index f229c9ce9f65..7218a3041ead 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -29,7 +29,8 @@ struct mt7615_fw_trailer { __le32 len; } __packed; -#define MCU_PATCH_ADDRESS 0x80000 +#define MT7615_PATCH_ADDRESS 0x80000 +#define MT7622_PATCH_ADDRESS 0x9c000 #define N9_REGION_NUM 2 #define CR4_REGION_NUM 1 @@ -57,9 +58,9 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, u32 val; __le32 *txd; - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + seq = ++dev->mt76.mcu.msg_seq & 0xf; if (!seq) - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + seq = ++dev->mt76.mcu.msg_seq & 0xf; mcu_txd = (struct mt7615_mcu_txd *)skb_push(skb, sizeof(struct mt7615_mcu_txd)); @@ -104,7 +105,7 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, if (wait_seq) *wait_seq = seq; - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) qid = MT_TXQ_MCU; else qid = MT_TXQ_FWDL; @@ -144,7 +145,7 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int len, bool wait_resp) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - unsigned long expires = jiffies + 10 * HZ; + unsigned long expires = jiffies + 20 * HZ; struct sk_buff *skb; int ret, seq; @@ -152,7 +153,7 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&mdev->mmio.mcu.mutex); + mutex_lock(&mdev->mcu.mutex); ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); if (ret) @@ -173,7 +174,7 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, } out: - mutex_unlock(&mdev->mmio.mcu.mutex); + mutex_unlock(&mdev->mcu.mutex); return ret; } @@ -185,6 +186,43 @@ mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) ieee80211_csa_finish(vif); } +static void +mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_mcu_rdd_report *r; + + r = (struct mt7615_mcu_rdd_report *)skb->data; + + if (r->idx && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + ieee80211_radar_detected(mphy->hw); + dev->hw_pattern++; +} + +static void +mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data; + const char *data = (char *)&rxd[1]; + const char *type; + + switch (rxd->s2d_index) { + case 0: + type = "N9"; + break; + case 2: + type = "CR4"; + break; + default: + type = "unknown"; + break; + } + + wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data); +} + static void mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) { @@ -192,14 +230,16 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) switch (rxd->ext_eid) { case MCU_EXT_EVENT_RDD_REPORT: - ieee80211_radar_detected(dev->mt76.hw); - dev->hw_pattern++; + 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); break; + case MCU_EXT_EVENT_FW_LOG_2_HOST: + mt7615_mcu_rx_log_message(dev, skb); + break; default: break; } @@ -319,19 +359,50 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) &req, sizeof(req), true); } +static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) +{ + if (!is_mt7622(&dev->mt76)) + return; + + regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC, + MT_INFRACFG_MISC_AP2CONN_WAKE, + !en * MT_INFRACFG_MISC_AP2CONN_WAKE); +} + static int mt7615_driver_own(struct mt7615_dev *dev) { mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_DRV_OWN); + + mt7622_trigger_hif_int(dev, true); if (!mt76_poll_msec(dev, MT_CFG_LPCR_HOST, - MT_CFG_LPCR_HOST_FW_OWN, 0, 500)) { + MT_CFG_LPCR_HOST_FW_OWN, 0, 3000)) { dev_err(dev->mt76.dev, "Timeout for driver own\n"); return -EIO; } + mt7622_trigger_hif_int(dev, false); return 0; } -static int mt7615_load_patch(struct mt7615_dev *dev) +static int mt7615_firmware_own(struct mt7615_dev *dev) +{ + mt7622_trigger_hif_int(dev, true); + + mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); + + if (is_mt7622(&dev->mt76) && + !mt76_poll_msec(dev, MT_CFG_LPCR_HOST, + MT_CFG_LPCR_HOST_FW_OWN, + MT_CFG_LPCR_HOST_FW_OWN, 3000)) { + dev_err(dev->mt76.dev, "Timeout for firmware own\n"); + return -EIO; + } + mt7622_trigger_hif_int(dev, false); + + return 0; +} + +static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) { const struct mt7615_patch_hdr *hdr; const struct firmware *fw = NULL; @@ -348,7 +419,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev) return -EAGAIN; } - ret = request_firmware(&fw, MT7615_ROM_PATCH, dev->mt76.dev); + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) goto out; @@ -365,8 +436,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev) len = fw->size - sizeof(*hdr); - ret = mt7615_mcu_init_download(dev, MCU_PATCH_ADDRESS, len, - DL_MODE_NEED_RSP); + ret = mt7615_mcu_init_download(dev, addr, len, DL_MODE_NEED_RSP); if (ret) { dev_err(dev->mt76.dev, "Download request failed\n"); goto out; @@ -444,13 +514,13 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev, return 0; } -static int mt7615_load_ram(struct mt7615_dev *dev) +static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) { const struct mt7615_fw_trailer *hdr; const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7615_FIRMWARE_N9, dev->mt76.dev); + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) return ret; @@ -477,9 +547,27 @@ static int mt7615_load_ram(struct mt7615_dev *dev) goto out; } - release_firmware(fw); + snprintf(dev->mt76.hw->wiphy->fw_version, + sizeof(dev->mt76.hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); - ret = request_firmware(&fw, MT7615_FIRMWARE_CR4, dev->mt76.dev); + if (!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) + dev->fw_ver = MT7615_FIRMWARE_V2; + else + dev->fw_ver = MT7615_FIRMWARE_V1; + +out: + release_firmware(fw); + return ret; +} + +static int mt7615_load_cr4(struct mt7615_dev *dev, const char *name) +{ + const struct mt7615_fw_trailer *hdr; + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) return ret; @@ -500,8 +588,10 @@ static int mt7615_load_ram(struct mt7615_dev *dev) goto out; ret = mt7615_mcu_start_firmware(dev, 0, FW_START_WORKING_PDA_CR4); - if (ret) + if (ret) { dev_err(dev->mt76.dev, "Failed to start CR4 firmware\n"); + goto out; + } out: release_firmware(fw); @@ -509,6 +599,17 @@ static int mt7615_load_ram(struct mt7615_dev *dev) return ret; } +static int mt7615_load_ram(struct mt7615_dev *dev) +{ + int ret; + + ret = mt7615_load_n9(dev, MT7615_FIRMWARE_N9); + if (ret) + return ret; + + return mt7615_load_cr4(dev, MT7615_FIRMWARE_CR4); +} + static int mt7615_load_firmware(struct mt7615_dev *dev) { int ret; @@ -521,7 +622,7 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) return -EIO; } - ret = mt7615_load_patch(dev); + ret = mt7615_load_patch(dev, MT7615_PATCH_ADDRESS, MT7615_ROM_PATCH); if (ret) return ret; @@ -536,13 +637,55 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) return -EIO; } - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + return 0; +} - dev_dbg(dev->mt76.dev, "Firmware init done\n"); +static int mt7622_load_firmware(struct mt7615_dev *dev) +{ + int ret; + u32 val; + + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); + + val = mt76_get_field(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE); + if (val != FW_STATE_FW_DOWNLOAD) { + dev_err(dev->mt76.dev, "Firmware is not ready for download\n"); + return -EIO; + } + + ret = mt7615_load_patch(dev, MT7622_PATCH_ADDRESS, MT7622_ROM_PATCH); + if (ret) + return ret; + + ret = mt7615_load_n9(dev, MT7622_FIRMWARE_N9); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE, + FIELD_PREP(MT_TOP_OFF_RSV_FW_STATE, + FW_STATE_NORMAL_TRX), 1500)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + + mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); return 0; } +int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl) +{ + struct { + u8 ctrl_val; + u8 pad[3]; + } data = { + .ctrl_val = ctrl + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, + &data, sizeof(data), true); +} + int mt7615_mcu_init(struct mt7615_dev *dev) { static const struct mt76_mcu_ops mt7615_mcu_ops = { @@ -557,11 +700,17 @@ int mt7615_mcu_init(struct mt7615_dev *dev) if (ret) return ret; - ret = mt7615_load_firmware(dev); + if (is_mt7622(&dev->mt76)) + ret = mt7622_load_firmware(dev); + else + ret = mt7615_load_firmware(dev); if (ret) return ret; - set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + mt7615_mcu_fw_log_2_host(dev, 0); return 0; } @@ -569,8 +718,8 @@ int mt7615_mcu_init(struct mt7615_dev *dev) void mt7615_mcu_exit(struct mt7615_dev *dev) { __mt76_mcu_restart(&dev->mt76); - mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); - skb_queue_purge(&dev->mt76.mmio.mcu.res_q); + mt7615_firmware_own(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); } int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) @@ -578,21 +727,26 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) struct { u8 buffer_mode; u8 pad; - u16 len; + __le16 len; } __packed req_hdr = { .buffer_mode = 1, - .len = __MT_EE_MAX - MT_EE_NIC_CONF_0, }; - int ret, len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; + int ret, len, eep_len; u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; + if (is_mt7622(&dev->mt76)) + eep_len = MT7622_EE_MAX - MT_EE_NIC_CONF_0; + else + eep_len = MT7615_EE_MAX - MT_EE_NIC_CONF_0; + + len = sizeof(req_hdr) + eep_len; req = kzalloc(len, GFP_KERNEL); if (!req) return -ENOMEM; + req_hdr.len = cpu_to_le16(eep_len); memcpy(req, &req_hdr, sizeof(req_hdr)); - memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, - __MT_EE_MAX - MT_EE_NIC_CONF_0); + memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, eep_len); ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, req, len, true); @@ -601,23 +755,24 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) return ret; } -int mt7615_mcu_init_mac(struct mt7615_dev *dev) +int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable) { struct { u8 enable; u8 band; u8 rsv[2]; } __packed req = { - .enable = 1, - .band = 0, + .enable = enable, + .band = band, }; return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, &req, sizeof(req), true); } -int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) +int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val) { + struct mt7615_dev *dev = phy->dev; struct { u8 prot_idx; u8 band; @@ -626,7 +781,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) __le32 pkt_thresh; } __packed req = { .prot_idx = 1, - .band = 0, + .band = phy != &dev->phy, .len_thresh = cpu_to_le32(val), .pkt_thresh = cpu_to_le32(0x2), }; @@ -672,7 +827,7 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, &req, sizeof(req), true); } -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) +int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter) { #define ENTER_PM_STATE 1 #define EXIT_PM_STATE 2 @@ -695,13 +850,72 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) } __packed req = { .pm_number = 5, .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, - .band_idx = 0, + .band_idx = band, }; return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, sizeof(req), true); } +int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) +{ + struct mt7615_phy *ext_phy = mt7615_ext_phy(dev); + struct dbdc_entry { + u8 type; + u8 index; + u8 band; + u8 _rsv; + }; + struct { + u8 enable; + u8 num; + u8 _rsv[2]; + struct dbdc_entry entry[64]; + } req = { + .enable = !!ext_phy, + }; + int i; + + if (!ext_phy) + goto out; + +#define ADD_DBDC_ENTRY(_type, _idx, _band) \ + do { \ + req.entry[req.num].type = _type; \ + req.entry[req.num].index = _idx; \ + req.entry[req.num++].band = _band; \ + } while (0) + + for (i = 0; i < 4; i++) { + bool band = !!(ext_phy->omac_mask & BIT(i)); + + ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band); + } + + for (i = 0; i < 14; i++) { + bool band = !!(ext_phy->omac_mask & BIT(0x11 + i)); + + ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band); + } + + ADD_DBDC_ENTRY(DBDC_TYPE_MU, 0, 1); + + for (i = 0; i < 3; i++) + ADD_DBDC_ENTRY(DBDC_TYPE_BF, i, 1); + + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 0, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 1, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 2, 1); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 3, 1); + + ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 0, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1); + +out: + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, + &req, sizeof(req), true); +} + int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable) { @@ -898,106 +1112,6 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, return ret; } -static int -mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, - struct mt7615_vif *mvif) -{ - struct { - struct wtbl_req_hdr hdr; - struct wtbl_generic g_wtbl; - struct wtbl_rx rx_wtbl; - } req = { - .hdr = { - .wlan_idx = mvif->sta.wcid.idx, - .operation = WTBL_RESET_AND_SET, - .tlv_num = cpu_to_le16(2), - }, - .g_wtbl = { - .tag = cpu_to_le16(WTBL_GENERIC), - .len = cpu_to_le16(sizeof(struct wtbl_generic)), - .muar_idx = 0xe, - }, - .rx_wtbl = { - .tag = cpu_to_le16(WTBL_RX), - .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = 1, - .rca2 = 1, - .rv = 1, - }, - }; - eth_broadcast_addr(req.g_wtbl.peer_addr); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} - -int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - - if (!enable) { - struct wtbl_req_hdr req = { - .wlan_idx = mvif->sta.wcid.idx, - .operation = WTBL_RESET_AND_SET, - }; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); - } - - return mt7615_mcu_add_wtbl_bmc(dev, mvif); -} - -int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_generic g_wtbl; - struct wtbl_rx rx_wtbl; - } req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_RESET_AND_SET, - .tlv_num = cpu_to_le16(2), - }, - .g_wtbl = { - .tag = cpu_to_le16(WTBL_GENERIC), - .len = cpu_to_le16(sizeof(struct wtbl_generic)), - .muar_idx = mvif->omac_idx, - .qos = sta->wme, - .partial_aid = cpu_to_le16(sta->aid), - }, - .rx_wtbl = { - .tag = cpu_to_le16(WTBL_RX), - .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = vif->type != NL80211_IFTYPE_AP, - .rca2 = 1, - .rv = 1, - }, - }; - memcpy(req.g_wtbl.peer_addr, sta->addr, ETH_ALEN); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} - -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, - struct ieee80211_sta *sta) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct wtbl_req_hdr req = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_RESET_AND_SET, - }; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} - int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) { struct wtbl_req_hdr req = { @@ -1008,14 +1122,45 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) &req, sizeof(req), true); } -int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool en) +static int +mt7615_mcu_send_sta_rec(struct mt7615_dev *dev, u8 *req, u8 *wreq, + u8 wlen, bool enable) +{ + bool is_v1 = (dev->fw_ver == MT7615_FIRMWARE_V1); + u32 slen = is_v1 ? wreq - req : wreq - req + wlen; + int ret; + + if (is_v1 && !enable) { + ret = __mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_STA_REC_UPDATE, + req, slen, true); + if (ret) + return ret; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + wreq, wlen, true); + } + + if (is_v1) { + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + wreq, wlen, true); + if (ret) + return ret; + } + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + req, slen, true); +} + +int mt7615_mcu_set_bmc(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct { struct sta_req_hdr hdr; struct sta_rec_basic basic; - } req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = mvif->sta.wcid.idx, @@ -1029,8 +1174,26 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, .conn_type = cpu_to_le32(CONNECTION_INFRA_BC), }, }; + struct sta_rec_wtbl *wtbl = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_generic *wtbl_g; + struct wtbl_rx *wtbl_rx; + u8 *buf = req.buf; + eth_broadcast_addr(req.basic.peer_addr); + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + req.hdr.tlv_num = cpu_to_le16(2); + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + } + + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = mvif->sta.wcid.idx; + wtbl_hdr->operation = WTBL_RESET_AND_SET; + if (en) { req.basic.conn_state = CONN_STATE_PORT_SECURE; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | @@ -1038,14 +1201,36 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, } else { req.basic.conn_state = CONN_STATE_DISCONNECT; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + goto out; } - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, sizeof(req), true); + wtbl_g = (struct wtbl_generic *)buf; + buf += sizeof(*wtbl_g); + wtbl_g->tag = cpu_to_le16(WTBL_GENERIC); + wtbl_g->len = cpu_to_le16(sizeof(*wtbl_g)); + wtbl_g->muar_idx = 0xe; + eth_broadcast_addr(wtbl_g->peer_addr); + + wtbl_rx = (struct wtbl_rx *)buf; + buf += sizeof(*wtbl_rx); + wtbl_rx->tag = cpu_to_le16(WTBL_RX); + wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); + wtbl_rx->rv = 1; + wtbl_rx->rca1 = 1; + wtbl_rx->rca2 = 1; + + wtbl_hdr->tlv_num = cpu_to_le16(2); + +out: + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); + + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, en); } -int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en) +int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -1053,11 +1238,11 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct { struct sta_req_hdr hdr; struct sta_rec_basic basic; - } req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = msta->wcid.idx, - .tlv_num = cpu_to_le16(1), .is_tlv_append = 1, .muar_idx = mvif->omac_idx, }, @@ -1068,6 +1253,13 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, .aid = cpu_to_le16(sta->aid), }, }; + struct sta_rec_wtbl *wtbl = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_generic *wtbl_g; + struct wtbl_rx *wtbl_rx; + u8 *buf = req.buf; + u8 wtlv = 0, stlv = 1; + memcpy(req.basic.peer_addr, sta->addr, ETH_ALEN); switch (vif->type) { @@ -1090,21 +1282,161 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, req.basic.conn_state = CONN_STATE_PORT_SECURE; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + + /* sta_rec ht */ + if (sta->ht_cap.ht_supported) { + struct sta_rec_ht *sta_ht; + + sta_ht = (struct sta_rec_ht *)buf; + buf += sizeof(*sta_ht); + sta_ht->tag = cpu_to_le16(STA_REC_HT); + sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); + sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + stlv++; + + /* sta_rec vht */ + if (sta->vht_cap.vht_supported) { + struct sta_rec_vht *sta_vht; + + sta_vht = (struct sta_rec_vht *)buf; + buf += sizeof(*sta_vht); + sta_vht->tag = cpu_to_le16(STA_REC_VHT); + sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); + sta_vht->vht_cap = + cpu_to_le32(sta->vht_cap.cap); + sta_vht->vht_rx_mcs_map = + sta->vht_cap.vht_mcs.rx_mcs_map; + sta_vht->vht_tx_mcs_map = + sta->vht_cap.vht_mcs.tx_mcs_map; + stlv++; + } + } } else { req.basic.conn_state = CONN_STATE_DISCONNECT; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); } - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, sizeof(req), true); + /* wtbl */ + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + stlv++; + } + + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_RESET_AND_SET; + + if (!en) + goto out; + + wtbl_g = (struct wtbl_generic *)buf; + buf += sizeof(*wtbl_g); + wtbl_g->tag = cpu_to_le16(WTBL_GENERIC); + wtbl_g->len = cpu_to_le16(sizeof(*wtbl_g)); + wtbl_g->muar_idx = mvif->omac_idx; + wtbl_g->qos = sta->wme; + wtbl_g->partial_aid = cpu_to_le16(sta->aid); + memcpy(wtbl_g->peer_addr, sta->addr, ETH_ALEN); + wtlv++; + + wtbl_rx = (struct wtbl_rx *)buf; + buf += sizeof(*wtbl_rx); + wtbl_rx->tag = cpu_to_le16(WTBL_RX); + wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); + wtbl_rx->rv = 1; + wtbl_rx->rca1 = vif->type != NL80211_IFTYPE_AP; + wtbl_rx->rca2 = 1; + wtlv++; + + /* wtbl ht */ + if (sta->ht_cap.ht_supported) { + struct wtbl_ht *wtbl_ht; + struct wtbl_raw *wtbl_raw; + u32 val = 0, msk; + + wtbl_ht = (struct wtbl_ht *)buf; + buf += sizeof(*wtbl_ht); + wtbl_ht->tag = cpu_to_le16(WTBL_HT); + wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); + wtbl_ht->ht = 1; + wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + wtbl_ht->af = sta->ht_cap.ampdu_factor; + wtbl_ht->mm = sta->ht_cap.ampdu_density; + wtlv++; + + /* wtbl vht */ + if (sta->vht_cap.vht_supported) { + struct wtbl_vht *wtbl_vht; + + wtbl_vht = (struct wtbl_vht *)buf; + buf += sizeof(*wtbl_vht); + wtbl_vht->tag = cpu_to_le16(WTBL_VHT); + wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); + wtbl_vht->vht = 1; + wtbl_vht->ldpc = sta->vht_cap.cap & + IEEE80211_VHT_CAP_RXLDPC; + wtlv++; + + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + val |= MT_WTBL_W5_SHORT_GI_80; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + val |= MT_WTBL_W5_SHORT_GI_160; + } + + /* wtbl smps */ + if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { + struct wtbl_smps *wtbl_smps; + + wtbl_smps = (struct wtbl_smps *)buf; + buf += sizeof(*wtbl_smps); + wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); + wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); + wtbl_smps->smps = 1; + wtlv++; + } + + /* sgi */ + msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | + MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; + + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + val |= MT_WTBL_W5_SHORT_GI_20; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + val |= MT_WTBL_W5_SHORT_GI_40; + + wtbl_raw = (struct wtbl_raw *)buf; + buf += sizeof(*wtbl_raw); + wtbl_raw->tag = cpu_to_le16(WTBL_RAW_DATA); + wtbl_raw->len = cpu_to_le16(sizeof(*wtbl_raw)); + wtbl_raw->wtbl_idx = 1; + wtbl_raw->dw = 5; + wtbl_raw->msk = cpu_to_le32(~msk); + wtbl_raw->val = cpu_to_le32(val); + wtlv++; + } + +out: + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); + + wtbl_hdr->tlv_num = cpu_to_le16(wtlv); + req.hdr.tlv_num = cpu_to_le16(stlv); + + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, en); } -int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, +int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en) { + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt76_wcid *wcid = &dev->mt76.global_wcid; struct ieee80211_mutable_offsets offs; + struct ieee80211_tx_info *info; struct req { u8 omac_idx; u8 enable; @@ -1128,7 +1460,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, }; struct sk_buff *skb; - skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); + skb = ieee80211_beacon_get_template(hw, vif, &offs); if (!skb) return -EINVAL; @@ -1138,6 +1470,11 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, return -EINVAL; } + if (mvif->band_idx) { + info = IEEE80211_SKB_CB(skb); + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + } + mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, 0, NULL); memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); @@ -1156,72 +1493,6 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, &req, sizeof(req), true); } -int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) -{ - int i, ret, n_chains = hweight8(dev->mt76.antenna_mask); - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; - int freq = chandef->center_freq1, len, target_chains; - u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; - enum nl80211_band band = chandef->chan->band; - struct ieee80211_hw *hw = mt76_hw(dev); - struct { - u8 center_chan; - u8 dbdc_idx; - u8 band; - u8 rsv; - } __packed req_hdr = { - .center_chan = ieee80211_frequency_to_channel(freq), - .band = band, - }; - s8 tx_power; - - len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; - req = kzalloc(len, GFP_KERNEL); - if (!req) - return -ENOMEM; - - memcpy(req, &req_hdr, sizeof(req_hdr)); - data = req + sizeof(req_hdr); - memcpy(data, eep + MT_EE_NIC_CONF_0, - __MT_EE_MAX - MT_EE_NIC_CONF_0); - - tx_power = hw->conf.power_level * 2; - switch (n_chains) { - case 4: - tx_power -= 12; - break; - case 3: - tx_power -= 8; - break; - case 2: - tx_power -= 6; - break; - default: - break; - } - tx_power = max_t(s8, tx_power, 0); - dev->mt76.txpower_cur = tx_power; - - target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; - for (i = 0; i < target_chains; i++) { - int index = -MT_EE_NIC_CONF_0; - - ret = mt7615_eeprom_get_power_index(dev, chandef->chan, i); - if (ret < 0) - goto out; - - index += ret; - data[index] = min_t(u8, data[index], tx_power); - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, - req, len, true); -out: - kfree(req); - - return ret; -} - int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val) @@ -1243,6 +1514,54 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, &req, sizeof(req), true); } +int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val) +{ + struct { + u16 tag; + u16 min_lpn; + } req = { + .tag = 0x1, + .min_lpn = val, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + +int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, + const struct mt7615_dfs_pulse *pulse) +{ + struct { + u16 tag; + struct mt7615_dfs_pulse pulse; + } req = { + .tag = 0x3, + }; + + memcpy(&req.pulse, pulse, sizeof(*pulse)); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + +int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, + const struct mt7615_dfs_pattern *pattern) +{ + struct { + u16 tag; + u16 radar_type; + struct mt7615_dfs_pattern pattern; + } req = { + .tag = 0x2, + .radar_type = index, + }; + + memcpy(&req.pattern, pattern, sizeof(*pattern)); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) { struct { @@ -1274,9 +1593,35 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) &req, sizeof(req), false); } -int mt7615_mcu_set_channel(struct mt7615_dev *dev) +static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct mt76_phy *mphy = phy->mt76; + struct ieee80211_hw *hw = mphy->hw; + int n_chains = hweight8(mphy->antenna_mask); + int tx_power; + int i; + + tx_power = hw->conf.power_level * 2 - + mt76_tx_power_nss_delta(n_chains); + mphy->txpower_cur = tx_power; + + for (i = 0; i < MT_SKU_1SS_DELTA; i++) + sku[i] = tx_power; + + for (i = 0; i < 4; i++) { + int delta = 0; + + if (i < n_chains - 1) + delta = mt76_tx_power_nss_delta(n_chains) - + mt76_tx_power_nss_delta(i + 1); + sku[MT_SKU_1SS_DELTA + i] = delta; + } +} + +int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) +{ + struct mt7615_dev *dev = phy->dev; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; struct { u8 control_chan; @@ -1299,11 +1644,10 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) } req = { .control_chan = chandef->chan->hw_value, .center_chan = ieee80211_frequency_to_channel(freq1), - .tx_streams = (dev->mt76.chainmask >> 8) & 0xf, - .rx_streams_mask = dev->mt76.antenna_mask, + .tx_streams = hweight8(phy->mt76->antenna_mask), + .rx_streams_mask = phy->chainmask, .center_chan2 = ieee80211_frequency_to_channel(freq2), }; - int ret; if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; @@ -1313,7 +1657,9 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) else req.switch_reason = CH_SWITCH_NORMAL; - switch (dev->mt76.chandef.width) { + req.band_idx = phy != &dev->phy; + + switch (chandef->width) { case NL80211_CHAN_WIDTH_40: req.bw = CMD_CBW_40MHZ; break; @@ -1338,139 +1684,10 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) req.bw = CMD_CBW_20MHZ; break; } - memset(req.txpower_sku, 0x3f, 49); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, - &req, sizeof(req), true); - if (ret) - return ret; + mt7615_mcu_set_txpower_sku(phy, req.txpower_sku); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RX_PATH, - &req, sizeof(req), true); -} - -int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct wtbl_req_hdr *wtbl_hdr; - struct sta_req_hdr *sta_hdr; - struct wtbl_raw *wtbl_raw; - struct sta_rec_ht *sta_ht; - struct wtbl_ht *wtbl_ht; - int buf_len, ret, ntlv = 2; - u32 msk, val = 0; - u8 *buf; - - buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wtbl_hdr = (struct wtbl_req_hdr *)buf; - wtbl_hdr->wlan_idx = msta->wcid.idx; - wtbl_hdr->operation = WTBL_SET; - buf_len = sizeof(*wtbl_hdr); - - /* ht basic */ - wtbl_ht = (struct wtbl_ht *)(buf + buf_len); - wtbl_ht->tag = cpu_to_le16(WTBL_HT); - wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); - wtbl_ht->ht = 1; - wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; - wtbl_ht->af = sta->ht_cap.ampdu_factor; - wtbl_ht->mm = sta->ht_cap.ampdu_density; - buf_len += sizeof(*wtbl_ht); - - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) - val |= MT_WTBL_W5_SHORT_GI_20; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) - val |= MT_WTBL_W5_SHORT_GI_40; - - /* vht basic */ - if (sta->vht_cap.vht_supported) { - struct wtbl_vht *wtbl_vht; - - wtbl_vht = (struct wtbl_vht *)(buf + buf_len); - buf_len += sizeof(*wtbl_vht); - wtbl_vht->tag = cpu_to_le16(WTBL_VHT); - wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); - wtbl_vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC; - wtbl_vht->vht = 1; - ntlv++; - - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) - val |= MT_WTBL_W5_SHORT_GI_80; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) - val |= MT_WTBL_W5_SHORT_GI_160; - } - - /* smps */ - if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { - struct wtbl_smps *wtbl_smps; - - wtbl_smps = (struct wtbl_smps *)(buf + buf_len); - buf_len += sizeof(*wtbl_smps); - wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); - wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); - wtbl_smps->smps = 1; - ntlv++; - } - - /* sgi */ - msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | - MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; - - wtbl_raw = (struct wtbl_raw *)(buf + buf_len); - buf_len += sizeof(*wtbl_raw); - wtbl_raw->tag = cpu_to_le16(WTBL_RAW_DATA); - wtbl_raw->len = cpu_to_le16(sizeof(*wtbl_raw)); - wtbl_raw->wtbl_idx = 1; - wtbl_raw->dw = 5; - wtbl_raw->msk = cpu_to_le32(~msk); - wtbl_raw->val = cpu_to_le32(val); - - wtbl_hdr->tlv_num = cpu_to_le16(ntlv); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - buf, buf_len, true); - if (ret) - goto out; - - memset(buf, 0, MT7615_WTBL_UPDATE_MAX_SIZE); - - sta_hdr = (struct sta_req_hdr *)buf; - sta_hdr->bss_idx = mvif->idx; - sta_hdr->wlan_idx = msta->wcid.idx; - sta_hdr->is_tlv_append = 1; - ntlv = sta->vht_cap.vht_supported ? 2 : 1; - sta_hdr->tlv_num = cpu_to_le16(ntlv); - sta_hdr->muar_idx = mvif->omac_idx; - buf_len = sizeof(*sta_hdr); - - sta_ht = (struct sta_rec_ht *)(buf + buf_len); - sta_ht->tag = cpu_to_le16(STA_REC_HT); - sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); - sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); - buf_len += sizeof(*sta_ht); - - if (sta->vht_cap.vht_supported) { - struct sta_rec_vht *sta_vht; - - sta_vht = (struct sta_rec_vht *)(buf + buf_len); - buf_len += sizeof(*sta_vht); - sta_vht->tag = cpu_to_le16(STA_REC_VHT); - sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); - sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - sta_vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; - sta_vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - buf, buf_len, true); -out: - kfree(buf); - - return ret; + return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, @@ -1479,28 +1696,11 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, { struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_ba ba; - } wtbl_req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_SET, - .tlv_num = cpu_to_le16(1), - }, - .ba = { - .tag = cpu_to_le16(WTBL_BA), - .len = cpu_to_le16(sizeof(struct wtbl_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_ORIGINATOR, - .sn = add ? cpu_to_le16(params->ssn) : 0, - .ba_en = add, - }, - }; struct { struct sta_req_hdr hdr; struct sta_rec_ba ba; - } sta_req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = msta->wcid.idx, @@ -1519,7 +1719,32 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, .winsize = cpu_to_le16(params->buf_size), }, }; - int ret; + struct sta_rec_wtbl *wtbl = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_ba *wtbl_ba; + u8 *buf = req.buf; + + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + req.hdr.tlv_num = cpu_to_le16(2); + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + } + + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_SET; + wtbl_hdr->tlv_num = cpu_to_le16(1); + + wtbl_ba = (struct wtbl_ba *)buf; + buf += sizeof(*wtbl_ba); + wtbl_ba->tag = cpu_to_le16(WTBL_BA); + wtbl_ba->len = cpu_to_le16(sizeof(*wtbl_ba)); + wtbl_ba->tid = params->tid; + wtbl_ba->ba_type = MT_BA_TYPE_ORIGINATOR; + wtbl_ba->sn = add ? cpu_to_le16(params->ssn) : 0; + wtbl_ba->ba_en = add; if (add) { u8 idx, ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; @@ -1529,16 +1754,14 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, break; } - wtbl_req.ba.ba_winsize_idx = idx; + wtbl_ba->ba_winsize_idx = idx; } - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &wtbl_req, sizeof(wtbl_req), true); - if (ret) - return ret; + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &sta_req, sizeof(sta_req), true); + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, true); } int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, @@ -1547,29 +1770,11 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, { struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_ba ba; - } wtbl_req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_SET, - .tlv_num = cpu_to_le16(1), - }, - .ba = { - .tag = cpu_to_le16(WTBL_BA), - .len = cpu_to_le16(sizeof(struct wtbl_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_RECIPIENT, - .rst_ba_tid = params->tid, - .rst_ba_sel = RST_BA_MAC_TID_MATCH, - .rst_ba_sb = 1, - }, - }; struct { struct sta_req_hdr hdr; struct sta_rec_ba ba; - } sta_req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = msta->wcid.idx, @@ -1588,17 +1793,41 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, .winsize = cpu_to_le16(params->buf_size), }, }; - int ret; + struct sta_rec_wtbl *wtbl = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_ba *wtbl_ba; + u8 *buf = req.buf; - memcpy(wtbl_req.ba.peer_addr, params->sta->addr, ETH_ALEN); + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + req.hdr.tlv_num = cpu_to_le16(2); + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + } - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &sta_req, sizeof(sta_req), true); - if (ret || !add) - return ret; + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_SET; + wtbl_hdr->tlv_num = cpu_to_le16(1); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &wtbl_req, sizeof(wtbl_req), true); + wtbl_ba = (struct wtbl_ba *)buf; + buf += sizeof(*wtbl_ba); + wtbl_ba->tag = cpu_to_le16(WTBL_BA); + wtbl_ba->len = cpu_to_le16(sizeof(*wtbl_ba)); + wtbl_ba->tid = params->tid; + wtbl_ba->ba_type = MT_BA_TYPE_RECIPIENT; + wtbl_ba->rst_ba_tid = params->tid; + wtbl_ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; + wtbl_ba->rst_ba_sb = 1; + + memcpy(wtbl_ba->peer_addr, params->sta->addr, ETH_ALEN); + + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); + + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, add); } int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) @@ -1613,3 +1842,21 @@ int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, sizeof(req), true); } + +int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) +{ + struct mt7615_dev *dev = phy->dev; + struct { + u8 format_id; + u8 sku_enable; + u8 band_idx; + u8 rsv; + } req = { + .format_id = 0, + .band_idx = phy != &dev->phy, + .sku_enable = enable, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, + sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 1fd7dffa6eef..db0199e60cb8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -45,6 +45,62 @@ enum { MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, }; +enum { + MT_SKU_CCK_1_2 = 0, + MT_SKU_CCK_55_11, + MT_SKU_OFDM_6_9, + MT_SKU_OFDM_12_18, + MT_SKU_OFDM_24_36, + MT_SKU_OFDM_48, + MT_SKU_OFDM_54, + MT_SKU_HT20_0_8, + MT_SKU_HT20_32, + MT_SKU_HT20_1_2_9_10, + MT_SKU_HT20_3_4_11_12, + MT_SKU_HT20_5_13, + MT_SKU_HT20_6_14, + MT_SKU_HT20_7_15, + MT_SKU_HT40_0_8, + MT_SKU_HT40_32, + MT_SKU_HT40_1_2_9_10, + MT_SKU_HT40_3_4_11_12, + MT_SKU_HT40_5_13, + MT_SKU_HT40_6_14, + MT_SKU_HT40_7_15, + MT_SKU_VHT20_0, + MT_SKU_VHT20_1_2, + MT_SKU_VHT20_3_4, + MT_SKU_VHT20_5_6, + MT_SKU_VHT20_7, + MT_SKU_VHT20_8, + MT_SKU_VHT20_9, + MT_SKU_VHT40_0, + MT_SKU_VHT40_1_2, + MT_SKU_VHT40_3_4, + MT_SKU_VHT40_5_6, + MT_SKU_VHT40_7, + MT_SKU_VHT40_8, + MT_SKU_VHT40_9, + MT_SKU_VHT80_0, + MT_SKU_VHT80_1_2, + MT_SKU_VHT80_3_4, + MT_SKU_VHT80_5_6, + MT_SKU_VHT80_7, + MT_SKU_VHT80_8, + MT_SKU_VHT80_9, + MT_SKU_VHT160_0, + MT_SKU_VHT160_1_2, + MT_SKU_VHT160_3_4, + MT_SKU_VHT160_5_6, + MT_SKU_VHT160_7, + MT_SKU_VHT160_8, + MT_SKU_VHT160_9, + MT_SKU_1SS_DELTA, + MT_SKU_2SS_DELTA, + MT_SKU_3SS_DELTA, + MT_SKU_4SS_DELTA, +}; + struct mt7615_mcu_rxd { __le32 rxd[4]; @@ -60,6 +116,52 @@ struct mt7615_mcu_rxd { u8 s2d_index; }; +struct mt7615_mcu_rdd_report { + struct mt7615_mcu_rxd rxd; + + u8 idx; + u8 long_detected; + u8 constant_prf_detected; + u8 staggered_prf_detected; + u8 radar_type_idx; + u8 periodic_pulse_num; + u8 long_pulse_num; + u8 hw_pulse_num; + + u8 out_lpn; + u8 out_spn; + u8 out_crpn; + u8 out_crpw; + u8 out_crbn; + u8 out_stgpn; + u8 out_stgpw; + + u8 _rsv[2]; + + __le32 out_pri_const; + __le32 out_pri_stg[3]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + } long_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + } periodic_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + u8 sc_pass; + u8 sw_reset; + } hw_pulse[32]; +}; + #define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) #define MCU_PKT_ID 0xa0 @@ -93,6 +195,7 @@ enum { MCU_EXT_CMD_PM_STATE_CTRL = 0x07, MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, + MCU_EXT_CMD_FW_LOG_2_HOST = 0x13, MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, MCU_EXT_CMD_STA_REC_UPDATE = 0x25, MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, @@ -102,9 +205,12 @@ enum { MCU_EXT_CMD_WTBL_UPDATE = 0x32, MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, MCU_EXT_CMD_PROTECT_CTRL = 0x3e, + MCU_EXT_CMD_DBDC_CTRL = 0x45, MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, MCU_EXT_CMD_BCN_OFFLOAD = 0x49, MCU_EXT_CMD_SET_RX_PATH = 0x4e, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, + MCU_EXT_CMD_SET_RDD_TH = 0x7c, MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, }; @@ -156,6 +262,18 @@ enum { DEV_INFO_MAX_NUM }; +enum { + DBDC_TYPE_WMM, + DBDC_TYPE_MGMT, + DBDC_TYPE_BSS, + DBDC_TYPE_MBSS, + DBDC_TYPE_REPEATER, + DBDC_TYPE_MU, + DBDC_TYPE_BF, + DBDC_TYPE_PTA, + __DBDC_TYPE_MAX, +}; + struct bss_info_omac { __le16 tag; __le16 len; @@ -447,9 +565,10 @@ struct sta_rec_ba { __le16 winsize; } __packed; -#define MT7615_STA_REC_UPDATE_MAX_SIZE (sizeof(struct sta_rec_basic) + \ - sizeof(struct sta_rec_ht) + \ - sizeof(struct sta_rec_vht)) +struct sta_rec_wtbl { + __le16 tag; + __le16 len; +} __packed; enum { STA_REC_BASIC, @@ -464,6 +583,7 @@ enum { STA_REC_HT, STA_REC_VHT, STA_REC_APPS, + STA_REC_WTBL = 13, STA_REC_MAX_NUM }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c new file mode 100644 index 000000000000..0b445471b6e8 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -0,0 +1,115 @@ +#include +#include + +#include "mt7615.h" +#include "mac.h" +#include "../trace.h" + +u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) +{ + u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; + u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; + + mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); + + return MT_PCIE_REMAP_BASE_2 + offset; +} + +static void +mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); +} + +static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) +{ + struct mt7615_dev *dev = dev_instance; + u32 intr; + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return IRQ_NONE; + + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + + intr &= dev->mt76.mmio.irqmask; + + if (intr & MT_INT_TX_DONE_ALL) { + mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL); + napi_schedule(&dev->mt76.tx_napi); + } + + if (intr & MT_INT_RX_DONE(0)) { + mt7615_irq_disable(dev, MT_INT_RX_DONE(0)); + napi_schedule(&dev->mt76.napi[0]); + } + + if (intr & MT_INT_RX_DONE(1)) { + mt7615_irq_disable(dev, MT_INT_RX_DONE(1)); + napi_schedule(&dev->mt76.napi[1]); + } + + if (intr & MT_INT_MCU_CMD) { + u32 val = mt76_rr(dev, MT_MCU_CMD); + + if (val & MT_MCU_CMD_ERROR_MASK) { + dev->reset_state = val; + ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + wake_up(&dev->reset_wait); + } + } + + return IRQ_HANDLED; +} + +int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq) +{ + static const struct mt76_driver_ops drv_ops = { + /* txwi_size = txd size + txp size */ + .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common), + .drv_flags = MT_DRV_TXWI_NO_FREE, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .tx_prepare_skb = mt7615_tx_prepare_skb, + .tx_complete_skb = mt7615_tx_complete_skb, + .rx_skb = mt7615_queue_rx_skb, + .rx_poll_complete = mt7615_rx_poll_complete, + .sta_ps = mt7615_sta_ps, + .sta_add = mt7615_mac_sta_add, + .sta_remove = mt7615_mac_sta_remove, + .update_survey = mt7615_update_channel, + }; + struct mt7615_dev *dev; + struct mt76_dev *mdev; + int ret; + + mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7615_ops, &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7615_dev, mt76); + mt76_mmio_init(&dev->mt76, mem_base); + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + + ret = mt7615_register_device(dev); + if (ret) + goto error; + + return 0; +error: + ieee80211_free_hw(mt76_hw(dev)); + return ret; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 21486831172c..a84a9b4cbf4e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -6,6 +6,7 @@ #include #include +#include #include "../mt76.h" #include "regs.h" @@ -17,9 +18,11 @@ MT7615_MAX_INTERFACES) #define MT7615_WATCHDOG_TIME (HZ / 10) +#define MT7615_RESET_TIMEOUT (30 * HZ) #define MT7615_RATE_RETRY 2 #define MT7615_TX_RING_SIZE 1024 +#define MT7615_TX_MGMT_RING_SIZE 128 #define MT7615_TX_MCU_RING_SIZE 128 #define MT7615_TX_FWDL_RING_SIZE 128 @@ -30,14 +33,30 @@ #define MT7615_FIRMWARE_N9 "mediatek/mt7615_n9.bin" #define MT7615_ROM_PATCH "mediatek/mt7615_rom_patch.bin" +#define MT7622_FIRMWARE_N9 "mediatek/mt7622_n9.bin" +#define MT7622_ROM_PATCH "mediatek/mt7622_rom_patch.bin" + +#define MT7615_FIRMWARE_V1 1 +#define MT7615_FIRMWARE_V2 2 + #define MT7615_EEPROM_SIZE 1024 #define MT7615_TOKEN_SIZE 4096 #define MT_FRAC_SCALE 12 #define MT_FRAC(val, div) (((val) << MT_FRAC_SCALE) / (div)) +#define MT_CHFREQ_VALID BIT(7) +#define MT_CHFREQ_DBDC_IDX BIT(6) +#define MT_CHFREQ_SEQ GENMASK(5, 0) + +#define MT7615_BAR_RATE_DEFAULT 0x4b /* OFDM 6M */ +#define MT7615_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ +#define MT7615_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ + struct mt7615_vif; struct mt7615_sta; +struct mt7615_dfs_pulse; +struct mt7615_dfs_pattern; enum mt7615_hw_txq_id { MT7615_TXQ_MAIN, @@ -46,6 +65,16 @@ enum mt7615_hw_txq_id { MT7615_TXQ_FWDL, }; +enum mt7622_hw_txq_id { + MT7622_TXQ_AC0, + MT7622_TXQ_AC1, + MT7622_TXQ_AC2, + MT7622_TXQ_FWDL = MT7615_TXQ_FWDL, + MT7622_TXQ_AC3, + MT7622_TXQ_MGMT, + MT7622_TXQ_MCU = 15, +}; + struct mt7615_rate_set { struct ieee80211_tx_rate probe_rate; struct ieee80211_tx_rate rates[4]; @@ -79,12 +108,61 @@ struct mt7615_vif { struct mt7615_sta sta; }; +struct mib_stats { + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; +}; + +struct mt7615_phy { + struct mt76_phy *mt76; + struct mt7615_dev *dev; + + u32 rxfilter; + u32 omac_mask; + + u16 noise; + + unsigned long last_cca_adj; + int false_cca_ofdm, false_cca_cck; + s8 ofdm_sensitivity; + s8 cck_sensitivity; + + u16 chainmask; + + s16 coverage_class; + u8 slottime; + + u8 chfreq; + u8 rdd_state; + int dfs_state; + + __le32 rx_ampdu_ts; + u32 ampdu_ref; + + struct mib_stats mib; +}; + struct mt7615_dev { - struct mt76_dev mt76; /* must be first */ + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; + + struct mt7615_phy phy; u32 vif_mask; u32 omac_mask; - __le32 rx_ampdu_ts; + u16 chainmask; + + struct regmap *infracfg; + + struct work_struct mcu_work; + + struct work_struct reset_work; + wait_queue_head_t reset_wait; + u32 reset_state; struct list_head sta_poll_list; spinlock_t sta_poll_lock; @@ -96,17 +174,15 @@ struct mt7615_dev { s16 power; } radar_pattern; u32 hw_pattern; - int dfs_state; - int false_cca_ofdm, false_cca_cck; - unsigned long last_cca_adj; u8 mac_work_count; - s8 ofdm_sensitivity; - s8 cck_sensitivity; bool scs_en; + bool fw_debug; spinlock_t token_lock; struct idr token; + + u8 fw_ver; }; enum { @@ -134,11 +210,6 @@ enum { EXT_BSSID_END }; -enum { - MT_HW_RDD0, - MT_HW_RDD1, -}; - enum { MT_RX_SEL0, MT_RX_SEL1, @@ -158,13 +229,53 @@ enum mt7615_rdd_cmd { RDD_RESUME_BF, }; +static inline struct mt7615_phy * +mt7615_hw_phy(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return phy->priv; +} + +static inline struct mt7615_dev * +mt7615_hw_dev(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return container_of(phy->dev, struct mt7615_dev, mt76); +} + +static inline struct mt7615_phy * +mt7615_ext_phy(struct mt7615_dev *dev) +{ + struct mt76_phy *phy = dev->mt76.phy2; + + if (!phy) + return NULL; + + return phy->priv; +} + extern const struct ieee80211_ops mt7615_ops; extern struct pci_driver mt7615_pci_driver; +extern struct platform_driver mt7622_wmac_driver; +#ifdef CONFIG_MT7622_WMAC +int mt7622_wmac_init(struct mt7615_dev *dev); +#else +static inline int mt7622_wmac_init(struct mt7615_dev *dev) +{ + return 0; +} +#endif + +int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq); u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); +int mt7615_register_ext_phy(struct mt7615_dev *dev); +void mt7615_unregister_ext_phy(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev); int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, struct ieee80211_channel *chan, @@ -172,26 +283,22 @@ int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, int mt7615_dma_init(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); int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, int en); -void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, +void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); -int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, - bool enable); -int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); -int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool en); -int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en); -int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, +int mt7615_mcu_set_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool en); +int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool en); +int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en); -int mt7615_mcu_set_channel(struct mt7615_dev *dev); +int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, const struct ieee80211_tx_queue_params *params); int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, @@ -200,30 +307,24 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, struct ieee80211_ampdu_params *params, bool add); -int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val); -int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev); -int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev); int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev); +int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl); static inline bool is_mt7622(struct mt76_dev *dev) { + if (!IS_ENABLED(CONFIG_MT7622_WMAC)) + return false; + return mt76_chip(dev) == 0x7622; } -static inline void mt7615_dfs_check_channel(struct mt7615_dev *dev) +static inline bool is_mt7615(struct mt76_dev *dev) { - enum nl80211_chan_width width = dev->mt76.chandef.width; - u32 freq = dev->mt76.chandef.chan->center_freq; - struct ieee80211_hw *hw = mt76_hw(dev); - - if (hw->conf.chandef.chan->center_freq != freq || - hw->conf.chandef.width != width) - dev->dfs_state = -1; + return mt76_chip(dev) == 0x7615; } static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) @@ -239,26 +340,29 @@ static inline void mt7615_irq_disable(struct mt7615_dev *dev, u32 mask) void mt7615_update_channel(struct mt76_dev *mdev); bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask); void mt7615_mac_reset_counters(struct mt7615_dev *dev); -void mt7615_mac_cca_stats_reset(struct mt7615_dev *dev); +void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy); void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable); +void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy); void mt7615_mac_sta_poll(struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, struct ieee80211_key_conf *key); +void mt7615_mac_set_timing(struct mt7615_phy *phy); int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb); void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data); void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, enum set_key_cmd cmd); +void mt7615_mac_reset_work(struct work_struct *work); +int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); -int mt7615_mcu_init_mac(struct mt7615_dev *dev); -int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val); -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter); +int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable); +int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val); +int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter); int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index); -int mt7615_mcu_set_tx_power(struct mt7615_dev *dev); void mt7615_mcu_exit(struct mt7615_dev *dev); int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -272,17 +376,20 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); -int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, +int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); +void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void mt7615_mac_work(struct work_struct *work); void mt7615_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *txwi); -int mt76_dfs_start_rdd(struct mt7615_dev *dev, bool force); -int mt7615_dfs_init_radar_detector(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); +int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, + const struct mt7615_dfs_pattern *pattern); +int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable); +int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_init_debugfs(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h new file mode 100644 index 000000000000..d3eb49d83b98 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (C) 2019 Lorenzo Bianconi + */ + +#if !defined(__MT7615_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __MT7615_TRACE_H + +#include +#include "mt7615.h" + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mt7615 + +#define MAXNAME 32 +#define DEV_ENTRY __array(char, wiphy_name, 32) +#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ + wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) +#define DEV_PR_FMT "%s" +#define DEV_PR_ARG __entry->wiphy_name + +#define TOKEN_ENTRY __field(u16, token) +#define TOKEN_ASSIGN __entry->token = token +#define TOKEN_PR_FMT " %d" +#define TOKEN_PR_ARG __entry->token + +DECLARE_EVENT_CLASS(dev_token, + TP_PROTO(struct mt7615_dev *dev, u16 token), + TP_ARGS(dev, token), + TP_STRUCT__entry( + DEV_ENTRY + TOKEN_ENTRY + ), + TP_fast_assign( + DEV_ASSIGN; + TOKEN_ASSIGN; + ), + TP_printk( + DEV_PR_FMT TOKEN_PR_FMT, + DEV_PR_ARG, TOKEN_PR_ARG + ) +); + +DEFINE_EVENT(dev_token, mac_tx_free, + TP_PROTO(struct mt7615_dev *dev, u16 token), + TP_ARGS(dev, token) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mt7615_trace + +#include diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 1eb1eb659c3f..43e02128cc48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -10,84 +10,15 @@ #include #include "mt7615.h" -#include "mac.h" static const struct pci_device_id mt7615_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7615) }, { }, }; -u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) -{ - u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; - u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; - - mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); - - return MT_PCIE_REMAP_BASE_2 + offset; -} - -static void -mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) -{ - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - - mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); -} - -static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) -{ - struct mt7615_dev *dev = dev_instance; - u32 intr; - - intr = mt76_rr(dev, MT_INT_SOURCE_CSR); - mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) - return IRQ_NONE; - - intr &= dev->mt76.mmio.irqmask; - - if (intr & MT_INT_TX_DONE_ALL) { - mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL); - napi_schedule(&dev->mt76.tx_napi); - } - - if (intr & MT_INT_RX_DONE(0)) { - mt7615_irq_disable(dev, MT_INT_RX_DONE(0)); - napi_schedule(&dev->mt76.napi[0]); - } - - if (intr & MT_INT_RX_DONE(1)) { - mt7615_irq_disable(dev, MT_INT_RX_DONE(1)); - napi_schedule(&dev->mt76.napi[1]); - } - - return IRQ_HANDLED; -} - static int mt7615_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - static const struct mt76_driver_ops drv_ops = { - /* txwi_size = txd size + txp size */ - .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp), - .drv_flags = MT_DRV_TXWI_NO_FREE, - .survey_flags = SURVEY_INFO_TIME_TX | - SURVEY_INFO_TIME_RX | - SURVEY_INFO_TIME_BSS_RX, - .tx_prepare_skb = mt7615_tx_prepare_skb, - .tx_complete_skb = mt7615_tx_complete_skb, - .rx_skb = mt7615_queue_rx_skb, - .rx_poll_complete = mt7615_rx_poll_complete, - .sta_ps = mt7615_sta_ps, - .sta_add = mt7615_sta_add, - .sta_assoc = mt7615_sta_assoc, - .sta_remove = mt7615_sta_remove, - .update_survey = mt7615_update_channel, - }; - struct mt7615_dev *dev; - struct mt76_dev *mdev; int ret; ret = pcim_enable_device(pdev); @@ -104,31 +35,7 @@ static int mt7615_pci_probe(struct pci_dev *pdev, if (ret) return ret; - mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7615_ops, - &drv_ops); - if (!mdev) - return -ENOMEM; - - dev = container_of(mdev, struct mt7615_dev, mt76); - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); - - mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | - (mt76_rr(dev, MT_HW_REV) & 0xff); - dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - - ret = devm_request_irq(mdev->dev, pdev->irq, mt7615_irq_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); - if (ret) - goto error; - - ret = mt7615_register_device(dev); - if (ret) - goto error; - - return 0; -error: - ieee80211_free_hw(mt76_hw(dev)); - return ret; + return mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], pdev->irq); } static void mt7615_pci_remove(struct pci_dev *pdev) @@ -146,10 +53,7 @@ struct pci_driver mt7615_pci_driver = { .remove = mt7615_pci_remove, }; -module_pci_driver(mt7615_pci_driver); - MODULE_DEVICE_TABLE(pci, mt7615_pci_device_table); MODULE_FIRMWARE(MT7615_FIRMWARE_CR4); MODULE_FIRMWARE(MT7615_FIRMWARE_N9); MODULE_FIRMWARE(MT7615_ROM_PATCH); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 61a4aa9ac6e6..fe68f6b2cbf8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -8,6 +8,10 @@ #define MT_HW_CHIPID 0x1008 #define MT_TOP_STRAP_STA 0x1010 #define MT_TOP_3NSS BIT(24) + +#define MT_TOP_OFF_RSV 0x1128 +#define MT_TOP_OFF_RSV_FW_STATE GENMASK(18, 16) + #define MT_TOP_MISC2 0x1134 #define MT_TOP_MISC2_FW_STATE GENMASK(2, 0) @@ -31,14 +35,21 @@ #define MT_CFG_LPCR_HOST_FW_OWN BIT(0) #define MT_CFG_LPCR_HOST_DRV_OWN BIT(1) +#define MT_MCU_INT_EVENT MT_HIF(0x1f8) +#define MT_MCU_INT_EVENT_PDMA_STOPPED BIT(0) +#define MT_MCU_INT_EVENT_PDMA_INIT BIT(1) +#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) +#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) + #define MT_INT_SOURCE_CSR MT_HIF(0x200) #define MT_INT_MASK_CSR MT_HIF(0x204) #define MT_DELAY_INT_CFG MT_HIF(0x210) #define MT_INT_RX_DONE(_n) BIT(_n) #define MT_INT_RX_DONE_ALL GENMASK(1, 0) -#define MT_INT_TX_DONE_ALL GENMASK(7, 4) +#define MT_INT_TX_DONE_ALL GENMASK(19, 4) #define MT_INT_TX_DONE(_n) BIT((_n) + 4) +#define MT_INT_MCU_CMD BIT(30) #define MT_WPDMA_GLO_CFG MT_HIF(0x208) #define MT_WPDMA_GLO_CFG_TX_DMA_EN BIT(0) @@ -49,6 +60,7 @@ #define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE BIT(6) #define MT_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) #define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0 BIT(9) +#define MT_WPDMA_GLO_CFG_BYPASS_TX_SCH BIT(9) /* MT7622 */ #define MT_WPDMA_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) #define MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) #define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT21 GENMASK(23, 22) @@ -58,6 +70,22 @@ #define MT_WPDMA_RST_IDX MT_HIF(0x20c) +#define MT_WPDMA_MEM_RNG_ERR MT_HIF(0x224) + +#define MT_MCU_CMD MT_HIF(0x234) +#define MT_MCU_CMD_CLEAR_FW_OWN BIT(0) +#define MT_MCU_CMD_STOP_PDMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_PDMA BIT(2) +#define MT_MCU_CMD_RESET_DONE BIT(3) +#define MT_MCU_CMD_RECOVERY_DONE BIT(4) +#define MT_MCU_CMD_NORMAL_STATE BIT(5) +#define MT_MCU_CMD_LMAC_ERROR BIT(24) +#define MT_MCU_CMD_PSE_ERROR BIT(25) +#define MT_MCU_CMD_PLE_ERROR BIT(26) +#define MT_MCU_CMD_PDMA_ERROR BIT(27) +#define MT_MCU_CMD_PCIE_ERROR BIT(28) +#define MT_MCU_CMD_ERROR_MASK (GENMASK(5, 1) | GENMASK(28, 24)) + #define MT_TX_RING_BASE MT_HIF(0x300) #define MT_RX_RING_BASE MT_HIF(0x400) @@ -81,36 +109,35 @@ #define MT_WF_PHY_BASE 0x10000 #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) -#define MT_WF_PHY_WF2_RFCTRL0 MT_WF_PHY(0x1900) +#define MT_WF_PHY_WF2_RFCTRL0(n) MT_WF_PHY(0x1900 + (n) * 0x400) #define MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN BIT(9) -#define MT_WF_PHY_R0_B0_PHYMUX_5 MT_WF_PHY(0x0614) +#define MT_WF_PHY_R0_PHYMUX_5(_phy) MT_WF_PHY(0x0614 + ((_phy) << 9)) -#define MT_WF_PHY_R0_B0_PHYCTRL_STS0 MT_WF_PHY(0x020c) +#define MT_WF_PHY_R0_PHYCTRL_STS0(_phy) MT_WF_PHY(0x020c + ((_phy) << 9)) #define MT_WF_PHYCTRL_STAT_PD_OFDM GENMASK(31, 16) #define MT_WF_PHYCTRL_STAT_PD_CCK GENMASK(15, 0) -#define MT_WF_PHY_R0_B0_PHYCTRL_STS5 MT_WF_PHY(0x0220) +#define MT_WF_PHY_R0_PHYCTRL_STS5(_phy) MT_WF_PHY(0x0220 + ((_phy) << 9)) #define MT_WF_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16) #define MT_WF_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0) -#define MT_WF_PHY_B0_MIN_PRI_PWR MT_WF_PHY(0x229c) -#define MT_WF_PHY_B0_PD_OFDM_MASK GENMASK(28, 20) -#define MT_WF_PHY_B0_PD_OFDM(v) ((v) << 20) -#define MT_WF_PHY_B0_PD_BLK BIT(19) +#define MT_WF_PHY_MIN_PRI_PWR(_phy) MT_WF_PHY((_phy) ? 0x084 : 0x229c) +#define MT_WF_PHY_PD_OFDM_MASK(_phy) ((_phy) ? GENMASK(24, 16) : \ + GENMASK(28, 20)) +#define MT_WF_PHY_PD_OFDM(_phy, v) ((v) << ((_phy) ? 16 : 20)) +#define MT_WF_PHY_PD_BLK(_phy) ((_phy) ? BIT(25) : BIT(19)) -#define MT_WF_PHY_B1_MIN_PRI_PWR MT_WF_PHY(0x084) -#define MT_WF_PHY_B1_PD_OFDM_MASK GENMASK(24, 16) -#define MT_WF_PHY_B1_PD_OFDM(v) ((v) << 16) -#define MT_WF_PHY_B1_PD_BLK BIT(25) +#define MT_WF_PHY_RXTD_BASE MT_WF_PHY(0x2200) +#define MT_WF_PHY_RXTD(_n) (MT_WF_PHY_RXTD_BASE + ((_n) << 2)) -#define MT_WF_PHY_B0_RXTD_CCK_PD MT_WF_PHY(0x2310) -#define MT_WF_PHY_B0_PD_CCK_MASK GENMASK(8, 1) -#define MT_WF_PHY_B0_PD_CCK(v) ((v) << 1) +#define MT_WF_PHY_RXTD_CCK_PD(_phy) MT_WF_PHY((_phy) ? 0x2314 : 0x2310) +#define MT_WF_PHY_PD_CCK_MASK(_phy) (_phy) ? GENMASK(31, 24) : \ + GENMASK(8, 1) +#define MT_WF_PHY_PD_CCK(_phy, v) ((v) << ((_phy) ? 24 : 1)) -#define MT_WF_PHY_B1_RXTD_CCK_PD MT_WF_PHY(0x2314) -#define MT_WF_PHY_B1_PD_CCK_MASK GENMASK(31, 24) -#define MT_WF_PHY_B1_PD_CCK(v) ((v) << 24) +#define MT_WF_PHY_RXTD2_BASE MT_WF_PHY(0x2a00) +#define MT_WF_PHY_RXTD2(_n) (MT_WF_PHY_RXTD2_BASE + ((_n) << 2)) #define MT_WF_CFG_BASE 0x20200 #define MT_WF_CFG(ofs) (MT_WF_CFG_BASE + (ofs)) @@ -131,8 +158,8 @@ #define MT_AGG_ARCR_RATE_DOWN_RATIO_EN BIT(19) #define MT_AGG_ARCR_RATE_UP_EXTRA_TH GENMASK(22, 20) -#define MT_AGG_ARUCR MT_WF_AGG(0x018) -#define MT_AGG_ARDCR MT_WF_AGG(0x01c) +#define MT_AGG_ARUCR(_band) MT_WF_AGG(0x018 + (_band) * 0x100) +#define MT_AGG_ARDCR(_band) MT_WF_AGG(0x01c + (_band) * 0x100) #define MT_AGG_ARxCR_LIMIT_SHIFT(_n) (4 * (_n)) #define MT_AGG_ARxCR_LIMIT(_n) GENMASK(2 + \ MT_AGG_ARxCR_LIMIT_SHIFT(_n), \ @@ -142,8 +169,7 @@ #define MT_AGG_ASRCR1 MT_WF_AGG(0x064) #define MT_AGG_ASRCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(5, 0)) -#define MT_AGG_ACR0 MT_WF_AGG(0x070) -#define MT_AGG_ACR1 MT_WF_AGG(0x170) +#define MT_AGG_ACR(_band) MT_WF_AGG(0x070 + (_band) * 0x100) #define MT_AGG_ACR_NO_BA_RULE BIT(0) #define MT_AGG_ACR_NO_BA_AR_RULE BIT(1) #define MT_AGG_ACR_PKT_TIME_EN BIT(2) @@ -153,14 +179,33 @@ #define MT_AGG_SCR MT_WF_AGG(0x0fc) #define MT_AGG_SCR_NLNAV_MID_PTEC_DIS BIT(3) +#define MT_WF_ARB_BASE 0x20c00 +#define MT_WF_ARB(ofs) (MT_WF_ARB_BASE + (ofs)) + +#define MT_ARB_SCR MT_WF_ARB(0x080) +#define MT_ARB_SCR_TX0_DISABLE BIT(8) +#define MT_ARB_SCR_RX0_DISABLE BIT(9) +#define MT_ARB_SCR_TX1_DISABLE BIT(10) +#define MT_ARB_SCR_RX1_DISABLE BIT(11) + #define MT_WF_TMAC_BASE 0x21000 #define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs)) -#define MT_TMAC_TRCR0 MT_WF_TMAC(0x09c) -#define MT_TMAC_TRCR1 MT_WF_TMAC(0x070) +#define MT_TMAC_CDTR MT_WF_TMAC(0x090) +#define MT_TMAC_ODTR MT_WF_TMAC(0x094) +#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) + +#define MT_TMAC_TRCR(_band) MT_WF_TMAC((_band) ? 0x070 : 0x09c) #define MT_TMAC_TRCR_CCA_SEL GENMASK(31, 30) #define MT_TMAC_TRCR_SEC_CCA_SEL GENMASK(29, 28) +#define MT_TMAC_ICR(_band) MT_WF_TMAC((_band) ? 0x074 : 0x0a4) +#define MT_IFS_EIFS GENMASK(8, 0) +#define MT_IFS_RIFS GENMASK(14, 10) +#define MT_IFS_SIFS GENMASK(22, 16) +#define MT_IFS_SLOT GENMASK(30, 24) + #define MT_TMAC_CTCR0 MT_WF_TMAC(0x0f4) #define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) #define MT_TMAC_CTCR0_INS_DDLMT_DENSITY GENMASK(15, 12) @@ -170,7 +215,7 @@ #define MT_WF_RMAC_BASE 0x21200 #define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs)) -#define MT_WF_RFCR MT_WF_RMAC(0x000) +#define MT_WF_RFCR(_band) MT_WF_RMAC((_band) ? 0x100 : 0x000) #define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) #define MT_WF_RFCR_DROP_FCSFAIL BIT(1) #define MT_WF_RFCR_DROP_VERSION BIT(3) @@ -193,13 +238,15 @@ #define MT_WF_RFCR_DROP_NDPA BIT(20) #define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) -#define MT_WF_RFCR1 MT_WF_RMAC(0x004) +#define MT_WF_RFCR1(_band) MT_WF_RMAC((_band) ? 0x104 : 0x004) #define MT_WF_RFCR1_DROP_ACK BIT(4) #define MT_WF_RFCR1_DROP_BF_POLL BIT(5) #define MT_WF_RFCR1_DROP_BA BIT(6) #define MT_WF_RFCR1_DROP_CFEND BIT(7) #define MT_WF_RFCR1_DROP_CFACK BIT(8) +#define MT_CHFREQ(_band) MT_WF_RMAC((_band) ? 0x130 : 0x030) + #define MT_WF_RMAC_MIB_TIME0 MT_WF_RMAC(0x03c4) #define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) #define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) @@ -207,6 +254,7 @@ #define MT_WF_RMAC_MIB_AIRTIME0 MT_WF_RMAC(0x0380) #define MT_WF_RMAC_MIB_TIME5 MT_WF_RMAC(0x03d8) +#define MT_WF_RMAC_MIB_TIME6 MT_WF_RMAC(0x03dc) #define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) #define MT_WF_DMA_BASE 0x21800 @@ -216,8 +264,7 @@ #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2) #define MT_DMA_DCR0_RX_VEC_DROP BIT(17) -#define MT_DMA_BN0RCFR0 MT_WF_DMA(0x070) -#define MT_DMA_BN1RCFR0 MT_WF_DMA(0x0b0) +#define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40) #define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2) #define MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR BIT(3) #define MT_DMA_RCFR0_MCU_RX_CTL_BAR BIT(4) @@ -294,9 +341,9 @@ #define MT_WF_MIB(ofs) (MT_WF_MIB_BASE + (ofs)) #define MT_MIB_M0_MISC_CR MT_WF_MIB(0x00c) -#define MT_MIB_MB_SDR0(n) MT_WF_MIB(0x100 + ((n) << 4)) -#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) -#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) + +#define MT_MIB_SDR3(n) MT_WF_MIB(0x014 + ((n) << 9)) +#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0) #define MT_MIB_SDR9(n) MT_WF_MIB(0x02c + ((n) << 9)) #define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) @@ -309,8 +356,56 @@ #define MT_MIB_SDR37(n) MT_WF_MIB(0x09c + ((n) << 9)) #define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) +#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(0x100 + ((_band) << 9) + \ + ((n) << 4)) +#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) +#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) + +#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(0x104 + ((_band) << 9) + \ + ((n) << 4)) +#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16) + #define MT_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2)) +#define MT_DMASHDL_BASE 0x5000a000 +#define MT_DMASHDL_OPTIONAL 0x008 +#define MT_DMASHDL_PAGE 0x00c + +#define MT_DMASHDL_REFILL 0x010 + +#define MT_DMASHDL_PKT_MAX_SIZE 0x01c +#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) +#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) + +#define MT_DMASHDL_GROUP_QUOTA(_n) (0x020 + ((_n) << 2)) +#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0) +#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16) + +#define MT_DMASHDL_SCHED_SET0 0x0b0 +#define MT_DMASHDL_SCHED_SET1 0x0b4 + +#define MT_DMASHDL_Q_MAP(_n) (0x0d0 + ((_n) << 2)) +#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0) +#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8)) + +#define MT_LED_BASE_PHYS 0x80024000 +#define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n)) + +#define MT_LED_CTRL MT_LED_PHYS(0x00) + +#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n))) +#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) +#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) +#define MT_LED_CTRL_TX_MANUAL_BLINK(_n) BIT(3 + (8 * (_n))) +#define MT_LED_CTRL_TX_OVER_BLINK(_n) BIT(5 + (8 * (_n))) +#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) + +#define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8)) +#define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8)) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 0) + #define MT_EFUSE_BASE 0x81070000 #define MT_EFUSE_BASE_CTRL 0x000 #define MT_EFUSE_BASE_CTRL_EMPTY BIT(30) @@ -328,4 +423,8 @@ #define MT_EFUSE_WDATA(_i) (0x010 + ((_i) * 4)) #define MT_EFUSE_RDATA(_i) (0x030 + ((_i) * 4)) +/* INFRACFG host register range on MT7622 */ +#define MT_INFRACFG_MISC 0x700 +#define MT_INFRACFG_MISC_AP2CONN_WAKE BIT(1) + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c new file mode 100644 index 000000000000..07ec9ec282f5 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Ryder Lee + * Felix Fietkau + */ + +#include +#include +#include +#include +#include +#include +#include "mt7615.h" + +int mt7622_wmac_init(struct mt7615_dev *dev) +{ + struct device_node *np = dev->mt76.dev->of_node; + + if (!is_mt7622(&dev->mt76)) + return 0; + + dev->infracfg = syscon_regmap_lookup_by_phandle(np, "mediatek,infracfg"); + if (IS_ERR(dev->infracfg)) { + dev_err(dev->mt76.dev, "Cannot find infracfg controller\n"); + return PTR_ERR(dev->infracfg); + } + + return 0; +} + +static int mt7622_wmac_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + void __iomem *mem_base; + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get device IRQ\n"); + return irq; + } + + mem_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mem_base)) { + dev_err(&pdev->dev, "Failed to get memory resource\n"); + return PTR_ERR(mem_base); + } + + return mt7615_mmio_probe(&pdev->dev, mem_base, irq); +} + +static int mt7622_wmac_remove(struct platform_device *pdev) +{ + struct mt7615_dev *dev = platform_get_drvdata(pdev); + + mt7615_unregister_device(dev); + + return 0; +} + +static const struct of_device_id mt7622_wmac_of_match[] = { + { .compatible = "mediatek,mt7622-wmac" }, + {}, +}; + +struct platform_driver mt7622_wmac_driver = { + .driver = { + .name = "mt7622-wmac", + .of_match_table = mt7622_wmac_of_match, + }, + .probe = mt7622_wmac_probe, + .remove = mt7622_wmac_remove, +}; + +MODULE_FIRMWARE(MT7622_FIRMWARE_N9); +MODULE_FIRMWARE(MT7622_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/trace.c b/drivers/net/wireless/mediatek/mt76/mt7615/trace.c new file mode 100644 index 000000000000..6c02d5aff68f --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/trace.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2019 Lorenzo Bianconi + */ + +#include + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "mt7615_trace.h" + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index d1405528b504..9087607b621e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -109,7 +109,7 @@ static void mt76x0_set_freq_offset(struct mt76x02_dev *dev) void mt76x0_read_rx_gain(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx; s8 val, lna_5g[3], lna_2g; u16 rssi_offset; @@ -129,7 +129,7 @@ void mt76x0_read_rx_gain(struct mt76x02_dev *dev) static s8 mt76x0_get_delta(struct mt76x02_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; u8 val; if (chandef->width == NL80211_CHAN_WIDTH_80) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 388b54cded1b..57f8d56737eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -264,12 +264,12 @@ int mt76x0_register_device(struct mt76x02_dev *dev) if (dev->mt76.cap.has_5ghz) { /* overwrite unsupported features */ - mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband); - mt76x0_init_txpower(dev, &dev->mt76.sband_5g.sband); + mt76x0_vht_cap_mask(&dev->mphy.sband_5g.sband); + mt76x0_init_txpower(dev, &dev->mphy.sband_5g.sband); } if (dev->mt76.cap.has_2ghz) - mt76x0_init_txpower(dev, &dev->mt76.sband_2g.sband); + mt76x0_init_txpower(dev, &dev->mphy.sband_2g.sband); mt76x02_init_debugfs(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index b2ccf50512dc..700ae9c12f1d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -16,7 +16,7 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) if (mt76_is_mmio(&dev->mt76)) tasklet_disable(&dev->dfs_pd.dfs_tasklet); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt76x0_phy_set_channel(dev, chandef); mt76x02_mac_cc_reset(dev); @@ -28,7 +28,7 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) } mt76x02_pre_tbtt_enable(dev, true); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } int mt76x0_config(struct ieee80211_hw *hw, u32 changed) @@ -44,9 +44,9 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->mt76.txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = hw->conf.power_level * 2; - if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) mt76x0_phy_set_txpower(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index e2974e0ae1fc..0b520ae08d01 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -20,7 +20,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw) MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -47,7 +47,7 @@ static void mt76x0e_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt76x0e_stop_hw(dev); } @@ -67,6 +67,7 @@ static const struct ieee80211_ops mt76x0e_ops = { .configure_filter = mt76x02_configure_filter, .bss_info_changed = mt76x02_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .conf_tx = mt76x02_conf_tx, .sw_scan_start = mt76_sw_scan, @@ -124,7 +125,7 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev) if (err < 0) return err; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); return 0; } @@ -195,7 +196,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) static void mt76x0e_cleanup(struct mt76x02_dev *dev) { - clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mt76x0_chip_onoff(dev, false, false); mt76x0e_stop_hw(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c index 038187b390ce..007c762c6db1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c @@ -126,7 +126,7 @@ int mt76x0e_mcu_init(struct mt76x02_dev *dev) if (err < 0) return err; - set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 2ecd45f8af90..b56397c05218 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -23,7 +23,7 @@ mt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value) int ret = 0; u8 bank, reg; - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return -ENODEV; bank = MT_RF_BANK(offset); @@ -62,7 +62,7 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 offset) u32 val; u8 bank, reg; - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return -ENODEV; bank = MT_RF_BANK(offset); @@ -109,7 +109,7 @@ mt76x0_rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val) }; WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, - &dev->mt76.state)); + &dev->mphy.state)); return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); } else { return mt76x0_rf_csr_wr(dev, offset, val); @@ -127,7 +127,7 @@ static int mt76x0_rf_rr(struct mt76x02_dev *dev, u32 offset) }; WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, - &dev->mt76.state)); + &dev->mphy.state)); ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); val = pair.value; } else { @@ -502,7 +502,7 @@ mt76x0_phy_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width) static void mt76x0_phy_tssi_dc_calibrate(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u32 val; if (chan->band == NL80211_BAND_5GHZ) @@ -543,7 +543,7 @@ static int mt76x0_phy_tssi_adc_calibrate(struct mt76x02_dev *dev, s16 *ltssi, u8 *info) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u32 val; val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050; @@ -696,7 +696,7 @@ mt76x0_phy_get_delta_power(struct mt76x02_dev *dev, u8 tx_mode, s8 target_power, s8 target_pa_power, s16 ltssi) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; int tssi_target = target_power << 12, tssi_slope; int tssi_offset, tssi_db, ret; u32 data; @@ -844,12 +844,12 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) struct mt76_rate_power *t = &dev->mt76.rate_power; s8 info; - mt76x0_get_tx_power_per_rate(dev, dev->mt76.chandef.chan, t); - mt76x0_get_power_info(dev, dev->mt76.chandef.chan, &info); + mt76x0_get_tx_power_per_rate(dev, dev->mphy.chandef.chan, t); + mt76x0_get_power_info(dev, dev->mphy.chandef.chan, &info); mt76x02_add_rate_power_offset(t, info); - mt76x02_limit_rate_power(t, dev->mt76.txpower_conf); - dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); + mt76x02_limit_rate_power(t, dev->txpower_conf); + dev->mphy.txpower_cur = mt76x02_get_max_rate_power(t); mt76x02_add_rate_power_offset(t, -info); dev->target_power = info; @@ -858,7 +858,7 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; int is_5ghz = (chan->band == NL80211_BAND_5GHZ) ? 1 : 0; u32 val, tx_alc, reg_val; @@ -933,7 +933,7 @@ void mt76x0_phy_set_channel(struct mt76x02_dev *dev, FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)), }; - bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); + bool scan = test_bit(MT76_SCANNING, &dev->mphy.state); int ch_group_index, freq, freq1; u8 channel; u32 val; @@ -1037,7 +1037,7 @@ static void mt76x0_phy_temp_sensor(struct mt76x02_dev *dev) if (abs(val - dev->cal.temp_vco) > 20) { mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, - dev->mt76.chandef.chan->hw_value); + dev->mphy.chandef.chan->hw_value); dev->cal.temp_vco = val; } if (abs(val - dev->cal.temp) > 30) { @@ -1057,7 +1057,7 @@ static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev) mt76_rmw_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN, gain); - if ((dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) && + if ((dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR) && !is_mt7630(dev)) mt76x02_phy_dfs_adjust_agc(dev); } @@ -1069,7 +1069,7 @@ mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev) u8 gain_delta; int low_gain; - dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); if (!dev->cal.avg_rssi_all) dev->cal.avg_rssi_all = -75; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 65ba9fc6ea0b..5535b9c0632f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -71,7 +71,7 @@ static void mt76x0_init_usb_dma(struct mt76x02_dev *dev) static void mt76x0u_cleanup(struct mt76x02_dev *dev) { - clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt76x0_chip_onoff(dev, false, false); mt76u_queues_deinit(&dev->mt76); } @@ -80,13 +80,13 @@ static void mt76x0u_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->mt76.mac_work); mt76u_stop_tx(&dev->mt76); mt76x02u_exit_beacon_config(dev); - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return; if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000)) @@ -112,7 +112,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw) MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -126,6 +126,7 @@ static const struct ieee80211_ops mt76x0u_ops = { .configure_filter = mt76x02_configure_filter, .bss_info_changed = mt76x02_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .conf_tx = mt76x02_conf_tx, .sw_scan_start = mt76_sw_scan, @@ -172,8 +173,14 @@ static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset) static int mt76x0u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = dev->mt76.hw; + struct mt76_usb *usb = &dev->mt76.usb; int err; + usb->mcu.data = devm_kmalloc(dev->mt76.dev, MCU_RESP_URB_SIZE, + GFP_KERNEL); + if (!usb->mcu.data) + return -ENOMEM; + err = mt76u_alloc_queues(&dev->mt76); if (err < 0) goto out_err; @@ -182,17 +189,13 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) if (err < 0) goto out_err; + /* check hw sg support in order to enable AMSDU */ + hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1; err = mt76x0_register_device(dev); if (err < 0) goto out_err; - /* check hw sg support in order to enable AMSDU */ - if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; - else - hw->max_tx_fragments = 1; - - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); return 0; @@ -240,7 +243,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, usb_set_intfdata(usb_intf, dev); mt76x02u_init_mcu(mdev); - ret = mt76u_init(mdev, usb_intf); + ret = mt76u_init(mdev, usb_intf, false); if (ret) goto err; @@ -283,7 +286,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, static void mt76x0_disconnect(struct usb_interface *usb_intf) { struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); - bool initialized = test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + bool initialized = test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); if (!initialized) return; @@ -304,7 +307,7 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); mt76u_stop_rx(&dev->mt76); - clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); mt76x0_chip_onoff(dev, false, false); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c index 888a930a5e08..45502fd4693f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c @@ -168,7 +168,7 @@ int mt76x0u_mcu_init(struct mt76x02_dev *dev) if (ret < 0) return ret; - set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 0ca0bbfe8769..23040c193ca5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -70,18 +70,23 @@ struct mt76x02_beacon_ops { (dev)->beacon_ops->pre_tbtt_enable(dev, enable) struct mt76x02_dev { - struct mt76_dev mt76; /* must be first */ + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; struct mac_address macaddr_list[8]; struct mutex phy_mutex; u16 vif_mask; + u16 chainmask; u8 txdone_seq; DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); spinlock_t txstatus_fifo_lock; u32 tx_airtime; + u32 ampdu_ref; struct sk_buff *rx_head; @@ -93,8 +98,7 @@ struct mt76x02_dev { const struct mt76x02_beacon_ops *beacon_ops; - struct sk_buff *beacons[8]; - u8 beacon_data_mask; + u8 beacon_data_count; u8 tbtt_count; @@ -104,13 +108,14 @@ struct mt76x02_dev { struct mt76x02_calibration cal; + int txpower_conf; s8 target_power; s8 target_power_delta[2]; bool enable_tpc; bool no_2ghz; - u8 coverage_class; + s16 coverage_class; u8 slottime; struct mt76x02_dfs_pattern_detector dfs_pd; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index 4209209ac940..5d034cec191b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -26,78 +26,40 @@ static int mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) { int beacon_len = dev->beacon_ops->slot_size; - struct mt76x02_txwi txwi; if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi))) return -ENOSPC; - mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); + /* USB devices already reserve enough skb headroom for txwi's. This + * helps to save slow copies over USB. + */ + if (mt76_is_usb(&dev->mt76)) { + struct mt76x02_txwi *txwi; - mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); - offset += sizeof(txwi); + txwi = (struct mt76x02_txwi *)(skb->data - sizeof(*txwi)); + mt76x02_mac_write_txwi(dev, txwi, skb, NULL, NULL, skb->len); + skb_push(skb, sizeof(*txwi)); + } else { + struct mt76x02_txwi txwi; + + mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); + mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); + offset += sizeof(txwi); + } mt76_wr_copy(dev, offset, skb->data, skb->len); return 0; } -static int -__mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, - struct sk_buff *skb) +void mt76x02_mac_set_beacon(struct mt76x02_dev *dev, + struct sk_buff *skb) { - int beacon_len = dev->beacon_ops->slot_size; - int beacon_addr = MT_BEACON_BASE + (beacon_len * bcn_idx); - int ret = 0; - int i; + int bcn_len = dev->beacon_ops->slot_size; + int bcn_addr = MT_BEACON_BASE + (bcn_len * dev->beacon_data_count); - /* Prevent corrupt transmissions during update */ - mt76_set(dev, MT_BCN_BYPASS_MASK, BIT(bcn_idx)); - - if (skb) { - ret = mt76x02_write_beacon(dev, beacon_addr, skb); - if (!ret) - dev->beacon_data_mask |= BIT(bcn_idx); - } else { - dev->beacon_data_mask &= ~BIT(bcn_idx); - for (i = 0; i < beacon_len; i += 4) - mt76_wr(dev, beacon_addr + i, 0); - } - - mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask); - - return ret; -} - -int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, - struct sk_buff *skb) -{ - bool force_update = false; - int bcn_idx = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) { - if (vif_idx == i) { - force_update = !!dev->beacons[i] ^ !!skb; - dev_kfree_skb(dev->beacons[i]); - dev->beacons[i] = skb; - __mt76x02_mac_set_beacon(dev, bcn_idx, skb); - } else if (force_update && dev->beacons[i]) { - __mt76x02_mac_set_beacon(dev, bcn_idx, - dev->beacons[i]); - } - - bcn_idx += !!dev->beacons[i]; - } - - for (i = bcn_idx; i < ARRAY_SIZE(dev->beacons); i++) { - if (!(dev->beacon_data_mask & BIT(i))) - break; - - __mt76x02_mac_set_beacon(dev, i, NULL); - } - - mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N, - bcn_idx - 1); - return 0; + if (!mt76x02_write_beacon(dev, bcn_addr, skb)) + dev->beacon_data_count++; + dev_kfree_skb(skb); } EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon); @@ -116,7 +78,6 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, dev->mt76.beacon_mask |= BIT(mvif->idx); } else { dev->mt76.beacon_mask &= ~BIT(mvif->idx); - mt76x02_mac_set_beacon(dev, mvif->idx, NULL); } if (!!old_mask == !!dev->mt76.beacon_mask) @@ -182,7 +143,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!skb) return; - mt76x02_mac_set_beacon(dev, mvif->idx, skb); + mt76x02_mac_set_beacon(dev, skb); } EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter); @@ -241,17 +202,11 @@ EXPORT_SYMBOL_GPL(mt76x02_enqueue_buffered_bc); void mt76x02_init_beacon_config(struct mt76x02_dev *dev) { - int i; - mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_BEACON_TX)); mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); - - for (i = 0; i < 8; i++) - mt76x02_mac_set_beacon(dev, i, NULL); - mt76x02_set_beacon_offsets(dev); } EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 5dec33ed8527..ff6a9e4daac0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -307,8 +307,8 @@ static bool mt76x02_dfs_check_hw_pulse(struct mt76x02_dev *dev, pulse->period <= 100100); break; case NL80211_DFS_JP: - if (dev->mt76.chandef.chan->center_freq >= 5250 && - dev->mt76.chandef.chan->center_freq <= 5350) { + if (dev->mphy.chandef.chan->center_freq >= 5250 && + dev->mphy.chandef.chan->center_freq <= 5350) { /* JPW53 */ if (pulse->w1 <= 130) ret = (pulse->period >= 28360 && @@ -616,7 +616,7 @@ static void mt76x02_dfs_tasklet(unsigned long arg) u32 engine_mask; int i; - if (test_bit(MT76_SCANNING, &dev->mt76.state)) + if (test_bit(MT76_SCANNING, &dev->mphy.state)) goto out; if (time_is_before_jiffies(dfs_pd->last_sw_check + @@ -702,7 +702,7 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) u8 i, shift; u32 data; - switch (dev->mt76.chandef.width) { + switch (dev->mphy.chandef.width) { case NL80211_CHAN_WIDTH_40: shift = MT_DFS_NUM_ENGINES; break; @@ -722,8 +722,8 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) radar_specs = &etsi_radar_specs[shift]; break; case NL80211_DFS_JP: - if (dev->mt76.chandef.chan->center_freq >= 5250 && - dev->mt76.chandef.chan->center_freq <= 5350) + if (dev->mphy.chandef.chan->center_freq >= 5250 && + dev->mphy.chandef.chan->center_freq <= 5350) radar_specs = &jp_w53_radar_specs[shift]; else radar_specs = &jp_w56_radar_specs[shift]; @@ -822,7 +822,7 @@ EXPORT_SYMBOL_GPL(mt76x02_phy_dfs_adjust_agc); void mt76x02_dfs_init_params(struct mt76x02_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && dev->mt76.region != NL80211_DFS_UNSET) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 4460548f346a..8b072277ea10 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -6,6 +6,7 @@ #include "mt76x02.h" #include "mt76x02_trace.h" +#include "trace.h" void mt76x02_mac_reset_counters(struct mt76x02_dev *dev) { @@ -200,7 +201,7 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mt76.chandef.chan->band; + int band = dev->mphy.chandef.chan->band; u16 val; r = &dev->mt76.hw->wiphy->bands[band]->bitrates[rate->idx]; @@ -344,7 +345,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, u16 txwi_flags = 0; u8 nss; s8 txpwr_adj, max_txpwr_adj; - u8 ccmp_pn[8], nstreams = dev->mt76.chainmask & 0xf; + u8 ccmp_pn[8], nstreams = dev->chainmask & 0xf; memset(txwi, 0, sizeof(*txwi)); @@ -386,7 +387,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); } - txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->mt76.txpower_conf, + txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->txpower_conf, max_txpwr_adj); txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj); @@ -487,17 +488,17 @@ mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, struct mt76x02_sta *msta, first_rate |= st->pktid & MT_PKTID_RATE; mt76x02_mac_process_tx_rate(&rate[0], first_rate, - dev->mt76.chandef.chan->band); + dev->mphy.chandef.chan->band); } else if (rate[0].idx < 0) { if (!msta) return; mt76x02_mac_process_tx_rate(&rate[0], msta->wcid.tx_info, - dev->mt76.chandef.chan->band); + dev->mphy.chandef.chan->band); } mt76x02_mac_process_tx_rate(&last_rate, st->rate, - dev->mt76.chandef.chan->band); + dev->mphy.chandef.chan->band); for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { retry--; @@ -630,7 +631,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, if (!len) goto out; - duration = mt76_calc_tx_airtime(&dev->mt76, &info, len); + duration = ieee80211_calc_tx_airtime(mt76_hw(dev), &info, len); spin_lock_bh(&dev->mt76.cc_lock); dev->tx_airtime += duration; @@ -679,7 +680,7 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev, status->rate_idx = idx; break; case MT_PHY_TYPE_VHT: { - u8 n_rxstream = dev->mt76.chainmask & 0xf; + u8 n_rxstream = dev->chainmask & 0xf; status->encoding = RX_ENC_VHT; status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx); @@ -741,6 +742,8 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr) get_unaligned_le16(dev->mt76.macaddr + 4) | FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */ MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); + /* enable 7 additional beacon slots and control them with bypass mask */ + mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N, 7); for (i = 0; i < 16; i++) mt76x02_mac_set_bssid(dev, i, null_addr); @@ -769,13 +772,13 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, u16 rate = le16_to_cpu(rxwi->rate); u16 tid_sn = le16_to_cpu(rxwi->tid_sn); bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST); - int pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; + int pad_len = 0, nstreams = dev->chainmask & 0xf; s8 signal; u8 pn_len; u8 wcid; int len; - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (!test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) return -EINVAL; if (rxinfo & MT_RXINFO_L2PAD) @@ -824,7 +827,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, if (rxinfo & MT_RXINFO_AMPDU) { status->flag |= RX_FLAG_AMPDU_DETAILS; - status->ampdu_ref = dev->mt76.ampdu_ref; + status->ampdu_ref = dev->ampdu_ref; /* * When receiving an A-MPDU subframe and RSSI info is not valid, @@ -832,8 +835,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, * are coming. The last one will have valid RSSI info */ if (rxinfo & MT_RXINFO_RSSI) { - if (!++dev->mt76.ampdu_ref) - dev->mt76.ampdu_ref++; + if (!++dev->ampdu_ref) + dev->ampdu_ref++; } } @@ -853,8 +856,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, signal = max_t(s8, signal, status->chain_signal[1]); } status->signal = signal; - status->freq = dev->mt76.chandef.chan->center_freq; - status->band = dev->mt76.chandef.chan->band; + status->freq = dev->mphy.chandef.chan->center_freq; + status->band = dev->mphy.chandef.chan->band; status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); @@ -868,7 +871,7 @@ void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq) u8 update = 1; bool ret; - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (!test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) return; trace_mac_txstat_poll(dev); @@ -908,7 +911,7 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, txwi_ptr = mt76_get_txwi_ptr(mdev, e->txwi); txwi = (struct mt76x02_txwi *)txwi_ptr; - trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid); + trace_mac_txdone(mdev, txwi->wcid, txwi->pktid); mt76_tx_complete_skb(mdev, e->skb); } @@ -1018,7 +1021,7 @@ void mt76x02_update_channel(struct mt76_dev *mdev) struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct mt76_channel_state *state; - state = mdev->chan_state; + state = mdev->phy.chan_state; state->cc_busy += mt76_rr(dev, MT_CH_BUSY); spin_lock_bh(&dev->mt76.cc_lock); @@ -1074,7 +1077,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev) dev->ed_silent = 0; if (dev->ed_monitor) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; mt76_clear(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN); @@ -1184,7 +1187,7 @@ void mt76x02_mac_work(struct work_struct *work) void mt76x02_mac_cc_reset(struct mt76x02_dev *dev) { - dev->mt76.survey_time = ktime_get_boottime(); + dev->mphy.survey_time = ktime_get_boottime(); mt76_wr(dev, MT_CH_TIME_CFG, MT_CH_TIME_CFG_TIMER_EN | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 7d946aa77182..c70d17b2290c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -152,7 +152,7 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev) int i; for (i = 0; i < 500; i++) { - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) return false; switch (dev->bus->rr(dev, MAC_CSR0)) { @@ -201,8 +201,7 @@ void mt76x02_mac_work(struct work_struct *work); void mt76x02_mac_cc_reset(struct mt76x02_dev *dev); void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); -int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, - struct sk_buff *skb); +void mt76x02_mac_set_beacon(struct mt76x02_dev *dev, struct sk_buff *skb); void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, struct ieee80211_vif *vif, bool enable); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 6274b6a24b07..5664749ad6c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -24,11 +24,11 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&mdev->mmio.mcu.mutex); + mutex_lock(&mdev->mcu.mutex); - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; if (!seq) - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; tx_info = MT_MCU_MSG_TYPE_CMD | FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) | @@ -65,7 +65,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, } out: - mutex_unlock(&mdev->mmio.mcu.mutex); + mutex_unlock(&mdev->mcu.mutex); return ret; } @@ -141,7 +141,7 @@ int mt76x02_mcu_cleanup(struct mt76x02_dev *dev) mt76_wr(dev, MT_MCU_INT_LEVEL, 1); usleep_range(20000, 30000); - while ((skb = skb_dequeue(&dev->mt76.mmio.mcu.res_q)) != NULL) + while ((skb = skb_dequeue(&dev->mt76.mcu.res_q)) != NULL) dev_kfree_skb(skb); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 4e2371c926d8..c7f028e73b6b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -9,7 +9,7 @@ #include "mt76x02.h" #include "mt76x02_mcu.h" -#include "mt76x02_trace.h" +#include "trace.h" static void mt76x02_pre_tbtt_tasklet(unsigned long arg) { @@ -24,10 +24,17 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) mt76x02_resync_beacon_timer(dev); + /* Prevent corrupt transmissions during update */ + mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff); + dev->beacon_data_count = 0; + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, mt76x02_update_beacon_iter, dev); + mt76_wr(dev, MT_BCN_BYPASS_MASK, + 0xff00 | ~(0xff00 >> dev->beacon_data_count)); + mt76_csa_check(&dev->mt76); if (dev->mt76.csa_complete) @@ -151,7 +158,7 @@ static void mt76x02_tx_tasklet(unsigned long data) mt76x02_mac_poll_tx_status(dev, false); mt76x02_process_tx_status_fifo(dev); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } static int mt76x02_poll_tx(struct napi_struct *napi, int budget) @@ -261,10 +268,10 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) intr = mt76_rr(dev, MT_INT_SOURCE_CSR); mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; - trace_dev_irq(dev, intr, dev->mt76.mmio.irqmask); + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); intr &= dev->mt76.mmio.irqmask; @@ -402,7 +409,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev) lockdep_assert_held(&dev->mt76.mutex); - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); rcu_read_lock(); ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL); @@ -420,6 +427,8 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev) if (!wcid) continue; + rcu_assign_pointer(dev->mt76.wcid[i], NULL); + priv = msta = container_of(wcid, struct mt76x02_sta, wcid); sta = container_of(priv, struct ieee80211_sta, drv_priv); @@ -441,7 +450,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) int i; ieee80211_stop_queues(dev->mt76.hw); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); tasklet_disable(&dev->mt76.tx_tasklet); @@ -476,7 +485,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) if (restart) mt76_mcu_restart(dev); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) + for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) @@ -496,7 +505,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) mutex_unlock(&dev->mt76.mutex); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); tasklet_enable(&dev->mt76.tx_tasklet); napi_enable(&dev->mt76.tx_napi); @@ -514,7 +523,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) ieee80211_restart_hw(dev->mt76.hw); } else { ieee80211_wake_queues(dev->mt76.hw); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } } @@ -535,9 +544,9 @@ static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) restart: mt76x02_watchdog_reset(dev); - mutex_lock(&dev->mt76.mmio.mcu.mutex); + mutex_lock(&dev->mt76.mcu.mutex); dev->mcu_timeout = 0; - mutex_unlock(&dev->mt76.mmio.mcu.mutex); + mutex_unlock(&dev->mt76.mcu.mutex); dev->tx_hang_reset++; dev->tx_hang_check = 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c index d7334267b530..aaadc15ea83c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c @@ -16,7 +16,7 @@ void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev) val = mt76_rr(dev, MT_BBP(AGC, 0)); val &= ~BIT(4); - switch (dev->mt76.chainmask & 0xf) { + switch (dev->chainmask & 0xf) { case 2: val |= BIT(3); break; @@ -35,7 +35,7 @@ void mt76x02_phy_set_txdac(struct mt76x02_dev *dev) { int txpath; - txpath = (dev->mt76.chainmask >> 8) & 0xf; + txpath = (dev->chainmask >> 8) & 0xf; switch (txpath) { case 2: mt76_set(dev, MT_BBP(TXBE, 5), 0x3); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h index fc2e41006a0d..1def25bf735a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h @@ -11,7 +11,7 @@ static inline int mt76x02_get_rssi_gain_thresh(struct mt76x02_dev *dev) { - switch (dev->mt76.chandef.width) { + switch (dev->mphy.chandef.width) { case NL80211_CHAN_WIDTH_80: return -62; case NL80211_CHAN_WIDTH_40: @@ -24,7 +24,7 @@ mt76x02_get_rssi_gain_thresh(struct mt76x02_dev *dev) static inline int mt76x02_get_low_rssi_gain_thresh(struct mt76x02_dev *dev) { - switch (dev->mt76.chandef.width) { + switch (dev->mphy.chandef.width) { case NL80211_CHAN_WIDTH_80: return -76; case NL80211_CHAN_WIDTH_40: diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 21c0f351fa09..3e722276b5c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -235,15 +235,9 @@ #define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n)) #define MT_LED_S1_BASE 0x0780 #define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n)) -#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) -#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \ - MT_LED_STATUS_OFF_MASK) -#define MT_LED_STATUS_ON_MASK GENMASK(23, 16) -#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \ - MT_LED_STATUS_ON_MASK) -#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8) -#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \ - MT_LED_STATUS_DURATION_MASK) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 8) #define MT_FCE_PSE_CTRL 0x0800 #define MT_FCE_PARAMETERS 0x0804 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h index 61ecaf0fe065..6a98092e996b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h @@ -20,7 +20,6 @@ #define DEV_PR_ARG __entry->wiphy_name #define TXID_ENTRY __field(u8, wcid) __field(u8, pktid) -#define TXID_ASSIGN __entry->wcid = wcid; __entry->pktid = pktid #define TXID_PR_FMT " [%d:%d]" #define TXID_PR_ARG __entry->wcid, __entry->pktid @@ -36,28 +35,6 @@ DECLARE_EVENT_CLASS(dev_evt, TP_printk(DEV_PR_FMT, DEV_PR_ARG) ); -DECLARE_EVENT_CLASS(dev_txid_evt, - TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid), - TP_ARGS(dev, wcid, pktid), - TP_STRUCT__entry( - DEV_ENTRY - TXID_ENTRY - ), - TP_fast_assign( - DEV_ASSIGN; - TXID_ASSIGN; - ), - TP_printk( - DEV_PR_FMT TXID_PR_FMT, - DEV_PR_ARG, TXID_PR_ARG - ) -); - -DEFINE_EVENT(dev_txid_evt, mac_txdone_add, - TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid), - TP_ARGS(dev, wcid, pktid) -); - DEFINE_EVENT(dev_evt, mac_txstat_poll, TP_PROTO(struct mt76x02_dev *dev), TP_ARGS(dev) @@ -100,29 +77,6 @@ TRACE_EVENT(mac_txstat_fetch, ) ); -TRACE_EVENT(dev_irq, - TP_PROTO(struct mt76x02_dev *dev, u32 val, u32 mask), - - TP_ARGS(dev, val, mask), - - TP_STRUCT__entry( - DEV_ENTRY - __field(u32, val) - __field(u32, mask) - ), - - TP_fast_assign( - DEV_ASSIGN; - __entry->val = val; - __entry->mask = mask; - ), - - TP_printk( - DEV_PR_FMT " %08x & %08x", - DEV_PR_ARG, __entry->val, __entry->mask - ) -); - #endif #undef TRACE_INCLUDE_PATH diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 13825f642087..96fdf423a348 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -28,7 +28,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, wcid = &mvif->group_wcid; } - mt76_tx(&dev->mt76, control->sta, wcid, skb); + mt76_tx(&dev->mphy, control->sta, wcid, skb); } EXPORT_SYMBOL_GPL(mt76x02_tx); @@ -39,7 +39,6 @@ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, void *rxwi = skb->data; if (q == MT_RXQ_MCU) { - /* this is used just by mmio code */ mt76_mcu_rx_event(&dev->mt76, skb); return; } @@ -74,7 +73,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev, } else if (rate->flags & IEEE80211_TX_RC_MCS) { max_txpwr = dev->mt76.rate_power.ht[rate->idx & 0xf]; } else { - enum nl80211_band band = dev->mt76.chandef.chan->band; + enum nl80211_band band = dev->mphy.chandef.chan->band; if (band == NL80211_BAND_2GHZ) { const struct ieee80211_rate *r; @@ -96,7 +95,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev, s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr, s8 max_txpwr_adj) { - txpwr = min_t(s8, txpwr, dev->mt76.txpower_conf); + txpwr = min_t(s8, txpwr, dev->txpower_conf); txpwr -= (dev->target_power + dev->target_power_delta[0]); txpwr = min_t(s8, txpwr, max_txpwr_adj); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index d03d3c8e296c..0180b6200b17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -46,8 +46,7 @@ EXPORT_SYMBOL_GPL(mt76x02u_mac_start); int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) { - struct sk_buff *iter, *last = skb; - u32 info, pad; + u32 info; /* Buffer layout: * | 4B | xfer len | pad | 4B | @@ -57,28 +56,8 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) */ info = FIELD_PREP(MT_TXD_INFO_LEN, round_up(skb->len, 4)) | FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags; - put_unaligned_le32(info, skb_push(skb, sizeof(info))); - /* Add zero pad of 4 - 7 bytes */ - pad = round_up(skb->len, 4) + 4 - skb->len; - - /* First packet of a A-MSDU burst keeps track of the whole burst - * length, need to update length of it and the last packet. - */ - skb_walk_frags(skb, iter) { - last = iter; - if (!iter->next) { - skb->data_len += pad; - skb->len += pad; - break; - } - } - - if (skb_pad(last, pad)) - return -ENOMEM; - __skb_put(last, pad); - - return 0; + return mt76u_skb_dma_info(skb, info); } int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, @@ -198,7 +177,7 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) container_of(work, struct mt76x02_dev, pre_tbtt_work); struct beacon_bc_data data = {}; struct sk_buff *skb; - int i, nbeacons; + int nbeacons; if (!dev->mt76.beacon_mask) return; @@ -208,17 +187,30 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) mt76x02_resync_beacon_timer(dev); + /* Prevent corrupt transmissions during update */ + mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff); + dev->beacon_data_count = 0; + ieee80211_iterate_active_interfaces(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, mt76x02_update_beacon_iter, dev); + mt76_csa_check(&dev->mt76); + + if (dev->mt76.csa_complete) { + mt76_csa_finish(&dev->mt76); + goto out; + } + nbeacons = hweight8(dev->mt76.beacon_mask); mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons); - for (i = nbeacons; i < N_BCN_SLOTS; i++) { - skb = __skb_dequeue(&data.q); - mt76x02_mac_set_beacon(dev, i, skb); - } + while ((skb = __skb_dequeue(&data.q)) != NULL) + mt76x02_mac_set_beacon(dev, skb); + +out: + mt76_wr(dev, MT_BCN_BYPASS_MASK, + 0xff00 | ~(0xff00 >> dev->beacon_data_count)); mt76x02u_restart_pre_tbtt_timer(dev); } @@ -244,20 +236,11 @@ static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en) static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en) { - int i; - if (WARN_ON_ONCE(!dev->mt76.beacon_int)) return; - if (en) { + if (en) mt76x02u_start_pre_tbtt_timer(dev); - } else { - /* Timer is already stopped, only clean up - * PS buffered frames if any. - */ - for (i = 0; i < N_BCN_SLOTS; i++) - mt76x02_mac_set_beacon(dev, i, NULL); - } } void mt76x02u_init_beacon_config(struct mt76x02_dev *dev) @@ -280,7 +263,7 @@ EXPORT_SYMBOL_GPL(mt76x02u_init_beacon_config); void mt76x02u_exit_beacon_config(struct mt76x02_dev *dev) { - if (!test_bit(MT76_REMOVED, &dev->mt76.state)) + if (!test_bit(MT76_REMOVED, &dev->mphy.state)) mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_SYNC_MODE | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index a993cd7e9948..843b86560ed4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -55,7 +55,8 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) u32 rxfce; for (i = 0; i < 5; i++) { - ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, 300); + ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, + 300, MT_EP_IN_CMD_RESP); if (ret == -ETIMEDOUT) continue; if (ret) @@ -82,18 +83,17 @@ static int __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, bool wait_resp) { - struct mt76_usb *usb = &dev->usb; - int ret; u8 seq = 0; u32 info; + int ret; - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) return 0; if (wait_resp) { - seq = ++usb->mcu.msg_seq & 0xf; + seq = ++dev->mcu.msg_seq & 0xf; if (!seq) - seq = ++usb->mcu.msg_seq & 0xf; + seq = ++dev->mcu.msg_seq & 0xf; } info = FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) | @@ -103,7 +103,8 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, if (ret) return ret; - ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500); + ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500, + MT_EP_OUT_INBAND_CMD); if (ret) return ret; @@ -119,7 +120,6 @@ static int mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, int len, bool wait_resp) { - struct mt76_usb *usb = &dev->usb; struct sk_buff *skb; int err; @@ -127,9 +127,9 @@ mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&usb->mcu.mutex); + mutex_lock(&dev->mcu.mutex); err = __mt76x02u_mcu_send_msg(dev, skb, cmd, wait_resp); - mutex_unlock(&usb->mcu.mutex); + mutex_unlock(&dev->mcu.mutex); return err; } @@ -143,9 +143,8 @@ static int mt76x02u_mcu_wr_rp(struct mt76_dev *dev, u32 base, const struct mt76_reg_pair *data, int n) { - const int CMD_RANDOM_WRITE = 12; const int max_vals_per_cmd = MT_INBAND_PACKET_MAX_LEN / 8; - struct mt76_usb *usb = &dev->usb; + const int CMD_RANDOM_WRITE = 12; struct sk_buff *skb; int cnt, i, ret; @@ -164,9 +163,9 @@ mt76x02u_mcu_wr_rp(struct mt76_dev *dev, u32 base, skb_put_le32(skb, data[i].value); } - mutex_lock(&usb->mcu.mutex); + mutex_lock(&dev->mcu.mutex); ret = __mt76x02u_mcu_send_msg(dev, skb, CMD_RANDOM_WRITE, cnt == n); - mutex_unlock(&usb->mcu.mutex); + mutex_unlock(&dev->mcu.mutex); if (ret) return ret; @@ -200,7 +199,7 @@ mt76x02u_mcu_rd_rp(struct mt76_dev *dev, u32 base, skb_put_le32(skb, data[i].value); } - mutex_lock(&usb->mcu.mutex); + mutex_lock(&dev->mcu.mutex); usb->mcu.rp = data; usb->mcu.rp_len = n; @@ -211,7 +210,7 @@ mt76x02u_mcu_rd_rp(struct mt76_dev *dev, u32 base, usb->mcu.rp = NULL; - mutex_unlock(&usb->mcu.mutex); + mutex_unlock(&dev->mcu.mutex); return ret; } @@ -248,7 +247,8 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data, data_len = MT_CMD_HDR_LEN + len + sizeof(info); - err = mt76u_bulk_msg(&dev->mt76, data, data_len, NULL, 1000); + err = mt76u_bulk_msg(&dev->mt76, data, data_len, NULL, 1000, + MT_EP_OUT_INBAND_CMD); if (err) { dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err); return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 0960fc56b672..b7a120b0856d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -96,9 +96,9 @@ mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on, mt76); u32 val; - val = MT_LED_STATUS_DURATION(0xff) | - MT_LED_STATUS_OFF(delay_off) | - MT_LED_STATUS_ON(delay_on); + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); mt76_wr(dev, MT_LED_S0(mdev->led_pin), val); mt76_wr(dev, MT_LED_S1(mdev->led_pin), val); @@ -166,7 +166,6 @@ void mt76x02_init_device(struct mt76x02_dev *dev) wiphy->reg_notifier = mt76x02_regd_notifier; wiphy->iface_combinations = mt76x02_if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { @@ -182,21 +181,22 @@ void mt76x02_init_device(struct mt76x02_dev *dev) hw->vif_data_size = sizeof(struct mt76x02_vif); ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); dev->mt76.global_wcid.idx = 255; dev->mt76.global_wcid.hw_key_idx = -1; dev->slottime = 9; if (is_mt76x2(dev)) { - dev->mt76.sband_2g.sband.ht_cap.cap |= + dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.ht_cap.cap |= + dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.chainmask = 0x202; - dev->mt76.antenna_mask = 3; + dev->chainmask = 0x202; + dev->mphy.antenna_mask = 3; } else { - dev->mt76.chainmask = 0x101; - dev->mt76.antenna_mask = 1; + dev->chainmask = 0x101; + dev->mphy.antenna_mask = 1; } } EXPORT_SYMBOL_GPL(mt76x02_init_device); @@ -325,7 +325,9 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) if (vif->type == NL80211_IFTYPE_STATION) idx += 8; - if (dev->vif_mask & BIT(idx)) + /* vif is already set or idx is 8 for AP/Mesh/... */ + if (dev->vif_mask & BIT(idx) || + (vif->type != NL80211_IFTYPE_STATION && idx > 7)) return -EBUSY; dev->vif_mask |= BIT(idx); @@ -545,7 +547,7 @@ void mt76x02_set_coverage_class(struct ieee80211_hw *hw, struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); - dev->coverage_class = coverage_class; + dev->coverage_class = max_t(s16, coverage_class, 0); mt76x02_set_tx_ackto(dev); mutex_unlock(&dev->mt76.mutex); } @@ -602,7 +604,7 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw, { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_SCANNING, &dev->mt76.state); + clear_bit(MT76_SCANNING, &dev->mphy.state); if (dev->cal.gain_init_done) { /* Restore AGC gain and resume calibration after scanning. */ dev->cal.low_gain = -1; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile index 7b2b187fbf47..caf089538c11 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile @@ -13,5 +13,3 @@ mt76x2e-y := \ mt76x2u-y := \ usb.o usb_init.o usb_main.o usb_mac.o usb_mcu.o \ usb_phy.o - -CFLAGS_pci_trace.o := -I$(src) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index 9f91556c7f38..4a748a6f0ce2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -248,7 +248,7 @@ mt76x2_get_5g_rx_gain(struct mt76x02_dev *dev, u8 channel) void mt76x2_read_rx_gain(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; int channel = chan->hw_value; s8 lna_5g[3], lna_2g; u8 lna; @@ -455,7 +455,7 @@ EXPORT_SYMBOL_GPL(mt76x2_get_power_info); int mt76x2_get_temp_comp(struct mt76x02_dev *dev, struct mt76x2_temp_comp *t) { - enum nl80211_band band = dev->mt76.chandef.chan->band; + enum nl80211_band band = dev->mphy.chandef.chan->band; u16 val, slope; u8 bounds; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h index 4dcf6518cb0d..3755632e6494 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h @@ -53,7 +53,7 @@ mt76x2_has_ext_lna(struct mt76x02_dev *dev) { u32 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); - if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) + if (dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ) return val & MT_EE_NIC_CONF_1_LNA_EXT_2G; else return val & MT_EE_NIC_CONF_1_LNA_EXT_5G; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index 79e583eb066b..a92a479aebaa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -82,7 +82,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev) { MT_PBF_SYS_CTRL, 0x00080c00 }, { MT_PBF_CFG, 0x1efebcff }, { MT_FCE_PSE_CTRL, 0x00000001 }, - { MT_MAC_SYS_CTRL, 0x0000000c }, + { MT_MAC_SYS_CTRL, 0x00000000 }, { MT_MAX_LEN_CFG, 0x003e3f00 }, { MT_AMPDU_MAX_LEN_20M1S, 0xaaa99887 }, { MT_AMPDU_MAX_LEN_20M2S, 0x000000aa }, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c index 76d8cd37d4de..9635c04ce032 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c @@ -29,7 +29,7 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, .idx = channel, .scan = scan, .bw = bw, - .chainmask = cpu_to_le16(dev->mt76.chainmask), + .chainmask = cpu_to_le16(dev->chainmask), }; /* first set the channel without the extension channel info */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index 41680c420cda..eca95b7f64d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -30,7 +30,7 @@ static inline bool is_mt7612(struct mt76x02_dev *dev) static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; return ((chan->flags & IEEE80211_CHAN_RADAR) && chan->dfs_state != NL80211_DFS_AVAILABLE); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 33fcec9179b2..c69579e5f647 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -239,7 +239,7 @@ static int mt76x2_init_hardware(struct mt76x02_dev *dev) if (ret) return ret; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt76x02_mac_start(dev); ret = mt76x2_mcu_init(dev); @@ -289,8 +289,8 @@ int mt76x2_register_device(struct mt76x02_dev *dev) goto fail; mt76x02_init_debugfs(dev); - mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband); - mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_5g.sband); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index cfe8905ce73f..105e5b99b3f9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -22,7 +22,7 @@ mt76x2_start(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, MT_WATCHDOG_TIME); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -31,7 +31,7 @@ mt76x2_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt76x2_stop_hardware(dev); } @@ -45,9 +45,9 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) tasklet_disable(&dev->dfs_pd.dfs_tasklet); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt76x2_mac_stop(dev, true); ret = mt76x2_phy_set_channel(dev, chandef); @@ -57,13 +57,13 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76x2_mac_resume(dev); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); tasklet_enable(&dev->dfs_pd.dfs_tasklet); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); return ret; } @@ -86,14 +86,14 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->mt76.txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = hw->conf.power_level * 2; /* convert to per-chain power for 2x2 devices */ - dev->mt76.txpower_conf -= 6; + dev->txpower_conf -= 6; - if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) { + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { mt76x2_phy_set_txpower(dev); - mt76x02_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf); + mt76x02_tx_set_txpwr_auto(dev, dev->txpower_conf); } } @@ -124,8 +124,8 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, mutex_lock(&dev->mt76.mutex); - dev->mt76.chainmask = (tx_ant == 3) ? 0x202 : 0x101; - dev->mt76.antenna_mask = tx_ant; + dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101; + dev->mphy.antenna_mask = tx_ant; mt76_set_stream_caps(&dev->mt76, true); mt76x2_phy_set_antenna(dev); @@ -145,6 +145,7 @@ const struct ieee80211_ops mt76x2_ops = { .configure_filter = mt76x02_configure_filter, .bss_info_changed = mt76x02_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .conf_tx = mt76x02_conf_tx, .sw_scan_start = mt76_sw_scan, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 23f35bf8d47b..8831337df23e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -12,7 +12,7 @@ static bool mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u32 flag = 0; if (!mt76x2_tssi_enabled(dev)) @@ -35,7 +35,7 @@ mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev) static void mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; bool is_5ghz = chan->band == NL80211_BAND_5GHZ; if (dev->cal.channel_cal_done) @@ -74,7 +74,7 @@ void mt76x2_phy_set_antenna(struct mt76x02_dev *dev) val = mt76_rr(dev, MT_BBP(AGC, 0)); val &= ~(BIT(4) | BIT(1)); - switch (dev->mt76.antenna_mask) { + switch (dev->mphy.antenna_mask) { case 1: /* disable mac DAC control */ mt76_clear(dev, MT_BBP(IBI, 9), BIT(11)); @@ -118,7 +118,7 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) { struct ieee80211_channel *chan = chandef->chan; - bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); + bool scan = test_bit(MT76_SCANNING, &dev->mphy.state); enum nl80211_band band = chan->band; u8 channel; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index edbab4fa7f6e..ed2dcb05d614 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -136,8 +136,8 @@ mt76x2_get_min_rate_power(struct mt76_rate_power *r) void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) { - enum nl80211_chan_width width = dev->mt76.chandef.width; - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + enum nl80211_chan_width width = dev->mphy.chandef.width; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; struct mt76x2_tx_power_info txp; int txp_0, txp_1, delta = 0; struct mt76_rate_power t = {}; @@ -152,8 +152,8 @@ void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) mt76x2_get_rate_power(dev, &t, chan); mt76x02_add_rate_power_offset(&t, txp.target_power + delta); - mt76x02_limit_rate_power(&t, dev->mt76.txpower_conf); - dev->mt76.txpower_cur = mt76x02_get_max_rate_power(&t); + mt76x02_limit_rate_power(&t, dev->txpower_conf); + dev->mphy.txpower_cur = mt76x02_get_max_rate_power(&t); base_power = mt76x2_get_min_rate_power(&t); delta = base_power - txp.target_power; @@ -202,7 +202,7 @@ EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay); void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; struct mt76x2_tx_power_info txp; struct mt76x2_tssi_comp t = {}; @@ -252,12 +252,12 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) val = 0x1836 << 16; if (!mt76x2_has_ext_lna(dev) && - dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) + dev->mphy.chandef.width >= NL80211_CHAN_WIDTH_40) val = 0x1e42 << 16; if (mt76x2_has_ext_lna(dev) && - dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ && - dev->mt76.chandef.width < NL80211_CHAN_WIDTH_40) + dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ && + dev->mphy.chandef.width < NL80211_CHAN_WIDTH_40) val = 0x0f36 << 16; val |= 0xf8; @@ -267,7 +267,7 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) mt76_wr(dev, MT_BBP(AGC, 9), val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1])); - if (dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) + if (dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR) mt76x02_phy_dfs_adjust_agc(dev); } @@ -280,7 +280,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) int low_gain; u32 val; - dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); if (!dev->cal.avg_rssi_all) dev->cal.avg_rssi_all = -75; @@ -297,7 +297,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) return; } - if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) { + if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) { mt76_wr(dev, MT_BBP(RXO, 14), 0x00560211); val = mt76_rr(dev, MT_BBP(AGC, 26)) & ~0xf; if (low_gain == 2) @@ -315,11 +315,11 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) low_gain_delta = 14; agc_37 = 0x2121262c; - if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) + if (dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ) agc_35 = 0x11111516; else if (low_gain == 2) agc_35 = agc_37 = 0x08080808; - else if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) + else if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) agc_35 = 0x10101014; else agc_35 = 0x11111116; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index b64ad816cc25..eafa283ca699 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -54,7 +54,7 @@ static int mt76x2u_probe(struct usb_interface *intf, usb_set_intfdata(intf, dev); mt76x02u_init_mcu(mdev); - err = mt76u_init(mdev, intf); + err = mt76u_init(mdev, intf, false); if (err < 0) goto err; @@ -86,7 +86,7 @@ static void mt76x2u_disconnect(struct usb_interface *intf) struct mt76x02_dev *dev = usb_get_intfdata(intf); struct ieee80211_hw *hw = mt76_hw(dev); - set_bit(MT76_REMOVED, &dev->mt76.state); + set_bit(MT76_REMOVED, &dev->mphy.state); ieee80211_unregister_hw(hw); mt76x2u_cleanup(dev); mt76u_deinit(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 2910068f4e79..ffc2deba29ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -190,6 +190,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) int mt76x2u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_usb *usb = &dev->mt76.usb; int err; INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate); @@ -199,6 +200,11 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) if (err < 0) return err; + usb->mcu.data = devm_kmalloc(dev->mt76.dev, MCU_RESP_URB_SIZE, + GFP_KERNEL); + if (!usb->mcu.data) + return -ENOMEM; + err = mt76u_alloc_queues(&dev->mt76); if (err < 0) goto fail; @@ -207,22 +213,18 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) if (err < 0) goto fail; + /* check hw sg support in order to enable AMSDU */ + hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1; err = mt76_register_device(&dev->mt76, true, mt76x02_rates, ARRAY_SIZE(mt76x02_rates)); if (err) goto fail; - /* check hw sg support in order to enable AMSDU */ - if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; - else - hw->max_tx_fragments = 1; - - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt76x02_init_debugfs(dev); - mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband); - mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_5g.sband); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index 59cbe826188a..eaa622833f85 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c @@ -98,7 +98,7 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev) bool stopped = false; u32 rts_cfg; - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return -EIO; rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 9e97204841f5..bab4e6e1904e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -17,7 +17,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT_MAC_WORK_INTERVAL); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -26,7 +26,7 @@ static void mt76x2u_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt76u_stop_tx(&dev->mt76); mt76x2u_stop_hw(dev); } @@ -41,9 +41,9 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mt76x02_pre_tbtt_enable(dev, false); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt76x2_mac_stop(dev, false); @@ -52,11 +52,11 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mt76x02_mac_cc_reset(dev); mt76x2_mac_resume(dev); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); mt76x02_pre_tbtt_enable(dev, true); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); return err; } @@ -78,12 +78,12 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->mt76.txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = hw->conf.power_level * 2; /* convert to per-chain power for 2x2 devices */ - dev->mt76.txpower_conf -= 6; + dev->txpower_conf -= 6; - if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) mt76x2_phy_set_txpower(dev); } @@ -105,6 +105,7 @@ const struct ieee80211_ops mt76x2u_ops = { .add_interface = mt76x02_add_interface, .remove_interface = mt76x02_remove_interface, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .ampdu_action = mt76x02_ampdu_action, .config = mt76x2u_config, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index b1381f9df992..a04a98f5ce1e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -10,7 +10,7 @@ static void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; bool is_5ghz = chan->band == NL80211_BAND_5GHZ; if (dev->cal.channel_cal_done) @@ -82,7 +82,7 @@ int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)), }; - bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); + bool scan = test_bit(MT76_SCANNING, &dev->mphy.state); struct ieee80211_channel *chan = chandef->chan; u8 channel = chan->hw_value, bw, bw_index; int ch_group_index, freq, freq1, ret; @@ -185,7 +185,7 @@ int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, struct ieee80211_channel *chan; u32 flag = 0; - chan = dev->mt76.chandef.chan; + chan = dev->mphy.chandef.chan; if (chan->band == NL80211_BAND_5GHZ) flag |= BIT(0); if (mt76x02_ext_pa_enabled(dev, chan->band)) diff --git a/drivers/net/wireless/mediatek/mt76/trace.c b/drivers/net/wireless/mediatek/mt76/trace.c index ed3df3c8b4b3..f199fcd2a63d 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.c +++ b/drivers/net/wireless/mediatek/mt76/trace.c @@ -9,4 +9,7 @@ #define CREATE_TRACE_POINTS #include "trace.h" +EXPORT_TRACEPOINT_SYMBOL_GPL(mac_txdone); +EXPORT_TRACEPOINT_SYMBOL_GPL(dev_irq); + #endif diff --git a/drivers/net/wireless/mediatek/mt76/trace.h b/drivers/net/wireless/mediatek/mt76/trace.h index 0b3e635da868..c3d0ef8e2890 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.h +++ b/drivers/net/wireless/mediatek/mt76/trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEVICE_ASSIGN strlcpy(__entry->wiphy_name, \ wiphy_name(dev->hw->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name @@ -24,6 +24,11 @@ #define REG_PR_FMT " %04x=%08x" #define REG_PR_ARG __entry->reg, __entry->val +#define TXID_ENTRY __field(u8, wcid) __field(u8, pktid) +#define TXID_ASSIGN __entry->wcid = wcid; __entry->pktid = pktid +#define TXID_PR_FMT " [%d:%d]" +#define TXID_PR_ARG __entry->wcid, __entry->pktid + DECLARE_EVENT_CLASS(dev_reg_evt, TP_PROTO(struct mt76_dev *dev, u32 reg, u32 val), TP_ARGS(dev, reg, val), @@ -32,7 +37,7 @@ DECLARE_EVENT_CLASS(dev_reg_evt, REG_ENTRY ), TP_fast_assign( - DEV_ASSIGN; + DEVICE_ASSIGN; REG_ASSIGN; ), TP_printk( @@ -51,6 +56,51 @@ DEFINE_EVENT(dev_reg_evt, reg_wr, TP_ARGS(dev, reg, val) ); +TRACE_EVENT(dev_irq, + TP_PROTO(struct mt76_dev *dev, u32 val, u32 mask), + + TP_ARGS(dev, val, mask), + + TP_STRUCT__entry( + DEV_ENTRY + __field(u32, val) + __field(u32, mask) + ), + + TP_fast_assign( + DEVICE_ASSIGN; + __entry->val = val; + __entry->mask = mask; + ), + + TP_printk( + DEV_PR_FMT " %08x & %08x", + DEV_PR_ARG, __entry->val, __entry->mask + ) +); + +DECLARE_EVENT_CLASS(dev_txid_evt, + TP_PROTO(struct mt76_dev *dev, u8 wcid, u8 pktid), + TP_ARGS(dev, wcid, pktid), + TP_STRUCT__entry( + DEV_ENTRY + TXID_ENTRY + ), + TP_fast_assign( + DEVICE_ASSIGN; + TXID_ASSIGN; + ), + TP_printk( + DEV_PR_FMT TXID_PR_FMT, + DEV_PR_ARG, TXID_PR_ARG + ) +); + +DEFINE_EVENT(dev_txid_evt, mac_txdone, + TP_PROTO(struct mt76_dev *dev, u8 wcid, u8 pktid), + TP_ARGS(dev, wcid, pktid) +); + #endif #undef TRACE_INCLUDE_PATH diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 7ee91d946882..eff522dbda34 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -109,13 +109,17 @@ void mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list) __releases(&dev->status_list.unlock) { + struct ieee80211_hw *hw; struct sk_buff *skb; spin_unlock_bh(&dev->status_list.lock); __release(&dev->status_list.unlock); - while ((skb = __skb_dequeue(list)) != NULL) - ieee80211_tx_status(dev->hw, skb); + while ((skb = __skb_dequeue(list)) != NULL) { + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_tx_status(hw, skb); + } + } EXPORT_SYMBOL_GPL(mt76_tx_status_unlock); @@ -231,10 +235,12 @@ EXPORT_SYMBOL_GPL(mt76_tx_status_check); void mt76_tx_complete_skb(struct mt76_dev *dev, struct sk_buff *skb) { + struct ieee80211_hw *hw; struct sk_buff_head list; if (!skb->prev) { - ieee80211_free_txskb(dev->hw, skb); + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); return; } @@ -245,13 +251,15 @@ void mt76_tx_complete_skb(struct mt76_dev *dev, struct sk_buff *skb) EXPORT_SYMBOL_GPL(mt76_tx_complete_skb); void -mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, +mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb) { + struct mt76_dev *dev = phy->dev; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct mt76_queue *q; int qid = skb_get_queue_mapping(skb); + bool ext_phy = phy != &dev->phy; if (WARN_ON(qid >= MT_TXQ_PSD)) { qid = MT_TXQ_BE; @@ -275,6 +283,9 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, mt76_check_agg_ssn(mtxq, skb); } + if (ext_phy) + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + q = dev->q_tx[qid].q; spin_lock_bh(&q->lock); @@ -282,7 +293,7 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, dev->queue_ops->kick(dev, q); if (q->queued > q->ndesc - 8 && !q->stopped) { - ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb)); + ieee80211_stop_queue(phy->hw, skb_get_queue_mapping(skb)); q->stopped = true; } @@ -291,9 +302,11 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, EXPORT_SYMBOL_GPL(mt76_tx); static struct sk_buff * -mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps) +mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq, bool ps) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); + struct ieee80211_tx_info *info; + bool ext_phy = phy != &phy->dev->phy; struct sk_buff *skb; skb = skb_dequeue(&mtxq->retry_q); @@ -306,10 +319,14 @@ mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps) return skb; } - skb = ieee80211_tx_dequeue(dev->hw, txq); + skb = ieee80211_tx_dequeue(phy->hw, txq); if (!skb) return NULL; + info = IEEE80211_SKB_CB(skb); + if (ext_phy) + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + return skb; } @@ -335,7 +352,8 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, enum ieee80211_frame_release_type reason, bool more_data) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; struct sk_buff *last_skb = NULL; struct mt76_queue *hwq = dev->q_tx[MT_TXQ_PSD].q; int i; @@ -350,7 +368,7 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, continue; do { - skb = mt76_txq_dequeue(dev, mtxq, true); + skb = mt76_txq_dequeue(phy, mtxq, true); if (!skb) break; @@ -377,9 +395,10 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, EXPORT_SYMBOL_GPL(mt76_release_buffered_frames); static int -mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, +mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_sw_queue *sq, struct mt76_txq *mtxq) { + struct mt76_dev *dev = phy->dev; struct ieee80211_txq *txq = mtxq_to_txq(mtxq); enum mt76_txq_id qid = mt76_txq_get_qid(txq); struct mt76_wcid *wcid = mtxq->wcid; @@ -395,7 +414,7 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) return 0; - skb = mt76_txq_dequeue(dev, mtxq, false); + skb = mt76_txq_dequeue(phy, mtxq, false); if (!skb) return 0; @@ -423,10 +442,10 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, if (probe) break; - if (test_bit(MT76_RESET, &dev->state)) + if (test_bit(MT76_RESET, &phy->state)) return -EBUSY; - skb = mt76_txq_dequeue(dev, mtxq, false); + skb = mt76_txq_dequeue(phy, mtxq, false); if (!skb) break; @@ -464,8 +483,9 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, } static int -mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) +mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) { + struct mt76_dev *dev = phy->dev; struct mt76_sw_queue *sq = &dev->q_tx[qid]; struct mt76_queue *hwq = sq->q; struct ieee80211_txq *txq; @@ -478,12 +498,12 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) if (sq->swq_queued >= 4) break; - if (test_bit(MT76_RESET, &dev->state)) { + if (test_bit(MT76_RESET, &phy->state)) { ret = -EBUSY; break; } - txq = ieee80211_next_txq(dev->hw, qid); + txq = ieee80211_next_txq(phy->hw, qid); if (!txq) break; @@ -505,8 +525,8 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) spin_lock_bh(&hwq->lock); } - ret += mt76_txq_send_burst(dev, sq, mtxq); - ieee80211_return_txq(dev->hw, txq, + ret += mt76_txq_send_burst(phy, sq, mtxq); + ieee80211_return_txq(phy->hw, txq, !skb_queue_empty(&mtxq->retry_q)); } spin_unlock_bh(&hwq->lock); @@ -514,8 +534,9 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) return ret; } -void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid) +void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid) { + struct mt76_dev *dev = phy->dev; struct mt76_sw_queue *sq = &dev->q_tx[qid]; int len; @@ -528,21 +549,21 @@ void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid) rcu_read_lock(); do { - ieee80211_txq_schedule_start(dev->hw, qid); - len = mt76_txq_schedule_list(dev, qid); - ieee80211_txq_schedule_end(dev->hw, qid); + ieee80211_txq_schedule_start(phy->hw, qid); + len = mt76_txq_schedule_list(phy, qid); + ieee80211_txq_schedule_end(phy->hw, qid); } while (len > 0); rcu_read_unlock(); } EXPORT_SYMBOL_GPL(mt76_txq_schedule); -void mt76_txq_schedule_all(struct mt76_dev *dev) +void mt76_txq_schedule_all(struct mt76_phy *phy) { int i; for (i = 0; i <= MT_TXQ_BK; i++) - mt76_txq_schedule(dev, i); + mt76_txq_schedule(phy, i); } EXPORT_SYMBOL_GPL(mt76_txq_schedule_all); @@ -550,7 +571,9 @@ void mt76_tx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; - mt76_txq_schedule_all(dev); + mt76_txq_schedule_all(&dev->phy); + if (dev->phy2) + mt76_txq_schedule_all(dev->phy2); } void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, @@ -578,9 +601,10 @@ EXPORT_SYMBOL_GPL(mt76_stop_tx_queues); void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) + if (!test_bit(MT76_STATE_RUNNING, &phy->state)) return; tasklet_schedule(&dev->tx_tasklet); @@ -589,6 +613,7 @@ EXPORT_SYMBOL_GPL(mt76_wake_tx_queue); void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq) { + struct ieee80211_hw *hw; struct mt76_txq *mtxq; struct sk_buff *skb; @@ -597,8 +622,10 @@ void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq) mtxq = (struct mt76_txq *)txq->drv_priv; - while ((skb = skb_dequeue(&mtxq->retry_q)) != NULL) - ieee80211_free_txskb(dev->hw, skb); + while ((skb = skb_dequeue(&mtxq->retry_q)) != NULL) { + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); + } } EXPORT_SYMBOL_GPL(mt76_txq_remove); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index d6d47081e281..36ba81d63f12 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -29,13 +29,13 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, pipe = (req_type & USB_DIR_IN) ? usb_rcvctrlpipe(udev, 0) : usb_sndctrlpipe(udev, 0); for (i = 0; i < MT_VEND_REQ_MAX_RETRY; i++) { - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) return -EIO; ret = usb_control_msg(udev, pipe, req, req_type, val, offset, buf, len, MT_VEND_REQ_TOUT_MS); if (ret == -ENODEV) - set_bit(MT76_REMOVED, &dev->state); + set_bit(MT76_REMOVED, &dev->phy.state); if (ret >= 0 || ret == -ENODEV) return ret; usleep_range(5000, 10000); @@ -62,12 +62,25 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, } EXPORT_SYMBOL_GPL(mt76u_vendor_request); -static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) +static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u32 addr) { struct mt76_usb *usb = &dev->usb; u32 data = ~0; - u16 offset; int ret; + + ret = __mt76u_vendor_request(dev, req, + USB_DIR_IN | USB_TYPE_VENDOR, + addr >> 16, addr, &usb->reg_val, + sizeof(__le32)); + if (ret == sizeof(__le32)) + data = le32_to_cpu(usb->reg_val); + trace_usb_reg_rr(dev, addr, data); + + return data; +} + +static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) +{ u8 req; switch (addr & MT_VEND_TYPE_MASK) { @@ -81,16 +94,8 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) req = MT_VEND_MULTI_READ; break; } - offset = addr & ~MT_VEND_TYPE_MASK; - ret = __mt76u_vendor_request(dev, req, - USB_DIR_IN | USB_TYPE_VENDOR, - 0, offset, &usb->reg_val, sizeof(__le32)); - if (ret == sizeof(__le32)) - data = le32_to_cpu(usb->reg_val); - trace_usb_reg_rr(dev, addr, data); - - return data; + return ___mt76u_rr(dev, req, addr & ~MT_VEND_TYPE_MASK); } static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) @@ -104,10 +109,32 @@ static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) return ret; } -static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) +static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void ___mt76u_wr(struct mt76_dev *dev, u8 req, + u32 addr, u32 val) { struct mt76_usb *usb = &dev->usb; - u16 offset; + + usb->reg_val = cpu_to_le32(val); + __mt76u_vendor_request(dev, req, + USB_DIR_OUT | USB_TYPE_VENDOR, + addr >> 16, addr, &usb->reg_val, + sizeof(__le32)); + trace_usb_reg_wr(dev, addr, val); +} + +static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ u8 req; switch (addr & MT_VEND_TYPE_MASK) { @@ -118,13 +145,7 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) req = MT_VEND_MULTI_WRITE; break; } - offset = addr & ~MT_VEND_TYPE_MASK; - - usb->reg_val = cpu_to_le32(val); - __mt76u_vendor_request(dev, req, - USB_DIR_OUT | USB_TYPE_VENDOR, 0, - offset, &usb->reg_val, sizeof(__le32)); - trace_usb_reg_wr(dev, addr, val); + ___mt76u_wr(dev, req, addr & ~MT_VEND_TYPE_MASK, val); } static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) @@ -134,6 +155,13 @@ static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) mutex_unlock(&dev->usb.usb_ctrl_mtx); } +static void mt76u_wr_ext(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val) { @@ -145,22 +173,94 @@ static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, return val; } +static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr, + u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} + static void mt76u_copy(struct mt76_dev *dev, u32 offset, const void *data, int len) { struct mt76_usb *usb = &dev->usb; - const u32 *val = data; - int i, ret; + const u8 *val = data; + int ret; + int current_batch_size; + int i = 0; + + /* Assure that always a multiple of 4 bytes are copied, + * otherwise beacons can be corrupted. + * See: "mt76: round up length on mt76_wr_copy" + * Commit 850e8f6fbd5d0003b0 + */ + len = round_up(len, 4); mutex_lock(&usb->usb_ctrl_mtx); - for (i = 0; i < DIV_ROUND_UP(len, 4); i++) { - put_unaligned(val[i], (u32 *)usb->data); + while (i < len) { + current_batch_size = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, current_batch_size); ret = __mt76u_vendor_request(dev, MT_VEND_MULTI_WRITE, USB_DIR_OUT | USB_TYPE_VENDOR, - 0, offset + i * 4, usb->data, - sizeof(u32)); + 0, offset + i, usb->data, + current_batch_size); if (ret < 0) break; + + i += current_batch_size; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + +static void mt76u_copy_ext(struct mt76_dev *dev, u32 offset, + const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + +static void +mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset, + void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int i = 0, batch_len, ret; + u8 *val = data; + + len = round_up(len, 4); + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + ret = __mt76u_vendor_request(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + memcpy(val + i, usb->data, batch_len); + i += batch_len; } mutex_unlock(&usb->usb_ctrl_mtx); } @@ -200,7 +300,7 @@ static int mt76u_wr_rp(struct mt76_dev *dev, u32 base, const struct mt76_reg_pair *data, int n) { - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->state)) + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) return dev->mcu_ops->mcu_wr_rp(dev, base, data, n); else return mt76u_req_wr_rp(dev, base, data, n); @@ -227,7 +327,7 @@ static int mt76u_rd_rp(struct mt76_dev *dev, u32 base, struct mt76_reg_pair *data, int n) { - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->state)) + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) return dev->mcu_ops->mcu_rd_rp(dev, base, data, n); else return mt76u_req_rd_rp(dev, base, data, n); @@ -306,11 +406,12 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, } static int -mt76u_refill_rx(struct mt76_dev *dev, struct urb *urb, int nsgs, gfp_t gfp) +mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, + struct urb *urb, int nsgs, gfp_t gfp) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN]; - if (dev->usb.sg_en) + if (qid == MT_RXQ_MAIN && dev->usb.sg_en) return mt76u_fill_rx_sg(dev, q, urb, nsgs, gfp); urb->transfer_buffer_length = q->buf_size; @@ -334,23 +435,25 @@ mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e, usb_init_urb(e->urb); - if (dev->usb.sg_en) + if (dev->usb.sg_en && sg_max_size > 0) e->urb->sg = (struct scatterlist *)(e->urb + 1); return 0; } static int -mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) +mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue *q, + struct mt76_queue_entry *e) { - int err; + enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN]; + int err, sg_size; - err = mt76u_urb_alloc(dev, e, MT_RX_SG_MAX_SIZE); + sg_size = qid == MT_RXQ_MAIN ? MT_RX_SG_MAX_SIZE : 0; + err = mt76u_urb_alloc(dev, e, sg_size); if (err) return err; - return mt76u_refill_rx(dev, e->urb, MT_RX_SG_MAX_SIZE, - GFP_KERNEL); + return mt76u_refill_rx(dev, q, e->urb, sg_size, GFP_KERNEL); } static void mt76u_urb_free(struct urb *urb) @@ -386,10 +489,9 @@ mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, urb->context = context; } -static inline struct urb * -mt76u_get_next_rx_entry(struct mt76_dev *dev) +static struct urb * +mt76u_get_next_rx_entry(struct mt76_queue *q) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; struct urb *urb = NULL; unsigned long flags; @@ -404,14 +506,17 @@ mt76u_get_next_rx_entry(struct mt76_dev *dev) return urb; } -static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) +static int +mt76u_get_rx_entry_len(struct mt76_dev *dev, u8 *data, + u32 data_len) { u16 dma_len, min_len; dma_len = get_unaligned_le16(data); - min_len = MT_DMA_HDR_LEN + MT_RX_RXWI_LEN + - MT_FCE_INFO_LEN; + if (dev->drv->drv_flags & MT_DRV_RX_DMA_HDR) + return dma_len; + min_len = MT_DMA_HDR_LEN + MT_RX_RXWI_LEN + MT_FCE_INFO_LEN; if (data_len < min_len || !dma_len || dma_len + MT_DMA_HDR_LEN > data_len || (dma_len & 0x3)) @@ -420,11 +525,14 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) } static struct sk_buff * -mt76u_build_rx_skb(void *data, int len, int buf_size) +mt76u_build_rx_skb(struct mt76_dev *dev, void *data, + int len, int buf_size) { + int head_room, drv_flags = dev->drv->drv_flags; struct sk_buff *skb; - if (SKB_WITH_OVERHEAD(buf_size) < MT_DMA_HDR_LEN + len) { + head_room = drv_flags & MT_DRV_RX_DMA_HDR ? 0 : MT_DMA_HDR_LEN; + if (SKB_WITH_OVERHEAD(buf_size) < head_room + len) { struct page *page; /* slow path, not enough space for data and @@ -434,8 +542,8 @@ mt76u_build_rx_skb(void *data, int len, int buf_size) if (!skb) return NULL; - skb_put_data(skb, data + MT_DMA_HDR_LEN, MT_SKB_HEAD_LEN); - data += (MT_DMA_HDR_LEN + MT_SKB_HEAD_LEN); + skb_put_data(skb, data + head_room, MT_SKB_HEAD_LEN); + data += head_room + MT_SKB_HEAD_LEN; page = virt_to_head_page(data); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, data - page_address(page), @@ -449,30 +557,31 @@ mt76u_build_rx_skb(void *data, int len, int buf_size) if (!skb) return NULL; - skb_reserve(skb, MT_DMA_HDR_LEN); + skb_reserve(skb, head_room); __skb_put(skb, len); return skb; } static int -mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) +mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, + int buf_size) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer; int data_len = urb->num_sgs ? urb->sg[0].length : urb->actual_length; - int len, nsgs = 1; + int len, nsgs = 1, head_room, drv_flags = dev->drv->drv_flags; struct sk_buff *skb; - if (!test_bit(MT76_STATE_INITIALIZED, &dev->state)) + if (!test_bit(MT76_STATE_INITIALIZED, &dev->phy.state)) return 0; - len = mt76u_get_rx_entry_len(data, urb->actual_length); + len = mt76u_get_rx_entry_len(dev, data, urb->actual_length); if (len < 0) return 0; - data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN); - skb = mt76u_build_rx_skb(data, data_len, q->buf_size); + head_room = drv_flags & MT_DRV_RX_DMA_HDR ? 0 : MT_DMA_HDR_LEN; + data_len = min_t(int, len, data_len - head_room); + skb = mt76u_build_rx_skb(dev, data, data_len, buf_size); if (!skb) return 0; @@ -481,8 +590,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) data_len = min_t(int, len, urb->sg[nsgs].length); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, sg_page(&urb->sg[nsgs]), - urb->sg[nsgs].offset, - data_len, q->buf_size); + urb->sg[nsgs].offset, data_len, + buf_size); len -= data_len; nsgs++; } @@ -493,8 +602,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) static void mt76u_complete_rx(struct urb *urb) { - struct mt76_dev *dev = urb->context; - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_dev *dev = dev_get_drvdata(&urb->dev->dev); + struct mt76_queue *q = urb->context; unsigned long flags; trace_rx_urb(dev, urb); @@ -524,50 +633,62 @@ static void mt76u_complete_rx(struct urb *urb) } static int -mt76u_submit_rx_buf(struct mt76_dev *dev, struct urb *urb) +mt76u_submit_rx_buf(struct mt76_dev *dev, enum mt76_rxq_id qid, + struct urb *urb) { - mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, urb, - mt76u_complete_rx, dev); + int ep = qid == MT_RXQ_MAIN ? MT_EP_IN_PKT_RX : MT_EP_IN_CMD_RESP; + + mt76u_fill_bulk_urb(dev, USB_DIR_IN, ep, urb, + mt76u_complete_rx, &dev->q_rx[qid]); trace_submit_urb(dev, urb); return usb_submit_urb(urb, GFP_ATOMIC); } -static void mt76u_rx_tasklet(unsigned long data) +static void +mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) { - struct mt76_dev *dev = (struct mt76_dev *)data; + int qid = q - &dev->q_rx[MT_RXQ_MAIN]; struct urb *urb; int err, count; - rcu_read_lock(); - while (true) { - urb = mt76u_get_next_rx_entry(dev); + urb = mt76u_get_next_rx_entry(q); if (!urb) break; - count = mt76u_process_rx_entry(dev, urb); + count = mt76u_process_rx_entry(dev, urb, q->buf_size); if (count > 0) { - err = mt76u_refill_rx(dev, urb, count, GFP_ATOMIC); + err = mt76u_refill_rx(dev, q, urb, count, GFP_ATOMIC); if (err < 0) break; } - mt76u_submit_rx_buf(dev, urb); + mt76u_submit_rx_buf(dev, qid, urb); } - mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); + if (qid == MT_RXQ_MAIN) + mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); +} +static void mt76u_rx_tasklet(unsigned long data) +{ + struct mt76_dev *dev = (struct mt76_dev *)data; + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + + rcu_read_lock(); + mt76u_process_rx_queue(dev, q); rcu_read_unlock(); } -static int mt76u_submit_rx_buffers(struct mt76_dev *dev) +static int +mt76u_submit_rx_buffers(struct mt76_dev *dev, enum mt76_rxq_id qid) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_queue *q = &dev->q_rx[qid]; unsigned long flags; int i, err = 0; spin_lock_irqsave(&q->lock, flags); for (i = 0; i < q->ndesc; i++) { - err = mt76u_submit_rx_buf(dev, q->entry[i].urb); + err = mt76u_submit_rx_buf(dev, qid, q->entry[i].urb); if (err < 0) break; } @@ -578,16 +699,12 @@ static int mt76u_submit_rx_buffers(struct mt76_dev *dev) return err; } -static int mt76u_alloc_rx(struct mt76_dev *dev) +static int +mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) { - struct mt76_usb *usb = &dev->usb; - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_queue *q = &dev->q_rx[qid]; int i, err; - usb->mcu.data = devm_kmalloc(dev->dev, MCU_RESP_URB_SIZE, GFP_KERNEL); - if (!usb->mcu.data) - return -ENOMEM; - spin_lock_init(&q->lock); q->entry = devm_kcalloc(dev->dev, MT_NUM_RX_ENTRIES, sizeof(*q->entry), @@ -599,17 +716,23 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) q->buf_size = PAGE_SIZE; for (i = 0; i < q->ndesc; i++) { - err = mt76u_rx_urb_alloc(dev, &q->entry[i]); + err = mt76u_rx_urb_alloc(dev, q, &q->entry[i]); if (err < 0) return err; } - return mt76u_submit_rx_buffers(dev); + return mt76u_submit_rx_buffers(dev, qid); } -static void mt76u_free_rx(struct mt76_dev *dev) +int mt76u_alloc_mcu_queue(struct mt76_dev *dev) +{ + return mt76u_alloc_rx_queue(dev, MT_RXQ_MCU); +} +EXPORT_SYMBOL_GPL(mt76u_alloc_mcu_queue); + +static void +mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; struct page *page; int i; @@ -624,13 +747,33 @@ static void mt76u_free_rx(struct mt76_dev *dev) memset(&q->rx_page, 0, sizeof(q->rx_page)); } -void mt76u_stop_rx(struct mt76_dev *dev) +static void mt76u_free_rx(struct mt76_dev *dev) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_queue *q; int i; - for (i = 0; i < q->ndesc; i++) - usb_poison_urb(q->entry[i].urb); + for (i = 0; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; + if (!q->ndesc) + continue; + + mt76u_free_rx_queue(dev, q); + } +} + +void mt76u_stop_rx(struct mt76_dev *dev) +{ + struct mt76_queue *q; + int i, j; + + for (i = 0; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; + if (!q->ndesc) + continue; + + for (j = 0; j < q->ndesc; j++) + usb_poison_urb(q->entry[j].urb); + } tasklet_kill(&dev->usb.rx_tasklet); } @@ -638,13 +781,24 @@ EXPORT_SYMBOL_GPL(mt76u_stop_rx); int mt76u_resume_rx(struct mt76_dev *dev) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int i; + struct mt76_queue *q; + int i, j, err; - for (i = 0; i < q->ndesc; i++) - usb_unpoison_urb(q->entry[i].urb); + for (i = 0; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; - return mt76u_submit_rx_buffers(dev); + if (!q->ndesc) + continue; + + for (j = 0; j < q->ndesc; j++) + usb_unpoison_urb(q->entry[j].urb); + + err = mt76u_submit_rx_buffers(dev, i); + if (err < 0) + return err; + } + + return 0; } EXPORT_SYMBOL_GPL(mt76u_resume_rx); @@ -694,10 +848,11 @@ static void mt76u_tx_tasklet(unsigned long data) spin_unlock_bh(&q->lock); - mt76_txq_schedule(dev, i); + mt76_txq_schedule(&dev->phy, i); - if (!test_and_set_bit(MT76_READING_STATS, &dev->state)) - queue_work(dev->usb.stat_wq, &dev->usb.stat_work); + if (dev->drv->tx_status_data && + !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) + queue_work(dev->usb.wq, &dev->usb.stat_work); if (wake) ieee80211_wake_queue(dev->hw, i); } @@ -714,7 +869,7 @@ static void mt76u_tx_status_data(struct work_struct *work) dev = container_of(usb, struct mt76_dev, usb); while (true) { - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) break; if (!dev->drv->tx_status_data(dev, &update)) @@ -722,10 +877,10 @@ static void mt76u_tx_status_data(struct work_struct *work) count++; } - if (count && test_bit(MT76_STATE_RUNNING, &dev->state)) - queue_work(usb->stat_wq, &usb->stat_work); + if (count && test_bit(MT76_STATE_RUNNING, &dev->phy.state)) + queue_work(usb->wq, &usb->stat_work); else - clear_bit(MT76_READING_STATS, &dev->state); + clear_bit(MT76_READING_STATS, &dev->phy.state); } static void mt76u_complete_tx(struct urb *urb) @@ -759,6 +914,35 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, return urb->num_sgs; } +int mt76u_skb_dma_info(struct sk_buff *skb, u32 info) +{ + struct sk_buff *iter, *last = skb; + u32 pad; + + put_unaligned_le32(info, skb_push(skb, sizeof(info))); + /* Add zero pad of 4 - 7 bytes */ + pad = round_up(skb->len, 4) + 4 - skb->len; + + /* First packet of a A-MSDU burst keeps track of the whole burst + * length, need to update length of it and the last packet. + */ + skb_walk_frags(skb, iter) { + last = iter; + if (!iter->next) { + skb->data_len += pad; + skb->len += pad; + break; + } + } + + if (skb_pad(last, pad)) + return -ENOMEM; + __skb_put(last, pad); + + return 0; +} +EXPORT_SYMBOL_GPL(mt76u_skb_dma_info); + static int mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, @@ -806,7 +990,7 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { if (err == -ENODEV) - set_bit(MT76_REMOVED, &dev->state); + set_bit(MT76_REMOVED, &dev->phy.state); else dev_err(dev->dev, "tx urb submit failed:%d\n", err); @@ -816,6 +1000,14 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) } } +static u8 mt76u_ac_to_hwq(struct mt76_dev *dev, u8 ac) +{ + if (mt76_chip(dev) == 0x7663) + return ac ^ 0x3; + + return mt76_ac_to_hwq(ac); +} + static int mt76u_alloc_tx(struct mt76_dev *dev) { struct mt76_queue *q; @@ -834,7 +1026,7 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) return -ENOMEM; spin_lock_init(&q->lock); - q->hw_idx = mt76_ac_to_hwq(i); + q->hw_idx = mt76u_ac_to_hwq(dev, i); dev->q_tx[i].q = q; q->entry = devm_kcalloc(dev->dev, @@ -872,7 +1064,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) struct mt76_queue *q; int i, j, ret; - ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(dev), + ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy), HZ / 5); if (!ret) { dev_err(dev->dev, "timed out waiting for pending tx\n"); @@ -905,7 +1097,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) } cancel_work_sync(&dev->usb.stat_work); - clear_bit(MT76_READING_STATS, &dev->state); + clear_bit(MT76_READING_STATS, &dev->phy.state); mt76_tx_status_check(dev, NULL, true); } @@ -925,7 +1117,7 @@ int mt76u_alloc_queues(struct mt76_dev *dev) { int err; - err = mt76u_alloc_rx(dev); + err = mt76u_alloc_rx_queue(dev, MT_RXQ_MAIN); if (err < 0) return err; @@ -938,14 +1130,20 @@ static const struct mt76_queue_ops usb_queue_ops = { .kick = mt76u_tx_kick, }; -int mt76u_init(struct mt76_dev *dev, - struct usb_interface *intf) +void mt76u_deinit(struct mt76_dev *dev) { - static const struct mt76_bus_ops mt76u_ops = { - .rr = mt76u_rr, - .wr = mt76u_wr, - .rmw = mt76u_rmw, - .write_copy = mt76u_copy, + if (dev->usb.wq) { + destroy_workqueue(dev->usb.wq); + dev->usb.wq = NULL; + } +} +EXPORT_SYMBOL_GPL(mt76u_deinit); + +int mt76u_init(struct mt76_dev *dev, + struct usb_interface *intf, bool ext) +{ + static struct mt76_bus_ops mt76u_ops = { + .read_copy = mt76u_read_copy_ext, .wr_rp = mt76u_wr_rp, .rd_rp = mt76u_rd_rp, .type = MT76_BUS_USB, @@ -953,16 +1151,28 @@ int mt76u_init(struct mt76_dev *dev, struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; + mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr; + mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr; + mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw; + mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy; + tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev); tasklet_init(&dev->tx_tasklet, mt76u_tx_tasklet, (unsigned long)dev); INIT_WORK(&usb->stat_work, mt76u_tx_status_data); - skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]); - usb->stat_wq = alloc_workqueue("mt76u", WQ_UNBOUND, 0); - if (!usb->stat_wq) + usb->wq = alloc_workqueue("mt76u", WQ_UNBOUND, 0); + if (!usb->wq) return -ENOMEM; - mutex_init(&usb->mcu.mutex); + usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); + if (usb->data_len < 32) + usb->data_len = 32; + + usb->data = devm_kmalloc(dev->dev, usb->data_len, GFP_KERNEL); + if (!usb->data) { + mt76u_deinit(dev); + return -ENOMEM; + } mutex_init(&usb->usb_ctrl_mtx); dev->bus = &mt76u_ops; @@ -976,14 +1186,5 @@ int mt76u_init(struct mt76_dev *dev, } EXPORT_SYMBOL_GPL(mt76u_init); -void mt76u_deinit(struct mt76_dev *dev) -{ - if (dev->usb.stat_wq) { - destroy_workqueue(dev->usb.stat_wq); - dev->usb.stat_wq = NULL; - } -} -EXPORT_SYMBOL_GPL(mt76u_deinit); - MODULE_AUTHOR("Lorenzo Bianconi "); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 23d1e1da78b2..8c60c450125a 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -64,7 +64,7 @@ int mt76_wcid_alloc(unsigned long *mask, int size) } EXPORT_SYMBOL_GPL(mt76_wcid_alloc); -int mt76_get_min_avg_rssi(struct mt76_dev *dev) +int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) { struct mt76_wcid *wcid; int i, j, min_rssi = 0; @@ -75,14 +75,18 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev) for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { unsigned long mask = dev->wcid_mask[i]; + unsigned long phy_mask = dev->wcid_phy_mask[i]; if (!mask) continue; - for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { + for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1, phy_mask >>= 1) { if (!(mask & 1)) continue; + if (!!(phy_mask & 1) != ext_phy) + continue; + wcid = rcu_dereference(dev->wcid[j]); if (!wcid) continue; diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h index fe3479c8e561..48a71e7479e5 100644 --- a/drivers/net/wireless/mediatek/mt76/util.h +++ b/drivers/net/wireless/mediatek/mt76/util.h @@ -16,8 +16,20 @@ int mt76_wcid_alloc(unsigned long *mask, int size); +static inline bool +mt76_wcid_mask_test(unsigned long *mask, int idx) +{ + return mask[idx / BITS_PER_LONG] & BIT(idx % BITS_PER_LONG); +} + static inline void -mt76_wcid_free(unsigned long *mask, int idx) +mt76_wcid_mask_set(unsigned long *mask, int idx) +{ + mask[idx / BITS_PER_LONG] |= BIT(idx % BITS_PER_LONG); +} + +static inline void +mt76_wcid_mask_clear(unsigned long *mask, int idx) { mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG); } diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 8849faa5bc10..73d5014a4234 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -248,7 +248,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, goto error_del_vif; } - if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) { + if (qtnf_hwcap_is_set(&mac->bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) { ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); if (ret) { unregister_netdevice(vif->netdev); @@ -739,7 +739,6 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_supported_band *sband; const struct cfg80211_chan_def *chandef = &wdev->chandef; struct ieee80211_channel *chan; - struct qtnf_chan_stats stats; int ret; sband = wiphy->bands[NL80211_BAND_2GHZ]; @@ -755,49 +754,16 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; chan = &sband->channels[idx]; - memset(&stats, 0, sizeof(stats)); - survey->channel = chan; survey->filled = 0x0; - if (chandef->chan) { - if (chan->hw_value == chandef->chan->hw_value) - survey->filled = SURVEY_INFO_IN_USE; - } + if (chan == chandef->chan) + survey->filled = SURVEY_INFO_IN_USE; - ret = qtnf_cmd_get_chan_stats(mac, chan->hw_value, &stats); - switch (ret) { - case 0: - if (unlikely(stats.chan_num != chan->hw_value)) { - pr_err("received stats for channel %d instead of %d\n", - stats.chan_num, chan->hw_value); - ret = -EINVAL; - break; - } - - survey->filled |= SURVEY_INFO_TIME | - SURVEY_INFO_TIME_SCAN | - SURVEY_INFO_TIME_BUSY | - SURVEY_INFO_TIME_RX | - SURVEY_INFO_TIME_TX | - SURVEY_INFO_NOISE_DBM; - - survey->time_scan = stats.cca_try; - survey->time = stats.cca_try; - survey->time_tx = stats.cca_tx; - survey->time_rx = stats.cca_rx; - survey->time_busy = stats.cca_busy; - survey->noise = stats.chan_noise; - break; - case -ENOENT: - pr_debug("no stats for channel %u\n", chan->hw_value); - ret = 0; - break; - default: + ret = qtnf_cmd_get_chan_stats(mac, chan->center_freq, survey); + if (ret) pr_debug("failed to get chan(%d) stats from card\n", chan->hw_value); - break; - } return ret; } @@ -1080,10 +1046,10 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus) struct wiphy *wiphy; if (qtnf_dfs_offload_get() && - (bus->hw_info.hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) + qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_DFS_OFFLOAD)) qtn_cfg80211_ops.start_radar_detection = NULL; - if (!(bus->hw_info.hw_capab & QLINK_HW_CAPAB_PWR_MGMT)) + if (!qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_PWR_MGMT)) qtn_cfg80211_ops.set_power_mgmt = NULL; wiphy = wiphy_new(&qtn_cfg80211_ops, sizeof(struct qtnf_wmac)); @@ -1142,7 +1108,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->coverage_class = macinfo->coverage_class; wiphy->max_scan_ssids = - (hw_info->max_scan_ssids) ? hw_info->max_scan_ssids : 1; + (macinfo->max_scan_ssids) ? macinfo->max_scan_ssids : 1; wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN; wiphy->mgmt_stypes = qtnf_mgmt_stypes; wiphy->max_remain_on_channel_duration = 5000; @@ -1166,10 +1132,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; if (qtnf_dfs_offload_get() && - (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) + qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_DFS_OFFLOAD)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD); - if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SCAN_DWELL)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); @@ -1185,16 +1151,16 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) ether_addr_copy(wiphy->perm_addr, mac->macaddr); - if (hw_info->hw_capab & QLINK_HW_CAPAB_STA_INACT_TIMEOUT) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_STA_INACT_TIMEOUT)) wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; - if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)) wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; - if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN)) + if (!qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_OBSS_SCAN)) wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN; - if (hw_info->hw_capab & QLINK_HW_CAPAB_SAE) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SAE)) wiphy->features |= NL80211_FEATURE_SAE; #ifdef CONFIG_PM @@ -1205,7 +1171,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) regdomain_is_known = isalpha(mac->rd->alpha2[0]) && isalpha(mac->rd->alpha2[1]); - if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) { + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_REG_UPDATE)) { wiphy->reg_notifier = qtnf_cfg80211_reg_notifier; if (mac->rd->alpha2[0] == '9' && mac->rd->alpha2[1] == '9') { diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index d0d7ec8794c4..ccc1e06dfcf6 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -11,11 +11,11 @@ #include "bus.h" #include "commands.h" +/* Let device itself to select best values for current conditions */ #define QTNF_SCAN_TIME_AUTO 0 -/* Let device itself to select best values for current conditions */ -#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT QTNF_SCAN_TIME_AUTO -#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT QTNF_SCAN_TIME_AUTO +#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT 90 +#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT 100 #define QTNF_SCAN_SAMPLE_DURATION_DEFAULT QTNF_SCAN_TIME_AUTO static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp, @@ -175,7 +175,8 @@ static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type, { struct qlink_tlv_ie_set *tlv; - tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len); + tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + + round_up(len, QLINK_ALIGN)); tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET); tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr)); tlv->type = frame_type; @@ -190,20 +191,24 @@ static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif, { unsigned int len = sizeof(struct qlink_cmd_start_ap); - len += s->ssid_len; - len += s->beacon.head_len; - len += s->beacon.tail_len; - len += s->beacon.beacon_ies_len; - len += s->beacon.proberesp_ies_len; - len += s->beacon.assocresp_ies_len; - len += s->beacon.probe_resp_len; + len += round_up(s->ssid_len, QLINK_ALIGN); + len += round_up(s->beacon.head_len, QLINK_ALIGN); + len += round_up(s->beacon.tail_len, QLINK_ALIGN); + len += round_up(s->beacon.beacon_ies_len, QLINK_ALIGN); + len += round_up(s->beacon.proberesp_ies_len, QLINK_ALIGN); + len += round_up(s->beacon.assocresp_ies_len, QLINK_ALIGN); + len += round_up(s->beacon.probe_resp_len, QLINK_ALIGN); if (cfg80211_chandef_valid(&s->chandef)) len += sizeof(struct qlink_tlv_chandef); - if (s->acl) + if (s->acl) { + unsigned int acl_len = struct_size(s->acl, mac_addrs, + s->acl->n_acl_entries); + len += sizeof(struct qlink_tlv_hdr) + - struct_size(s->acl, mac_addrs, s->acl->n_acl_entries); + round_up(acl_len, QLINK_ALIGN); + } if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) { pr_err("VIF%u.%u: can not fit AP settings: %u\n", @@ -315,7 +320,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, if (s->ht_cap) { struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *) - skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->ht_cap)); + skb_put(cmd_skb, sizeof(*tlv) + + round_up(sizeof(*s->ht_cap), QLINK_ALIGN)); tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); tlv->len = cpu_to_le16(sizeof(*s->ht_cap)); @@ -339,7 +345,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, size_t acl_size = struct_size(s->acl, mac_addrs, s->acl->n_acl_entries); struct qlink_tlv_hdr *tlv = - skb_put(cmd_skb, sizeof(*tlv) + acl_size); + skb_put(cmd_skb, + sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN)); tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA); tlv->len = cpu_to_le16(acl_size); @@ -581,10 +588,10 @@ qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst, } static void -qtnf_cmd_sta_info_parse(struct station_info *sinfo, - const struct qlink_tlv_hdr *tlv, +qtnf_cmd_sta_info_parse(struct station_info *sinfo, const u8 *data, size_t resp_size) { + const struct qlink_tlv_hdr *tlv; const struct qlink_sta_stats *stats = NULL; const u8 *map = NULL; unsigned int map_len = 0; @@ -595,11 +602,11 @@ qtnf_cmd_sta_info_parse(struct station_info *sinfo, (qtnf_utils_is_bit_set(map, bitn, map_len) && \ (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len)) - while (resp_size >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, data, resp_size) { tlv_len = le16_to_cpu(tlv->len); switch (le16_to_cpu(tlv->type)) { - case QTN_TLV_ID_STA_STATS_MAP: + case QTN_TLV_ID_BITMAP: map_len = tlv_len; map = tlv->val; break; @@ -610,9 +617,11 @@ qtnf_cmd_sta_info_parse(struct station_info *sinfo, default: break; } + } - resp_size -= tlv_len + sizeof(*tlv); - tlv = (const struct qlink_tlv_hdr *)(tlv->val + tlv_len); + if (!qlink_tlv_parsing_ok(tlv, data, resp_size)) { + pr_err("Malformed TLV buffer\n"); + return; } if (!map || !stats) @@ -736,9 +745,7 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac, goto out; } - qtnf_cmd_sta_info_parse(sinfo, - (const struct qlink_tlv_hdr *)resp->info, - var_resp_len); + qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len); out: qtnf_bus_unlock(vif->mac->bus); @@ -895,31 +902,21 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, const char *uboot_ver = NULL; u32 hw_ver = 0; u16 tlv_type; - u16 tlv_value_len; + u16 tlv_len; hwinfo->num_mac = resp->num_mac; hwinfo->mac_bitmap = resp->mac_bitmap; hwinfo->fw_ver = le32_to_cpu(resp->fw_ver); - hwinfo->ql_proto_ver = le16_to_cpu(resp->ql_proto_ver); hwinfo->total_tx_chain = resp->total_tx_chain; hwinfo->total_rx_chain = resp->total_rx_chain; - hwinfo->hw_capab = le32_to_cpu(resp->hw_capab); bld_tmstamp = le32_to_cpu(resp->bld_tmstamp); plat_id = le32_to_cpu(resp->plat_id); hw_ver = le32_to_cpu(resp->hw_ver); - tlv = (const struct qlink_tlv_hdr *)resp->info; - - while (info_len >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, resp->info, info_len) { tlv_type = le16_to_cpu(tlv->type); - tlv_value_len = le16_to_cpu(tlv->len); - - if (tlv_value_len + sizeof(*tlv) > info_len) { - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_value_len); - return -EINVAL; - } + tlv_len = le16_to_cpu(tlv->len); switch (tlv_type) { case QTN_TLV_ID_BUILD_NAME: @@ -943,36 +940,43 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, case QTN_TLV_ID_UBOOT_VER: uboot_ver = (const void *)tlv->val; break; - case QTN_TLV_ID_MAX_SCAN_SSIDS: - hwinfo->max_scan_ssids = *tlv->val; + case QTN_TLV_ID_BITMAP: + memcpy(hwinfo->hw_capab, tlv->val, + min(sizeof(hwinfo->hw_capab), (size_t)tlv_len)); break; default: break; } - - info_len -= tlv_value_len + sizeof(*tlv); - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - pr_info("fw_version=%d, MACs map %#x, chains Tx=%u Rx=%u, capab=0x%x\n", - hwinfo->fw_ver, hwinfo->mac_bitmap, - hwinfo->total_tx_chain, hwinfo->total_rx_chain, - hwinfo->hw_capab); + if (!qlink_tlv_parsing_ok(tlv, resp->info, info_len)) { + pr_err("Malformed TLV buffer\n"); + return -EINVAL; + } - pr_info("\nBuild name: %s" \ - "\nBuild revision: %s" \ - "\nBuild type: %s" \ - "\nBuild label: %s" \ - "\nBuild timestamp: %lu" \ - "\nPlatform ID: %lu" \ - "\nHardware ID: %s" \ - "\nCalibration version: %s" \ - "\nU-Boot version: %s" \ - "\nHardware version: 0x%08x\n", + pr_info("\nBuild name: %s\n" + "Build revision: %s\n" + "Build type: %s\n" + "Build label: %s\n" + "Build timestamp: %lu\n" + "Platform ID: %lu\n" + "Hardware ID: %s\n" + "Calibration version: %s\n" + "U-Boot version: %s\n" + "Hardware version: 0x%08x\n" + "Qlink ver: %u.%u\n" + "MACs map: %#x\n" + "Chains Rx-Tx: %ux%u\n" + "FW version: 0x%x\n", bld_name, bld_rev, bld_type, bld_label, (unsigned long)bld_tmstamp, (unsigned long)plat_id, - hw_id, calibration_ver, uboot_ver, hw_ver); + hw_id, calibration_ver, uboot_ver, hw_ver, + QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver), + QLINK_VER_MINOR(bus->hw_info.ql_proto_ver), + hwinfo->mac_bitmap, + hwinfo->total_rx_chain, hwinfo->total_tx_chain, + hwinfo->fw_ver); strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version)); hwinfo->hw_version = hw_ver; @@ -1016,18 +1020,15 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, const struct qlink_resp_get_mac_info *resp, size_t tlv_buf_size) { - const u8 *tlv_buf = resp->var_info; - struct ieee80211_iface_combination *comb = NULL; + struct ieee80211_iface_combination *comb = mac->macinfo.if_comb; size_t n_comb = 0; struct ieee80211_iface_limit *limits; - const struct qlink_iface_comb_num *comb_num; const struct qlink_iface_limit_record *rec; const struct qlink_iface_limit *lim; const struct qlink_wowlan_capab_data *wowlan; u16 rec_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; u8 *ext_capa = NULL; u8 *ext_capa_mask = NULL; @@ -1066,44 +1067,11 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, break; } - tlv = (const struct qlink_tlv_hdr *)tlv_buf; - while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) { + qlink_for_each_tlv(tlv, resp->var_info, tlv_buf_size) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - if (tlv_full_len > tlv_buf_size) { - pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n", - mac->macid, tlv_type, tlv_value_len); - return -EINVAL; - } switch (tlv_type) { - case QTN_TLV_ID_NUM_IFACE_COMB: - if (tlv_value_len != sizeof(*comb_num)) - return -EINVAL; - - comb_num = (void *)tlv->val; - - /* free earlier iface comb memory */ - qtnf_mac_iface_comb_free(mac); - - mac->macinfo.n_if_comb = - le32_to_cpu(comb_num->iface_comb_num); - - mac->macinfo.if_comb = - kcalloc(mac->macinfo.n_if_comb, - sizeof(*mac->macinfo.if_comb), - GFP_KERNEL); - - if (!mac->macinfo.if_comb) - return -ENOMEM; - - comb = mac->macinfo.if_comb; - - pr_debug("MAC%u: %zu iface combinations\n", - mac->macid, mac->macinfo.n_if_comb); - - break; case QTN_TLV_ID_IFACE_LIMIT: if (unlikely(!comb)) { pr_warn("MAC%u: no combinations advertised\n", @@ -1207,14 +1175,10 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, mac->macid, tlv_type); break; } - - tlv_buf_size -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (tlv_buf_size) { - pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n", - mac->macid, tlv_buf_size); + if (!qlink_tlv_parsing_ok(tlv, resp->var_info, tlv_buf_size)) { + pr_err("Malformed TLV buffer\n"); return -EINVAL; } @@ -1260,13 +1224,15 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, return 0; } -static void +static int qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, const struct qlink_resp_get_mac_info *resp_info) { struct qtnf_mac_info *mac_info; struct qtnf_vif *vif; + qtnf_mac_iface_comb_free(mac); + mac_info = &mac->macinfo; mac_info->bands_cap = resp_info->bands_cap; @@ -1285,12 +1251,28 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, mac_info->radar_detect_widths = qlink_chan_width_mask_to_nl(le16_to_cpu( resp_info->radar_detect_widths)); - mac_info->max_acl_mac_addrs = le32_to_cpu(resp_info->max_acl_mac_addrs); + mac_info->max_acl_mac_addrs = le16_to_cpu(resp_info->max_acl_mac_addrs); + mac_info->frag_thr = le32_to_cpu(resp_info->frag_threshold); + mac_info->rts_thr = le32_to_cpu(resp_info->rts_threshold); + mac_info->sretry_limit = resp_info->retry_short; + mac_info->lretry_limit = resp_info->retry_long; + mac_info->coverage_class = resp_info->coverage_class; + mac_info->max_scan_ssids = resp_info->max_scan_ssids; memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask, sizeof(mac_info->ht_cap_mod_mask)); memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask, sizeof(mac_info->vht_cap_mod_mask)); + + mac_info->n_if_comb = resp_info->n_iface_combinations; + mac_info->if_comb = kcalloc(mac->macinfo.n_if_comb, + sizeof(*mac->macinfo.if_comb), + GFP_KERNEL); + + if (!mac->macinfo.if_comb) + return -ENOMEM; + + return 0; } static void qtnf_cmd_resp_band_fill_htcap(const u8 *info, @@ -1389,7 +1371,6 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, size_t payload_len) { u16 tlv_type; - size_t tlv_len; size_t tlv_dlen; const struct qlink_tlv_hdr *tlv; const struct qlink_channel *qchan; @@ -1424,24 +1405,15 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, return -ENOMEM; } - tlv = (struct qlink_tlv_hdr *)resp->info; - - while (payload_len >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, resp->info, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_dlen = le16_to_cpu(tlv->len); - tlv_len = tlv_dlen + sizeof(*tlv); - - if (tlv_len > payload_len) { - pr_warn("malformed TLV 0x%.2X; LEN: %zu\n", - tlv_type, tlv_len); - goto error_ret; - } switch (tlv_type) { case QTN_TLV_ID_CHANNEL: if (unlikely(tlv_dlen != sizeof(*qchan))) { pr_err("invalid channel TLV len %zu\n", - tlv_len); + tlv_dlen); goto error_ret; } @@ -1544,13 +1516,10 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, pr_warn("unknown TLV type: %#x\n", tlv_type); break; } - - payload_len -= tlv_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_dlen); } - if (payload_len) { - pr_err("malformed TLV buf; bytes left: %zu\n", payload_len); + if (!qlink_tlv_parsing_ok(tlv, resp->info, payload_len)) { + pr_err("Malformed TLV buffer\n"); goto error_ret; } @@ -1570,128 +1539,6 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, return ret; } -static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac, - const u8 *payload, size_t payload_len) -{ - struct qtnf_mac_info *mac_info; - struct qlink_tlv_frag_rts_thr *phy_thr; - struct qlink_tlv_rlimit *limit; - struct qlink_tlv_cclass *class; - u16 tlv_type; - u16 tlv_value_len; - size_t tlv_full_len; - const struct qlink_tlv_hdr *tlv; - - mac_info = &mac->macinfo; - - tlv = (struct qlink_tlv_hdr *)payload; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { - tlv_type = le16_to_cpu(tlv->type); - tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (tlv_full_len > payload_len) { - pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n", - mac->macid, tlv_type, tlv_value_len); - return -EINVAL; - } - - switch (tlv_type) { - case QTN_TLV_ID_FRAG_THRESH: - phy_thr = (void *)tlv; - mac_info->frag_thr = le32_to_cpu(phy_thr->thr); - break; - case QTN_TLV_ID_RTS_THRESH: - phy_thr = (void *)tlv; - mac_info->rts_thr = le32_to_cpu(phy_thr->thr); - break; - case QTN_TLV_ID_SRETRY_LIMIT: - limit = (void *)tlv; - mac_info->sretry_limit = limit->rlimit; - break; - case QTN_TLV_ID_LRETRY_LIMIT: - limit = (void *)tlv; - mac_info->lretry_limit = limit->rlimit; - break; - case QTN_TLV_ID_COVERAGE_CLASS: - class = (void *)tlv; - mac_info->coverage_class = class->cclass; - break; - default: - pr_err("MAC%u: Unknown TLV type: %#x\n", mac->macid, - le16_to_cpu(tlv->type)); - break; - } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); - } - - if (payload_len) { - pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n", - mac->macid, payload_len); - return -EINVAL; - } - - return 0; -} - -static int -qtnf_cmd_resp_proc_chan_stat_info(struct qtnf_chan_stats *stats, - const u8 *payload, size_t payload_len) -{ - struct qlink_chan_stats *qlink_stats; - const struct qlink_tlv_hdr *tlv; - size_t tlv_full_len; - u16 tlv_value_len; - u16 tlv_type; - - tlv = (struct qlink_tlv_hdr *)payload; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { - tlv_type = le16_to_cpu(tlv->type); - tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - if (tlv_full_len > payload_len) { - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_value_len); - return -EINVAL; - } - switch (tlv_type) { - case QTN_TLV_ID_CHANNEL_STATS: - if (unlikely(tlv_value_len != sizeof(*qlink_stats))) { - pr_err("invalid CHANNEL_STATS entry size\n"); - return -EINVAL; - } - - qlink_stats = (void *)tlv->val; - - stats->chan_num = le32_to_cpu(qlink_stats->chan_num); - stats->cca_tx = le32_to_cpu(qlink_stats->cca_tx); - stats->cca_rx = le32_to_cpu(qlink_stats->cca_rx); - stats->cca_busy = le32_to_cpu(qlink_stats->cca_busy); - stats->cca_try = le32_to_cpu(qlink_stats->cca_try); - stats->chan_noise = qlink_stats->chan_noise; - - pr_debug("chan(%u) try(%u) busy(%u) noise(%d)\n", - stats->chan_num, stats->cca_try, - stats->cca_busy, stats->chan_noise); - break; - default: - pr_warn("Unknown TLV type: %#x\n", - le16_to_cpu(tlv->type)); - } - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); - } - - if (payload_len) { - pr_warn("malformed TLV buf; bytes left: %zu\n", payload_len); - return -EINVAL; - } - - return 0; -} - int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) { struct sk_buff *cmd_skb, *resp_skb = NULL; @@ -1712,7 +1559,10 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) goto out; resp = (const struct qlink_resp_get_mac_info *)resp_skb->data; - qtnf_cmd_resp_proc_mac_info(mac, resp); + ret = qtnf_cmd_resp_proc_mac_info(mac, resp); + if (ret) + goto out; + ret = qtnf_parse_variable_mac_info(mac, resp, var_data_len); out: @@ -1793,35 +1643,6 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac, return ret; } -int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac) -{ - struct sk_buff *cmd_skb, *resp_skb = NULL; - struct qlink_resp_phy_params *resp; - size_t response_size = 0; - int ret = 0; - - cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, - QLINK_CMD_PHY_PARAMS_GET, - sizeof(struct qlink_cmd)); - if (!cmd_skb) - return -ENOMEM; - - qtnf_bus_lock(mac->bus); - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, - sizeof(*resp), &response_size); - if (ret) - goto out; - - resp = (struct qlink_resp_phy_params *)resp_skb->data; - ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size); - -out: - qtnf_bus_unlock(mac->bus); - consume_skb(resp_skb); - - return ret; -} - int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) { struct wiphy *wiphy = priv_to_wiphy(mac); @@ -1843,16 +1664,16 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH, wiphy->rts_threshold); if (changed & WIPHY_PARAM_COVERAGE_CLASS) - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, - wiphy->coverage_class); + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, + wiphy->coverage_class); if (changed & WIPHY_PARAM_RETRY_LONG) - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT, - wiphy->retry_long); + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT, + wiphy->retry_long); if (changed & WIPHY_PARAM_RETRY_SHORT) - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT, - wiphy->retry_short); + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT, + wiphy->retry_short); ret = qtnf_cmd_send(mac->bus, cmd_skb); if (ret) @@ -1866,23 +1687,35 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) int qtnf_cmd_send_init_fw(struct qtnf_bus *bus) { + struct sk_buff *resp_skb = NULL; + struct qlink_resp_init_fw *resp; + struct qlink_cmd_init_fw *cmd; struct sk_buff *cmd_skb; - int ret = 0; + size_t info_len = 0; + int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, QLINK_CMD_FW_INIT, - sizeof(struct qlink_cmd)); + sizeof(*cmd)); if (!cmd_skb) return -ENOMEM; + cmd = (struct qlink_cmd_init_fw *)cmd_skb->data; + cmd->qlink_proto_ver = cpu_to_le32(QLINK_PROTO_VER); + qtnf_bus_lock(bus); - ret = qtnf_cmd_send(bus, cmd_skb); + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, + sizeof(*resp), &info_len); + qtnf_bus_unlock(bus); + if (ret) goto out; -out: - qtnf_bus_unlock(bus); + resp = (struct qlink_resp_init_fw *)resp_skb->data; + bus->hw_info.ql_proto_ver = le32_to_cpu(resp->qlink_proto_ver); +out: + consume_skb(resp_skb); return ret; } @@ -2178,108 +2011,90 @@ static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb, memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN); } -static void qtnf_cmd_scan_set_dwell(struct qtnf_wmac *mac, - struct sk_buff *cmd_skb) -{ - struct cfg80211_scan_request *scan_req = mac->scan_req; - u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT; - u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT; - u16 duration = QTNF_SCAN_SAMPLE_DURATION_DEFAULT; - - if (scan_req->duration) { - dwell_active = scan_req->duration; - dwell_passive = scan_req->duration; - } - - pr_debug("MAC%u: %s scan dwell active=%u, passive=%u, duration=%u\n", - mac->macid, - scan_req->duration_mandatory ? "mandatory" : "max", - dwell_active, dwell_passive, duration); - - qtnf_cmd_skb_put_tlv_u16(cmd_skb, - QTN_TLV_ID_SCAN_DWELL_ACTIVE, - dwell_active); - qtnf_cmd_skb_put_tlv_u16(cmd_skb, - QTN_TLV_ID_SCAN_DWELL_PASSIVE, - dwell_passive); - qtnf_cmd_skb_put_tlv_u16(cmd_skb, - QTN_TLV_ID_SCAN_SAMPLE_DURATION, - duration); -} - int qtnf_cmd_send_scan(struct qtnf_wmac *mac) { - struct sk_buff *cmd_skb; - struct ieee80211_channel *sc; struct cfg80211_scan_request *scan_req = mac->scan_req; - int n_channels; - int count = 0; + u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT; + u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT; + struct wireless_dev *wdev = scan_req->wdev; + struct ieee80211_channel *sc; + struct qlink_cmd_scan *cmd; + struct sk_buff *cmd_skb; + int n_channels = 0; + u64 flags = 0; + int count; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, QLINK_CMD_SCAN, - sizeof(struct qlink_cmd)); + sizeof(*cmd)); if (!cmd_skb) return -ENOMEM; - qtnf_bus_lock(mac->bus); + cmd = (struct qlink_cmd_scan *)cmd_skb->data; - if (scan_req->n_ssids != 0) { - while (count < scan_req->n_ssids) { - qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, - scan_req->ssids[count].ssid, - scan_req->ssids[count].ssid_len); - count++; - } + if (scan_req->duration) { + dwell_active = scan_req->duration; + dwell_passive = scan_req->duration; + } else if (wdev->iftype == NL80211_IFTYPE_STATION && + wdev->current_bss) { + /* let device select dwell based on traffic conditions */ + dwell_active = QTNF_SCAN_TIME_AUTO; + dwell_passive = QTNF_SCAN_TIME_AUTO; + } + + cmd->n_ssids = cpu_to_le16(scan_req->n_ssids); + for (count = 0; count < scan_req->n_ssids; ++count) { + qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, + scan_req->ssids[count].ssid, + scan_req->ssids[count].ssid_len); } if (scan_req->ie_len != 0) qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ, scan_req->ie, scan_req->ie_len); - if (scan_req->n_channels) { - n_channels = scan_req->n_channels; - count = 0; + for (count = 0; count < scan_req->n_channels; ++count) { + sc = scan_req->channels[count]; + if (sc->flags & IEEE80211_CHAN_DISABLED) + continue; - while (n_channels != 0) { - sc = scan_req->channels[count]; - if (sc->flags & IEEE80211_CHAN_DISABLED) { - n_channels--; - continue; - } + pr_debug("[MAC%u] scan chan=%d, freq=%d, flags=%#x\n", + mac->macid, sc->hw_value, sc->center_freq, + sc->flags); - pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n", - mac->macid, sc->hw_value, sc->center_freq, - sc->flags); - - qtnf_cmd_channel_tlv_add(cmd_skb, sc); - n_channels--; - count++; - } + qtnf_cmd_channel_tlv_add(cmd_skb, sc); + ++n_channels; } - qtnf_cmd_scan_set_dwell(mac, cmd_skb); + if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) + flags |= QLINK_SCAN_FLAG_FLUSH; + + if (scan_req->duration_mandatory) + flags |= QLINK_SCAN_FLAG_DURATION_MANDATORY; + + cmd->n_channels = cpu_to_le16(n_channels); + cmd->active_dwell = cpu_to_le16(dwell_active); + cmd->passive_dwell = cpu_to_le16(dwell_passive); + cmd->sample_duration = cpu_to_le16(QTNF_SCAN_SAMPLE_DURATION_DEFAULT); + cmd->flags = cpu_to_le64(flags); + + pr_debug("[MAC%u] %s scan dwell active=%u passive=%u duration=%u\n", + mac->macid, + scan_req->duration_mandatory ? "mandatory" : "max", + dwell_active, dwell_passive, + QTNF_SCAN_SAMPLE_DURATION_DEFAULT); if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { - pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n", + pr_debug("[MAC%u] scan with random addr=%pM, mask=%pM\n", mac->macid, scan_req->mac_addr, scan_req->mac_addr_mask); - qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr, scan_req->mac_addr_mask); } - if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) { - pr_debug("MAC%u: flush cache before scan\n", mac->macid); - - qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH); - } - + qtnf_bus_lock(mac->bus); ret = qtnf_cmd_send(mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(mac->bus); return ret; @@ -2552,8 +2367,91 @@ int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, return ret; } -int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, - struct qtnf_chan_stats *stats) +static int +qtnf_cmd_resp_proc_chan_stat_info(struct survey_info *survey, + const u8 *payload, size_t payload_len) +{ + const struct qlink_chan_stats *stats = NULL; + const struct qlink_tlv_hdr *tlv; + u16 tlv_value_len; + u16 tlv_type; + const u8 *map = NULL; + unsigned int map_len = 0; + unsigned int stats_len = 0; + + qlink_for_each_tlv(tlv, payload, payload_len) { + tlv_type = le16_to_cpu(tlv->type); + tlv_value_len = le16_to_cpu(tlv->len); + + switch (tlv_type) { + case QTN_TLV_ID_BITMAP: + map = tlv->val; + map_len = tlv_value_len; + break; + case QTN_TLV_ID_CHANNEL_STATS: + stats = (struct qlink_chan_stats *)tlv->val; + stats_len = tlv_value_len; + break; + default: + pr_info("Unknown TLV type: %#x\n", tlv_type); + break; + } + } + + if (!qlink_tlv_parsing_ok(tlv, payload, payload_len)) { + pr_err("Malformed TLV buffer\n"); + return -EINVAL; + } + + if (!map || !stats) + return 0; + +#define qtnf_chan_stat_avail(stat_name, bitn) \ + (qtnf_utils_is_bit_set(map, bitn, map_len) && \ + (offsetofend(struct qlink_chan_stats, stat_name) <= stats_len)) + + if (qtnf_chan_stat_avail(time_on, QLINK_CHAN_STAT_TIME_ON)) { + survey->filled |= SURVEY_INFO_TIME; + survey->time = le64_to_cpu(stats->time_on); + } + + if (qtnf_chan_stat_avail(time_tx, QLINK_CHAN_STAT_TIME_TX)) { + survey->filled |= SURVEY_INFO_TIME_TX; + survey->time_tx = le64_to_cpu(stats->time_tx); + } + + if (qtnf_chan_stat_avail(time_rx, QLINK_CHAN_STAT_TIME_RX)) { + survey->filled |= SURVEY_INFO_TIME_RX; + survey->time_rx = le64_to_cpu(stats->time_rx); + } + + if (qtnf_chan_stat_avail(cca_busy, QLINK_CHAN_STAT_CCA_BUSY)) { + survey->filled |= SURVEY_INFO_TIME_BUSY; + survey->time_busy = le64_to_cpu(stats->cca_busy); + } + + if (qtnf_chan_stat_avail(cca_busy_ext, QLINK_CHAN_STAT_CCA_BUSY_EXT)) { + survey->filled |= SURVEY_INFO_TIME_EXT_BUSY; + survey->time_ext_busy = le64_to_cpu(stats->cca_busy_ext); + } + + if (qtnf_chan_stat_avail(time_scan, QLINK_CHAN_STAT_TIME_SCAN)) { + survey->filled |= SURVEY_INFO_TIME_SCAN; + survey->time_scan = le64_to_cpu(stats->time_scan); + } + + if (qtnf_chan_stat_avail(chan_noise, QLINK_CHAN_STAT_CHAN_NOISE)) { + survey->filled |= SURVEY_INFO_NOISE_DBM; + survey->noise = stats->chan_noise; + } + +#undef qtnf_chan_stat_avail + + return 0; +} + +int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u32 chan_freq, + struct survey_info *survey) { struct sk_buff *cmd_skb, *resp_skb = NULL; struct qlink_cmd_get_chan_stats *cmd; @@ -2567,22 +2465,30 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, if (!cmd_skb) return -ENOMEM; - qtnf_bus_lock(mac->bus); - cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data; - cmd->channel = cpu_to_le16(channel); + cmd->channel_freq = cpu_to_le32(chan_freq); + qtnf_bus_lock(mac->bus); ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, sizeof(*resp), &var_data_len); + qtnf_bus_unlock(mac->bus); + if (ret) goto out; resp = (struct qlink_resp_get_chan_stats *)resp_skb->data; - ret = qtnf_cmd_resp_proc_chan_stat_info(stats, resp->info, + + if (le32_to_cpu(resp->chan_freq) != chan_freq) { + pr_err("[MAC%u] channel stats freq %u != requested %u\n", + mac->macid, le32_to_cpu(resp->chan_freq), chan_freq); + ret = -EINVAL; + goto out; + } + + ret = qtnf_cmd_resp_proc_chan_stat_info(survey, resp->info, var_data_len); out: - qtnf_bus_unlock(mac->bus); consume_skb(resp_skb); return ret; @@ -2595,6 +2501,7 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, struct qlink_cmd_chan_switch *cmd; struct sk_buff *cmd_skb; int ret; + u64 flags = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid, QLINK_CMD_CHAN_SWITCH, @@ -2602,19 +2509,19 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, if (!cmd_skb) return -ENOMEM; - qtnf_bus_lock(mac->bus); + if (params->radar_required) + flags |= QLINK_CHAN_SW_RADAR_REQUIRED; + + if (params->block_tx) + flags |= QLINK_CHAN_SW_BLOCK_TX; cmd = (struct qlink_cmd_chan_switch *)cmd_skb->data; - cmd->channel = cpu_to_le16(params->chandef.chan->hw_value); - cmd->radar_required = params->radar_required; - cmd->block_tx = params->block_tx; + qlink_chandef_cfg2q(¶ms->chandef, &cmd->channel); + cmd->flags = cpu_to_le64(flags); cmd->beacon_count = params->count; + qtnf_bus_lock(mac->bus); ret = qtnf_cmd_send(mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(mac->bus); return ret; @@ -2695,7 +2602,7 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif, if (!cmd_skb) return -ENOMEM; - tlv = skb_put(cmd_skb, sizeof(*tlv) + acl_size); + tlv = skb_put(cmd_skb, sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN)); tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA); tlv->len = cpu_to_le16(acl_size); qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val); diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index ab273257b078..9db695101d28 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -59,8 +59,8 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up); int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, bool slave_radar, bool dfs_offload); -int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, - struct qtnf_chan_stats *stats); +int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u32 chan_freq, + struct survey_info *survey); int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, struct cfg80211_csa_settings *params); int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 4320180f8c07..9e666fac8b5f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "core.h" #include "bus.h" @@ -41,11 +42,12 @@ struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid) { struct qtnf_wmac *mac = NULL; - if (unlikely(macid >= QTNF_MAX_MAC)) { + if (macid >= QTNF_MAX_MAC) { pr_err("invalid MAC index %u\n", macid); return NULL; } + macid = array_index_nospec(macid, QTNF_MAX_MAC); mac = bus->mac[macid]; if (unlikely(!mac)) { @@ -497,7 +499,7 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif, dev->tx_queue_len = 100; dev->ethtool_ops = &qtnf_ethtool_ops; - if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) + if (qtnf_hwcap_is_set(&mac->bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) dev->needed_tailroom = sizeof(struct qtnf_frame_meta_info); qdev_vif = netdev_priv(dev); @@ -585,16 +587,6 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) return PTR_ERR(mac); } - ret = qtnf_cmd_get_mac_info(mac); - if (ret) { - pr_err("MAC%u: failed to get info\n", macid); - goto error; - } - - /* Use MAC address of the first active radio as a unique device ID */ - if (is_zero_ether_addr(mac->bus->hw_id)) - ether_addr_copy(mac->bus->hw_id, mac->macaddr); - vif = qtnf_mac_get_base_vif(mac); if (!vif) { pr_err("MAC%u: primary VIF is not ready\n", macid); @@ -609,12 +601,16 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) goto error; } - ret = qtnf_cmd_send_get_phy_params(mac); + ret = qtnf_cmd_get_mac_info(mac); if (ret) { - pr_err("MAC%u: failed to get PHY settings\n", macid); + pr_err("MAC%u: failed to get MAC info\n", macid); goto error_del_vif; } + /* Use MAC address of the first active radio as a unique device ID */ + if (is_zero_ether_addr(mac->bus->hw_id)) + ether_addr_copy(mac->bus->hw_id, mac->macaddr); + ret = qtnf_mac_init_bands(mac); if (ret) { pr_err("MAC%u: failed to init bands\n", macid); @@ -639,7 +635,7 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) goto error_del_vif; } - if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) { + if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) { ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); if (ret) goto error; @@ -705,7 +701,8 @@ static int qtnf_core_netdevice_event(struct notifier_block *nb, info->linking ? "add" : "del"); if (IS_ENABLED(CONFIG_NET_SWITCHDEV) && - (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE)) { + qtnf_hwcap_is_set(&bus->hw_info, + QLINK_HW_CAPAB_HW_BRIDGE)) { if (info->linking) br_domain = brdev->ifindex; else @@ -756,6 +753,15 @@ int qtnf_core_attach(struct qtnf_bus *bus) goto error; } + if (QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver) != + QLINK_PROTO_VER_MAJOR) { + pr_err("qlink driver vs FW version mismatch: %u vs %u\n", + QLINK_PROTO_VER_MAJOR, + QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver)); + ret = -EPROTONOSUPPORT; + goto error; + } + bus->fw_state = QTNF_FW_STATE_ACTIVE; ret = qtnf_cmd_get_hw_info(bus); if (ret) { @@ -763,14 +769,7 @@ int qtnf_core_attach(struct qtnf_bus *bus) goto error; } - if (bus->hw_info.ql_proto_ver != QLINK_PROTO_VER) { - pr_err("qlink version mismatch %u != %u\n", - QLINK_PROTO_VER, bus->hw_info.ql_proto_ver); - ret = -EPROTONOSUPPORT; - goto error; - } - - if ((bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) && + if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE) && bus->bus_ops->data_tx_use_meta_set) bus->bus_ops->data_tx_use_meta_set(bus, true); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index d715e1cd0006..b993f9ca14c5 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -23,6 +23,7 @@ #include "qlink.h" #include "trans.h" +#include "qlink_util.h" #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ @@ -83,7 +84,8 @@ struct qtnf_mac_info { u8 sretry_limit; u8 coverage_class; u8 radar_detect_widths; - u32 max_acl_mac_addrs; + u8 max_scan_ssids; + u16 max_acl_mac_addrs; struct ieee80211_ht_cap ht_cap_mod_mask; struct ieee80211_vht_cap vht_cap_mod_mask; struct ieee80211_iface_combination *if_comb; @@ -94,15 +96,6 @@ struct qtnf_mac_info { struct wiphy_wowlan_support *wowlan; }; -struct qtnf_chan_stats { - u32 chan_num; - u32 cca_tx; - u32 cca_rx; - u32 cca_busy; - u32 cca_try; - s8 chan_noise; -}; - struct qtnf_wmac { u8 macid; u8 wiphy_registered; @@ -117,16 +110,15 @@ struct qtnf_wmac { }; struct qtnf_hw_info { - u16 ql_proto_ver; + u32 ql_proto_ver; u8 num_mac; u8 mac_bitmap; u32 fw_ver; - u32 hw_capab; u8 total_tx_chain; u8 total_rx_chain; char fw_version[ETHTOOL_FWVERS_LEN]; u32 hw_version; - u8 max_scan_ssids; + u8 hw_capab[QLINK_HW_CAPAB_NUM / BITS_PER_BYTE + 1]; }; struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac); @@ -140,7 +132,6 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv, const char *name, unsigned char name_assign_type); void qtnf_main_work_queue(struct work_struct *work); int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed); -int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac); struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid); struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb); @@ -160,4 +151,11 @@ static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev) return *((void **)netdev_priv(dev)); } +static inline bool qtnf_hwcap_is_set(const struct qtnf_hw_info *info, + unsigned int bit) +{ + return qtnf_utils_is_bit_set(info->hw_capab, bit, + sizeof(info->hw_capab)); +} + #endif /* _QTN_FMAC_CORE_H_ */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 51af93bdf06e..7e408b5c5549 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "cfg80211.h" #include "core.h" @@ -25,7 +26,6 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, size_t payload_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; int ret = 0; @@ -58,23 +58,17 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, sinfo->generation = vif->generation; payload_len = len - sizeof(*sta_assoc); - tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies; - while (payload_len >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, sta_assoc->ies, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (tlv_full_len > payload_len) { - ret = -EINVAL; - goto out; - } if (tlv_type == QTN_TLV_ID_IE_SET) { const struct qlink_tlv_ie_set *ie_set; unsigned int ie_len; - if (payload_len < sizeof(*ie_set)) { + if (tlv_value_len < + (sizeof(*ie_set) - sizeof(ie_set->hdr))) { ret = -EINVAL; goto out; } @@ -88,12 +82,10 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, sinfo->assoc_req_ies_len = ie_len; } } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) { + if (!qlink_tlv_parsing_ok(tlv, sta_assoc->ies, payload_len)) { + pr_err("Malformed TLV buffer\n"); ret = -EINVAL; goto out; } @@ -153,7 +145,6 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, size_t payload_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; const u8 *rsp_ies = NULL; size_t rsp_ies_len = 0; @@ -235,24 +226,17 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, } payload_len = len - sizeof(*join_info); - tlv = (struct qlink_tlv_hdr *)join_info->ies; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { + qlink_for_each_tlv(tlv, join_info->ies, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (payload_len < tlv_full_len) { - pr_warn("invalid %u TLV\n", tlv_type); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto done; - } if (tlv_type == QTN_TLV_ID_IE_SET) { const struct qlink_tlv_ie_set *ie_set; unsigned int ie_len; - if (payload_len < sizeof(*ie_set)) { + if (tlv_value_len < + (sizeof(*ie_set) - sizeof(ie_set->hdr))) { pr_warn("invalid IE_SET TLV\n"); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; @@ -275,15 +259,10 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, break; } } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) - pr_warn("VIF%u.%u: unexpected remaining payload: %zu\n", - vif->mac->macid, vif->vifid, payload_len); - + if (!qlink_tlv_parsing_ok(tlv, join_info->ies, payload_len)) + pr_warn("Malformed TLV buffer\n"); done: cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, rsp_ies, rsp_ies_len, status, GFP_KERNEL); @@ -368,7 +347,6 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, size_t payload_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; const u8 *ies = NULL; size_t ies_len = 0; @@ -387,21 +365,17 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, } payload_len = len - sizeof(*sr); - tlv = (struct qlink_tlv_hdr *)sr->payload; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { + qlink_for_each_tlv(tlv, sr->payload, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (tlv_full_len > payload_len) - return -EINVAL; if (tlv_type == QTN_TLV_ID_IE_SET) { const struct qlink_tlv_ie_set *ie_set; unsigned int ie_len; - if (payload_len < sizeof(*ie_set)) + if (tlv_value_len < + (sizeof(*ie_set) - sizeof(ie_set->hdr))) return -EINVAL; ie_set = (const struct qlink_tlv_ie_set *)tlv; @@ -424,12 +398,9 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, ies_len = ie_len; } } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) + if (!qlink_tlv_parsing_ok(tlv, sr->payload, payload_len)) return -EINVAL; bss = cfg80211_inform_bss(wiphy, channel, frame_type, @@ -662,18 +633,20 @@ static int qtnf_event_parse(struct qtnf_wmac *mac, int ret = -1; u16 event_id; u16 event_len; + u8 vifid; event = (const struct qlink_event *)event_skb->data; event_id = le16_to_cpu(event->event_id); event_len = le16_to_cpu(event->mhdr.len); - if (likely(event->vifid < QTNF_MAX_INTF)) { - vif = &mac->iflist[event->vifid]; - } else { + if (event->vifid >= QTNF_MAX_INTF) { pr_err("invalid vif(%u)\n", event->vifid); return -EINVAL; } + vifid = array_index_nospec(event->vifid, QTNF_MAX_INTF); + vif = &mac->iflist[vifid]; + switch (event_id) { case QLINK_EVENT_STA_ASSOCIATED: ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event, diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c index 8e0d8018208a..dbb241106d8a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c @@ -593,7 +593,7 @@ static int qtnf_pcie_skb_send(struct qtnf_bus *bus, struct sk_buff *skb) priv->tx_bd_w_index = i; tx_done: - if (ret && skb) { + if (ret) { pr_err_ratelimited("drop skb\n"); if (skb->dev) skb->dev->stats.tx_dropped++; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index b2edb03819d1..7ee1070f985f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -6,7 +6,20 @@ #include -#define QLINK_PROTO_VER 16 +#define QLINK_PROTO_VER_MAJOR_M 0xFFFF +#define QLINK_PROTO_VER_MAJOR_S 16 +#define QLINK_PROTO_VER_MINOR_M 0xFFFF +#define QLINK_VER_MINOR(_ver) ((_ver) & QLINK_PROTO_VER_MINOR_M) +#define QLINK_VER_MAJOR(_ver) \ + (((_ver) >> QLINK_PROTO_VER_MAJOR_S) & QLINK_PROTO_VER_MAJOR_M) +#define QLINK_VER(_maj, _min) (((_maj) << QLINK_PROTO_VER_MAJOR_S) | (_min)) + +#define QLINK_PROTO_VER_MAJOR 18 +#define QLINK_PROTO_VER_MINOR 0 +#define QLINK_PROTO_VER \ + QLINK_VER(QLINK_PROTO_VER_MAJOR, QLINK_PROTO_VER_MINOR) + +#define QLINK_ALIGN 4 #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -62,15 +75,24 @@ struct qlink_msg_header { * @QLINK_HW_CAPAB_HW_BRIDGE: device has hardware switch capabilities. */ enum qlink_hw_capab { - QLINK_HW_CAPAB_REG_UPDATE = BIT(0), - QLINK_HW_CAPAB_STA_INACT_TIMEOUT = BIT(1), - QLINK_HW_CAPAB_DFS_OFFLOAD = BIT(2), - QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3), - QLINK_HW_CAPAB_PWR_MGMT = BIT(4), - QLINK_HW_CAPAB_OBSS_SCAN = BIT(5), - QLINK_HW_CAPAB_SCAN_DWELL = BIT(6), - QLINK_HW_CAPAB_SAE = BIT(8), - QLINK_HW_CAPAB_HW_BRIDGE = BIT(9), + QLINK_HW_CAPAB_REG_UPDATE = 0, + QLINK_HW_CAPAB_STA_INACT_TIMEOUT, + QLINK_HW_CAPAB_DFS_OFFLOAD, + QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR, + QLINK_HW_CAPAB_PWR_MGMT, + QLINK_HW_CAPAB_OBSS_SCAN, + QLINK_HW_CAPAB_SCAN_DWELL, + QLINK_HW_CAPAB_SAE, + QLINK_HW_CAPAB_HW_BRIDGE, + QLINK_HW_CAPAB_NUM +}; + +/** + * enum qlink_driver_capab - host driver capabilities. + * + */ +enum qlink_driver_capab { + QLINK_DRV_CAPAB_NUM = 0 }; enum qlink_iface_type { @@ -164,7 +186,7 @@ struct qlink_chandef { __le16 center_freq1; __le16 center_freq2; u8 width; - u8 rsvd; + u8 rsvd[3]; } __packed; #define QLINK_MAX_NR_CIPHER_SUITES 5 @@ -269,7 +291,6 @@ enum qlink_cmd_type { QLINK_CMD_REGISTER_MGMT = 0x0003, QLINK_CMD_SEND_FRAME = 0x0004, QLINK_CMD_MGMT_SET_APPIE = 0x0005, - QLINK_CMD_PHY_PARAMS_GET = 0x0011, QLINK_CMD_PHY_PARAMS_SET = 0x0012, QLINK_CMD_GET_HW_INFO = 0x0013, QLINK_CMD_MAC_INFO = 0x0014, @@ -321,9 +342,26 @@ struct qlink_cmd { struct qlink_msg_header mhdr; __le16 cmd_id; __le16 seq_num; - u8 rsvd[2]; u8 macid; u8 vifid; + u8 rsvd[2]; +} __packed; + +/** + * struct qlink_cmd_init_fw - data for QLINK_CMD_FW_INIT + * + * Initialize firmware based on specified host configuration. This is the first + * command sent to wifi card and it's fixed part should never be changed, any + * additions must be done by appending TLVs. + * If wifi card can not operate with a specified parameters it will return + * error. + * + * @qlink_proto_ver: QLINK protocol version used by host driver. + */ +struct qlink_cmd_init_fw { + struct qlink_cmd chdr; + __le32 qlink_proto_ver; + u8 var_info[0]; } __packed; /** @@ -368,6 +406,7 @@ struct qlink_cmd_mgmt_frame_register { struct qlink_cmd chdr; __le16 frame_type; u8 do_register; + u8 rsvd[1]; } __packed; /** @@ -405,6 +444,7 @@ struct qlink_cmd_frame_tx { struct qlink_cmd_get_sta_info { struct qlink_cmd chdr; u8 sta_addr[ETH_ALEN]; + u8 rsvd[2]; } __packed; /** @@ -424,6 +464,7 @@ struct qlink_cmd_add_key { u8 addr[ETH_ALEN]; __le32 cipher; __le16 vlanid; + u8 rsvd[2]; u8 key_data[0]; } __packed; @@ -453,6 +494,7 @@ struct qlink_cmd_set_def_key { u8 key_index; u8 unicast; u8 multicast; + u8 rsvd[1]; } __packed; /** @@ -463,6 +505,7 @@ struct qlink_cmd_set_def_key { struct qlink_cmd_set_def_mgmt_key { struct qlink_cmd chdr; u8 key_index; + u8 rsvd[3]; } __packed; /** @@ -479,6 +522,7 @@ struct qlink_cmd_change_sta { __le16 if_type; __le16 vlanid; u8 sta_addr[ETH_ALEN]; + u8 rsvd[2]; } __packed; /** @@ -489,8 +533,9 @@ struct qlink_cmd_change_sta { struct qlink_cmd_del_sta { struct qlink_cmd chdr; __le16 reason_code; - u8 subtype; u8 sta_addr[ETH_ALEN]; + u8 subtype; + u8 rsvd[3]; } __packed; enum qlink_sta_connect_flags { @@ -557,6 +602,7 @@ struct qlink_cmd_external_auth { struct qlink_cmd_disconnect { struct qlink_cmd chdr; __le16 reason; + u8 rsvd[2]; } __packed; /** @@ -568,6 +614,7 @@ struct qlink_cmd_disconnect { struct qlink_cmd_updown { struct qlink_cmd chdr; u8 if_up; + u8 rsvd[3]; } __packed; /** @@ -591,16 +638,17 @@ enum qlink_band { struct qlink_cmd_band_info_get { struct qlink_cmd chdr; u8 band; + u8 rsvd[3]; } __packed; /** * struct qlink_cmd_get_chan_stats - data for QLINK_CMD_CHAN_STATS command * - * @channel: channel number according to 802.11 17.3.8.3.2 and Annex J + * @channel_freq: channel center frequency */ struct qlink_cmd_get_chan_stats { struct qlink_cmd chdr; - __le16 channel; + __le32 channel_freq; } __packed; /** @@ -652,20 +700,34 @@ struct qlink_cmd_reg_notify { u8 info[0]; } __packed; +/** + * enum qlink_chan_sw_flags - channel switch control flags + * + * @QLINK_CHAN_SW_RADAR_REQUIRED: whether radar detection is required on a new + * channel. + * @QLINK_CHAN_SW_BLOCK_TX: whether transmissions should be blocked while + * changing a channel. + */ +enum qlink_chan_sw_flags { + QLINK_CHAN_SW_RADAR_REQUIRED = BIT(0), + QLINK_CHAN_SW_BLOCK_TX = BIT(1), +}; + /** * struct qlink_cmd_chan_switch - data for QLINK_CMD_CHAN_SWITCH command * - * @channel: channel number according to 802.11 17.3.8.3.2 and Annex J - * @radar_required: whether radar detection is required on the new channel - * @block_tx: whether transmissions should be blocked while changing + * @channel: channel to switch to. + * @flags: flags to control channel switch, bitmap of &enum qlink_chan_sw_flags. * @beacon_count: number of beacons until switch */ struct qlink_cmd_chan_switch { struct qlink_cmd chdr; - __le16 channel; - u8 radar_required; - u8 block_tx; + struct qlink_chandef channel; + __le64 flags; + __le32 n_counter_offsets_beacon; + __le32 n_counter_offsets_presp; u8 beacon_count; + u8 rsvd[3]; } __packed; /** @@ -769,6 +831,7 @@ struct qlink_cmd_pm_set { struct qlink_cmd chdr; __le32 pm_standby_timer; u8 pm_mode; + u8 rsvd[3]; } __packed; /** @@ -857,6 +920,46 @@ struct qlink_cmd_ndev_changeupper { u8 rsvd[1]; } __packed; +/** + * enum qlink_scan_flags - scan request control flags + * + * Scan flags are used to control QLINK_CMD_SCAN behavior. + * + * @QLINK_SCAN_FLAG_FLUSH: flush cache before scanning. + */ +enum qlink_scan_flags { + QLINK_SCAN_FLAG_FLUSH = BIT(0), + QLINK_SCAN_FLAG_DURATION_MANDATORY = BIT(1), +}; + +/** + * struct qlink_cmd_scan - data for QLINK_CMD_SCAN command + * + * @flags: scan flags, a bitmap of &enum qlink_scan_flags. + * @n_ssids: number of WLAN_EID_SSID TLVs expected in variable portion of the + * command. + * @n_channels: number of QTN_TLV_ID_CHANNEL TLVs expected in variable payload. + * @active_dwell: time spent on a single channel for an active scan. + * @passive_dwell: time spent on a single channel for a passive scan. + * @sample_duration: total duration of sampling a single channel during a scan + * including off-channel dwell time and operating channel time. + * @bssid: specific BSSID to scan for or a broadcast BSSID. + * @scan_width: channel width to use, one of &enum qlink_channel_width. + */ +struct qlink_cmd_scan { + struct qlink_cmd chdr; + __le64 flags; + __le16 n_ssids; + __le16 n_channels; + __le16 active_dwell; + __le16 passive_dwell; + __le16 sample_duration; + u8 bssid[ETH_ALEN]; + u8 scan_width; + u8 rsvd[3]; + u8 var_info[0]; +} __packed; + /* QLINK Command Responses messages related definitions */ @@ -895,6 +998,16 @@ struct qlink_resp { u8 vifid; } __packed; +/** + * struct qlink_resp_init_fw - response for QLINK_CMD_FW_INIT + * + * @qlink_proto_ver: QLINK protocol version used by wifi card firmware. + */ +struct qlink_resp_init_fw { + struct qlink_resp rhdr; + __le32 qlink_proto_ver; +} __packed; + /** * enum qlink_dfs_regions - regulatory DFS regions * @@ -919,6 +1032,7 @@ enum qlink_dfs_regions { * @num_rx_chain: Number of receive chains used by WMAC. * @vht_cap_mod_mask: mask specifying which VHT capabilities can be altered. * @ht_cap_mod_mask: mask specifying which HT capabilities can be altered. + * @max_scan_ssids: maximum number of SSIDs the device can scan for in any scan. * @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band. * @max_ap_assoc_sta: Maximum number of associations supported by WMAC. * @radar_detect_widths: bitmask of channels BW for which WMAC can detect radar. @@ -935,14 +1049,48 @@ struct qlink_resp_get_mac_info { u8 num_rx_chain; struct ieee80211_vht_cap vht_cap_mod_mask; struct ieee80211_ht_cap ht_cap_mod_mask; + __le16 max_ap_assoc_sta; + __le32 hw_version; + __le32 probe_resp_offload; + __le32 bss_select_support; + __le16 n_addresses; __le16 radar_detect_widths; - __le32 max_acl_mac_addrs; + __le16 max_remain_on_channel_duration; + __le16 max_acl_mac_addrs; + + __le32 frag_threshold; + __le32 rts_threshold; + u8 retry_short; + u8 retry_long; + u8 coverage_class; + + u8 max_scan_ssids; + u8 max_sched_scan_reqs; + u8 max_sched_scan_ssids; + u8 max_match_sets; + u8 max_adj_channel_rssi_comp; + + __le16 max_scan_ie_len; + __le16 max_sched_scan_ie_len; + __le32 max_sched_scan_plans; + __le32 max_sched_scan_plan_interval; + __le32 max_sched_scan_plan_iterations; + + u8 n_cipher_suites; + u8 n_akm_suites; + u8 max_num_pmkids; + u8 num_iftype_ext_capab; + u8 extended_capabilities_len; + u8 max_data_retry_count; + u8 n_iface_combinations; + u8 max_num_csa_counters; + u8 bands_cap; u8 alpha2[2]; u8 n_reg_rules; u8 dfs_region; - u8 rsvd[1]; + u8 rsvd[3]; u8 var_info[0]; } __packed; @@ -952,8 +1100,6 @@ struct qlink_resp_get_mac_info { * Description of wireless hardware capabilities and features. * * @fw_ver: wireless hardware firmware version. - * @hw_capab: Bitmap of capabilities supported by firmware. - * @ql_proto_ver: Version of QLINK protocol used by firmware. * @num_mac: Number of separate physical radio devices provided by hardware. * @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware. * @total_tx_chains: total number of transmit chains used by device. @@ -963,11 +1109,9 @@ struct qlink_resp_get_mac_info { struct qlink_resp_get_hw_info { struct qlink_resp rhdr; __le32 fw_ver; - __le32 hw_capab; __le32 bld_tmstamp; __le32 plat_id; __le32 hw_ver; - __le16 ql_proto_ver; u8 num_mac; u8 mac_bitmap; u8 total_tx_chain; @@ -1001,8 +1145,6 @@ enum qlink_sta_info_rate_flags { * * Response data containing statistics for specified STA. * - * @filled: a bitmask of &enum qlink_sta_info, specifies which info in response - * is valid. * @sta_addr: MAC address of STA the response carries statistic for. * @info: variable statistics for specified STA. */ @@ -1030,23 +1172,15 @@ struct qlink_resp_band_info_get { u8 info[0]; } __packed; -/** - * struct qlink_resp_phy_params - response for QLINK_CMD_PHY_PARAMS_GET command - * - * @info: variable-length array of PHY params. - */ -struct qlink_resp_phy_params { - struct qlink_resp rhdr; - u8 info[0]; -} __packed; - /** * struct qlink_resp_get_chan_stats - response for QLINK_CMD_CHAN_STATS cmd * + * @chan_freq: center frequency for a channel the report is sent for. * @info: variable-length channel info. */ struct qlink_resp_get_chan_stats { - struct qlink_cmd rhdr; + struct qlink_resp rhdr; + __le32 chan_freq; u8 info[0]; } __packed; @@ -1158,6 +1292,7 @@ struct qlink_event_bss_join { struct qlink_event_bss_leave { struct qlink_event ehdr; __le16 reason; + u8 rsvd[2]; } __packed; /** @@ -1274,10 +1409,10 @@ struct qlink_event_radar { */ struct qlink_event_external_auth { struct qlink_event ehdr; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - u8 bssid[ETH_ALEN]; __le32 akm_suite; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 bssid[ETH_ALEN]; + u8 ssid_len; u8 action; } __packed; @@ -1301,20 +1436,17 @@ struct qlink_event_mic_failure { /** * enum qlink_tlv_id - list of TLVs that Qlink messages can carry * - * @QTN_TLV_ID_STA_STATS_MAP: a bitmap of &enum qlink_sta_info, used to - * indicate which statistic carried in QTN_TLV_ID_STA_STATS is valid. + * @QTN_TLV_ID_BITMAP: a data representing a bitmap that is used together with + * other TLVs: + * &enum qlink_sta_info used to indicate which statistic carried in + * QTN_TLV_ID_STA_STATS is valid. + * &enum qlink_hw_capab listing wireless card capabilities. + * &enum qlink_driver_capab listing driver/host system capabilities. + * &enum qlink_chan_stat used to indicate which statistic carried in + * QTN_TLV_ID_CHANNEL_STATS is valid. * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by * &struct qlink_sta_stats. Valid values are marked as such in a bitmap - * carried by QTN_TLV_ID_STA_STATS_MAP. - * @QTN_TLV_ID_MAX_SCAN_SSIDS: maximum number of SSIDs the device can scan - * for in any given scan. - * @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active - * scan. - * @QTN_TLV_ID_SCAN_DWELL_PASSIVE: time spent on a single channel for a passive - * scan. - * @QTN_TLV_ID_SCAN_SAMPLE_DURATION: total duration of sampling a single channel - * during a scan including off-channel dwell time and operating channel - * time. + * carried by QTN_TLV_ID_BITMAP. * @QTN_TLV_ID_IFTYPE_DATA: supported band data. */ enum qlink_tlv_id { @@ -1325,11 +1457,10 @@ enum qlink_tlv_id { QTN_TLV_ID_REG_RULE = 0x0207, QTN_TLV_ID_CHANNEL = 0x020F, QTN_TLV_ID_CHANDEF = 0x0210, - QTN_TLV_ID_STA_STATS_MAP = 0x0211, + QTN_TLV_ID_BITMAP = 0x0211, QTN_TLV_ID_STA_STATS = 0x0212, QTN_TLV_ID_COVERAGE_CLASS = 0x0213, QTN_TLV_ID_IFACE_LIMIT = 0x0214, - QTN_TLV_ID_NUM_IFACE_COMB = 0x0215, QTN_TLV_ID_CHANNEL_STATS = 0x0216, QTN_TLV_ID_KEY = 0x0302, QTN_TLV_ID_SEQ = 0x0303, @@ -1344,13 +1475,8 @@ enum qlink_tlv_id { QTN_TLV_ID_CALIBRATION_VER = 0x0406, QTN_TLV_ID_UBOOT_VER = 0x0407, QTN_TLV_ID_RANDOM_MAC_ADDR = 0x0408, - QTN_TLV_ID_MAX_SCAN_SSIDS = 0x0409, QTN_TLV_ID_WOWLAN_CAPAB = 0x0410, QTN_TLV_ID_WOWLAN_PATTERN = 0x0411, - QTN_TLV_ID_SCAN_FLUSH = 0x0412, - QTN_TLV_ID_SCAN_DWELL_ACTIVE = 0x0413, - QTN_TLV_ID_SCAN_DWELL_PASSIVE = 0x0416, - QTN_TLV_ID_SCAN_SAMPLE_DURATION = 0x0417, QTN_TLV_ID_IFTYPE_DATA = 0x0418, }; @@ -1360,10 +1486,6 @@ struct qlink_tlv_hdr { u8 val[0]; } __packed; -struct qlink_iface_comb_num { - __le32 iface_comb_num; -} __packed; - struct qlink_iface_limit { __le16 max_num; __le16 type; @@ -1378,21 +1500,6 @@ struct qlink_iface_limit_record { #define QLINK_RSSI_OFFSET 120 -struct qlink_tlv_frag_rts_thr { - struct qlink_tlv_hdr hdr; - __le32 thr; -} __packed; - -struct qlink_tlv_rlimit { - struct qlink_tlv_hdr hdr; - u8 rlimit; -} __packed; - -struct qlink_tlv_cclass { - struct qlink_tlv_hdr hdr; - u8 cclass; -} __packed; - /** * enum qlink_reg_rule_flags - regulatory rule flags * @@ -1510,6 +1617,7 @@ struct qlink_tlv_ie_set { struct qlink_tlv_hdr hdr; u8 type; u8 flags; + u8 rsvd[2]; u8 ie_data[0]; } __packed; @@ -1522,6 +1630,7 @@ struct qlink_tlv_ie_set { struct qlink_tlv_ext_ie { struct qlink_tlv_hdr hdr; u8 eid_ext; + u8 rsvd[3]; u8 ie_data[0]; } __packed; @@ -1546,13 +1655,57 @@ struct qlink_tlv_iftype_data { struct qlink_sband_iftype_data iftype_data[0]; } __packed; +/** + * enum qlink_chan_stat - channel statistics bitmap + * + * Used to indicate which statistics values in &struct qlink_chan_stats + * are valid. Individual values are used to fill a bitmap carried in a + * payload of QTN_TLV_ID_BITMAP. + * + * @QLINK_CHAN_STAT_TIME_ON: time_on value is valid. + * @QLINK_CHAN_STAT_TIME_TX: time_tx value is valid. + * @QLINK_CHAN_STAT_TIME_RX: time_rx value is valid. + * @QLINK_CHAN_STAT_CCA_BUSY: cca_busy value is valid. + * @QLINK_CHAN_STAT_CCA_BUSY_EXT: cca_busy_ext value is valid. + * @QLINK_CHAN_STAT_TIME_SCAN: time_scan value is valid. + * @QLINK_CHAN_STAT_CHAN_NOISE: chan_noise value is valid. + */ +enum qlink_chan_stat { + QLINK_CHAN_STAT_TIME_ON, + QLINK_CHAN_STAT_TIME_TX, + QLINK_CHAN_STAT_TIME_RX, + QLINK_CHAN_STAT_CCA_BUSY, + QLINK_CHAN_STAT_CCA_BUSY_EXT, + QLINK_CHAN_STAT_TIME_SCAN, + QLINK_CHAN_STAT_CHAN_NOISE, + QLINK_CHAN_STAT_NUM, +}; + +/** + * struct qlink_chan_stats - data for QTN_TLV_ID_CHANNEL_STATS + * + * Carries a per-channel statistics. Not all fields may be filled with + * valid values. Valid fields should be indicated as such using a bitmap of + * &enum qlink_chan_stat. Bitmap is carried separately in a payload of + * QTN_TLV_ID_BITMAP. + * + * @time_on: amount of time radio operated on that channel. + * @time_tx: amount of time radio spent transmitting on the channel. + * @time_rx: amount of time radio spent receiving on the channel. + * @cca_busy: amount of time the the primary channel was busy. + * @cca_busy_ext: amount of time the the secondary channel was busy. + * @time_scan: amount of radio spent scanning on the channel. + * @chan_noise: channel noise. + */ struct qlink_chan_stats { - __le32 chan_num; - __le32 cca_tx; - __le32 cca_rx; - __le32 cca_busy; - __le32 cca_try; + __le64 time_on; + __le64 time_tx; + __le64 time_rx; + __le64 cca_busy; + __le64 cca_busy_ext; + __le64 time_scan; s8 chan_noise; + u8 rsvd[3]; } __packed; /** @@ -1560,7 +1713,7 @@ struct qlink_chan_stats { * * Used to indicate which statistics values in &struct qlink_sta_stats * are valid. Individual values are used to fill a bitmap carried in a - * payload of QTN_TLV_ID_STA_STATS_MAP. + * payload of QTN_TLV_ID_BITMAP. * * @QLINK_STA_INFO_CONNECTED_TIME: connected_time value is valid. * @QLINK_STA_INFO_INACTIVE_TIME: inactive_time value is valid. @@ -1624,7 +1777,7 @@ struct qlink_sta_info_rate { * Carries statistics of a STA. Not all fields may be filled with * valid values. Valid fields should be indicated as such using a bitmap of * &enum qlink_sta_info. Bitmap is carried separately in a payload of - * QTN_TLV_ID_STA_STATS_MAP. + * QTN_TLV_ID_BITMAP. */ struct qlink_sta_stats { __le64 rx_bytes; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index f873beed2ae7..230a10a41c7a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -20,42 +20,14 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb, u16 tlv_id, const u8 arr[], size_t arr_len) { - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + arr_len); + struct qlink_tlv_hdr *hdr; + hdr = skb_put(skb, sizeof(*hdr) + round_up(arr_len, QLINK_ALIGN)); hdr->type = cpu_to_le16(tlv_id); hdr->len = cpu_to_le16(arr_len); memcpy(hdr->val, arr, arr_len); } -static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id) -{ - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr)); - - hdr->type = cpu_to_le16(tlv_id); - hdr->len = cpu_to_le16(0); -} - -static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id, - u8 value) -{ - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value)); - - hdr->type = cpu_to_le16(tlv_id); - hdr->len = cpu_to_le16(sizeof(value)); - *hdr->val = value; -} - -static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb, - u16 tlv_id, u16 value) -{ - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value)); - __le16 tmp = cpu_to_le16(value); - - hdr->type = cpu_to_le16(tlv_id); - hdr->len = cpu_to_le16(sizeof(value)); - memcpy(hdr->val, &tmp, sizeof(tmp)); -} - static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb, u16 tlv_id, u32 value) { @@ -85,4 +57,17 @@ u32 qlink_utils_chflags_cfg2q(u32 cfgflags); void qlink_utils_regrule_q2nl(struct ieee80211_reg_rule *rule, const struct qlink_tlv_reg_rule *tlv_rule); +#define qlink_for_each_tlv(_tlv, _start, _datalen) \ + for (_tlv = (const struct qlink_tlv_hdr *)(_start); \ + (const u8 *)(_start) + (_datalen) - (const u8 *)_tlv >= \ + (int)sizeof(*_tlv) && \ + (const u8 *)(_start) + (_datalen) - (const u8 *)_tlv >= \ + (int)sizeof(*_tlv) + le16_to_cpu(_tlv->len); \ + _tlv = (const struct qlink_tlv_hdr *)(_tlv->val + \ + round_up(le16_to_cpu(_tlv->len), QLINK_ALIGN))) + +#define qlink_tlv_parsing_ok(_tlv_last, _start, _datalen) \ + ((const u8 *)(_tlv_last) == \ + (const u8 *)(_start) + round_up(_datalen, QLINK_ALIGN)) + #endif /* _QTN_FMAC_QLINK_UTIL_H_ */ diff --git a/drivers/net/wireless/realtek/rtw88/bf.c b/drivers/net/wireless/realtek/rtw88/bf.c index fda771d23f71..b6d1d71f4d30 100644 --- a/drivers/net/wireless/realtek/rtw88/bf.c +++ b/drivers/net/wireless/realtek/rtw88/bf.c @@ -41,7 +41,6 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta_vht_cap *ic_vht_cap; const u8 *bssid = bss_conf->bssid; u32 sound_dim; - u8 bfee_role = RTW_BFEE_NONE; u8 i; if (!(chip->band & RTW_BAND_5G)) @@ -67,7 +66,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, } ether_addr_copy(bfee->mac_addr, bssid); - bfee_role = RTW_BFEE_MU; + bfee->role = RTW_BFEE_MU; bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); bfee->aid = bss_conf->aid; bfinfo->bfer_mu_cnt++; @@ -85,7 +84,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ether_addr_copy(bfee->mac_addr, bssid); - bfee_role = RTW_BFEE_SU; + bfee->role = RTW_BFEE_SU; bfee->sound_dim = (u8)sound_dim; bfee->g_id = 0; bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); @@ -102,7 +101,6 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, } out_unlock: - bfee->role = bfee_role; rcu_read_unlock(); } diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c index 4dfb2ec395ee..f91dc21a8bf1 100644 --- a/drivers/net/wireless/realtek/rtw88/coex.c +++ b/drivers/net/wireless/realtek/rtw88/coex.c @@ -1904,6 +1904,9 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) lockdep_assert_held(&rtwdev->mutex); + if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) + return; + coex_dm->reason = reason; /* update wifi_link_info_ext variable */ diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 243441453ead..6867bf29d4c8 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -136,6 +136,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) mutex_lock(&rtwdev->mutex); + if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) + goto unlock; + switch (c2h->id) { case C2H_BT_INFO: rtw_coex_bt_info_notify(rtwdev, c2h->payload, len); @@ -153,6 +156,7 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) break; } +unlock: mutex_unlock(&rtwdev->mutex); } @@ -745,7 +749,7 @@ static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw) loc = rtw_get_rsvd_page_probe_req_location(rtwdev, ssid); if (!loc) { rtw_err(rtwdev, "failed to get probe req rsvd loc\n"); - kfree(skb); + kfree_skb(skb); return NULL; } nlo_hdr->location[i] = loc; @@ -819,8 +823,7 @@ static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw) return skb; } -static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw) { struct rtw_dev *rtwdev = hw->priv; struct rtw_chip_info *chip = rtwdev->chip; @@ -876,7 +879,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, skb_new = rtw_lps_pg_dpk_get(hw); break; case RSVD_LPS_PG_INFO: - skb_new = rtw_lps_pg_info_get(hw, vif); + skb_new = rtw_lps_pg_info_get(hw); break; case RSVD_PROBE_REQ: ssid = (struct cfg80211_ssid *)rsvd_pkt->ssid; diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h index 85a81a578fd5..cad56389182c 100644 --- a/drivers/net/wireless/realtek/rtw88/hci.h +++ b/drivers/net/wireless/realtek/rtw88/hci.h @@ -193,6 +193,32 @@ rtw_read32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask) return ret; } +static inline u16 +rtw_read16_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask) +{ + u32 shift = __ffs(mask); + u32 orig; + u32 ret; + + orig = rtw_read16(rtwdev, addr); + ret = (orig & mask) >> shift; + + return ret; +} + +static inline u8 +rtw_read8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask) +{ + u32 shift = __ffs(mask); + u32 orig; + u32 ret; + + orig = rtw_read8(rtwdev, addr); + ret = (orig & mask) >> shift; + + return ret; +} + static inline void rtw_write32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) { diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index cadf0abbe16b..7b245779ff90 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -17,10 +17,10 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, txsc20 = primary_ch_idx; if (bw == RTW_CHANNEL_WIDTH_80) { - if (txsc20 == 1 || txsc20 == 3) - txsc40 = 9; + if (txsc20 == RTW_SC_20_UPPER || txsc20 == RTW_SC_20_UPMOST) + txsc40 = RTW_SC_40_UPPER; else - txsc40 = 10; + txsc40 = RTW_SC_40_LOWER; } rtw_write8(rtwdev, REG_DATA_SC, BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40)); @@ -101,7 +101,7 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) } static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev, - struct rtw_pwr_seq_cmd *cmd) + const struct rtw_pwr_seq_cmd *cmd) { u8 value; u8 flag = 0; @@ -139,9 +139,10 @@ static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev, } static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, - u8 cut_mask, struct rtw_pwr_seq_cmd *cmd) + u8 cut_mask, + const struct rtw_pwr_seq_cmd *cmd) { - struct rtw_pwr_seq_cmd *cur_cmd; + const struct rtw_pwr_seq_cmd *cur_cmd; u32 offset; u8 value; @@ -183,13 +184,13 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, } static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, - struct rtw_pwr_seq_cmd **cmd_seq) + const struct rtw_pwr_seq_cmd **cmd_seq) { u8 cut_mask; u8 intf_mask; u8 cut; u32 idx = 0; - struct rtw_pwr_seq_cmd *cmd; + const struct rtw_pwr_seq_cmd *cmd; int ret; cut = rtwdev->hal.cut_version; @@ -223,7 +224,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) { struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_pwr_seq_cmd **pwr_seq; + const struct rtw_pwr_seq_cmd **pwr_seq; u8 rpwm; bool cur_pwr; @@ -705,7 +706,7 @@ int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) { - struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; + const struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; u32 prio_queues = 0; if (queues & BIT(IEEE80211_AC_VO)) @@ -793,7 +794,7 @@ void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop) static int txdma_queue_mapping(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_rqpn *rqpn = NULL; + const struct rtw_rqpn *rqpn = NULL; u16 txdma_pq_map = 0; switch (rtw_hci_type(rtwdev)) { @@ -882,7 +883,7 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev) { struct rtw_fifo_conf *fifo = &rtwdev->fifo; struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_page_table *pg_tbl = NULL; + const struct rtw_page_table *pg_tbl = NULL; u16 pubq_num; int ret; diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 6fc33e11d08c..b3125e311fa2 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -75,15 +75,12 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) rtw_leave_lps_deep(rtwdev); - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - if (hw->conf.flags & IEEE80211_CONF_IDLE) { - rtw_enter_ips(rtwdev); - } else { - ret = rtw_leave_ips(rtwdev); - if (ret) { - rtw_err(rtwdev, "failed to leave idle state\n"); - goto out; - } + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + !(hw->conf.flags & IEEE80211_CONF_IDLE)) { + ret = rtw_leave_ips(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to leave idle state\n"); + goto out; } } @@ -99,6 +96,10 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) rtw_set_channel(rtwdev); + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + (hw->conf.flags & IEEE80211_CONF_IDLE)) + rtw_enter_ips(rtwdev); + out: mutex_unlock(&rtwdev->mutex); return ret; @@ -514,6 +515,9 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_BIP_CMAC_256: case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: /* suppress error messages */ return -EOPNOTSUPP; default: @@ -592,6 +596,20 @@ static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, return 0; } +static bool rtw_ops_can_aggregate_in_amsdu(struct ieee80211_hw *hw, + struct sk_buff *head, + struct sk_buff *skb) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_hal *hal = &rtwdev->hal; + + /* we don't want to enable TX AMSDU on 2.4G */ + if (hal->current_band_type == RTW_BAND_2G) + return false; + + return true; +} + static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac_addr) @@ -787,6 +805,7 @@ const struct ieee80211_ops rtw_ops = { .sta_remove = rtw_ops_sta_remove, .set_key = rtw_ops_set_key, .ampdu_action = rtw_ops_ampdu_action, + .can_aggregate_in_amsdu = rtw_ops_can_aggregate_in_amsdu, .sw_scan_start = rtw_ops_sw_scan_start, .sw_scan_complete = rtw_ops_sw_scan_complete, .mgd_prepare_tx = rtw_ops_mgd_prepare_tx, diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 2845d2838f7b..2f73820cd9ba 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -317,15 +317,15 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef, case NL80211_CHAN_WIDTH_20_NOHT: case NL80211_CHAN_WIDTH_20: bandwidth = RTW_CHANNEL_WIDTH_20; - primary_chan_idx = 0; + primary_chan_idx = RTW_SC_DONT_CARE; break; case NL80211_CHAN_WIDTH_40: bandwidth = RTW_CHANNEL_WIDTH_40; if (primary_freq > center_freq) { - primary_chan_idx = 1; + primary_chan_idx = RTW_SC_20_UPPER; center_chan -= 2; } else { - primary_chan_idx = 2; + primary_chan_idx = RTW_SC_20_LOWER; center_chan += 2; } break; @@ -333,10 +333,10 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef, bandwidth = RTW_CHANNEL_WIDTH_80; if (primary_freq > center_freq) { if (primary_freq - center_freq == 10) { - primary_chan_idx = 1; + primary_chan_idx = RTW_SC_20_UPPER; center_chan -= 2; } else { - primary_chan_idx = 3; + primary_chan_idx = RTW_SC_20_UPMOST; center_chan -= 6; } /* assign the center channel used @@ -345,10 +345,10 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef, cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan + 4; } else { if (center_freq - primary_freq == 10) { - primary_chan_idx = 2; + primary_chan_idx = RTW_SC_20_LOWER; center_chan += 2; } else { - primary_chan_idx = 4; + primary_chan_idx = RTW_SC_20_LOWEST; center_chan += 6; } /* assign the center channel used @@ -909,11 +909,16 @@ void rtw_core_stop(struct rtw_dev *rtwdev) clear_bit(RTW_FLAG_RUNNING, rtwdev->flags); clear_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags); + mutex_unlock(&rtwdev->mutex); + + cancel_work_sync(&rtwdev->c2h_work); cancel_delayed_work_sync(&rtwdev->watch_dog_work); cancel_delayed_work_sync(&coex->bt_relink_work); cancel_delayed_work_sync(&coex->bt_reenable_work); cancel_delayed_work_sync(&coex->defreeze_work); + mutex_lock(&rtwdev->mutex); + rtw_power_off(rtwdev); } diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index f334d201bfb5..c074cef22120 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -99,6 +99,16 @@ enum rtw_bandwidth { RTW_CHANNEL_WIDTH_10 = 6, }; +enum rtw_sc_offset { + RTW_SC_DONT_CARE = 0, + RTW_SC_20_UPPER = 1, + RTW_SC_20_LOWER = 2, + RTW_SC_20_UPMOST = 3, + RTW_SC_20_LOWEST = 4, + RTW_SC_40_UPPER = 9, + RTW_SC_40_LOWER = 10, +}; + enum rtw_net_type { RTW_NET_NO_LINK = 0, RTW_NET_AD_HOC = 1, @@ -948,10 +958,10 @@ struct rtw_wow_param { }; struct rtw_intf_phy_para_table { - struct rtw_intf_phy_para *usb2_para; - struct rtw_intf_phy_para *usb3_para; - struct rtw_intf_phy_para *gen1_para; - struct rtw_intf_phy_para *gen2_para; + const struct rtw_intf_phy_para *usb2_para; + const struct rtw_intf_phy_para *usb3_para; + const struct rtw_intf_phy_para *gen1_para; + const struct rtw_intf_phy_para *gen2_para; u8 n_usb2_para; u8 n_usb3_para; u8 n_gen1_para; @@ -1048,13 +1058,13 @@ struct rtw_chip_info { /* init values */ u8 sys_func_en; - struct rtw_pwr_seq_cmd **pwr_on_seq; - struct rtw_pwr_seq_cmd **pwr_off_seq; - struct rtw_rqpn *rqpn_table; - struct rtw_page_table *page_table; - struct rtw_intf_phy_para_table *intf_table; + const struct rtw_pwr_seq_cmd **pwr_on_seq; + const struct rtw_pwr_seq_cmd **pwr_off_seq; + const struct rtw_rqpn *rqpn_table; + const struct rtw_page_table *page_table; + const struct rtw_intf_phy_para_table *intf_table; - struct rtw_hw_reg *dig; + const struct rtw_hw_reg *dig; u32 rf_base_addr[2]; u32 rf_sipi_addr[2]; @@ -1500,7 +1510,7 @@ struct rtw_fifo_conf { u16 rsvd_cpu_instr_addr; u16 rsvd_fw_txbuf_addr; u16 rsvd_csibuf_addr; - struct rtw_rqpn *rqpn; + const struct rtw_rqpn *rqpn; }; struct rtw_fw_state { diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 1fbc14c149ec..7c525bb0337d 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1197,11 +1197,18 @@ static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter) static void rtw_pci_link_cfg(struct rtw_dev *rtwdev) { + struct rtw_chip_info *chip = rtwdev->chip; struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; struct pci_dev *pdev = rtwpci->pdev; u16 link_ctrl; int ret; + /* RTL8822CE has enabled REFCLK auto calibration, it does not need + * to add clock delay to cover the REFCLK timing gap. + */ + if (chip->id == RTW_CHIP_TYPE_8822C) + rtw_dbi_write8(rtwdev, RTK_PCIE_CLKDLY_CTRL, 0); + /* Though there is standard PCIE configuration space to set the * link control register, but by Realtek's design, driver should * check if host supports CLKREQ/ASPM to enable the HW module. @@ -1248,7 +1255,7 @@ static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev) static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_intf_phy_para *para; + const struct rtw_intf_phy_para *para; u16 cut; u16 value; u16 offset; diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h index 1580cfc57361..cd4fcd064cdb 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.h +++ b/drivers/net/wireless/realtek/rtw88/pci.h @@ -39,6 +39,7 @@ #define RTK_PCIE_LINK_CFG 0x0719 #define BIT_CLKREQ_SW_EN BIT(4) #define BIT_L1_SW_EN BIT(3) +#define RTK_PCIE_CLKDLY_CTRL 0x0725 #define BIT_PCI_BCNQ_FLAG BIT(4) #define RTK_PCI_TXBD_DESA_BCNQ 0x308 diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index eea9d888fbf1..8793dd22188f 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -749,20 +749,10 @@ bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, direct_addr = base_addr[rf_path] + (addr << 2); mask &= RFREG_MASK; - if (addr == RF_CFGCH) { - rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, DISABLE_PI); - rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, DISABLE_PI); - } - rtw_write32_mask(rtwdev, direct_addr, mask, data); udelay(1); - if (addr == RF_CFGCH) { - rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, ENABLE_PI); - rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, ENABLE_PI); - } - return true; } diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 4bc14b1a6340..96aa332fb28d 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -645,7 +645,7 @@ static void rtw8822b_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x1); break; case RTW_CHANNEL_WIDTH_40: - if (primary_ch_idx == 1) + if (primary_ch_idx == RTW_SC_20_UPPER) rtw_write32_set(rtwdev, REG_RXSB, BIT(4)); else rtw_write32_clr(rtwdev, REG_RXSB, BIT(4)); @@ -1543,7 +1543,7 @@ static void rtw8822b_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif, rtw_warn(rtwdev, "wrong bfee role\n"); } -static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1581,7 +1581,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { {0x0012, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -1714,7 +1714,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { {0x0003, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1787,7 +1787,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { {0x0005, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1905,26 +1905,26 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { trans_carddis_to_cardemu_8822b, trans_cardemu_to_act_8822b, NULL }; -static struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { trans_act_to_cardemu_8822b, trans_cardemu_to_carddis_8822b, NULL }; -static struct rtw_intf_phy_para usb2_param_8822b[] = { +static const struct rtw_intf_phy_para usb2_param_8822b[] = { {0xFFFF, 0x00, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para usb3_param_8822b[] = { +static const struct rtw_intf_phy_para usb3_param_8822b[] = { {0x0001, 0xA841, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_D, @@ -1935,7 +1935,7 @@ static struct rtw_intf_phy_para usb3_param_8822b[] = { RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen1_param_8822b[] = { +static const struct rtw_intf_phy_para pcie_gen1_param_8822b[] = { {0x0001, 0xA841, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_C, @@ -1982,7 +1982,7 @@ static struct rtw_intf_phy_para pcie_gen1_param_8822b[] = { RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen2_param_8822b[] = { +static const struct rtw_intf_phy_para pcie_gen2_param_8822b[] = { {0x0001, 0xA841, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_C, @@ -2029,7 +2029,7 @@ static struct rtw_intf_phy_para pcie_gen2_param_8822b[] = { RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para_table phy_para_table_8822b = { +static const struct rtw_intf_phy_para_table phy_para_table_8822b = { .usb2_para = usb2_param_8822b, .usb3_para = usb3_param_8822b, .gen1_para = pcie_gen1_param_8822b, @@ -2046,12 +2046,12 @@ static const struct rtw_rfe_def rtw8822b_rfe_defs[] = { [5] = RTW_DEF_RFE(8822b, 5, 5), }; -static struct rtw_hw_reg rtw8822b_dig[] = { +static const struct rtw_hw_reg rtw8822b_dig[] = { [0] = { .addr = 0xc50, .mask = 0x7f }, [1] = { .addr = 0xe50, .mask = 0x7f }, }; -static struct rtw_page_table page_table_8822b[] = { +static const struct rtw_page_table page_table_8822b[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, {64, 64, 0, 0, 1}, @@ -2059,7 +2059,7 @@ static struct rtw_page_table page_table_8822b[] = { {64, 64, 64, 64, 1}, }; -static struct rtw_rqpn rqpn_table_8822b[] = { +static const struct rtw_rqpn rqpn_table_8822b[] = { {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 3865097696d4..146f693c7592 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -1289,6 +1289,17 @@ static int rtw8822c_mac_init(struct rtw_dev *rtwdev) return 0; } +static void rtw8822c_rstb_3wire(struct rtw_dev *rtwdev, bool enable) +{ + if (enable) { + rtw_write32_mask(rtwdev, REG_RSTB, BIT_RSTB_3WIRE, 0x1); + rtw_write32_mask(rtwdev, REG_ANAPAR_A, BIT_ANAPAR_UPDATE, 0x1); + rtw_write32_mask(rtwdev, REG_ANAPAR_B, BIT_ANAPAR_UPDATE, 0x1); + } else { + rtw_write32_mask(rtwdev, REG_RSTB, BIT_RSTB_3WIRE, 0x0); + } +} + static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) { #define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8)) @@ -1337,6 +1348,8 @@ static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) break; } + rtw8822c_rstb_3wire(rtwdev, false); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, 0x04, 0x01); rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, 0x1f, 0x12); rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, 0xfffff, rf_rxbb); @@ -1349,6 +1362,8 @@ static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, rf_reg18); rtw_write_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK, rf_reg18); + + rtw8822c_rstb_3wire(rtwdev, true); } static void rtw8822c_toggle_igi(struct rtw_dev *rtwdev) @@ -1482,7 +1497,7 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, break; case RTW_CHANNEL_WIDTH_40: rtw_write32_mask(rtwdev, REG_CCKSB, BIT(4), - (primary_ch_idx == 1 ? 1 : 0)); + (primary_ch_idx == RTW_SC_20_UPPER ? 1 : 0)); rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0x5); rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xc0, 0x0); rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xff00, @@ -3399,7 +3414,7 @@ static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) dm_info->pwr_trk_triggered = false; } -static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -3442,7 +3457,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { {0x0000, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -3544,6 +3559,11 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, + {0x1064, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, {0xFFFF, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -3551,7 +3571,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { {0x0093, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -3614,7 +3634,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { {0x0005, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -3677,47 +3697,47 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { trans_carddis_to_cardemu_8822c, trans_cardemu_to_act_8822c, NULL }; -static struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { trans_act_to_cardemu_8822c, trans_cardemu_to_carddis_8822c, NULL }; -static struct rtw_intf_phy_para usb2_param_8822c[] = { +static const struct rtw_intf_phy_para usb2_param_8822c[] = { {0xFFFF, 0x00, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para usb3_param_8822c[] = { +static const struct rtw_intf_phy_para usb3_param_8822c[] = { {0xFFFF, 0x0000, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen1_param_8822c[] = { +static const struct rtw_intf_phy_para pcie_gen1_param_8822c[] = { {0xFFFF, 0x0000, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen2_param_8822c[] = { +static const struct rtw_intf_phy_para pcie_gen2_param_8822c[] = { {0xFFFF, 0x0000, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para_table phy_para_table_8822c = { +static const struct rtw_intf_phy_para_table phy_para_table_8822c = { .usb2_para = usb2_param_8822c, .usb3_para = usb3_param_8822c, .gen1_para = pcie_gen1_param_8822c, @@ -3734,12 +3754,12 @@ static const struct rtw_rfe_def rtw8822c_rfe_defs[] = { [2] = RTW_DEF_RFE(8822c, 0, 0), }; -static struct rtw_hw_reg rtw8822c_dig[] = { +static const struct rtw_hw_reg rtw8822c_dig[] = { [0] = { .addr = 0x1d70, .mask = 0x7f }, [1] = { .addr = 0x1d70, .mask = 0x7f00 }, }; -static struct rtw_page_table page_table_8822c[] = { +static const struct rtw_page_table page_table_8822c[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, {64, 64, 0, 0, 1}, @@ -3747,7 +3767,7 @@ static struct rtw_page_table page_table_8822c[] = { {64, 64, 64, 64, 1}, }; -static struct rtw_rqpn rqpn_table_8822c[] = { +static const struct rtw_rqpn rqpn_table_8822c[] = { {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h index abd9f300bedd..dfd8662a0c0e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h @@ -190,6 +190,8 @@ const struct rtw_table name ## _tbl = { \ #define BIT_3WIRE_TX_EN BIT(0) #define BIT_3WIRE_RX_EN BIT(1) #define BIT_3WIRE_PI_ON BIT(28) +#define REG_ANAPAR_A 0x1830 +#define BIT_ANAPAR_UPDATE BIT(29) #define REG_RXAGCCTL0 0x18ac #define BITS_RXAGC_CCK GENMASK(15, 12) #define BITS_RXAGC_OFDM GENMASK(8, 4) @@ -223,6 +225,8 @@ const struct rtw_table name ## _tbl = { \ #define BIT_CCK_BLK_EN BIT(1) #define BIT_CCK_OFDM_BLK_EN (BIT(0) | BIT(1)) #define REG_CCAMSK 0x1c80 +#define REG_RSTB 0x1c90 +#define BIT_RSTB_3WIRE BIT(8) #define REG_RX_BREAK 0x1d2c #define BIT_COM_RX_GCK_EN BIT(31) #define REG_RXFNCTL 0x1d30 @@ -243,6 +247,7 @@ const struct rtw_table name ## _tbl = { \ #define REG_OFDM_TXCNT 0x2de0 #define REG_ORITXCODE2 0x4100 #define REG_3WIRE2 0x410c +#define REG_ANAPAR_B 0x4130 #define REG_RXAGCCTL 0x41ac #define REG_DCKB_I_0 0x41bc #define REG_DCKB_I_1 0x41c0 diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 1bebba4e8527..5d6143a55187 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1468,12 +1468,15 @@ static void rsi_shutdown(struct device *dev) struct rsi_91x_sdiodev *sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; struct ieee80211_hw *hw = adapter->hw; - struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n"); - if (rsi_config_wowlan(adapter, wowlan)) - rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); + if (hw) { + struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; + + if (rsi_config_wowlan(adapter, wowlan)) + rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); + } if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 && adapter->priv->bt_adapter) { diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index 94569cd695c8..c9a4e9a43400 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -15,9 +15,7 @@ #include #include #include -#include #include -#include #include #include "wl1251.h" @@ -160,15 +158,6 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) int ret; if (enable) { - /* - * Power is controlled by runtime PM, but we still call board - * callback in case it wants to do any additional setup, - * for example enabling clock buffer for the module. - */ - if (gpio_is_valid(wl->power_gpio)) - gpio_set_value(wl->power_gpio, true); - - ret = pm_runtime_get_sync(&func->dev); if (ret < 0) { pm_runtime_put_sync(&func->dev); @@ -186,9 +175,6 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) ret = pm_runtime_put_sync(&func->dev); if (ret < 0) goto out; - - if (gpio_is_valid(wl->power_gpio)) - gpio_set_value(wl->power_gpio, false); } out: @@ -241,31 +227,17 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl1251_board_data = wl1251_get_platform_data(); if (!IS_ERR(wl1251_board_data)) { - wl->power_gpio = wl1251_board_data->power_gpio; wl->irq = wl1251_board_data->irq; wl->use_eeprom = wl1251_board_data->use_eeprom; } else if (np) { - wl->use_eeprom = of_property_read_bool(np, - "ti,wl1251-has-eeprom"); - wl->power_gpio = of_get_named_gpio(np, "ti,power-gpio", 0); + wl->use_eeprom = of_property_read_bool(np, "ti,wl1251-has-eeprom"); wl->irq = of_irq_get(np, 0); - - if (wl->power_gpio == -EPROBE_DEFER || - wl->irq == -EPROBE_DEFER) { + if (wl->irq == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto disable; } } - if (gpio_is_valid(wl->power_gpio)) { - ret = devm_gpio_request(&func->dev, wl->power_gpio, - "wl1251 power"); - if (ret) { - wl1251_error("Failed to request gpio: %d\n", ret); - goto disable; - } - } - if (wl->irq) { irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);